From 85311ea695b4f1938d1159e5cd7aac50616fb38d Mon Sep 17 00:00:00 2001
From: Dominik Muller <dominik.muller@cern.ch>
Date: Tue, 18 Dec 2018 14:20:43 +0100
Subject: [PATCH 01/90] Converted TrackerHits to multithreading

---
 Sim/GaussTracker/src/TrackerHit.cpp | 122 +---------------------------
 Sim/GaussTracker/src/TrackerHit.h   |  88 +++++++++-----------
 Sim/GaussTracker/src/TrackerHit.icc |  67 +++++++++++++++
 3 files changed, 107 insertions(+), 170 deletions(-)
 create mode 100644 Sim/GaussTracker/src/TrackerHit.icc

diff --git a/Sim/GaussTracker/src/TrackerHit.cpp b/Sim/GaussTracker/src/TrackerHit.cpp
index 63d16d987..2ae236ec6 100755
--- a/Sim/GaussTracker/src/TrackerHit.cpp
+++ b/Sim/GaussTracker/src/TrackerHit.cpp
@@ -3,6 +3,7 @@
 //
 // 16/05/2002 : Witold POKORSKI
 // 25/07/2006 : Gloria CORTI
+// 18/12/2018 : Dominik Muller
 //-----------------------------------------------------------------------------
 
 // Include files 
@@ -15,125 +16,6 @@
 // local
 #include "TrackerHit.h"
 
-G4Allocator<TrackerHit> TrackerHitAllocator;
-
-//=============================================================================
-// Default Constructor
-//=============================================================================
-TrackerHit::TrackerHit() { }
-
-//=============================================================================
-// Destructor
-//=============================================================================
-TrackerHit::~TrackerHit() {}
-
-//=============================================================================
-// Constructor
-//=============================================================================
-TrackerHit::TrackerHit(const TrackerHit &right)
-  : GaussHitBase(right)
-{
-  m_edep = right.m_edep;
-  m_entryPos = right.m_entryPos;
-  m_exitPos = right.m_exitPos;
-  m_timeOfFlight = right.m_timeOfFlight;
-  m_momentum = right.m_momentum;
-}
-
-//=============================================================================
-// new operator (fast G4 allocator)
-//=============================================================================
-void* TrackerHit::operator new(size_t)
-{
-  void *aHit;
-  aHit = (void *) TrackerHitAllocator.MallocSingle();
-  return aHit;
-}
-
-//=============================================================================
-// delete operator (fast G4 allocator)
-//=============================================================================
-void TrackerHit::operator delete(void *aHit)
-{
-  TrackerHitAllocator.FreeSingle((TrackerHit*) aHit);
-}
-
-//=============================================================================
-// assignmnet operator
-//=============================================================================
-const TrackerHit& TrackerHit::operator=(const TrackerHit &right)
-{
-  m_edep = right.m_edep;
-  m_entryPos = right.m_entryPos;
-  m_exitPos = right.m_exitPos;
-  m_timeOfFlight = right.m_timeOfFlight;
-  m_momentum = right.m_momentum;
-  return *this;
-}
-
-//=============================================================================
-// equality operator
-//=============================================================================
-int TrackerHit::operator==(const TrackerHit& /*right*/ ) const
-{
-  return 0;
-}
-
-//=============================================================================
-// Accessors for energy deposition
-//=============================================================================
-void TrackerHit::SetEdep(G4double de) { 
-  m_edep = de; 
-}
-
-G4double TrackerHit::GetEdep() { 
-  return m_edep; 
-}
-
-//=============================================================================
-// Accessors for entry point
-//=============================================================================
-void TrackerHit::SetEntryPos(G4ThreeVector xyz) { 
-  m_entryPos = xyz; 
-}
-
-G4ThreeVector TrackerHit::GetEntryPos() {
-  return m_entryPos; 
-}
-
-//=============================================================================
-// Accessors for exit point
-//=============================================================================
-void TrackerHit::SetExitPos(G4ThreeVector xyz) { 
-  m_exitPos = xyz; 
-}
-
-G4ThreeVector TrackerHit::GetExitPos() { 
-  return m_exitPos; 
-}
-
-//=============================================================================
-// Accessors for time of flight at entry point
-//=============================================================================
-void TrackerHit::SetTimeOfFlight(G4double tof) { 
-  m_timeOfFlight = tof; 
-}
-
-G4double TrackerHit::GetTimeOfFlight() { 
-  return m_timeOfFlight;
-}
-
-//=============================================================================
-// Accessors for momentum at entry point
-//=============================================================================
-void TrackerHit::SetMomentum(G4ThreeVector p) {
-  m_momentum = p; 
-}
- 
-G4ThreeVector TrackerHit::GetMomentum() {
-  return m_momentum; 
-} 
-
 //=============================================================================
 // Draw 
 //=============================================================================
@@ -168,5 +50,3 @@ void TrackerHit::Print() {
             << this->m_momentum.y() << "," << this->m_momentum.z() << ")"
             << std::endl;
 }
-
-//=============================================================================
diff --git a/Sim/GaussTracker/src/TrackerHit.h b/Sim/GaussTracker/src/TrackerHit.h
index d20cde6bb..ba4037898 100755
--- a/Sim/GaussTracker/src/TrackerHit.h
+++ b/Sim/GaussTracker/src/TrackerHit.h
@@ -1,85 +1,75 @@
-#ifndef TrackerHit_h
-#define TrackerHit_h 1
+#pragma once
 
 /** @class TrackerHit TrackerHit.h component/TrackerHit.h
  *
  *
  *  @author Witold POKORSKI
  *  @author Gloria CORTI
+ *  @author Dominik MULLER
  *  @date   16/05/2002
- *  @date   26/07/2006 (last modified)
+ *  @date   26/07/2006
+ *  @date   18/12/2018 (last modified)
  */
 
-#include "GaussTools/GaussHitBase.h"
-#include "Geant4/G4THitsCollection.hh"
 #include "Geant4/G4Allocator.hh"
+#include "Geant4/G4THitsCollection.hh"
 #include "Geant4/G4ThreeVector.hh"
+#include "GiGaMTCore/GaussHitBase.h"
 
-class TrackerHit : public GaussHitBase
-{
-public:
+class TrackerHit : public GaussHitBase {
+  public:
+  TrackerHit() = default;
+  virtual ~TrackerHit() = default;
+  TrackerHit(const TrackerHit& right);
+  inline const TrackerHit& operator=(const TrackerHit& right);
+  int operator==(const TrackerHit& ) const {return 0;};
 
-  TrackerHit();
-  virtual ~TrackerHit();
-  TrackerHit(const TrackerHit &right);
-  const TrackerHit& operator=(const TrackerHit &right);
-  int operator==(const TrackerHit &right) const;
-
-  void *operator new(size_t);
-  void operator delete(void *aHit);
+  inline void* operator new(size_t);
+  inline void operator delete(void* aHit);
+  inline static G4Allocator<TrackerHit>* TrackerHitAllocator();
 
   void Draw() override;
   void Print() override;
 
-private:
+  private:
   G4ThreeVector m_entryPos;
   G4ThreeVector m_exitPos;
-  G4double      m_timeOfFlight;
-  G4double      m_edep;
+  G4double m_timeOfFlight;
+  G4double m_edep;
   G4ThreeVector m_momentum;
 
-public:
-
-  void SetEdep(G4double de);
-  G4double GetEdep();
+  public:
+  inline void SetEdep(G4double de);
+  inline G4double GetEdep();
 
-  void SetEntryPos(G4ThreeVector xyz);
-  G4ThreeVector GetEntryPos();
+  inline void SetEntryPos(G4ThreeVector xyz);
+  inline G4ThreeVector GetEntryPos();
 
-  void SetExitPos(G4ThreeVector xyz);
-  G4ThreeVector GetExitPos();
+  inline void SetExitPos(G4ThreeVector xyz);
+  inline G4ThreeVector GetExitPos();
 
-  void SetTimeOfFlight(G4double tof);
-  G4double GetTimeOfFlight();
+  inline void SetTimeOfFlight(G4double tof);
+  inline G4double GetTimeOfFlight();
 
-  void SetMomentum(G4ThreeVector p);
-  G4ThreeVector GetMomentum();
+  inline void SetMomentum(G4ThreeVector p);
+  inline G4ThreeVector GetMomentum();
 };
 
 typedef G4THitsCollection<TrackerHit> TrackerHitsCollection;
 
 extern G4Allocator<TrackerHit> TrackerHitAllocator;
 
-// ============================================================================
-/** @fn  trackerHits
- *  Fast cast of G4VHitsCollection interface to concrete Gauss implementation
- *  @param  g4   pointer to G4VHitsCollection interface
- *  @return cast (dynamic or static) to TrackerHitsColelction*
- */
-// ============================================================================
-inline TrackerHitsCollection* trackerHits( G4VHitsCollection* g4 )
-{
-  GiGaUtil::FastCast<G4VHitsCollection, TrackerHitsCollection> cast ;
-  return cast( g4 );
+inline G4Allocator<TrackerHit>* TrackerHit::TrackerHitAllocator() {
+  thread_local auto hitAllocator = new G4Allocator<TrackerHit>{};
+  return hitAllocator;
 }
 
-inline TrackerHit* trackerHit( G4VHit* g4 )
-{
-  GiGaUtil::FastCast<G4VHit,TrackerHit> cast ;
-  return cast( g4 );
+inline void* TrackerHit::operator new(size_t) {
+  return (void*)TrackerHitAllocator()->MallocSingle();
 }
-// ============================================================================
-
-#endif
 
+inline void TrackerHit::operator delete(void* aHit) {
+  TrackerHitAllocator()->FreeSingle((TrackerHit*)aHit);
+}
 
+#include "TrackerHit.icc"
diff --git a/Sim/GaussTracker/src/TrackerHit.icc b/Sim/GaussTracker/src/TrackerHit.icc
new file mode 100644
index 000000000..4355faec2
--- /dev/null
+++ b/Sim/GaussTracker/src/TrackerHit.icc
@@ -0,0 +1,67 @@
+//=============================================================================
+// Constructor
+//=============================================================================
+TrackerHit::TrackerHit(const TrackerHit &right)
+  : GaussHitBase(right)
+{
+  m_edep = right.m_edep;
+  m_entryPos = right.m_entryPos;
+  m_exitPos = right.m_exitPos;
+  m_timeOfFlight = right.m_timeOfFlight;
+  m_momentum = right.m_momentum;
+}
+
+//=============================================================================
+// Accessors for energy deposition
+//=============================================================================
+void TrackerHit::SetEdep(G4double de) { 
+  m_edep = de; 
+}
+
+G4double TrackerHit::GetEdep() { 
+  return m_edep; 
+}
+
+//=============================================================================
+// Accessors for entry point
+//=============================================================================
+void TrackerHit::SetEntryPos(G4ThreeVector xyz) { 
+  m_entryPos = xyz; 
+}
+
+G4ThreeVector TrackerHit::GetEntryPos() {
+  return m_entryPos; 
+}
+
+//=============================================================================
+// Accessors for exit point
+//=============================================================================
+void TrackerHit::SetExitPos(G4ThreeVector xyz) { 
+  m_exitPos = xyz; 
+}
+
+G4ThreeVector TrackerHit::GetExitPos() { 
+  return m_exitPos; 
+}
+
+//=============================================================================
+// Accessors for time of flight at entry point
+//=============================================================================
+void TrackerHit::SetTimeOfFlight(G4double tof) { 
+  m_timeOfFlight = tof; 
+}
+
+G4double TrackerHit::GetTimeOfFlight() { 
+  return m_timeOfFlight;
+}
+
+//=============================================================================
+// Accessors for momentum at entry point
+//=============================================================================
+void TrackerHit::SetMomentum(G4ThreeVector p) {
+  m_momentum = p; 
+}
+ 
+G4ThreeVector TrackerHit::GetMomentum() {
+  return m_momentum; 
+} 
-- 
GitLab


From 2067d6744534b3ff110dbe4c5547eb93ddb1e67d Mon Sep 17 00:00:00 2001
From: Dominik Muller <dominik.muller@cern.ch>
Date: Tue, 18 Dec 2018 14:24:06 +0100
Subject: [PATCH 02/90] TrackerHits function local ptr to val

---
 Sim/GaussTracker/src/TrackerHit.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/Sim/GaussTracker/src/TrackerHit.h b/Sim/GaussTracker/src/TrackerHit.h
index ba4037898..509dcf3f7 100755
--- a/Sim/GaussTracker/src/TrackerHit.h
+++ b/Sim/GaussTracker/src/TrackerHit.h
@@ -60,8 +60,8 @@ typedef G4THitsCollection<TrackerHit> TrackerHitsCollection;
 extern G4Allocator<TrackerHit> TrackerHitAllocator;
 
 inline G4Allocator<TrackerHit>* TrackerHit::TrackerHitAllocator() {
-  thread_local auto hitAllocator = new G4Allocator<TrackerHit>{};
-  return hitAllocator;
+  thread_local auto hitAllocator = G4Allocator<TrackerHit>{};
+  return &hitAllocator;
 }
 
 inline void* TrackerHit::operator new(size_t) {
-- 
GitLab


From b07014beebb0371f4dd64a2953a27ace01b338a7 Mon Sep 17 00:00:00 2001
From: Dominik Muller <dominik.muller@cern.ch>
Date: Sat, 18 May 2019 14:24:51 +0200
Subject: [PATCH 03/90] Ported GaussTracker

---
 .gitignore                                    | 249 ++++++--
 CMakeLists.txt                                |   6 +-
 .../GaussCore}/DetTrackInfo.h                 |   0
 .../GaussCore/GaussTrackInformation.h         | 177 ++++++
 .../src/Lib/GaussTrackInformation.cpp         |  28 +
 Sim/GaussKine/src/GenerationToSimulation.cpp  | 571 +++++++++++-------
 .../GaussTools/GaussTrackInformation.h        | 195 ------
 .../GaussTools/GaussTrackInformation.icpp     |  21 -
 .../src/Components/GaussTrackActionHepMC.cpp  | 335 ----------
 .../src/Components/GaussTrackActionHepMC.h    |  98 ---
 .../src/Lib/GaussTrackInformation.cpp         | 135 -----
 Sim/GaussTracker/CMakeLists.txt               |  15 +-
 Sim/GaussTracker/src/GetTrackerHitsAlg.cpp    | 236 +++-----
 Sim/GaussTracker/src/GetTrackerHitsAlg.h      | 110 ++--
 Sim/GaussTracker/src/GiGaSensDetTracker.cpp   |  46 +-
 Sim/GaussTracker/src/GiGaSensDetTracker.h     |  51 +-
 .../src/GiGaSensDetTrackerFAC.cpp             |  25 +
 Sim/GaussTracker/src/TrackerHit.h             |  36 +-
 Sim/GaussTracker/src/TrackerHit.icc           |   2 +-
 19 files changed, 971 insertions(+), 1365 deletions(-)
 rename Sim/{GaussTools/GaussTools => GaussCore/GaussCore}/DetTrackInfo.h (100%)
 create mode 100755 Sim/GaussCore/GaussCore/GaussTrackInformation.h
 create mode 100755 Sim/GaussCore/src/Lib/GaussTrackInformation.cpp
 delete mode 100755 Sim/GaussTools/GaussTools/GaussTrackInformation.h
 delete mode 100755 Sim/GaussTools/GaussTools/GaussTrackInformation.icpp
 delete mode 100755 Sim/GaussTools/src/Components/GaussTrackActionHepMC.cpp
 delete mode 100755 Sim/GaussTools/src/Components/GaussTrackActionHepMC.h
 delete mode 100755 Sim/GaussTools/src/Lib/GaussTrackInformation.cpp
 create mode 100644 Sim/GaussTracker/src/GiGaSensDetTrackerFAC.cpp

diff --git a/.gitignore b/.gitignore
index 44d671029..b301cf426 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,49 +1,202 @@
-# backup files
+# Created by https://www.gitignore.io/api/vim,c++,root,python,fortran
+# Edit at https://www.gitignore.io/?templates=vim,c++,root,python,fortran
+
+### C++ ###
+# Prerequisites
+*.d
+
+# Compiled Object files
+*.slo
+*.lo
+*.o
+*.obj
+
+# Precompiled Headers
+*.gch
+*.pch
+
+# Compiled Dynamic libraries
+*.so
+*.dylib
+*.dll
+
+# Fortran module files
+*.mod
+*.smod
+
+# Compiled Static libraries
+*.lai
+*.la
+*.a
+*.lib
+
+# Executables
+*.exe
+*.out
+*.app
+
+### Fortran ###
+# Prerequisites
+
+# Compiled Object files
+
+# Precompiled Headers
+
+# Compiled Dynamic libraries
+
+# Fortran module files
+
+# Compiled Static libraries
+
+# Executables
+
+### Python ###
+# Byte-compiled / optimized / DLL files
+__pycache__/
+*.py[cod]
+*$py.class
+
+# C extensions
+
+# Distribution / packaging
+.Python
+build/
+develop-eggs/
+dist/
+downloads/
+eggs/
+.eggs/
+lib/
+lib64/
+parts/
+sdist/
+var/
+wheels/
+share/python-wheels/
+*.egg-info/
+.installed.cfg
+*.egg
+MANIFEST
+
+# PyInstaller
+#  Usually these files are written by a python script from a template
+#  before PyInstaller builds the exe, so as to inject date/other infos into it.
+*.manifest
+*.spec
+
+# Installer logs
+pip-log.txt
+pip-delete-this-directory.txt
+
+# Unit test / coverage reports
+htmlcov/
+.tox/
+.nox/
+.coverage
+.coverage.*
+.cache
+nosetests.xml
+coverage.xml
+*.cover
+.hypothesis/
+.pytest_cache/
+
+# Translations
+*.mo
+*.pot
+
+# Django stuff:
+*.log
+local_settings.py
+db.sqlite3
+
+# Flask stuff:
+instance/
+.webassets-cache
+
+# Scrapy stuff:
+.scrapy
+
+# Sphinx documentation
+docs/_build/
+
+# PyBuilder
+target/
+
+# Jupyter Notebook
+.ipynb_checkpoints
+
+# IPython
+profile_default/
+ipython_config.py
+
+# pyenv
+.python-version
+
+# celery beat schedule file
+celerybeat-schedule
+
+# SageMath parsed files
+*.sage.py
+
+# Environments
+.env
+.venv
+env/
+venv/
+ENV/
+env.bak/
+venv.bak/
+
+# Spyder project settings
+.spyderproject
+.spyproject
+
+# Rope project settings
+.ropeproject
+
+# mkdocs documentation
+/site
+
+# mypy
+.mypy_cache/
+.dmypy.json
+dmypy.json
+
+# Pyre type checker
+.pyre/
+
+### Python Patch ###
+.venv/
+
+### ROOT ###
+# ROOT Home Page : https://root.cern.ch/
+# ROOT Used by Experimental Physicists, not necessarily HEP
+# ROOT based on C++
+
+# Files generated by ROOT, observed with v6.xy
+
+*.pcm
+
+
+
+### Vim ###
+# Swap
+[._]*.s[a-v][a-z]
+[._]*.sw[a-p]
+[._]s[a-rt-v][a-z]
+[._]ss[a-gi-z]
+[._]sw[a-p]
+
+# Session
+Session.vim
+
+# Temporary
+.netrwhist
 *~
-.*.swp
-
-# build products
-InstallArea/
-
-# CMake temporary files
-build.*/
-.build/
-build-dir/
-CMakeFiles/
-CTestTestfile.cmake
-CPackSourceConfig.cmake
-CPackConfig.cmake
-cmake_install.cmake
-
-# common byproducts
-*.pyc
-*.pyo
-DoxyWarnings.log
-.gdb_history
-*.new
-*.launch
-*.launch.py
-*.launch.opts
-
-# Eclipse data
-.project
-.cproject
-.settings
-.pydevproject
-.eclipse/
-
-# CMT temporary files
-build.*.log
-Makefile
-NMake
-install.*.history
-setup.*
-cleanup.*
-version.cmt
-genConf/
-QMTest/
-test_results/
-*-slc[56]-*/
-i686-winxp-vc9-dbg/
-.*-slc[56]-*.d/
-.i686-winxp-vc9-dbg.d/
+# Auto-generated tag files
+tags
+# Persistent undo
+[._]*.un~
+
+# End of https://www.gitignore.io/api/vim,c++,root,python,fortran
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 8143ebef6..9c5f6b881 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -3,6 +3,7 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8.5)
 #---------------------------------------------------------------
 # Load macros and functions for Gaudi-based projects
 find_package(GaudiProject)
+set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
 #---------------------------------------------------------------
 
 macro(FindG4libs)
@@ -20,10 +21,9 @@ macro(FindG4libs)
 endmacro()
 
 # Declare project name and version
-gaudi_project(Gauss v54r1
+gaudi_project(Gauss v60r0
               FORTRAN
-              USE LHCb v51r0
-                  Geant4 v106r1
+              USE Gaussino v1r0
               DATA AppConfig VERSION v3r*
                    BcVegPyData VERSION v3r*
                    Det/GDMLData VERSION v1r*
diff --git a/Sim/GaussTools/GaussTools/DetTrackInfo.h b/Sim/GaussCore/GaussCore/DetTrackInfo.h
similarity index 100%
rename from Sim/GaussTools/GaussTools/DetTrackInfo.h
rename to Sim/GaussCore/GaussCore/DetTrackInfo.h
diff --git a/Sim/GaussCore/GaussCore/GaussTrackInformation.h b/Sim/GaussCore/GaussCore/GaussTrackInformation.h
new file mode 100755
index 000000000..ee83477f0
--- /dev/null
+++ b/Sim/GaussCore/GaussCore/GaussTrackInformation.h
@@ -0,0 +1,177 @@
+#pragma once
+// ============================================================================
+/// STL
+#include <string>
+#include <vector>
+/// Geant4
+#include "Geant4/G4VUserTrackInformation.hh"
+/// GaussTools
+#include "DetTrackInfo.h"
+#include "Geant4/G4Allocator.hh"
+#include "GiGaMTCore/GaussHitBase.h"
+
+/** @class GaussTrackInformation GaussTrackInformation.h
+ *
+ *  Class which is used to store auxilliary information about G4Track,
+ *
+ *  @author  Witek Pokorski Witold.Pokorski@cern.ch
+ *  @author  Vanya Belyaev Ivan.Belyaev@itep.ru
+ *  @date    23/02/2001
+ */
+
+///
+class GaussTrackInformation : public G4VUserTrackInformation {
+  public:
+  // the actual tyep of hit conatiner
+  typedef std::vector<GaussHitBase*> Hits;
+
+  public:
+  /** copy constructor
+   *  @param right object to be copied
+   */
+  GaussTrackInformation(const GaussTrackInformation& right);
+
+  /// destructor
+  virtual ~GaussTrackInformation(){ delete m_detInfo; };
+
+  /// clone (virtual constructor)
+  virtual GaussTrackInformation* clone() const;
+
+  /// overloaded operator new
+  inline void* operator new(size_t);
+
+  /// overloaded operator delete
+  inline void operator delete(void*);
+
+  /// needed by base class
+  void Print() const override{};
+
+  /// flag to append the step
+  inline bool appendStep() const { return m_appendStep; }
+
+  /** set new value for flag to append step
+   *  @param value new value of the flag
+   */
+  inline GaussTrackInformation& setAppendStep(const bool value) {
+    m_appendStep = value;
+    return *this;
+  }
+
+  /// flag to force the saving of track into traectory
+  inline bool toBeStored() const { return m_toBeStored; }
+
+  /** set new value for flag to force the saving track into trajectory
+   *  @param value new value of the flag
+   */
+  inline GaussTrackInformation& setToBeStored(const bool value) {
+    m_toBeStored = value;
+    return *this;
+  }
+
+  /// track created a hit
+  inline bool createdHit() const { return m_createdHit; }
+
+  /** set new value for flag
+   *  @param value new value of the flag
+   */
+  inline GaussTrackInformation& setCreatedHit(const bool value) {
+    m_createdHit = value;
+    return *this;
+  }
+
+  // Retrieve if direct parent particle has been stored or not
+  inline bool directParent() const { return m_directParent; }
+
+  // Set if direct parent particle has been stored or not
+  inline GaussTrackInformation& setDirectParent(const bool value) {
+    m_directParent = value;
+    return *this;
+  }
+
+  /// Get flag to store or not in internal HepMC structure
+  inline bool storeHepMC() const { return m_storeHepMC; }
+
+  /// Set value of flag to store or not in internal HepMC structure
+  inline GaussTrackInformation& setStoreHepMC(const bool value) {
+    m_storeHepMC = value;
+    return *this;
+  }
+
+  /** add hit pointer
+   *  @param hit hit to be added into list of connected hits
+   */
+  GaussTrackInformation& addHit(GaussHitBase* hit) {
+    if (0 != hit) {
+      m_hits.push_back(hit);
+    };
+    return *this;
+  }
+
+  /** add hit pointer
+   *  @param hit hit to be added into list of connected hits
+   */
+  GaussTrackInformation& addToHits(GaussHitBase* hit) { return addHit(hit); }
+
+  // get the container of hits
+  const Hits& hits() const { return m_hits; }
+
+  /** update Tracks IDs in hits
+   *  (set the new track ID for all connected hits)
+   *  @param trackID new value of trackID
+   */
+  GaussTrackInformation& updateHitsTrackID(G4int trackID) {
+    for (Hits::iterator ihit = m_hits.begin(); m_hits.end() != ihit; ++ihit) {
+      GaussHitBase* hit = *ihit;
+      if (0 != hit) {
+        hit->setTrackID(trackID);
+      }
+    }
+    return *this;
+  }
+
+  /** get the pointer to the detInfo
+   */
+  DetTrackInfo* detInfo() const { return m_detInfo; }
+
+  /** set the pointer to the detInfo
+   *  @param aDetInfo pointer to DetTrackInfo
+   */
+  void setDetInfo(DetTrackInfo* aDetInfo) { m_detInfo = aDetInfo; }
+
+  inline static G4Allocator<GaussTrackInformation>*
+  GaussTrackInformationAllocator();
+
+  private:
+  /// flag indicating that TrajectoryPoint should be appended
+  bool m_appendStep{false};
+  /// flag indicating that track is forced to be stored into trajectory
+  bool m_toBeStored{false};
+  /// flag indicating that track created a hit
+  bool m_createdHit{false};
+  /// flag indicating that the direct parent particle was not stored
+  /// in HepMC event this will be represented by a special 'dummy' link
+  bool m_directParent{true};
+  // flag indicating that the track should be stored in HepMC record
+  bool m_storeHepMC{false};
+
+  /// vector of pointers to hits created by that track
+  Hits m_hits{};
+
+  /// pointer to a specialised DetTrackInfo object containing detector-specific
+  /// track information
+  DetTrackInfo* m_detInfo{nullptr};
+};
+
+inline G4Allocator<GaussTrackInformation>*
+GaussTrackInformation::GaussTrackInformationAllocator() {
+  thread_local auto hitAllocator = G4Allocator<GaussTrackInformation>{};
+  return &hitAllocator;
+}
+
+inline void* GaussTrackInformation::operator new(size_t) {
+  return (void*)GaussTrackInformationAllocator()->MallocSingle();
+}
+
+inline void GaussTrackInformation::operator delete(void* info) {
+  GaussTrackInformationAllocator()->FreeSingle((GaussTrackInformation*)info);
+}
diff --git a/Sim/GaussCore/src/Lib/GaussTrackInformation.cpp b/Sim/GaussCore/src/Lib/GaussTrackInformation.cpp
new file mode 100755
index 000000000..2ecf71496
--- /dev/null
+++ b/Sim/GaussCore/src/Lib/GaussTrackInformation.cpp
@@ -0,0 +1,28 @@
+#include "GaussCore/GaussTrackInformation.h"
+
+// ============================================================================
+/** @file
+ *  Implementation file for class : GaussTrackInformation
+ *  @author  Witek Pokorski Witold.Pokorski@cern.ch
+ *  @author  Vanya Belyaev Ivan.Belyaev@itep.ru
+ *  @date    23/02/2001
+ */
+// ============================================================================
+
+GaussTrackInformation::GaussTrackInformation(const GaussTrackInformation& right)
+    : G4VUserTrackInformation(right),
+      m_appendStep(right.m_appendStep),
+      m_toBeStored(right.m_toBeStored),
+      m_createdHit(right.m_createdHit),
+      m_directParent(right.m_directParent),
+      m_storeHepMC(right.m_storeHepMC),
+      m_hits(right.m_hits),
+      m_detInfo(right.m_detInfo) {
+#ifdef GIGA_DEBUG
+  GaussTrackInformationLocal::s_Counter.increment();
+#endif
+}
+
+GaussTrackInformation* GaussTrackInformation::clone() const {
+  return new GaussTrackInformation(*this);
+}
diff --git a/Sim/GaussKine/src/GenerationToSimulation.cpp b/Sim/GaussKine/src/GenerationToSimulation.cpp
index 13ea7881f..cfcc9a29c 100755
--- a/Sim/GaussKine/src/GenerationToSimulation.cpp
+++ b/Sim/GaussKine/src/GenerationToSimulation.cpp
@@ -3,12 +3,12 @@
 #include "MCInterfaces/IFlagSignalChain.h"
 
 // Gaudi.
-#include "GaudiKernel/Vector3DTypes.h"
-#include "GaudiKernel/Transform4DTypes.h"
 #include "GaudiKernel/PhysicalConstants.h"
+#include "GaudiKernel/Transform4DTypes.h"
+#include "GaudiKernel/Vector3DTypes.h"
 
 // GiGa.
-#include "GiGa/IGiGaSvc.h" 
+#include "GiGa/IGiGaSvc.h"
 #include "GiGaCnv/GiGaPrimaryParticleInformation.h"
 
 // Event.
@@ -23,10 +23,10 @@
 #include "GenEvent/HepMCUtils.h"
 
 // Geant4.
-#include "Geant4/G4PrimaryVertex.hh"
-#include "Geant4/G4PrimaryParticle.hh"
-#include "Geant4/G4ParticleTable.hh"
 #include "Geant4/G4ParticlePropertyTable.hh"
+#include "Geant4/G4ParticleTable.hh"
+#include "Geant4/G4PrimaryParticle.hh"
+#include "Geant4/G4PrimaryVertex.hh"
 
 //-----------------------------------------------------------------------------
 // Implementation file for class : GenerationToSimulation
@@ -41,35 +41,36 @@ DECLARE_COMPONENT(GenerationToSimulation)
 // Standard constructor, declares properties.
 //=============================================================================
 GenerationToSimulation::GenerationToSimulation(const std::string& name,
-					       ISvcLocator* pSvcLocator) : 
-  GaudiAlgorithm(name, pSvcLocator), m_gigaSvc(0), m_particleContainer(0), 
-  m_vertexContainer(0), m_keepCuts(LoKi::Constant<const HepMC::GenParticle*, 
-				   bool>(true)) {
+                                               ISvcLocator* pSvcLocator)
+    : GaudiAlgorithm(name, pSvcLocator),
+      m_gigaSvc(0),
+      m_particleContainer(0),
+      m_vertexContainer(0),
+      m_keepCuts(LoKi::Constant<const HepMC::GenParticle*, bool>(true)) {
   declareProperty("GiGaService", m_gigaSvcName = "GiGa",
-		  "Name of the GiGa service.");
+                  "Name of the GiGa service.");
   declareProperty("HepMCEventLocation",
-		  m_generationLocation = LHCb::HepMCEventLocation::Default,
-		  "Location to read the HepMC event.");
+                  m_generationLocation = LHCb::HepMCEventLocation::Default,
+                  "Location to read the HepMC event.");
   declareProperty("Particles",
-		  m_particlesLocation = LHCb::MCParticleLocation::Default,
-		  "Location to place the MCParticles.");
+                  m_particlesLocation = LHCb::MCParticleLocation::Default,
+                  "Location to place the MCParticles.");
   declareProperty("Vertices",
-		  m_verticesLocation = LHCb::MCVertexLocation::Default,
-		  "Location to place the MCVertices.");  
+                  m_verticesLocation = LHCb::MCVertexLocation::Default,
+                  "Location to place the MCVertices.");
   declareProperty("TravelLimit", m_travelLimit = 1e-10 * CLHEP::m,
-		  "Pass particles to Geant4 with travel length above this.");
-  declareProperty("LookForUnknownParticles", 
-		  m_lookForUnknownParticles = false,
-		  "Check if Geant4 knows the particle type.");
+                  "Pass particles to Geant4 with travel length above this.");
+  declareProperty("LookForUnknownParticles", m_lookForUnknownParticles = false,
+                  "Check if Geant4 knows the particle type.");
   declareProperty("SkipGeant", m_skipGeant4 = false,
-		  "Skip passing everything to Geant4.");
-  declareProperty("UpdateG4ParticleProperties", 
-		  m_updateG4ParticleProperties = true,
-		  "Update the Geant4 particle properties.");
+                  "Skip passing everything to Geant4.");
+  declareProperty("UpdateG4ParticleProperties",
+                  m_updateG4ParticleProperties = true,
+                  "Update the Geant4 particle properties.");
   declareProperty("MCHeader", m_mcHeader = LHCb::MCHeaderLocation::Default,
-		  "Location to retrieve the MCHeader.");
-  declareProperty("KeepCode", m_keepCode = "", 
-		  "The code to flag additional particles for storage.");
+                  "Location to retrieve the MCHeader.");
+  declareProperty("KeepCode", m_keepCode = "",
+                  "The code to flag additional particles for storage.");
 }
 
 //=============================================================================
@@ -81,32 +82,30 @@ GenerationToSimulation::~GenerationToSimulation() {}
 // Initialization.
 //=============================================================================
 StatusCode GenerationToSimulation::initialize() {
-
   // Initialize the GaudiAlgorithm, return if failure.
-  StatusCode sc = GaudiAlgorithm::initialize(); 
+  StatusCode sc = GaudiAlgorithm::initialize();
   if (sc.isFailure()) return sc;
 
   // Intialize the tool.
   debug() << "==> Initialize" << endmsg;
   if (!m_skipGeant4) {
-    
     // Create the GiGa service.
     m_gigaSvc = svc<IGiGaSvc>(m_gigaSvcName, true);
-  
+
     // Update Geant4 particle properties from ParticlePropertySvc.
-    if (m_updateG4ParticleProperties) { 
-      LHCb::IParticlePropertySvc* ppSvc = 
-        svc<LHCb::IParticlePropertySvc>("LHCb::ParticlePropertySvc", true);
-      G4ParticlePropertyTable* PPT = G4ParticlePropertyTable::
-	GetParticlePropertyTable();
+    if (m_updateG4ParticleProperties) {
+      LHCb::IParticlePropertySvc* ppSvc =
+          svc<LHCb::IParticlePropertySvc>("LHCb::ParticlePropertySvc", true);
+      G4ParticlePropertyTable* PPT =
+          G4ParticlePropertyTable::GetParticlePropertyTable();
       G4ParticleTable* particleTable = G4ParticleTable::GetParticleTable();
 
       // Suppress printing unknown PDGs from Gauss.
       if (!msgLevel(MSG::DEBUG)) particleTable->SetVerboseLevel(0);
       for (int i = 0; i < particleTable->size(); ++i) {
         G4ParticleDefinition* PDef = particleTable->GetParticle(i);
-        const LHCb::ParticleProperty* pp = ppSvc->
-	  find(LHCb::ParticleID(PDef->GetPDGEncoding()));
+        const LHCb::ParticleProperty* pp =
+            ppSvc->find(LHCb::ParticleID(PDef->GetPDGEncoding()));
         if (pp) {
           G4ParticlePropertyData* PPData = PPT->GetParticleProperty(PDef);
           PPData->SetPDGMass(pp->mass());
@@ -117,19 +116,19 @@ StatusCode GenerationToSimulation::initialize() {
       release(ppSvc);
     }
   }
-  
+
   // Cuts to keep additional particles.
   if (m_keepCode != "") {
     svc<IService>("LoKiSvc");
-    LoKi::IGenHybridFactory* factory = tool<LoKi::IGenHybridFactory>
-      ("LoKi::Hybrid::GenTool/GenFactory:PUBLIC", this);
+    LoKi::IGenHybridFactory* factory = tool<LoKi::IGenHybridFactory>(
+        "LoKi::Hybrid::GenTool/GenFactory:PUBLIC", this);
     sc = factory->get(m_keepCode, m_keepCuts);
-    if (sc.isFailure()) 
+    if (sc.isFailure())
       always() << "Error from KeepCode = '" + m_keepCode + "'" << endmsg;
   }
 
   // get tool to set signal flag
-  m_setSignalFlagTool = tool< IFlagSignalChain >( "FlagSignalChain" );
+  m_setSignalFlagTool = tool<IFlagSignalChain>("FlagSignalChain");
 
   return StatusCode::SUCCESS;
 }
@@ -138,27 +137,27 @@ StatusCode GenerationToSimulation::initialize() {
 // Main execution.
 //=============================================================================
 StatusCode GenerationToSimulation::execute() {
-  
   // Retrieve the HepMCEvents.
   debug() << "==> Execute" << endmsg;
-  LHCb::HepMCEvents* generationEvents = 
-    get<LHCb::HepMCEvents>(m_generationLocation);
+  LHCb::HepMCEvents* generationEvents =
+      get<LHCb::HepMCEvents>(m_generationLocation);
 
   // Create containers in TES for MCParticles and MCVertices.
   m_particleContainer = new LHCb::MCParticles();
   put(m_particleContainer, m_particlesLocation);
   m_vertexContainer = new LHCb::MCVertices();
   put(m_vertexContainer, m_verticesLocation);
-  if (!generationEvents || generationEvents->size() == 0)
-    {*gigaSvc() << NULL; return StatusCode::SUCCESS;}
+  if (!generationEvents || generationEvents->size() == 0) {
+    *gigaSvc() << NULL;
+    return StatusCode::SUCCESS;
+  }
 
   // Retrieve the MCHeader.
   LHCb::MCHeader* mcHeader = get<LHCb::MCHeader>(m_mcHeader);
 
   // Loop over the events (one for each pile-up interaction).
-  for(LHCb::HepMCEvents::const_iterator genEvent = generationEvents->begin(); 
+  for (LHCb::HepMCEvents::const_iterator genEvent = generationEvents->begin();
        generationEvents->end() != genEvent; ++genEvent) {
-
     // Retrieve the event.
     HepMC::GenEvent* ev = (*genEvent)->pGenEvt();
 
@@ -166,9 +165,13 @@ StatusCode GenerationToSimulation::execute() {
     m_g4ParticleMap.clear();
     m_mcParticleMap.clear();
     m_particlesToDelete.clear();
-    
+
     // Determine the position of the primary vertex.
     Gaudi::LorentzVector thePV = primaryVertex(ev);
+<<<<<<< HEAD
+=======
+
+>>>>>>> Ported GaussTracker
     /*
       Set G4PrimaryVertex to this position. The assumption is that all
       particles transferred to Geant4 for this pile up interaction
@@ -176,56 +179,62 @@ StatusCode GenerationToSimulation::execute() {
       with non zero lifetimes must be passed to Geant4 and then must
       be declared to Geant4 so that they can be transported correctly.
     */
-    G4PrimaryVertex* origVertex = 
-      new G4PrimaryVertex(thePV.X(), thePV.Y(), thePV.Z(), thePV.T());
+    G4PrimaryVertex* origVertex =
+        new G4PrimaryVertex(thePV.X(), thePV.Y(), thePV.Z(), thePV.T());
 
     // Create and add the primary MCVertex.
     LHCb::MCVertex* primaryVertex = new LHCb::MCVertex();
     m_vertexContainer->insert(primaryVertex);
-    primaryVertex->setPosition(Gaudi::XYZPoint( thePV.Vect()));
+    primaryVertex->setPosition(Gaudi::XYZPoint(thePV.Vect()));
     primaryVertex->setTime(thePV.T());
     primaryVertex->setType(LHCb::MCVertex::ppCollision);
     mcHeader->addToPrimaryVertices(primaryVertex);
-  
+
     // Set ID of all vertices to 0.
     for (HepMC::GenEvent::vertex_iterator itV = ev->vertices_begin();
-	 itV != ev->vertices_end(); ++itV) (*itV)->set_id(0);
+         itV != ev->vertices_end(); ++itV)
+      (*itV)->set_id(0);
 
     // Extract the particles to store in MCParticles.
     std::vector<HepMC::GenParticle*> mctruthList;
     for (HepMC::GenEvent::particle_const_iterator itP = ev->particles_begin();
-	 itP != ev->particles_end(); ++itP) {
-      if (keep(*itP) || (m_keepCode != "" && m_keepCuts(*itP))) { 
+         itP != ev->particles_end(); ++itP) {
+      if (keep(*itP) || (m_keepCode != "" && m_keepCuts(*itP))) {
         mctruthList.push_back(*itP);
-	
-	/*
+
+        /*
          Set the ID of of the end vertex to one, then the particle
          with production vertex of ID 0 and end vertex of ID 1 (or
          without end vertex) will be the start point of a decay tree
          to convert to MCTruth.
-	*/
+        */
         HepMC::GenVertex* endVertex = (*itP)->end_vertex();
         if (endVertex) endVertex->set_id(1);
       }
     }
-    
+
     // Sort the particles to be stored by barcode and then convert them.
-    std::sort(mctruthList.begin(), mctruthList.end(), 
-	      HepMCUtils::compareHepMCParticles);
+    std::sort(mctruthList.begin(), mctruthList.end(),
+              HepMCUtils::compareHepMCParticles);
     for (std::vector<HepMC::GenParticle*>::iterator it = mctruthList.begin();
-	 mctruthList.end() != it; ++it) {
+         mctruthList.end() != it; ++it) {
       HepMC::GenVertex* prodVertex = (*it)->production_vertex();
+<<<<<<< HEAD
       if (!prodVertex) 
         warning() << "The particle has no production vertex !!" <<endmsg;
+=======
+      if (!prodVertex)
+        warning() << "The particle has no production vertex !!" << endmsg;
+>>>>>>> Ported GaussTracker
       else if (0 == prodVertex->id())
         convert(*it, origVertex, primaryVertex, 0, 0);
     }
-    
+
     // Remove from the primary vertex and delete the unneeded particles.
     if (!m_particlesToDelete.empty()) {
-      std::vector< G4PrimaryParticle*>::const_iterator itDel;
-      for (itDel = m_particlesToDelete.begin(); 
-	   itDel != m_particlesToDelete.end(); ++itDel) { 
+      std::vector<G4PrimaryParticle*>::const_iterator itDel;
+      for (itDel = m_particlesToDelete.begin();
+           itDel != m_particlesToDelete.end(); ++itDel) {
         removeFromPrimaryVertex(origVertex, *itDel);
         delete *itDel;
       }
@@ -234,13 +243,14 @@ StatusCode GenerationToSimulation::execute() {
   }
 
   // This needs to be done only if Geant4 is not called since in that case
-  // the setting of the flags for the daughters is taken care of by 
+  // the setting of the flags for the daughters is taken care of by
   // SimulationToMCTruth
-  if ( m_skipGeant4 ) {
+  if (m_skipGeant4) {
     LHCb::MCParticles::const_iterator ip;
-    for ( ip = m_particleContainer->begin(); ip != m_particleContainer->end(); ip++ ) {
-      if ( (*ip)->fromSignal() ) {
-        m_setSignalFlagTool->setFromSignalFlag( *ip );
+    for (ip = m_particleContainer->begin(); ip != m_particleContainer->end();
+         ip++) {
+      if ((*ip)->fromSignal()) {
+        m_setSignalFlagTool->setFromSignalFlag(*ip);
       }
     }
   }
@@ -251,8 +261,9 @@ StatusCode GenerationToSimulation::execute() {
 //=============================================================================
 // Decides if a particle should be kept in MCParticles.
 //=============================================================================
-bool GenerationToSimulation::keep(const HepMC::GenParticle* particle) const{
+bool GenerationToSimulation::keep(const HepMC::GenParticle* particle) const {
   LHCb::ParticleID pid(particle->pdg_id());
+<<<<<<< HEAD
   switch (particle -> status()) {
   case LHCb::HepMCEvent::StableInProdGen: return true;
   case LHCb::HepMCEvent::DecayedByDecayGen: return true;
@@ -321,6 +332,109 @@ bool GenerationToSimulation::keep(const HepMC::GenParticle* particle) const{
     }
     return true;
   default: return false;
+=======
+  switch (particle->status()) {
+    case LHCb::HepMCEvent::StableInProdGen:
+      return true;
+    case LHCb::HepMCEvent::DecayedByDecayGen:
+      return true;
+    case LHCb::HepMCEvent::DecayedByDecayGenAndProducedByProdGen:
+      return true;
+    case LHCb::HepMCEvent::SignalInLabFrame:
+      return true;
+    case LHCb::HepMCEvent::StableInDecayGen:
+      return true;
+
+    // For some processes the resonance has status 3.
+    case LHCb::HepMCEvent::DocumentationParticle:
+      if (24 == particle->parent_event()->signal_process_id()) {
+        if (23 == pid.abspid())
+          return true;
+        else if (25 == pid.abspid())
+          return true;
+      } else if (26 == particle->parent_event()->signal_process_id()) {
+        if (24 == pid.abspid())
+          return true;
+        else if (25 == pid.abspid())
+          return true;
+      } else if (102 == particle->parent_event()->signal_process_id()) {
+        if (25 == pid.abspid()) return true;
+      } else if (6 == pid.abspid())
+        return true;
+      return false;
+    case LHCb::HepMCEvent::Unknown:
+      return false;
+    case LHCb::HepMCEvent::DecayedByProdGen:
+      if (pid.isHadron()) return true;
+      if (pid.isLepton()) return true;
+      if (pid.isNucleus()) return true;
+      if (pid.isDiQuark()) return false;
+
+      // Store particles of interest.
+      switch (pid.abspid()) {
+        case LHCb::ParticleID::down:
+          return false;
+        case LHCb::ParticleID::up:
+          return false;
+        case LHCb::ParticleID::strange:
+          return false;
+        case LHCb::ParticleID::charm:
+          return true;
+        case LHCb::ParticleID::bottom:
+          return true;
+        case LHCb::ParticleID::top:
+          return false;
+        case 21:
+          return false;  // Gluon.
+        case 22:
+          return true;  // Photon.
+        case 23:        // Z0.
+          if (24 == particle->parent_event()->signal_process_id())
+            return false;
+          else
+            return true;
+        case 24:  // W.
+          if (26 == particle->parent_event()->signal_process_id())
+            return false;
+          else
+            return true;
+        case 25:  // SM Higgs.
+          if (24 == particle->parent_event()->signal_process_id() ||
+              26 == particle->parent_event()->signal_process_id() ||
+              102 == particle->parent_event()->signal_process_id())
+            return false;
+          else
+            return true;
+        case 32:
+          return true;  // Z'.
+        case 33:
+          return true;  // Z''.
+        case 34:
+          return true;  // W'.
+        case 35:
+          return true;  // CP-even heavy Higgs (H0/H2).
+        case 36:
+          return true;  // CP-odd Higgs (A0/H3).
+        case 37:
+          return true;  // Charged Higgs (H+).
+        // See Table 6 of the Pythia 6 manual (arxiv.org/abs/hep-ph/0603175).
+        case 90:
+          return false;  // System particle.
+        case 91:
+          return false;  // Parton system from cluster fragmentation.
+        case 92:
+          return false;  // Parton system from string fragmentation.
+        case 93:
+          return false;  // Parton system from independent fragmentation.
+        case 94:
+          return false;  // Time-like showering system.
+        default:
+          return true;
+      }
+      return true;
+    default:
+      return false;
+>>>>>>> Ported GaussTracker
   }
   return false;
 }
@@ -328,100 +442,101 @@ bool GenerationToSimulation::keep(const HepMC::GenParticle* particle) const{
 //=============================================================================
 // Convert a decay tree into MCParticle or to G4PrimaryParticle.
 //=============================================================================
-void GenerationToSimulation::convert(HepMC::GenParticle*& particle, 
-				     G4PrimaryVertex* pvertexg4,
-				     LHCb::MCVertex* originVertex,
-				     G4PrimaryParticle* motherg4,
-				     LHCb::MCParticle* mothermcp) {
-
+void GenerationToSimulation::convert(HepMC::GenParticle*& particle,
+                                     G4PrimaryVertex* pvertexg4,
+                                     LHCb::MCVertex* originVertex,
+                                     G4PrimaryParticle* motherg4,
+                                     LHCb::MCParticle* mothermcp) {
   // Decision to convert the particle.
   unsigned char conversionCode = transferToGeant4(particle);
   switch (conversionCode) {
-  case 1: { // Convert particle to G4.
-
-    // Check if particle has been converted.
-    const int pBarcode = particle->barcode();
-    std::map<int, std::pair<bool, G4PrimaryParticle*> >::const_iterator 
-      result = m_g4ParticleMap.find(pBarcode);
-    if (result != m_g4ParticleMap.end()) {
-
-      // Return if converted.
-      if (result->second.first) return;
-
-      // Flag for deletion.
-      else {
-	m_g4ParticleMap.erase(pBarcode);
-	m_particlesToDelete.push_back(result->second.second);
+    case 1: {  // Convert particle to G4.
+
+      // Check if particle has been converted.
+      const int pBarcode = particle->barcode();
+      std::map<int, std::pair<bool, G4PrimaryParticle*>>::const_iterator
+          result = m_g4ParticleMap.find(pBarcode);
+      if (result != m_g4ParticleMap.end()) {
+        // Return if converted.
+        if (result->second.first) return;
+
+        // Flag for deletion.
+        else {
+          m_g4ParticleMap.erase(pBarcode);
+          m_particlesToDelete.push_back(result->second.second);
+        }
       }
+      G4PrimaryParticle* g4P = makeG4Particle(particle, mothermcp);
+
+      // Check mother.
+      if (!motherg4) {
+        // Flag for recreation with correct mother link.
+        if (!mothermcp)
+          m_g4ParticleMap.insert(
+              std::make_pair(pBarcode, std::make_pair(false, g4P)));
+        else
+          m_g4ParticleMap.insert(
+              std::make_pair(pBarcode, std::make_pair(true, g4P)));
+
+        // Attach root particle to G4 primary vertex.
+        if (pvertexg4)
+          pvertexg4->SetPrimary(g4P);
+        else
+          error() << "Primary vertex points to NULL !" << endmsg;
+
+        // Set mother link.
+      } else {
+        m_g4ParticleMap.insert(
+            std::make_pair(pBarcode, std::make_pair(true, g4P)));
+        motherg4->SetDaughter(g4P);
+      }
+      pvertexg4 = 0;
+      originVertex = 0;
+      motherg4 = g4P;
+      mothermcp = 0;
+      break;
     }
-    G4PrimaryParticle* g4P = makeG4Particle(particle, mothermcp);
-
-    // Check mother.
-    if (!motherg4) {
-
-      // Flag for recreation with correct mother link.
-      if (!mothermcp) m_g4ParticleMap.insert
-			(std::make_pair(pBarcode, std::make_pair(false, g4P)));
-      else m_g4ParticleMap.insert
-	     (std::make_pair(pBarcode, std::make_pair(true, g4P)));
-
-      // Attach root particle to G4 primary vertex.
-      if (pvertexg4) pvertexg4->SetPrimary(g4P);
-      else error() << "Primary vertex points to NULL !" << endmsg ;
-
-    // Set mother link.
-    } else {
-      m_g4ParticleMap.insert
-	(std::make_pair(pBarcode, std::make_pair(true, g4P)));
-      motherg4->SetDaughter(g4P);
-    }
-    pvertexg4 = 0;
-    originVertex = 0;
-    motherg4 = g4P;
-    mothermcp = 0; 
-    break;
-  }
-  case 2: { // Convert to MCParticle.
-
-    // Check if already converted.
-    const int pBarcode = particle->barcode() ;
-    std::map<int, bool>::const_iterator result = m_mcParticleMap.find(pBarcode);
-    if (result != m_mcParticleMap.end()) return;
-    
-    // Convert the particle.
-    LHCb::MCVertex* endVertex = 0 ;
-    LHCb::MCParticle* mcP = makeMCParticle(particle, endVertex);
-    if (originVertex) {
-      mcP->setOriginVertex(originVertex);
-      originVertex->addToProducts(mcP);
+    case 2: {  // Convert to MCParticle.
+
+      // Check if already converted.
+      const int pBarcode = particle->barcode();
+      std::map<int, bool>::const_iterator result =
+          m_mcParticleMap.find(pBarcode);
+      if (result != m_mcParticleMap.end()) return;
+
+      // Convert the particle.
+      LHCb::MCVertex* endVertex = 0;
+      LHCb::MCParticle* mcP = makeMCParticle(particle, endVertex);
+      if (originVertex) {
+        mcP->setOriginVertex(originVertex);
+        originVertex->addToProducts(mcP);
+      }
+      m_mcParticleMap.insert(std::make_pair(pBarcode, true));
+      mothermcp = mcP;
+      originVertex = endVertex;
+      break;
     }
-    m_mcParticleMap.insert(std::make_pair(pBarcode, true));
-    mothermcp = mcP;
-    originVertex = endVertex; 
-    break;
-  }
-  case 3: // Skip the particle.
-  default:
-    break;
+    case 3:  // Skip the particle.
+    default:
+      break;
   }
 
   // Convert all daughters of the HepMC particle (recurse).
   HepMC::GenVertex* ev = particle->end_vertex();
   if (ev) {
-
     // Create the list.
     std::vector<HepMC::GenParticle*> dList;
-    for (HepMC::GenVertex::particle_iterator itD = ev->particles_begin
-	   (HepMC::children); itD != ev->particles_end(HepMC::children); 
-	 ++itD) {
+    for (HepMC::GenVertex::particle_iterator itD =
+             ev->particles_begin(HepMC::children);
+         itD != ev->particles_end(HepMC::children); ++itD) {
       HepMC::GenParticle* P = (*itD);
       dList.push_back(P);
     }
-    
+
     // Sort by barcode and convert.
     std::sort(dList.begin(), dList.end(), HepMCUtils::compareHepMCParticles);
-    for (std::vector<HepMC::GenParticle*>::iterator itDD = dList.begin(); 
-	 dList.end() != itDD; ++itDD) {
+    for (std::vector<HepMC::GenParticle*>::iterator itDD = dList.begin();
+         dList.end() != itDD; ++itDD) {
       HepMC::GenParticle* P = (*itDD);
       convert(P, pvertexg4, originVertex, motherg4, mothermcp);
     }
@@ -434,19 +549,19 @@ void GenerationToSimulation::convert(HepMC::GenParticle*& particle,
 // 2: convert to MCParticle directly, the particle is not sent to Geant4.
 // 3: skip the particle completely.
 //=============================================================================
-unsigned char GenerationToSimulation::transferToGeant4
-(const HepMC::GenParticle* p) const {
+unsigned char GenerationToSimulation::transferToGeant4(
+    const HepMC::GenParticle* p) const {
   if (!(keep(p) || (m_keepCode != "" && m_keepCuts(p)))) return 3;
   if (m_skipGeant4) return 2;
 
   // Return for Geant4 tracking if stable.
   HepMC::GenVertex* ev = p->end_vertex();
-  if (!ev) { 
-    if (m_lookForUnknownParticles) 
-      if (!G4ParticleTable::GetParticleTable()->FindParticle(p->pdg_id())) 
-        warning() << "The particle " << p -> pdg_id() 
-		  << " is not known to Geant4 but travels a finite distance" 
-		  << endmsg;
+  if (!ev) {
+    if (m_lookForUnknownParticles)
+      if (!G4ParticleTable::GetParticleTable()->FindParticle(p->pdg_id()))
+        warning() << "The particle " << p->pdg_id()
+                  << " is not known to Geant4 but travels a finite distance"
+                  << endmsg;
     return 1;
   }
 
@@ -460,69 +575,67 @@ unsigned char GenerationToSimulation::transferToGeant4
   if (dist < m_travelLimit) return 2;
 
   // Return for Geant4 tracking if stable.
-  if (m_lookForUnknownParticles) 
-    if (!G4ParticleTable::GetParticleTable()->FindParticle(p->pdg_id())) 
-      warning() << "The particle " << p -> pdg_id() 
-		<< " is not known to Geant4 but travels a finite distance" 
-		<< endmsg;
+  if (m_lookForUnknownParticles)
+    if (!G4ParticleTable::GetParticleTable()->FindParticle(p->pdg_id()))
+      warning() << "The particle " << p->pdg_id()
+                << " is not known to Geant4 but travels a finite distance"
+                << endmsg;
   return 1;
 }
 
 //=============================================================================
 // Create a G4PrimaryParticle from a HepMC Particle.
 //=============================================================================
-G4PrimaryParticle* GenerationToSimulation::makeG4Particle
-(HepMC::GenParticle*& particle, LHCb::MCParticle* mcp) const {
-  HepMC::FourVector mom = particle -> momentum();
-  G4PrimaryParticle * g4P = new G4PrimaryParticle(particle->pdg_id(), mom.x(), 
-						  mom.y(), mom.z());
+G4PrimaryParticle* GenerationToSimulation::makeG4Particle(
+    HepMC::GenParticle*& particle, LHCb::MCParticle* mcp) const {
+  HepMC::FourVector mom = particle->momentum();
+  G4PrimaryParticle* g4P =
+      new G4PrimaryParticle(particle->pdg_id(), mom.x(), mom.y(), mom.z());
   g4P->SetMass(particle->generated_mass());
-  
+
   // Create information containing the HepMC link and signal information.
-  bool isSignalParticle(LHCb::HepMCEvent::SignalInLabFrame == 
-			(particle->status()));
-  GiGaPrimaryParticleInformation* gInfo = new GiGaPrimaryParticleInformation
-    (isSignalParticle, particle->barcode(), 0);
+  bool isSignalParticle(LHCb::HepMCEvent::SignalInLabFrame ==
+                        (particle->status()));
+  GiGaPrimaryParticleInformation* gInfo = new GiGaPrimaryParticleInformation(
+      isSignalParticle, particle->barcode(), 0);
 
   HepMC::GenVertex* ev = particle->end_vertex();
   if (ev) {
-    
     // Set propertime of the particle.
     double life = lifetime(mom, particle->production_vertex(), ev);
     g4P->SetProperTime(life);
-    
+
     // Store if particle has oscillated.
     const HepMC::GenParticle* B = hasOscillated(particle);
-    if (B) { 
+    if (B) {
       gInfo->setHasOscillated(true);
       particle = const_cast<HepMC::GenParticle*>(B);
     }
   }
-  
+
   // Link to MCParticle to be able to rebuild history later.
   if (mcp) gInfo->setMotherMCParticle(mcp);
   g4P->SetUserInformation(gInfo);
-  return g4P ;
+  return g4P;
 }
 
 //=============================================================================
 // Create an MCParticle from a HepMC GenParticle.
 //=============================================================================
-LHCb::MCParticle* GenerationToSimulation::makeMCParticle
-(HepMC::GenParticle*& particle, LHCb::MCVertex*& endVertex) const {
-
+LHCb::MCParticle* GenerationToSimulation::makeMCParticle(
+    HepMC::GenParticle*& particle, LHCb::MCVertex*& endVertex) const {
   // Create and insert into TES.
-  LHCb::MCParticle * mcp = new LHCb::MCParticle();
+  LHCb::MCParticle* mcp = new LHCb::MCParticle();
   m_particleContainer->insert(mcp);
 
   // Set properties.
   Gaudi::LorentzVector mom(particle->momentum());
   LHCb::ParticleID pid(particle->pdg_id());
-  mcp -> setMomentum(mom);
-  mcp -> setParticleID(pid);
-  
+  mcp->setMomentum(mom);
+  mcp->setParticleID(pid);
+
   // Set the vertex.
-  HepMC::GenVertex* V = particle->end_vertex() ;
+  HepMC::GenVertex* V = particle->end_vertex();
   if (V) {
     endVertex = new LHCb::MCVertex();
     m_vertexContainer->insert(endVertex);
@@ -533,19 +646,25 @@ LHCb::MCParticle* GenerationToSimulation::makeMCParticle
     // Check if the particle has oscillated.
     const HepMC::GenParticle* B = hasOscillated(particle);
     if (B) {
-      endVertex->setType( LHCb::MCVertex::OscillatedAndDecay);
+      endVertex->setType(LHCb::MCVertex::OscillatedAndDecay);
       particle = const_cast<HepMC::GenParticle*>(B);
-    } else if (( 4 == pid.abspid()) || (5 == pid.abspid()))
-      endVertex->setType( LHCb::MCVertex::StringFragmentation);
+    } else if ((4 == pid.abspid()) || (5 == pid.abspid()))
+      endVertex->setType(LHCb::MCVertex::StringFragmentation);
     else
-      endVertex -> setType( LHCb::MCVertex::DecayVertex);
-    mcp -> addToEndVertices(endVertex);
+      endVertex->setType(LHCb::MCVertex::DecayVertex);
+    mcp->addToEndVertices(endVertex);
   }
   
   //  Set the fromSignal flag
+<<<<<<< HEAD
   if ( LHCb::HepMCEvent::SignalInLabFrame == (particle->status())  ) {
       mcp -> setFromSignal(true);
     }
+=======
+  if (LHCb::HepMCEvent::SignalInLabFrame == (particle->status())) {
+    mcp->setFromSignal(true);
+  }
+>>>>>>> Ported GaussTracker
 
   //  Set the incoming parton flag
   // some more placeholders for status to be added
@@ -563,34 +682,40 @@ LHCb::MCParticle* GenerationToSimulation::makeMCParticle
 //=============================================================================
 // Determine the primary vertex for the event.
 //=============================================================================
-Gaudi::LorentzVector GenerationToSimulation::primaryVertex
-(const HepMC::GenEvent* genEvent) const {
+Gaudi::LorentzVector GenerationToSimulation::primaryVertex(
+    const HepMC::GenEvent* genEvent) const {
   Gaudi::LorentzVector result(0, 0, 0, 0);
 
   // First method, get the beam particle and use the decay vertex if it exists.
   if (genEvent->valid_beam_particles()) {
     HepMC::GenParticle* P = genEvent->beam_particles().first;
-    HepMC::GenVertex*   V = P->end_vertex();
-    if (V) result = V->position(); 
-    else error() << "The beam particles have no end vertex!" << endmsg;
-  // Second method, use the singal vertex stored in HepMC.
-  } else if ( 0 != genEvent -> signal_process_vertex() ) {
+    HepMC::GenVertex* V = P->end_vertex();
+    if (V)
+      result = V->position();
+    else
+      error() << "The beam particles have no end vertex!" << endmsg;
+    // Second method, use the singal vertex stored in HepMC.
+  } else if (0 != genEvent->signal_process_vertex()) {
     HepMC::GenVertex* V = genEvent->signal_process_vertex();
     result = V->position();
-  // Third method, take production/end vertex of the particle with barcode 1.
+    // Third method, take production/end vertex of the particle with barcode 1.
   } else {
     HepMC::GenParticle* P = genEvent->barcode_to_particle(1);
-    HepMC::GenVertex*   V = 0;
+    HepMC::GenVertex* V = 0;
     if (P) {
       V = P->production_vertex();
-      if (V) result = V->position();
+      if (V)
+        result = V->position();
       else {
         V = P->end_vertex();
-        if (V) result = V->position();
-        else error() << "The first particle has no production vertex and "
-		     << "no end vertex !" << endmsg ;
+        if (V)
+          result = V->position();
+        else
+          error() << "The first particle has no production vertex and "
+                  << "no end vertex !" << endmsg;
       }
-    } else error() << "No particle with barcode equal to 1!" << endmsg;
+    } else
+      error() << "No particle with barcode equal to 1!" << endmsg;
   }
   return result;
 }
@@ -598,9 +723,9 @@ Gaudi::LorentzVector GenerationToSimulation::primaryVertex
 //=============================================================================
 // Compute the lifetime of a particle.
 //=============================================================================
-double GenerationToSimulation::lifetime(const HepMC::FourVector mom, 
-					const HepMC::GenVertex* P,
-					const HepMC::GenVertex* E ) const {
+double GenerationToSimulation::lifetime(const HepMC::FourVector mom,
+                                        const HepMC::GenVertex* P,
+                                        const HepMC::GenVertex* E) const {
   if (!E) return 0;
   Gaudi::LorentzVector A(P->position()), B(E->position());
   Gaudi::LorentzVector AB = B - A;
@@ -612,7 +737,7 @@ double GenerationToSimulation::lifetime(const HepMC::FourVector mom,
   Gaudi::LorentzVector M(mom);
   ROOT::Math::Boost theBoost(M.BoostToCM());
   Gaudi::LorentzVector ABStar = theBoost(AB);
-  
+
   // Switch back to time.
   return ABStar.T() / Gaudi::Units::c_light;
 }
@@ -620,13 +745,13 @@ double GenerationToSimulation::lifetime(const HepMC::FourVector mom,
 //=============================================================================
 // Check if a particle has oscillated.
 //=============================================================================
-const HepMC::GenParticle* GenerationToSimulation::hasOscillated
-(const HepMC::GenParticle* P) const {
+const HepMC::GenParticle* GenerationToSimulation::hasOscillated(
+    const HepMC::GenParticle* P) const {
   const HepMC::GenVertex* ev = P->end_vertex();
-  if (!ev) return 0 ; 
+  if (!ev) return 0;
   if (1 != ev->particles_out_size()) return 0;
   const HepMC::GenParticle* D = *(ev->particles_out_const_begin());
-  if (!D) return 0 ;
+  if (!D) return 0;
   if (-P->pdg_id() != D->pdg_id()) return 0;
   return D;
 }
@@ -634,18 +759,18 @@ const HepMC::GenParticle* GenerationToSimulation::hasOscillated
 //=============================================================================
 // Remove a particle from a primary vertex.
 //=============================================================================
-void GenerationToSimulation::removeFromPrimaryVertex
-(G4PrimaryVertex*& pvertexg4, const G4PrimaryParticle* particleToDelete) const {
-
+void GenerationToSimulation::removeFromPrimaryVertex(
+    G4PrimaryVertex*& pvertexg4,
+    const G4PrimaryParticle* particleToDelete) const {
   // This should be rare, so warn.
-  warning() << "A G4PrimaryParticle will be removed from the G4PrimaryVertex" 
-	    << endmsg ;
+  warning() << "A G4PrimaryParticle will be removed from the G4PrimaryVertex"
+            << endmsg;
   particleToDelete->Print();
 
   // Make a new vertex.
-  G4PrimaryVertex* newVertex = new G4PrimaryVertex
-    (pvertexg4->GetX0(), pvertexg4->GetY0(),
-     pvertexg4->GetZ0(), pvertexg4->GetT0());
+  G4PrimaryVertex* newVertex =
+      new G4PrimaryVertex(pvertexg4->GetX0(), pvertexg4->GetY0(),
+                          pvertexg4->GetZ0(), pvertexg4->GetT0());
 
   // Copy particles to new vertex, except the one to remove.
   G4PrimaryParticle* particle = pvertexg4->GetPrimary();
diff --git a/Sim/GaussTools/GaussTools/GaussTrackInformation.h b/Sim/GaussTools/GaussTools/GaussTrackInformation.h
deleted file mode 100755
index 18cd67ca2..000000000
--- a/Sim/GaussTools/GaussTools/GaussTrackInformation.h
+++ /dev/null
@@ -1,195 +0,0 @@
-// ============================================================================
-#ifndef      GaussTools_GaussTrackInformation_H
-#define      GaussTools_GaussTrackInformation_H 1
-// ============================================================================
-/// STL
-#include <string>
-#include <vector>
-// GiGa
-#include "GiGa/GiGaUtil.h"
-/// Geant4
-#include "Geant4/G4VUserTrackInformation.hh"
-/// GaussTools
-#include "GaussTools/GaussHitBase.h"
-#include "GaussTools/DetTrackInfo.h"
-
-/** @class GaussTrackInformation GaussTrackInformation.h
- *
- *  Class which is used to store auxilliary information about G4Track,
- *
- *  @author  Witek Pokorski Witold.Pokorski@cern.ch
- *  @author  Vanya Belyaev Ivan.Belyaev@itep.ru
- *  @date    23/02/2001
- */
-
-///
-class GaussTrackInformation : public G4VUserTrackInformation
-{
-public:
-  // the actual tyep of hit conatiner
-  typedef std::vector<GaussHitBase*> Hits;
-public:
-
-  /// default (empty) constructor
-  GaussTrackInformation() ;
-
-  /** copy constructor
-   *  @param right object to be copied
-   */
-  GaussTrackInformation( const GaussTrackInformation& right );
-
-  /// destructor
-  virtual ~GaussTrackInformation() ;
-
-  /// clone (virtual constructor)
-  virtual GaussTrackInformation* clone() const ;
-
-  /// overloaded operator new
-  void* operator new    ( size_t );
-
-  /// overloaded operator delete
-  void  operator delete ( void*  );
-
-  /// needed by base class
-  void Print      () const override {};
-
-  /// flag to append the step
-  bool appendStep () const { return m_appendStep ; }
-
-  /** set new value for flag to append step
-   *  @param value new value of the flag
-   */
-  GaussTrackInformation& setAppendStep ( const bool value )
-  { m_appendStep = value ; return *this ; }
-
-  /// flag to force the saving of track into traectory
-  bool toBeStored () const { return m_toBeStored ; }
-
-  /** set new value for flag to force the saving track into trajectory
-   *  @param value new value of the flag
-   */
-  GaussTrackInformation& setToBeStored ( const bool value )
-  { m_toBeStored = value ; return *this ; }
-
-  /// track created a hit
-  bool createdHit() const { return m_createdHit ; }
-
-  /** set new value for flag
-   *  @param value new value of the flag
-   */
-  GaussTrackInformation& setCreatedHit ( const bool value )
-  { m_createdHit = value ; return *this ; }
-
-  // Retrieve if direct parent particle has been stored or not
-  bool directParent() const {return m_directParent;}
-
-  // Set if direct parent particle has been stored or not
-  GaussTrackInformation& setDirectParent(const bool value)
-  { m_directParent = value; return *this;}
-
-  /// Get flag to store or not in internal HepMC structure
-  bool storeHepMC() const {return m_storeHepMC;}
-
-  /// Set value of flag to store or not in internal HepMC structure
-  GaussTrackInformation& setStoreHepMC(const bool value)
-  { m_storeHepMC = value; return *this;}
-
-  /** add hit pointer
-   *  @param hit hit to be added into list of connected hits
-   */
-  GaussTrackInformation& addHit    ( GaussHitBase* hit )
-  { if ( 0 != hit ) { m_hits.push_back( hit ) ; } ; return *this ; }
-
-  /** add hit pointer
-   *  @param hit hit to be added into list of connected hits
-   */
-  GaussTrackInformation& addToHits ( GaussHitBase* hit )
-  { return addHit( hit ) ; }
-
-  // get the container of hits
-  const Hits& hits() const { return m_hits ; }
-
-  /** update Tracks IDs in hits
-   *  (set the new track ID for all connected hits)
-   *  @param trackID new value of trackID
-   */
-  GaussTrackInformation& updateHitsTrackID( G4int trackID )
-  {
-    for( Hits::iterator ihit = m_hits.begin() ; m_hits.end() != ihit ; ++ihit )
-      {
-        GaussHitBase* hit = *ihit ;
-        if( 0 != hit ) { hit->setTrackID( trackID ); }
-      }
-    return *this ;
-  }
-
-  /** get the pointer to the detInfo
-   */
-  DetTrackInfo* detInfo() const { return  m_detInfo; }
-
-  /** set the pointer to the detInfo
-   *  @param aDetInfo pointer to DetTrackInfo
-   */
-  void setDetInfo ( DetTrackInfo* aDetInfo )
-  { m_detInfo = aDetInfo; }
-
-
-private:
-
-  /// flag indicating that TrajectoryPoint should be appended
-  bool m_appendStep ;
-  /// flag indicating that track is forced to be stored into trajectory
-  bool m_toBeStored ;
-  /// flag indicating that track created a hit
-  bool m_createdHit ;
-  /// flag indicating that the direct parent particle was not stored
-  /// in HepMC event this will be represented by a special 'dummy' link
-  bool m_directParent;
-  // flag indicating that the track should be stored in HepMC record
-  bool m_storeHepMC;
-
-  /// vector of pointers to hits created by that track
-  Hits  m_hits;
-
-  /// pointer to a specialised DetTrackInfo object containing detector-specific
-  /// track information
-  DetTrackInfo* m_detInfo;
-
-};
-
-
-// ===========================================================================
-/** @fn  gaussTrackInformation
- *  @param  g4  pointer to G4VUserTrackInformation object
- *  @return cast (dynamic or static to GaussTrackInformation
- *  @author  Vanya Belyaev Ivan.Belyaev@itep.ru
- *  @date    2002-12-07
- */
-// ============================================================================
-inline GaussTrackInformation*
-gaussTrackInformation ( G4VUserTrackInformation* g4 )
-{
-  GiGaUtil::FastCast<G4VUserTrackInformation,GaussTrackInformation> cast;
-  return cast( g4 );
-}
-
-
-// ===========================================================================
-/** @fn  gaussTrackInformation
- *  @param  g4  pointer to G4VUserTrackInformation object
- *  @return cast (dynamic or static to GaussTrackInformation
- *  @author  Vanya Belyaev Ivan.Belyaev@itep.ru
- *  @date    2002-12-07
- */
-// ============================================================================
-inline const GaussTrackInformation*
-gaussTrackInformation ( const G4VUserTrackInformation* g4 )
-{
-  GiGaUtil::FastCast<
-    const G4VUserTrackInformation,const GaussTrackInformation> cast;
-  return cast( g4 );
-}
-
-// ============================================================================
-#endif   ///<  GIGA_GaussTrackInformation_H
-
diff --git a/Sim/GaussTools/GaussTools/GaussTrackInformation.icpp b/Sim/GaussTools/GaussTools/GaussTrackInformation.icpp
deleted file mode 100755
index e03e46e09..000000000
--- a/Sim/GaussTools/GaussTools/GaussTrackInformation.icpp
+++ /dev/null
@@ -1,21 +0,0 @@
-// $Id: GaussTrackInformation.icpp,v 1.2 2002-12-07 21:19:13 ibelyaev Exp $ 
-// ============================================================================
-// CVS tag $Name: not supported by cvs2svn $ 
-// ============================================================================
-// $Log: not supported by cvs2svn $
-// ============================================================================
-#ifndef     GaussTools_GaussTrackInformation_ICPP
-#define     GaussTools_GaussTrackInformation_ICPP 1 
-// ============================================================================
-
-/** implementation of inline methods from class GaussTrackInformation 
- *  
- *  @author Vanya Belyaev 
- */
-
-// ============================================================================
-#endif  //  GaussTools_GaussTrackInformation_ICPP
-// ============================================================================
-
-
-
diff --git a/Sim/GaussTools/src/Components/GaussTrackActionHepMC.cpp b/Sim/GaussTools/src/Components/GaussTrackActionHepMC.cpp
deleted file mode 100755
index 83312ca34..000000000
--- a/Sim/GaussTools/src/Components/GaussTrackActionHepMC.cpp
+++ /dev/null
@@ -1,335 +0,0 @@
-// $Id: GaussTrackActionHepMC.cpp,v 1.9 2008-10-20 08:23:11 robbep Exp $
-// Include files 
-
-// STD & STL 
-#include <functional>
-#include <algorithm>
-
-// from Gaudi
-
-// from LHCb 
-#include "Kernel/IParticlePropertySvc.h"
-#include "Kernel/ParticleProperty.h"
-
-// G4
-#include "Geant4/G4TrackingManager.hh"
-#include "Geant4/G4PrimaryParticle.hh"
-
-// GiGa 
-#include "GiGa/IGiGaSvc.h"
-#include "GiGa/GiGaUtil.h"
-#include "GiGaCnv/GiGaPrimaryParticleInformation.h"
-
-// LHCb
-#include "Event/MCVertex.h"
-
-// Gauss
-#include "GaussTools/GaussTrackInformation.h"
-
-// local 
-#include "GaussTrackActionHepMC.h"
-
-// ============================================================================
-/** @file 
- *  
- *  Implementation file for class : GaussTrackActionHepMC
- *  @date 24/07/2001 
- *  @author Witek Pokorski
- */
-// ============================================================================
-
-// Declaration of the Tool Factory
-DECLARE_COMPONENT( GaussTrackActionHepMC )
-
-// ============================================================================
-/** standard constructor 
- *  @see GiGaTrackActionBase 
- *  @see GiGaBase 
- *  @see AlgTool 
- *  @param type type of the object (?)
- *  @param name name of the object
- *  @param parent  pointer to parent object
- */
-// ============================================================================
-GaussTrackActionHepMC::GaussTrackActionHepMC
-( const std::string& type   ,
-  const std::string& name   ,
-  const IInterface*  parent ) 
-  : GiGaTrackActionBase( type , name , parent  ) 
-{
-  m_mcMgr = MCTruthManager::GetInstance();
-
-  m_hadronicProcesses.clear();
-  m_hadronicProcesses.push_back( "KaonPlusInelastic"             ) ;
-  m_hadronicProcesses.push_back( "PionMinusAbsorptionAtRest"     ) ;
-  m_hadronicProcesses.push_back( "KaonZeroLInelastic"            ) ;
-  m_hadronicProcesses.push_back( "KaonZeroSInelastic"            ) ;
-  m_hadronicProcesses.push_back( "MuonMinusCaptureAtRest"        ) ; 
-  m_hadronicProcesses.push_back( "TritonInelastic"               ) ;
-  m_hadronicProcesses.push_back( "KaonMinusAbsorption"           ) ;
-  m_hadronicProcesses.push_back( "LambdaInelastic"               ) ;
-  m_hadronicProcesses.push_back( "SigmaMinusInelastic"           ) ;
-  m_hadronicProcesses.push_back( "LCapture"                      ) ;
-  m_hadronicProcesses.push_back( "AntiNeutronAnnihilationAtRest" ) ;
-  m_hadronicProcesses.push_back( "AntiProtonAnnihilationAtRest"  ) ;  
-  m_hadronicProcesses.push_back( "AntiLambdaInelastic"           ) ;
-  m_hadronicProcesses.push_back( "AntiXiZeroInelastic"           ) ;
-  m_hadronicProcesses.push_back( "AntiSigmaPlusInelastic"        ) ;
-  m_hadronicProcesses.push_back( "SigmaPlusInelastic"            ) ;
-  m_hadronicProcesses.push_back( "XiMinusInelastic"              ) ;
-  m_hadronicProcesses.push_back( "XiZeroInelastic"               ) ;
-  m_hadronicProcesses.push_back( "AntiSigmaMinusInelastic"       ) ;
-  m_hadronicProcesses.push_back( "AntiXiMinusInelastic"          ) ;
-  m_hadronicProcesses.push_back( "OmegaMinusInelastic"           ) ;
-  m_hadronicProcesses.push_back( "AntiOmegaMinusInelastic"       ) ;
-  m_hadronicProcesses.push_back( "AlphaInelastic"                ) ;
-  
-  std::sort ( m_hadronicProcesses.begin () ,
-              m_hadronicProcesses.end   () ) ;
-  
-}
-
-
-// ============================================================================
-/// destructor 
-// ============================================================================
-GaussTrackActionHepMC::~GaussTrackActionHepMC() {}
-
-
-// ============================================================================
-/** initialise the action object 
- *  @return status code
- */ 
-// ============================================================================
-StatusCode GaussTrackActionHepMC::initialize () 
-{
-  StatusCode sc = GiGaTrackActionBase::initialize();
-  if( sc.isFailure() ) 
-  { return Error("Could not initialize the base class!", sc ); }
-
-  m_ppSvc = svc<LHCb::IParticlePropertySvc> ( "LHCb::ParticlePropertySvc", true );
-
-  return Print("Iinitialized successfully" , 
-               StatusCode::SUCCESS         , MSG::VERBOSE );
-}
-
-// ============================================================================
-// finalize
-// ============================================================================
-StatusCode GaussTrackActionHepMC::finalize() {
-
-  debug() << "==> Finalize" << endmsg;
-
-  return GiGaTrackActionBase::finalize();  // must be called after all other actions
-}
-
-// ============================================================================
-/** perform the pre-action
- *  @param track pointer to Geant4 track object 
- */ 
-// ============================================================================
-void GaussTrackActionHepMC::PreUserTrackingAction  ( const G4Track* track )
-{
-  // new track is being started
-  // we record its initial momentum 
-  fourmomentum = HepMC::FourVector( track->GetMomentum().x(),
-                                    track->GetMomentum().y(),
-                                    track->GetMomentum().z(),
-                                    track->GetTotalEnergy() );
-
-  // This should have been done in GaussPostTrackAction, but check here
-  if( !track->GetUserInformation() ) {    
-    GaussTrackInformation* mcinf = new GaussTrackInformation();
-    trackMgr()->SetUserTrackInformation(mcinf);
-  }
-
-  // Reset momentum in the case of short lived from HepMC
-//  if( track->GetDefinition()->IsShortLived() ) {
-//    if( NULL != track->GetDynamicParticle() ) {
-//      if( NULL != track->GetDynamicParticle()->GetPrimaryParticle() ) {
-//        G4VUserPrimaryParticleInformation* g4uInf = 
-//          track->GetDynamicParticle()->GetPrimaryParticle()->GetUserInformation();
-//        if( g4uInf ) {
-//          GiGaPrimaryParticleInformation* uInf = 
-//            (GiGaPrimaryParticleInformation*) g4uInf;
-//          HepMC::GenEvent* gEvt = uInf->pHepMCEvent()->pGenEvt();
-//          HepMC::GenParticle* gPart = 
-//            gEvt->barcode_to_particle( uInf->signalBarcode() );
-//          fourmomentum = gPart->momentum();
-//        }
-//      }
-//    }
-//  }
-
-}
-
-
-// ============================================================================
-/** perform the post-action
- *  @param track pointer to Geant4 track object 
- */ 
-// ============================================================================
-void GaussTrackActionHepMC::PostUserTrackingAction  ( const G4Track* track )
-{
-  
-//   HepMC::GenEvent* genevt = m_mcMgr->GetCurrentEvent();
-  
-  // if track is to be stored, create new GenParticle, and its decay vertex
-  // we check the flag (store or not store) in the GaussTrackInformation
-  GaussTrackInformation* ginf = (GaussTrackInformation*) track->GetUserInformation();
-
-  if( ginf->storeHepMC() ) {
-    HepMC::FourVector prodpos(track->GetVertexPosition().x(),
-                              track->GetVertexPosition().y(),
-                              track->GetVertexPosition().z(),
-                              track->GetGlobalTime() - track->GetLocalTime());
-    HepMC::FourVector endpos(track->GetPosition().x(), 
-                             track->GetPosition().y(), 
-                             track->GetPosition().z(), 
-                             track->GetGlobalTime());
-
-    // Get the pdgID+LHCb extension
-    int pdgID = track->GetDefinition()->GetPDGEncoding();
-    if( 0 == pdgID ) {
-      // Use dynamic particle PDG Id in this case (unknown particle)
-      if ( NULL != track -> GetDynamicParticle() ) {
-        if ( NULL != track -> GetDynamicParticle() -> GetPrimaryParticle() ) {
-          pdgID = track -> GetDynamicParticle() -> GetPrimaryParticle() -> GetPDGcode() ;
-          if ( "unknown" == track->GetDefinition()->GetParticleName() ) {
-            double ener = 
-              sqrt( track->GetDynamicParticle()->GetPrimaryParticle()->GetMomentum().mag2() + 
-                    track -> GetDynamicParticle() -> GetPrimaryParticle() -> GetMass() * 
-                    track -> GetDynamicParticle() -> GetPrimaryParticle() -> GetMass() ) ;
-            fourmomentum.setPx( track -> GetDynamicParticle() -> GetPrimaryParticle() -> GetMomentum().x() ) ;
-            fourmomentum.setPy( track -> GetDynamicParticle() -> GetPrimaryParticle() -> GetMomentum().y() ) ;
-            fourmomentum.setPz( track -> GetDynamicParticle() -> GetPrimaryParticle() -> GetMomentum().z() ) ;
-            fourmomentum.setE( ener ) ;
-          }
-        }
-      } 
-      if ( 0 == pdgID ) {
-        // Last chance, use name of particle
-        const LHCb::ParticleProperty* pProp = 
-          m_ppSvc->find( track->GetDefinition()->GetParticleName() );
-        if( NULL != pProp ) {
-          pdgID = pProp->pdgID().pid();
-        } else {
-          std::string message = "PDGEncoding does not exist, G4 name is ";
-          message += track->GetDefinition()->GetParticleName();
-          Warning( message, StatusCode::SUCCESS, 10 );
-        }
-      }
-    }
-    // get the process type of the origin vertex
-    int creatorID = processID( track->GetCreatorProcess() );
-
-    // Get User information from primary particle to set Vertex type 
-    // OscillatedAndDecay and to set SignalFlag
-    bool hasOscillated = false;
-    LHCb::MCParticle * mcp = 0 ;
-    bool isSignal = false;
-    if( NULL != track->GetDynamicParticle() ) {
-      if( NULL != track->GetDynamicParticle()->GetPrimaryParticle() ) {
-        G4VUserPrimaryParticleInformation* g4uInf = 
-          track->GetDynamicParticle()->GetPrimaryParticle()->GetUserInformation();
-        if( g4uInf ) {
-          GiGaPrimaryParticleInformation* uInf = 
-            (GiGaPrimaryParticleInformation*) g4uInf;
-          hasOscillated = uInf->hasOscillated();
-          mcp = uInf -> motherMCParticle() ;
-          isSignal = uInf -> isSignal();
-        }
-      }
-    }
-
-    m_mcMgr->AddParticle( fourmomentum, prodpos, endpos,
-                          pdgID, track->GetTrackID(), track->GetParentID(), 
-                          ginf->directParent(), creatorID, mcp , hasOscillated,
-                          isSignal );
-  }
-
-  // For the moment the following is in GaussPostTrackAction
-//   else {
-//     // If track is not to be stored, propagate it's parent ID (stored) to its
-//     // secondaries.    
-//     G4TrackVector* childrens = trackMgr()->GimmeSecondaries() ;
-//     //
-//     for( unsigned int index = 0 ; index < childrens->size() ; ++index )
-//     {
-//       G4Track* tr = (*childrens)[index] ;
-//       //
-//       tr->SetParentID( track->GetParentID() );
-//       // set the flag saying that the direct mother is not stored
-//       GaussTrackInformation* mcinf = (GaussTrackInformation*) tr->GetUserInformation();
-//       if(!mcinf) tr->SetUserInformation( mcinf = new GaussTrackInformation() );
-//       mcinf->setDirectParent( false ); 
-//       //
-//     }     
-//   }
-  
-}
-
-// ============================================================================
-// processID
-// ============================================================================
-int GaussTrackActionHepMC::processID(const G4VProcess* creator ) { 
-
-  int processID = LHCb::MCVertex::Unknown;
-  if( NULL == creator ) {
-    processID = LHCb::MCVertex::DecayVertex;
-    return processID;
-  }
-  
-  if( fDecay == creator->GetProcessType() ) {
-    processID = LHCb::MCVertex::DecayVertex;
-  }
-  else if ( fHadronic == creator->GetProcessType() ) { 
-    processID = LHCb::MCVertex::HadronicInteraction;
-  }
-  else {
-    const std::string& pname = creator->GetProcessName();
-    if( "conv"== pname ) { 
-      processID = LHCb::MCVertex::PairProduction;
-    } else if( "compt" == pname ) {
-      processID = LHCb::MCVertex::Compton;
-    } else if( "eBrem" == pname || "muBrems" == pname ) {
-      processID = LHCb::MCVertex::Bremsstrahlung;
-    } else if( "annihil" == pname ) {
-      processID = LHCb::MCVertex::Annihilation;
-    } else if( "phot" == pname ) {
-      processID = LHCb::MCVertex::PhotoElectric;
-    } else if( "RichHpdPhotoelectricProcess" == pname ) {
-      processID = LHCb::MCVertex::RICHPhotoElectric;
-    } else if( "RichPmtPhotoelectricProcess" == pname ) {
-      processID = LHCb::MCVertex::RICHPhotoElectric;
-    } else if( "TorchTBMcpPhotoElectricProcess" == pname ) {
-      processID = LHCb::MCVertex::RICHPhotoElectric;
-    } else if( "RichG4Cerenkov" == pname ) {
-      processID = LHCb::MCVertex::Cerenkov;
-    } else if( "eIoni" == pname || "hIoni" == pname || "ionIoni" == pname ||
-               "muIoni" == pname ) {
-      processID = LHCb::MCVertex::DeltaRay;
-    } else {
-      const bool found = std::binary_search( m_hadronicProcesses.begin() , 
-                                             m_hadronicProcesses.end(), pname );
-      if( found ) { 
-        processID = LHCb::MCVertex::HadronicInteraction; 
-      }
-    }
-  }
-  
-  if( processID == 0 ) {
-    // here we have an intertsting situation
-    // the process is *KNOWN*, but the vertex type 
-    // is still 'Unknown'
-    std::string message = "The process is known '" + 
-      G4VProcess::GetProcessTypeName ( creator->GetProcessType() ) + "/" +
-      creator -> GetProcessName() + "', but vertex type is still 'Unknown'";
-    Warning( message, StatusCode::SUCCESS, 10 );
-  }        
-
-  return processID;
-  
-}
-
-// ============================================================================
diff --git a/Sim/GaussTools/src/Components/GaussTrackActionHepMC.h b/Sim/GaussTools/src/Components/GaussTrackActionHepMC.h
deleted file mode 100755
index 36749bc51..000000000
--- a/Sim/GaussTools/src/Components/GaussTrackActionHepMC.h
+++ /dev/null
@@ -1,98 +0,0 @@
-// $Id: GaussTrackActionHepMC.h,v 1.4 2008-07-26 15:43:15 robbep Exp $
-#ifndef COMPONENT_GAUSSTRACKACTIONHEPMC_H
-#define COMPONENT_GAUSSTRACKACTIONHEPMC_H 1
-
-// STD & STL
-#include <string>
-#include <vector>
-// GiGa
-#include "GiGa/GiGaTrackActionBase.h"
-// Gauss
-#include "GaussTools/MCTruthManager.h"
-namespace LHCb {
-  class IParticlePropertySvc;
-}
-
-/** @class GaussTrackActionHepMC GaussTrackActionHepMC.h
- *
- *  @author Witek Pokorski
- *  @date   24/07/2001
- */
-
-class GaussTrackActionHepMC: public GiGaTrackActionBase
-{
-  /// friend factory for instantiation
-  //friend class GiGaFactory<GaussTrackActionHepMC>;
-  ///
-public:
-
-  /** initialize the track action
-   *  @see GiGaTrackActionBase
-   *  @see GiGaBase
-   *  @see  AlgTool
-   *  @see IAlgTool
-   *  @return status code
-   */
-  StatusCode initialize () override;
-
-  /** initialize the track action
-   *  @see GiGaTrackActionBase
-   *  @see GiGaBase
-   *  @see  AlgTool
-   *  @see IAlgTool
-   *  @return status code
-   */
-  StatusCode finalize () override;
-
-  /** perform the pre-action
-   *  @see G4UserTrackingAction
-   *  @param track pointer to Geant4 track object
-   */
-  void PreUserTrackingAction  ( const G4Track* track ) override;
-
-  /** perform the post-action
-   *  @see G4UserTrackingAction
-   *  @param track pointer to Geant4 track object
-   */
-  void PostUserTrackingAction ( const G4Track* track ) override;
-
-  //protected:
-
-  /** standard constructor
-   *  @see GiGaTrackActionBase
-   *  @see GiGaBase
-   *  @see AlgTool
-   *  @param type type of the object (?)
-   *  @param name name of the object
-   *  @param parent  pointer to parent object
-   */
-  GaussTrackActionHepMC
-  ( const std::string& type   ,
-    const std::string& name   ,
-    const IInterface*  parent ) ;
-
-  /// destructor (virtual and protected)
-  virtual ~GaussTrackActionHepMC();
-
-private:
-
-  /// no default constructor
-  GaussTrackActionHepMC();
-  /// no copy constructor
-  GaussTrackActionHepMC( const GaussTrackActionHepMC& );
-  /// no assignment
-  GaussTrackActionHepMC& operator=( const GaussTrackActionHepMC& );
-
-private:
-
-  int processID(const G4VProcess* creator );
-
-  MCTruthManager*        m_mcMgr;
-  LHCb::IParticlePropertySvc*  m_ppSvc;
-  HepMC::FourVector      fourmomentum;
-
-  std::vector<std::string> m_hadronicProcesses;
-
-};
-
-#endif
diff --git a/Sim/GaussTools/src/Lib/GaussTrackInformation.cpp b/Sim/GaussTools/src/Lib/GaussTrackInformation.cpp
deleted file mode 100755
index b0ffb794a..000000000
--- a/Sim/GaussTools/src/Lib/GaussTrackInformation.cpp
+++ /dev/null
@@ -1,135 +0,0 @@
-// $Id: GaussTrackInformation.cpp,v 1.5 2006-04-12 19:32:08 gcorti Exp $
-// ============================================================================
-// CVS tag $Name: not supported by cvs2svn $
-// ============================================================================
-// $Log: not supported by cvs2svn $
-// Revision 1.4  2005/10/31 09:29:44  gcorti
-// use HepMC for history during tracking
-//
-// Revision 1.3  2003/07/28 10:26:23  witoldp
-// added WorldCuts and DetTrackInfo
-//
-// Revision 1.2  2003/04/09 12:07:37  witoldp
-// added pointer to RICHInfo
-//
-// Revision 1.1  2002/12/07 21:19:14  ibelyaev
-//  few optimization updates
-// 
-// ============================================================================
-// Include files
-// GiGa 
-#include "GiGa/GiGaUtil.h"
-// local
-#include "GaussTools/GaussTrackInformation.h"
-// G4 
-#include "Geant4/G4Allocator.hh"
-
-// ============================================================================
-/** @file 
- *  Implementation file for class : GaussTrackInformation
- *  @author  Witek Pokorski Witold.Pokorski@cern.ch
- *  @author  Vanya Belyaev Ivan.Belyaev@itep.ru
- *  @date    23/02/2001
- */
-// ============================================================================
-
-// ============================================================================
-namespace GaussTrackInformationLocal
-{
-  // ==========================================================================
-  /** @var s_Allocator 
-   *  G4 allocator for fast creation of many "small" objects 
-   */
-  // ==========================================================================
-  G4Allocator<GaussTrackInformation> s_Allocator;
-  // ==========================================================================
-  /** @var s_Counter 
-   *  static instance counter 
-   */
-  // ==========================================================================
-#ifdef GIGA_DEBUG
-  static GiGaUtil::InstanceCounter<GaussTrackInformation> s_Counter ;
-#endif
-  // ==========================================================================
-}
-
-
-// ============================================================================
-/// default (empty) constructor 
-// ============================================================================
-GaussTrackInformation::GaussTrackInformation()
-  : m_appendStep(false)
-  , m_toBeStored(false)
-  , m_createdHit(false)
-  , m_directParent(true)
-  , m_storeHepMC(false)
-  , m_hits()
-  , m_detInfo(0)
-{
-#ifdef GIGA_DEBUG
-  GaussTrackInformationLocal::s_Counter.increment() ;
-#endif
-}
-
-
-
-// ============================================================================
-/// copy constructor 
-// ============================================================================
-GaussTrackInformation:: GaussTrackInformation 
-( const GaussTrackInformation& right)
-  : G4VUserTrackInformation(right) 
-  , m_appendStep(right.m_appendStep)
-  , m_toBeStored(right.m_toBeStored)
-  , m_createdHit(right.m_createdHit)
-  , m_directParent(right.m_directParent)
-  , m_storeHepMC(right.m_storeHepMC)
-  , m_hits(right.m_hits)
-  , m_detInfo(right.m_detInfo) 
-{
-#ifdef GIGA_DEBUG
-  GaussTrackInformationLocal::s_Counter.increment() ;
-#endif
-}
-
-
-// ============================================================================
-/// clone (virtual constructor)
-// ============================================================================
-GaussTrackInformation* GaussTrackInformation::clone() const 
-{ return new GaussTrackInformation( *this ); }
-// ============================================================================
-
-// ============================================================================
-/// destructor 
-// ============================================================================
-GaussTrackInformation::~GaussTrackInformation() 
-{
-  delete m_detInfo;
-
-#ifdef GIGA_DEBUG
-  GaussTrackInformationLocal::s_Counter.decrement() ;
-#endif
-}
-
-
-// ============================================================================
-/// operator new 
-// ============================================================================
-void* GaussTrackInformation::operator new    ( size_t )
-{ return (void*) GaussTrackInformationLocal::s_Allocator.MallocSingle(); }
-// ============================================================================
-
-// ============================================================================
-/// operator delete 
-// ============================================================================
-void GaussTrackInformation::operator delete ( void*  info  )
-{ 
-  GaussTrackInformationLocal::s_Allocator.FreeSingle
-    ( (GaussTrackInformation*) info ); 
-}
-
-
-// ============================================================================
-// The END 
-// ============================================================================
diff --git a/Sim/GaussTracker/CMakeLists.txt b/Sim/GaussTracker/CMakeLists.txt
index 168cb7337..67d325c3e 100644
--- a/Sim/GaussTracker/CMakeLists.txt
+++ b/Sim/GaussTracker/CMakeLists.txt
@@ -1,17 +1,24 @@
 ################################################################################
 # Package: GaussTracker
 ################################################################################
-gaudi_subdir(GaussTracker v7r0p1)
+gaudi_subdir(GaussTracker v8r0)
 
-gaudi_depends_on_subdirs(Sim/GaussTools)
+gaudi_depends_on_subdirs(GaudiAlg
+                         Sim/GiGaMTCore
+                         HepMC3
+                         Sim/GiGaMTFactories)
 
 find_package(Boost)
 find_package(CLHEP)
-include_directories(SYSTEM ${Boost_INCLUDE_DIRS} ${CLHEP_INCLUDE_DIRS} ${Geant4_INCLUDE_DIRS})
+AddHepMC3()
+include_directories(SYSTEM ${Boost_INCLUDE_DIRS} ${CLHEP_INCLUDE_DIRS} ${Geant4_INCLUDE_DIRS} ${HEPMC3_INCLUDE_DIR})
+
+add_definitions(-DG4MULTITHREADED)
+add_definitions(-DG4USE_STD11)
 
 gaudi_add_module(GaussTracker
                  src/*.cpp
-                 LINK_LIBRARIES GaussToolsLib)
+                 LINK_LIBRARIES Geant4 GiGaMTCoreTruthLib GaudiAlgLib)
 
 gaudi_env(SET GAUSSTRACKEROPTS \${GAUSSTRACKERROOT}/options)
 
diff --git a/Sim/GaussTracker/src/GetTrackerHitsAlg.cpp b/Sim/GaussTracker/src/GetTrackerHitsAlg.cpp
index 4b79fd808..4f4227a05 100755
--- a/Sim/GaussTracker/src/GetTrackerHitsAlg.cpp
+++ b/Sim/GaussTracker/src/GetTrackerHitsAlg.cpp
@@ -1,23 +1,10 @@
-// $Id: GetTrackerHitsAlg.cpp,v 1.16 2009-03-26 21:52:20 robbep Exp $
-// Include files 
-
-// from Gaudi
-
-// from GiGa 
-#include "GiGa/IGiGaSvc.h"
-#include "GiGa/GiGaHitsByName.h"
-
-// from GiGaCnv
-#include "GiGaCnv/IGiGaKineCnvSvc.h" 
-#include "GiGaCnv/IGiGaCnvSvcLocation.h"
-#include "GiGaCnv/GiGaKineRefTable.h"
-
 // from Geant4
 #include "Geant4/G4HCofThisEvent.hh"
+#include "Geant4/G4SDManager.hh"
 
 // from LHCb
 #include "Event/MCExtendedHit.h"
-#include "DetDesc/DetectorElement.h"
+//#include "DetDesc/DetectorElement.h"
 
 // local
 #include "GetTrackerHitsAlg.h"
@@ -27,204 +14,135 @@
 // Implementation file for class : GetTrackerHitsAlg
 //
 // 2005-10-02 : Gloria CORTI
+// 2018-04-05 : Dominik Muller
 //-----------------------------------------------------------------------------
 
 // Declaration of the Algorithm Factory
-DECLARE_COMPONENT( GetTrackerHitsAlg )
-
-
-//=============================================================================
-// Standard constructor, initializes variables
-//=============================================================================
-GetTrackerHitsAlg::GetTrackerHitsAlg( const std::string& name,
-                                                ISvcLocator* pSvcLocator)
-  : GaudiAlgorithm ( name , pSvcLocator )
-  , m_gigaSvc      ( 0 )
-  , m_gigaKineCnvSvc ( 0 )
-{
-  declareProperty( "GiGaService",    m_gigaSvcName  = "GiGa",
-                   "The service handling the intreface to Geant4" );
-  declareProperty( "KineCnvService", m_kineSvcName  = IGiGaCnvSvcLocation::Kine,
-                   "The service keeping the relation between Geant4 kinematic and MCTruth" );
-  declareProperty( "ExtendedInfo",   m_extendedInfo = false, 
-                   "Flag to control filling of MCExtendedHits instead of MCHits (def = false)" );
-  declareProperty( "MCHitsLocation", m_hitsLocation = "",
-                   "Location in TES where to put resulting MCHits" );
-  declareProperty( "CollectionName", m_colName = "",
-                   "Name of Geant4 collection where to retrieve hits" );
-  declareProperty( "Detectors",      m_detName,
-                   "List of detector paths in TDS for which to retrieve the hits (most of the time one" );
-  declareProperty( "MCParticles",    m_mcParticles = LHCb::MCParticleLocation::Default,
-		   "Location of MCParticles" ) ;
-}
-
-//=============================================================================
-// Destructor
-//=============================================================================
-GetTrackerHitsAlg::~GetTrackerHitsAlg() {}
+DECLARE_COMPONENT(GetTrackerHitsAlg)
 
 //=============================================================================
 // Initialization
 //=============================================================================
 StatusCode GetTrackerHitsAlg::initialize() {
-
-  StatusCode sc = GaudiAlgorithm::initialize(); // must be executed first
-  if ( sc.isFailure() ) return sc;  // error printed already by GaudiAlgorithm
+  StatusCode sc = GaudiAlgorithm::initialize();  // must be executed first
+  if (sc.isFailure()) return sc;  // error printed already by GaudiAlgorithm
 
   debug() << "==> Initialize" << endmsg;
 
-  if( "" == m_hitsLocation ) {
-    fatal() << "Property MCHitsLocation need to be set! " << endmsg;
-    return StatusCode::FAILURE;
-  }
-  if( "" == m_colName ) {
+  if ("" == m_colName) {
     fatal() << "Property CollectionName need to be set! " << endmsg;
     return StatusCode::FAILURE;
   }
-  if( !m_detName.size() ) {
-    warning() << "Property Detector need to be set! " << endmsg;
-  }
 
+  auto& hit_outputhandle = std::get<0>(m_outputs);
   std::vector<std::string>::iterator itDet;
-  debug() << " The hits " << m_hitsLocation  << endmsg;
-  debug() << " will be taken from G4 collection " << m_colName  << endmsg;
-  debug() << " for detector(s) ";
-  for( itDet=m_detName.begin(); itDet!=m_detName.end(); itDet++ ){
-    debug() << *itDet << " ";
-  }
+  debug() << " The hits " << hit_outputhandle.objKey() << endmsg;
+  debug() << " will be taken from G4 collection " << m_colName << endmsg;
   debug() << endmsg;
-  
-  m_gigaSvc = svc<IGiGaSvc>( m_gigaSvcName ); // GiGa has to already exist!
-
-  // get kineCnv service that hold the MCParticle/Geant4 table list
-  m_gigaKineCnvSvc = svc<IGiGaKineCnvSvc>( m_kineSvcName );
 
-  // get the detector element
-  for( itDet=m_detName.begin(); itDet!=m_detName.end(); itDet++ ){
-    m_detector.push_back( getDet<DetectorElement>(*itDet) );
-  }
-  
   return StatusCode::SUCCESS;
 }
 
 //=============================================================================
 // Main execution
 //=============================================================================
-StatusCode GetTrackerHitsAlg::execute() {
-
+LHCb::MCHits GetTrackerHitsAlg::operator()(
+    const G4EventProxies& eventproxies,
+    const LinkedParticleMCParticleLinks& mcp_links) const {
   debug() << "==> Execute" << endmsg;
 
-  if( 0 == gigaSvc() ) {
-    return Error( " execute(): IGiGaSvc* points to NULL" );
-  }
-
   // Create the MCHits and put them in the TES
-  // Cannot use 
+  // Cannot use
   // MCHits* hits = getOrCreate<MCHits,MCHits>( m_hitsLocation );
   // because triggers convertion
-  LHCb::MCHits* hits = new LHCb::MCHits();
-  put( hits, m_hitsLocation );
-  
-  // Get the G4 necessary hit collection from GiGa
-  GiGaHitsByName col( m_colName );
-  *gigaSvc() >> col;   // also StatusCode sc = retrieveHitCollection( col );
-                       // in TRY/CATCH&PRINT
-  
-  if( 0 == col.hits() ) { 
-    return Warning( "The hit collection='" + m_colName + "' is not found!",
-                    StatusCode::SUCCESS ); 
-  }
-  
-  const TrackerHitsCollection* hitCollection = trackerHits( col.hits() );
-  if( 0 == hitCollection ) { 
-    return Error( "Wrong Collection type" );
-  }
-  
-  // The MCParticles should have already been filled
-  if( !( exist<LHCb::MCParticles>( m_mcParticles ) ) ) {
-    return Error( "MCParticles do not exist at'" 
-                  + m_mcParticles +"'" );
-  }
-  
-  // reserve elements on output container
-  int numOfHits = hitCollection->entries();
-  if( numOfHits > 0 ) {
-    hits->reserve( numOfHits );
-  }
-
-  // tranform G4Hit into MCHit and insert it in container
-  for( int iG4Hit = 0; iG4Hit < numOfHits; ++iG4Hit ) { 
-    
-    // create hit or extended hit depending on choice
-    if ( m_extendedInfo ) {
-      LHCb::MCExtendedHit* newHit = new LHCb::MCExtendedHit();
-      fillHit( (*hitCollection)[iG4Hit], newHit );
-      Gaudi::XYZVector mom( (*hitCollection)[iG4Hit]->GetMomentum() );
-      newHit->setMomentum( mom );
-      hits->add( newHit );
+  LHCb::MCHits hits;
+
+  for (auto& ep : eventproxies) {
+    auto g4event = ep.event();
+    int HCID = G4SDManager::GetSDMpointer()->GetCollectionID(m_colName.value());
+    auto col = g4event->GetHCofThisEvent()->GetHC(HCID);
+    if (0 == col) {
+      warning() << "The hit collection='" + m_colName + "' is not found!"
+                << endmsg;
+      continue;
     }
-    else {
-      LHCb::MCHit* newHit = new LHCb::MCHit();
-      fillHit( (*hitCollection)[iG4Hit], newHit );
-      hits->add( newHit );
+    auto hitCollection = dynamic_cast<TrackerHitsCollection*>(col);
+    if (0 == hitCollection) {
+      error() << "Wrong Collection type" << endmsg;
+      continue;
+    }
+    // reserve elements on output container
+    int numOfHits = hitCollection->entries();
+    // tranform G4Hit into MCHit and insert it in container
+    for (int iG4Hit = 0; iG4Hit < numOfHits; ++iG4Hit) {
+      // create hit or extended hit depending on choice
+      if (m_extendedInfo) {
+        LHCb::MCExtendedHit* newHit = new LHCb::MCExtendedHit();
+        fillHit((*hitCollection)[iG4Hit], newHit, ep.truth(), mcp_links);
+        Gaudi::XYZVector mom((*hitCollection)[iG4Hit]->GetMomentum());
+        newHit->setMomentum(mom);
+        hits.add(newHit);
+      } else {
+        LHCb::MCHit* newHit = new LHCb::MCHit();
+        fillHit((*hitCollection)[iG4Hit], newHit, ep.truth(), mcp_links);
+        hits.add(newHit);
+      }
     }
   }
-  
-  // Check that all hits have been transformed
-  if( (size_t) hits->size() != (size_t) hitCollection->entries() ) {
-    return Error("MCHits and G4TrackerHitsCollection have different sizes!");
-  }  
 
-  return StatusCode::SUCCESS;
-  
+  return hits;
 }
 
 //=============================================================================
 //  Finalize
 //=============================================================================
 StatusCode GetTrackerHitsAlg::finalize() {
-
   debug() << "==> Finalize" << endmsg;
 
   return GaudiAlgorithm::finalize();  // must be called after all other actions
 }
 
 //=============================================================================
-//  Fill MCHit 
+//  Fill MCHit
 //=============================================================================
 
-void GetTrackerHitsAlg::fillHit( TrackerHit* g4Hit, LHCb::MCHit* mcHit ) {
-  
+void GetTrackerHitsAlg::fillHit(
+    TrackerHit* g4Hit, LHCb::MCHit* mcHit, const Gaussino::MCTruth* mctruth,
+    const LinkedParticleMCParticleLinks& mcplinks) const {
   // fill data members
-  Gaudi::XYZPoint entry( g4Hit->GetEntryPos() );
-  Gaudi::XYZPoint exit( g4Hit->GetExitPos() );
-  mcHit->setEntry( entry );
-  mcHit->setDisplacement( exit-entry );
-  mcHit->setEnergy( g4Hit->GetEdep() );
-  mcHit->setTime( g4Hit->GetTimeOfFlight() );
-  mcHit->setP( g4Hit->GetMomentum().mag() );
- 
+  Gaudi::XYZPoint entry(g4Hit->GetEntryPos());
+  Gaudi::XYZPoint exit(g4Hit->GetExitPos());
+  mcHit->setEntry(entry);
+  mcHit->setDisplacement(exit - entry);
+  mcHit->setEnergy(g4Hit->GetEdep());
+  mcHit->setTime(g4Hit->GetTimeOfFlight());
+  mcHit->setP(g4Hit->GetMomentum().mag());
+
   // get sensitive detector identifier using mid point
+  // FIXME: This needs to be added once geometry has been worked in
   int detID = -1;
-  std::vector<const DetectorElement*>::iterator itDet;
-  for( itDet=m_detector.begin(); itDet!=m_detector.end(); itDet++){
-    if( (*itDet)->isInside(mcHit->midPoint()) ){
-      detID = (*itDet)->sensitiveVolumeID( mcHit->midPoint() );
-      break;
-    }
-  }
+  // std::vector<const DetectorElement*>::iterator itDet;
+  // for (itDet = m_detector.begin(); itDet != m_detector.end(); itDet++) {
+  // if ((*itDet)->isInside(mcHit->midPoint())) {
+  // detID = (*itDet)->sensitiveVolumeID(mcHit->midPoint());
+  // break;
+  //}
+  //}
   mcHit->setSensDetID(detID);
 
   // fill reference to MCParticle using the Geant4->MCParticle table
-  GiGaKineRefTable& table = kineSvc()->table();
   int trackID = g4Hit->GetTrackID();
-  if( table[trackID].particle() ) {
-    mcHit->setMCParticle( table[trackID].particle() );
+  if (auto lp = mctruth->GetParticleFromTrackID(trackID); lp) {
+    if (auto it = mcplinks.find(lp); it != std::end(mcplinks)) {
+      mcHit->setMCParticle(it->second);
+    } else {
+      warning()
+          << "No pointer to MCParticle for MCHit associated to G4 trackID: "
+          << trackID << endmsg;
+    }
   } else {
-    warning() << "No pointer to MCParticle for MCHit associated to G4 trackID: "
-              << trackID << endmsg;
+    warning()
+        << "No LinkedParticle found. Something went seriously wrong. trackID: "
+        << trackID << endmsg;
   }
-  
 }
-
-//=============================================================================
diff --git a/Sim/GaussTracker/src/GetTrackerHitsAlg.h b/Sim/GaussTracker/src/GetTrackerHitsAlg.h
index 40bbf0bc7..180d85bb6 100755
--- a/Sim/GaussTracker/src/GetTrackerHitsAlg.h
+++ b/Sim/GaussTracker/src/GetTrackerHitsAlg.h
@@ -1,20 +1,22 @@
-// $Id: GetTrackerHitsAlg.h,v 1.6 2009-03-26 21:52:20 robbep Exp $
-#ifndef GETTRACKERHITSALG_H
-#define GETTRACKERHITSALG_H 1
+#pragma once
+#include <vector>
 
 // Include files
 // from Gaudi
 #include "GaudiAlg/GaudiAlgorithm.h"
-
+#include "GaudiAlg/Transformer.h"
+#include "GaudiKernel/DataHandle.h"
+#include "GiGaMTCore/G4EventProxy.h"
+#include "GiGaMTCore/Truth/MCTruthConverter.h"
+#include "MCTruthToEDM/LinkedParticleMCParticleLink.h"
+
+#include "Defaults/Locations.h"
+#include "Event/MCHit.h"
 // Forward declarations
 class IGiGaSvc;
 class IGiGaKineCnvSvc;
 class DetectorElement;
 class TrackerHit;
-namespace LHCb {
-  class MCHit;
-}
-
 
 /** @class GetTrackerHitsAlg GetTrackerHitsAlg.h
  *
@@ -22,52 +24,50 @@ namespace LHCb {
  *  @author Gloria CORTI
  *  @date   2005-10-02
  */
-class GetTrackerHitsAlg : public GaudiAlgorithm {
-public:
+class GetTrackerHitsAlg
+    : public Gaudi::Functional::Transformer<LHCb::MCHits(
+          const G4EventProxies&, const LinkedParticleMCParticleLinks&)> {
+  public:
   /// Standard constructor
-  GetTrackerHitsAlg( const std::string& name, ISvcLocator* pSvcLocator );
-
-  virtual ~GetTrackerHitsAlg( ); ///< Destructor
-
-  StatusCode initialize() override;    ///< Algorithm initialization
-  StatusCode execute   () override;    ///< Algorithm execution
-  StatusCode finalize  () override;    ///< Algorithm finalization
-
-protected:
-
-  /** accessor to GiGa Service
-   *  @return pointer to GiGa Service
-   */
-  IGiGaSvc* gigaSvc() const {
-    return m_gigaSvc;
-  }
-
-  /** accessor to kinematics  conversion service
-   *  @return pointer to kinematics conversion service
-   */
-  IGiGaKineCnvSvc*      kineSvc   () const {
-    return m_gigaKineCnvSvc;
-  }
-
-  void fillHit( TrackerHit* g4Hit, LHCb::MCHit* mcHit );
-
-
-private:
-
-  std::string        m_gigaSvcName;      ///< Name of GiGa Service
-  std::string        m_kineSvcName;      ///< Name of GiGaCnv Service
-  IGiGaSvc*          m_gigaSvc;          ///< Pointer to GiGa Service
-  IGiGaKineCnvSvc*   m_gigaKineCnvSvc;   ///< Pointer to GiGaKine Service
-
-  bool               m_extendedInfo;     ///< Flag to fill MCHit or MCExtendedHit
-
-  std::string        m_hitsLocation;     ///< Name of TES path for MCHits
-  std::string        m_colName;          ///< Name of G4 hits collection
-
-  std::vector<std::string> m_detName;             ///< Detector PATHs
-  std::vector<const DetectorElement*> m_detector; ///< Pointers to DetectorEl
-
-  std::string        m_mcParticles;       ///< Name of MCParticles location
-
+  GetTrackerHitsAlg(const std::string& name, ISvcLocator* pSvcLocator)
+      : Transformer(
+            name, pSvcLocator,
+            {{KeyValue{"Input", ""},
+              KeyValue{
+                  "LinkedParticleMCParticleLinks",
+                  Gaussino::LinkedParticleMCParticleLinksLocation::Default}}},
+            KeyValue{"MCHitsLocation", ""}) {}
+  virtual ~GetTrackerHitsAlg() = default;
+
+  virtual LHCb::MCHits operator()(const G4EventProxies&, const LinkedParticleMCParticleLinks&) const override;
+
+  virtual StatusCode initialize() override;  ///< Algorithm initialization
+  virtual StatusCode finalize() override;    ///< Algorithm finalization
+
+  // declareProperty( "GiGaService",    m_gigaSvcName  = "GiGa",
+  //"The service handling the intreface to Geant4" );
+  // declareProperty( "KineCnvService", m_kineSvcName  =
+  // IGiGaCnvSvcLocation::Kine, "The service keeping the relation between Geant4
+  // kinematic and MCTruth" );
+  Gaudi::Property<bool> m_extendedInfo{this, "ExtendedInfo", false,
+                                       "Flag to control filling of "
+                                       "MCExtendedHits instead of MCHits (def "
+                                       "= false)"};
+  Gaudi::Property<std::string> m_colName{
+      this, "CollectionName", "",
+      "Name of Geant4 collection where to retrieve hits"};
+  Gaudi::Property<std::vector<std::string>> m_detName{
+      this,
+      "Detectors",
+      {},
+      "List of detector paths in TDS for which to retrieve the hits (most of "
+      "the time one"};
+  // declareProperty( "MCParticles",    m_mcParticles =
+  // LHCb::MCParticleLocation::Default, "Location of MCParticles" ) ;
+
+  protected:
+  void fillHit(TrackerHit* g4Hit, LHCb::MCHit* mcHit,const Gaussino::MCTruth* mctruth, const LinkedParticleMCParticleLinks& mcplinks) const;
+
+  private:
+  std::string m_mcParticles;  ///< Name of MCParticles location
 };
-#endif // GETTRACKERHITSALG_H
diff --git a/Sim/GaussTracker/src/GiGaSensDetTracker.cpp b/Sim/GaussTracker/src/GiGaSensDetTracker.cpp
index 9d3a2a1dc..a0b8c5378 100755
--- a/Sim/GaussTracker/src/GiGaSensDetTracker.cpp
+++ b/Sim/GaussTracker/src/GiGaSensDetTracker.cpp
@@ -26,56 +26,30 @@
 // 2006-07-14 : Gloria CORTI (clean up)
 //-----------------------------------------------------------------------------
 
-// Declaration of the Factory
-DECLARE_COMPONENT( GiGaSensDetTracker )
 
-
-//=============================================================================
-// Standard constructor, initializes variables
-//=============================================================================
-GiGaSensDetTracker::GiGaSensDetTracker( const std::string& type,
-                                        const std::string& name,
-                                        const IInterface*  parent ) 
+GiGaSensDetTracker::GiGaSensDetTracker( const std::string& name)
   : G4VSensitiveDetector( name  )
-  , GiGaSensDetBase     ( type , name , parent ) 
 {  
 
   collectionName.insert( "Hits" );
-  declareProperty( "RequireEDep", m_requireEDep = true,
-                   "Flag to control storing of hits if track deposited energy or not" );
 
 }
 
-//=============================================================================
-// Destructor
-//=============================================================================
-GiGaSensDetTracker::~GiGaSensDetTracker(){}
-
-
-//=============================================================================
-// Initialize method from G4 (Called at the begin of each G4event)
-// see G4VSensitiveDetector 
-// ============================================================================
 void GiGaSensDetTracker::Initialize(G4HCofThisEvent*HCE) {
   
   m_trackerCol = new TrackerHitsCollection( SensitiveDetectorName,
                                             collectionName[0] );
+
+  std::string hit_location = SensitiveDetectorName + "/" + collectionName[0];
   
+  debug("Registering location at "+hit_location);
   int HCID = G4SDManager::GetSDMpointer()
     ->GetCollectionID( SensitiveDetectorName + "/" + collectionName[0] );
 
   HCE->AddHitsCollection(HCID, m_trackerCol);
 
-  Print (" Initialize(): CollectionName='" + m_trackerCol->GetName   () +
-         "' for SensDet='"                 + m_trackerCol->GetSDname () + 
-         "'" , StatusCode::SUCCESS , MSG::VERBOSE                       ).ignore() ;
-  
 }
 
-
-//=============================================================================
-// process the hit (G4 method)
-//=============================================================================
 bool GiGaSensDetTracker::ProcessHits( G4Step* step , 
                                       G4TouchableHistory* /* history */ ) 
 {
@@ -94,7 +68,8 @@ bool GiGaSensDetTracker::ProcessHits( G4Step* step ,
   
   if( step->GetStepLength() != 0.0 ) {     // step must be finite
 
-    Print("Filling a hit", StatusCode::SUCCESS, MSG::VERBOSE).ignore();
+    
+    debug("Filling a hit");
 
     G4ThreeVector prepos  = step->GetPreStepPoint()->GetPosition();
     double timeof = step->GetPreStepPoint()->GetGlobalTime();
@@ -114,10 +89,9 @@ bool GiGaSensDetTracker::ProcessHits( G4Step* step ,
     int trid = track->GetTrackID();
     newHit->SetTrackID( trid );
 
-    G4VUserTrackInformation* ui = track->GetUserInformation(); 
-    GaussTrackInformation* gi = (GaussTrackInformation*) ui;
+    auto gi = GaussinoTrackInformation::Get(track);
     gi->setCreatedHit(true);
-    gi->setToBeStored(true);
+    gi->storeTruth();
     gi->addHit(newHit);
 
     // add hit to collection
@@ -129,7 +103,3 @@ bool GiGaSensDetTracker::ProcessHits( G4Step* step ,
   return false;
   
 }
-
-//=============================================================================
-
-
diff --git a/Sim/GaussTracker/src/GiGaSensDetTracker.h b/Sim/GaussTracker/src/GiGaSensDetTracker.h
index d2806f7d5..7613de9b7 100755
--- a/Sim/GaussTracker/src/GiGaSensDetTracker.h
+++ b/Sim/GaussTracker/src/GiGaSensDetTracker.h
@@ -1,10 +1,9 @@
-// $Id: GiGaSensDetTracker.h,v 1.6 2008-05-07 07:05:44 gcorti Exp $
-#ifndef GIGASENSDETTRACKER_H
-#define GIGASENSDETTRACKER_H 1
+#pragma once
 
 // Include files
-#include "GiGa/GiGaSensDetBase.h"
-#include "GaussTools/GaussTrackInformation.h"
+#include "GiGaMTCore/Truth/GaussinoTrackInformation.h"
+#include "GiGaMTCore/IGiGaMessage.h"
+#include "Geant4/G4VSensitiveDetector.hh"
 #include "TrackerHit.h"
 
 // Forward declarations
@@ -12,7 +11,6 @@ class G4Step;
 class G4HCofThisEvent;
 class G4TouchableHistory;
 
-
 /** @class GiGaSensDetTracker GiGaSensDetTracker.h
  *
  *  Fill information in TrackerHits to be later stored
@@ -21,28 +19,19 @@ class G4TouchableHistory;
  *
  *  @author Witek POKORSKI
  *  @author Gloria CORTI
- *  @date   2006-07-17 (last revision)
+ *  @author Dominik Muller
+ *  @date   2018-12-18 (last revision)
  */
-class GiGaSensDetTracker: virtual public GiGaSensDetBase
-{
-
-public:
-
-  /// Standard constructor
-  GiGaSensDetTracker( const std::string& type   ,
-                      const std::string& name   ,
-                      const IInterface*  parent ) ;
-
-  /// destructor (virtual and protected)
-  virtual ~GiGaSensDetTracker();
-
+class GiGaSensDetTracker : public G4VSensitiveDetector, public virtual GiGaMessage {
+  public:
+  GiGaSensDetTracker(const std::string& name);
 
   /** Initialize method (Geant4).
    *  Called at the beginning of each event
    *  @see G4VSensitiveDetector
    *  @param HCE pointer to hit collection of current event
    */
-  void Initialize( G4HCofThisEvent* HCE ) override;
+  void Initialize(G4HCofThisEvent* HCE) override;
 
   /** Process a hit (Geant4).
    *  The method is invoked by G4 for each step in the
@@ -58,24 +47,20 @@ public:
    *  @param step     pointer to current Geant4 step
    *  @param history  pointer to touchable history
    */
-  bool ProcessHits( G4Step* step,
-                    G4TouchableHistory* history ) override;
+  bool ProcessHits(G4Step* step, G4TouchableHistory* history) override;
 
-private:
+  // Flag to control storing of hits if track deposited energy or not
+  void SetRequireEDep(bool val = true) { m_requireEDep = val; }
 
-  GiGaSensDetTracker(); ///< no default constructor
-  GiGaSensDetTracker( const GiGaSensDetTracker& ); ///< no copy constructor
-  GiGaSensDetTracker& operator=( const GiGaSensDetTracker& ) ; ///< no =
+  private:
+  GiGaSensDetTracker();                           ///< no default constructor
+  GiGaSensDetTracker(const GiGaSensDetTracker&);  ///< no copy constructor
+  GiGaSensDetTracker& operator=(const GiGaSensDetTracker&);  ///< no =
 
   /// Pointer to G4 collection for this sensitive detector
   TrackerHitsCollection* m_trackerCol;
 
   /// Flag to store hits if dE/dx occured, this is to enable hits when
   /// switching it off for special studies (like with geantinos)
-  bool m_requireEDep;
-
+  bool m_requireEDep = true;
 };
-
-
-#endif  // GIGASENSDETTRACKER_H
-
diff --git a/Sim/GaussTracker/src/GiGaSensDetTrackerFAC.cpp b/Sim/GaussTracker/src/GiGaSensDetTrackerFAC.cpp
new file mode 100644
index 000000000..66b2bbed5
--- /dev/null
+++ b/Sim/GaussTracker/src/GiGaSensDetTrackerFAC.cpp
@@ -0,0 +1,25 @@
+// Include files
+
+#include "GiGaMTFactories/GiGaMTG4SensDetFactory.h"
+
+// Geant4 physics lists
+#include "GiGaSensDetTracker.h"
+
+typedef GiGaMTG4SensDetFactory<GiGaSensDetTracker> TrackerBaseFAC;
+
+class GiGaSensDetTrackerFAC: public TrackerBaseFAC
+{
+  Gaudi::Property<bool> m_requireEDep{this, "RequireEDep", true,
+                                      "Hits must have non-zero Energy deposition"};
+
+public:
+  using TrackerBaseFAC::TrackerBaseFAC;
+  GiGaSensDetTracker* construct() const override
+  {
+    auto tmp = TrackerBaseFAC::construct();
+    tmp->SetRequireEDep(m_requireEDep);
+    return tmp;
+  }
+};
+
+DECLARE_COMPONENT_WITH_ID( GiGaSensDetTrackerFAC, "GiGaSensDetTracker" )
diff --git a/Sim/GaussTracker/src/TrackerHit.h b/Sim/GaussTracker/src/TrackerHit.h
index 509dcf3f7..1945186c9 100755
--- a/Sim/GaussTracker/src/TrackerHit.h
+++ b/Sim/GaussTracker/src/TrackerHit.h
@@ -16,13 +16,19 @@
 #include "Geant4/G4ThreeVector.hh"
 #include "GiGaMTCore/GaussHitBase.h"
 
-class TrackerHit : public GaussHitBase {
+class TrackerHit : public Gaussino::HitBase {
   public:
   TrackerHit() = default;
   virtual ~TrackerHit() = default;
-  TrackerHit(const TrackerHit& right);
+  TrackerHit(const TrackerHit& right) : Gaussino::HitBase(right) {
+    m_edep = right.m_edep;
+    m_entryPos = right.m_entryPos;
+    m_exitPos = right.m_exitPos;
+    m_timeOfFlight = right.m_timeOfFlight;
+    m_momentum = right.m_momentum;
+  }
   inline const TrackerHit& operator=(const TrackerHit& right);
-  int operator==(const TrackerHit& ) const {return 0;};
+  int operator==(const TrackerHit&) const { return 0; };
 
   inline void* operator new(size_t);
   inline void operator delete(void* aHit);
@@ -39,26 +45,24 @@ class TrackerHit : public GaussHitBase {
   G4ThreeVector m_momentum;
 
   public:
-  inline void SetEdep(G4double de);
-  inline G4double GetEdep();
+  inline void SetEdep(G4double de) { m_edep = de; }
+  inline G4double GetEdep() { return m_edep; }
 
-  inline void SetEntryPos(G4ThreeVector xyz);
-  inline G4ThreeVector GetEntryPos();
+  inline void SetEntryPos(G4ThreeVector xyz) { m_entryPos = xyz; }
+  inline G4ThreeVector GetEntryPos() { return m_entryPos; }
 
-  inline void SetExitPos(G4ThreeVector xyz);
-  inline G4ThreeVector GetExitPos();
+  inline void SetExitPos(G4ThreeVector xyz) { m_exitPos = xyz; }
+  inline G4ThreeVector GetExitPos() { return m_exitPos; }
 
-  inline void SetTimeOfFlight(G4double tof);
-  inline G4double GetTimeOfFlight();
+  inline void SetTimeOfFlight(G4double tof) { m_timeOfFlight = tof; }
+  inline G4double GetTimeOfFlight() { return m_timeOfFlight; }
 
-  inline void SetMomentum(G4ThreeVector p);
-  inline G4ThreeVector GetMomentum();
+  inline void SetMomentum(G4ThreeVector p) { m_momentum = p; }
+  inline G4ThreeVector GetMomentum() { return m_momentum; }
 };
 
 typedef G4THitsCollection<TrackerHit> TrackerHitsCollection;
 
-extern G4Allocator<TrackerHit> TrackerHitAllocator;
-
 inline G4Allocator<TrackerHit>* TrackerHit::TrackerHitAllocator() {
   thread_local auto hitAllocator = G4Allocator<TrackerHit>{};
   return &hitAllocator;
@@ -71,5 +75,3 @@ inline void* TrackerHit::operator new(size_t) {
 inline void TrackerHit::operator delete(void* aHit) {
   TrackerHitAllocator()->FreeSingle((TrackerHit*)aHit);
 }
-
-#include "TrackerHit.icc"
diff --git a/Sim/GaussTracker/src/TrackerHit.icc b/Sim/GaussTracker/src/TrackerHit.icc
index 4355faec2..a46d99a1b 100644
--- a/Sim/GaussTracker/src/TrackerHit.icc
+++ b/Sim/GaussTracker/src/TrackerHit.icc
@@ -2,7 +2,7 @@
 // Constructor
 //=============================================================================
 TrackerHit::TrackerHit(const TrackerHit &right)
-  : GaussHitBase(right)
+  : Gaussino::HitBase(right)
 {
   m_edep = right.m_edep;
   m_entryPos = right.m_entryPos;
-- 
GitLab


From f55ac84eff6c02e1450859c5e57f0fd3bae134fa Mon Sep 17 00:00:00 2001
From: Dominik Muller <dominik.muller@cern.ch>
Date: Sun, 19 May 2019 15:51:56 +0200
Subject: [PATCH 04/90] GaussPhysics for Gaussino MT

---
 Sim/Gauss/python/Gauss/Physics.py             | 182 ++++++++
 Sim/Gauss/python/Gauss/__init__.py            |   5 +
 Sim/GaussPhysics/CMakeLists.txt               |  13 +-
 Sim/GaussPhysics/src/G4Higgses.cpp            |   2 +-
 .../src/GaussPhysics_factories.cpp            | 400 ++----------------
 Sim/GaussPhysics/src/GiGaHiggsParticles.cpp   | 149 +++----
 .../src/GiGaPhysUnknownParticles.cpp          | 139 +++---
 .../src/GiGaPhysUnknownParticles.h            |  47 +-
 8 files changed, 354 insertions(+), 583 deletions(-)
 create mode 100644 Sim/Gauss/python/Gauss/Physics.py

diff --git a/Sim/Gauss/python/Gauss/Physics.py b/Sim/Gauss/python/Gauss/Physics.py
new file mode 100644
index 000000000..a84eaeeec
--- /dev/null
+++ b/Sim/Gauss/python/Gauss/Physics.py
@@ -0,0 +1,182 @@
+from Gaudi.Configuration import log
+from Configurables import LHCbConfigurableUser
+from GaudiKernel import SystemOfUnits
+
+
+def gef(name):
+    import Configurables
+    return getattr(Configurables, "GiGaMT_%s" % name)
+
+
+def addConstructor(pl, template, name):
+    pl.addTool(gef(template), name=name)
+    pl.PhysicsConstructors.append(getattr(pl, name))
+
+
+class G4Physics(LHCbConfigurableUser):
+    # Steering options
+    __slots__ = {
+        "Em": 'NoCuts',
+        "Hadron": 'FTFP_BERT',
+        "GeneralPhys": True,
+        "LHCbPhys": False,
+        "Other": '',
+        "DeltaRays": True,
+        "RichUpgradeConfig": False}
+
+    _propertyDocDct = {
+        'Em': """Electromagnetic physics used. Choices:
+                 ['Std','Opt1,'Opt2','Opt3','NoCuts','LHCb', 'LHCbNoCuts',
+                 'LHCbOldForE', 'LHCbNoCutsOldForE', 'LHCbTest',
+                 'LHCbTestNoCut' ]""",
+        'GeneralPhys': """Flag to include general physics (e.g. decays).
+                          Choices: [True,False]""",
+        'Hadron':  """Hadronic physics used.
+                      Choices: ['QGSP_BERT','QGSP_BERT_HP','QGSP_FTFP_BERT',
+                                'FTFP_BERT','FTFP_BERT_HP']""",
+        'LHCbPhys': """LHCb specific physics (mostly Cherenkov).
+                       Choices: [True,False]""",
+        'Other': """Anything else. Currently not used ['']""",
+        "DeltaRays": """Simulation of delta rays enabled (default True)""",
+        "RichUpgradeConfig": """Use RICH upgrade (default True)"""
+    }
+
+    def __apply_configuration__(self):
+        from Configurables import GiGaMT
+        giga = GiGaMT()
+
+        from Configurables import GiGaMTModularPhysListFAC
+        gmpl = giga.addTool(GiGaMTModularPhysListFAC("ModularPL"),
+                            name="ModularPL")
+        giga.PhysicsListFactory = "GiGaMTModularPhysListFAC/ModularPL"
+        gmpl = giga.ModularPL
+        gmpl.PhysicsConstructors = []
+
+        # set production cuts
+        ecut = 5.0 * SystemOfUnits.mm
+        if not self.getProp("DeltaRays"):
+            ecut = 10000.0 * SystemOfUnits.m
+        print 'Ecut value =', ecut
+        gmpl.CutForElectron = ecut
+        gmpl.CutForPositron = 5.0 * SystemOfUnits.mm
+        gmpl.CutForGamma = 5.0 * SystemOfUnits.mm
+
+        # set up the physics list
+
+        # --- EM physics:
+        self.AddEMPhys(gmpl)
+
+        # --- general  physics (common to all PL):
+        self.AddGenPhysics(gmpl)
+
+        # --- Hadron physics:
+        self.AddHadronPhysics(gmpl)
+
+        # --- LHCb specific physics:
+        self.AddLHCbPhysics(gmpl)
+
+        # --- Other physics
+        self.AddOtherPhysics(gmpl)
+
+    def AddEMPhys(self, pl):
+        emPhys = self.getProp('Em')
+        _all = {
+            "Opt1": ("G4EmStandardPhysics_option1", "EmOpt1Physics"),
+            "Opt2": ("G4EmStandardPhysics_option2", "EmOpt2Physics"),
+            "Opt3": ("G4EmStandardPhysics_option3", "EmOpt3Physics"),
+            "Std": ("G4EmStandardPhysics", "EmPhysics"),
+            "NoCuts": ("G4EmStandardPhysics_option1NoApplyCuts",
+                       "EmOpt1NoCutsPhysics")
+        }
+
+        if emPhys in _all:
+            addConstructor(pl, *_all[emPhys])
+            return True
+
+        if 'LHCb' not in emPhys:
+            return False
+
+        if 'Test' in emPhys:
+            addConstructor(pl, "G4EmStandardPhysics_LHCbTest",
+                               "EmOpt1LHCbPhysics")
+        else:
+            addConstructor(pl, "G4EmStandardPhysics_option1LHCb",
+                               "EmOpt1LHCbPhysics")
+        # overwrite cuts depending on choice of list
+        if 'NoCuts' in emPhys:
+            pl.EmOpt1LHCbPhysics.ApplyCuts = False
+        if 'OldForE' in emPhys:
+            pl.EmOpt1LHCbPhysics.NewModelForE = False
+
+        return True
+        raise RuntimeError("Unknown Em PhysicsList chosen ('%s')" % emPhys)
+
+    def AddGenPhysics(self, pl):
+        genPhys = self.getProp('GeneralPhys')
+        # Decays
+        if genPhys:
+            addConstructor(pl, "G4DecayPhysics", "DecayPhysics")
+            addConstructor(pl, "G4EmExtraPhysics", "EmExtraPhysics")
+            addConstructor(pl, "G4IonPhysics", "IonPhysics")
+        else:
+            log.warning("The general physics (Decays,"
+                        "hadron elastic, ion ...) is disabled")
+
+    def AddHadronPhysics(self, pl):
+        hadronPhys = self.getProp('Hadron')
+        _all = {
+            "QGSP_BERT": [
+                ("G4HadronElasticPhysics", "ElasticPhysics"),
+                ("G4HadronPhysicsQGSP_BERT", "QGSP_BERTPhysics"),
+                ("G4StoppingPhysics", "StoppingPhysics"),
+                ("G4NeutronTrackingCut", "NeutronTrkCut")],
+            "QGSP_BERT_HP": [
+                ("G4HadronElasticPhysicsHP", "ElasticPhysicsHP"),
+                ("G4HadronPhysicsQGSP_BERT_HP", "QGSP_BERT_HPPhysics"),
+                ("G4StoppingPhysics", "StoppingPhysics")],
+            "QGSP_FTFP_BERT": [
+                ("G4HadronElasticPhysics", "ElasticPhysics"),
+                ("G4HadronPhysicsQGSP_FTFP_BERT", "QGSP_FTFP_BERTPhysics"),
+                ("G4StoppingPhysics", "StoppingPhysics"),
+                ("G4NeutronTrackingCut", "NeutronTrkCut")],
+            "FTFP_BERT": [
+                ("G4HadronElasticPhysics", "ElasticPhysics"),
+                ("G4HadronPhysicsFTFP_BERT", "FTFP_BERTPhysics"),
+                ("G4StoppingPhysics", "StoppingPhysics"),
+                ("G4NeutronTrackingCut", "NeutronTrkCut")],
+            "FTFP_BERT_HP": [
+                ("G4HadronElasticPhysicsHP", "ElasticPhysicsHP"),
+                ("G4HadronPhysicsFTFP_BERT_HP", "FTFP_BERT_HPPhysics"),
+                ("G4StoppingPhysics", "StoppingPhysics")],
+        }
+        if hadronPhys in _all:
+            for hp in _all[hadronPhys]:
+                addConstructor(pl, *hp)
+            return True
+        else:
+            raise RuntimeError("Unknown Hadron PhysicsList "
+                               "chosen ('%s')" % hadronPhys)
+
+    def AddLHCbPhysics(self, pl):
+        lhcbPhys = self.getProp('LHCbPhys')
+        richUpgradeConfig = self.getProp('RichUpgradeConfig')
+        if lhcbPhys:
+            if richUpgradeConfig:
+                self.defineRichMaPmtPhys(pl)
+            else:
+                self.defineRichPhys(pl)
+            pl.PhysicsConstructors.append("GiGaMTPhysUnknownParticles")
+        else:
+            log.warning("The lhcb-related physics (RICH processed,"
+                        "UnknownParticles) is disabled")
+
+    def AddOtherPhysics(self, pl):
+        otherPhys = self.getProp('Other')
+
+        if otherPhys == 'Higgs':
+            log.info("Enabling physics processe for Higgs particles")
+            pl.PhysicsConstructors.append("GiGaMTHiggsParticles")
+        else:
+            if otherPhys != '':
+                raise RuntimeError("Unknown setting for OtherPhys"
+                                   "PhysicsList chosen ('%s')" % otherPhys)
diff --git a/Sim/Gauss/python/Gauss/__init__.py b/Sim/Gauss/python/Gauss/__init__.py
index c4235bac5..a17e4b6aa 100644
--- a/Sim/Gauss/python/Gauss/__init__.py
+++ b/Sim/Gauss/python/Gauss/__init__.py
@@ -1 +1,6 @@
 # entry point for the Python module
+from Physics import G4Physics
+
+__all__ = [
+    G4Physics
+]
diff --git a/Sim/GaussPhysics/CMakeLists.txt b/Sim/GaussPhysics/CMakeLists.txt
index 4eaec1d00..6dcade727 100644
--- a/Sim/GaussPhysics/CMakeLists.txt
+++ b/Sim/GaussPhysics/CMakeLists.txt
@@ -3,16 +3,21 @@
 ################################################################################
 gaudi_subdir(GaussPhysics v11r1p1)
 
-gaudi_depends_on_subdirs(Sim/GaussTools)
+gaudi_depends_on_subdirs(Sim/GiGaMTFactories
+                         Sim/GiGaMT
+                         LHCbG4PhysLists)
 
-FindG4libs(LHCblists physicslists)
+add_definitions(-DG4MULTITHREADED)
+add_definitions(-DG4USE_STD11)
 
 find_package(Boost)
 find_package(CLHEP)
 include_directories(SYSTEM ${Boost_INCLUDE_DIRS} ${CLHEP_INCLUDE_DIRS} ${Geant4_INCLUDE_DIRS})
+AddHepMC3()
+FindG4libs(digits_hits event geometry global graphics_reps materials
+           particles processes run tracking track)
 
 gaudi_add_module(GaussPhysics
                  src/*.cpp
-                 LINK_LIBRARIES GaussToolsLib
-                                ${GEANT4_LIBS})
+                 LINK_LIBRARIES GiGaMTCoreRunLib GaudiAlgLib GiGaMTLib G4LHCblists ${GEANT4_LIBS})
 
diff --git a/Sim/GaussPhysics/src/G4Higgses.cpp b/Sim/GaussPhysics/src/G4Higgses.cpp
index 5b9e49f84..46b0bca5f 100755
--- a/Sim/GaussPhysics/src/G4Higgses.cpp
+++ b/Sim/GaussPhysics/src/G4Higgses.cpp
@@ -9,7 +9,7 @@
 #include "GaudiKernel/PhysicalConstants.h"
 
 // GiGa
-#include "GiGa/GiGaException.h"
+#include "GiGaMT/GiGaException.h"
 
 // local
 #include "G4Higgses.h"
diff --git a/Sim/GaussPhysics/src/GaussPhysics_factories.cpp b/Sim/GaussPhysics/src/GaussPhysics_factories.cpp
index 5b8b793ed..541e454b3 100644
--- a/Sim/GaussPhysics/src/GaussPhysics_factories.cpp
+++ b/Sim/GaussPhysics/src/GaussPhysics_factories.cpp
@@ -1,370 +1,40 @@
-// Include files 
-
-#include "GiGa/GiGaExtPhysics.h"
-
-
-/** @file 
- *  The mandatory file for declaration of component library entries 
- *  @author Witold Pokorsky
- *  @author Vanya Belyaev
- *  @author Gloria Corti, port to Gaudi v19
- *  @date 2002-09-26, last modified 2007-01-19
- */
-
-// Geant4 physics lists
-#include "Geant4/G4DecayPhysics.hh"
-
-// EM physics
-#include "Geant4/G4EmStandardPhysics_option1.hh"
-#include "Geant4/G4EmStandardPhysics_option2.hh"
-#include "Geant4/G4EmStandardPhysics_option3.hh"
-#include "Geant4/G4EmStandardPhysics.hh"
-#include "Geant4/G4EmExtraPhysics.hh"
+#include "GiGaMTFactories/GiGaMTG4PhysicsConstrFAC.h"
 
 // LHCb Physics Lists
+#include "LHCbG4PhysLists/G4EmStandardPhysics_LHCbTest.h"
 #include "LHCbG4PhysLists/G4EmStandardPhysics_option1LHCb.h"
 #include "LHCbG4PhysLists/G4EmStandardPhysics_option1NoApplyCuts.h"
-#include "LHCbG4PhysLists/G4EmStandardPhysics_LHCbTest.h"
-
-// Ion and hadrons
-#include "Geant4/G4IonPhysics.hh"
-#include "Geant4/G4StoppingPhysics.hh"                // G4QStoppingPhysics.hh -> G4StoppingPhysics.hh in G4r10
-#include "Geant4/G4HadronElasticPhysics.hh"
-//#include "Geant4/G4HadronElasticPhysicsLHEP.hh"     // Removed from G4r10
-#include "Geant4/G4HadronElasticPhysicsHP.hh"
-#include "Geant4/G4NeutronTrackingCut.hh"
-
-// LHEP hadrons
-//#include "Geant4/HadronPhysicsLHEP.hh"              // Removed from G4r10
-
-// QGSP hadrons
-//#include "Geant4/G4HadronPhysicsQGSP.hh"            // Removed from G4r10
-#include "Geant4/G4HadronPhysicsQGSP_BERT.hh"
-#include "Geant4/G4HadronPhysicsQGSP_BERT_HP.hh"
-//#include "Geant4/G4HadronPhysicsQGSP_BERT_CHIPS.hh" // Removed from G4r10
-#include "Geant4/G4HadronPhysicsQGSP_FTFP_BERT.hh"
-
-// FTFP hadrons
-#include "Geant4/G4HadronPhysicsFTFP_BERT.hh"
-#include "Geant4/G4HadronPhysicsFTFP_BERT_HP.hh"
-
-
-// =========== Specialized extensions to GiGaExtPhysics ===========
-
-template <>
-class GiGaExtPhysicsExtender<G4EmStandardPhysics> {
-public:
-  inline void addPropertiesTo(AlgTool */*tool*/) {
-    // No specific properties
-  }
-  inline G4EmStandardPhysics *newInstance(const std::string &name, int verbosity) const {
-    return new G4EmStandardPhysics(verbosity, name);
-  }
-};
-
-template <>
-class GiGaExtPhysicsExtender<G4EmStandardPhysics_option1> {
-public:
-  inline void addPropertiesTo(AlgTool */*tool*/) {
-    // No specific properties
-  }
-  inline G4EmStandardPhysics_option1 *newInstance(const std::string &name, int verbosity) const {
-    return new G4EmStandardPhysics_option1(verbosity, name);
-  }
-};
-
-template <>
-class GiGaExtPhysicsExtender<G4EmStandardPhysics_option2> {
-public:
-  inline void addPropertiesTo(AlgTool */*tool*/) {
-    // No specific properties
-  }
-  inline G4EmStandardPhysics_option2 *newInstance(const std::string &name, int verbosity) const {
-    return new G4EmStandardPhysics_option2(verbosity, name);
-  }
-};
-
-template <>
-class GiGaExtPhysicsExtender<G4EmStandardPhysics_option3> {
-public:
-  inline void addPropertiesTo(AlgTool */*tool*/) {
-    // No specific properties
-  }
-  inline G4EmStandardPhysics_option3 *newInstance(const std::string &name, int verbosity) const {
-    return new G4EmStandardPhysics_option3(verbosity, name);
-  }
-};
-
-template <>
-class GiGaExtPhysicsExtender<G4EmStandardPhysics_option1NoApplyCuts> {
-public:
-  inline void addPropertiesTo(AlgTool */*tool*/) {
-    // No specific properties
-  }
-  inline G4EmStandardPhysics_option1NoApplyCuts *newInstance(const std::string &name, int verbosity) const {
-    return new G4EmStandardPhysics_option1NoApplyCuts(verbosity, name);
-  }
-};
-
-template <>
-class GiGaExtPhysicsExtender<G4EmStandardPhysics_option1LHCb> {
-public:
-  inline void addPropertiesTo(AlgTool *tool) {
-    tool->declareProperty("ApplyCuts", m_applyCuts = true, 
-                          "Apply production cuts to all EM processes for the LHCb EM constructor");
-    tool->declareProperty("NewModelForE", m_newForE = true,
-                          "Use new MS models for electrons and positrons");
-  }
-  inline G4EmStandardPhysics_option1LHCb *newInstance(const std::string &/*name*/, int verbosity) const {
-    return new G4EmStandardPhysics_option1LHCb(verbosity, m_applyCuts, m_newForE);
-  }
-private:
-  bool m_applyCuts;
-  bool m_newForE;
-};
-
-template <>
-class GiGaExtPhysicsExtender<G4EmStandardPhysics_LHCbTest> {
-public:
-  inline void addPropertiesTo(AlgTool *tool) {
-    tool->declareProperty("ApplyCuts", m_applyCuts = true, 
-                          "Apply production cuts to all EM processes for the LHCb EM constructor");
-    tool->declareProperty("NewModelForE", m_newForE = true,
-                          "Use new MS models for electrons and positrons");
-  }
-  inline G4EmStandardPhysics_LHCbTest *newInstance(const std::string &/*name*/, int verbosity) const {
-    return new G4EmStandardPhysics_LHCbTest(verbosity, m_applyCuts, m_newForE);
-  }
-private:
-  bool m_applyCuts;
-  bool m_newForE;
-};
-
-template <>
-class GiGaExtPhysicsExtender<G4DecayPhysics> {
-public:
-  inline void addPropertiesTo(AlgTool */*tool*/) {
-    // No specific properties
-  }
-  inline G4DecayPhysics *newInstance(const std::string &name, int verbosity) const {
-    return new G4DecayPhysics(name, verbosity);
-  }
-};
-
-
-template <>
-class GiGaExtPhysicsExtender<G4StoppingPhysics> {
-public:
-  inline void addPropertiesTo(AlgTool *tool) {
-    tool->declareProperty("UseMuonMinusCapture", m_useMuonMinusCapture = true,
-                          "Parameter 'UseMuonMinusCapture' for the constructor of G4StoppingPhysics");
-  }
-  inline G4StoppingPhysics *newInstance(const std::string &name, int verbosity) const {
-    return new G4StoppingPhysics(name, verbosity, m_useMuonMinusCapture);
-  }
-private:
-  bool m_useMuonMinusCapture;
-};
-
-
-template <>
-class GiGaExtPhysicsExtender<G4HadronElasticPhysics> {
-public:
-  inline void addPropertiesTo(AlgTool */*tool*/) {
-  // no specialised properties
-    //    tool->declareProperty("HighPrecision", m_highPrecision = false,
-    //                          "Parameter 'HighPrecision' for the constructor of G4HadronElasticPhysics");
-    // tool->declareProperty("Glauber", m_glauber = false,
-    //                          "Parameter 'Glauber' for the constructor of G4HadronElasticPhysics");
-  }
-  inline G4HadronElasticPhysics *newInstance(const std::string &/*name*/, int verbosity) const {
-    //return new G4HadronElasticPhysics(name, verbosity, m_highPrecision, m_glauber);
-    return new G4HadronElasticPhysics(verbosity);
-  }
-//private:
-//  bool m_highPrecision;
-//  bool m_glauber;
-};
-
-// Removed in G4r10
-/*template <>
-class GiGaExtPhysicsExtender<G4HadronElasticPhysicsLHEP> {
-public:
-  inline void addPropertiesTo(AlgTool *tool) {
-  // No specific properties
-  }
-  inline G4HadronElasticPhysicsLHEP *newInstance(const std::string &name, int verbosity) const {
-    return new G4HadronElasticPhysicsLHEP(verbosity);
-  }
-};*/
-
-template <>
-class GiGaExtPhysicsExtender<G4HadronElasticPhysicsHP> {
-public:
-  inline void addPropertiesTo(AlgTool */*tool*/) {
-  // No specific properties
-  }
-  inline G4HadronElasticPhysicsHP *newInstance(const std::string &/*name*/, int verbosity) const {
-    return new G4HadronElasticPhysicsHP(verbosity);
-  }
-};
-
-// Removed in G4r10
-/*template <>
-class GiGaExtPhysicsExtender<HadronPhysicsQGSP> {
-public:
-  inline void addPropertiesTo(AlgTool *tool) {
-    tool->declareProperty("QuasiElastic", m_quasiElastic = true,
-                          "Parameter 'quasiElastic' for the constructor of HadronPhysicsQGSP");
-  }
-  inline HadronPhysicsQGSP *newInstance(const std::string &name, int verbosity) const {
-    return new HadronPhysicsQGSP(name, m_quasiElastic);
-  }
-private:
-  bool m_quasiElastic;
-};*/
-
-template <>
-class GiGaExtPhysicsExtender<G4HadronPhysicsQGSP_BERT> {
-public:
-  inline void addPropertiesTo(AlgTool *tool) {
-    tool->declareProperty("QuasiElastic", m_quasiElastic = true,
-                          "Parameter 'quasiElastic' for the constructor of HadronPhysicsQGSP_BERT");
-  }
-  inline G4HadronPhysicsQGSP_BERT *newInstance(const std::string &name, int /*verbosity*/) const {
-    return new G4HadronPhysicsQGSP_BERT(name, m_quasiElastic);
-  }
-private:
-  bool m_quasiElastic;
-};
-
-template <>
-class GiGaExtPhysicsExtender<G4HadronPhysicsQGSP_BERT_HP> {
-public:
-  inline void addPropertiesTo(AlgTool *tool) {
-    tool->declareProperty("QuasiElastic", m_quasiElastic = true,
-                          "Parameter 'quasiElastic' for the constructor of HadronPhysicsQGSP_BERT_HP");
-  }
-  inline G4HadronPhysicsQGSP_BERT_HP *newInstance(const std::string &name, int /*verbosity*/) const {
-    return new G4HadronPhysicsQGSP_BERT_HP(name, m_quasiElastic);
-  }
-private:
-  bool m_quasiElastic;
-};
-
-// Removed in G4r10
-/*template <>
-class GiGaExtPhysicsExtender<HadronPhysicsQGSP_BERT_CHIPS> {
-public:
-  inline void addPropertiesTo(AlgTool *tool) {
-    tool->declareProperty("QuasiElastic", m_quasiElastic = true,
-                          "Parameter 'quasiElastic' for the constructor of HadronPhysicsQGSP_BERT_HP");
-  }
-  inline HadronPhysicsQGSP_BERT_CHIPS *newInstance(const std::string &name, int verbosity) const {
-    return new HadronPhysicsQGSP_BERT_CHIPS(name, m_quasiElastic);
-  }
-private:
-  bool m_quasiElastic;
-};*/
-
-template <>
-class GiGaExtPhysicsExtender<G4HadronPhysicsQGSP_FTFP_BERT> {
-public:
-  inline void addPropertiesTo(AlgTool *tool) {
-    tool->declareProperty("QuasiElastic", m_quasiElastic = true,
-                          "Parameter 'quasiElastic' for the constructor of HadronPhysicsQGSP_FTFP_BERT");
-  }
-  inline G4HadronPhysicsQGSP_FTFP_BERT *newInstance(const std::string &name, int /*verbosity*/) const {
-    return new G4HadronPhysicsQGSP_FTFP_BERT(name, m_quasiElastic);
-  }
-private:
-  bool m_quasiElastic;
-};
-
-template <>
-class GiGaExtPhysicsExtender<G4HadronPhysicsFTFP_BERT> {
-public:
-  inline void addPropertiesTo(AlgTool *tool) {
-    tool->declareProperty("QuasiElastic", m_quasiElastic = false,
-                          "Parameter 'quasiElastic' for the constructor of HadronPhysicsFTFP_BERT");
-  }
-  inline G4HadronPhysicsFTFP_BERT *newInstance(const std::string &name, int /*verbosity*/) const {
-    return new G4HadronPhysicsFTFP_BERT(name, m_quasiElastic);
-  }
-private:
-  bool m_quasiElastic;
-};
-
-template <>
-class GiGaExtPhysicsExtender<G4HadronPhysicsFTFP_BERT_HP> {
-public:
-  inline void addPropertiesTo(AlgTool *tool) {
-    tool->declareProperty("QuasiElastic", m_quasiElastic = false,
-                          "Parameter 'quasiElastic' for the constructor of HadronPhysicsFTFP_BERT_HP");
-  }
-  inline G4HadronPhysicsFTFP_BERT_HP *newInstance(const std::string &name, int /*verbosity*/) const {
-    return new G4HadronPhysicsFTFP_BERT_HP(name, m_quasiElastic);
-  }
-private:
-  bool m_quasiElastic;
-};
-
-template <>
-class GiGaExtPhysicsExtender<G4NeutronTrackingCut> {
-public:
-  inline void addPropertiesTo(AlgTool */*tool*/) {
-    // No specific properties
-  }
-  inline G4NeutronTrackingCut *newInstance(const std::string &name, int verbosity) const {
-    return new G4NeutronTrackingCut(name, verbosity);
-  }
-};
-
-typedef GiGaExtPhysics< G4EmStandardPhysics_option1 > EmStdOpt1PhysFactory;
-DECLARE_COMPONENT( EmStdOpt1PhysFactory )
-typedef GiGaExtPhysics< G4EmStandardPhysics_option2 > EmStdOpt2PhysFactory;
-DECLARE_COMPONENT( EmStdOpt2PhysFactory )
-typedef GiGaExtPhysics< G4EmStandardPhysics_option3 > EmStdOpt3PhysFactory;
-DECLARE_COMPONENT( EmStdOpt3PhysFactory )
-typedef GiGaExtPhysics< G4EmStandardPhysics > EmStdPhysFactory;
-DECLARE_COMPONENT( EmStdPhysFactory )
-typedef GiGaExtPhysics< G4DecayPhysics > DecayFactory;
-DECLARE_COMPONENT( DecayFactory )
-
-typedef GiGaExtPhysics< G4EmStandardPhysics_option1LHCb > EmStdLHCbPhysFactory;
-DECLARE_COMPONENT( EmStdLHCbPhysFactory )
-typedef GiGaExtPhysics< G4EmStandardPhysics_option1NoApplyCuts > EmStdOpt1NoCutsPhysFactory;
-DECLARE_COMPONENT( EmStdOpt1NoCutsPhysFactory )
-typedef GiGaExtPhysics< G4EmStandardPhysics_LHCbTest > EmStdLHCbTestPhysFactory;
-DECLARE_COMPONENT( EmStdLHCbTestPhysFactory )
-
-typedef GiGaExtPhysics< G4EmExtraPhysics > EmExtraPhysFactory;
-DECLARE_COMPONENT( EmExtraPhysFactory )
-
-typedef GiGaExtPhysics< G4IonPhysics > IonPhysFactory;
-DECLARE_COMPONENT( IonPhysFactory )
-typedef GiGaExtPhysics< G4StoppingPhysics > StopPhysFactory;
-DECLARE_COMPONENT( StopPhysFactory )
-typedef GiGaExtPhysics< G4HadronElasticPhysics > HadElPhysFactory;
-DECLARE_COMPONENT( HadElPhysFactory )
-
-typedef GiGaExtPhysics< G4HadronElasticPhysicsHP > HadElHPPhysFactory;
-DECLARE_COMPONENT( HadElHPPhysFactory )
-
-typedef GiGaExtPhysics< G4NeutronTrackingCut > NeuTrkCutFactory;
-DECLARE_COMPONENT( NeuTrkCutFactory )
-
-typedef GiGaExtPhysics< G4HadronPhysicsQGSP_BERT > HadPhysQGSP_BERTFactory;
-DECLARE_COMPONENT( HadPhysQGSP_BERTFactory )
-typedef GiGaExtPhysics< G4HadronPhysicsQGSP_BERT_HP > HadPhysQGSP_BERT_HPFactory;
-DECLARE_COMPONENT( HadPhysQGSP_BERT_HPFactory )
-
-typedef GiGaExtPhysics< G4HadronPhysicsQGSP_FTFP_BERT > HadPhysQGSP_FTFP_BERTFactory;
-DECLARE_COMPONENT( HadPhysQGSP_FTFP_BERTFactory )
-
-typedef GiGaExtPhysics< G4HadronPhysicsFTFP_BERT > HadPhysFTFP_BERTFactory;
-DECLARE_COMPONENT( HadPhysFTFP_BERTFactory )
-
-typedef GiGaExtPhysics< G4HadronPhysicsFTFP_BERT_HP > HadPhysFTFP_BERT_HPFactory;
-DECLARE_COMPONENT( HadPhysFTFP_BERT_HPFactory )
 
+typedef GiGaMTG4PhysicsConstrFAC<G4EmStandardPhysics_option1NoApplyCuts> GiGaMT_G4EmStandardPhysics_option1NoApplyCuts;
+DECLARE_COMPONENT_WITH_ID(GiGaMT_G4EmStandardPhysics_option1NoApplyCuts, "GiGaMT_G4EmStandardPhysics_option1NoApplyCuts")
+
+template <typename PhysConstr>
+class GiGaMTG4PhysicsConstrFAC<
+    PhysConstr,
+    typename std::enable_if<
+        std::is_same<PhysConstr, G4EmStandardPhysics_option1LHCb>::value ||
+            std::is_same<PhysConstr, G4EmStandardPhysics_LHCbTest>::value,
+        PhysConstr>::type>
+    : public extends<GiGaMTPhysConstr, GiGaFactoryBase<G4VPhysicsConstructor>> {
+  Gaudi::Property<bool> m_applyCuts{
+      this, "ApplyCuts", true,
+      "Apply production cuts to all EM processes for the LHCb EM constructor"};
+  Gaudi::Property<bool> m_newForE{
+      this, "NewModelForE", true,
+      "Use new MS models for electrons and positrons"};
+
+  public:
+  using extends::extends;
+  PhysConstr* construct() const override {
+    auto tmp = new PhysConstr{verbosity(), m_applyCuts, m_newForE};
+    tmp->SetVerboseLevel(verbosity());
+    tmp->SetPhysicsName(name());
+    return tmp;
+  }
+};
+
+typedef GiGaMTG4PhysicsConstrFAC<G4EmStandardPhysics_option1LHCb> GiGaMT_G4EmStandardPhysics_option1LHCb;
+DECLARE_COMPONENT_WITH_ID(GiGaMT_G4EmStandardPhysics_option1LHCb, "GiGaMT_G4EmStandardPhysics_option1LHCb")
+
+typedef GiGaMTG4PhysicsConstrFAC<G4EmStandardPhysics_LHCbTest> GiGaMT_G4EmStandardPhysics_LHCbTest;
+DECLARE_COMPONENT_WITH_ID(GiGaMT_G4EmStandardPhysics_LHCbTest, "GiGaMT_G4EmStandardPhysics_LHCbTest")
diff --git a/Sim/GaussPhysics/src/GiGaHiggsParticles.cpp b/Sim/GaussPhysics/src/GiGaHiggsParticles.cpp
index b57cbb8ca..fb8a6729a 100755
--- a/Sim/GaussPhysics/src/GiGaHiggsParticles.cpp
+++ b/Sim/GaussPhysics/src/GiGaHiggsParticles.cpp
@@ -1,6 +1,3 @@
-// ============================================================================
-// Include files
-// STD & STL
 #include <algorithm>
 
 // GaudiKernel
@@ -9,130 +6,118 @@
 // LHCb
 #include "Kernel/IParticlePropertySvc.h"
 #include "Kernel/ParticleProperty.h"
-// GiGa
-#include "GiGa/GiGaPhysConstructorBase.h"
 // Geant4
 #include "Geant4/G4ParticleTable.hh"
+#include "Geant4/G4VPhysicsConstructor.hh"
 // Local
 #include "G4Higgses.h"
+#include "GiGaMTCore/IGiGaMessage.h"
+#include "GiGaMTFactories/GiGaMTG4PhysicsConstrFAC.h"
 
-// ============================================================================
-/** @class GiGaHiggsParticles
- *  simple class to construct Higgs particles
- *  (needed for Hidden Valley studies)
- *
- *  The major properties:
- *
- *    - "Higgses" : list of higgs particles to be created.
- *                  the default valeu contains [ "H_10" , "H_20" , "H_30" ]
- *
- *  It also prints (@ MSG::INFO) the properties of created higgses
- *
- *  @author Vanya BELYAEV Ivan.Belyaev@nikhef.nl
- *  @date 2008-06-22
- */
-class GiGaHiggsParticles : public GiGaPhysConstructorBase
+class GiGaMTHiggsParticles : public G4VPhysicsConstructor, public GiGaMessage
 {
 public:
-  // ==========================================================================
-  /// constructor
-  GiGaHiggsParticles
-  ( const std::string& type   ,
-    const std::string& name   ,
-    const IInterface*  parent )
-    : GiGaPhysConstructorBase ( type , name , parent )
-    , m_higgses ()
+  GiGaMTHiggsParticles() = delete;
+  GiGaMTHiggsParticles
+  ( const LHCb::IParticlePropertySvc* ppsvc, std::vector<std::string> higgses): m_higgses(higgses), m_ppsvc(ppsvc)
   {
-    m_higgses.push_back ( "H_10" ) ;
-    m_higgses.push_back ( "H_20" ) ;
-    m_higgses.push_back ( "H_30" ) ;
-    declareProperty
-      ("Higgses" , m_higgses ,
-       "The List of Higgsed to be instantiated") ;
   }
-  // ==========================================================================
-  /// construct the particles
   void ConstructParticle ()    override; // construct the particles
-  /// construct the processed  (empty)
   void ConstructProcess  () override {} ; // construct the processed
-  // ==========================================================================
 protected:
-  // ==========================================================================
-  /// get the particle property for the given particle name
   const LHCb::ParticleProperty* pp
   ( const std::string&    n ,
-    LHCb::IParticlePropertySvc* s ) const
+    const LHCb::IParticlePropertySvc* s ) const
   {
-    Assert ( 0 != s , "Invalid ParticleProperty Service") ;
+    if(!s){
+      throw std::runtime_error("Invalid ParticleProperty Service");
+    }
     const LHCb::ParticleProperty* p = s->find ( n ) ;
-    Assert ( 0 != p , "No information is availale for '" + n + "'") ;
+    if(!p){
+      throw std::runtime_error("No information is availale for '" + n + "'");
+    }
     return p ;
   }
-  // ==========================================================================
 private:
-  // ==========================================================================
-  typedef std::vector<std::string> Strings ;
-  /// list of Higgses to be instantiated
-  Strings    m_higgses ; // list of Higgses to be instantiated
-  // ==========================================================================
+  std::vector<std::string> m_higgses{};
+  const LHCb::IParticlePropertySvc *m_ppsvc{nullptr};
 };
 
-// ============================================================================
-// construct the particles
-// ============================================================================
-void GiGaHiggsParticles::ConstructParticle () // construct the particles
+void GiGaMTHiggsParticles::ConstructParticle () // construct the particles
 {
 
-  LHCb::IParticlePropertySvc* ppSvc =
-    svc<LHCb::IParticlePropertySvc> ("LHCb::ParticlePropertySvc") ;
-
-  Strings tmp = m_higgses ;
+  auto tmp = m_higgses ;
   {
-    // ========================================================================
-    Strings::iterator it = std::find  ( tmp.begin() , tmp.end() , "H_10" ) ;
-    if ( tmp.end() != it )
+    auto it = std::find  ( std::begin(tmp) , std::end(tmp) , "H_10" ) ;
+    if ( std::end(tmp) != it )
     {
-      const LHCb::ParticleProperty* h10 = pp ( "H_10" , ppSvc ) ;
+      const LHCb::ParticleProperty* h10 = pp ( "H_10" , m_ppsvc) ;
       G4H_10* h_10 = G4H_10::Create
         ( h10 -> mass     () ,
           h10 -> lifetime () * Gaudi::Units::c_light ) ;
-      Assert ( 0 != h_10 , "Unable to create H_10" ) ;
-      if ( msgLevel ( MSG::INFO )  ) { h_10->DumpTable () ; }
+      if(!h_10){
+        throw std::runtime_error("Unable to create H_10");
+      }
+      if ( printInfo()  ) { h_10->DumpTable () ; }
       tmp.erase ( it ) ;
     }
     // ========================================================================
-    it = std::find  ( tmp.begin() , tmp.end() , "H_20" ) ;
-    if ( tmp.end() != it )
+    it = std::find  ( std::begin(tmp) , std::end(tmp) , "H_20" ) ;
+    if ( std::end(tmp) != it )
     {
-      const LHCb::ParticleProperty* h20 = pp ( "H_20" , ppSvc ) ;
+      const LHCb::ParticleProperty* h20 = pp ( "H_20" , m_ppsvc) ;
       G4H_20* h_20 = G4H_20::Create
         ( h20 -> mass     () ,
           h20 -> lifetime () * Gaudi::Units::c_light ) ;
-      Assert ( 0 != h_20 , "Unable to create H_20" ) ;
-      if ( msgLevel ( MSG::INFO ) ) { h_20->DumpTable () ; }
+      if(!h_20){
+        throw std::runtime_error("Unable to create H_20");
+      }
+      if ( printInfo()  ) { h_20->DumpTable () ; }
       tmp.erase ( it ) ;
     }
     // ========================================================================
-    it = std::find  ( tmp.begin() , tmp.end() , "H_30" ) ;
-    if ( tmp.end() != it )
+    it = std::find  ( std::begin(tmp) , std::end(tmp) , "H_30" ) ;
+    if ( std::end(tmp) != it )
     {
-      const LHCb::ParticleProperty* h30 = pp ( "H_30" , ppSvc ) ;
+      const LHCb::ParticleProperty* h30 = pp ( "H_30" , m_ppsvc) ;
       G4H_30* h_30 = G4H_30::Create
         ( h30 -> mass     () ,
           h30 -> lifetime () * Gaudi::Units::c_light ) ;
-      Assert ( 0 != h_30 , "Unable to create H_30" ) ;
-      if ( msgLevel ( MSG::INFO ) ) { h_30->DumpTable () ; }
+      if(!h_30){
+        throw std::runtime_error("Unable to create H_30");
+      }
+      if ( printInfo()  ) { h_30->DumpTable () ; }
       tmp.erase ( it ) ;
     }
-    // ========================================================================
-    Assert ( tmp.empty() , "Unknown Higgses in the list!" ) ;
-    // ========================================================================
+    if(!tmp.empty()){
+      throw std::runtime_error("Unknown Higgses in the list!");
+    }
   }
 }
 
-// ============================================================================
-/// Declaration of the Tool Factory
-DECLARE_COMPONENT( GiGaHiggsParticles )
 
-// The END
-// ============================================================================
+template <typename PhysConstr>
+class GiGaMTG4PhysicsConstrFAC<
+    PhysConstr,
+    typename std::enable_if<
+        std::is_same<PhysConstr, GiGaMTHiggsParticles>::value,
+        PhysConstr>::type>
+    : public extends<GiGaMTPhysConstr, GiGaFactoryBase<G4VPhysicsConstructor>> {
+  Gaudi::Property<std::vector<std::string>> m_higgses{
+      this, "Higgses", {},
+      "The List of Higgsed to be instantiated"};
+  ServiceHandle<LHCb::IParticlePropertySvc> m_ppSvc{this, "PropertyService", "LHCb::ParticlePropertySvc"};
+
+  public:
+  using extends::extends;
+  PhysConstr* construct() const override {
+    auto tmp = new PhysConstr{m_ppSvc.get(), m_higgses};
+    tmp->SetMessageInterface(message_interface());
+    tmp->SetVerboseLevel(verbosity());
+    tmp->SetPhysicsName(name());
+    return tmp;
+  }
+};
+
+typedef GiGaMTG4PhysicsConstrFAC<GiGaMTHiggsParticles> GiGaMT_GiGaMTHiggsParticles;
+DECLARE_COMPONENT_WITH_ID(GiGaMT_GiGaMTHiggsParticles, "GiGaMTHiggsParticles")
diff --git a/Sim/GaussPhysics/src/GiGaPhysUnknownParticles.cpp b/Sim/GaussPhysics/src/GiGaPhysUnknownParticles.cpp
index 0be58c2d0..87b322c5f 100755
--- a/Sim/GaussPhysics/src/GiGaPhysUnknownParticles.cpp
+++ b/Sim/GaussPhysics/src/GiGaPhysUnknownParticles.cpp
@@ -1,81 +1,52 @@
-// $Id: GiGaPhysUnknownParticles.cpp,v 1.6 2009-10-20 07:35:07 marcin Exp $
-// Include files
-
 // from Gaudi
 #include "GaudiKernel/PhysicalConstants.h"
 
 // G4
-#include "Geant4/G4UnknownParticle.hh"
-#include "Geant4/G4ProcessManager.hh"
 #include "Geant4/G4ParticleTable.hh"
+#include "Geant4/G4ProcessManager.hh"
+#include "Geant4/G4UnknownParticle.hh"
 
 // local
-#include "G4BcMesonMinus.h"
-#include "G4BcMesonPlus.h"
 #include "G4AntiLambdabZero.h"
-#include "G4LambdabZero.h"
+#include "G4AntiOmegabcZero.h"
+#include "G4AntiOmegaccMinus.h"
 #include "G4AntiXibZero.h"
-#include "G4XibZero.h"
-#include "G4XibMinus.h"
-#include "G4XibPlus.h"
-#include "G4OmegabMinus.h"
-#include "G4OmegabPlus.h"
-#include "G4AntiXiccStarMinus.h"
-#include "G4XiccStarPlus.h"
-#include "G4AntiXiccMinus.h"
-#include "G4XiccPlus.h"
 #include "G4AntiXibcMinus.h"
-#include "G4XibcPlus.h"
 #include "G4AntiXibcZero.h"
-#include "G4XibcZero.h"
+#include "G4AntiXiccMinus.h"
 #include "G4AntiXiccMinusMinus.h"
-#include "G4XiccPlusPlus.h"
-#include "G4Neutralino.h"
-#include "G4Neutralino2.h"
+#include "G4AntiXiccStarMinus.h"
+#include "G4BcMesonMinus.h"
+#include "G4BcMesonPlus.h"
 #include "G4CharginoMinus.h"
 #include "G4CharginoPlus.h"
 #include "G4HiddenValley.h"
-#include "G4AntiOmegaccMinus.h"
-#include "G4OmegaccPlus.h"
-#include "G4AntiOmegabcZero.h"
+#include "G4LambdabZero.h"
+#include "G4Neutralino.h"
+#include "G4Neutralino2.h"
+#include "G4OmegabMinus.h"
+#include "G4OmegabPlus.h"
 #include "G4OmegabcZero.h"
+#include "G4OmegaccPlus.h"
+#include "G4XibMinus.h"
+#include "G4XibPlus.h"
+#include "G4XibZero.h"
+#include "G4XibcPlus.h"
+#include "G4XibcZero.h"
+#include "G4XiccPlus.h"
+#include "G4XiccPlusPlus.h"
+#include "G4XiccStarPlus.h"
 
 //
 #include "GiGaPhysUnknownParticles.h"
 
-//-----------------------------------------------------------------------------
-// Implementation file for class : GiGaPhysUnknownParticles
-//-----------------------------------------------------------------------------
-
-// Declaration of the Tool Factory
-DECLARE_COMPONENT( GiGaPhysUnknownParticles )
-
-//=============================================================================
-// Standard constructor, initializes variables
-//=============================================================================
-GiGaPhysUnknownParticles::GiGaPhysUnknownParticles
-( const std::string& type   ,
-  const std::string& name   ,
-  const IInterface*  parent )
-  : GiGaPhysConstructorBase( type , name , parent ) 
-{ }
-
-//=============================================================================
-// Destructor
-//=============================================================================
-GiGaPhysUnknownParticles::~GiGaPhysUnknownParticles(){}
-
-//=============================================================================
-// ConstructParticle
-//=============================================================================
-void GiGaPhysUnknownParticles::ConstructParticle()
-{
-  G4BcMesonMinus::BcMesonMinusDefinition() ;
-  G4BcMesonPlus::BcMesonPlusDefinition() ;  
-  G4XibMinus::XibMinusDefinition() ;
-  G4XibPlus::XibPlusDefinition() ;  
-  G4OmegabMinus::OmegabMinusDefinition() ;
-  G4OmegabPlus::OmegabPlusDefinition() ;  
+void GiGaMTPhysUnknownParticles::ConstructParticle() {
+  G4BcMesonMinus::BcMesonMinusDefinition();
+  G4BcMesonPlus::BcMesonPlusDefinition();
+  G4XibMinus::XibMinusDefinition();
+  G4XibPlus::XibPlusDefinition();
+  G4OmegabMinus::OmegabMinusDefinition();
+  G4OmegabPlus::OmegabPlusDefinition();
   G4AntiLambdabZero::AntiLambdabZeroDefinition();
   G4LambdabZero::LambdabZeroDefinition();
   G4AntiXibZero::AntiXibZeroDefinition();
@@ -91,47 +62,37 @@ void GiGaPhysUnknownParticles::ConstructParticle()
   G4AntiXiccMinusMinus::AntiXiccMinusMinusDefinition();
   G4XiccPlusPlus::XiccPlusPlusDefinition();
   G4Neutralino::NeutralinoDefinition();
-  G4HiddenValley::HiddenValleyDefinition(); 
+  G4HiddenValley::HiddenValleyDefinition();
   G4Neutralino2::Neutralino2Definition();
   G4CharginoPlus::CharginoPlusDefinition();
   G4CharginoMinus::CharginoMinusDefinition();
-  G4OmegaccPlus::OmegaccPlusDefinition(); 
+  G4OmegaccPlus::OmegaccPlusDefinition();
   G4AntiOmegaccMinus::AntiOmegaccMinusDefinition();
   G4OmegabcZero::OmegabcZeroDefinition();
-  G4AntiOmegabcZero::AntiOmegabcZeroDefinition(); 
+  G4AntiOmegabcZero::AntiOmegabcZeroDefinition();
 
- 
-  G4UnknownParticle::UnknownParticleDefinition();  
+  G4UnknownParticle::UnknownParticleDefinition();
 }
 
-//=============================================================================
-// ConstructProcess
-//=============================================================================
-void GiGaPhysUnknownParticles::ConstructProcess()
-{
+void GiGaMTPhysUnknownParticles::ConstructProcess() {
   auto theParticleIterator = GetParticleIterator();
-  theParticleIterator -> reset() ;
-  while ( (*theParticleIterator)() ) {
-    G4ParticleDefinition * particle = theParticleIterator -> value() ;
-    G4ProcessManager     * pmanager = particle -> GetProcessManager() ;
-//    if ( m_decayProcess.IsApplicable( *particle ) ) {
-//      debug() << "### Decays for " << particle -> GetParticleName() 
-//              << endmsg ;
-//      pmanager -> AddProcess( &m_decayProcess ) ;
-      // set ordering for PostStepDoIt and AtRestDoIt
-//      pmanager -> SetProcessOrdering( &m_decayProcess , idxPostStep ) ;
-//      pmanager -> SetProcessOrdering( &m_decayProcess , idxAtRest   ) ;
-//      pmanager -> DumpInfo() ;      
-//    }
-    if ( particle -> GetParticleName() == "unknown" ) {
-      pmanager -> AddProcess( &m_unknownDecay ) ;
-      pmanager -> SetProcessOrdering( &m_unknownDecay , idxPostStep ) ;
-      debug() << "### Unknown Decays for " << particle -> GetParticleName() 
-              << endmsg ;
-      if ( msgLevel( MSG::DEBUG) ) 
-        pmanager -> DumpInfo() ;
+  theParticleIterator->reset();
+  while ((*theParticleIterator)()) {
+    G4ParticleDefinition* particle = theParticleIterator->value();
+    G4ProcessManager* pmanager = particle->GetProcessManager();
+    if (particle->GetParticleName() == "unknown") {
+      pmanager->AddProcess(&m_unknownDecay);
+      pmanager->SetProcessOrdering(&m_unknownDecay, idxPostStep);
+      if (printDebug()) {
+        std::stringstream message;
+        message << "### Unknown Decays for " << particle->GetParticleName();
+        debug(message.str());
+      }
+      if (printDebug()) pmanager->DumpInfo();
     }
   }
 }
 
-//=============================================================================
+#include "GiGaMTFactories/GiGaMTG4PhysicsConstrFAC.h"
+typedef GiGaMTG4PhysicsConstrFAC<GiGaMTPhysUnknownParticles> GiGaMT_GiGaMTPhysUnknownParticles;
+DECLARE_COMPONENT_WITH_ID(GiGaMT_GiGaMTPhysUnknownParticles, "GiGaPhysUnknownParticles")
diff --git a/Sim/GaussPhysics/src/GiGaPhysUnknownParticles.h b/Sim/GaussPhysics/src/GiGaPhysUnknownParticles.h
index 91541edde..3b08c0a2b 100755
--- a/Sim/GaussPhysics/src/GiGaPhysUnknownParticles.h
+++ b/Sim/GaussPhysics/src/GiGaPhysUnknownParticles.h
@@ -1,32 +1,12 @@
-// ============================================================================
-#ifndef    GAUSSPHYS_GIGAPHYSUNKNOWNPARTICLES_H
-#define    GAUSSPHYS_GIGAPHYSUNKNOWNPARTICLES_H 1
-// ============================================================================
-// include files
-// ============================================================================
-// GiGa
-// ============================================================================
-#include "GiGa/GiGaPhysConstructorBase.h"
+#pragma once
+
+#include "Geant4/G4VPhysicsConstructor.hh"
 #include "Geant4/G4Decay.hh"
 #include "Geant4/G4UnknownDecay.hh"
-// ============================================================================
-// forward declarations
-template <class TYPE> class GiGaFactory;
+#include "GiGaMTCore/IGiGaMessage.h"
 
-class GiGaPhysUnknownParticles : public GiGaPhysConstructorBase
+class GiGaMTPhysUnknownParticles :public GiGaMessage, public G4VPhysicsConstructor
 {
-  /// friend factory for instantiation
-  friend class GiGaFactory<GiGaPhysUnknownParticles>;
-
-public:
-
-  GiGaPhysUnknownParticles
-  ( const std::string& type   ,
-    const std::string& name   ,
-    const IInterface*  parent ) ;
-
-  ~GiGaPhysUnknownParticles();
-
 
 public:
   void ConstructParticle () override;
@@ -38,20 +18,3 @@ private:
   G4UnknownDecay m_unknownDecay ;
 
 };
-// ============================================================================
-
-
-// ============================================================================
-#endif   ///< GAUSSPHYS_GIGAPHYSUNKNOWNPARTICLES_H
-// ============================================================================
-
-
-
-
-
-
-
-
-
-
-
-- 
GitLab


From 28bb7ab409e9e6211687842b857436449ff8c174 Mon Sep 17 00:00:00 2001
From: Dominik Muller <dominik.muller@cern.ch>
Date: Thu, 23 May 2019 17:37:52 +0200
Subject: [PATCH 05/90] Initial commit with reworked GaussGeo + GaussTracker
 and cleaned Configuration

---
 CMakeLists.txt                                |   5 +
 Sim/Gauss/CMakeLists.txt                      |  56 ++-
 Sim/Gauss/python/Gauss/Geometry/BCM.py        |  30 ++
 Sim/Gauss/python/Gauss/Geometry/BLS.py        |  28 ++
 Sim/Gauss/python/Gauss/Geometry/BeamPipe.py   | 110 +++++
 Sim/Gauss/python/Gauss/Geometry/CALO.py       |  37 ++
 .../python/Gauss/Geometry/Configuration.py    | 202 +++++++++
 Sim/Gauss/python/Gauss/Geometry/FT.py         |  17 +
 Sim/Gauss/python/Gauss/Geometry/HC.py         |  44 ++
 Sim/Gauss/python/Gauss/Geometry/Helpers.py    |  53 +++
 Sim/Gauss/python/Gauss/Geometry/IT.py         |  28 ++
 Sim/Gauss/python/Gauss/Geometry/Magnet.py     |  44 ++
 Sim/Gauss/python/Gauss/Geometry/Muon.py       |  22 +
 Sim/Gauss/python/Gauss/Geometry/OT.py         |  28 ++
 Sim/Gauss/python/Gauss/Geometry/PuVeto.py     |   9 +
 Sim/Gauss/python/Gauss/Geometry/RICH.py       |  65 +++
 Sim/Gauss/python/Gauss/Geometry/SL.py         |  16 +
 Sim/Gauss/python/Gauss/Geometry/TT.py         |  25 ++
 Sim/Gauss/python/Gauss/Geometry/UT.py         |  12 +
 Sim/Gauss/python/Gauss/Geometry/VP.py         |  12 +
 Sim/Gauss/python/Gauss/Geometry/Velo.py       | 155 +++++++
 Sim/Gauss/python/Gauss/Geometry/__init__.py   |  20 +
 Sim/Gauss/python/Gauss/Geometry/det_base.py   |  67 +++
 Sim/Gauss/python/Gauss/Physics.py             |   3 +-
 Sim/Gauss/python/Gauss/Utilities.py           |  57 +++
 Sim/GaussGeo/CMakeLists.txt                   |   8 +-
 Sim/GaussGeo/GaussGeo/IGaussGeo.h             |   5 +-
 Sim/GaussGeo/src/component/GaussGeo.cpp       | 412 +++++++++---------
 Sim/GaussGeo/src/component/GaussGeo.h         |  53 ++-
 Sim/GaussTracker/src/GetTrackerHitsAlg.cpp    | 174 ++++----
 Sim/GaussTracker/src/GetTrackerHitsAlg.h      |   2 +-
 Sim/GaussTracker/src/GiGaSensDetTracker.cpp   | 137 +++---
 Sim/GaussTracker/src/TrackerHit.cpp           |   2 +
 Sim/GaussTracker/src/TrackerHit.h             |  14 +-
 34 files changed, 1521 insertions(+), 431 deletions(-)
 create mode 100644 Sim/Gauss/python/Gauss/Geometry/BCM.py
 create mode 100644 Sim/Gauss/python/Gauss/Geometry/BLS.py
 create mode 100644 Sim/Gauss/python/Gauss/Geometry/BeamPipe.py
 create mode 100644 Sim/Gauss/python/Gauss/Geometry/CALO.py
 create mode 100644 Sim/Gauss/python/Gauss/Geometry/Configuration.py
 create mode 100644 Sim/Gauss/python/Gauss/Geometry/FT.py
 create mode 100644 Sim/Gauss/python/Gauss/Geometry/HC.py
 create mode 100644 Sim/Gauss/python/Gauss/Geometry/Helpers.py
 create mode 100644 Sim/Gauss/python/Gauss/Geometry/IT.py
 create mode 100644 Sim/Gauss/python/Gauss/Geometry/Magnet.py
 create mode 100644 Sim/Gauss/python/Gauss/Geometry/Muon.py
 create mode 100644 Sim/Gauss/python/Gauss/Geometry/OT.py
 create mode 100644 Sim/Gauss/python/Gauss/Geometry/PuVeto.py
 create mode 100644 Sim/Gauss/python/Gauss/Geometry/RICH.py
 create mode 100644 Sim/Gauss/python/Gauss/Geometry/SL.py
 create mode 100644 Sim/Gauss/python/Gauss/Geometry/TT.py
 create mode 100644 Sim/Gauss/python/Gauss/Geometry/UT.py
 create mode 100644 Sim/Gauss/python/Gauss/Geometry/VP.py
 create mode 100644 Sim/Gauss/python/Gauss/Geometry/Velo.py
 create mode 100644 Sim/Gauss/python/Gauss/Geometry/__init__.py
 create mode 100644 Sim/Gauss/python/Gauss/Geometry/det_base.py
 create mode 100644 Sim/Gauss/python/Gauss/Utilities.py

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 9c5f6b881..7af042366 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -20,6 +20,11 @@ macro(FindG4libs)
     link_directories(${Geant4_LIBRARY_DIRS})
 endmacro()
 
+macro(AddHepMC3)
+    include_directories(SYSTEM ${Gaussino_DIR}/include)
+    link_directories(${Gaussino_DIR}/lib)
+endmacro()
+
 # Declare project name and version
 gaudi_project(Gauss v60r0
               FORTRAN
diff --git a/Sim/Gauss/CMakeLists.txt b/Sim/Gauss/CMakeLists.txt
index 1a3d21e74..6072d921c 100644
--- a/Sim/Gauss/CMakeLists.txt
+++ b/Sim/Gauss/CMakeLists.txt
@@ -3,36 +3,34 @@
 ################################################################################
 gaudi_subdir(Gauss v53r2)
 
-find_package(HepMC)
-
-gaudi_depends_on_subdirs(Det/DDDB
-                         Det/DetSys
-                         Event/EventPacker
-                         Gaudi
-                         GaudiConf
-                         GaudiKernel
-                         Kernel/KernelSys
-                         Sim/SimComponents
-                         Sim/GaussAlgs
-                         Gen/LbPGuns
-                         Gen/LbMIB
-                         Gen/LbPythia
-                         Gen/LbPythia8
-                         Gen/LbHijing
-                         Gen/LbCRMC
-                         Sim/GaussAlgs
-                         Sim/GaussKine
-                         Sim/GaussRICH
-                         Sim/GaussRedecay
-                         Sim/GaussCherenkov
-                         Sim/GaussCalo
-                         Sim/GaussTracker
-                         Muon/MuonMoniSim)
+#gaudi_depends_on_subdirs(Det/DDDB
+                         #Det/DetSys
+                         #Event/EventPacker
+                         #Gaudi
+                         #GaudiConf
+                         #GaudiKernel
+                         #Kernel/KernelSys
+                         #Sim/SimComponents
+                         #Sim/GaussAlgs
+                         #Gen/LbPGuns
+                         #Gen/LbMIB
+                         #Gen/LbPythia
+                         #Gen/LbPythia8
+                         #Gen/LbHijing
+                         #Gen/LbCRMC
+                         #Sim/GaussAlgs
+                         #Sim/GaussKine
+                         #Sim/GaussRICH
+                         #Sim/GaussRedecay
+                         #Sim/GaussCherenkov
+                         #Sim/GaussCalo
+                         #Sim/GaussTracker
+                         #Muon/MuonMoniSim)
 
 gaudi_install_python_modules()
-gaudi_install_scripts()
+#gaudi_install_scripts()
 
-gaudi_env(SET AlwaysKillLeadingHadron 1
-          SET GAUSSOPTS \${GAUSSROOT}/options)
+#gaudi_env(SET AlwaysKillLeadingHadron 1
+          #SET GAUSSOPTS \${GAUSSROOT}/options)
 
-gaudi_add_test(QMTest QMTEST)
+#gaudi_add_test(QMTest QMTEST)
diff --git a/Sim/Gauss/python/Gauss/Geometry/BCM.py b/Sim/Gauss/python/Gauss/Geometry/BCM.py
new file mode 100644
index 000000000..c6d0c948f
--- /dev/null
+++ b/Sim/Gauss/python/Gauss/Geometry/BCM.py
@@ -0,0 +1,30 @@
+from Gauss.Geometry.det_base import det_base
+from Gauss.Geometry.Helpers import subdetector
+
+
+@subdetector
+class BCM(det_base):
+
+    def ApplyDetector(self, basePieces, detPieces):
+        from Gauss.Geometry import LHCbGeo
+        # Add the non-standard pieces of the BeforeMagnet region.
+        region = 'BeforeMagnetRegion'
+        if region in detPieces:
+            pieces = ['PipeJunctionBeforeVelo', 'BeforeVelo']
+            for piece in pieces:
+                if piece in detPieces[region]:
+                    continue
+                detPieces[region] += [piece]
+        # Add the entire Upstream region.
+        region = 'UpstreamRegion'
+        if region in detPieces:
+            detPieces[region] = []
+        LHCbGeo._listOfGeoObjects_.append("/dd/Structure/LHCb/" + region)
+        # Add the AfterMuon part of the Downstream region.
+        region = 'DownstreamRegion'
+        if region in detPieces:
+            pieces = ['AfterMuon']
+            for piece in pieces:
+                if piece in detPieces[region]:
+                    continue
+                detPieces[region] += [piece]
diff --git a/Sim/Gauss/python/Gauss/Geometry/BLS.py b/Sim/Gauss/python/Gauss/Geometry/BLS.py
new file mode 100644
index 000000000..c3a2eba6e
--- /dev/null
+++ b/Sim/Gauss/python/Gauss/Geometry/BLS.py
@@ -0,0 +1,28 @@
+
+from Gauss.Geometry.det_base import det_base
+from Gauss.Geometry.Helpers import subdetector
+
+
+@subdetector
+class BCM(det_base):
+
+    def ApplyDetector(self, basePieces, detPieces):
+        from Gauss.Geometry import LHCbGeo
+        # Add the non-standard pieces of the BeforeMagnet region.
+        region = 'BeforeMagnetRegion'
+        if region in detPieces:
+            pieces = ['PipeJunctionBeforeVelo', 'BeforeVelo']
+            for piece in pieces:
+                if piece in detPieces[region]:
+                    continue
+                detPieces[region] += [piece]
+        # Add the non-standard pieces of the Upstream region,
+        # unless the Upstream region has been added as a whole.
+        region = 'UpstreamRegion'
+        path = '/dd/Structure/LHCb/' + region
+        if region in detPieces and path not in LHCbGeo._listOfGeoObjects_:
+            pieces = ['BlockWallUpstr']
+            for piece in pieces:
+                if piece in detPieces[region]:
+                    continue
+                detPieces[region] += [piece]
diff --git a/Sim/Gauss/python/Gauss/Geometry/BeamPipe.py b/Sim/Gauss/python/Gauss/Geometry/BeamPipe.py
new file mode 100644
index 000000000..00e6e95ea
--- /dev/null
+++ b/Sim/Gauss/python/Gauss/Geometry/BeamPipe.py
@@ -0,0 +1,110 @@
+from Gauss.Geometry.det_base import det_base
+from Gauss.Geometry import LHCbGeo
+from Gaudi.Configuration import Configurable
+from Gauss.Geometry.Helpers import subdetector
+
+
+@subdetector
+class BeamPipe(det_base):
+
+    __slots__ = {
+        "State": 'BeamPipeOn',
+    }
+
+    _beamPipeStates = ['beampipeon', 'beampipeoff', 'beampipeindet']
+    _beamPipeElements = {
+        "velo": [
+            "/dd/Structure/LHCb/BeforeMagnetRegion/Velo/"
+            "DownStreamWakeFieldCone",
+            "/dd/Structure/LHCb/BeforeMagnetRegion/Velo/UpStreamWakeFieldCone",
+            "/dd/Structure/LHCb/BeforeMagnetRegion/Velo/DownstreamPipeSections",
+            "/dd/Structure/LHCb/BeforeMagnetRegion/Velo/VacTank"],
+        "rich1": [
+            "/dd/Structure/LHCb/BeforeMagnetRegion/Rich1/PipeInRich1BeforeSubM",
+            "/dd/Structure/LHCb/BeforeMagnetRegion/Rich1/PipeInRich1SubMaster",
+            "/dd/Structure/LHCb/BeforeMagnetRegion/Rich1/PipeInRich1AfterSubM",
+            "/dd/Structure/LHCb/BeforeMagnetRegion/Rich1/Rich1BeamPipe"],
+        "tt": ["/dd/Structure/LHCb/BeforeMagnetRegion/TT/PipeInTT"],
+        "ut": ["/dd/Structure/LHCb/BeforeMagnetRegion/UT/PipeInUT"],
+        "magnet": [
+            "/dd/Structure/LHCb/MagnetRegion/PipeInMagnet",
+            "/dd/Structure/LHCb/MagnetRegion/PipeSupportsInMagnet"],
+        "AfterMagnetRegion": [
+            "/dd/Structure/LHCb/AfterMagnetRegion/PipeAfterT",
+            "/dd/Structure/LHCb/AfterMagnetRegion/PipeSupportsAfterMagnet"],
+        "t": ["/dd/Structure/LHCb/AfterMagnetRegion/T/PipeInT"],
+        "rich2": ["/dd/Structure/LHCb/AfterMagnetRegion/Rich2/Rich2BeamPipe"],
+        "downstreamregion": [
+            "/dd/Structure/LHCb/DownstreamRegion/PipeDownstream",
+            "/dd/Structure/LHCb/DownstreamRegion/PipeSupportsDownstream",
+            "/dd/Structure/LHCb/DownstreamRegion/PipeBakeoutDownstream"]}
+
+    @staticmethod
+    def removeBeamPipeElements(det):
+        det = det.lower()
+        # Remove beampipe elements in <det> - will be included automatically
+        if det in BeamPipe._beamPipeElements.keys():
+            for element in BeamPipe._beamPipeElements[det]:
+                # remove all instances of the element
+                while element in LHCbGeo._listOfGeoObjects_:
+                    LHCbGeo._listOfGeoObjects_.remove(element)
+
+    @staticmethod
+    def removeAllBeamPipeElements():
+        # Remove all beampipe elements
+        for det in BeamPipe._beamPipeElements.keys():
+            for element in BeamPipe._beamPipeElements[det]:
+                # remove all instances of the element
+                while element in LHCbGeo._listOfGeoObjects_:
+                    LHCbGeo._listOfGeoObjects_.remove(element)
+
+    def validateBeamPipeSwitch(self):
+        bpString = self.getProp("State")
+        bpLower = bpString.lower()
+        if bpLower not in self._beamPipeStates:
+            raise RuntimeError(
+                "ERROR: BeamPipe configuration '%s' not recognised!" %
+                bpString)
+
+    def __init__(self, name=Configurable.DefaultName, **kwargs):
+        kwargs["name"] = name
+        super(det_base, self).__init__(*(), **kwargs)
+        self.initialize()
+
+    def ApplyDetector(self, basePieces, detPieces):
+        # This function is only executed if BeamPipe was set to Active
+        self.validateBeamPipeSwitch()
+
+        if not "BeamPipeOn" == self.getProp("State"):
+            return
+        all_dets = LHCbGeo().getProp('DetectorGeo')['Detectors']
+        # Here commences a hack to deal with daft DDDB structure
+        ignoreList = ['ut', 'tt']
+        # decide if TT or UT in dets to simulate
+        ttDetectorList = [det for det in ['UT', 'TT'] if det in all_dets]
+        # lower strings
+        if ttDetectorList:
+            # lower everything in ttDetectorList
+            ttDetectorList = [det.lower() for det in ttDetectorList]
+            # get the elements to ignore
+            ignoreList = [
+                det
+                for det in ignoreList if det not in ttDetectorList]
+
+        for region in self._beamPipeElements.keys():
+            if region in ignoreList:
+                continue
+            for element in self._beamPipeElements[region]:
+                LHCbGeo._listOfGeoObjects_.append(element)
+
+        # Finally add in the TT or UT beampipe if we're not defining the
+        # detectors but want the BP anyway depending on DataType
+        # Nasty and unclean - change the DDDB s.t. it makes sense please!
+        if "UT" not in all_dets and "TT" not in all_dets:
+            from Configurables import LHCbApp
+            if LHCbApp().getProp("DataType") not in ["Upgrade"]:
+                for element in BeamPipe._beamPipeElements["tt"]:
+                    BeamPipe._listOfGeoObjects_.append(element)
+            else:
+                for element in BeamPipe._beamPipeElements["ut"]:
+                    BeamPipe._listOfGeoObjects_.append(element)
diff --git a/Sim/Gauss/python/Gauss/Geometry/CALO.py b/Sim/Gauss/python/Gauss/Geometry/CALO.py
new file mode 100644
index 000000000..bb650c615
--- /dev/null
+++ b/Sim/Gauss/python/Gauss/Geometry/CALO.py
@@ -0,0 +1,37 @@
+from Gauss.Geometry.det_base import det_base
+from Gauss.Geometry.Helpers import subdetector
+from Gauss.Geometry.BeamPipe import BeamPipe
+
+
+@subdetector
+class SPD(det_base):
+
+    def ApplyDetector(self, basePieces, detPieces):
+        BeamPipe.removeBeamPipeElements("calo")
+        region = 'DownstreamRegion'
+        detPieces[region] += ['Spd']
+        detPieces[region] += ['Converter']
+
+
+@subdetector
+class PRS(det_base):
+
+    def ApplyDetector(self, basePieces, detPieces):
+        region = 'DownstreamRegion'
+        detPieces[region] += ['Prs']
+
+
+@subdetector
+class ECAL(det_base):
+
+    def ApplyDetector(self, basePieces, detPieces):
+        region = 'DownstreamRegion'
+        detPieces[region] += ['Ecal']
+
+
+@subdetector
+class HCAL(det_base):
+
+    def ApplyDetector(self, basePieces, detPieces):
+        region = 'DownstreamRegion'
+        detPieces[region] += ['Hcal']
diff --git a/Sim/Gauss/python/Gauss/Geometry/Configuration.py b/Sim/Gauss/python/Gauss/Geometry/Configuration.py
new file mode 100644
index 000000000..e4843def7
--- /dev/null
+++ b/Sim/Gauss/python/Gauss/Geometry/Configuration.py
@@ -0,0 +1,202 @@
+from Gaudi.Configuration import log
+from Configurables import LHCbConfigurableUser
+from GaudiKernel import SystemOfUnits
+from Gaudi.Configuration import Configurable
+from Gauss.Geometry.Helpers import checkIncompatibleDetectors
+from Gauss.Geometry.Helpers import defineGeoBasePieces
+
+
+class LHCbGeo(LHCbConfigurableUser):
+
+    """Main configurable to set up the LHCb geometry using the GaussGeo
+    service for Run1 or Run2"""
+
+    __knownDetectors__ = [
+        'velo', 'puveto', 'vp', 'tt', 'ut',
+        'it', 'sl', 'ot', 'ft', 'ft-noshield',
+        'rich',  'rich1', 'rich2', 'torch',
+        'calo',  'spd', 'prs', 'ecal', 'hcal',
+        'muon', 'magnet', 'rich1pmt', 'rich2pmt', 'hc'
+        ]
+
+    __slots__ = {
+        # Simple lists of sub detectors
+        "DetectorGeo": {
+            "Detectors": ['PuVeto', 'Velo', 'TT', 'IT', 'OT', 'Rich1', 'Rich2',
+                          'Spd', 'Prs', 'Ecal', 'Hcal', 'Muon', 'Magnet']},
+        "DetectorSim": {
+            "Detectors": ['PuVeto', 'Velo', 'TT', 'IT', 'OT', 'Rich1', 'Rich2',
+                          'Spd', 'Prs', 'Ecal', 'Hcal', 'Muon', 'Magnet']},
+        "DetectorMoni": {
+            "Detectors": ['PuVeto', 'Velo', 'TT', 'IT', 'OT', 'Rich1', 'Rich2',
+                          'Spd', 'Prs', 'Ecal', 'Hcal', 'Muon']},
+        "Debug": False
+        }
+
+    _detectorsDefaults = {
+        "Detectors": ['PuVeto', 'Velo', 'TT', 'IT', 'OT', 'Rich1', 'Rich2',
+                      'Spd', 'Prs', 'Ecal', 'Hcal', 'Muon', 'Magnet']
+    }
+    _propertyDocDct = {
+        "DetectorGeo": """ Dictionary specifying the detectors to take
+                           into account in Geometry """,
+        "DetectorSim": """ Dictionary specifying the detectors
+                            to simulated (should be in geometry): """,
+        "DetectorMoni": """ Dictionary specifying the detectors
+                             to monitor (should be simulated) :"""
+    }
+
+    TrackingSystem = ['VELO', 'TT', 'IT', 'OT']
+    PIDSystem = ['RICH', 'CALO', 'MUON']
+
+    # List of geometry objects which will be converted, it's content is used in
+    # GaussGeo or in GiGaInputStream if GiGaGeo is used for conversion
+    _listOfGeoObjects_ = []
+
+    def setLHCbAppDetectors(self):
+        from Configurables import LHCbApp
+        # If detectors set in LHCbApp then use those
+        if hasattr(LHCbApp(), "Detectors"):
+            if not LHCbApp().Detectors:
+                LHCbApp().Detectors = self.getProp("DetectorGeo")["Detectors"]
+            else:
+                log.warning(
+                    "Value of 'LHCbApp().Detectors' already set"
+                    ", using that value: %s" % LHCbApp().Detectors)
+        return
+
+    def __init__(self, name=Configurable.DefaultName, **kwargs):
+        kwargs["name"] = name
+        super(LHCbConfigurableUser, self).__init__(*(), **kwargs)
+        self.initialize()
+
+    def defineStreamItemsGeo(self, basePieces, detPieces):
+        for region in basePieces.keys():
+            path = "/dd/Structure/LHCb/"+region+"/"
+            if len(detPieces[region]) == 0:
+                continue
+            # This should preserve order
+            for element in basePieces[region] + detPieces[region]:
+                myStreamItem = path + element
+                if myStreamItem not in self._listOfGeoObjects_:
+                    self._listOfGeoObjects_.append(myStreamItem)
+
+    def __apply_configuration__(self):
+        from Configurables import GaussGeo
+        if self.getProp('Debug'):
+            GaussGeo.OutputLevel = -10
+
+        detPieces = {'BeforeUpstreamRegion': [],
+                     'UpstreamRegion': [],
+                     'BeforeMagnetRegion': [],
+                     'MagnetRegion': [],
+                     'AfterMagnetRegion': [],
+                     'DownstreamRegion': [],
+                     'AfterDownstreamRegion': []}
+        basePieces = {}
+
+        self.setLHCbAppDetectors()
+        checkIncompatibleDetectors()
+        defineGeoBasePieces(basePieces)
+
+        gaussgeo = GaussGeo()
+
+        # Use information from SIMCOND and GeometryInfo
+        # Allows to be set to False by RichXPmt
+        gaussgeo.UseAlignment = True
+        gaussgeo.AlignAllDetectors = True
+
+        from Gauss.Geometry.Helpers import getsubdetector
+        detectors_geo = self.getProp("DetectorGeo")["Detectors"]
+        detectors_sim = self.getProp("DetectorSim")["Detectors"]
+        detectors_moni = self.getProp("DetectorMoni")["Detectors"]
+        # Initial loop to mark all used detectors as active
+        for det in detectors_geo:
+            getsubdetector(det).Active = True
+        for det in detectors_sim:
+            getsubdetector(det).Simulate = True
+        for det in detectors_moni:
+            getsubdetector(det).Monitor = True
+
+        # BeamPipe
+        getsubdetector('BeamPipe').ApplyDetector(basePieces, detPieces)
+
+        for det in detectors_geo:
+            getsubdetector(det).ApplyDetector(basePieces, detPieces)
+
+        # Now convert all basePieces entries to fill list of geo objects
+        self.defineStreamItemsGeo(basePieces, detPieces)
+
+        # FIXME: does basically the same as before, but was done this way in
+        # the main Gauss configuration. Should rethink
+        for det in detectors_geo:
+            getsubdetector(det).ApplyStream()
+
+        # FIXME: those calo option files
+        # Seperate Calo opts
+        # Returns a list containing all the elments common to both lists
+        # if self.getProp('UseGaussGeo'):
+        # if [det for det in ['Spd', 'Prs', 'Ecal', 'Hcal'] if det in
+        # self.getProp('DetectorGeo')['Detectors']]:  # NOQA
+        # importOptions("$GAUSSCALOROOT/options/GaussGeo-Calo.py")
+        # else:
+        # if [det for det in ['Spd', 'Prs', 'Ecal', 'Hcal'] if det in
+        # self.getProp('DetectorGeo')['Detectors']]:  # NOQA
+        # importOptions("$GAUSSCALOROOT/options/Calo.opts")
+
+        self.PrintDebugDump(detPieces, basePieces)
+
+        # No BP requested - therefore remove all elements from Geo.StreamItems
+        if ("BeamPipeOff" == getsubdetector('BeamPipe').getProp("State")):
+            from Gauss.Geometry.BeamPipe import BeamPipe
+            BeamPipe.removeAllBeamPipeElements()
+
+        # Populate the list of geometry elements
+        # in the requested conversion service
+        for el in self._listOfGeoObjects_:
+            gaussgeo.GeoItemsNames.append(el)
+
+        self.MakeItTalkToGaussino()
+
+        # Setup read-out algorithms
+        for det in detectors_geo:
+            getsubdetector(det).SetupExtraction()
+
+    def MakeItTalkToGaussino(self):
+        from Configurables import GiGaMTProxyDetectorConstructionFAC
+        from Configurables import GaussGeo, GiGaMT, ApplicationMgr
+        giga = GiGaMT()
+        giga.DetectorConstruction = "GiGaMTProxyDetectorConstructionFAC"
+        dettool = giga.addTool(GiGaMTProxyDetectorConstructionFAC,
+                               "GiGaMTProxyDetectorConstructionFAC")
+        dettool.GiGaMTGeoSvc = "GaussGeo"
+        # ApplicationMgr().ExtSvc += [GaussGeo()]
+
+    def PrintDebugDump(self, detPieces, basePieces):
+        if self.getProp("Debug"):
+            print "\nDEBUG Detector Geometry Elements:"
+            print "\nkey : detPieces[key]"
+            for key in detPieces.keys():
+                print "%s : %s" % (key, detPieces[key])
+            print "\nkey : detPieces[key]"
+
+            for key in sorted(detPieces.keys()):
+                print "%s : %s" % (key, detPieces[key])
+
+            print "\nkey : basePieces[key]"
+            for key in basePieces.keys():
+                print "%s : %s" % (key, basePieces[key])
+
+            print "\nkey : Sorted basePieces[key]"
+            for key in sorted(basePieces.keys()):
+                print "%s : %s" % (key, basePieces[key])
+
+            print "\ngeo items:"
+            for item in self._listOfGeoObjects_:
+                print "%s" % (item)
+
+            print "\ngeo items SORTED:"
+            mySortedGeoStream = self._listOfGeoObjects_[:]
+            mySortedGeoStream.sort()
+            for item in mySortedGeoStream:
+                print "%s" % (item)
diff --git a/Sim/Gauss/python/Gauss/Geometry/FT.py b/Sim/Gauss/python/Gauss/Geometry/FT.py
new file mode 100644
index 000000000..6d20aad56
--- /dev/null
+++ b/Sim/Gauss/python/Gauss/Geometry/FT.py
@@ -0,0 +1,17 @@
+from Gauss.Geometry.det_base import det_base
+from Gauss.Geometry.Helpers import subdetector
+from Gauss.Geometry.BeamPipe import BeamPipe
+
+
+@subdetector
+class FT(det_base):
+
+    def ApplyDetector(self, basePieces, detPieces):
+        BeamPipe.removeBeamPipeElements("t")
+        region = "AfterMagnetRegion"
+        if 'T' not in detPieces[region]:
+            detPieces[region] += ['T/FT']
+        if 'T/PipeInT' not in detPieces[region]:
+            detPieces[region] += ['T/PipeInT']
+        region = "DownstreamRegion"
+        detPieces[region] += ['NeutronShielding']
diff --git a/Sim/Gauss/python/Gauss/Geometry/HC.py b/Sim/Gauss/python/Gauss/Geometry/HC.py
new file mode 100644
index 000000000..b26d04a64
--- /dev/null
+++ b/Sim/Gauss/python/Gauss/Geometry/HC.py
@@ -0,0 +1,44 @@
+from Gauss.Geometry.det_base import det_base
+from Gauss.Geometry.Helpers import subdetector
+from Gaudi.Configuration import log
+from GaudiKernel import SystemOfUnits
+
+
+@subdetector
+class HC(det_base):
+
+    def ApplyDetector(self, basePieces, detPieces):
+        from Gauss.Geometry import LHCbGeo
+        from Configurables import LHCbApp
+        year = LHCbApp().getProp("DataType")
+        if year not in self.Run2DataTypes:
+            log.warning("Check your options: you have asked"
+                        "to simulate Herschel but not in %s." % year)
+            log.warning("Simulating only the LHC tunnel.")
+        # Add the non-standard pieces of the BeforeMagnet region.
+        region = 'BeforeMagnetRegion'
+        if region in detPieces:
+            pieces = ['PipeJunctionBeforeVelo', 'BeforeVelo']
+            for piece in pieces:
+                if piece in detPieces[region]:
+                    continue
+                detPieces[region] += [piece]
+        # Add the AfterMuon part of the Downstream region.
+        region = 'DownstreamRegion'
+        if region in detPieces:
+            pieces = ['AfterMuon']
+            for piece in pieces:
+                if piece in detPieces[region]:
+                    continue
+                detPieces[region] += [piece]
+        # Add the entire Upstream, BeforeUpstream, and AfterDownstream regions.
+        regions = ['UpstreamRegion', 'BeforeUpstreamRegion',
+                   'AfterDownstreamRegion']
+        for region in regions:
+            if region in detPieces:
+                detPieces[region] = []
+            LHCbGeo._listOfGeoObjects_.append("/dd/Structure/LHCb/" + region)
+
+        # Extend the world volume.
+        from Configurables import GaussGeo
+        GaussGeo().ZsizeOfWorldVolume = 300.0 * SystemOfUnits.m
diff --git a/Sim/Gauss/python/Gauss/Geometry/Helpers.py b/Sim/Gauss/python/Gauss/Geometry/Helpers.py
new file mode 100644
index 000000000..0cf71eb27
--- /dev/null
+++ b/Sim/Gauss/python/Gauss/Geometry/Helpers.py
@@ -0,0 +1,53 @@
+__subdetector_configurables = {}
+
+
+def subdetector(obj):
+    lname = obj.__name__.lower()
+    if lname in __subdetector_configurables:
+        raise RuntimeError("Class definition conflict found")
+    __subdetector_configurables[lname] = obj
+    return obj
+
+
+def getsubdetector(name):
+    lname = name.lower()
+    if lname not in __subdetector_configurables:
+        raise RuntimeError("Class definition not found: {}".format(name))
+    return __subdetector_configurables[lname]()
+
+
+def checkIncompatibleDetectors():
+    from Gauss.Geometry import LHCbGeo
+    _incompatibleDetectors = {
+        "Velo": ["Velo", "VP"],
+        "VeloPuVeto": ["PuVeto", "VP"],
+        "TT": ["TT", "UT"],
+        "Muon": ["Muon", "MuonNoM1"],
+        "MuonTorch": ["Muon", "Torch"]
+    }
+    for section in _incompatibleDetectors.keys():
+        incompatList = _incompatibleDetectors[section]
+        used_dets = LHCbGeo().getProp("DetectorGeo")['Detectors']
+        myList = [det for det in used_dets if det in incompatList]
+        if len(myList) > 1:
+            raise RuntimeError(
+                "Incompatible detectors: %s in %s section." %
+                (myList, section))
+
+
+def defineGeoBasePieces(basePieces):
+    basePieces['BeforeUpstreamRegion']  = []
+    basePieces['UpstreamRegion']        = []
+    basePieces['BeforeMagnetRegion']    = []
+    basePieces['MagnetRegion']          = []
+    basePieces['AfterMagnetRegion']     = []
+    basePieces['DownstreamRegion']      = []
+    basePieces['AfterDownstreamRegion'] = []
+
+
+__all__ = [
+    'checkIncompatibleDetectors',
+    'getsubdetector',
+    'subdetector',
+    'defineGeoBasePieces'
+]
diff --git a/Sim/Gauss/python/Gauss/Geometry/IT.py b/Sim/Gauss/python/Gauss/Geometry/IT.py
new file mode 100644
index 000000000..cc75631e1
--- /dev/null
+++ b/Sim/Gauss/python/Gauss/Geometry/IT.py
@@ -0,0 +1,28 @@
+from Gauss.Geometry.det_base import det_base
+from Gauss.Geometry.Helpers import subdetector
+from Gauss.Geometry.BeamPipe import BeamPipe
+
+
+@subdetector
+class IT(det_base):
+
+    def ApplyDetector(self, basePieces, detPieces):
+        BeamPipe.removeBeamPipeElements("t")
+        region = "AfterMagnetRegion"
+        if 'T' not in detPieces[region]:
+            detPieces[region] += ['T/IT']
+        if 'T/PipeInT' not in detPieces[region]:
+            detPieces[region] += ['T/PipeInT']
+
+    def SetupExtraction(self, slot=''):
+        from Configurables import GetTrackerHitsAlg
+        region = "AfterMagnetRegion/T"
+        det = "IT"
+        alg = GetTrackerHitsAlg(
+            'Get'+det+'Hits'+slot,
+            MCHitsLocation='MC/'+det+'/Hits',
+            CollectionName=det + 'SDet/Hits',
+            Detectors=['/dd/Structure/LHCb/' + region + '/' + det]
+        )
+        from Configurables import ApplicationMgr
+        ApplicationMgr().TopAlg += [alg]
diff --git a/Sim/Gauss/python/Gauss/Geometry/Magnet.py b/Sim/Gauss/python/Gauss/Geometry/Magnet.py
new file mode 100644
index 000000000..34bd5a6fb
--- /dev/null
+++ b/Sim/Gauss/python/Gauss/Geometry/Magnet.py
@@ -0,0 +1,44 @@
+from Gauss.Geometry.det_base import det_base
+from Gauss.Geometry.Helpers import subdetector
+
+
+@subdetector
+class Magnet(det_base):
+
+    def ApplyDetector(self, basePieces, detPieces):
+        path = "dd/Structure/LHCb/MagnetRegion/"
+        detPieces["MagnetRegion"] = ['Magnet','BcmDown']
+
+    def defineMagnetGeoField( self ):
+        from Configurables import GaussGeo
+        from Gauss.Geometry.Helpers import getsubdetector
+        # Only bother with the FIELD Geometry if simulated.
+        simDets = self.getProp('DetectorSim')['Detectors']
+        if getsubdetector("Magnet").Simulate or getsubdetector("HC").Simulate:
+            GaussGeo().FieldManager           = "GiGaFieldMgr/FieldMgr"
+            GaussGeo().addTool( GiGaFieldMgr("FieldMgr"), name="FieldMgr" )
+            GaussGeo().FieldMgr.Stepper       = "ClassicalRK4"
+            GaussGeo().FieldMgr.Global        = True
+            GaussGeo().FieldMgr.MagneticField = "GiGaMagFieldGlobal/LHCbField"
+            GaussGeo().FieldMgr.addTool( GiGaMagFieldGlobal("LHCbField"), name="LHCbField" )
+            GaussGeo().FieldMgr.LHCbField.MagneticFieldService = "MagneticFieldSvc"
+
+        if getsubdetector("HC").Simulate:
+            from Configurables import MagneticFieldSvc, MultipleMagneticFieldSvc
+            # Use MultipleMagneticFieldSvc instead of default MagneticFieldSvc.
+            GaussGeo().FieldMgr.LHCbField.MagneticFieldService = "MultipleMagneticFieldSvc"
+            # Add LHCb dipole magnet and compensators.
+            if getsubdetector("Magnet").Simulate:
+              MultipleMagneticFieldSvc().MagneticFieldServices += ["MagneticFieldSvc"]
+              importOptions("$MAGNETROOT/options/UseCompensators.py")
+            # Import LSS fields.
+            importOptions("$MAGNETROOT/options/UseTripletLeft.py")
+            importOptions("$MAGNETROOT/options/UseTripletRight.py")
+            # Scale dipoles and quadrupoles.
+            scalableMagnets = ["Q1", "Q2", "Q3", "D1", "MCBX"]
+            magnets = MultipleMagneticFieldSvc().getProp("MagneticFieldServices")
+            scale =  self.getProp("BeamMomentum") / (3.5 * SystemOfUnits.TeV )
+            for magnet in magnets:
+              if any(m in magnet for m in scalableMagnets):
+                 MagneticFieldSvc(magnet).ForcedSignedCurrentScaling = scale
+                 print "Scaling", magnet, "by", scale
diff --git a/Sim/Gauss/python/Gauss/Geometry/Muon.py b/Sim/Gauss/python/Gauss/Geometry/Muon.py
new file mode 100644
index 000000000..21df8a88d
--- /dev/null
+++ b/Sim/Gauss/python/Gauss/Geometry/Muon.py
@@ -0,0 +1,22 @@
+from Gauss.Geometry.det_base import det_base
+from Gauss.Geometry.Helpers import subdetector
+
+
+@subdetector
+class Muon(det_base):
+
+    def ApplyDetector(self, basePieces, detPieces):
+        region = 'DownstreamRegion'
+        detPieces[region] += ['Muon']
+
+    def SetupExtraction(self, slot=''):
+        from Configurables import GetTrackerHitsAlg
+        det = "Muon"
+        alg = GetTrackerHitsAlg(
+            "Get"+det+"Hits"+slot,
+            MCHitsLocation='MC/' + det + '/Hits',
+            CollectionName=det + 'SDet/Hits',
+            Detectors=['/dd/Structure/LHCb/DownstreamRegion/'+det]
+        )
+        from Configurables import ApplicationMgr
+        ApplicationMgr().TopAlg += [alg]
diff --git a/Sim/Gauss/python/Gauss/Geometry/OT.py b/Sim/Gauss/python/Gauss/Geometry/OT.py
new file mode 100644
index 000000000..e0af2bb2e
--- /dev/null
+++ b/Sim/Gauss/python/Gauss/Geometry/OT.py
@@ -0,0 +1,28 @@
+from Gauss.Geometry.det_base import det_base
+from Gauss.Geometry.Helpers import subdetector
+from Gauss.Geometry.BeamPipe import BeamPipe
+
+
+@subdetector
+class OT(det_base):
+
+    def ApplyDetector(self, basePieces, detPieces):
+        BeamPipe.removeBeamPipeElements("t")
+        region = "AfterMagnetRegion"
+        if 'T' not in detPieces[region]:
+            detPieces[region] += ['T/OT']
+        if 'T/PipeInT' not in detPieces[region]:
+            detPieces[region] += ['T/PipeInT']
+
+    def SetupExtraction(self, slot=''):
+        from Configurables import GetTrackerHitsAlg
+        region = "AfterMagnetRegion/T"
+        det = "OT"
+        alg = GetTrackerHitsAlg(
+            'Get'+det+'Hits'+slot,
+            MCHitsLocation='MC/'+det+'/Hits',
+            CollectionName=det + 'SDet/Hits',
+            Detectors=['/dd/Structure/LHCb/' + region + '/' + det]
+        )
+        from Configurables import ApplicationMgr
+        ApplicationMgr().TopAlg += [alg]
diff --git a/Sim/Gauss/python/Gauss/Geometry/PuVeto.py b/Sim/Gauss/python/Gauss/Geometry/PuVeto.py
new file mode 100644
index 000000000..8161b9b61
--- /dev/null
+++ b/Sim/Gauss/python/Gauss/Geometry/PuVeto.py
@@ -0,0 +1,9 @@
+from Gauss.Geometry.det_base import det_base
+from Gauss.Geometry.Helpers import subdetector
+
+
+@subdetector
+class PuVeto(det_base):
+
+    def ApplyDetector(self, basePieces, detPieces):
+        pass
diff --git a/Sim/Gauss/python/Gauss/Geometry/RICH.py b/Sim/Gauss/python/Gauss/Geometry/RICH.py
new file mode 100644
index 000000000..4b7de2c8f
--- /dev/null
+++ b/Sim/Gauss/python/Gauss/Geometry/RICH.py
@@ -0,0 +1,65 @@
+from Gauss.Geometry.det_base import det_base
+from Gauss.Geometry.Helpers import subdetector
+from Gauss.Geometry.BeamPipe import BeamPipe
+
+
+@subdetector
+class RICH1(det_base):
+
+    def ApplyDetector(self, basePieces, detPieces):
+        BeamPipe.removeBeamPipeElements("rich1")
+        detPieces['BeforeMagnetRegion'] += ['Rich1']
+
+    def ApplyStream(self):
+        from Gauss.Geometry import LHCbGeo
+        LHCbGeo._listOfGeoObjects_.append(
+            "/dd/Geometry/BeforeMagnetRegion/Rich1/Rich1Surfaces")
+        LHCbGeo._listOfGeoObjects_.append(
+            "/dd/Geometry/BeforeMagnetRegion/Rich1/RichHPDSurfaces")
+
+
+@subdetector
+class RICH2(det_base):
+
+    def ApplyDetector(self, basePieces, detPieces):
+        BeamPipe.removeBeamPipeElements("rich2")
+        detPieces['AfterMagnetRegion'] += ['Rich2']
+
+    def ApplyStream(self):
+        from Gauss.Geometry import LHCbGeo
+        LHCbGeo._listOfGeoObjects_.append(
+            "/dd/Geometry/AfterMagnetRegion/Rich2/Rich2Surfaces")
+
+
+@subdetector
+class RICH1PMT(det_base):
+
+    def ApplyDetector(self, basePieces, detPieces):
+        BeamPipe.removeBeamPipeElements("rich1")
+        detPieces['BeforeMagnetRegion'] += ['Rich1']
+
+    def ApplyStream(self):
+        from Configurables import GaussGeo
+        from Gauss.Geometry import LHCbGeo
+        LHCbGeo._listOfGeoObjects_.append(
+            "/dd/Geometry/BeforeMagnetRegion/Rich1/Rich1Surfaces")
+        LHCbGeo._listOfGeoObjects_.append(
+            "/dd/Geometry/BeforeMagnetRegion/Rich1/RichPMTSurfaces")
+        GaussGeo().UseAlignment = False
+        GaussGeo().AlignAllDetectors = False
+
+
+@subdetector
+class RICH2PMT(det_base):
+
+    def ApplyDetector(self, basePieces, detPieces):
+        BeamPipe.removeBeamPipeElements("rich2")
+        detPieces['AfterMagnetRegion'] += ['Rich2']
+
+    def ApplyStream(self):
+        from Configurables import GaussGeo
+        from Gauss.Geometry import LHCbGeo
+        LHCbGeo._listOfGeoObjects_.append(
+            "/dd/Geometry/AfterMagnetRegion/Rich2/Rich2Surfaces")
+        GaussGeo().UseAlignment = False
+        GaussGeo().AlignAllDetectors = False
diff --git a/Sim/Gauss/python/Gauss/Geometry/SL.py b/Sim/Gauss/python/Gauss/Geometry/SL.py
new file mode 100644
index 000000000..2e1202a20
--- /dev/null
+++ b/Sim/Gauss/python/Gauss/Geometry/SL.py
@@ -0,0 +1,16 @@
+from Gauss.Geometry.det_base import det_base
+from Gauss.Geometry.Helpers import subdetector
+from Gauss.Geometry.BeamPipe import BeamPipe
+
+
+@subdetector
+class SL(det_base):
+
+    def ApplyDetector(self, basePieces, detPieces):
+        BeamPipe.removeBeamPipeElements("t")
+        region = "AfterMagnetRegion"
+        if 'T' not in detPieces[region]:
+            detPieces[region] += ['T/SL']
+        # PSZ - line below might need to go depending on SL definition
+        if 'T/PipeInT' not in detPieces[region]:
+            detPieces[region] += ['T/PipeInT']
diff --git a/Sim/Gauss/python/Gauss/Geometry/TT.py b/Sim/Gauss/python/Gauss/Geometry/TT.py
new file mode 100644
index 000000000..e8ac6ebfd
--- /dev/null
+++ b/Sim/Gauss/python/Gauss/Geometry/TT.py
@@ -0,0 +1,25 @@
+from Gauss.Geometry.det_base import det_base
+from Gauss.Geometry.Helpers import subdetector
+from Gauss.Geometry.BeamPipe import BeamPipe
+
+
+@subdetector
+class TT(det_base):
+
+    def ApplyDetector(self, basePieces, detPieces):
+        BeamPipe.removeBeamPipeElements("tt")
+        if 'TT' not in detPieces['BeforeMagnetRegion']:
+            detPieces['BeforeMagnetRegion'] += ['TT']
+
+    def SetupExtraction(self, slot=''):
+        from Configurables import GetTrackerHitsAlg
+        region = "BeforeMagnetRegion"
+        det = "TT"
+        alg = GetTrackerHitsAlg(
+            'Get'+det+'Hits'+slot,
+            MCHitsLocation='MC/'+det+'/Hits',
+            CollectionName=det + 'SDet/Hits',
+            Detectors=['/dd/Structure/LHCb/' + region + '/' + det]
+        )
+        from Configurables import ApplicationMgr
+        ApplicationMgr().TopAlg += [alg]
diff --git a/Sim/Gauss/python/Gauss/Geometry/UT.py b/Sim/Gauss/python/Gauss/Geometry/UT.py
new file mode 100644
index 000000000..4940fa025
--- /dev/null
+++ b/Sim/Gauss/python/Gauss/Geometry/UT.py
@@ -0,0 +1,12 @@
+from Gauss.Geometry.det_base import det_base
+from Gauss.Geometry.Helpers import subdetector
+from Gauss.Geometry.BeamPipe import BeamPipe
+
+
+@subdetector
+class UT(det_base):
+
+    def ApplyDetector(self, basePieces, detPieces):
+        BeamPipe.removeBeamPipeElements("ut")
+        if 'UT' not in detPieces['BeforeMagnetRegion']:
+            detPieces['BeforeMagnetRegion'] += ['UT']
diff --git a/Sim/Gauss/python/Gauss/Geometry/VP.py b/Sim/Gauss/python/Gauss/Geometry/VP.py
new file mode 100644
index 000000000..b4a3c1ab6
--- /dev/null
+++ b/Sim/Gauss/python/Gauss/Geometry/VP.py
@@ -0,0 +1,12 @@
+from Gauss.Geometry.det_base import det_base
+from Gauss.Geometry.Helpers import subdetector
+from Gauss.Geometry.BeamPipe import BeamPipe
+
+
+@subdetector
+class VP(det_base):
+
+    def ApplyDetector(self, basePieces, detPieces):
+        BeamPipe.removeBeamPipeElements("velo")
+        if 'BeforeMagnetRegion' in detPieces:
+            detPieces['BeforeMagnetRegion'] += ['VP']
diff --git a/Sim/Gauss/python/Gauss/Geometry/Velo.py b/Sim/Gauss/python/Gauss/Geometry/Velo.py
new file mode 100644
index 000000000..a3541e83f
--- /dev/null
+++ b/Sim/Gauss/python/Gauss/Geometry/Velo.py
@@ -0,0 +1,155 @@
+from Gauss.Geometry.det_base import det_base
+from Gaudi.Configuration import log
+from Gaudi.Configuration import Configurable
+from Gauss.Geometry.Helpers import subdetector
+
+
+@subdetector
+class Velo(det_base):
+
+    __slots__ = {
+        "State": 'BeamPipeOn',
+    }
+
+    def __init__(self, name=Configurable.DefaultName, **kwargs):
+        kwargs["name"] = name
+        super(det_base, self).__init__(*(), **kwargs)
+        self.initialize()
+
+    @staticmethod
+    def checkVeloDDDB():
+        """
+        Check if the Velo geometry is compatible with the chosen tags
+        """
+        from Configurables import LHCbApp
+        from DetCond.Configuration import CondDB
+        # set validity limits for  Velo geometry
+        # first postMC09 Velo geometry
+        GTagLimit1 = "head-20091120"
+        GTagLimit1 = GTagLimit1.split('-')[1].strip()
+        VeloLTagLimit1 = "velo-20091116"
+        VeloLTagLimit1 = VeloLTagLimit1.split('-')[1].strip()
+        # Thomas L. Velo geometry
+        GTagLimit2 = "head-20100119"
+        GTagLimit2 = GTagLimit2.split('-')[1].strip()
+        VeloLTagLimit2 = "velo-20100114"
+        VeloLTagLimit2 = VeloLTagLimit2.split('-')[1].strip()
+
+        # DDDB global tag used
+        DDDBDate = LHCbApp().DDDBtag
+        DDDBDate = DDDBDate.split('-')
+
+        # Check if DDDB tag has a regular format
+        # (instead of e.g. a user git branch)
+        if len(DDDBDate) > 1:
+            DDDBDate = DDDBDate[1].strip()
+            if DDDBDate.isdigit():
+                # check if/which local tag is used for Velo
+                cdb = CondDB()
+                cdbVeloDate = 0
+                for p in cdb.LocalTags:
+                    if p == "DDDB":
+                        taglist = list(cdb.LocalTags[p])
+                        for ltag in taglist:
+                            if ltag.find("velo") != -1:
+                                cdbVeloDate = ltag.split('-')[1].strip()
+
+                # Put this here rather than as an argument
+                VeloPostMC09 = 0
+                # check if the selected tags require
+                # one of the postMC09 Velo geometries
+                if (DDDBDate >= GTagLimit1) or (cdbVeloDate >= VeloLTagLimit1):
+                    VeloPostMC09 = 1
+                if (DDDBDate >= GTagLimit2) or (cdbVeloDate >= VeloLTagLimit2):
+                    VeloPostMC09 = 2
+
+                return VeloPostMC09
+
+        log.warning("DDDB tag not parsable as date. "
+                    "Using post-MC09 velo geometry : %s" % (DDDBDate))
+        return 2
+
+    def veloMisAlignGeometry(self, VeloPostMC09):
+
+        """
+        File containing the list of detector element to explicitely set
+        to have misalignement in the VELO.
+        """
+        # remove Automatically included detector elements
+        from Gauss.Geometry.BeamPipe import BeamPipe
+        BeamPipe.removeBeamPipeElements("velo")
+
+        from Gauss.Geometry import LHCbGeo
+        go = LHCbGeo._listOfGeoObjects_
+
+        if "/dd/Structure/LHCb/BeforeMagnetRegion/Velo" in go:
+            go.remove(
+                "/dd/Structure/LHCb/BeforeMagnetRegion/Velo")
+
+        go += ["/dd/Structure/LHCb/BeforeMagnetRegion/Velo/VeloLeft/ModulePU00"]
+        go += ["/dd/Structure/LHCb/BeforeMagnetRegion/Velo/VeloLeft/ModulePU02"]
+        go += ["/dd/Structure/LHCb/BeforeMagnetRegion/Velo/VeloRight/ModulePU01"]  # NOQA
+        go += ["/dd/Structure/LHCb/BeforeMagnetRegion/Velo/VeloRight/ModulePU03"]  # NOQA
+
+        txt = "/dd/Structure/LHCb/BeforeMagnetRegion/Velo/VeloLeft/ModuleXX"
+        import math
+        for i in range(42):
+            nr = str(i)
+            if len(nr) == 1:
+                nr = '0'+str(i)
+            temp1 = txt.replace('XX', nr)
+            if math.modf(float(nr)/2.)[0] > 0.1:
+                temp1 = temp1.replace('Left', 'Right')
+            go += [temp1]
+
+        go += ["/dd/Structure/LHCb/BeforeMagnetRegion/Velo/DownStreamWakeFieldCone"]  # NOQA
+        go += ["/dd/Structure/LHCb/BeforeMagnetRegion/Velo/UpStreamWakeFieldCone"]  # NOQA
+        if VeloPostMC09 == 1:
+            # description postMC09 of Velo (head-20091120),
+            # problem with Velo Tank simulation
+            go += ["/dd/Structure/LHCb/BeforeMagnetRegion/Velo/VacTank"]
+            go += ["/dd/Structure/LHCb/BeforeMagnetRegion/Velo/DownstreamPipeSections"]  # NOQA
+            go += [ "/dd/Structure/LHCb/BeforeMagnetRegion/Velo/UpstreamPipeSections"]  # NOQA
+        elif VeloPostMC09 == 2:
+            # Thomas L. newer description postMC09 of Velo
+            # --- Velo Right
+            go += ["/dd/Structure/LHCb/BeforeMagnetRegion/Velo/VeloRight/RFBoxRight"]  # NOQA
+            go += ["/dd/Structure/LHCb/BeforeMagnetRegion/Velo/VeloRight/DetSupportRight"]  # NOQA
+            go += ["/dd/Structure/LHCb/BeforeMagnetRegion/Velo/VeloRight/ConstSysRight"]  # NOQA
+            # --- Velo Left
+            go += ["/dd/Structure/LHCb/BeforeMagnetRegion/Velo/VeloLeft/RFBoxLeft"]  # NOQA
+            go += ["/dd/Structure/LHCb/BeforeMagnetRegion/Velo/VeloLeft/DetSupportLeft"]  # NOQA
+            go += ["/dd/Structure/LHCb/BeforeMagnetRegion/Velo/VeloLeft/ConstSysLeft"]  # NOQA
+            # --- Velo
+            go += ["/dd/Structure/LHCb/BeforeMagnetRegion/Velo/DownstreamPipeSections"]  # NOQA
+            go += ["/dd/Structure/LHCb/BeforeMagnetRegion/Velo/UpstreamPipeSections"]  # NOQA
+            go += ["/dd/Structure/LHCb/BeforeMagnetRegion/Velo/VacTank"]
+        else:
+            go += ["/dd/Structure/LHCb/BeforeMagnetRegion/Velo/UpStreamVacTank"]
+            go += ["/dd/Structure/LHCb/BeforeMagnetRegion/Velo/DownStreamVacTank"]  # NOQA
+
+        go += ["/dd/Structure/LHCb/BeforeMagnetRegion/Velo/VeloRight/RFFoilRight"]  # NOQA
+        go += ["/dd/Structure/LHCb/BeforeMagnetRegion/Velo/VeloLeft/RFFoilLeft"]
+
+    def ApplyDetector(self, basePieces, detPieces):
+        VeloP = Velo.checkVeloDDDB()
+        if VeloP == 1 or VeloP == 2:
+            basePieces['BeforeMagnetRegion'] = []
+
+        # Also sort out mis-alignment
+        VeloP = Velo.checkVeloDDDB()
+        # No need to misalign if only PuVeto exits - check me PSZ.
+        self.veloMisAlignGeometry(VeloP)  # To misalign VELO
+
+    def SetupExtraction(self, slot=''):
+        from Configurables import GetTrackerHitsAlg
+        region = "BeforeMagnetRegion"
+        det = "Velo"
+        alg = GetTrackerHitsAlg(
+            'Get'+det+'Hits'+slot,
+            MCHitsLocation='MC/'+det+'/Hits',
+            CollectionName=det + 'SDet/Hits',
+            Detectors=['/dd/Structure/LHCb/' + region + '/' + det]
+        )
+        from Configurables import ApplicationMgr
+        ApplicationMgr().TopAlg += [alg]
diff --git a/Sim/Gauss/python/Gauss/Geometry/__init__.py b/Sim/Gauss/python/Gauss/Geometry/__init__.py
new file mode 100644
index 000000000..4d1ef0029
--- /dev/null
+++ b/Sim/Gauss/python/Gauss/Geometry/__init__.py
@@ -0,0 +1,20 @@
+from Gauss.Geometry.Configuration import LHCbGeo
+from Gauss.Geometry.BeamPipe import BeamPipe
+from Gauss.Geometry.Velo import Velo
+from Gauss.Geometry.PuVeto import PuVeto
+from Gauss.Geometry.CALO import *
+from Gauss.Geometry.RICH import *
+from Gauss.Geometry.Velo import *
+from Gauss.Geometry.VP import *
+from Gauss.Geometry.FT import *
+from Gauss.Geometry.TT import *
+from Gauss.Geometry.OT import *
+from Gauss.Geometry.IT import *
+from Gauss.Geometry.UT import *
+from Gauss.Geometry.Magnet import *
+from Gauss.Geometry.Muon import *
+from Gauss.Geometry.HC import *
+
+__all__ = [
+    'LHCbGeo', 'BeamPipe'
+]
diff --git a/Sim/Gauss/python/Gauss/Geometry/det_base.py b/Sim/Gauss/python/Gauss/Geometry/det_base.py
new file mode 100644
index 000000000..65a89ed15
--- /dev/null
+++ b/Sim/Gauss/python/Gauss/Geometry/det_base.py
@@ -0,0 +1,67 @@
+from Configurables import LHCbConfigurableUser
+from Gaudi.Configuration import Configurable
+
+
+class det_base(LHCbConfigurableUser):
+
+    """Base class for all subdetector configurables. These configurables should
+    not instantiate everything during the apply configuration call to allow
+    for a more fine-grained activation. Maybe ..."""
+
+    __slots__ = {
+        "active": False,
+        "simulate": False,
+        "monitor": False
+    }
+
+    @property
+    def Active(self):
+        return self.getProp('active')
+
+    @property
+    def Simulate(self):
+        return self.getProp('simulate')
+
+    @property
+    def Monitor(self):
+        return self.getProp('monitor')
+
+    @Active.setter
+    def Active(self, value):
+        self.active = value
+
+    @Simulate.setter
+    def Simulate(self, value):
+        if not self.Active:
+            raise RuntimeError(
+                "Setting {} to be simulated but not active".format(self.name()))
+        self.simulate = value
+
+    @Monitor.setter
+    def Monitor(self, value):
+        if not self.Active or not self.Simulate:
+            raise RuntimeError(
+                "Setting {} to be monitored but not active"
+                "or simulated".format(self.name()))
+        self.monitor = value
+
+    def __init__(self, name=Configurable.DefaultName, **kwargs):
+        kwargs["name"] = name
+        apply(super(LHCbConfigurableUser, self).__init__, (), kwargs)
+        self.initialize()
+
+    def __apply_configuration__(self):
+        if self.getProp("Active"):
+            self.impl_configuration()
+
+    def impl_configuration(self):
+        pass
+
+    def ApplyDetector(self, basePieces, detPieces):
+        pass
+
+    def ApplyStream(self):
+        pass
+
+    def SetupExtraction(self, slot=''):
+        pass
diff --git a/Sim/Gauss/python/Gauss/Physics.py b/Sim/Gauss/python/Gauss/Physics.py
index a84eaeeec..54e3888de 100644
--- a/Sim/Gauss/python/Gauss/Physics.py
+++ b/Sim/Gauss/python/Gauss/Physics.py
@@ -22,7 +22,8 @@ class G4Physics(LHCbConfigurableUser):
         "LHCbPhys": False,
         "Other": '',
         "DeltaRays": True,
-        "RichUpgradeConfig": False}
+        "RichUpgradeConfig": False
+    }
 
     _propertyDocDct = {
         'Em': """Electromagnetic physics used. Choices:
diff --git a/Sim/Gauss/python/Gauss/Utilities.py b/Sim/Gauss/python/Gauss/Utilities.py
new file mode 100644
index 000000000..bd5216900
--- /dev/null
+++ b/Sim/Gauss/python/Gauss/Utilities.py
@@ -0,0 +1,57 @@
+
+class HelperBase:
+
+    def slotName(self, slot):
+        name = slot
+        if slot == '':
+            name = "Main"
+        return name
+
+    def isGaussMP(self):
+        import argparse
+        parser = argparse.ArgumentParser(description='Hello')
+
+        parser.add_argument("--ncpus", action="store", type=int, default=0)
+        args = parser.parse_known_args()
+        return args[0].ncpus != 0
+
+    ##
+    # Helper functions for spill-over
+    def slot_(self, slot):
+        if slot != '':
+            return slot + '/'
+        return slot
+
+    ##
+    def setTrackersHitsProperties(self, alg, det, slot, dd):
+        alg.MCHitsLocation = '/Event/' + \
+            self.slot_(slot) + 'MC/' + det + '/Hits'
+        if det == 'PuVeto':
+            det = 'VeloPu'
+        alg.CollectionName = det + 'SDet/Hits'
+        alg.Detectors = ['/dd/Structure/LHCb/'+dd]
+
+    ##
+    def evtMax(self):
+        from Configurables import LHCbApp
+        return LHCbApp().evtMax()
+
+    ##
+    def eventType(self):
+        from Configurables import Generation
+        evtType = ''
+        if Generation("Generation").isPropertySet("EventType"):
+            evtType = str(Generation("Generation").EventType)
+        return evtType
+
+    def setLHCbAppDetectors(self):
+        from Configurables import LHCbApp
+        # If detectors set in LHCbApp then use those
+        if hasattr(LHCbApp(), "Detectors"):
+            if not LHCbApp().Detectors:
+                LHCbApp().Detectors = self.getProp("DetectorGeo")["Detectors"]
+            else:
+                log.warning(
+                    "Value of 'LHCbApp().Detectors' already set, using that value: %s" %
+                    (LHCbApp().Detectors))
+        return
diff --git a/Sim/GaussGeo/CMakeLists.txt b/Sim/GaussGeo/CMakeLists.txt
index 253dd9252..2f1c1b360 100644
--- a/Sim/GaussGeo/CMakeLists.txt
+++ b/Sim/GaussGeo/CMakeLists.txt
@@ -4,13 +4,15 @@
 gaudi_subdir(GaussGeo v1r0)
 
 gaudi_depends_on_subdirs(Det/DetDesc
-                         Sim/GiGa)
+                         Sim/GiGaMTGeo)
 
 find_package(Boost)
 find_package(CLHEP)
 include_directories(SYSTEM ${Boost_INCLUDE_DIRS} ${CLHEP_INCLUDE_DIRS} ${Geant4_INCLUDE_DIRS})
+FindG4libs(digits_hits event geometry global graphics_reps materials
+           particles processes run tracking track)
 
 gaudi_add_module(GaussGeo
                  src/component/*.cpp
-                 INCLUDE_DIRS Tools/ClhepTools
-                 LINK_LIBRARIES DetDescLib GiGaLib)
+                 INCLUDE_DIRS Tools/ClhepTools GiGaMTGeo
+                 LINK_LIBRARIES DetDescLib ${GEANT4_LIBS})
diff --git a/Sim/GaussGeo/GaussGeo/IGaussGeo.h b/Sim/GaussGeo/GaussGeo/IGaussGeo.h
index 9567af0c4..65a9a3e64 100644
--- a/Sim/GaussGeo/GaussGeo/IGaussGeo.h
+++ b/Sim/GaussGeo/GaussGeo/IGaussGeo.h
@@ -1,5 +1,4 @@
-#ifndef  GAUSSGEO_IGAUSSGEO_H_
-#define  GAUSSGEO_IGAUSSGEO_H_
+#pragma once
 
 // GaudiKernel
 #include "GaudiKernel/IInterface.h"
@@ -20,5 +19,3 @@ class IGaussGeo : virtual public IInterface {
   // Retrieve the pointer to the G4 geometry tree root
   virtual G4VPhysicalVolume* world() = 0;
 };
-
-#endif  // GAUSSGEO_IGAUSSGEO_H_
diff --git a/Sim/GaussGeo/src/component/GaussGeo.cpp b/Sim/GaussGeo/src/component/GaussGeo.cpp
index 3479af040..abbfff963 100644
--- a/Sim/GaussGeo/src/component/GaussGeo.cpp
+++ b/Sim/GaussGeo/src/component/GaussGeo.cpp
@@ -60,10 +60,11 @@
 #include "Geant4/G4SolidStore.hh"
 
 // GiGa
-#include "GiGa/IGiGaSensDet.h"
-#include "GiGa/IGiGaMagField.h"
-#include "GiGa/IGiGaFieldMgr.h"
-#include "GiGa/IGDMLReader.h"
+// FIXME: Need to integrate this
+//#include "GiGaMTFactories/GiGaMTG4SensDetFactory.h"
+//#include "GiGa/IGiGaMagField.h"
+//#include "GiGa/IGiGaFieldMgr.h"
+//#include "GiGa/IGDMLReader.h"
 
 // Local unclides
 #include "GaussGeo.h"
@@ -93,9 +94,9 @@ GaussGeo::GaussGeo(const std::string& service_name, ISvcLocator* service_locator
     m_data_selector(),
     m_world_root(nullptr),
     m_mag_field_mgr(""),
-    m_sensitive_detectors(),
-    m_magnetic_fields(),
-    m_mag_field_managers(),
+    //m_sensitive_detectors(),
+    //m_magnetic_fields(),
+    //m_mag_field_managers(),
     m_use_alignment(false),
     m_align_all(false),
     m_align_dets_names(),
@@ -176,30 +177,30 @@ StatusCode GaussGeo::initialize() {
     warning() << "Special run for material budget calculation requested!" << endmsg;
   }
 
-  // Retrieve GDMLReader tools
-  {
-    StatusCode sc = StatusCode::SUCCESS;
-    m_gdml_readers.clear();
-    for (const auto& reader : m_gdml_readers_names) {
-      if (reader == "") {
-        continue;
-      }
+  // FIXME: Retrieve GDMLReader tools
+  //{
+    //StatusCode sc = StatusCode::SUCCESS;
+    //m_gdml_readers.clear();
+    //for (const auto& reader : m_gdml_readers_names) {
+      //if (reader == "") {
+        //continue;
+      //}
 
-      IGDMLReader* gdml_tool = nullptr;
-      sc = toolSvc()->retrieveTool("GDMLReader/" + reader, gdml_tool, this);
-      if (sc.isFailure()) {
-        return reportError("Failed to retrieve a GDMLReader tool!", sc);
-      }
+      //IGDMLReader* gdml_tool = nullptr;
+      //sc = toolSvc()->retrieveTool("GDMLReader/" + reader, gdml_tool, this);
+      //if (sc.isFailure()) {
+        //return reportError("Failed to retrieve a GDMLReader tool!", sc);
+      //}
 
-      if (gdml_tool != nullptr) {
-        m_gdml_readers.push_back(gdml_tool);
-      }
-    }
+      //if (gdml_tool != nullptr) {
+        //m_gdml_readers.push_back(gdml_tool);
+      //}
+    //}
 
-    if (!m_gdml_readers.empty()) {
-      info() << "Retrieved " << m_gdml_readers.size() << " GDMLReader tools..." << endmsg;
-    }
-  }
+    //if (!m_gdml_readers.empty()) {
+      //info() << "Retrieved " << m_gdml_readers.size() << " GDMLReader tools..." << endmsg;
+    //}
+  //}
 
   // Print out names of geo items for debugging
   if (outputLevel() == MSG::VERBOSE) {
@@ -264,32 +265,30 @@ StatusCode GaussGeo::finalize() {
     verbose() << m_str_prefix << "=> Service Finilization Start" << endmsg;
   }
 
-  // Finalize all sensitive detectors
-  for (auto& idet : m_sensitive_detectors) {
-    IAlgTool* det = idet;
-    if (det != nullptr && toolSvc() != nullptr) {
-      toolSvc()->releaseTool(det);
-    }
-  }
-  m_sensitive_detectors.clear();
+  //// Finalize all sensitive detectors
+  //for (auto& idet : mmap_sensdet_to_lvols) {
+    //if(idet.first){
+      //idet.first->release();
+    //}
+  //}
 
   // Finalize magnetic field objects
-  for (auto& imf : m_magnetic_fields) {
-    IAlgTool* mf = imf;
-    if (mf != nullptr && toolSvc() != nullptr) {
-      toolSvc()->releaseTool(mf);
-    }
-  }
-  m_magnetic_fields.clear();
+  //for (auto& imf : m_magnetic_fields) {
+    //IAlgTool* mf = imf;
+    //if (mf != nullptr && toolSvc() != nullptr) {
+      //toolSvc()->releaseTool(mf);
+    //}
+  //}
+  //m_magnetic_fields.clear();
 
   // Finalize magnetic field manager objects
-  for (auto& imfmgr : m_mag_field_managers) {
-    IAlgTool* mfmgr = imfmgr;
-    if (mfmgr != nullptr && toolSvc() != nullptr) {
-      toolSvc()->releaseTool(mfmgr);
-    }
-  }
-  m_mag_field_managers.clear();
+  //for (auto& imfmgr : m_mag_field_managers) {
+    //IAlgTool* mfmgr = imfmgr;
+    //if (mfmgr != nullptr && toolSvc() != nullptr) {
+      //toolSvc()->releaseTool(mfmgr);
+    //}
+  //}
+  //m_mag_field_managers.clear();
 
   // Clear assembly store
   GaussGeoAssemblyStore::store()->clear();
@@ -351,8 +350,8 @@ StatusCode GaussGeo::queryInterface(const InterfaceID& iid, void** ppi) {
     return StatusCode::FAILURE;
   }
 
-  if (iid == IGiGaGeoSrc::interfaceID()) {
-    *ppi = static_cast<IGiGaGeoSrc*>(this);
+  if (iid == IGiGaMTGeoSvc::interfaceID()) {
+    *ppi = static_cast<IGiGaMTGeoSvc*>(this);
   } else if (iid == IIncidentListener::interfaceID()) {
     *ppi = static_cast<IIncidentListener*>(this);
   } else if (iid == IService::interfaceID()) {
@@ -504,7 +503,7 @@ StatusCode GaussGeo::convertDetectorElementObject(DataObject* object) {
     return reportError("Failed to convert logical volume " + lvolume->name());
   }
 
-  G4VPhysicalVolume* pvolume = world();
+  G4VPhysicalVolume* pvolume = constructWorld();
   if (pvolume == nullptr) {
     return reportError("G4WorldPV is not available!");
   }
@@ -639,40 +638,29 @@ StatusCode GaussGeo::convertLVolumeObject(DataObject* object) {
 
   // Sensitivity
   if (!lvolume->sdName().empty()) {
-    if (g4_volume->GetSensitiveDetector() == nullptr) {
-      IGiGaSensDet* sens_det = nullptr;
-      StatusCode sc = sensitive(lvolume->sdName(), sens_det);
-
-      if (sc.isFailure() || sens_det == nullptr) {
-        return reportError("Failed to create SensDet", sc);
-      }
-
-      // Set sensitive detector
-      g4_volume->SetSensitiveDetector(sens_det);
-    } else {
-      warning() << "SensDet is already defined!'" << endmsg;
-    }
+    register_sensitive(lvolume->sdName(), g4_volume);
   }
 
   // Magnetic field
-  if (!lvolume->mfName().empty()) {
-    IGiGaFieldMgr* fmanager = nullptr;
-    StatusCode sc = fieldMgr(lvolume->mfName(), fmanager);
-    if (sc.isFailure() || fmanager == nullptr) {
-      return reportError("Failed to create FieldMgr!", sc);
-    }
-
-    if (fmanager->fieldMgr() == nullptr) {
-      return reportError("FieldMgr is invalid!");
-    }
-
-    if (fmanager->global()) {
-      return reportError("FieldMgr is 'global'!");
-    }
-
-    // Set magnetic field manager
-    g4_volume->SetFieldManager(fmanager->fieldMgr(), false);
-  }
+  // FIXME: Field stuff
+  //if (!lvolume->mfName().empty()) {
+    //IGiGaFieldMgr* fmanager = nullptr;
+    //StatusCode sc = fieldMgr(lvolume->mfName(), fmanager);
+    //if (sc.isFailure() || fmanager == nullptr) {
+      //return reportError("Failed to create FieldMgr!", sc);
+    //}
+
+    //if (fmanager->fieldMgr() == nullptr) {
+      //return reportError("FieldMgr is invalid!");
+    //}
+
+    //if (fmanager->global()) {
+      //return reportError("FieldMgr is 'global'!");
+    //}
+
+    //// Set magnetic field manager
+    //g4_volume->SetFieldManager(fmanager->fieldMgr(), false);
+  //}
 
   // Check the G4 static store
   if (GaussGeoVolumeUtils::findLVolume(lvolume->name()) != nullptr) {
@@ -1466,9 +1454,9 @@ G4VSolid* GaussGeo::solidBoolToG4Solid(const SolidBoolean* solid_bool) {
 //=============================================================================
 // Retrieve the pointer to G4 geometry tree root
 //=============================================================================
-G4VPhysicalVolume* GaussGeo::world() {
+G4VPhysicalVolume* GaussGeo::constructWorld() {
   if (outputLevel() == MSG::VERBOSE) {
-    verbose() << m_str_prefix << "world()" << endmsg;
+    verbose() << m_str_prefix << "constructWorld()" << endmsg;
   }
 
   if (m_world_root != nullptr) {
@@ -1491,72 +1479,64 @@ G4VPhysicalVolume* GaussGeo::world() {
   m_world_root = new G4PVPlacement(nullptr, CLHEP::Hep3Vector(), m_world_pv_name, world_logical_volume, 0, false, 0, m_performOverlapCheck);
 
   // Import GDML geometry
-  for (const auto& reader : m_gdml_readers) {
-    reader->import(m_world_root);
-  }
-
-  if (!m_mag_field_mgr.empty()) {
-    IGiGaFieldMgr* giga_fmanager = nullptr;
-    StatusCode sc = fieldMgr(m_mag_field_mgr, giga_fmanager);
-    if (sc.isFailure() || giga_fmanager == nullptr) {
-      error() << "Faild to construct GiGaFieldManager '" << m_mag_field_mgr << "'" << endmsg;
-      return nullptr;
-    }
-
-    if (!giga_fmanager->global()) {
-      error() << "GiGaFieldManager '" + m_mag_field_mgr + "' is not 'global'" << endmsg;
-      return nullptr;
-    }
-
-    if (giga_fmanager->fieldMgr() ==  nullptr) {
-      error() << "GiGaFieldManager '" + m_mag_field_mgr + "' has invalid G4FieldManager" << endmsg;
-      return nullptr;
-    }
-
-    if (giga_fmanager->field() == nullptr) {
-      error() << "GiGaFieldManager '" + m_mag_field_mgr + "' has invalid G4MagneticField" << endmsg;
-      return nullptr;
-    }
-
-    if (giga_fmanager->stepper() == nullptr) {
-      error() << "GiGaFieldManager '" + m_mag_field_mgr + "' has invalid G4MagIntegratorStepper" << endmsg;
-      return nullptr;
-    }
-
-    // Additional check
-    G4TransportationManager* trans_manager = G4TransportationManager::GetTransportationManager();
-    if (trans_manager == nullptr) {
-      error() << "G4TransportationMgr is invalid!" << endmsg;
-      return nullptr;
-    }
-
-    if (trans_manager->GetFieldManager() != giga_fmanager->fieldMgr()) {
-      error() << "Mismatch in the G4FieldManager!" << endmsg;
-      return nullptr;
-    }
-
-    info() << "Global 'Field Manager' is set to '" << objectTypeName(giga_fmanager)
-           << "/" << giga_fmanager->name() << "'" << endmsg;
-    info() << "Global 'G4Field Manager' is set to '" << objectTypeName(giga_fmanager->fieldMgr()) << "'" << endmsg;
-    info() << "Global 'G4MagneticField' is set to '" << objectTypeName(giga_fmanager->field()) << "'" << endmsg;
-    info() << "Global 'G4MagIntegratorStepper' is set to '" << objectTypeName(giga_fmanager->stepper()) << "'" << endmsg;
-  } else {
-    warning() << "Magnetic Field was not requested to be loaded" << endmsg;
-  }
+  // FIXME
+  //for (const auto& reader : m_gdml_readers) {
+    //reader->import(m_world_root);
+  //}
+
+  //FIXME Field stuff
+  //if (!m_mag_field_mgr.empty()) {
+    //IGiGaFieldMgr* giga_fmanager = nullptr;
+    //StatusCode sc = fieldMgr(m_mag_field_mgr, giga_fmanager);
+    //if (sc.isFailure() || giga_fmanager == nullptr) {
+      //error() << "Faild to construct GiGaFieldManager '" << m_mag_field_mgr << "'" << endmsg;
+      //return nullptr;
+    //}
+
+    //if (!giga_fmanager->global()) {
+      //error() << "GiGaFieldManager '" + m_mag_field_mgr + "' is not 'global'" << endmsg;
+      //return nullptr;
+    //}
+
+    //if (giga_fmanager->fieldMgr() ==  nullptr) {
+      //error() << "GiGaFieldManager '" + m_mag_field_mgr + "' has invalid G4FieldManager" << endmsg;
+      //return nullptr;
+    //}
+
+    //if (giga_fmanager->field() == nullptr) {
+      //error() << "GiGaFieldManager '" + m_mag_field_mgr + "' has invalid G4MagneticField" << endmsg;
+      //return nullptr;
+    //}
+
+    //if (giga_fmanager->stepper() == nullptr) {
+      //error() << "GiGaFieldManager '" + m_mag_field_mgr + "' has invalid G4MagIntegratorStepper" << endmsg;
+      //return nullptr;
+    //}
+
+    //// Additional check
+    //G4TransportationManager* trans_manager = G4TransportationManager::GetTransportationManager();
+    //if (trans_manager == nullptr) {
+      //error() << "G4TransportationMgr is invalid!" << endmsg;
+      //return nullptr;
+    //}
+
+    //if (trans_manager->GetFieldManager() != giga_fmanager->fieldMgr()) {
+      //error() << "Mismatch in the G4FieldManager!" << endmsg;
+      //return nullptr;
+    //}
+
+    //info() << "Global 'Field Manager' is set to '" << objectTypeName(giga_fmanager)
+           //<< "/" << giga_fmanager->name() << "'" << endmsg;
+    //info() << "Global 'G4Field Manager' is set to '" << objectTypeName(giga_fmanager->fieldMgr()) << "'" << endmsg;
+    //info() << "Global 'G4MagneticField' is set to '" << objectTypeName(giga_fmanager->field()) << "'" << endmsg;
+    //info() << "Global 'G4MagIntegratorStepper' is set to '" << objectTypeName(giga_fmanager->stepper()) << "'" << endmsg;
+  //} else {
+    //warning() << "Magnetic Field was not requested to be loaded" << endmsg;
+  //}
 
   return m_world_root;
 }
 
-//=============================================================================
-// Retrieve the pointer to G4 geometry tree root
-// Obsolete method, for compatibility with IGiGaGeoSrc interface
-//=============================================================================
-G4VPhysicalVolume* GaussGeo::G4WorldPV() {
-  warning() << "G4WorldPV() is obsolete, use world()!" << endmsg;
-
-  return world();
-}
-
 //=============================================================================
 // Create a new G4LogicalVolume
 //=============================================================================
@@ -1585,14 +1565,7 @@ G4LogicalVolume* GaussGeo::createG4LVolume(G4VSolid* g4_solid, G4Material* g4_ma
 
   // Look for global material budget counter
   if (!m_budget.empty()) {
-    IGiGaSensDet* budget = 0;
-    StatusCode sc = sensitive(m_budget, budget);
-
-    if (sc.isFailure() || budget == nullptr) {
-      error() << "Failed to get Material Budget '" << m_budget << "'" << endmsg;
-    } else {
-      g4_lvolume->SetSensitiveDetector(budget);
-    }
+    register_sensitive(m_budget, g4_lvolume);
   }
 
   if (outputLevel() == MSG::VERBOSE) {
@@ -1753,69 +1726,104 @@ StatusCode GaussGeo::installVolume(G4LogicalVolume* g4_volume, const std::string
 //=============================================================================
 // Instantiate a Sensitive Detector object
 //=============================================================================
-StatusCode GaussGeo::sensitive(const std::string& name, IGiGaSensDet*& detector) {
-  if (outputLevel() == MSG::VERBOSE) {
-    prefixIn();
-    verbose() << m_str_prefix << "=> sensitive(): " << name << endmsg;
+StatusCode GaussGeo::register_sensitive(const std::string& name, G4LogicalVolume* vol) {
+  // First check if we have already obtained the sensitive detector factory for the
+  // provided name.
+  auto it = mmap_name_to_sensdetfac.find(name);
+  if(it == std::end(mmap_name_to_sensdetfac)){
+    mmap_name_to_sensdetfac[name] = nullptr;
+    getTool(name, mmap_name_to_sensdetfac[name], this);
+    // Check if successful
+    if(!mmap_name_to_sensdetfac[name]){
+      warning() << "Could not retrieve sensitive detector " << name << "." << endmsg;
+      warning() << "What do we say to the geo service? Not today ..." << endmsg;
+    }
   }
-
-  // Reset the output value
-  detector = nullptr;
-
-  // Locate the detector
-  detector = getTool(name, detector, this);
-  if (detector == nullptr) {
-    return reportError("Failed to locate Sensitive Detector '" + name + "'");
+  // Now fill the map of identified sensitive detectors to volumes
+  if(auto & sensdet = mmap_name_to_sensdetfac[name]; sensdet){
+    if(mmap_sensdet_to_lvols.find(sensdet) == std::end(mmap_sensdet_to_lvols)){
+      mmap_sensdet_to_lvols[sensdet] = {};
+    }
+    mmap_sensdet_to_lvols[sensdet].insert(vol);
   }
+  return StatusCode::SUCCESS;
+}
 
-  // Inform G4 sensitive detector manager
-  if (std::find(m_sensitive_detectors.begin(), m_sensitive_detectors.end(), detector) == m_sensitive_detectors.end()) {
-    G4SDManager* sd_manager = G4SDManager::GetSDMpointer();
-    if (sd_manager == nullptr) {
-      return reportError("Failed to locate G4SDManager!");
+void GaussGeo::constructSDandField() {
+  auto sdmanager = G4SDManager::GetSDMpointer();
+  for(auto & [sensdetfac, vols]:  mmap_sensdet_to_lvols){
+    debug() << "Assigning " << sensdetfac->name() << " to " << vols.size() << " logical volumes" << endmsg;
+    auto sensdet = sensdetfac->construct();
+    sdmanager->AddNewDetector(sensdet);
+    for(auto * vol: vols){
+      vol->SetSensitiveDetector(sensdet);
     }
-    sd_manager->AddNewDetector(detector);
   }
+}
 
-  // Keep a local copy
-  m_sensitive_detectors.push_back(detector);
+//StatusCode GaussGeo::sensitive(const std::string& name, IGiGaSensDet*& detector) {
+  //if (outputLevel() == MSG::VERBOSE) {
+    //prefixIn();
+    //verbose() << m_str_prefix << "=> sensitive(): " << name << endmsg;
+  //}
 
-  if (outputLevel() == MSG::VERBOSE) {
-    verbose() << m_str_prefix << "<= sensitive()" << endmsg;
-    prefixOut();
-  }
+  //// Reset the output value
+  //detector = nullptr;
 
-  return StatusCode::SUCCESS;
-}
+  //// Locate the detector
+  //detector = getTool(name, detector, this);
+  //if (detector == nullptr) {
+    //return reportError("Failed to locate Sensitive Detector '" + name + "'");
+  //}
+
+  //// Inform G4 sensitive detector manager
+  //if (std::find(m_sensitive_detectors.begin(), m_sensitive_detectors.end(), detector) == m_sensitive_detectors.end()) {
+    //G4SDManager* sd_manager = G4SDManager::GetSDMpointer();
+    //if (sd_manager == nullptr) {
+      //return reportError("Failed to locate G4SDManager!");
+    //}
+    //sd_manager->AddNewDetector(detector);
+  //}
+
+  //// Keep a local copy
+  //m_sensitive_detectors.push_back(detector);
+
+  //if (outputLevel() == MSG::VERBOSE) {
+    //verbose() << m_str_prefix << "<= sensitive()" << endmsg;
+    //prefixOut();
+  //}
+
+  //return StatusCode::SUCCESS;
+//}
 
 //=============================================================================
 // Instantiate a Magnetic Field object
 //=============================================================================
-StatusCode GaussGeo::fieldMgr(const std::string& name, IGiGaFieldMgr*& fmanager) {
-  if (outputLevel() == MSG::VERBOSE) {
-    prefixIn();
-    verbose() << m_str_prefix << "=> fieldMgr(): " << name << endmsg;
-  }
+//StatusCode GaussGeo::fieldMgr(const std::string& name, IGiGaFieldMgr*& fmanager) {
+  //if (outputLevel() == MSG::VERBOSE) {
+    //prefixIn();
+    //verbose() << m_str_prefix << "=> fieldMgr(): " << name << endmsg;
+  //}
 
-  // Reset the output value
-  fmanager = nullptr;
+  //// Reset the output value
+  //fmanager = nullptr;
 
-  // Locate the magnetic field tool
-  fmanager = getTool(name, fmanager, this);
-  if (fmanager == nullptr) {
-    return reportError("Failed to locate FieldManager '" + name + "'");
-  }
+  //// Locate the magnetic field tool
+  //fmanager = getTool(name, fmanager, this);
+  //if (fmanager == nullptr) {
+    //return reportError("Failed to locate FieldManager '" + name + "'");
+  //}
 
-  // Keep a local copy
-  m_mag_field_managers.push_back(fmanager);
+  //// Keep a local copy
+  //m_mag_field_managers.push_back(fmanager);
 
-  if (outputLevel() == MSG::VERBOSE) {
-    verbose() << m_str_prefix << "<= fieldMgr()" << endmsg;
-    prefixOut();
-  }
+  //if (outputLevel() == MSG::VERBOSE) {
+    //verbose() << m_str_prefix << "<= fieldMgr()" << endmsg;
+    //prefixOut();
+  //}
 
-  return StatusCode::SUCCESS;
-}
+  //return StatusCode::SUCCESS;
+//}
 
 //=============================================================================
 // Retrieve a tool by type and name
diff --git a/Sim/GaussGeo/src/component/GaussGeo.h b/Sim/GaussGeo/src/component/GaussGeo.h
index b05122eb7..306c20b41 100644
--- a/Sim/GaussGeo/src/component/GaussGeo.h
+++ b/Sim/GaussGeo/src/component/GaussGeo.h
@@ -1,5 +1,4 @@
-#ifndef  GAUSSGEO_GAUSSGEO_H_
-#define  GAUSSGEO_GAUSSGEO_H_
+#pragma once
 
 // Kernel includes
 #include "Kernel/IPropertyConfigSvc.h"
@@ -11,20 +10,25 @@
 #include "GaudiKernel/IDataProviderSvc.h"
 #include "GaudiKernel/DataStoreItem.h"
 #include "GaudiKernel/IDataSelector.h"
+#include "GiGaMTFactories/GiGaFactoryBase.h"
+#include "Geant4/G4VSensitiveDetector.hh"
+#include "GaudiKernel/Transform3DTypes.h"
 
-// GiGa Geo Interface
-#include "GiGa/IGiGaGeoSrc.h"
-
+#include "GiGaMTGeo/IGiGaMTGeoSvc.h"
 // Forward declaration
 class GaussGeoVolume;
 class GaussGeoAssembly;
-class IGiGaSensDet;
-class IGiGaMagField;
-class IGiGaFieldMgr;
-class IGDMLReader;
 class G4Material;
 class G4VSolid;
 class G4LogicalVolume;
+class G4VPhysicalVolume;
+
+// Missing from the original
+struct ISolid;
+struct IPVolume;
+struct IDetectorElement;
+class SolidBoolean;
+class G4MaterialPropertiesTable;
 
 // ============================================================================
 // Interface file for class : GaussGeo
@@ -33,14 +37,14 @@ class G4LogicalVolume;
 // into GEANT4 format. Based on GiGaGeo convertion service.
 //
 // 2015-11-11 : Dmitry Popov
+// 2019-5-16 : Dominik Muller
 // ============================================================================
 
-class GaussGeo : public Service,
-                 virtual public IIncidentListener,
-                 virtual public IGiGaGeoSrc {
+class GaussGeo : public Service, virtual public IGiGaMTGeoSvc,
+                 virtual public IIncidentListener{
  public:
   GaussGeo(const std::string& service_name, ISvcLocator* service_locator);
-  virtual ~GaussGeo() {}
+  virtual ~GaussGeo() = default;
 
   // Service pure member functions
   StatusCode initialize() override;
@@ -52,8 +56,8 @@ class GaussGeo : public Service,
   void handle(const Incident& incident) override;
 
   // Pointer to the root of G4 geometry tree
-  G4VPhysicalVolume* world() override;
-  G4VPhysicalVolume* G4WorldPV() override;  // Obsolete method for IGiGeGeoSrc
+  G4VPhysicalVolume* constructWorld() override;
+  void constructSDandField() override;
 
  private:
   GaussGeo();
@@ -87,9 +91,9 @@ class GaussGeo : public Service,
   bool m_performOverlapCheck;  // Given to G4VPlacements to control Overlap checking
   std::string m_assemblyNameSeparator;  // Separator between assembly and placement name
 
-  std::vector<IGiGaSensDet*>  m_sensitive_detectors;
-  std::vector<IGiGaMagField*> m_magnetic_fields;
-  std::vector<IGiGaFieldMgr*> m_mag_field_managers;
+  std::vector<GiGaFactoryBase<G4VSensitiveDetector>*>  m_sensitive_detectors;
+  //std::vector<IGiGaMagField*> m_magnetic_fields;
+  //std::vector<IGiGaFieldMgr*> m_mag_field_managers;
 
   bool m_use_alignment;  // Flag to switch on use of condDB info for children detector elements
   bool m_align_all;  // Flag to switch on for which detector to use condDB info for children detector elements
@@ -102,7 +106,7 @@ class GaussGeo : public Service,
 
   // GDML readers to be called when creating world volume
   std::vector<std::string> m_gdml_readers_names;
-  std::vector<IGDMLReader*> m_gdml_readers;
+  //std::vector<IGDMLReader*> m_gdml_readers;
 
   // For verbose info printout beautification
   std::string m_str_prefix;
@@ -158,8 +162,13 @@ class GaussGeo : public Service,
   StatusCode installVolume(G4LogicalVolume* g4_volume, const std::string& name,
                            const Gaudi::Transform3D& matrix, G4LogicalVolume* mother_volume);
 
-  StatusCode sensitive(const std::string& name, IGiGaSensDet*& detector);
-  StatusCode fieldMgr(const std::string& name, IGiGaFieldMgr*& fmanager);
+  // Register that sensitive detector of given name is supposed to be
+  // associated to given logical volume during worker thread initialisation
+  std::map<GiGaFactoryBase<G4VSensitiveDetector>*, std::set<G4LogicalVolume*>> mmap_sensdet_to_lvols;
+  std::map<std::string, GiGaFactoryBase<G4VSensitiveDetector>*> mmap_name_to_sensdetfac;
+  StatusCode register_sensitive(const std::string& name, G4LogicalVolume*);
+  //FIXME: FIELD STUFF
+  //StatusCode fieldMgr(const std::string& name, IGiGaFieldMgr*& fmanager);
 
   // Methods to simplify tools retrieval
   template<class T>
@@ -174,5 +183,3 @@ class GaussGeo : public Service,
   int findBestDetElemFromPVName(std::string pv_name, std::vector<const IDetectorElement*> found_detelem, int& found_detelems_num);
   StatusCode detectorElementSupportPath(const IDetectorElement* det_elem, std::string& path, const std::string& parent_path = "");
 };
-
-#endif  // GAUSSGEO_GAUSSGEO_H_
diff --git a/Sim/GaussTracker/src/GetTrackerHitsAlg.cpp b/Sim/GaussTracker/src/GetTrackerHitsAlg.cpp
index 4f4227a05..1f0f6edb6 100755
--- a/Sim/GaussTracker/src/GetTrackerHitsAlg.cpp
+++ b/Sim/GaussTracker/src/GetTrackerHitsAlg.cpp
@@ -24,23 +24,23 @@ DECLARE_COMPONENT(GetTrackerHitsAlg)
 // Initialization
 //=============================================================================
 StatusCode GetTrackerHitsAlg::initialize() {
-  StatusCode sc = GaudiAlgorithm::initialize();  // must be executed first
-  if (sc.isFailure()) return sc;  // error printed already by GaudiAlgorithm
+    StatusCode sc = GaudiAlgorithm::initialize();  // must be executed first
+    if (sc.isFailure()) return sc;  // error printed already by GaudiAlgorithm
 
-  debug() << "==> Initialize" << endmsg;
+    debug() << "==> Initialize" << endmsg;
 
-  if ("" == m_colName) {
-    fatal() << "Property CollectionName need to be set! " << endmsg;
-    return StatusCode::FAILURE;
-  }
+    if ("" == m_colName) {
+        fatal() << "Property CollectionName need to be set! " << endmsg;
+        return StatusCode::FAILURE;
+    }
 
-  auto& hit_outputhandle = std::get<0>(m_outputs);
-  std::vector<std::string>::iterator itDet;
-  debug() << " The hits " << hit_outputhandle.objKey() << endmsg;
-  debug() << " will be taken from G4 collection " << m_colName << endmsg;
-  debug() << endmsg;
+    auto& hit_outputhandle = std::get<0>(m_outputs);
+    std::vector<std::string>::iterator itDet;
+    debug() << " The hits " << hit_outputhandle.objKey() << endmsg;
+    debug() << " will be taken from G4 collection " << m_colName << endmsg;
+    debug() << endmsg;
 
-  return StatusCode::SUCCESS;
+    return StatusCode::SUCCESS;
 }
 
 //=============================================================================
@@ -49,57 +49,53 @@ StatusCode GetTrackerHitsAlg::initialize() {
 LHCb::MCHits GetTrackerHitsAlg::operator()(
     const G4EventProxies& eventproxies,
     const LinkedParticleMCParticleLinks& mcp_links) const {
-  debug() << "==> Execute" << endmsg;
-
-  // Create the MCHits and put them in the TES
-  // Cannot use
-  // MCHits* hits = getOrCreate<MCHits,MCHits>( m_hitsLocation );
-  // because triggers convertion
-  LHCb::MCHits hits;
-
-  for (auto& ep : eventproxies) {
-    auto g4event = ep.event();
-    int HCID = G4SDManager::GetSDMpointer()->GetCollectionID(m_colName.value());
-    auto col = g4event->GetHCofThisEvent()->GetHC(HCID);
-    if (0 == col) {
-      warning() << "The hit collection='" + m_colName + "' is not found!"
-                << endmsg;
-      continue;
-    }
-    auto hitCollection = dynamic_cast<TrackerHitsCollection*>(col);
-    if (0 == hitCollection) {
-      error() << "Wrong Collection type" << endmsg;
-      continue;
-    }
-    // reserve elements on output container
-    int numOfHits = hitCollection->entries();
-    // tranform G4Hit into MCHit and insert it in container
-    for (int iG4Hit = 0; iG4Hit < numOfHits; ++iG4Hit) {
-      // create hit or extended hit depending on choice
-      if (m_extendedInfo) {
-        LHCb::MCExtendedHit* newHit = new LHCb::MCExtendedHit();
-        fillHit((*hitCollection)[iG4Hit], newHit, ep.truth(), mcp_links);
-        Gaudi::XYZVector mom((*hitCollection)[iG4Hit]->GetMomentum());
-        newHit->setMomentum(mom);
-        hits.add(newHit);
-      } else {
-        LHCb::MCHit* newHit = new LHCb::MCHit();
-        fillHit((*hitCollection)[iG4Hit], newHit, ep.truth(), mcp_links);
-        hits.add(newHit);
-      }
+    debug() << "==> Execute" << endmsg;
+
+    // Create the MCHits and put them in the TES
+    // Cannot use
+    // MCHits* hits = getOrCreate<MCHits,MCHits>( m_hitsLocation );
+    // because triggers convertion
+    LHCb::MCHits hits;
+
+    for (auto& ep : eventproxies) {
+        auto hitCollection = ep.GetHitCollection<TrackerHitsCollection>(m_colName);
+        if (!hitCollection) {
+            warning() << "The hit collection='" + m_colName + "' is not found!"
+                      << endmsg;
+            continue;
+        }
+        // reserve elements on output container
+        int numOfHits = hitCollection->entries();
+        // tranform G4Hit into MCHit and insert it in container
+        for (int iG4Hit = 0; iG4Hit < numOfHits; ++iG4Hit) {
+            // create hit or extended hit depending on choice
+            if (m_extendedInfo) {
+                LHCb::MCExtendedHit* newHit = new LHCb::MCExtendedHit();
+                fillHit((*hitCollection)[iG4Hit], newHit, ep.truth(),
+                        mcp_links);
+                Gaudi::XYZVector mom((*hitCollection)[iG4Hit]->GetMomentum());
+                newHit->setMomentum(mom);
+                hits.add(newHit);
+            } else {
+                LHCb::MCHit* newHit = new LHCb::MCHit();
+                fillHit((*hitCollection)[iG4Hit], newHit, ep.truth(),
+                        mcp_links);
+                hits.add(newHit);
+            }
+        }
     }
-  }
 
-  return hits;
+    return hits;
 }
 
 //=============================================================================
 //  Finalize
 //=============================================================================
 StatusCode GetTrackerHitsAlg::finalize() {
-  debug() << "==> Finalize" << endmsg;
+    debug() << "==> Finalize" << endmsg;
 
-  return GaudiAlgorithm::finalize();  // must be called after all other actions
+    return GaudiAlgorithm::finalize();  // must be called after all other
+                                        // actions
 }
 
 //=============================================================================
@@ -109,40 +105,40 @@ StatusCode GetTrackerHitsAlg::finalize() {
 void GetTrackerHitsAlg::fillHit(
     TrackerHit* g4Hit, LHCb::MCHit* mcHit, const Gaussino::MCTruth* mctruth,
     const LinkedParticleMCParticleLinks& mcplinks) const {
-  // fill data members
-  Gaudi::XYZPoint entry(g4Hit->GetEntryPos());
-  Gaudi::XYZPoint exit(g4Hit->GetExitPos());
-  mcHit->setEntry(entry);
-  mcHit->setDisplacement(exit - entry);
-  mcHit->setEnergy(g4Hit->GetEdep());
-  mcHit->setTime(g4Hit->GetTimeOfFlight());
-  mcHit->setP(g4Hit->GetMomentum().mag());
-
-  // get sensitive detector identifier using mid point
-  // FIXME: This needs to be added once geometry has been worked in
-  int detID = -1;
-  // std::vector<const DetectorElement*>::iterator itDet;
-  // for (itDet = m_detector.begin(); itDet != m_detector.end(); itDet++) {
-  // if ((*itDet)->isInside(mcHit->midPoint())) {
-  // detID = (*itDet)->sensitiveVolumeID(mcHit->midPoint());
-  // break;
-  //}
-  //}
-  mcHit->setSensDetID(detID);
-
-  // fill reference to MCParticle using the Geant4->MCParticle table
-  int trackID = g4Hit->GetTrackID();
-  if (auto lp = mctruth->GetParticleFromTrackID(trackID); lp) {
-    if (auto it = mcplinks.find(lp); it != std::end(mcplinks)) {
-      mcHit->setMCParticle(it->second);
+    // fill data members
+    Gaudi::XYZPoint entry(g4Hit->GetEntryPos());
+    Gaudi::XYZPoint exit(g4Hit->GetExitPos());
+    mcHit->setEntry(entry);
+    mcHit->setDisplacement(exit - entry);
+    mcHit->setEnergy(g4Hit->GetEdep());
+    mcHit->setTime(g4Hit->GetTimeOfFlight());
+    mcHit->setP(g4Hit->GetMomentum().mag());
+
+    // get sensitive detector identifier using mid point
+    // FIXME: This needs to be added once geometry has been worked in
+    int detID = -1;
+    // std::vector<const DetectorElement*>::iterator itDet;
+    // for (itDet = m_detector.begin(); itDet != m_detector.end(); itDet++) {
+    // if ((*itDet)->isInside(mcHit->midPoint())) {
+    // detID = (*itDet)->sensitiveVolumeID(mcHit->midPoint());
+    // break;
+    //}
+    //}
+    mcHit->setSensDetID(detID);
+
+    // fill reference to MCParticle using the Geant4->MCParticle table
+    int trackID = g4Hit->GetTrackID();
+    if (auto lp = mctruth->GetParticleFromTrackID(trackID); lp) {
+        if (auto it = mcplinks.find(lp); it != std::end(mcplinks)) {
+            mcHit->setMCParticle(it->second);
+        } else {
+            warning() << "No pointer to MCParticle for MCHit associated to G4 "
+                         "trackID: "
+                      << trackID << endmsg;
+        }
     } else {
-      warning()
-          << "No pointer to MCParticle for MCHit associated to G4 trackID: "
-          << trackID << endmsg;
+        warning() << "No LinkedParticle found. Something went seriously wrong. "
+                     "trackID: "
+                  << trackID << endmsg;
     }
-  } else {
-    warning()
-        << "No LinkedParticle found. Something went seriously wrong. trackID: "
-        << trackID << endmsg;
-  }
 }
diff --git a/Sim/GaussTracker/src/GetTrackerHitsAlg.h b/Sim/GaussTracker/src/GetTrackerHitsAlg.h
index 180d85bb6..f463d9456 100755
--- a/Sim/GaussTracker/src/GetTrackerHitsAlg.h
+++ b/Sim/GaussTracker/src/GetTrackerHitsAlg.h
@@ -32,7 +32,7 @@ class GetTrackerHitsAlg
   GetTrackerHitsAlg(const std::string& name, ISvcLocator* pSvcLocator)
       : Transformer(
             name, pSvcLocator,
-            {{KeyValue{"Input", ""},
+            {{KeyValue{"Input", Gaussino::G4EventsLocation::Default},
               KeyValue{
                   "LinkedParticleMCParticleLinks",
                   Gaussino::LinkedParticleMCParticleLinksLocation::Default}}},
diff --git a/Sim/GaussTracker/src/GiGaSensDetTracker.cpp b/Sim/GaussTracker/src/GiGaSensDetTracker.cpp
index a0b8c5378..039709153 100755
--- a/Sim/GaussTracker/src/GiGaSensDetTracker.cpp
+++ b/Sim/GaussTracker/src/GiGaSensDetTracker.cpp
@@ -1,5 +1,5 @@
 // $Id: GiGaSensDetTracker.cpp,v 1.14 2009-06-10 16:57:25 gcorti Exp $
-// Include files 
+// Include files
 
 // from CLHEP
 #include "CLHEP/Geometry/Point3D.h"
@@ -7,14 +7,14 @@
 // from Gaudi
 #include "GaudiKernel/MsgStream.h"
 
-// from Geant4 
+// from Geant4
+#include "Geant4/G4HCofThisEvent.hh"
+#include "Geant4/G4LogicalVolume.hh"
+#include "Geant4/G4SDManager.hh"
 #include "Geant4/G4Step.hh"
-#include "Geant4/G4Track.hh"
 #include "Geant4/G4TouchableHistory.hh"
+#include "Geant4/G4Track.hh"
 #include "Geant4/G4VPhysicalVolume.hh"
-#include "Geant4/G4LogicalVolume.hh"
-#include "Geant4/G4SDManager.hh"
-#include "Geant4/G4HCofThisEvent.hh"
 #include "Geant4/G4ios.hh"
 
 // local
@@ -26,80 +26,73 @@
 // 2006-07-14 : Gloria CORTI (clean up)
 //-----------------------------------------------------------------------------
 
+GiGaSensDetTracker::GiGaSensDetTracker(const std::string& name)
+    : G4VSensitiveDetector(name) {
+    collectionName.insert("Hits");
+}
+
+void GiGaSensDetTracker::Initialize(G4HCofThisEvent* HCE) {
+    m_trackerCol =
+        new TrackerHitsCollection(SensitiveDetectorName, collectionName[0]);
 
-GiGaSensDetTracker::GiGaSensDetTracker( const std::string& name)
-  : G4VSensitiveDetector( name  )
-{  
+    std::string hit_location = SensitiveDetectorName + "/" + collectionName[0];
 
-  collectionName.insert( "Hits" );
+    debug("Registering location at " + hit_location);
+    int HCID = G4SDManager::GetSDMpointer()->GetCollectionID(hit_location);
 
+    HCE->AddHitsCollection(HCID, m_trackerCol);
 }
 
-void GiGaSensDetTracker::Initialize(G4HCofThisEvent*HCE) {
-  
-  m_trackerCol = new TrackerHitsCollection( SensitiveDetectorName,
-                                            collectionName[0] );
+bool GiGaSensDetTracker::ProcessHits(G4Step* step,
+                                     G4TouchableHistory* /* history */) {
+    if (0 == step) {
+        return false;
+    }
 
-  std::string hit_location = SensitiveDetectorName + "/" + collectionName[0];
-  
-  debug("Registering location at "+hit_location);
-  int HCID = G4SDManager::GetSDMpointer()
-    ->GetCollectionID( SensitiveDetectorName + "/" + collectionName[0] );
+    G4Track* track = step->GetTrack();
+    G4double charge = track->GetDefinition()->GetPDGCharge();
 
-  HCE->AddHitsCollection(HCID, m_trackerCol);
+    if (charge == 0.0) {
+        return false;
+    }  // fill hits only for charged tracks
 
-}
+    // If required to have energy deposition check
+    double edep = step->GetTotalEnergyDeposit();
+    if (m_requireEDep && (edep <= 0.0)) {
+        return false;
+    }
+
+    if (step->GetStepLength() != 0.0) {  // step must be finite
+
+        debug("Filling a hit");
+
+        G4ThreeVector prepos = step->GetPreStepPoint()->GetPosition();
+        double timeof = step->GetPreStepPoint()->GetGlobalTime();
+        G4ThreeVector premom = step->GetPreStepPoint()->GetMomentum();
+
+        TrackerHit* newHit = new TrackerHit();
+        newHit->SetEdep(edep);
+        newHit->SetEntryPos(prepos);
+        newHit->SetTimeOfFlight(timeof);
+        newHit->SetMomentum(premom);
+
+        // Store exit point
+        G4ThreeVector postpos = step->GetPostStepPoint()->GetPosition();
+        newHit->SetExitPos(postpos);
+
+        // Set id to track
+        int trid = track->GetTrackID();
+        newHit->SetTrackID(trid);
+
+        auto gi = GaussinoTrackInformation::Get(track);
+        gi->setCreatedHit(true);
+        gi->storeTruth();
+        gi->addHit(newHit);
+
+        // add hit to collection
+        m_trackerCol->insert(newHit);
+        return true;
+    }
 
-bool GiGaSensDetTracker::ProcessHits( G4Step* step , 
-                                      G4TouchableHistory* /* history */ ) 
-{
-  if( 0 == step ) { return false; } 
-  
-  G4Track* track=step->GetTrack();
-  G4double charge = track->GetDefinition()->GetPDGCharge();
-  
-  if( charge == 0.0 ) { return false; }   // fill hits only for charged tracks
-  
-  // If required to have energy deposition check
-  double edep = step->GetTotalEnergyDeposit();
-  if( m_requireEDep && ( edep <= 0.0 ) ) {
     return false;
-  }
-  
-  if( step->GetStepLength() != 0.0 ) {     // step must be finite
-
-    
-    debug("Filling a hit");
-
-    G4ThreeVector prepos  = step->GetPreStepPoint()->GetPosition();
-    double timeof = step->GetPreStepPoint()->GetGlobalTime();
-    G4ThreeVector premom = step->GetPreStepPoint()->GetMomentum();
-    
-    TrackerHit* newHit = new TrackerHit();
-    newHit->SetEdep( edep );
-    newHit->SetEntryPos( prepos );
-    newHit->SetTimeOfFlight( timeof );
-    newHit->SetMomentum( premom );
-
-    // Store exit point
-    G4ThreeVector postpos  = step->GetPostStepPoint()->GetPosition();
-    newHit->SetExitPos( postpos );
-    
-    // Set id to track 
-    int trid = track->GetTrackID();
-    newHit->SetTrackID( trid );
-
-    auto gi = GaussinoTrackInformation::Get(track);
-    gi->setCreatedHit(true);
-    gi->storeTruth();
-    gi->addHit(newHit);
-
-    // add hit to collection
-    m_trackerCol->insert( newHit );    
-    return true;
-    
-  }
-
-  return false;
-  
 }
diff --git a/Sim/GaussTracker/src/TrackerHit.cpp b/Sim/GaussTracker/src/TrackerHit.cpp
index 2ae236ec6..f4b6f029b 100755
--- a/Sim/GaussTracker/src/TrackerHit.cpp
+++ b/Sim/GaussTracker/src/TrackerHit.cpp
@@ -16,6 +16,8 @@
 // local
 #include "TrackerHit.h"
 
+G4ThreadLocal G4Allocator<TrackerHit> *aTrackerHitAllocator = nullptr;
+
 //=============================================================================
 // Draw 
 //=============================================================================
diff --git a/Sim/GaussTracker/src/TrackerHit.h b/Sim/GaussTracker/src/TrackerHit.h
index 1945186c9..65d588957 100755
--- a/Sim/GaussTracker/src/TrackerHit.h
+++ b/Sim/GaussTracker/src/TrackerHit.h
@@ -32,7 +32,6 @@ class TrackerHit : public Gaussino::HitBase {
 
   inline void* operator new(size_t);
   inline void operator delete(void* aHit);
-  inline static G4Allocator<TrackerHit>* TrackerHitAllocator();
 
   void Draw() override;
   void Print() override;
@@ -63,15 +62,16 @@ class TrackerHit : public Gaussino::HitBase {
 
 typedef G4THitsCollection<TrackerHit> TrackerHitsCollection;
 
-inline G4Allocator<TrackerHit>* TrackerHit::TrackerHitAllocator() {
-  thread_local auto hitAllocator = G4Allocator<TrackerHit>{};
-  return &hitAllocator;
-}
+extern G4ThreadLocal G4Allocator<TrackerHit> *aTrackerHitAllocator;
 
 inline void* TrackerHit::operator new(size_t) {
-  return (void*)TrackerHitAllocator()->MallocSingle();
+  if (!aTrackerHitAllocator)
+  {
+    aTrackerHitAllocator = new G4Allocator<TrackerHit>;
+  }
+  return (void*)aTrackerHitAllocator->MallocSingle();
 }
 
 inline void TrackerHit::operator delete(void* aHit) {
-  TrackerHitAllocator()->FreeSingle((TrackerHit*)aHit);
+  aTrackerHitAllocator->FreeSingle((TrackerHit*)aHit);
 }
-- 
GitLab


From 80fdc9118af1b5b1527dafac00a09c3a042b210a Mon Sep 17 00:00:00 2001
From: Dominik Muller <dominik.muller@cern.ch>
Date: Fri, 31 May 2019 12:14:53 +0200
Subject: [PATCH 06/90] Removed monitors now in Gaussino

---
 Sim/GaussMonitor/src/GenMonitorAlg.cpp  | 299 ------------------------
 Sim/GaussMonitor/src/GenMonitorAlg.h    |  71 ------
 Sim/GaussMonitor/src/MCTruthMonitor.cpp | 173 --------------
 Sim/GaussMonitor/src/MCTruthMonitor.h   |  66 ------
 4 files changed, 609 deletions(-)
 delete mode 100755 Sim/GaussMonitor/src/GenMonitorAlg.cpp
 delete mode 100755 Sim/GaussMonitor/src/GenMonitorAlg.h
 delete mode 100755 Sim/GaussMonitor/src/MCTruthMonitor.cpp
 delete mode 100755 Sim/GaussMonitor/src/MCTruthMonitor.h

diff --git a/Sim/GaussMonitor/src/GenMonitorAlg.cpp b/Sim/GaussMonitor/src/GenMonitorAlg.cpp
deleted file mode 100755
index 5e5f54f46..000000000
--- a/Sim/GaussMonitor/src/GenMonitorAlg.cpp
+++ /dev/null
@@ -1,299 +0,0 @@
-// $Id: GenMonitorAlg.cpp,v 1.16 2010-02-24 19:02:33 robbep Exp $
-// Include files 
-
-// from Gaudi
-#include "GaudiKernel/SystemOfUnits.h"
-
-// From HepMC
-#include "Event/HepMCEvent.h"
-#include "HepMC/GenEvent.h"
-#include "HepMC/GenParticle.h"
-
-// From LHCb
-#include "Kernel/ParticleID.h"
-
-// local
-#include "GenMonitorAlg.h"
-#include "GaussGenUtil.h"
-
-//-----------------------------------------------------------------------------
-// Implementation file for class : GenMonitorAlg
-//
-// 2003-11-13 : Patrick Robbe
-// 2005-04-11 : G.Corti
-//-----------------------------------------------------------------------------
-
-// Declaration of the Algorithm Factory
-DECLARE_COMPONENT( GenMonitorAlg )
-
-
-//=============================================================================
-// Standard constructor, initializes variables
-//=============================================================================
-GenMonitorAlg::GenMonitorAlg( const std::string& name,
-                              ISvcLocator* pSvcLocator)
-  : GaudiHistoAlg( name , pSvcLocator ) ,
-    m_counter       ( 0 ) ,
-    m_counterstable ( 0 ) ,
-    m_counterCharged( 0 ),
-    m_counterChInEta( 0 ),
-    m_nEvents       ( 0 ) {
-
-  declareProperty( "MinEta", m_minEta = 2.0);
-  declareProperty( "MaxEta", m_maxEta = 4.9);
-  declareProperty( "Input",  m_dataPath = LHCb::HepMCEventLocation::Default );
-  declareProperty( "ApplyTo", m_generatorName = "" );
-  
-  // Set by default not to fill histograms for this algorithm
-  setProduceHistos( false );
-  
-}
-
-//=============================================================================
-// Destructor
-//=============================================================================
-GenMonitorAlg::~GenMonitorAlg() {}
-
-//=============================================================================
-// Initialisation. Check parameters
-//=============================================================================
-StatusCode GenMonitorAlg::initialize() {
-
-  StatusCode sc = GaudiHistoAlg::initialize(); // must be executed first
-  if ( sc.isFailure() ) return sc;  // error printed already by GaudiHistoAlg
-
-  debug() << "==> Initialize" << endmsg;
-  
-  if ( m_generatorName.empty() ) {
-    info() << "Monitor will be applied to all events in container " 
-           << m_dataPath << endmsg;
-  } else {
-    info() << "Monitor will be applied to events produced with generator "
-           << m_generatorName << " in container "
-           << m_dataPath << endmsg; 
-  }
-
-  if( produceHistos() ) {
-    bookHistos();
-  }
-  
-  return StatusCode::SUCCESS;
-}
-
-//=============================================================================
-// Main execution
-//=============================================================================
-StatusCode GenMonitorAlg::execute() {
-
-  debug() << "==> Execute" << endmsg;  
-
-  // Initialize counters
-  int nParticles(0), nParticlesStable(0);
-  int nParticlesStableCharged(0), nParChStabEtaAcc(0);
-  int nPileUp(0);
-  
-  // Retrieve data from selected path
-  SmartDataPtr< LHCb::HepMCEvents > hepMCptr( eventSvc() , m_dataPath );
-
-  if( 0 == hepMCptr ) {
-    info() << "No HepMCEvents at location " << m_dataPath << endmsg;
-  } else {
-    LHCb::HepMCEvents::iterator it ;
-    for( it = hepMCptr->begin() ; it != hepMCptr->end(); ++it ) {
-
-      // Check if monitor has to be applied to this event
-      if( !m_generatorName.empty() ) {
-        if( m_generatorName != (*it)->generatorName() ) {
-          continue;
-        }
-      }
-      debug() << "Monitor for " << (*it)->generatorName()
-              << endmsg;
-      
-      // Plot process type 
-      if( produceHistos() ) {
-        m_hProcess->fill( (*it)->pGenEvt()->signal_process_id() );
-      }
-
-      bool primFound = false;
-      nPileUp++;
-      for( HepMC::GenEvent::particle_const_iterator 
-             itp = (*it)->pGenEvt()->particles_begin();
-           itp != (*it)->pGenEvt()->particles_end(); itp++ ) {
-        HepMC::GenParticle* hepMCpart = *itp;
-        nParticles++ ;
-        if( produceHistos() ) { 
-          // Identify primary vertex and fill histograms
-          if( !primFound ) {
-            if( (hepMCpart->status() == 1) || (hepMCpart->status() == 888 ) ) {
-              primFound = true;
-              if ( hepMCpart -> production_vertex() ) {
-                m_hPrimX->fill( hepMCpart->production_vertex()->position().x()/
-                                Gaudi::Units::mm );
-                m_hPrimY->fill( hepMCpart->production_vertex()->position().y()/
-                                Gaudi::Units::mm );
-                m_hPrimZ->fill( hepMCpart->production_vertex()->position().z()/
-                                Gaudi::Units::mm );
-                m_hPrimZV->fill( hepMCpart->production_vertex()->position().z()/
-                                 Gaudi::Units::mm );
-                m_hPrimZE->fill( hepMCpart->production_vertex()->position().z()/
-                                 Gaudi::Units::mm );
-                m_hPrimT->fill( hepMCpart->production_vertex()->position().t()/
-                                Gaudi::Units::ns );
-                m_hPrimXvsZ->fill( hepMCpart->production_vertex()->position().z()/Gaudi::Units::mm,
-                                   hepMCpart->production_vertex()->position().x()/Gaudi::Units::mm );                
-                m_hPrimYvsZ->fill( hepMCpart->production_vertex()->position().z()/Gaudi::Units::mm,
-                                   hepMCpart->production_vertex()->position().y()/Gaudi::Units::mm );                
-              }
-            } 
-          }
-          
-          m_hPartP->fill( hepMCpart->momentum().rho()/
-                          Gaudi::Units::GeV );
-          m_hPartPDG->fill( hepMCpart->pdg_id() );
-        }
-        // Note that the following is really multiplicity of particle defined
-        // as stable by Pythia just after hadronization: all particles known by
-        // EvtGen are defined stable for Pythia (it will count rho and pi0  
-        // and gamma all togheter as stable ...
-        if( ( hepMCpart->status() != 2 ) && ( hepMCpart->status() != 3 ) ) {
-          nParticlesStable++;
-          if( produceHistos() ) {
-            m_hProtoP->fill( hepMCpart->momentum().rho()/
-                             Gaudi::Units::GeV );
-            m_hProtoPDG->fill( hepMCpart->pdg_id() );
-            m_hProtoLTime->fill( GaussGenUtil::lifetime( hepMCpart )/
-                                 Gaudi::Units::mm );
-          }
-          // Charged stable particles meaning really stable after EvtGen
-          LHCb::ParticleID pID( hepMCpart->pdg_id() );
-          if( 0.0 != pID.threeCharge() ) {
-            // A stable particle does not have an outgoing vertex
-            if( !hepMCpart->end_vertex() ) {
-             // should be the same as the following  
-              //             if ( ( hepMCpart -> status() == 999 )  
-              ++nParticlesStableCharged;
-              double pseudoRap =  hepMCpart->momentum().pseudoRapidity();
-              // in LHCb acceptance
-              if( (pseudoRap > m_minEta) && (pseudoRap < m_maxEta) ) {
-                ++nParChStabEtaAcc;
-              }
-              if( produceHistos() ) {
-                m_hStableEta->fill( pseudoRap );
-                m_hStablePt->fill( hepMCpart->momentum().perp()/
-                                   Gaudi::Units::GeV );
-              }
-            }
-          }    
-        }
-      }
-    }
-  }
-  if( produceHistos() ) {
-    m_hNPart->fill( nParticles );
-    m_hNStable->fill( nParticlesStable );
-    m_hNSCharg->fill( nParticlesStableCharged );
-    m_hNSChEta->fill( nParChStabEtaAcc );
-    m_hNPileUp->fill( nPileUp );
-  }
-  m_counter += nParticles ;
-  m_counterstable += nParticlesStable ;
-  m_counterCharged += nParticlesStableCharged;
-  m_counterChInEta += nParChStabEtaAcc;
-  m_nEvents++ ;
-  
-  debug() << "Event number " << m_nEvents << " contains "
-          << nParticles << " particles" << endmsg;
-  
-  return StatusCode::SUCCESS;
-}
-
-//=============================================================================
-//  Finalize
-//=============================================================================
-StatusCode GenMonitorAlg::finalize() {
-
-  debug() << "==> Finalize" << endmsg;
-  
-  info() << std::endl 
-         << "======================== Generators Statistics ====================" 
-         << std::endl
-         << "=                                                                 ="
-         << std::endl 
-         << "= Number of particles generated: " << m_counter 
-         << std::endl 
-         << "= Number of events: " << m_nEvents
-         << std::endl
-         << "= Mean multiplicity: " << m_counter / ( double ) m_nEvents
-         << std::endl 
-         << "=                                                                 ="
-         << std::endl 
-         << "= Number of pseudo stable particles generated: " << m_counterstable
-         << std::endl 
-         << "= Number of events: " << m_nEvents
-         << std::endl
-         << "= Mean pseudo stable multiplicity: " 
-         << m_counterstable / ( double ) m_nEvents
-         << std::endl 
-         << "=                                                                 ="
-         << std::endl 
-         << "= Number of charged stable particles generated: " << m_counterCharged
-         << std::endl 
-         << "= Number of events: " << m_nEvents
-         << std::endl
-         << "= Mean charged stable multiplicity: " 
-         << m_counterCharged / ( double ) m_nEvents
-         << std::endl 
-         << "=                                                                 ="
-         << std::endl 
-         << "= Number of charged stable particles in LHCb eta " << m_counterChInEta
-         << std::endl 
-         << "= Number of events: " << m_nEvents
-         << std::endl
-         << "= Mean charged stable multiplicity in LHCb eta: " 
-         << m_counterChInEta / ( double ) m_nEvents
-         << std::endl 
-         << "=                                                                 ="
-         << std::endl 
-         << "==================================================================="
-         << endmsg;
-
-  return GaudiHistoAlg::finalize();
-  
-}
-
-//============================================================================
-// Booking of histograms
-//============================================================================
-void GenMonitorAlg::bookHistos() 
-{
-
-  debug() << "==> Book histograms" << endmsg;
- 
-  m_hNPart   = book(  1, "Multiplicity all particles", 0., 2999., 300 );
-  m_hNStable = book(  2, "Multiplicity protostable particles", 0., 2999., 300 );
-  m_hNSCharg = book(  3, "Multiplicity stable charged particles", -0.5, 299.5, 300 );
-  m_hNSChEta = book(  4, "Multiplicity stable charged particles in LHCb eta",
-                      -0.5, 299.5, 300 );
-  m_hProcess = book(  5, "Process type", -0.5, 5100.5, 5101);
-  m_hNPileUp = book( 10, "Num. of primary interaction per bunch", -0.5, 10.5, 11 );
-  m_hPrimX   = book( 11, "PrimaryVertex x (mm)", -1.0, 1.0, 200 );
-  m_hPrimY   = book( 12, "PrimaryVertex y (mm)", -1.0, 1.0, 200 );
-  m_hPrimZ   = book( 13, "PrimaryVertex z (mm)", -200., 200., 100 ); 
-  m_hPrimZV  = book( 14, "PrimaryVertex z, all Velo (mm)", -1000., 1000., 100 );
-  m_hPrimZE  = book( 15, "PrimaryVertex z, all Exp Area (mm)", -1000., 20000., 105 );
-  m_hPrimT   = book( 16, "PrimaryVertex t (ns)", -75.5, 75.5, 151 );
-  m_hPrimXvsZ = book2D( 17, "PrimaryVertex x vs z (mm)", -500., 500., 100, -1., 1., 100 );
-  m_hPrimYvsZ = book2D( 18, "PrimaryVertex y vs z (mm)", -500., 500., 100, -1., 1., 100 );
-  m_hPartP   = book( 21, "Momentum of all particles (GeV)", 0., 100., 100 );
-  m_hPartPDG = book( 22, "PDGid of all particles", -4999., 5000., 10000 );
-  m_hProtoP  = book( 31, "Momentum of protostable particles (GeV)", 0., 100., 100);
-  m_hProtoPDG = book( 32, "PDGid of protostable particles", -4999., 5000., 10000 );
-  m_hProtoLTime = book( 33, "Lifetime protostable particles (mm) ", -1., 20., 105 );
-  m_hStableEta = book( 44, "Pseudorapidity stable charged particles", -15., 15., 150 );
-  m_hStablePt  = book( 45, "Pt stable charged particles", 0., 20., 100 );
-
-  return;
-
-}
-
diff --git a/Sim/GaussMonitor/src/GenMonitorAlg.h b/Sim/GaussMonitor/src/GenMonitorAlg.h
deleted file mode 100755
index 9c9c8ad0a..000000000
--- a/Sim/GaussMonitor/src/GenMonitorAlg.h
+++ /dev/null
@@ -1,71 +0,0 @@
-// $Id: GenMonitorAlg.h,v 1.7 2009-12-17 19:29:19 gcorti Exp $
-#ifndef GAUSSMONITOR_GENMONITORALG_H
-#define GAUSSMONITOR_GENMONITORALG_H 1
-
-// Include files
-// from STL
-#include <string>
-
-// from Gaudi
-#include "GaudiAlg/GaudiHistoAlg.h"
-
-// from AIDA
-#include "AIDA/IHistogram1D.h"
-#include "AIDA/IHistogram2D.h"
-
-/** @class GenMonitorAlg GenMonitorAlg.h Algorithms/GenMonitorAlg.h
- *
- *  Monitoring algorithms for the generator sequences
- *
- *  @author Patrick Robbe (modified G.Corti)
- *  @date   2005-04-11
- */
-class GenMonitorAlg : public GaudiHistoAlg {
-public:
-  /// Standard constructor
-  GenMonitorAlg( const std::string& name, ISvcLocator* pSvcLocator );
-
-  virtual ~GenMonitorAlg( ); ///< Destructor
-
-  StatusCode initialize() override;    ///< Algorithm initialization
-  StatusCode execute   () override;    ///< Algorithm execution
-  StatusCode finalize  () override;    ///< Algorithm finalization
-
-protected:
-  void bookHistos();                  ///< Book histograms
-
-private:
-  std::string    m_dataPath;            ///< location of input data
-  double         m_minEta;              ///< Min pseudo rapidity acceptance
-  double         m_maxEta;              ///< Max pseudo rapidity acceptance
-
-  int            m_counter       , m_counterstable;
-  int            m_counterCharged, m_counterChInEta;
-  int            m_nEvents;
-
-  std::string    m_generatorName;
-
-  AIDA::IHistogram1D* m_hNPart;
-  AIDA::IHistogram1D* m_hNStable;
-  AIDA::IHistogram1D* m_hNSCharg;
-  AIDA::IHistogram1D* m_hNSChEta;
-  AIDA::IHistogram1D* m_hProcess;
-  AIDA::IHistogram1D* m_hNPileUp;
-  AIDA::IHistogram1D* m_hPrimX;
-  AIDA::IHistogram1D* m_hPrimY;
-  AIDA::IHistogram1D* m_hPrimZ;
-  AIDA::IHistogram1D* m_hPrimZV;
-  AIDA::IHistogram1D* m_hPrimZE;
-  AIDA::IHistogram1D* m_hPrimT;
-  AIDA::IHistogram1D* m_hPartP;
-  AIDA::IHistogram1D* m_hPartPDG;
-  AIDA::IHistogram1D* m_hProtoP;
-  AIDA::IHistogram1D* m_hProtoPDG;
-  AIDA::IHistogram1D* m_hProtoLTime;
-  AIDA::IHistogram1D* m_hStableEta;
-  AIDA::IHistogram1D* m_hStablePt;
-  AIDA::IHistogram2D* m_hPrimXvsZ;
-  AIDA::IHistogram2D* m_hPrimYvsZ;
-
-};
-#endif // GAUSSMONITOR_GENMONITORALG_H
diff --git a/Sim/GaussMonitor/src/MCTruthMonitor.cpp b/Sim/GaussMonitor/src/MCTruthMonitor.cpp
deleted file mode 100755
index 000a83f14..000000000
--- a/Sim/GaussMonitor/src/MCTruthMonitor.cpp
+++ /dev/null
@@ -1,173 +0,0 @@
-// $Id: MCTruthMonitor.cpp,v 1.5 2009-03-26 21:45:04 robbep Exp $
-// Include files 
-
-// from Gaudi
-
-// from LHCb
-#include "Event/MCParticle.h"
-#include "Event/MCVertex.h"
-
-// local1
-#include "MCTruthMonitor.h"
-
-//-----------------------------------------------------------------------------
-// Implementation file for class : MCTruthMonitor
-//
-// 2005-08-12 : Gloria CORTI
-//-----------------------------------------------------------------------------
-
-// Declaration of the Algorithm Factory
-DECLARE_COMPONENT( MCTruthMonitor )
-
-
-//=============================================================================
-// Standard constructor, initializes variables
-//=============================================================================
-MCTruthMonitor::MCTruthMonitor( const std::string& name,
-                                ISvcLocator* pSvcLocator)
-  : GaudiHistoAlg ( name , pSvcLocator )
-{
-  declareProperty( "DetailedHistos", m_detailedHistos = false );  
-  declareProperty( "MCParticles"   , 
-                   m_mcParticles = LHCb::MCParticleLocation::Default ) ;
-  declareProperty( "MCVertices" , 
-                   m_mcVertices = LHCb::MCVertexLocation::Default ) ;
-}
-//=============================================================================
-// Destructor
-//=============================================================================
-MCTruthMonitor::~MCTruthMonitor() {}
-
-//=============================================================================
-// Initialization
-//=============================================================================
-StatusCode MCTruthMonitor::initialize() {
-  StatusCode sc = GaudiHistoAlg::initialize(); // must be executed first
-  if ( sc.isFailure() ) return sc;  // error printed already by GaudiAlgorithm
-
-  debug() << "==> Initialize" << endmsg;
-
-  m_hNPart   = book(100, "Multiplicity MCparticles", 0., 1000., 100);
-  m_hNVert   = book(200, "Multiplicity MCVertices", 0., 200., 100);
-
-  m_hPOrigT   = book(101, "Vertex type of particles", 0., 20., 20);
-  m_hPOrigZ   = book(102, "Z origin of all particles (mm)", -1000., 20000., 2100);  
-  m_hPMom     = book(103, "Momentum of all particles (GeV)", 0., 1., 200);
-  m_hPPrimMom = book(104, "Momentum of primary particles (GeV)", 0., 100., 50);
-  m_hPProtMom = book(105, "Momentum of protons particles (GeV)", 0., 100., 50);
-
-  m_hVType   = book(201, "Vertex type", 0., 20., 20);
-  m_hVZpos   = book(202, "Z position of all vertices (mm)", -1000., 20000., 2100);
-  m_hVZpos2  = book(203, "Z position of all vertices (mm)", -10000., 10000., 200);
-  m_hVTime   = book(204, "Time of all vertices (ns)", -20., 100., 120);
-
-  if( !detailedHistos() ) {
-    return StatusCode::SUCCESS;
-  }
-
-  m_hNProtons   = book(111, "Number of protons", 0., 100., 50);
-  m_hNNeutrons  = book(112, "Number of neutrons", 0., 100., 50);
-  m_hNChPions   = book(113, "Number of charged pions", 0., 200., 100);
-  m_hNPiZeros   = book(114, "Number of pi zeros", 0., 200., 100);
-  m_hNChKaons   = book(115, "Number of charged kaons", 0., 50., 50);
-  m_hNKs        = book(116, "Number of Ks", 0., 50., 50);
-  m_hNElectrons = book(117, "Number of e+/e-", 0., 200., 100);
-  m_hNMuons     = book(118, "Number of mu+mu-", 0., 100., 100);
-  m_hNGammas    = book(119, "Number of gammas", 0., 200., 100);
-  m_hNBeauty    = book(120, "Number of particles with b/b~ quark", 0., 10., 10);
-  m_hNCharm     = book(121, "Number of particles with c/c~ quark", 0., 20., 20);
-  m_hNNuclei    = book(122, "Number of nuclei", 0., 50., 50);
-
-  return StatusCode::SUCCESS;
-}
- 
-//=============================================================================
-// Main execution
-//=============================================================================
-StatusCode MCTruthMonitor::execute() {
-
-  debug() << "==> Execute" << endmsg;
-
-  unsigned int nProtons = 0, nNeutrons = 0, nChPions = 0, nPiZeros = 0;
-  unsigned int nChKaons = 0, nKs = 0, nElectrons = 0, nMuons = 0, nGammas = 0;
-  unsigned int nBeauty = 0, nCharm = 0, nNuclei = 0;
-
-  const LHCb::MCParticles* particles = 
-    get<LHCb::MCParticles>( m_mcParticles );
-  m_hNPart->fill(particles->size());
-  LHCb::MCParticles::const_iterator ip;
-  for( ip = particles->begin(); particles->end() != ip; ++ip ) {
-    m_hPOrigZ->fill((*ip)->originVertex()->position().z()/Gaudi::Units::mm);
-    int vtype = (*ip)->originVertex()->type();
-    if( vtype >=100 ) { vtype = vtype - 100 + 10; }
-    m_hPOrigT->fill(vtype);
-    m_hPMom->fill((*ip)->p()/Gaudi::Units::GeV);
-    if( (*ip)->originVertex()->type() == LHCb::MCVertex::ppCollision ) {
-      m_hPPrimMom->fill((*ip)->p()/Gaudi::Units::GeV);
-    }
-    LHCb::ParticleID id = (*ip)->particleID();
-    if( id.pid() == 2212 ) {
-      if( (*ip)->p() >= 5.0*Gaudi::Units::TeV ) {
-        m_hPProtMom->fill(10*((*ip)->p())/(Gaudi::Units::TeV/Gaudi::Units::GeV));
-      } else {
-        m_hPProtMom->fill((*ip)->p()/Gaudi::Units::GeV);
-      } 
-    }
-    if( detailedHistos() ) {
-      // Find number of different particles types
-      if( id.abspid() == 2212 ) nProtons++;
-      if( id.abspid() == 2112 ) nNeutrons++;
-      if( id.abspid() == 211 )  nChPions++;
-      if( id.abspid() == 111 )  nPiZeros++;
-      if( id.abspid() == 321 )  nChKaons++;
-      if( id.abspid() == 310 )  nKs++;
-      if( id.abspid() == 11 )   nElectrons++;
-      if( id.abspid() == 13 )   nMuons++;
-      if( id.abspid() == 22 )   nGammas++;
-      if( id.hasBottom() )      nBeauty++;
-      if( id.hasCharm() )       nCharm++;
-      if( id.isNucleus() )      nNuclei++;
-    }
-  }
-  if( detailedHistos() ) {
-    m_hNProtons->fill(nProtons);
-    m_hNNeutrons->fill(nNeutrons);
-    m_hNChPions->fill(nChPions);
-    m_hNPiZeros->fill(nPiZeros);
-    m_hNChKaons->fill(nChKaons);
-    m_hNKs->fill(nKs);
-    m_hNElectrons->fill(nElectrons);
-    m_hNMuons->fill(nMuons);
-    m_hNGammas->fill(nGammas);
-    m_hNBeauty->fill(nBeauty);
-    m_hNCharm->fill(nCharm);
-    m_hNNuclei->fill(nNuclei);
-  }
-  
-  const LHCb::MCVertices* vertices = 
-    get<LHCb::MCVertices>( m_mcVertices );
-  m_hNVert->fill(vertices->size());
-  LHCb::MCVertices::const_iterator iv;
-  for( iv = vertices->begin(); vertices->end()!= iv; ++iv ) {
-    int vtype = (*iv)->type();
-    if( vtype >=100 ) { vtype = vtype - 100 + 10; }
-    m_hVType->fill(vtype);
-    m_hVZpos->fill((*iv)->position().z()/Gaudi::Units::mm);
-    m_hVZpos2->fill((*iv)->position().z()/Gaudi::Units::mm);
-    m_hVTime->fill((*iv)->time()/Gaudi::Units::ns);
-  }
-  
-  return StatusCode::SUCCESS;
-}
-
-//=============================================================================
-//  Finalize
-//=============================================================================
-StatusCode MCTruthMonitor::finalize() {
-
-  debug() << "==> Finalize" << endmsg;
-
-  return GaudiAlgorithm::finalize();  // must be called after all other actions
-}
-
-//=============================================================================
diff --git a/Sim/GaussMonitor/src/MCTruthMonitor.h b/Sim/GaussMonitor/src/MCTruthMonitor.h
deleted file mode 100755
index c5cf9963c..000000000
--- a/Sim/GaussMonitor/src/MCTruthMonitor.h
+++ /dev/null
@@ -1,66 +0,0 @@
-// $Id: MCTruthMonitor.h,v 1.2 2009-03-26 21:45:04 robbep Exp $
-#ifndef MCTRUTHMONITOR_H
-#define MCTRUTHMONITOR_H 1
-
-// Include files
-// from Gaudi
-#include "GaudiAlg/GaudiHistoAlg.h"
-
-// from AIDA
-#include "AIDA/IHistogram1D.h"
-
-/** @class MCTruthMonitor MCTruthMonitor.h
- *
- *  Algorithm to fill reference historgam for MCParticles and MCVertices.
- *  A more detailed set is switched on with property "DetailedHistos = true".
- *
- *  @author Gloria CORTI
- *  @date   2005-08-12
- */
-class MCTruthMonitor : public GaudiHistoAlg {
-public:
-  /// Standard constructor
-  MCTruthMonitor( const std::string& name, ISvcLocator* pSvcLocator );
-
-  virtual ~MCTruthMonitor( ); ///< Destructor
-
-  StatusCode initialize() override;    ///< Algorithm initialization
-  StatusCode execute   () override;    ///< Algorithm execution
-  StatusCode finalize  () override;    ///< Algorithm finalization
-
-protected:
-  bool detailedHistos() {
-    return m_detailedHistos;
-  }
-
-private:
-
-  bool m_detailedHistos;             ///< Property to control set of histos
-  std::string m_mcParticles ;        ///< Location of the MCParticles
-  std::string m_mcVertices ;         ///< Location of the MCVertices
-  AIDA::IHistogram1D* m_hNPart;      ///< Histo of MCParticle multiplicity
-  AIDA::IHistogram1D* m_hNVert;      ///< Histo of MCVertices multiplicity
-  AIDA::IHistogram1D* m_hPOrigZ;     ///< Z Origin of all particles
-  AIDA::IHistogram1D* m_hPOrigT;     ///< Origin vertex type for all particles
-  AIDA::IHistogram1D* m_hPMom;       ///< |P| of all particles
-  AIDA::IHistogram1D* m_hPPrimMom;   ///< |P| of particles from primary vertex
-  AIDA::IHistogram1D* m_hPProtMom;   ///< |P| of protons
-  AIDA::IHistogram1D* m_hNProtons;   ///< p/p_bar multiplicity
-  AIDA::IHistogram1D* m_hNNeutrons;  ///< n/n_bar multiplicity
-  AIDA::IHistogram1D* m_hNChPions;   ///< pi+/- multiplicity
-  AIDA::IHistogram1D* m_hNPiZeros;   ///< pi0 multiplicity
-  AIDA::IHistogram1D* m_hNChKaons;   ///< K+/- multiplicity
-  AIDA::IHistogram1D* m_hNKs;        ///< Kshort multiplicity
-  AIDA::IHistogram1D* m_hNElectrons; ///< e+/- multiplicity
-  AIDA::IHistogram1D* m_hNMuons;     ///< mu+/- multiplicity
-  AIDA::IHistogram1D* m_hNGammas;    ///< gammas multiplicity
-  AIDA::IHistogram1D* m_hNBeauty;    ///< Particles with b/b_bar quark multip.
-  AIDA::IHistogram1D* m_hNCharm;     ///< Particles with c/c_bar quark multip.
-  AIDA::IHistogram1D* m_hNNuclei;    ///< nuclei multiplicity
-  AIDA::IHistogram1D* m_hVType;      ///< Type of all vertices
-  AIDA::IHistogram1D* m_hVZpos;      ///< Zpos of all vertices (in detector)
-  AIDA::IHistogram1D* m_hVZpos2;     ///< Zpos of all vertices (symm. in IP)
-  AIDA::IHistogram1D* m_hVTime;      ///< Time of all vertices
-
-};
-#endif // MCTRUTHMONITOR_H
-- 
GitLab


From b512995618fc027f800aa3705c5d38f355981787 Mon Sep 17 00:00:00 2001
From: Dominik Muller <dominik.muller@cern.ch>
Date: Fri, 31 May 2019 12:16:28 +0200
Subject: [PATCH 07/90] Ported Velo monitor

---
 .../python/Gauss/Geometry/Configuration.py    |   6 +-
 Sim/Gauss/python/Gauss/Geometry/PuVeto.py     |  16 +-
 Sim/Gauss/python/Gauss/Geometry/Velo.py       |   6 +
 Sim/Gauss/python/Gauss/Geometry/det_base.py   |   3 +
 Sim/GaussTracker/CMakeLists.txt               |   3 +-
 Sim/GaussTracker/src/GetTrackerHitsAlg.cpp    |  27 ++-
 Sim/GaussTracker/src/GetTrackerHitsAlg.h      |   1 +
 Velo/VeloGauss/src/VeloGaussMoni.cpp          | 163 +++---------------
 Velo/VeloGauss/src/VeloGaussMoni.h            |  52 +++---
 9 files changed, 101 insertions(+), 176 deletions(-)

diff --git a/Sim/Gauss/python/Gauss/Geometry/Configuration.py b/Sim/Gauss/python/Gauss/Geometry/Configuration.py
index e4843def7..10b865b8d 100644
--- a/Sim/Gauss/python/Gauss/Geometry/Configuration.py
+++ b/Sim/Gauss/python/Gauss/Geometry/Configuration.py
@@ -162,15 +162,17 @@ class LHCbGeo(LHCbConfigurableUser):
         for det in detectors_geo:
             getsubdetector(det).SetupExtraction()
 
+        for det in detectors_moni:
+            getsubdetector(det).SetupMonitor()
+
     def MakeItTalkToGaussino(self):
         from Configurables import GiGaMTProxyDetectorConstructionFAC
-        from Configurables import GaussGeo, GiGaMT, ApplicationMgr
+        from Configurables import GiGaMT
         giga = GiGaMT()
         giga.DetectorConstruction = "GiGaMTProxyDetectorConstructionFAC"
         dettool = giga.addTool(GiGaMTProxyDetectorConstructionFAC,
                                "GiGaMTProxyDetectorConstructionFAC")
         dettool.GiGaMTGeoSvc = "GaussGeo"
-        # ApplicationMgr().ExtSvc += [GaussGeo()]
 
     def PrintDebugDump(self, detPieces, basePieces):
         if self.getProp("Debug"):
diff --git a/Sim/Gauss/python/Gauss/Geometry/PuVeto.py b/Sim/Gauss/python/Gauss/Geometry/PuVeto.py
index 8161b9b61..ea91aa8cf 100644
--- a/Sim/Gauss/python/Gauss/Geometry/PuVeto.py
+++ b/Sim/Gauss/python/Gauss/Geometry/PuVeto.py
@@ -1,5 +1,5 @@
 from Gauss.Geometry.det_base import det_base
-from Gauss.Geometry.Helpers import subdetector
+from Gauss.Geometry.Helpers import subdetector, getsubdetector
 
 
 @subdetector
@@ -7,3 +7,17 @@ class PuVeto(det_base):
 
     def ApplyDetector(self, basePieces, detPieces):
         pass
+
+    def SetupExtraction(self, slot=''):
+        det = "PuVeto"
+        region = "BeforeMagnetRegion"
+        from Configurables import GetTrackerHitsAlg
+        if not getsubdetector('VP').Active:
+            hits = GetTrackerHitsAlg(
+                'Get' + det + 'Hits' + slot,
+                MCHitsLocation='MC/'+det+'/Hits',
+                CollectionName='VeloPuSDet/Hits',
+                Detectors=['/dd/Structure/LHCb/' + region + '/Velo']
+                )
+            from Configurables import ApplicationMgr
+            ApplicationMgr().TopAlg += [hits]
diff --git a/Sim/Gauss/python/Gauss/Geometry/Velo.py b/Sim/Gauss/python/Gauss/Geometry/Velo.py
index a3541e83f..cc4764117 100644
--- a/Sim/Gauss/python/Gauss/Geometry/Velo.py
+++ b/Sim/Gauss/python/Gauss/Geometry/Velo.py
@@ -153,3 +153,9 @@ class Velo(det_base):
         )
         from Configurables import ApplicationMgr
         ApplicationMgr().TopAlg += [alg]
+
+    def SetupMonitor(self, slot=''):
+        from Configurables import VeloGaussMoni
+        moni = VeloGaussMoni("VeloGaussMoni"+slot)
+        from Configurables import ApplicationMgr
+        ApplicationMgr().TopAlg += [moni]
diff --git a/Sim/Gauss/python/Gauss/Geometry/det_base.py b/Sim/Gauss/python/Gauss/Geometry/det_base.py
index 65a89ed15..bf4184855 100644
--- a/Sim/Gauss/python/Gauss/Geometry/det_base.py
+++ b/Sim/Gauss/python/Gauss/Geometry/det_base.py
@@ -65,3 +65,6 @@ class det_base(LHCbConfigurableUser):
 
     def SetupExtraction(self, slot=''):
         pass
+
+    def SetupMonitor(self, slot=''):
+        pass
diff --git a/Sim/GaussTracker/CMakeLists.txt b/Sim/GaussTracker/CMakeLists.txt
index 67d325c3e..2e4a9b593 100644
--- a/Sim/GaussTracker/CMakeLists.txt
+++ b/Sim/GaussTracker/CMakeLists.txt
@@ -5,6 +5,7 @@ gaudi_subdir(GaussTracker v8r0)
 
 gaudi_depends_on_subdirs(GaudiAlg
                          Sim/GiGaMTCore
+                         Det/DetDesc
                          HepMC3
                          Sim/GiGaMTFactories)
 
@@ -18,7 +19,7 @@ add_definitions(-DG4USE_STD11)
 
 gaudi_add_module(GaussTracker
                  src/*.cpp
-                 LINK_LIBRARIES Geant4 GiGaMTCoreTruthLib GaudiAlgLib)
+                 LINK_LIBRARIES DetDescLib Geant4 GiGaMTCoreTruthLib GaudiAlgLib)
 
 gaudi_env(SET GAUSSTRACKEROPTS \${GAUSSTRACKERROOT}/options)
 
diff --git a/Sim/GaussTracker/src/GetTrackerHitsAlg.cpp b/Sim/GaussTracker/src/GetTrackerHitsAlg.cpp
index 1f0f6edb6..2b6c0a15d 100755
--- a/Sim/GaussTracker/src/GetTrackerHitsAlg.cpp
+++ b/Sim/GaussTracker/src/GetTrackerHitsAlg.cpp
@@ -3,8 +3,8 @@
 #include "Geant4/G4SDManager.hh"
 
 // from LHCb
+#include "DetDesc/DetectorElement.h"
 #include "Event/MCExtendedHit.h"
-//#include "DetDesc/DetectorElement.h"
 
 // local
 #include "GetTrackerHitsAlg.h"
@@ -40,6 +40,14 @@ StatusCode GetTrackerHitsAlg::initialize() {
     debug() << " will be taken from G4 collection " << m_colName << endmsg;
     debug() << endmsg;
 
+    // FIXME: Should become a tool
+    // get the detector element
+  debug() << " for detector(s) ";
+    for (itDet = m_detName.begin(); itDet != m_detName.end(); itDet++) {
+        debug() << *itDet << " ";
+        m_detector.push_back(getDet<DetectorElement>(*itDet));
+    }
+
     return StatusCode::SUCCESS;
 }
 
@@ -58,7 +66,8 @@ LHCb::MCHits GetTrackerHitsAlg::operator()(
     LHCb::MCHits hits;
 
     for (auto& ep : eventproxies) {
-        auto hitCollection = ep.GetHitCollection<TrackerHitsCollection>(m_colName);
+        auto hitCollection =
+            ep.GetHitCollection<TrackerHitsCollection>(m_colName);
         if (!hitCollection) {
             warning() << "The hit collection='" + m_colName + "' is not found!"
                       << endmsg;
@@ -117,13 +126,13 @@ void GetTrackerHitsAlg::fillHit(
     // get sensitive detector identifier using mid point
     // FIXME: This needs to be added once geometry has been worked in
     int detID = -1;
-    // std::vector<const DetectorElement*>::iterator itDet;
-    // for (itDet = m_detector.begin(); itDet != m_detector.end(); itDet++) {
-    // if ((*itDet)->isInside(mcHit->midPoint())) {
-    // detID = (*itDet)->sensitiveVolumeID(mcHit->midPoint());
-    // break;
-    //}
-    //}
+    // FIXME: put this into a tool so it can be configured when using DD4hep
+    for (auto itDet = m_detector.begin(); itDet != m_detector.end(); itDet++) {
+        if ((*itDet)->isInside(mcHit->midPoint())) {
+            detID = (*itDet)->sensitiveVolumeID(mcHit->midPoint());
+            break;
+        }
+    }
     mcHit->setSensDetID(detID);
 
     // fill reference to MCParticle using the Geant4->MCParticle table
diff --git a/Sim/GaussTracker/src/GetTrackerHitsAlg.h b/Sim/GaussTracker/src/GetTrackerHitsAlg.h
index f463d9456..00f58219f 100755
--- a/Sim/GaussTracker/src/GetTrackerHitsAlg.h
+++ b/Sim/GaussTracker/src/GetTrackerHitsAlg.h
@@ -70,4 +70,5 @@ class GetTrackerHitsAlg
 
   private:
   std::string m_mcParticles;  ///< Name of MCParticles location
+  std::vector<const DetectorElement*> m_detector; ///< Pointers to DetectorEl
 };
diff --git a/Velo/VeloGauss/src/VeloGaussMoni.cpp b/Velo/VeloGauss/src/VeloGaussMoni.cpp
index 0efa10ae6..668ff8e94 100755
--- a/Velo/VeloGauss/src/VeloGaussMoni.cpp
+++ b/Velo/VeloGauss/src/VeloGaussMoni.cpp
@@ -8,88 +8,40 @@
 // from LHcb
 #include "Event/MCParticle.h"
 
-// velo
-#include "VeloDet/DeVelo.h"
-
 // local
 #include "VeloGaussMoni.h"
 
-//-----------------------------------------------------------------------------
-// Implementation file for class : VeloGaussMoni
-//
-// 2005-12-13 : Tomasz Szumlak & Chris Parkes
-//-----------------------------------------------------------------------------
-
 // Declaration of the Algorithm Factory
 DECLARE_COMPONENT( VeloGaussMoni )
 
 
-//=============================================================================
-// Standard constructor, initializes variables
-//=============================================================================
-VeloGaussMoni::VeloGaussMoni( const std::string& name,
-                              ISvcLocator* pSvcLocator)
-  : GaudiTupleAlg ( name , pSvcLocator ),
-    m_veloDetLocation ( DeVeloLocation::Default ),
-    m_veloMCHits ( ),
-    m_veloPileUpMCHits ( ),
-    m_print ( 0 ),
-    m_printInfo (false),
-    m_detailedMonitor ( true ),
-    m_testMCHit ( true ),
-    m_testPileUpMCHit ( true ),
-    m_nMCH ( 0. ),
-    m_nMCH2 ( 0. ),
-    m_nPUMCH ( 0. ),
-    m_nPUMCH2 ( 0. ),
-    m_nEvent ( 0 )
-{
-  declareProperty("Print", m_print);
-  declareProperty("PrintInfo", m_printInfo);
-  declareProperty("TestMCHit", m_testMCHit);
-  declareProperty("TestPileUpMCHit", m_testPileUpMCHit);
-  declareProperty("DetailedMonitor", m_detailedMonitor);
-  declareProperty("VeloDetLocation", m_veloDetLocation);
-  declareProperty("VeloMCHits" , 
-                  m_veloMCHitsLocation = LHCb::MCHitLocation::Velo ) ;
-  declareProperty("PuVetoMCHits" , 
-                  m_puVetoMCHitsLocation = LHCb::MCHitLocation::PuVeto ) ;
-}
-//=============================================================================
-// Destructor
-//=============================================================================
-VeloGaussMoni::~VeloGaussMoni() {}
-
 //=============================================================================
 // Initialization
 //=============================================================================
 StatusCode VeloGaussMoni::initialize() {
-  StatusCode sc = GaudiAlgorithm::initialize(); // must be executed first
+  StatusCode sc = GaudiHistoAlg::initialize(); // must be executed first
   if ( sc.isFailure() ) return sc;  // error printed already by GaudiAlgorithm
 
   debug() << "==> Initialize" << endmsg;
   //
   m_veloDet=( getDet<DeVelo>(m_veloDetLocation ) );
   setHistoTopDir("Velo/");
+  checkTests();
   //
   return StatusCode::SUCCESS;
 }
 
-//=============================================================================
-// Main execution
-//=============================================================================
-StatusCode VeloGaussMoni::execute() {
+
+void VeloGaussMoni::operator()(const LHCb::MCHits& m_veloMCHits, const LHCb::MCHits& m_veloPileUpMCHits) const{
 
   debug() << "==> Execute" << endmsg;
   //
+  //FIXME: Cannot have the threads interfere with each others plotting
+  //so instead of doing something smart we just lock this for now ...
+  std::lock_guard<std::mutex> guard_lock(m_lazy_lock);
   m_nEvent++;
-  getData();
-  if(m_testMCHit) veloMCHitMonitor();
-  if(m_testPileUpMCHit) veloPileUpMCHitMonitor();
-  if(!m_detailedMonitor) basicMonitor();
-  checkTests();
-  //
-  return StatusCode::SUCCESS;
+  if(m_testMCHit) veloMCHitMonitor(&m_veloMCHits);
+  if(m_testPileUpMCHit) veloPileUpMCHitMonitor(&m_veloPileUpMCHits);
 }
 
 //=============================================================================
@@ -98,66 +50,35 @@ StatusCode VeloGaussMoni::execute() {
 StatusCode VeloGaussMoni::finalize() {
 
   debug() << "==> Finalize" << endmsg;  
-  m_nMCH/=m_nEvent;
-  m_nMCH2/=m_nEvent;
-  double err_nMCH=sqrt((m_nMCH2-(m_nMCH*m_nMCH))/m_nEvent);
-  m_nPUMCH/=m_nEvent;
-  m_nPUMCH2/=m_nEvent;
-  double err_nPUMCH=sqrt((m_nPUMCH2-(m_nPUMCH*m_nPUMCH))/m_nEvent);
+  double ave_nMCH = (double) m_nMCH / m_nEvent;
+  double ave_nMCH2 = (double) m_nMCH2 / m_nEvent;
+  double err_nMCH=sqrt((ave_nMCH2-(ave_nMCH*ave_nMCH))/m_nEvent);
+  double ave_nPUMCH = (double) m_nPUMCH / m_nEvent;
+  double ave_nPUMCH2 = (double)m_nPUMCH2 / m_nEvent;
+  double err_nPUMCH=sqrt((ave_nPUMCH2-(ave_nPUMCH*ave_nPUMCH))/m_nEvent);
   //
   info()<< "------------------------------------------------------" <<endmsg;
   info()<< "                - VeloGaussMoni table -                 " <<endmsg;
   info()<< "------------------------------------------------------" <<endmsg;
   if(m_nMCH>0){
-    info()<< "| Number of MCHits/Event:       " << m_nMCH << "+/-"
+    info()<< "| Number of MCHits/Event:       " << ave_nMCH << "+/-"
           << err_nMCH <<endmsg;
-    info()<< "| Number of PileUpMCHits/Event: " << m_nPUMCH << "+/-"
+    info()<< "| Number of PileUpMCHits/Event: " << ave_nPUMCH << "+/-"
           << err_nPUMCH <<endmsg;
   }else{
     info()<< "| ==> No MCHits found! " <<endmsg;
   }
   info()<< "------------------------------------------------------" <<endmsg;
   //
-  return GaudiAlgorithm::finalize();  // must be called after all other actions
+  return GaudiHistoAlg::finalize();  // must be called after all other actions
 }
-//
-StatusCode VeloGaussMoni::getData()
-{
-  debug()<< " ==> VeloGaussMoni::getData" <<endmsg;
 
-  if(!exist<LHCb::MCHits>( m_veloMCHitsLocation )){
-    error()<< "There is no MCHits at MC/Velo/Hits in TES!" <<endmsg;
-    m_testMCHit=false;
-  }else{
-    m_veloMCHits=get<LHCb::MCHits>( m_veloMCHitsLocation );
-  }
-  //
-  if(!exist<LHCb::MCHits>( m_puVetoMCHitsLocation )){
-    error()<< "There is no MCHits at MC/PuVeto/Hits in TES!" <<endmsg;
-    m_testPileUpMCHit=false;
-  }else{
-    m_veloPileUpMCHits=get<LHCb::MCHits>( m_puVetoMCHitsLocation );
-  }
-  //  
-  if(m_printInfo){
-    info()<< "----------------------------------------------------" <<endmsg;
-    if(m_testMCHit)
-      info()<< " ==> Number of MCHits found in Velo Detector: "
-            << m_veloMCHits->size() <<endmsg;
-    if(m_testPileUpMCHit)
-      info()<< " ==> Number of Pile Up MCHits found in Velo Detector: "
-            << m_veloPileUpMCHits->size() <<endmsg;
-    info()<< "---------------------------------------------------" <<endmsg;
-  }
-  //
-  return StatusCode::SUCCESS;
-}
 //
-StatusCode VeloGaussMoni::veloMCHitMonitor()
+StatusCode VeloGaussMoni::veloMCHitMonitor(const LHCb::MCHits * m_veloMCHits) const
 {
   debug()<< " ==> VeloGaussMoni::VeloMCHitMonitor " <<endmsg;
   //
-  double size=m_veloMCHits->size();
+  auto size=m_veloMCHits->size();
   m_nMCH+=size;
   m_nMCH2+=size*size;
   //
@@ -165,9 +86,8 @@ StatusCode VeloGaussMoni::veloMCHitMonitor()
        "Number of hits in Velo per event",
        0., 3000., 100);
   //
-  LHCb::MCHits::iterator It;
   // loop over all MCHits stored into the container
-  for(It=m_veloMCHits->begin(); It!=m_veloMCHits->end(); It++){
+  for(auto It=m_veloMCHits->begin(); It!=m_veloMCHits->end(); It++){
     if(m_printInfo){
       info()<< " ==> Test MCHit: \n"
             << " sensor: " << ((*It)->sensDetID())
@@ -270,11 +190,11 @@ StatusCode VeloGaussMoni::veloMCHitMonitor()
   return StatusCode::SUCCESS;
 }
 //
-StatusCode VeloGaussMoni::veloPileUpMCHitMonitor()
+StatusCode VeloGaussMoni::veloPileUpMCHitMonitor(const LHCb::MCHits *m_veloPileUpMCHits) const
 {
   debug()<< " ==> VeloGaussMoni::VeloPileUpMCHitMonitor " <<endmsg;
   //
-  double size=m_veloPileUpMCHits->size();
+  auto size=m_veloPileUpMCHits->size();
   m_nPUMCH+=size;
   m_nPUMCH2+=size*size;
   //
@@ -282,9 +202,8 @@ StatusCode VeloGaussMoni::veloPileUpMCHitMonitor()
        "Number of PileUp hits per event",
        0., 3000., 100);
   //
-  LHCb::MCHits::iterator It;
   // loop over all hits sotred into the Pile Up Hits container
-  for(It=m_veloPileUpMCHits->begin(); It!=m_veloPileUpMCHits->end(); It++){
+  for(auto It=m_veloPileUpMCHits->begin(); It!=m_veloPileUpMCHits->end(); It++){
     if(m_printInfo){
       info()<< " ==> Test Pile Up MCHit: \n"
             << " sensor: " << ((*It)->sensDetID())
@@ -343,40 +262,6 @@ StatusCode VeloGaussMoni::veloPileUpMCHitMonitor()
   return StatusCode::SUCCESS;
 }
 //
-StatusCode VeloGaussMoni::basicMonitor()
-{
-  debug()<< " ==> VeloGaussMoni::basicMonitor " <<endmsg;
-  
-  double size=0.;
-  if(m_testMCHit){
-    if(0==m_veloMCHits){
-      error()<< " -- No MCHit container retrieved! -- " <<endmsg;
-      return StatusCode::FAILURE;
-    }else{
-      debug()<< " -- Retrieved MCHit container --" <<endmsg;
-    }
-    size=m_veloMCHits->size();    
-    m_nMCH+=size;
-    m_nMCH2+=size*size;
-    plot(size, "nMCHits", "Number of MCHits per event" , 0., 3000., 100);
-  }
-  //
-  if(m_testPileUpMCHit){
-    if(0==m_veloPileUpMCHits){
-      error()<< " -- No PileUp MCHit container retrieved! -- " <<endmsg;
-      return StatusCode::FAILURE;
-    }else{
-      debug()<< " -- Retrieved PileUp MCHit container --" <<endmsg;
-    }
-    size=m_veloPileUpMCHits->size();
-    m_nPUMCH+=size;
-    m_nPUMCH2+=size*size;
-    plot(size, "nMCHitsPU", "Number of PileUp MCHits per event" , 0., 3000., 100);
-  }
-  //
-  return StatusCode::SUCCESS;
-}
-//
 StatusCode VeloGaussMoni::checkTests()
 {
   if(!(m_testMCHit||m_testPileUpMCHit)){
diff --git a/Velo/VeloGauss/src/VeloGaussMoni.h b/Velo/VeloGauss/src/VeloGaussMoni.h
index 5c57769d8..5daee8078 100755
--- a/Velo/VeloGauss/src/VeloGaussMoni.h
+++ b/Velo/VeloGauss/src/VeloGaussMoni.h
@@ -1,12 +1,14 @@
-// $Id: VeloGaussMoni.h,v 1.5 2009-03-26 22:02:12 robbep Exp $
-#ifndef VELOGAUSSMONI_H
-#define VELOGAUSSMONI_H 1
+#pragma once
 
 // Include files
 // from Gaudi
 #include "GaudiAlg/GaudiTupleAlg.h"
+#include "GaudiAlg/Consumer.h"
 #include "Event/MCHit.h"
 
+// velo
+#include "VeloDet/DeVelo.h"
+
 /** @class VeloGaussMoni VeloGaussMoni.h
  *
  *
@@ -18,44 +20,46 @@ class DeVelo;
 class DeVeloRType;
 class DeVeloPhiType;
 
-class VeloGaussMoni : public GaudiTupleAlg {
+class VeloGaussMoni
+    : public Gaudi::Functional::Consumer<void(
+          const LHCb::MCHits&, const LHCb::MCHits&),Gaudi::Functional::Traits::BaseClass_t<GaudiHistoAlg>> {
+//public GaudiTupleAlg {
 public:
   /// Standard constructor
-  VeloGaussMoni( const std::string& name, ISvcLocator* pSvcLocator );
-
-  virtual ~VeloGaussMoni( ); ///< Destructor
+  VeloGaussMoni( const std::string& name, ISvcLocator* pSvcLocator )
+      : Consumer(name, pSvcLocator,
+                 {{KeyValue{"VeloMCHits", LHCb::MCHitLocation::Velo},
+                   KeyValue{"PuVetoMCHits", LHCb::MCHitLocation::PuVeto} }}){};
 
   StatusCode initialize() override;    ///< Algorithm initialization
-  StatusCode execute   () override;    ///< Algorithm execution
   StatusCode finalize  () override;    ///< Algorithm finalization
 
+  void operator()(const LHCb::MCHits&, const LHCb::MCHits&) const override;
 protected:
 
   StatusCode checkTests();
-  StatusCode getData();
-  StatusCode veloMCHitMonitor();
-  StatusCode veloPileUpMCHitMonitor();
-  StatusCode basicMonitor();
+  StatusCode veloMCHitMonitor(const LHCb::MCHits *) const;
+  StatusCode veloPileUpMCHitMonitor(const LHCb::MCHits *) const;
 
 private:
 
-  std::string m_veloDetLocation;
+  Gaudi::Property<std::string> m_veloDetLocation{this, "VeloDetLocation", DeVeloLocation::Default};
   DeVelo* m_veloDet;
   LHCb::MCHits* m_veloMCHits;
   LHCb::MCHits* m_veloPileUpMCHits;
-  int m_print;
-  bool m_printInfo;
-  bool m_detailedMonitor;
-  bool m_testMCHit;
-  bool m_testPileUpMCHit;
-  double m_nMCH;
-  double m_nMCH2;
-  double m_nPUMCH;
-  double m_nPUMCH2;
-  int m_nEvent;
+  Gaudi::Property<int> m_print{this, "Print", 0};
+  Gaudi::Property<bool> m_printInfo{this, "PrintInfo", false};
+  Gaudi::Property<bool> m_detailedMonitor{this, "DetailedMonitor", true};
+  Gaudi::Property<bool> m_testMCHit{this, "TestMCHit", true};
+  Gaudi::Property<bool> m_testPileUpMCHit{this, "TestPileupMCHit", true};
+  mutable std::atomic_ulong m_nMCH{0};
+  mutable std::atomic_ulong m_nMCH2{0};
+  mutable std::atomic_ulong m_nPUMCH{0};
+  mutable std::atomic_ulong m_nPUMCH2{0};
+  mutable std::atomic_uint m_nEvent{0};
   /// Location of Velo MCHits
   std::string m_veloMCHitsLocation ;
   /// Location of PuVeto MCHits
   std::string m_puVetoMCHitsLocation ;
+  mutable std::mutex m_lazy_lock;
 };
-#endif // VELOGAUSSMONI_H
-- 
GitLab


From a7c3d1842e9832c3156a21f9c966795ec35afe3e Mon Sep 17 00:00:00 2001
From: Dominik Muller <dominik.muller@cern.ch>
Date: Thu, 13 Jun 2019 16:22:14 +0200
Subject: [PATCH 08/90] Prebook all histograms in initialize to avoid race
 condition with other monitoring algorithms

---
 Velo/VeloGauss/src/VeloGaussMoni.cpp | 179 +++++++++++++++------------
 Velo/VeloGauss/src/VeloGaussMoni.h   |  33 +++++
 2 files changed, 133 insertions(+), 79 deletions(-)

diff --git a/Velo/VeloGauss/src/VeloGaussMoni.cpp b/Velo/VeloGauss/src/VeloGaussMoni.cpp
index 668ff8e94..90e568dd7 100755
--- a/Velo/VeloGauss/src/VeloGaussMoni.cpp
+++ b/Velo/VeloGauss/src/VeloGaussMoni.cpp
@@ -11,6 +11,10 @@
 // local
 #include "VeloGaussMoni.h"
 
+// from AIDA
+#include "AIDA/IHistogram1D.h"
+#include "AIDA/IHistogram2D.h"
+
 // Declaration of the Algorithm Factory
 DECLARE_COMPONENT( VeloGaussMoni )
 
@@ -26,6 +30,7 @@ StatusCode VeloGaussMoni::initialize() {
   //
   m_veloDet=( getDet<DeVelo>(m_veloDetLocation ) );
   setHistoTopDir("Velo/");
+  bookHistograms();
   checkTests();
   //
   return StatusCode::SUCCESS;
@@ -82,9 +87,7 @@ StatusCode VeloGaussMoni::veloMCHitMonitor(const LHCb::MCHits * m_veloMCHits) co
   m_nMCH+=size;
   m_nMCH2+=size*size;
   //
-  plot(size, "nMCHits", 
-       "Number of hits in Velo per event",
-       0., 3000., 100);
+  m_hist_nMCHits->fill(size);
   //
   // loop over all MCHits stored into the container
   for(auto It=m_veloMCHits->begin(); It!=m_veloMCHits->end(); It++){
@@ -103,28 +106,16 @@ StatusCode VeloGaussMoni::veloMCHitMonitor(const LHCb::MCHits * m_veloMCHits) co
     }
     //
     if(m_detailedMonitor){
-    plot((*It)->energy()/Gaudi::Units::eV, "eDepSi",
-         "Energy deposited in Si [eV]",
-         0., 300000., 100);
-    plot2D((*It)->entry().z()/Gaudi::Units::cm,
-           (*It)->entry().x()/Gaudi::Units::cm, "entryZX",
-           "Particle entry point in Si [cm] - ZX plane",
-           -20., 80., -5., 5., 1000, 50);
-    plot2D((*It)->entry().x()/Gaudi::Units::cm,
-           (*It)->entry().y()/Gaudi::Units::cm, "entryXY",
-           "Particle entry point in Si [cm] - XY plane",
-           -5., 5., -5., 5., 50, 50);
-    plot2D((*It)->exit().z()/Gaudi::Units::cm,
-           (*It)->exit().x()/Gaudi::Units::cm, "exitZX",
-           "Particle exit point in Si [cm] - ZX plane",
-           -20., 80., -5., 5., 1000, 50);
-    plot2D((*It)->exit().x()/Gaudi::Units::cm,
-           (*It)->exit().y()/Gaudi::Units::cm, "exitXY",
-           "Particle exit point in Si [cm] - XY plane",
-           -5., 5., -5., 5., 50, 50);
-    plot((*It)->time()/Gaudi::Units::ns, "TOF",
-         "Time Of Flight [ns]", 
-         0., 50., 100);
+    m_hist_eDepSi->fill((*It)->energy()/Gaudi::Units::eV);
+    m_hist_entryZX->fill((*It)->entry().z()/Gaudi::Units::cm,
+           (*It)->entry().x()/Gaudi::Units::cm);
+    m_hist_entryXY->fill((*It)->entry().x()/Gaudi::Units::cm,
+           (*It)->entry().y()/Gaudi::Units::cm);
+    m_hist_exitZX->fill((*It)->exit().z()/Gaudi::Units::cm,
+           (*It)->exit().x()/Gaudi::Units::cm);
+    m_hist_exitXY->fill((*It)->exit().x()/Gaudi::Units::cm,
+           (*It)->exit().y()/Gaudi::Units::cm);
+    m_hist_TOF->fill((*It)->time()/Gaudi::Units::ns);
     //
     const DeVeloSensor* sensor=m_veloDet->sensor((*It)->sensDetID());
     double x=(*It)->entry().x()/Gaudi::Units::cm;
@@ -133,40 +124,24 @@ StatusCode VeloGaussMoni::veloMCHitMonitor(const LHCb::MCHits * m_veloMCHits) co
     //
     if(sensor->isRight()){
       if(sensor->isR()){
-        plot2D(x, y, "entryRRXY",
-               "Particle entry point in RRight [cm] - XY plane",
-               -5., 5., -5., 5., 50, 50);
-        plot2D(z, x, "entryRRZX",
-               "Particle entry point in RRight [cm] - ZX plane",
-               -20., 80., -5., 5., 1000, 50);
+        m_hist_entryRRXY->fill(x, y);
+        m_hist_entryRRZX->fill(z, x);
       }else if(sensor->isPhi()){
         if(sensor->isDownstream()){
-          plot2D(x, y, "entryPDRXY",
-                 "Particle entry point in PhiDR [cm] - XY plane",
-                 -5., 5., -5., 5., 50, 50);
+          m_hist_entryPDRXY->fill(x, y);
         }else{
-          plot2D(x, y, "entryPURXY",
-                 "Particle entry point in PhiUR [cm] - XY plane",
-                 -5., 5., -5., 5., 50, 50);
+          m_hist_entryPURXY->fill(x, y);
         }
       }
     }else{
       if(sensor->isR()){
-        plot2D(x, y, "entryRLXY",
-               "Particle entry point in RLeft [cm] - XY plane",
-               -5., 5., -5., 5., 50, 50);
-        plot2D(z, x, "entryRLZX",
-               "Particle entry point in RLeft [cm] - ZX plane",
-               -20, 80, -5., 5., 1000, 50);
+        m_hist_entryRLXY->fill(x, y);
+        m_hist_entryRLZX->fill(z, x);
       }else if(sensor->isPhi()){
         if(sensor->isDownstream()){
-          plot2D(x, y, "entryPDLXY",
-                 "Particle entry point in PhiDR [cm] - XY plane",
-                 -5., 5., -5., 5., 50, 50);
+          m_hist_entryPDLXY->fill(x, y);
         }else{    
-          plot2D(x, y, "entryPULXY",
-                 "Particle entry point in PhiUL [cm] - XY plane",
-                 -5., 5., -5., 5., 50, 50);
+          m_hist_entryPULXY->fill(x, y);
        }
       }
      }
@@ -175,9 +150,7 @@ StatusCode VeloGaussMoni::veloMCHitMonitor(const LHCb::MCHits * m_veloMCHits) co
     const LHCb::MCParticle* myMCParticle=(*It)->mcParticle();
     if(0!=myMCParticle){
       Gaudi::LorentzVector fMom=myMCParticle->momentum();
-      plot(fMom.e()/Gaudi::Units::GeV, "eMCPart",
-           "Particle energy [GeV]",
-           0., 50., 100);        
+      m_hist_eMCPart->fill(fMom.e()/Gaudi::Units::GeV);        
       if(m_printInfo){
         info()<< " ==> MCHit - MCParticle: "
               << "\np_x = " << fMom.px()/Gaudi::Units::GeV
@@ -198,9 +171,7 @@ StatusCode VeloGaussMoni::veloPileUpMCHitMonitor(const LHCb::MCHits *m_veloPileU
   m_nPUMCH+=size;
   m_nPUMCH2+=size*size;
   //
-  plot(size, "nMCPUHits",
-       "Number of PileUp hits per event",
-       0., 3000., 100);
+  m_hist_nMCPUHits->fill(size);
   //
   // loop over all hits sotred into the Pile Up Hits container
   for(auto It=m_veloPileUpMCHits->begin(); It!=m_veloPileUpMCHits->end(); It++){
@@ -219,28 +190,16 @@ StatusCode VeloGaussMoni::veloPileUpMCHitMonitor(const LHCb::MCHits *m_veloPileU
     }
     //
     if(m_detailedMonitor){
-    plot((*It)->energy()/Gaudi::Units::eV, "eDepSiPU",
-         "PileUp: Energy deposited in Si [eV]",
-         0., 300000., 100);
-    plot2D((*It)->entry().x()/Gaudi::Units::cm,
-           (*It)->entry().y()/Gaudi::Units::cm, "entryXYPU",
-           "PileUp: Particle entry point in Si [cm] - XY plane",
-           -5., 5., -5., 5., 50, 50);
-    plot2D((*It)->entry().z()/Gaudi::Units::cm,
-           (*It)->entry().x()/Gaudi::Units::cm, "entryXYPU",
-           "PileUp: Particle entry point in Si [cm] - ZX plane",
-           -40., -10., -5., 5., 1000, 50);
-    plot2D((*It)->exit().x()/Gaudi::Units::cm,
-           (*It)->exit().y()/Gaudi::Units::cm, "exitXYPU",
-           "PileUp: Particle exit point in Si [cm] - XY plane",
-           -5., 5., -5., 5., 50, 50);
-    plot2D((*It)->exit().z()/Gaudi::Units::cm,
-           (*It)->exit().x()/Gaudi::Units::cm, "exitZXPU",
-           "PileUp: Particle exit point in Si [cm] - ZX plane",
-           -40., -10., -5., 5., 1000, 50);
-    plot((*It)->time()/Gaudi::Units::ns, "TOFPU",
-         "PileUp: Time Of Flight [ns]",
-         0., 50., 100);
+    m_hist_eDepSiPU->fill((*It)->energy()/Gaudi::Units::eV);
+    m_hist_entryXYPU->fill((*It)->entry().x()/Gaudi::Units::cm,
+           (*It)->entry().y()/Gaudi::Units::cm);
+    m_hist_entryZXPU->fill((*It)->entry().z()/Gaudi::Units::cm,
+           (*It)->entry().x()/Gaudi::Units::cm);
+    m_hist_exitXYPU->fill((*It)->exit().x()/Gaudi::Units::cm,
+           (*It)->exit().y()/Gaudi::Units::cm);
+    m_hist_exitZXPU->fill((*It)->exit().z()/Gaudi::Units::cm,
+           (*It)->exit().x()/Gaudi::Units::cm);
+    m_hist_TOFPU->fill((*It)->time()/Gaudi::Units::ns);
     }
    // get access to the MCParticle which made the hit, and write out 4-mom
    const LHCb::MCParticle* myMCParticle=(*It)->mcParticle();
@@ -270,5 +229,67 @@ StatusCode VeloGaussMoni::checkTests()
   }
   //
   return StatusCode::SUCCESS;
-}   
-//=============================================================================
+}
+
+void VeloGaussMoni::bookHistograms() {
+  m_hist_nMCHits =
+      book1D("nMCHits", "Number of hits in Velo per event", 0., 3000., 100);
+  m_hist_eDepSi =
+      book("eDepSi", "Energy deposited in Si [eV]", 0., 300000., 100);
+  m_hist_TOF = book("TOF", "Time Of Flight [ns]", 0., 50., 100);
+  m_hist_entryZX =
+      book2D("entryZX", "Particle entry point in Si [cm] - ZX plane", -20., 80.,
+             1000, -5., 5., 50);
+  m_hist_entryXY =
+      book2D("entryXY", "Particle entry point in Si [cm] - XY plane", -5., 5.,
+             50, -5., 5., 50);
+  m_hist_exitZX = book2D("exitZX", "Particle exit point in Si [cm] - ZX plane",
+                         -20., 80., 1000, -5., 5., 50);
+  m_hist_exitXY = book2D("exitXY", "Particle exit point in Si [cm] - XY plane",
+                         -5., 5., 50, -5., 5., 50);
+
+  m_hist_entryRRXY =
+      book2D("entryRRXY", "Particle entry point in RRight [cm] - XY plane", -5.,
+             5., 50, -5., 5., 50);
+  m_hist_entryRRZX =
+      book2D("entryRRZX", "Particle entry point in RRight [cm] - ZX plane",
+             -20., 80., 1000, -5., 5., 50);
+  m_hist_entryPDRXY =
+      book2D("entryPDRXY", "Particle entry point in PhiDR [cm] - XY plane", -5.,
+             5., 50, -5., 5., 50);
+  m_hist_entryPURXY =
+      book2D("entryPURXY", "Particle entry point in PhiUR [cm] - XY plane", -5.,
+             5., 50, -5., 5., 50);
+  m_hist_entryRLXY =
+      book2D("entryRLXY", "Particle entry point in RLeft [cm] - XY plane", -5.,
+             5., 50, -5., 5., 50);
+  m_hist_entryRLZX =
+      book2D("entryRLZX", "Particle entry point in RLeft [cm] - ZX plane", -20,
+             80, 1000, -5., 5., 50);
+  m_hist_entryPDLXY =
+      book2D("entryPDLXY", "Particle entry point in PhiDR [cm] - XY plane", -5.,
+             5., 50, -5., 5., 50);
+  m_hist_entryPULXY =
+      book2D("entryPULXY", "Particle entry point in PhiUL [cm] - XY plane", -5.,
+             5., 50, -5., 5., 50);
+
+  m_hist_eMCPart = book("eMCPart", "Particle energy [GeV]", 0., 50., 100);
+
+  m_hist_nMCPUHits =
+      book1D("nMCPUHits", "PileUp: Number of hits in Velo per event", 0., 3000., 100);
+  m_hist_eDepSiPU =
+      book("eDepSiPU", "PileUp: Energy deposited in Si [eV]", 0., 300000., 100);
+  m_hist_TOFPU = book("TOFPU", "PileUp: Time Of Flight [ns]", 0., 50., 100);
+  m_hist_entryZXPU =
+      book2D("entryZXPU", "PileUp: Particle entry point in Si [cm] - ZX plane", -20., 80.,
+             1000, -5., 5., 50);
+  m_hist_entryXYPU =
+      book2D("entryXYPU", "PileUp: Particle entry point in Si [cm] - XY plane", -5., 5.,
+             50, -5., 5., 50);
+  m_hist_exitZXPU = book2D("exitZXPU", "PileUp: Particle exit point in Si [cm] - ZX plane",
+                         -20., 80., 1000, -5., 5., 50);
+  m_hist_exitXYPU = book2D("exitXYPU", "PileUp: Particle exit point in Si [cm] - XY plane",
+                         -5., 5., 50, -5., 5., 50);
+
+  m_hist_eMCPartPU = book("eMCPartPU", "PileUp: Particle energy [GeV]", 0., 50., 100);
+}
diff --git a/Velo/VeloGauss/src/VeloGaussMoni.h b/Velo/VeloGauss/src/VeloGaussMoni.h
index 5daee8078..758baf24d 100755
--- a/Velo/VeloGauss/src/VeloGaussMoni.h
+++ b/Velo/VeloGauss/src/VeloGaussMoni.h
@@ -43,6 +43,8 @@ protected:
 
 private:
 
+  void bookHistograms();
+
   Gaudi::Property<std::string> m_veloDetLocation{this, "VeloDetLocation", DeVeloLocation::Default};
   DeVelo* m_veloDet;
   LHCb::MCHits* m_veloMCHits;
@@ -62,4 +64,35 @@ private:
   /// Location of PuVeto MCHits
   std::string m_puVetoMCHitsLocation ;
   mutable std::mutex m_lazy_lock;
+
+  AIDA::IHistogram1D* m_hist_nMCHits{nullptr};
+  AIDA::IHistogram1D* m_hist_eDepSi{nullptr};
+  AIDA::IHistogram1D* m_hist_TOF{nullptr};
+
+  AIDA::IHistogram2D* m_hist_entryZX{nullptr};
+  AIDA::IHistogram2D* m_hist_entryXY{nullptr};
+  AIDA::IHistogram2D* m_hist_exitZX{nullptr};
+  AIDA::IHistogram2D* m_hist_exitXY{nullptr};
+
+  AIDA::IHistogram2D* m_hist_entryRRXY{nullptr};
+  AIDA::IHistogram2D* m_hist_entryRRZX{nullptr};
+  AIDA::IHistogram2D* m_hist_entryPDRXY{nullptr};
+  AIDA::IHistogram2D* m_hist_entryPURXY{nullptr};
+  AIDA::IHistogram2D* m_hist_entryRLXY{nullptr};
+  AIDA::IHistogram2D* m_hist_entryRLZX{nullptr};
+  AIDA::IHistogram2D* m_hist_entryPDLXY{nullptr};
+  AIDA::IHistogram2D* m_hist_entryPULXY{nullptr};
+
+  AIDA::IHistogram1D* m_hist_eMCPart{nullptr};
+
+  AIDA::IHistogram1D* m_hist_nMCPUHits{nullptr};
+  AIDA::IHistogram1D* m_hist_eDepSiPU{nullptr};
+  AIDA::IHistogram1D* m_hist_TOFPU{nullptr};
+
+  AIDA::IHistogram2D* m_hist_entryZXPU{nullptr};
+  AIDA::IHistogram2D* m_hist_entryXYPU{nullptr};
+  AIDA::IHistogram2D* m_hist_exitZXPU{nullptr};
+  AIDA::IHistogram2D* m_hist_exitXYPU{nullptr};
+
+  AIDA::IHistogram1D* m_hist_eMCPartPU{nullptr};
 };
-- 
GitLab


From db0174ea09c7c201f56e549027cb37eb06826b72 Mon Sep 17 00:00:00 2001
From: Dominik Muller <dominik.muller@cern.ch>
Date: Thu, 13 Jun 2019 17:18:19 +0200
Subject: [PATCH 09/90] Ported MuonHitChecker and changed to prebooking of
 histograms during initialize.

---
 Muon/MuonMoniSim/CMakeLists.txt         |   2 +-
 Muon/MuonMoniSim/src/MuonHitChecker.cpp | 405 ++++++++++++------------
 Muon/MuonMoniSim/src/MuonHitChecker.h   |  61 ++--
 3 files changed, 235 insertions(+), 233 deletions(-)

diff --git a/Muon/MuonMoniSim/CMakeLists.txt b/Muon/MuonMoniSim/CMakeLists.txt
index 94e523710..7084baaf2 100644
--- a/Muon/MuonMoniSim/CMakeLists.txt
+++ b/Muon/MuonMoniSim/CMakeLists.txt
@@ -14,7 +14,7 @@ find_package(ROOT)
 include_directories(SYSTEM ${Boost_INCLUDE_DIRS} ${ROOT_INCLUDE_DIRS})
 
 gaudi_add_module(MuonMoniSim
-                 src/*.cpp
+                 src/MuonHitChecker.cpp
                  INCLUDE_DIRS AIDA
                  LINK_LIBRARIES MuonDetLib MCEvent GaudiAlgLib)
 
diff --git a/Muon/MuonMoniSim/src/MuonHitChecker.cpp b/Muon/MuonMoniSim/src/MuonHitChecker.cpp
index c0cd87db1..27c01c6c8 100755
--- a/Muon/MuonMoniSim/src/MuonHitChecker.cpp
+++ b/Muon/MuonMoniSim/src/MuonHitChecker.cpp
@@ -1,12 +1,12 @@
 // $Id: MuonHitChecker.cpp,v 1.12 2009-06-15 16:57:49 gcorti Exp $
-// Include files 
+// Include files
 
 // from Gaudi
 
 // local
-#include "MuonDet/DeMuonDetector.h"
 #include "MuonHitChecker.h"
-#include "Event/MCHeader.h"
+#include "MuonDet/DeMuonDetector.h"
+#include "AIDA/IHistogram1D.h"
 
 //-----------------------------------------------------------------------------
 // This File contains the monitor for muon Hit system
@@ -17,265 +17,250 @@
 //-----------------------------------------------------------------------------
 
 // Declaration of the Algortihm Factory
-DECLARE_COMPONENT( MuonHitChecker )
-
-//=============================================================================
-// Standard constructor, initializes variables
-//=============================================================================
-MuonHitChecker::MuonHitChecker( const std::string& name,
-				ISvcLocator* pSvcLocator)
-  : GaudiTupleAlg ( name , pSvcLocator )   
-{
-  declareProperty( "DetailedMonitor"         ,m_detailedMonitor=false );
-  declareProperty( "MCHeader" , m_mcHeader = LHCb::MCHeaderLocation::Default ) ;
-  declareProperty( "MuonHits" , m_muonHits = LHCb::MCHitLocation::Muon ) ;
-  m_hit_outside_gaps=0;
-  
-}
-
-//=============================================================================
-// Destructor
-//=============================================================================
-MuonHitChecker::~MuonHitChecker() {}
+DECLARE_COMPONENT(MuonHitChecker)
 
-//=============================================================================
-// Initialisation. Check parameters
-//=============================================================================
 StatusCode MuonHitChecker::initialize() {
+  StatusCode sc = GaudiHistoAlg::initialize(); // must be executed first
+  if ( sc.isFailure() ) return sc;  // error printed already by GaudiAlgorithm
 
-  StatusCode sc = GaudiTupleAlg::initialize();
-  if (sc.isFailure()){
-    return Error("Failed to initialize", sc);
-  }
-  
-  debug() << "==> Initialise" << endmsg;
-
-  for(int i=0; i<5; i++) {
-    nhit_ri[i] = cnt_ri[i] = 0;
-    for(int j=0; j<4; j++) {
-      nhit[i][j] = cnt[i][j] = 0;
-    }
-  }
-
+  debug() << "==> Initialize" << endmsg;
+  bookHistograms();
   return StatusCode::SUCCESS;
 }
 
 //=============================================================================
 // Main execution
 //=============================================================================
-StatusCode MuonHitChecker::execute() {
+void MuonHitChecker::operator()(const LHCb::MCHits& hits,
+                                const LHCb::MCHeader& header) const {
 
-  const LHCb::MCHeader* evt = get<LHCb::MCHeader>( m_mcHeader );
-
-  long  m_evt = evt->evtNumber();
+  long m_evt = header.evtNumber();
+  std::lock_guard<std::mutex> guard_lock(m_lazy_lock);
 
   debug() << "==> Execute MuonHitChecker" << endmsg;
   // Header
 
-  int tnhit[5][4];    int tnhit_ri[5];  int tmhit_ri[5];  
-  for(int i=0; i<5; i++) {
-    tnhit_ri[i] = 0; tmhit_ri[i] = 0;
-    for(int j=0; j<4; j++) {
+  int tnhit[5][4];
+  int tnhit_ri[5];
+  int tmhit_ri[5];
+  for (int i = 0; i < 5; i++) {
+    tnhit_ri[i] = 0;
+    tmhit_ri[i] = 0;
+    for (int j = 0; j < 4; j++) {
       tnhit[i][j] = 0;
     }
   }
-  
 
-  std::vector<float> m_sta,m_reg,m_con,m_x,m_y,m_z,m_time;
-  std::vector<float> m_id,m_px,m_py,m_pz,m_E,m_xv,m_yv,m_zv,m_tv, m_mom;
-  std::vector<float> m_ple,m_hen,m_dix,m_dxz,m_dyz;
+  std::vector<float> m_sta, m_reg, m_con, m_x, m_y, m_z, m_time;
+  std::vector<float> m_id, m_px, m_py, m_pz, m_E, m_xv, m_yv, m_zv, m_tv, m_mom;
+  std::vector<float> m_ple, m_hen, m_dix, m_dxz, m_dyz;
 
-  DeMuonDetector * muonD = getDet<DeMuonDetector>("/dd/Structure/LHCb/DownstreamRegion/Muon"); 
+  DeMuonDetector* muonD =
+      getDet<DeMuonDetector>("/dd/Structure/LHCb/DownstreamRegion/Muon");
 
   // get the MCHits
-  SmartDataPtr<LHCb::MCHits> hits(eventSvc() , m_muonHits );
-  
-  LHCb::MCHits::const_iterator iter;
   int MyDetID;
   // Loop over Muon Hits of given type
-  if(hits!=0){
-    for (iter = hits->begin(); iter < hits->end();iter++){
-      
-      MyDetID = (*iter)->sensDetID();
-      if(MyDetID<0) m_hit_outside_gaps++;
-      if(MyDetID<0) continue;
-      
-      //Needs to extract info from sens ID      
-      int station = muonD->stationID(MyDetID);  
-      
-      int region  = muonD->regionID(MyDetID);   
-
-      //int chamber = muonD->chamberID(MyDetID);        
-
-      debug()<<" Station, Region :: " <<station<<" "<<region<<endmsg;
-  
-      float xpos=((*iter)->entry().x()+(*iter)->exit().x())/2.0;
-      float ypos=((*iter)->entry().y()+(*iter)->exit().y())/2.0;
-      float zpos=((*iter)->entry().z()+(*iter)->exit().z())/2.0;
-      float time=(*iter)->time();
-      
-      //New monitored quantities
-      float plen=(*iter)->pathLength();
-      float hene=(*iter)->energy();
-      float hdis=(*iter)->displacement().x();
-      float hdxz=(*iter)->dxdz();
-      float hdyz=(*iter)->dydz();
-      
-      //Temporary monitoring (need to check if already available)
-      m_ple.push_back(plen);
-      m_hen.push_back(hene);
-      m_dix.push_back(hdis);
-      m_dxz.push_back(hdxz);
-      m_dyz.push_back(hdyz);
-      
-      double tof=time-sqrt(xpos*xpos+ypos*ypos+zpos*zpos)/300.0;
-      if(tof<0.1)tof=0.1;
-      float r=sqrt(xpos*xpos+ypos*ypos);
-      
-      m_sta.push_back(station);
-      m_reg.push_back(region);
-      //Only Geant Container available
-      m_con.push_back(0);
-      
-      m_x.push_back(xpos); m_y.push_back(ypos); m_z.push_back(zpos);
-      m_time.push_back(time);
-      
-      //Fill some histos	  
-      int hh =station*4+region;
-      if (fullDetail() == true) {
-	plot( r, hh+2000, "Radial Multiplicity", 0., 6000.,200 );
-	plot(tof,hh+1000, "Time multiplicity",   0.,  100.,200 ); 
+  for (auto& hit : hits) {
+    MyDetID = hit->sensDetID();
+    if (MyDetID < 0) m_hit_outside_gaps++;
+    if (MyDetID < 0) continue;
+
+    // Needs to extract info from sens ID
+    int station = muonD->stationID(MyDetID);
+
+    int region = muonD->regionID(MyDetID);
+
+    // int chamber = muonD->chamberID(MyDetID);
+
+    debug() << " Station, Region :: " << station << " " << region << endmsg;
+
+    float xpos = (hit->entry().x() + hit->exit().x()) / 2.0;
+    float ypos = (hit->entry().y() + hit->exit().y()) / 2.0;
+    float zpos = (hit->entry().z() + hit->exit().z()) / 2.0;
+    float time = hit->time();
+
+    // New monitored quantities
+    float plen = hit->pathLength();
+    float hene = hit->energy();
+    float hdis = hit->displacement().x();
+    float hdxz = hit->dxdz();
+    float hdyz = hit->dydz();
+
+    // Temporary monitoring (need to check if already available)
+    m_ple.push_back(plen);
+    m_hen.push_back(hene);
+    m_dix.push_back(hdis);
+    m_dxz.push_back(hdxz);
+    m_dyz.push_back(hdyz);
+
+    double tof = time - sqrt(xpos * xpos + ypos * ypos + zpos * zpos) / 300.0;
+    if (tof < 0.1) tof = 0.1;
+    float r = sqrt(xpos * xpos + ypos * ypos);
+
+    m_sta.push_back(station);
+    m_reg.push_back(region);
+    // Only Geant Container available
+    m_con.push_back(0);
+
+    m_x.push_back(xpos);
+    m_y.push_back(ypos);
+    m_z.push_back(zpos);
+    m_time.push_back(time);
+
+    // Fill some histos
+    unsigned int hh = station * m_nBookRegions + region;
+    if (fullDetail() == true) {
+      if(m_histos.find(hh+2000) != std::end(m_histos)){
+        m_histos[hh + 2000]->fill(r);
+      }
+      if(m_histos.find(hh+1000) != std::end(m_histos)){
+      m_histos[hh + 1000]->fill(tof);
       }
-      
-      //MC truth
-      const LHCb::MCParticle* particle=(*iter)->mcParticle();
-      if(particle){            
-	if(abs(particle->particleID().pid())<100000){
-	  m_id.push_back(particle->particleID().pid());
-	}
-	
-	m_px.push_back(particle->momentum().px());
-	m_py.push_back(particle->momentum().py());
-	//Pz sign tells you the particle direction
-	m_pz.push_back(particle->momentum().pz());
-	m_E.push_back(particle->momentum().e());
-	
-	//Particle Vertex studies	    
-	m_xv.push_back(particle->originVertex()->position().x());
-	m_yv.push_back(particle->originVertex()->position().y());
-	m_zv.push_back(particle->originVertex()->position().z());
-	m_tv.push_back(particle->originVertex()->time());
-	
-	const LHCb::MCParticle * moth=particle->mother();
-	if(moth && (abs(moth->particleID().pid())<100000)){
-	  m_mom.push_back(moth->particleID().pid()); 
-	} else {
-	  m_mom.push_back(0);
-	}
+    }
+
+    // MC truth
+    const LHCb::MCParticle* particle = hit->mcParticle();
+    if (particle) {
+      if (abs(particle->particleID().pid()) < 100000) {
+        m_id.push_back(particle->particleID().pid());
+      }
+
+      m_px.push_back(particle->momentum().px());
+      m_py.push_back(particle->momentum().py());
+      // Pz sign tells you the particle direction
+      m_pz.push_back(particle->momentum().pz());
+      m_E.push_back(particle->momentum().e());
+
+      // Particle Vertex studies
+      m_xv.push_back(particle->originVertex()->position().x());
+      m_yv.push_back(particle->originVertex()->position().y());
+      m_zv.push_back(particle->originVertex()->position().z());
+      m_tv.push_back(particle->originVertex()->time());
+
+      const LHCb::MCParticle* moth = particle->mother();
+      if (moth && (abs(moth->particleID().pid()) < 100000)) {
+        m_mom.push_back(moth->particleID().pid());
       } else {
-	m_id.push_back(0);	    m_px.push_back(0);	    m_py.push_back(0);
-	m_pz.push_back(0);	    m_E.push_back(0);	    m_xv.push_back(0);
-	m_yv.push_back(0);	    m_zv.push_back(0);	    m_tv.push_back(0);
-	m_mom.push_back(0);
-      }          
-      
-      if(abs(particle->particleID().pid()) == 13) tmhit_ri[station]++;
-      tnhit[station][region]++;
-      tnhit_ri[station]++;
+        m_mom.push_back(0);
+      }
+    } else {
+      m_id.push_back(0);
+      m_px.push_back(0);
+      m_py.push_back(0);
+      m_pz.push_back(0);
+      m_E.push_back(0);
+      m_xv.push_back(0);
+      m_yv.push_back(0);
+      m_zv.push_back(0);
+      m_tv.push_back(0);
+      m_mom.push_back(0);
     }
+
+    if (abs(particle->particleID().pid()) == 13) tmhit_ri[station]++;
+    tnhit[station][region]++;
+    tnhit_ri[station]++;
   }
 
-  for(int s=0; s<5; s++) {
-    //Looking at mean number of hits (intregrated over regions)
+  for (int s = 0; s < 5; s++) {
+    // Looking at mean number of hits (intregrated over regions)
     cnt_ri[s]++;
-    nhit_ri[s]+= tnhit_ri[s];
-    for(int r=0; r<4; r++) {
-      //Looking at mean number of hits
+    nhit_ri[s] += tnhit_ri[s];
+    for (int r = 0; r < 4; r++) {
+      // Looking at mean number of hits
       cnt[s][r]++;
-      nhit[s][r]+= tnhit[s][r];
-    }  
-  }  
+      nhit[s][r] += tnhit[s][r];
+    }
+  }
 
   // book vectors of histos
-  if(m_detailedMonitor == true) { 
-
-    Tuple nt1 = nTuple(1,"MC HITS",CLID_ColumnWiseTuple);
-    info() << "Doing ntuple stuff"
-           << endmsg;
+  if (m_detailedMonitor == true) {
+    Tuple nt1 = nTuple(1, "MC HITS", CLID_ColumnWiseTuple);
+    info() << "Doing ntuple stuff" << endmsg;
     //    nt1->column("Run", m_run,0,1000000);
-    int pippo=m_evt;
-    nt1->column("Event",pippo,0,10000);
-
-    nt1->farray("is", m_sta ,"Nhits",1000);
-    nt1->farray("ir", m_reg ,"Nhits",1000);
-    nt1->farray("ic", m_con ,"Nhits",1000);
-    nt1->farray("x",  m_x   ,"Nhits",1000);
-    nt1->farray("y",  m_y   ,"Nhits",1000);
-    nt1->farray("z",  m_z   ,"Nhits",1000);
-    nt1->farray("t",  m_time,"Nhits",1000);
-    nt1->farray("id", m_id  ,"Nhits",1000);
-    nt1->farray("px", m_px  ,"Nhits",1000);
-    nt1->farray("py", m_py  ,"Nhits",1000);
-    nt1->farray("pz", m_pz  ,"Nhits",1000);
-    nt1->farray("E",  m_E   ,"Nhits",1000);
-    nt1->farray("xv", m_xv  ,"Nhits",1000);
-    nt1->farray("yv", m_yv  ,"Nhits",1000);
-    nt1->farray("zv", m_zv  ,"Nhits",1000);
-    nt1->farray("tv", m_tv  ,"Nhits",1000);
-    nt1->farray("idm",m_mom ,"Nhits",1000);
-    nt1->farray("pl", m_ple ,"Nhits",1000);
-    nt1->farray("he", m_hen ,"Nhits",1000);
-    nt1->farray("dx", m_dix ,"Nhits",1000);
-    nt1->farray("xz", m_dxz ,"Nhits",1000);
-    nt1->farray("yz", m_dyz ,"Nhits",1000);
-    nt1->write(); 
-  }
-   
+    int pippo = m_evt;
+    nt1->column("Event", pippo, 0, 10000);
 
-  return StatusCode::SUCCESS;
+    nt1->farray("is", m_sta, "Nhits", 1000);
+    nt1->farray("ir", m_reg, "Nhits", 1000);
+    nt1->farray("ic", m_con, "Nhits", 1000);
+    nt1->farray("x", m_x, "Nhits", 1000);
+    nt1->farray("y", m_y, "Nhits", 1000);
+    nt1->farray("z", m_z, "Nhits", 1000);
+    nt1->farray("t", m_time, "Nhits", 1000);
+    nt1->farray("id", m_id, "Nhits", 1000);
+    nt1->farray("px", m_px, "Nhits", 1000);
+    nt1->farray("py", m_py, "Nhits", 1000);
+    nt1->farray("pz", m_pz, "Nhits", 1000);
+    nt1->farray("E", m_E, "Nhits", 1000);
+    nt1->farray("xv", m_xv, "Nhits", 1000);
+    nt1->farray("yv", m_yv, "Nhits", 1000);
+    nt1->farray("zv", m_zv, "Nhits", 1000);
+    nt1->farray("tv", m_tv, "Nhits", 1000);
+    nt1->farray("idm", m_mom, "Nhits", 1000);
+    nt1->farray("pl", m_ple, "Nhits", 1000);
+    nt1->farray("he", m_hen, "Nhits", 1000);
+    nt1->farray("dx", m_dix, "Nhits", 1000);
+    nt1->farray("xz", m_dxz, "Nhits", 1000);
+    nt1->farray("yz", m_dyz, "Nhits", 1000);
+    nt1->write();
+  }
 }
 //=============================================================================
 //  Finalize
 //=============================================================================
 StatusCode MuonHitChecker::finalize() {
- info() << "-----------------------------------------------------------------"
-	 << endmsg;
+  info() << "-----------------------------------------------------------------"
+         << endmsg;
   info() << "       Muon Monitoring Table " << endmsg;
   info() << "-----------------------------------------------------------------"
-	 << endmsg;
-  info()<<" M1        M2        M3        M4        M5 "<<endmsg;
-  for(int r=0; r<4; r++) {
-    for(int s=0; s<5; s++) {
-      if(cnt[s][r])  {
-	info()<<format("%5.3lf  ",(double)nhit[s][r]/cnt[s][r]);
-	//	info()<<(double)nhit[s][r]/cnt[s][r]<<"     ";
+         << endmsg;
+  info() << " M1        M2        M3        M4        M5 " << endmsg;
+  for (int r = 0; r < 4; r++) {
+    for (int s = 0; s < 5; s++) {
+      if (cnt[s][r]) {
+        info() << format("%5.3lf  ", (double)nhit[s][r] / cnt[s][r]);
+        //	info()<<(double)nhit[s][r]/cnt[s][r]<<"     ";
       } else {
-	info()<<"0.000  ";
+        info() << "0.000  ";
       }
     }
-    info()<<" R"<<r+1<<endmsg;
+    info() << " R" << r + 1 << endmsg;
   }
   info() << "-----------------------------------------------------------------"
-	 << endmsg;
+         << endmsg;
   info() << "-------    Integrated over regions    ---------------------------"
-	 << endmsg;
+         << endmsg;
   info() << "-----------------------------------------------------------------"
-	 << endmsg;
-  for(int s=0; s<5; s++) {
-    if(cnt_ri[s])  {
-      info()<<format("%5.3lf  ",(double)nhit_ri[s]/cnt_ri[s]);
+         << endmsg;
+  for (int s = 0; s < 5; s++) {
+    if (cnt_ri[s]) {
+      info() << format("%5.3lf  ", (double)nhit_ri[s] / cnt_ri[s]);
       //	info()<<(double)nhit[s][r]/cnt[s][r]<<"     ";
     } else {
-      info()<<"0.000  ";
+      info() << "0.000  ";
     }
   }
-  info()<<" allR"<<endmsg;
-  info()<<" number of hits generated outside gaps volume "<<  m_hit_outside_gaps<<endmsg;
-  
-  return StatusCode::SUCCESS; // what was here before but this doesn't finalise the GaudiTupleAlg like in the multiplescattering checker 
-  
-  // return GaudiTupleAlg::finalize();
-}
+  info() << " allR" << endmsg;
+  info() << " number of hits generated outside gaps volume "
+         << m_hit_outside_gaps << endmsg;
 
+  return StatusCode::SUCCESS;  // what was here before but this doesn't finalise
+                               // the GaudiTupleAlg like in the
+                               // multiplescattering checker
 
+  // return GaudiTupleAlg::finalize();
+}
 
+void MuonHitChecker::bookHistograms() {
+  if (!fullDetail()) {
+    return;
+  }
+  for (unsigned int station = 0; station < m_nBookStations; station++) {
+    for (unsigned int region = 0; region < m_nBookRegions; region++) {
+      int hh = station * m_nBookRegions + region;
+      m_histos[hh + 2000] = book(hh + 2000, "Radial Multiplicity", 0., 6000., 200);
+      m_histos[hh + 1000] = book(hh + 1000, "Time multiplicity", 0., 100., 200);
+    }
+  }
+}
diff --git a/Muon/MuonMoniSim/src/MuonHitChecker.h b/Muon/MuonMoniSim/src/MuonHitChecker.h
index 48172606d..2dfe3acc5 100755
--- a/Muon/MuonMoniSim/src/MuonHitChecker.h
+++ b/Muon/MuonMoniSim/src/MuonHitChecker.h
@@ -1,6 +1,4 @@
-// $Id: MuonHitChecker.h,v 1.6 2009-03-26 21:59:02 robbep Exp $
-#ifndef MuonHitChecker_H
-#define MuonHitChecker_H 1
+#pragma once
 
 // Include files
 // from STL
@@ -10,39 +8,58 @@
 #include "GaudiAlg/GaudiTupleAlg.h"
 
 // for Muons
+#include "Event/MCHeader.h"
 #include "Event/MCHit.h"
+#include "GaudiAlg/Consumer.h"
+#include "GaudiAlg/GaudiTupleAlg.h"
 
+namespace AIDA {
+  class IHistogram1D;
+}
 /** @class MuonHitChecker MuonHitChecker.h
  *
  *
  *  @author A Sarti
  *  @date   2005-05-20
+ *  @author Dominik Muller
+ *  @date   2005-05-20
  */
-class MuonHitChecker : public GaudiTupleAlg {
-public:
+class MuonHitChecker
+    : public Gaudi::Functional::Consumer<
+          void(const LHCb::MCHits&, const LHCb::MCHeader&),
+          Gaudi::Functional::Traits::BaseClass_t<GaudiTupleAlg>> {
+  public:
   /// Standard constructor
-  MuonHitChecker( const std::string& name, ISvcLocator* pSvcLocator );
-
-  virtual ~MuonHitChecker( ); ///< Destructor
-  StatusCode initialize() override;    ///< Algorithm initialization
-  StatusCode execute   () override;    ///< Algorithm execution
-  StatusCode finalize  () override;    ///< Algorithm finalization
+  MuonHitChecker(const std::string& name, ISvcLocator* pSvcLocator)
+      : Consumer(name, pSvcLocator,
+                 {{KeyValue{"MuonHits", LHCb::MCHitLocation::Muon},
+                   KeyValue{"MCHeader", LHCb::MCHeaderLocation::Default}}}) {
+    for (int i = 0; i < 5; i++) {
+      nhit_ri[i] = cnt_ri[i] = 0;
+      for (int j = 0; j < 4; j++) {
+        nhit[i][j] = cnt[i][j] = 0;
+      }
+    }
+  };
 
-  bool m_detailedMonitor; //was in private
+  void operator()(const LHCb::MCHits&, const LHCb::MCHeader&) const override;
+  StatusCode finalize() override;
+  StatusCode initialize() override;
 
-protected:
+  Gaudi::Property<bool> m_detailedMonitor{this, "DetailedMonitor", false};
+  Gaudi::Property<unsigned int> m_nBookStations{this, "NBookStations", 5};
+  Gaudi::Property<unsigned int> m_nBookRegions{this, "NBookRegions", 4};
 
+  protected:
   std::vector<int> m_numberOfGaps;
 
-private:
-
-  int nhit[5][4],cnt[5][4];
-  int nhit_ri[5],cnt_ri[5];
-
+  private:
+  mutable std::mutex m_lazy_lock;
+  mutable int nhit[5][4], cnt[5][4];
+  mutable int nhit_ri[5], cnt_ri[5];
+  mutable std::map<unsigned int, AIDA::IHistogram1D*> m_histos;
 
-  int m_hit_outside_gaps;
+  mutable std::atomic_uint m_hit_outside_gaps{0};
 
-  std::string m_mcHeader ; ///< Location of MC Header
-  std::string m_muonHits ; ///< Location of muon hits
+  void bookHistograms();
 };
-#endif // MuonHitChecker_H
-- 
GitLab


From 909e0fd2067d74187c35cbc5f8faf130dc21c599 Mon Sep 17 00:00:00 2001
From: Dominik Muller <dominik.muller@cern.ch>
Date: Thu, 13 Jun 2019 17:21:40 +0200
Subject: [PATCH 10/90] Added MT magnetic field support to GaussGeo using
 Gaussino functionality

---
 .../python/Gauss/Geometry/Configuration.py    |   2 +
 Sim/Gauss/python/Gauss/Geometry/Magnet.py     |  23 +-
 Sim/Gauss/python/Gauss/Geometry/Muon.py       |   6 +
 Sim/GaussGeo/src/component/GaussGeo.cpp       | 200 ++++++------------
 Sim/GaussGeo/src/component/GaussGeo.h         |   9 +-
 5 files changed, 93 insertions(+), 147 deletions(-)

diff --git a/Sim/Gauss/python/Gauss/Geometry/Configuration.py b/Sim/Gauss/python/Gauss/Geometry/Configuration.py
index 10b865b8d..7dc7e3260 100644
--- a/Sim/Gauss/python/Gauss/Geometry/Configuration.py
+++ b/Sim/Gauss/python/Gauss/Geometry/Configuration.py
@@ -132,6 +132,8 @@ class LHCbGeo(LHCbConfigurableUser):
         for det in detectors_geo:
             getsubdetector(det).ApplyStream()
 
+        getsubdetector("Magnet").defineMagnetGeoField()
+
         # FIXME: those calo option files
         # Seperate Calo opts
         # Returns a list containing all the elments common to both lists
diff --git a/Sim/Gauss/python/Gauss/Geometry/Magnet.py b/Sim/Gauss/python/Gauss/Geometry/Magnet.py
index 34bd5a6fb..17f8d9d97 100644
--- a/Sim/Gauss/python/Gauss/Geometry/Magnet.py
+++ b/Sim/Gauss/python/Gauss/Geometry/Magnet.py
@@ -6,27 +6,24 @@ from Gauss.Geometry.Helpers import subdetector
 class Magnet(det_base):
 
     def ApplyDetector(self, basePieces, detPieces):
-        path = "dd/Structure/LHCb/MagnetRegion/"
-        detPieces["MagnetRegion"] = ['Magnet','BcmDown']
+        detPieces["MagnetRegion"] = ['Magnet', 'BcmDown']
 
-    def defineMagnetGeoField( self ):
-        from Configurables import GaussGeo
+    def defineMagnetGeoField(self):
+        from Configurables import GaussGeo, ToolFieldMgr, MagFieldFromSvc
         from Gauss.Geometry.Helpers import getsubdetector
         # Only bother with the FIELD Geometry if simulated.
-        simDets = self.getProp('DetectorSim')['Detectors']
         if getsubdetector("Magnet").Simulate or getsubdetector("HC").Simulate:
-            GaussGeo().FieldManager           = "GiGaFieldMgr/FieldMgr"
-            GaussGeo().addTool( GiGaFieldMgr("FieldMgr"), name="FieldMgr" )
-            GaussGeo().FieldMgr.Stepper       = "ClassicalRK4"
-            GaussGeo().FieldMgr.Global        = True
-            GaussGeo().FieldMgr.MagneticField = "GiGaMagFieldGlobal/LHCbField"
-            GaussGeo().FieldMgr.addTool( GiGaMagFieldGlobal("LHCbField"), name="LHCbField" )
-            GaussGeo().FieldMgr.LHCbField.MagneticFieldService = "MagneticFieldSvc"
+            GaussGeo().FieldManager = "ToolFieldMgr/FieldMgr"
+            GaussGeo().addTool(ToolFieldMgr("FieldMgr"), name="FieldMgr")
+            GaussGeo().FieldMgr.Stepper = "G4ClassicalRK4"
+            GaussGeo().FieldMgr.MagneticField = "MagFieldFromSvc/LHCbField"
+            GaussGeo().FieldMgr.addTool(MagFieldFromSvc("LHCbField"), name="LHCbField")  # NOQA
+            GaussGeo().FieldMgr.LHCbField.MagneticFieldService = "MagneticFieldSvc"  # NOQA
 
         if getsubdetector("HC").Simulate:
             from Configurables import MagneticFieldSvc, MultipleMagneticFieldSvc
             # Use MultipleMagneticFieldSvc instead of default MagneticFieldSvc.
-            GaussGeo().FieldMgr.LHCbField.MagneticFieldService = "MultipleMagneticFieldSvc"
+            GaussGeo().FieldMgr.LHCbField.MagneticFieldService = "MultipleMagneticFieldSvc"  # NOQA
             # Add LHCb dipole magnet and compensators.
             if getsubdetector("Magnet").Simulate:
               MultipleMagneticFieldSvc().MagneticFieldServices += ["MagneticFieldSvc"]
diff --git a/Sim/Gauss/python/Gauss/Geometry/Muon.py b/Sim/Gauss/python/Gauss/Geometry/Muon.py
index 21df8a88d..8e94b7261 100644
--- a/Sim/Gauss/python/Gauss/Geometry/Muon.py
+++ b/Sim/Gauss/python/Gauss/Geometry/Muon.py
@@ -20,3 +20,9 @@ class Muon(det_base):
         )
         from Configurables import ApplicationMgr
         ApplicationMgr().TopAlg += [alg]
+
+    def SetupMonitor(self, slot=''):
+        from Configurables import MuonHitChecker
+        moni = MuonHitChecker("MuonHitChecker"+slot, FullDetail=True)
+        from Configurables import ApplicationMgr
+        ApplicationMgr().TopAlg += [moni]
diff --git a/Sim/GaussGeo/src/component/GaussGeo.cpp b/Sim/GaussGeo/src/component/GaussGeo.cpp
index abbfff963..665185fe3 100644
--- a/Sim/GaussGeo/src/component/GaussGeo.cpp
+++ b/Sim/GaussGeo/src/component/GaussGeo.cpp
@@ -638,29 +638,20 @@ StatusCode GaussGeo::convertLVolumeObject(DataObject* object) {
 
   // Sensitivity
   if (!lvolume->sdName().empty()) {
-    register_sensitive(lvolume->sdName(), g4_volume);
+    auto sc = register_sensitive(lvolume->sdName(), g4_volume);
+    if(sc.isFailure()){
+      return reportError("Failed to set '" + lvolume->sdName() + "' for '"+ lvolume->name() + "'");
+    }
   }
 
   // Magnetic field
   // FIXME: Field stuff
-  //if (!lvolume->mfName().empty()) {
-    //IGiGaFieldMgr* fmanager = nullptr;
-    //StatusCode sc = fieldMgr(lvolume->mfName(), fmanager);
-    //if (sc.isFailure() || fmanager == nullptr) {
-      //return reportError("Failed to create FieldMgr!", sc);
-    //}
-
-    //if (fmanager->fieldMgr() == nullptr) {
-      //return reportError("FieldMgr is invalid!");
-    //}
-
-    //if (fmanager->global()) {
-      //return reportError("FieldMgr is 'global'!");
-    //}
-
-    //// Set magnetic field manager
-    //g4_volume->SetFieldManager(fmanager->fieldMgr(), false);
-  //}
+  if (!lvolume->mfName().empty()) {
+    auto sc = register_mag_field(lvolume->mfName(), g4_volume);
+    if(sc.isFailure()){
+      return reportError("Failed to set '" + lvolume->mfName() + "' for '"+ lvolume->name() + "'");
+    }
+  }
 
   // Check the G4 static store
   if (GaussGeoVolumeUtils::findLVolume(lvolume->name()) != nullptr) {
@@ -1485,54 +1476,12 @@ G4VPhysicalVolume* GaussGeo::constructWorld() {
   //}
 
   //FIXME Field stuff
-  //if (!m_mag_field_mgr.empty()) {
-    //IGiGaFieldMgr* giga_fmanager = nullptr;
-    //StatusCode sc = fieldMgr(m_mag_field_mgr, giga_fmanager);
-    //if (sc.isFailure() || giga_fmanager == nullptr) {
-      //error() << "Faild to construct GiGaFieldManager '" << m_mag_field_mgr << "'" << endmsg;
-      //return nullptr;
-    //}
-
-    //if (!giga_fmanager->global()) {
-      //error() << "GiGaFieldManager '" + m_mag_field_mgr + "' is not 'global'" << endmsg;
-      //return nullptr;
-    //}
-
-    //if (giga_fmanager->fieldMgr() ==  nullptr) {
-      //error() << "GiGaFieldManager '" + m_mag_field_mgr + "' has invalid G4FieldManager" << endmsg;
-      //return nullptr;
-    //}
-
-    //if (giga_fmanager->field() == nullptr) {
-      //error() << "GiGaFieldManager '" + m_mag_field_mgr + "' has invalid G4MagneticField" << endmsg;
-      //return nullptr;
-    //}
-
-    //if (giga_fmanager->stepper() == nullptr) {
-      //error() << "GiGaFieldManager '" + m_mag_field_mgr + "' has invalid G4MagIntegratorStepper" << endmsg;
-      //return nullptr;
-    //}
-
-    //// Additional check
-    //G4TransportationManager* trans_manager = G4TransportationManager::GetTransportationManager();
-    //if (trans_manager == nullptr) {
-      //error() << "G4TransportationMgr is invalid!" << endmsg;
-      //return nullptr;
-    //}
-
-    //if (trans_manager->GetFieldManager() != giga_fmanager->fieldMgr()) {
-      //error() << "Mismatch in the G4FieldManager!" << endmsg;
-      //return nullptr;
-    //}
+  if (!m_mag_field_mgr.empty()) {
+    register_mag_field(m_mag_field_mgr, nullptr);
 
-    //info() << "Global 'Field Manager' is set to '" << objectTypeName(giga_fmanager)
-           //<< "/" << giga_fmanager->name() << "'" << endmsg;
-    //info() << "Global 'G4Field Manager' is set to '" << objectTypeName(giga_fmanager->fieldMgr()) << "'" << endmsg;
-    //info() << "Global 'G4MagneticField' is set to '" << objectTypeName(giga_fmanager->field()) << "'" << endmsg;
-    //info() << "Global 'G4MagIntegratorStepper' is set to '" << objectTypeName(giga_fmanager->stepper()) << "'" << endmsg;
-  //} else {
-    //warning() << "Magnetic Field was not requested to be loaded" << endmsg;
-  //}
+  } else {
+    warning() << "Magnetic Field was not requested to be loaded" << endmsg;
+  }
 
   return m_world_root;
 }
@@ -1749,6 +1698,47 @@ StatusCode GaussGeo::register_sensitive(const std::string& name, G4LogicalVolume
   return StatusCode::SUCCESS;
 }
 
+//=============================================================================
+// Instantiate a Magnetic Field Factories
+//=============================================================================
+StatusCode GaussGeo::register_mag_field(const std::string& name, G4LogicalVolume* vol) {
+  // First check if we have already obtained the magnetic field factory for the
+  // provided name.
+  if(!vol && m_found_global_fieldmgr){
+    error() << "Tried to register second global magnetic field manager" << endmsg;
+    return StatusCode::FAILURE;
+  }
+  auto it = mmap_name_to_fieldmgrfac.find(name);
+  if(it == std::end(mmap_name_to_fieldmgrfac)){
+    mmap_name_to_fieldmgrfac[name] = nullptr;
+    getTool(name, mmap_name_to_fieldmgrfac[name], this);
+    // Check if successful
+    if(!mmap_name_to_fieldmgrfac[name]){
+      warning() << "Could not field manager " << name << "." << endmsg;
+      warning() << "What do we say to the geo service? Not today ..." << endmsg;
+    }
+  }
+
+  // Now fill the map of field managers to volumes
+  if(auto & fieldmgr = mmap_name_to_fieldmgrfac[name]; fieldmgr){
+    if(mmap_fieldmgr_to_lvols.find(fieldmgr) == std::end(mmap_fieldmgr_to_lvols)){
+      mmap_fieldmgr_to_lvols[fieldmgr] = {};
+    }
+    mmap_fieldmgr_to_lvols[fieldmgr].insert(vol);
+    if(vol){
+      debug() << "Asked to use field " << name << " for " << vol->GetName() << "" << endmsg;
+    }
+  }
+  if(!vol){
+    auto giga_fmanager = mmap_name_to_fieldmgrfac[name];
+    info() << "Global 'Field Manager' is set to '" << objectTypeName(giga_fmanager)
+           << "/" << giga_fmanager->name() << "'" << endmsg;
+    m_found_global_fieldmgr = true;
+  }
+  
+  return StatusCode::SUCCESS;
+}
+
 void GaussGeo::constructSDandField() {
   auto sdmanager = G4SDManager::GetSDMpointer();
   for(auto & [sensdetfac, vols]:  mmap_sensdet_to_lvols){
@@ -1759,71 +1749,21 @@ void GaussGeo::constructSDandField() {
       vol->SetSensitiveDetector(sensdet);
     }
   }
-}
-
-//StatusCode GaussGeo::sensitive(const std::string& name, IGiGaSensDet*& detector) {
-  //if (outputLevel() == MSG::VERBOSE) {
-    //prefixIn();
-    //verbose() << m_str_prefix << "=> sensitive(): " << name << endmsg;
-  //}
-
-  //// Reset the output value
-  //detector = nullptr;
-
-  //// Locate the detector
-  //detector = getTool(name, detector, this);
-  //if (detector == nullptr) {
-    //return reportError("Failed to locate Sensitive Detector '" + name + "'");
-  //}
-
-  //// Inform G4 sensitive detector manager
-  //if (std::find(m_sensitive_detectors.begin(), m_sensitive_detectors.end(), detector) == m_sensitive_detectors.end()) {
-    //G4SDManager* sd_manager = G4SDManager::GetSDMpointer();
-    //if (sd_manager == nullptr) {
-      //return reportError("Failed to locate G4SDManager!");
-    //}
-    //sd_manager->AddNewDetector(detector);
-  //}
-
-  //// Keep a local copy
-  //m_sensitive_detectors.push_back(detector);
-
-  //if (outputLevel() == MSG::VERBOSE) {
-    //verbose() << m_str_prefix << "<= sensitive()" << endmsg;
-    //prefixOut();
-  //}
-
-  //return StatusCode::SUCCESS;
-//}
-
-//=============================================================================
-// Instantiate a Magnetic Field object
-//=============================================================================
-//StatusCode GaussGeo::fieldMgr(const std::string& name, IGiGaFieldMgr*& fmanager) {
-  //if (outputLevel() == MSG::VERBOSE) {
-    //prefixIn();
-    //verbose() << m_str_prefix << "=> fieldMgr(): " << name << endmsg;
-  //}
-
-  //// Reset the output value
-  //fmanager = nullptr;
-
-  //// Locate the magnetic field tool
-  //fmanager = getTool(name, fmanager, this);
-  //if (fmanager == nullptr) {
-    //return reportError("Failed to locate FieldManager '" + name + "'");
-  //}
-
-  //// Keep a local copy
-  //m_mag_field_managers.push_back(fmanager);
-
-  //if (outputLevel() == MSG::VERBOSE) {
-    //verbose() << m_str_prefix << "<= fieldMgr()" << endmsg;
-    //prefixOut();
-  //}
+  for(auto & [fieldmgrfac, vols]:  mmap_fieldmgr_to_lvols){
+    //Catch the global field manager
+    if(vols.size() == 1 && *std::begin(vols) == nullptr){
+      debug() << "Constructing global " << fieldmgrfac->name() << "." << endmsg;
+      fieldmgrfac->construct(true);
+    } else {
+    auto fieldmgr = fieldmgrfac->construct(false);
+      debug() << "Assigning " << fieldmgrfac->name() << " to " << vols.size() << " logical volumes" << endmsg;
+      for(auto * vol: vols){
+        vol->SetFieldManager(fieldmgr, false);
+      }
+    }
 
-  //return StatusCode::SUCCESS;
-//}
+  }
+}
 
 //=============================================================================
 // Retrieve a tool by type and name
diff --git a/Sim/GaussGeo/src/component/GaussGeo.h b/Sim/GaussGeo/src/component/GaussGeo.h
index 306c20b41..72eacee30 100644
--- a/Sim/GaussGeo/src/component/GaussGeo.h
+++ b/Sim/GaussGeo/src/component/GaussGeo.h
@@ -91,10 +91,6 @@ class GaussGeo : public Service, virtual public IGiGaMTGeoSvc,
   bool m_performOverlapCheck;  // Given to G4VPlacements to control Overlap checking
   std::string m_assemblyNameSeparator;  // Separator between assembly and placement name
 
-  std::vector<GiGaFactoryBase<G4VSensitiveDetector>*>  m_sensitive_detectors;
-  //std::vector<IGiGaMagField*> m_magnetic_fields;
-  //std::vector<IGiGaFieldMgr*> m_mag_field_managers;
-
   bool m_use_alignment;  // Flag to switch on use of condDB info for children detector elements
   bool m_align_all;  // Flag to switch on for which detector to use condDB info for children detector elements
   std::vector<std::string> m_align_dets_names;  // List of paths in TES to which to apply condDB info
@@ -166,8 +162,13 @@ class GaussGeo : public Service, virtual public IGiGaMTGeoSvc,
   // associated to given logical volume during worker thread initialisation
   std::map<GiGaFactoryBase<G4VSensitiveDetector>*, std::set<G4LogicalVolume*>> mmap_sensdet_to_lvols;
   std::map<std::string, GiGaFactoryBase<G4VSensitiveDetector>*> mmap_name_to_sensdetfac;
+  std::map<GiGaFactoryBase<G4FieldManager,bool>*, std::set<G4LogicalVolume*>> mmap_fieldmgr_to_lvols;
+  std::map<std::string, GiGaFactoryBase<G4FieldManager,bool>*> mmap_name_to_fieldmgrfac;
   StatusCode register_sensitive(const std::string& name, G4LogicalVolume*);
   //FIXME: FIELD STUFF
+  StatusCode register_mag_field(const std::string& name, G4LogicalVolume*);
+  std::atomic_bool m_found_global_fieldmgr{false};
+  //StatusCode fieldMgr(const std::string& name, IGiGaFieldMgr*& fmanager);
   //StatusCode fieldMgr(const std::string& name, IGiGaFieldMgr*& fmanager);
 
   // Methods to simplify tools retrieval
-- 
GitLab


From fe936e8bf411d87ff1eeaba1fa582754aa00def1 Mon Sep 17 00:00:00 2001
From: Dominik Muller <dominik.muller@cern.ch>
Date: Fri, 14 Jun 2019 17:55:30 +0200
Subject: [PATCH 11/90] Added tracking cuts as physics processes

---
 Sim/Gauss/python/Gauss/Physics.py             |   8 +
 Sim/GaussPhysics/CMakeLists.txt               |   9 +-
 .../src/cuts}/KillAtOriginCut.cpp             |   0
 .../src/cuts}/KillAtOriginCut.h               |   0
 .../src/cuts}/LoopCuts.cpp                    |   0
 .../src/cuts}/LoopCuts.h                      |   0
 .../src/cuts}/MinEkineCuts.cpp                |   0
 .../src/cuts}/MinEkineCuts.h                  |   0
 .../src/cuts}/PingPongCut.cpp                 |   0
 .../src/cuts}/PingPongCut.h                   |   0
 .../src/cuts}/SpecialCuts.cpp                 |   0
 .../src/cuts}/SpecialCuts.h                   |   0
 Sim/GaussPhysics/src/cuts/TrCutsRunAction.cpp | 185 +++++++++++++
 Sim/GaussPhysics/src/cuts/TrCutsRunAction.h   |  56 ++++
 .../src/cuts}/WorldCuts.cpp                   |   0
 .../src/cuts}/WorldCuts.h                     |   0
 .../src/cuts}/ZeroStepsCut.cpp                |   0
 .../src/cuts}/ZeroStepsCut.h                  |   0
 .../src/{ => particles}/G4AntiLambdabZero.cpp |   0
 .../src/{ => particles}/G4AntiLambdabZero.h   |   0
 .../src/{ => particles}/G4AntiOmegabcZero.cpp |   0
 .../src/{ => particles}/G4AntiOmegabcZero.h   |   0
 .../{ => particles}/G4AntiOmegaccMinus.cpp    |   0
 .../src/{ => particles}/G4AntiOmegaccMinus.h  |   0
 .../src/{ => particles}/G4AntiXibZero.cpp     |   0
 .../src/{ => particles}/G4AntiXibZero.h       |   0
 .../src/{ => particles}/G4AntiXibcMinus.cpp   |   0
 .../src/{ => particles}/G4AntiXibcMinus.h     |   0
 .../src/{ => particles}/G4AntiXibcZero.cpp    |   0
 .../src/{ => particles}/G4AntiXibcZero.h      |   0
 .../src/{ => particles}/G4AntiXiccMinus.cpp   |   0
 .../src/{ => particles}/G4AntiXiccMinus.h     |   0
 .../{ => particles}/G4AntiXiccMinusMinus.cpp  |   0
 .../{ => particles}/G4AntiXiccMinusMinus.h    |   0
 .../{ => particles}/G4AntiXiccStarMinus.cpp   |   0
 .../src/{ => particles}/G4AntiXiccStarMinus.h |   0
 .../src/{ => particles}/G4BcMesonMinus.cpp    |   0
 .../src/{ => particles}/G4BcMesonMinus.h      |   0
 .../src/{ => particles}/G4BcMesonPlus.cpp     |   0
 .../src/{ => particles}/G4BcMesonPlus.h       |   0
 .../src/{ => particles}/G4CharginoMinus.cpp   |   0
 .../src/{ => particles}/G4CharginoMinus.h     |   0
 .../src/{ => particles}/G4CharginoPlus.cpp    |   0
 .../src/{ => particles}/G4CharginoPlus.h      |   0
 .../src/{ => particles}/G4HiddenValley.cpp    |   0
 .../src/{ => particles}/G4HiddenValley.h      |   0
 .../src/{ => particles}/G4Higgses.cpp         |   0
 .../src/{ => particles}/G4Higgses.h           |   0
 .../src/{ => particles}/G4LambdabZero.cpp     |   0
 .../src/{ => particles}/G4LambdabZero.h       |   0
 .../src/{ => particles}/G4Neutralino.cpp      |   0
 .../src/{ => particles}/G4Neutralino.h        |   0
 .../src/{ => particles}/G4Neutralino2.cpp     |   0
 .../src/{ => particles}/G4Neutralino2.h       |   0
 .../src/{ => particles}/G4OmegabMinus.cpp     |   0
 .../src/{ => particles}/G4OmegabMinus.h       |   0
 .../src/{ => particles}/G4OmegabPlus.cpp      |   0
 .../src/{ => particles}/G4OmegabPlus.h        |   0
 .../src/{ => particles}/G4OmegabcZero.cpp     |   0
 .../src/{ => particles}/G4OmegabcZero.h       |   0
 .../src/{ => particles}/G4OmegaccPlus.cpp     |   0
 .../src/{ => particles}/G4OmegaccPlus.h       |   0
 .../src/{ => particles}/G4XibMinus.cpp        |   0
 .../src/{ => particles}/G4XibMinus.h          |   0
 .../src/{ => particles}/G4XibPlus.cpp         |   0
 .../src/{ => particles}/G4XibPlus.h           |   0
 .../src/{ => particles}/G4XibZero.cpp         |   0
 .../src/{ => particles}/G4XibZero.h           |   0
 .../src/{ => particles}/G4XibcPlus.cpp        |   0
 .../src/{ => particles}/G4XibcPlus.h          |   0
 .../src/{ => particles}/G4XibcZero.cpp        |   0
 .../src/{ => particles}/G4XibcZero.h          |   0
 .../src/{ => particles}/G4XiccPlus.cpp        |   0
 .../src/{ => particles}/G4XiccPlus.h          |   0
 .../src/{ => particles}/G4XiccPlusPlus.cpp    |   0
 .../src/{ => particles}/G4XiccPlusPlus.h      |   0
 .../src/{ => particles}/G4XiccStarPlus.cpp    |   0
 .../src/{ => particles}/G4XiccStarPlus.h      |   0
 .../GaussPhysics_factories.cpp                |   0
 .../{ => particles}/GiGaHiggsParticles.cpp    |   0
 .../GiGaPhysUnknownParticles.cpp              |   0
 .../GiGaPhysUnknownParticles.h                |   0
 .../src/Components/TrCutsRunAction.cpp        | 245 ------------------
 .../src/Components/TrCutsRunAction.h          |  94 -------
 84 files changed, 256 insertions(+), 341 deletions(-)
 rename Sim/{GaussTools/src/Components => GaussPhysics/src/cuts}/KillAtOriginCut.cpp (100%)
 rename Sim/{GaussTools/src/Components => GaussPhysics/src/cuts}/KillAtOriginCut.h (100%)
 rename Sim/{GaussTools/src/Components => GaussPhysics/src/cuts}/LoopCuts.cpp (100%)
 rename Sim/{GaussTools/src/Components => GaussPhysics/src/cuts}/LoopCuts.h (100%)
 rename Sim/{GaussTools/src/Components => GaussPhysics/src/cuts}/MinEkineCuts.cpp (100%)
 rename Sim/{GaussTools/src/Components => GaussPhysics/src/cuts}/MinEkineCuts.h (100%)
 rename Sim/{GaussTools/src/Components => GaussPhysics/src/cuts}/PingPongCut.cpp (100%)
 rename Sim/{GaussTools/src/Components => GaussPhysics/src/cuts}/PingPongCut.h (100%)
 rename Sim/{GaussTools/src/Components => GaussPhysics/src/cuts}/SpecialCuts.cpp (100%)
 rename Sim/{GaussTools/src/Components => GaussPhysics/src/cuts}/SpecialCuts.h (100%)
 create mode 100755 Sim/GaussPhysics/src/cuts/TrCutsRunAction.cpp
 create mode 100755 Sim/GaussPhysics/src/cuts/TrCutsRunAction.h
 rename Sim/{GaussTools/src/Components => GaussPhysics/src/cuts}/WorldCuts.cpp (100%)
 rename Sim/{GaussTools/src/Components => GaussPhysics/src/cuts}/WorldCuts.h (100%)
 rename Sim/{GaussTools/src/Components => GaussPhysics/src/cuts}/ZeroStepsCut.cpp (100%)
 rename Sim/{GaussTools/src/Components => GaussPhysics/src/cuts}/ZeroStepsCut.h (100%)
 rename Sim/GaussPhysics/src/{ => particles}/G4AntiLambdabZero.cpp (100%)
 rename Sim/GaussPhysics/src/{ => particles}/G4AntiLambdabZero.h (100%)
 rename Sim/GaussPhysics/src/{ => particles}/G4AntiOmegabcZero.cpp (100%)
 rename Sim/GaussPhysics/src/{ => particles}/G4AntiOmegabcZero.h (100%)
 rename Sim/GaussPhysics/src/{ => particles}/G4AntiOmegaccMinus.cpp (100%)
 rename Sim/GaussPhysics/src/{ => particles}/G4AntiOmegaccMinus.h (100%)
 rename Sim/GaussPhysics/src/{ => particles}/G4AntiXibZero.cpp (100%)
 rename Sim/GaussPhysics/src/{ => particles}/G4AntiXibZero.h (100%)
 rename Sim/GaussPhysics/src/{ => particles}/G4AntiXibcMinus.cpp (100%)
 rename Sim/GaussPhysics/src/{ => particles}/G4AntiXibcMinus.h (100%)
 rename Sim/GaussPhysics/src/{ => particles}/G4AntiXibcZero.cpp (100%)
 rename Sim/GaussPhysics/src/{ => particles}/G4AntiXibcZero.h (100%)
 rename Sim/GaussPhysics/src/{ => particles}/G4AntiXiccMinus.cpp (100%)
 rename Sim/GaussPhysics/src/{ => particles}/G4AntiXiccMinus.h (100%)
 rename Sim/GaussPhysics/src/{ => particles}/G4AntiXiccMinusMinus.cpp (100%)
 rename Sim/GaussPhysics/src/{ => particles}/G4AntiXiccMinusMinus.h (100%)
 rename Sim/GaussPhysics/src/{ => particles}/G4AntiXiccStarMinus.cpp (100%)
 rename Sim/GaussPhysics/src/{ => particles}/G4AntiXiccStarMinus.h (100%)
 rename Sim/GaussPhysics/src/{ => particles}/G4BcMesonMinus.cpp (100%)
 rename Sim/GaussPhysics/src/{ => particles}/G4BcMesonMinus.h (100%)
 rename Sim/GaussPhysics/src/{ => particles}/G4BcMesonPlus.cpp (100%)
 rename Sim/GaussPhysics/src/{ => particles}/G4BcMesonPlus.h (100%)
 rename Sim/GaussPhysics/src/{ => particles}/G4CharginoMinus.cpp (100%)
 rename Sim/GaussPhysics/src/{ => particles}/G4CharginoMinus.h (100%)
 rename Sim/GaussPhysics/src/{ => particles}/G4CharginoPlus.cpp (100%)
 rename Sim/GaussPhysics/src/{ => particles}/G4CharginoPlus.h (100%)
 rename Sim/GaussPhysics/src/{ => particles}/G4HiddenValley.cpp (100%)
 rename Sim/GaussPhysics/src/{ => particles}/G4HiddenValley.h (100%)
 rename Sim/GaussPhysics/src/{ => particles}/G4Higgses.cpp (100%)
 rename Sim/GaussPhysics/src/{ => particles}/G4Higgses.h (100%)
 rename Sim/GaussPhysics/src/{ => particles}/G4LambdabZero.cpp (100%)
 rename Sim/GaussPhysics/src/{ => particles}/G4LambdabZero.h (100%)
 rename Sim/GaussPhysics/src/{ => particles}/G4Neutralino.cpp (100%)
 rename Sim/GaussPhysics/src/{ => particles}/G4Neutralino.h (100%)
 rename Sim/GaussPhysics/src/{ => particles}/G4Neutralino2.cpp (100%)
 rename Sim/GaussPhysics/src/{ => particles}/G4Neutralino2.h (100%)
 rename Sim/GaussPhysics/src/{ => particles}/G4OmegabMinus.cpp (100%)
 rename Sim/GaussPhysics/src/{ => particles}/G4OmegabMinus.h (100%)
 rename Sim/GaussPhysics/src/{ => particles}/G4OmegabPlus.cpp (100%)
 rename Sim/GaussPhysics/src/{ => particles}/G4OmegabPlus.h (100%)
 rename Sim/GaussPhysics/src/{ => particles}/G4OmegabcZero.cpp (100%)
 rename Sim/GaussPhysics/src/{ => particles}/G4OmegabcZero.h (100%)
 rename Sim/GaussPhysics/src/{ => particles}/G4OmegaccPlus.cpp (100%)
 rename Sim/GaussPhysics/src/{ => particles}/G4OmegaccPlus.h (100%)
 rename Sim/GaussPhysics/src/{ => particles}/G4XibMinus.cpp (100%)
 rename Sim/GaussPhysics/src/{ => particles}/G4XibMinus.h (100%)
 rename Sim/GaussPhysics/src/{ => particles}/G4XibPlus.cpp (100%)
 rename Sim/GaussPhysics/src/{ => particles}/G4XibPlus.h (100%)
 rename Sim/GaussPhysics/src/{ => particles}/G4XibZero.cpp (100%)
 rename Sim/GaussPhysics/src/{ => particles}/G4XibZero.h (100%)
 rename Sim/GaussPhysics/src/{ => particles}/G4XibcPlus.cpp (100%)
 rename Sim/GaussPhysics/src/{ => particles}/G4XibcPlus.h (100%)
 rename Sim/GaussPhysics/src/{ => particles}/G4XibcZero.cpp (100%)
 rename Sim/GaussPhysics/src/{ => particles}/G4XibcZero.h (100%)
 rename Sim/GaussPhysics/src/{ => particles}/G4XiccPlus.cpp (100%)
 rename Sim/GaussPhysics/src/{ => particles}/G4XiccPlus.h (100%)
 rename Sim/GaussPhysics/src/{ => particles}/G4XiccPlusPlus.cpp (100%)
 rename Sim/GaussPhysics/src/{ => particles}/G4XiccPlusPlus.h (100%)
 rename Sim/GaussPhysics/src/{ => particles}/G4XiccStarPlus.cpp (100%)
 rename Sim/GaussPhysics/src/{ => particles}/G4XiccStarPlus.h (100%)
 rename Sim/GaussPhysics/src/{ => particles}/GaussPhysics_factories.cpp (100%)
 rename Sim/GaussPhysics/src/{ => particles}/GiGaHiggsParticles.cpp (100%)
 rename Sim/GaussPhysics/src/{ => particles}/GiGaPhysUnknownParticles.cpp (100%)
 rename Sim/GaussPhysics/src/{ => particles}/GiGaPhysUnknownParticles.h (100%)
 delete mode 100755 Sim/GaussTools/src/Components/TrCutsRunAction.cpp
 delete mode 100755 Sim/GaussTools/src/Components/TrCutsRunAction.h

diff --git a/Sim/Gauss/python/Gauss/Physics.py b/Sim/Gauss/python/Gauss/Physics.py
index 54e3888de..b0dc40a38 100644
--- a/Sim/Gauss/python/Gauss/Physics.py
+++ b/Sim/Gauss/python/Gauss/Physics.py
@@ -79,6 +79,9 @@ class G4Physics(LHCbConfigurableUser):
         # --- Other physics
         self.AddOtherPhysics(gmpl)
 
+        # --- Tracking cuts
+        self.AddTrackingCuts(gmpl)
+
     def AddEMPhys(self, pl):
         emPhys = self.getProp('Em')
         _all = {
@@ -181,3 +184,8 @@ class G4Physics(LHCbConfigurableUser):
             if otherPhys != '':
                 raise RuntimeError("Unknown setting for OtherPhys"
                                    "PhysicsList chosen ('%s')" % otherPhys)
+
+    def AddTrackingCuts(self, pl):
+        from Configurables import TrCutsRunAction
+        pl.addTool(TrCutsRunAction("TrCuts"), name="TrCuts")
+        pl.PhysicsConstructors.append("TrCutsRunAction/TrCuts")
diff --git a/Sim/GaussPhysics/CMakeLists.txt b/Sim/GaussPhysics/CMakeLists.txt
index 6dcade727..b56839c23 100644
--- a/Sim/GaussPhysics/CMakeLists.txt
+++ b/Sim/GaussPhysics/CMakeLists.txt
@@ -17,7 +17,12 @@ AddHepMC3()
 FindG4libs(digits_hits event geometry global graphics_reps materials
            particles processes run tracking track)
 
-gaudi_add_module(GaussPhysics
-                 src/*.cpp
+gaudi_add_module(GaussParticlesPhysics
+                 src/particles/*.cpp
                  LINK_LIBRARIES GiGaMTCoreRunLib GaudiAlgLib GiGaMTLib G4LHCblists ${GEANT4_LIBS})
 
+
+gaudi_add_module(GaussCutPhysics
+                 src/cuts/*.cpp
+                 INCLUDE_DIRS GiGaMTFactories CLHEP Geant4
+                 LINK_LIBRARIES GaudiAlgLib CLHEP ${GEANT4_LIBS})
diff --git a/Sim/GaussTools/src/Components/KillAtOriginCut.cpp b/Sim/GaussPhysics/src/cuts/KillAtOriginCut.cpp
similarity index 100%
rename from Sim/GaussTools/src/Components/KillAtOriginCut.cpp
rename to Sim/GaussPhysics/src/cuts/KillAtOriginCut.cpp
diff --git a/Sim/GaussTools/src/Components/KillAtOriginCut.h b/Sim/GaussPhysics/src/cuts/KillAtOriginCut.h
similarity index 100%
rename from Sim/GaussTools/src/Components/KillAtOriginCut.h
rename to Sim/GaussPhysics/src/cuts/KillAtOriginCut.h
diff --git a/Sim/GaussTools/src/Components/LoopCuts.cpp b/Sim/GaussPhysics/src/cuts/LoopCuts.cpp
similarity index 100%
rename from Sim/GaussTools/src/Components/LoopCuts.cpp
rename to Sim/GaussPhysics/src/cuts/LoopCuts.cpp
diff --git a/Sim/GaussTools/src/Components/LoopCuts.h b/Sim/GaussPhysics/src/cuts/LoopCuts.h
similarity index 100%
rename from Sim/GaussTools/src/Components/LoopCuts.h
rename to Sim/GaussPhysics/src/cuts/LoopCuts.h
diff --git a/Sim/GaussTools/src/Components/MinEkineCuts.cpp b/Sim/GaussPhysics/src/cuts/MinEkineCuts.cpp
similarity index 100%
rename from Sim/GaussTools/src/Components/MinEkineCuts.cpp
rename to Sim/GaussPhysics/src/cuts/MinEkineCuts.cpp
diff --git a/Sim/GaussTools/src/Components/MinEkineCuts.h b/Sim/GaussPhysics/src/cuts/MinEkineCuts.h
similarity index 100%
rename from Sim/GaussTools/src/Components/MinEkineCuts.h
rename to Sim/GaussPhysics/src/cuts/MinEkineCuts.h
diff --git a/Sim/GaussTools/src/Components/PingPongCut.cpp b/Sim/GaussPhysics/src/cuts/PingPongCut.cpp
similarity index 100%
rename from Sim/GaussTools/src/Components/PingPongCut.cpp
rename to Sim/GaussPhysics/src/cuts/PingPongCut.cpp
diff --git a/Sim/GaussTools/src/Components/PingPongCut.h b/Sim/GaussPhysics/src/cuts/PingPongCut.h
similarity index 100%
rename from Sim/GaussTools/src/Components/PingPongCut.h
rename to Sim/GaussPhysics/src/cuts/PingPongCut.h
diff --git a/Sim/GaussTools/src/Components/SpecialCuts.cpp b/Sim/GaussPhysics/src/cuts/SpecialCuts.cpp
similarity index 100%
rename from Sim/GaussTools/src/Components/SpecialCuts.cpp
rename to Sim/GaussPhysics/src/cuts/SpecialCuts.cpp
diff --git a/Sim/GaussTools/src/Components/SpecialCuts.h b/Sim/GaussPhysics/src/cuts/SpecialCuts.h
similarity index 100%
rename from Sim/GaussTools/src/Components/SpecialCuts.h
rename to Sim/GaussPhysics/src/cuts/SpecialCuts.h
diff --git a/Sim/GaussPhysics/src/cuts/TrCutsRunAction.cpp b/Sim/GaussPhysics/src/cuts/TrCutsRunAction.cpp
new file mode 100755
index 000000000..f75fbefc9
--- /dev/null
+++ b/Sim/GaussPhysics/src/cuts/TrCutsRunAction.cpp
@@ -0,0 +1,185 @@
+// G4
+#include "Geant4/G4ParticleDefinition.hh"
+#include "Geant4/G4ParticleTable.hh"
+#include "Geant4/G4ProcessManager.hh"
+
+// local
+#include "KillAtOriginCut.h"
+#include "LoopCuts.h"
+#include "MinEkineCuts.h"
+#include "PingPongCut.h"
+#include "TrCutsRunAction.h"
+#include "WorldCuts.h"
+#include "ZeroStepsCut.h"
+
+void TrCutsRunAction::ConstructProcess() {
+
+  // Loop on particles that have been defined and attach process
+  G4ParticleTable* particleTable = G4ParticleTable::GetParticleTable();
+  if (!particleTable) {
+    error("G4ParticleTable points to NULL!; return! ");
+    return;
+  }
+
+  int ii, ptbSiz = particleTable->size();
+
+  for (ii = 0; ii < ptbSiz; ii++) {
+    G4ParticleDefinition* particle = particleTable->GetParticle(ii);
+
+    if (!particle) {
+      warning("G4ParticleDefinition* points to NULL, skip it");
+      continue;
+    }
+
+    std::string pname = particle->GetParticleName();
+
+    // Do not attach cuts processes to optical photons nor short lived
+    // particle as will disappear anyway for other reasons!!!
+    if ((pname != "opticalphoton") && (!particle->IsShortLived())) {
+      int particleCode = particle->GetPDGEncoding();
+
+      double acut;
+
+      if (abs(particleCode) == 11) {
+        acut = m_ecut;
+      } else if (particleCode == 22) {
+        acut = m_phcut;
+      } else if (abs(particleCode) == 13) {
+        acut = m_mcut;
+      } else if (abs(particleCode) == 2112) {
+        acut = m_ncut;
+      } else if (abs(particleCode) == 12 || abs(particleCode) == 14 ||
+                 abs(particleCode) == 16) {
+        acut = m_nucut;
+      } else if ((abs(particleCode) == 2212) || (abs(particleCode) == 321) ||
+                 (abs(particleCode) == 211)) {
+        acut = m_pKpicut;
+      } else {
+        acut = m_ocut;
+      }
+
+      if ((pname != "opticalphoton") && (!particle->IsShortLived())) {
+        G4ProcessManager* procMgr = particle->GetProcessManager();
+        if (0 == procMgr) {
+          error("G4ProcessManager* points to NULL!");
+          return;
+        }
+
+        for (std::vector<int>::iterator ik = m_killAtOrigin.begin();
+             m_killAtOrigin.end() != ik; ik++) {
+          if (particleCode == *ik) {
+            procMgr->AddDiscreteProcess(
+                new GiGa::KillAtOriginCut("KillAtOriginCut"));
+          }
+        }  // closes loop on particles to kill
+
+        procMgr->AddDiscreteProcess(
+            new GiGa::MinEkineCuts("MinEkineCut", acut));
+        procMgr->AddDiscreteProcess(new GiGa::WorldCuts(
+            "WorldCut", m_minx, m_miny, m_minz, m_maxx, m_maxy, m_maxz));
+        if ((pname == "e-" || pname == "gamma") && m_killloops) {
+          procMgr->AddDiscreteProcess(
+              new GiGa::LoopCuts("LoopCuts", m_maxsteps, m_minstep));
+        }
+
+        if (m_killPingPong) {
+          procMgr->AddDiscreteProcess(
+              new GiGa::PingPongCut("PingPongCut", m_nMaxForPingPong,
+                                    m_stepLenghtPingPong, m_nMaxOfPingPong));
+        }
+        if (m_killZeroSteps) {
+          procMgr->AddDiscreteProcess(new GiGa::ZeroStepsCut(
+              "ZeroStepsCut", m_nStepsForZero, m_zeroMaxLenght, m_maxNZeroSteps,
+              m_world));
+        }
+      }
+    }
+  }
+}
+
+
+#include "GiGaMTFactories/GiGaFactoryBase.h"
+#include "GiGaMTFactories/GiGaTool.h"
+
+class TrCutsRunActionFAC
+    : public extends<GiGaTool, GiGaFactoryBase<G4VPhysicsConstructor>> {
+  public:
+  using extends::extends;
+  G4VPhysicsConstructor* construct() const override {
+    auto ret = new TrCutsRunAction{};
+    ret->SetMessageInterface(message_interface());
+    ret->m_ecut = m_ecut;
+    ret->m_phcut = m_phcut;
+    ret->m_pKpicut = m_pKpicut;
+    ret->m_ocut = m_ocut;
+    ret->m_ncut = m_ncut;
+    ret->m_nucut = m_nucut;
+    ret->m_mcut = m_mcut;
+    ret->m_killloops = m_killloops;
+    ret->m_maxsteps = m_maxsteps;
+    ret->m_minstep = m_minstep;
+    ret->m_minx = m_minx;
+    ret->m_miny = m_miny;
+    ret->m_minz = m_minz;
+    ret->m_maxx = m_maxx;
+    ret->m_maxy = m_maxy;
+    ret->m_maxz = m_maxz;
+    ret->m_killPingPong = m_killPingPong;
+    ret->m_nMaxForPingPong = m_nMaxForPingPong;
+    ret->m_nMaxOfPingPong = m_nMaxOfPingPong;
+    ret->m_stepLenghtPingPong = m_stepLenghtPingPong;
+    ret->m_killAtOrigin = m_killAtOrigin;
+    ret->m_killZeroSteps = m_killZeroSteps;
+    ret->m_nStepsForZero = m_nStepsForZero;
+    ret->m_zeroMaxLenght = m_zeroMaxLenght;
+    ret->m_maxNZeroSteps = m_maxNZeroSteps;
+    ret->m_world = m_world;
+    return ret;
+  }
+  Gaudi::Property<double> m_ecut{this, "ElectronTrCut", 1.0 * CLHEP::MeV};
+  Gaudi::Property<double> m_phcut{this, "GammaTrCut", 1.0 * CLHEP::MeV};
+  Gaudi::Property<double> m_pKpicut{this, "pKpiCut", 10.0 * CLHEP::MeV};
+  Gaudi::Property<double> m_ncut{this, "NeutronTrCut", 10.0 * CLHEP::MeV};
+  Gaudi::Property<double> m_nucut{this, "NeutrinoTrCut", 0.0 * CLHEP::MeV};
+  Gaudi::Property<double> m_mcut{this, "MuonTrCut", 10.0 * CLHEP::MeV};
+  Gaudi::Property<double> m_ocut{this, "OtherTrCut", 0.0 * CLHEP::MeV};
+  Gaudi::Property<bool> m_killloops{this, "KillLoops", true};
+  Gaudi::Property<int> m_maxsteps{this, "MaxNumberSteps", 100};
+  Gaudi::Property<double> m_minstep{this, "MininumStep", 0.001};
+  Gaudi::Property<double> m_minx{this, "MinX", -10000 * CLHEP::mm};
+  Gaudi::Property<double> m_miny{this, "MinY", -5000 * CLHEP::mm};
+  Gaudi::Property<double> m_minz{this, "MinZ", -10000 * CLHEP::mm};
+  Gaudi::Property<double> m_maxx{this, "MaxX", 10000 * CLHEP::mm};
+  Gaudi::Property<double> m_maxy{this, "MaxY", 10000 * CLHEP::mm};
+  Gaudi::Property<double> m_maxz{this, "MaxZ", 25000 * CLHEP::mm};
+  Gaudi::Property<bool> m_killPingPong{this, "KillPingPong", true};
+  Gaudi::Property<int> m_nMaxForPingPong{this, "MaxNumStepsForPingPong",
+                                         1000000};
+  Gaudi::Property<int> m_nMaxOfPingPong{this, "MaxNumOfPingPong", 20};
+  Gaudi::Property<double> m_stepLenghtPingPong{this, "MaxStepLenForPingPong",
+                                               1.0e-3};
+  Gaudi::Property<std::vector<int>> m_killAtOrigin{
+      this,
+      "DoNotTrackParticles",
+      {12, 14, 16, -12, -14, -16},
+      "List of particles to discard at their origin"};
+  Gaudi::Property<bool> m_killZeroSteps{
+      this, "KillZeroSteps", true,
+      "Flag to activate killing particles that make step of zero "
+      "lenght in a volume"};
+  Gaudi::Property<int> m_nStepsForZero{
+      this, "NmaxForZeroSteps", 1000000,
+      "Number of steps after which to check for zero lenght steps"};
+  Gaudi::Property<double> m_zeroMaxLenght{
+      this, "StepLenghAsZero", 1.0e-9,
+      "Lenght of steps below which a steps has to be considered as "
+      "of zero lenght"};
+  Gaudi::Property<int> m_maxNZeroSteps{
+      this, "NZeroSteps", 20,
+      "Number of consecutive steps of zero lenght after which the "
+      "particle is killed"};
+  Gaudi::Property<std::string> m_world{this, "WorldName", "Universe",
+                                       "Name of the world volume"};
+};
+
+DECLARE_COMPONENT_WITH_ID( TrCutsRunActionFAC, "TrCutsRunAction" )
diff --git a/Sim/GaussPhysics/src/cuts/TrCutsRunAction.h b/Sim/GaussPhysics/src/cuts/TrCutsRunAction.h
new file mode 100755
index 000000000..f7e58756a
--- /dev/null
+++ b/Sim/GaussPhysics/src/cuts/TrCutsRunAction.h
@@ -0,0 +1,56 @@
+#pragma once
+#include "Geant4/G4VPhysicsConstructor.hh"
+#include "CLHEP/Units/SystemOfUnits.h"
+#include "GiGaMTCore/IGiGaMessage.h"
+#include <vector>
+
+
+/** @class TrCutsRunAction TrCutsRunAction.h
+ *
+ *  Class to pass Tracking Cuts to Geant4 as processes.
+ *  Modified to
+ *
+ *
+ *  @author Witek POKORSKI
+ *  @date   2003-04-10
+ *  @author Gloria CORTI
+ *  @date   2009-03-31
+ */
+
+class TrCutsRunActionFAC;
+
+class TrCutsRunAction: public G4VPhysicsConstructor, public GiGaMessage
+{
+  friend TrCutsRunActionFAC;
+
+public:
+
+  void ConstructParticle () override {};
+  void ConstructProcess  () override;
+
+  virtual ~TrCutsRunAction( ) = default;
+
+private:
+
+  double m_ecut{1.0*CLHEP::MeV}; ///< kinetic energy cut for e+/-
+  double m_phcut{1.0*CLHEP::MeV}; ///< kinetic energy cut for gamma
+  double m_pKpicut{10.0*CLHEP::MeV}; ///< kinetic energy cut for proton, K+/- and pi+/-
+  double m_ocut{0.0*CLHEP::MeV}; ///< kinetic energy cut for other particles
+  double m_ncut{10.0*CLHEP::MeV}; ///< kinetic energy cut for neutrons
+  double m_nucut{0.0*CLHEP::MeV}; ///< kinetic energy cut for neutrinos (when tracked)
+  double m_mcut{10.0*CLHEP::MeV}; ///< kinetic energy cut for muons
+  bool m_killloops{true}; ///< kill looping e- and gamma
+  int m_maxsteps{100}; ///< maximum number of step looping
+  double m_minstep{0.001}; ///< minimum lenght for looping cut
+  double m_minx{-10000*CLHEP::mm}, m_miny{-10000*CLHEP::mm}, m_minz{-5000*CLHEP::mm}, m_maxx{10000*CLHEP::mm}, m_maxy{10000*CLHEP::mm}, m_maxz{25000*CLHEP::mm}; ///< world cut limits
+  bool m_killPingPong{true}; ///< kill particles ping ponging
+  int m_nMaxForPingPong{1000000}; ///< maximum number of steps to check pingpong
+  int m_nMaxOfPingPong{20}; ///< maximum number of ping pong
+  double m_stepLenghtPingPong{1.0e-3}; ///< step lenght to consider in pingpong
+  std::vector<int> m_killAtOrigin{{12,14,16,-12,-14,-16}}; ///< particle to kill at origin (def=neutrino)
+  bool m_killZeroSteps{true}; ///< kill particle with 'zero' step
+  int m_nStepsForZero{1000000}; ///< number of steps after which to check for 'zero' steps
+  double m_zeroMaxLenght{1.0e-9}; ///< max lenght to consider a step of 'zero' lenght
+  int m_maxNZeroSteps{20}; ///< number of steps of zero length to trigger cut
+  std::string m_world{"Universe"}; ///< Name of world volume
+};
diff --git a/Sim/GaussTools/src/Components/WorldCuts.cpp b/Sim/GaussPhysics/src/cuts/WorldCuts.cpp
similarity index 100%
rename from Sim/GaussTools/src/Components/WorldCuts.cpp
rename to Sim/GaussPhysics/src/cuts/WorldCuts.cpp
diff --git a/Sim/GaussTools/src/Components/WorldCuts.h b/Sim/GaussPhysics/src/cuts/WorldCuts.h
similarity index 100%
rename from Sim/GaussTools/src/Components/WorldCuts.h
rename to Sim/GaussPhysics/src/cuts/WorldCuts.h
diff --git a/Sim/GaussTools/src/Components/ZeroStepsCut.cpp b/Sim/GaussPhysics/src/cuts/ZeroStepsCut.cpp
similarity index 100%
rename from Sim/GaussTools/src/Components/ZeroStepsCut.cpp
rename to Sim/GaussPhysics/src/cuts/ZeroStepsCut.cpp
diff --git a/Sim/GaussTools/src/Components/ZeroStepsCut.h b/Sim/GaussPhysics/src/cuts/ZeroStepsCut.h
similarity index 100%
rename from Sim/GaussTools/src/Components/ZeroStepsCut.h
rename to Sim/GaussPhysics/src/cuts/ZeroStepsCut.h
diff --git a/Sim/GaussPhysics/src/G4AntiLambdabZero.cpp b/Sim/GaussPhysics/src/particles/G4AntiLambdabZero.cpp
similarity index 100%
rename from Sim/GaussPhysics/src/G4AntiLambdabZero.cpp
rename to Sim/GaussPhysics/src/particles/G4AntiLambdabZero.cpp
diff --git a/Sim/GaussPhysics/src/G4AntiLambdabZero.h b/Sim/GaussPhysics/src/particles/G4AntiLambdabZero.h
similarity index 100%
rename from Sim/GaussPhysics/src/G4AntiLambdabZero.h
rename to Sim/GaussPhysics/src/particles/G4AntiLambdabZero.h
diff --git a/Sim/GaussPhysics/src/G4AntiOmegabcZero.cpp b/Sim/GaussPhysics/src/particles/G4AntiOmegabcZero.cpp
similarity index 100%
rename from Sim/GaussPhysics/src/G4AntiOmegabcZero.cpp
rename to Sim/GaussPhysics/src/particles/G4AntiOmegabcZero.cpp
diff --git a/Sim/GaussPhysics/src/G4AntiOmegabcZero.h b/Sim/GaussPhysics/src/particles/G4AntiOmegabcZero.h
similarity index 100%
rename from Sim/GaussPhysics/src/G4AntiOmegabcZero.h
rename to Sim/GaussPhysics/src/particles/G4AntiOmegabcZero.h
diff --git a/Sim/GaussPhysics/src/G4AntiOmegaccMinus.cpp b/Sim/GaussPhysics/src/particles/G4AntiOmegaccMinus.cpp
similarity index 100%
rename from Sim/GaussPhysics/src/G4AntiOmegaccMinus.cpp
rename to Sim/GaussPhysics/src/particles/G4AntiOmegaccMinus.cpp
diff --git a/Sim/GaussPhysics/src/G4AntiOmegaccMinus.h b/Sim/GaussPhysics/src/particles/G4AntiOmegaccMinus.h
similarity index 100%
rename from Sim/GaussPhysics/src/G4AntiOmegaccMinus.h
rename to Sim/GaussPhysics/src/particles/G4AntiOmegaccMinus.h
diff --git a/Sim/GaussPhysics/src/G4AntiXibZero.cpp b/Sim/GaussPhysics/src/particles/G4AntiXibZero.cpp
similarity index 100%
rename from Sim/GaussPhysics/src/G4AntiXibZero.cpp
rename to Sim/GaussPhysics/src/particles/G4AntiXibZero.cpp
diff --git a/Sim/GaussPhysics/src/G4AntiXibZero.h b/Sim/GaussPhysics/src/particles/G4AntiXibZero.h
similarity index 100%
rename from Sim/GaussPhysics/src/G4AntiXibZero.h
rename to Sim/GaussPhysics/src/particles/G4AntiXibZero.h
diff --git a/Sim/GaussPhysics/src/G4AntiXibcMinus.cpp b/Sim/GaussPhysics/src/particles/G4AntiXibcMinus.cpp
similarity index 100%
rename from Sim/GaussPhysics/src/G4AntiXibcMinus.cpp
rename to Sim/GaussPhysics/src/particles/G4AntiXibcMinus.cpp
diff --git a/Sim/GaussPhysics/src/G4AntiXibcMinus.h b/Sim/GaussPhysics/src/particles/G4AntiXibcMinus.h
similarity index 100%
rename from Sim/GaussPhysics/src/G4AntiXibcMinus.h
rename to Sim/GaussPhysics/src/particles/G4AntiXibcMinus.h
diff --git a/Sim/GaussPhysics/src/G4AntiXibcZero.cpp b/Sim/GaussPhysics/src/particles/G4AntiXibcZero.cpp
similarity index 100%
rename from Sim/GaussPhysics/src/G4AntiXibcZero.cpp
rename to Sim/GaussPhysics/src/particles/G4AntiXibcZero.cpp
diff --git a/Sim/GaussPhysics/src/G4AntiXibcZero.h b/Sim/GaussPhysics/src/particles/G4AntiXibcZero.h
similarity index 100%
rename from Sim/GaussPhysics/src/G4AntiXibcZero.h
rename to Sim/GaussPhysics/src/particles/G4AntiXibcZero.h
diff --git a/Sim/GaussPhysics/src/G4AntiXiccMinus.cpp b/Sim/GaussPhysics/src/particles/G4AntiXiccMinus.cpp
similarity index 100%
rename from Sim/GaussPhysics/src/G4AntiXiccMinus.cpp
rename to Sim/GaussPhysics/src/particles/G4AntiXiccMinus.cpp
diff --git a/Sim/GaussPhysics/src/G4AntiXiccMinus.h b/Sim/GaussPhysics/src/particles/G4AntiXiccMinus.h
similarity index 100%
rename from Sim/GaussPhysics/src/G4AntiXiccMinus.h
rename to Sim/GaussPhysics/src/particles/G4AntiXiccMinus.h
diff --git a/Sim/GaussPhysics/src/G4AntiXiccMinusMinus.cpp b/Sim/GaussPhysics/src/particles/G4AntiXiccMinusMinus.cpp
similarity index 100%
rename from Sim/GaussPhysics/src/G4AntiXiccMinusMinus.cpp
rename to Sim/GaussPhysics/src/particles/G4AntiXiccMinusMinus.cpp
diff --git a/Sim/GaussPhysics/src/G4AntiXiccMinusMinus.h b/Sim/GaussPhysics/src/particles/G4AntiXiccMinusMinus.h
similarity index 100%
rename from Sim/GaussPhysics/src/G4AntiXiccMinusMinus.h
rename to Sim/GaussPhysics/src/particles/G4AntiXiccMinusMinus.h
diff --git a/Sim/GaussPhysics/src/G4AntiXiccStarMinus.cpp b/Sim/GaussPhysics/src/particles/G4AntiXiccStarMinus.cpp
similarity index 100%
rename from Sim/GaussPhysics/src/G4AntiXiccStarMinus.cpp
rename to Sim/GaussPhysics/src/particles/G4AntiXiccStarMinus.cpp
diff --git a/Sim/GaussPhysics/src/G4AntiXiccStarMinus.h b/Sim/GaussPhysics/src/particles/G4AntiXiccStarMinus.h
similarity index 100%
rename from Sim/GaussPhysics/src/G4AntiXiccStarMinus.h
rename to Sim/GaussPhysics/src/particles/G4AntiXiccStarMinus.h
diff --git a/Sim/GaussPhysics/src/G4BcMesonMinus.cpp b/Sim/GaussPhysics/src/particles/G4BcMesonMinus.cpp
similarity index 100%
rename from Sim/GaussPhysics/src/G4BcMesonMinus.cpp
rename to Sim/GaussPhysics/src/particles/G4BcMesonMinus.cpp
diff --git a/Sim/GaussPhysics/src/G4BcMesonMinus.h b/Sim/GaussPhysics/src/particles/G4BcMesonMinus.h
similarity index 100%
rename from Sim/GaussPhysics/src/G4BcMesonMinus.h
rename to Sim/GaussPhysics/src/particles/G4BcMesonMinus.h
diff --git a/Sim/GaussPhysics/src/G4BcMesonPlus.cpp b/Sim/GaussPhysics/src/particles/G4BcMesonPlus.cpp
similarity index 100%
rename from Sim/GaussPhysics/src/G4BcMesonPlus.cpp
rename to Sim/GaussPhysics/src/particles/G4BcMesonPlus.cpp
diff --git a/Sim/GaussPhysics/src/G4BcMesonPlus.h b/Sim/GaussPhysics/src/particles/G4BcMesonPlus.h
similarity index 100%
rename from Sim/GaussPhysics/src/G4BcMesonPlus.h
rename to Sim/GaussPhysics/src/particles/G4BcMesonPlus.h
diff --git a/Sim/GaussPhysics/src/G4CharginoMinus.cpp b/Sim/GaussPhysics/src/particles/G4CharginoMinus.cpp
similarity index 100%
rename from Sim/GaussPhysics/src/G4CharginoMinus.cpp
rename to Sim/GaussPhysics/src/particles/G4CharginoMinus.cpp
diff --git a/Sim/GaussPhysics/src/G4CharginoMinus.h b/Sim/GaussPhysics/src/particles/G4CharginoMinus.h
similarity index 100%
rename from Sim/GaussPhysics/src/G4CharginoMinus.h
rename to Sim/GaussPhysics/src/particles/G4CharginoMinus.h
diff --git a/Sim/GaussPhysics/src/G4CharginoPlus.cpp b/Sim/GaussPhysics/src/particles/G4CharginoPlus.cpp
similarity index 100%
rename from Sim/GaussPhysics/src/G4CharginoPlus.cpp
rename to Sim/GaussPhysics/src/particles/G4CharginoPlus.cpp
diff --git a/Sim/GaussPhysics/src/G4CharginoPlus.h b/Sim/GaussPhysics/src/particles/G4CharginoPlus.h
similarity index 100%
rename from Sim/GaussPhysics/src/G4CharginoPlus.h
rename to Sim/GaussPhysics/src/particles/G4CharginoPlus.h
diff --git a/Sim/GaussPhysics/src/G4HiddenValley.cpp b/Sim/GaussPhysics/src/particles/G4HiddenValley.cpp
similarity index 100%
rename from Sim/GaussPhysics/src/G4HiddenValley.cpp
rename to Sim/GaussPhysics/src/particles/G4HiddenValley.cpp
diff --git a/Sim/GaussPhysics/src/G4HiddenValley.h b/Sim/GaussPhysics/src/particles/G4HiddenValley.h
similarity index 100%
rename from Sim/GaussPhysics/src/G4HiddenValley.h
rename to Sim/GaussPhysics/src/particles/G4HiddenValley.h
diff --git a/Sim/GaussPhysics/src/G4Higgses.cpp b/Sim/GaussPhysics/src/particles/G4Higgses.cpp
similarity index 100%
rename from Sim/GaussPhysics/src/G4Higgses.cpp
rename to Sim/GaussPhysics/src/particles/G4Higgses.cpp
diff --git a/Sim/GaussPhysics/src/G4Higgses.h b/Sim/GaussPhysics/src/particles/G4Higgses.h
similarity index 100%
rename from Sim/GaussPhysics/src/G4Higgses.h
rename to Sim/GaussPhysics/src/particles/G4Higgses.h
diff --git a/Sim/GaussPhysics/src/G4LambdabZero.cpp b/Sim/GaussPhysics/src/particles/G4LambdabZero.cpp
similarity index 100%
rename from Sim/GaussPhysics/src/G4LambdabZero.cpp
rename to Sim/GaussPhysics/src/particles/G4LambdabZero.cpp
diff --git a/Sim/GaussPhysics/src/G4LambdabZero.h b/Sim/GaussPhysics/src/particles/G4LambdabZero.h
similarity index 100%
rename from Sim/GaussPhysics/src/G4LambdabZero.h
rename to Sim/GaussPhysics/src/particles/G4LambdabZero.h
diff --git a/Sim/GaussPhysics/src/G4Neutralino.cpp b/Sim/GaussPhysics/src/particles/G4Neutralino.cpp
similarity index 100%
rename from Sim/GaussPhysics/src/G4Neutralino.cpp
rename to Sim/GaussPhysics/src/particles/G4Neutralino.cpp
diff --git a/Sim/GaussPhysics/src/G4Neutralino.h b/Sim/GaussPhysics/src/particles/G4Neutralino.h
similarity index 100%
rename from Sim/GaussPhysics/src/G4Neutralino.h
rename to Sim/GaussPhysics/src/particles/G4Neutralino.h
diff --git a/Sim/GaussPhysics/src/G4Neutralino2.cpp b/Sim/GaussPhysics/src/particles/G4Neutralino2.cpp
similarity index 100%
rename from Sim/GaussPhysics/src/G4Neutralino2.cpp
rename to Sim/GaussPhysics/src/particles/G4Neutralino2.cpp
diff --git a/Sim/GaussPhysics/src/G4Neutralino2.h b/Sim/GaussPhysics/src/particles/G4Neutralino2.h
similarity index 100%
rename from Sim/GaussPhysics/src/G4Neutralino2.h
rename to Sim/GaussPhysics/src/particles/G4Neutralino2.h
diff --git a/Sim/GaussPhysics/src/G4OmegabMinus.cpp b/Sim/GaussPhysics/src/particles/G4OmegabMinus.cpp
similarity index 100%
rename from Sim/GaussPhysics/src/G4OmegabMinus.cpp
rename to Sim/GaussPhysics/src/particles/G4OmegabMinus.cpp
diff --git a/Sim/GaussPhysics/src/G4OmegabMinus.h b/Sim/GaussPhysics/src/particles/G4OmegabMinus.h
similarity index 100%
rename from Sim/GaussPhysics/src/G4OmegabMinus.h
rename to Sim/GaussPhysics/src/particles/G4OmegabMinus.h
diff --git a/Sim/GaussPhysics/src/G4OmegabPlus.cpp b/Sim/GaussPhysics/src/particles/G4OmegabPlus.cpp
similarity index 100%
rename from Sim/GaussPhysics/src/G4OmegabPlus.cpp
rename to Sim/GaussPhysics/src/particles/G4OmegabPlus.cpp
diff --git a/Sim/GaussPhysics/src/G4OmegabPlus.h b/Sim/GaussPhysics/src/particles/G4OmegabPlus.h
similarity index 100%
rename from Sim/GaussPhysics/src/G4OmegabPlus.h
rename to Sim/GaussPhysics/src/particles/G4OmegabPlus.h
diff --git a/Sim/GaussPhysics/src/G4OmegabcZero.cpp b/Sim/GaussPhysics/src/particles/G4OmegabcZero.cpp
similarity index 100%
rename from Sim/GaussPhysics/src/G4OmegabcZero.cpp
rename to Sim/GaussPhysics/src/particles/G4OmegabcZero.cpp
diff --git a/Sim/GaussPhysics/src/G4OmegabcZero.h b/Sim/GaussPhysics/src/particles/G4OmegabcZero.h
similarity index 100%
rename from Sim/GaussPhysics/src/G4OmegabcZero.h
rename to Sim/GaussPhysics/src/particles/G4OmegabcZero.h
diff --git a/Sim/GaussPhysics/src/G4OmegaccPlus.cpp b/Sim/GaussPhysics/src/particles/G4OmegaccPlus.cpp
similarity index 100%
rename from Sim/GaussPhysics/src/G4OmegaccPlus.cpp
rename to Sim/GaussPhysics/src/particles/G4OmegaccPlus.cpp
diff --git a/Sim/GaussPhysics/src/G4OmegaccPlus.h b/Sim/GaussPhysics/src/particles/G4OmegaccPlus.h
similarity index 100%
rename from Sim/GaussPhysics/src/G4OmegaccPlus.h
rename to Sim/GaussPhysics/src/particles/G4OmegaccPlus.h
diff --git a/Sim/GaussPhysics/src/G4XibMinus.cpp b/Sim/GaussPhysics/src/particles/G4XibMinus.cpp
similarity index 100%
rename from Sim/GaussPhysics/src/G4XibMinus.cpp
rename to Sim/GaussPhysics/src/particles/G4XibMinus.cpp
diff --git a/Sim/GaussPhysics/src/G4XibMinus.h b/Sim/GaussPhysics/src/particles/G4XibMinus.h
similarity index 100%
rename from Sim/GaussPhysics/src/G4XibMinus.h
rename to Sim/GaussPhysics/src/particles/G4XibMinus.h
diff --git a/Sim/GaussPhysics/src/G4XibPlus.cpp b/Sim/GaussPhysics/src/particles/G4XibPlus.cpp
similarity index 100%
rename from Sim/GaussPhysics/src/G4XibPlus.cpp
rename to Sim/GaussPhysics/src/particles/G4XibPlus.cpp
diff --git a/Sim/GaussPhysics/src/G4XibPlus.h b/Sim/GaussPhysics/src/particles/G4XibPlus.h
similarity index 100%
rename from Sim/GaussPhysics/src/G4XibPlus.h
rename to Sim/GaussPhysics/src/particles/G4XibPlus.h
diff --git a/Sim/GaussPhysics/src/G4XibZero.cpp b/Sim/GaussPhysics/src/particles/G4XibZero.cpp
similarity index 100%
rename from Sim/GaussPhysics/src/G4XibZero.cpp
rename to Sim/GaussPhysics/src/particles/G4XibZero.cpp
diff --git a/Sim/GaussPhysics/src/G4XibZero.h b/Sim/GaussPhysics/src/particles/G4XibZero.h
similarity index 100%
rename from Sim/GaussPhysics/src/G4XibZero.h
rename to Sim/GaussPhysics/src/particles/G4XibZero.h
diff --git a/Sim/GaussPhysics/src/G4XibcPlus.cpp b/Sim/GaussPhysics/src/particles/G4XibcPlus.cpp
similarity index 100%
rename from Sim/GaussPhysics/src/G4XibcPlus.cpp
rename to Sim/GaussPhysics/src/particles/G4XibcPlus.cpp
diff --git a/Sim/GaussPhysics/src/G4XibcPlus.h b/Sim/GaussPhysics/src/particles/G4XibcPlus.h
similarity index 100%
rename from Sim/GaussPhysics/src/G4XibcPlus.h
rename to Sim/GaussPhysics/src/particles/G4XibcPlus.h
diff --git a/Sim/GaussPhysics/src/G4XibcZero.cpp b/Sim/GaussPhysics/src/particles/G4XibcZero.cpp
similarity index 100%
rename from Sim/GaussPhysics/src/G4XibcZero.cpp
rename to Sim/GaussPhysics/src/particles/G4XibcZero.cpp
diff --git a/Sim/GaussPhysics/src/G4XibcZero.h b/Sim/GaussPhysics/src/particles/G4XibcZero.h
similarity index 100%
rename from Sim/GaussPhysics/src/G4XibcZero.h
rename to Sim/GaussPhysics/src/particles/G4XibcZero.h
diff --git a/Sim/GaussPhysics/src/G4XiccPlus.cpp b/Sim/GaussPhysics/src/particles/G4XiccPlus.cpp
similarity index 100%
rename from Sim/GaussPhysics/src/G4XiccPlus.cpp
rename to Sim/GaussPhysics/src/particles/G4XiccPlus.cpp
diff --git a/Sim/GaussPhysics/src/G4XiccPlus.h b/Sim/GaussPhysics/src/particles/G4XiccPlus.h
similarity index 100%
rename from Sim/GaussPhysics/src/G4XiccPlus.h
rename to Sim/GaussPhysics/src/particles/G4XiccPlus.h
diff --git a/Sim/GaussPhysics/src/G4XiccPlusPlus.cpp b/Sim/GaussPhysics/src/particles/G4XiccPlusPlus.cpp
similarity index 100%
rename from Sim/GaussPhysics/src/G4XiccPlusPlus.cpp
rename to Sim/GaussPhysics/src/particles/G4XiccPlusPlus.cpp
diff --git a/Sim/GaussPhysics/src/G4XiccPlusPlus.h b/Sim/GaussPhysics/src/particles/G4XiccPlusPlus.h
similarity index 100%
rename from Sim/GaussPhysics/src/G4XiccPlusPlus.h
rename to Sim/GaussPhysics/src/particles/G4XiccPlusPlus.h
diff --git a/Sim/GaussPhysics/src/G4XiccStarPlus.cpp b/Sim/GaussPhysics/src/particles/G4XiccStarPlus.cpp
similarity index 100%
rename from Sim/GaussPhysics/src/G4XiccStarPlus.cpp
rename to Sim/GaussPhysics/src/particles/G4XiccStarPlus.cpp
diff --git a/Sim/GaussPhysics/src/G4XiccStarPlus.h b/Sim/GaussPhysics/src/particles/G4XiccStarPlus.h
similarity index 100%
rename from Sim/GaussPhysics/src/G4XiccStarPlus.h
rename to Sim/GaussPhysics/src/particles/G4XiccStarPlus.h
diff --git a/Sim/GaussPhysics/src/GaussPhysics_factories.cpp b/Sim/GaussPhysics/src/particles/GaussPhysics_factories.cpp
similarity index 100%
rename from Sim/GaussPhysics/src/GaussPhysics_factories.cpp
rename to Sim/GaussPhysics/src/particles/GaussPhysics_factories.cpp
diff --git a/Sim/GaussPhysics/src/GiGaHiggsParticles.cpp b/Sim/GaussPhysics/src/particles/GiGaHiggsParticles.cpp
similarity index 100%
rename from Sim/GaussPhysics/src/GiGaHiggsParticles.cpp
rename to Sim/GaussPhysics/src/particles/GiGaHiggsParticles.cpp
diff --git a/Sim/GaussPhysics/src/GiGaPhysUnknownParticles.cpp b/Sim/GaussPhysics/src/particles/GiGaPhysUnknownParticles.cpp
similarity index 100%
rename from Sim/GaussPhysics/src/GiGaPhysUnknownParticles.cpp
rename to Sim/GaussPhysics/src/particles/GiGaPhysUnknownParticles.cpp
diff --git a/Sim/GaussPhysics/src/GiGaPhysUnknownParticles.h b/Sim/GaussPhysics/src/particles/GiGaPhysUnknownParticles.h
similarity index 100%
rename from Sim/GaussPhysics/src/GiGaPhysUnknownParticles.h
rename to Sim/GaussPhysics/src/particles/GiGaPhysUnknownParticles.h
diff --git a/Sim/GaussTools/src/Components/TrCutsRunAction.cpp b/Sim/GaussTools/src/Components/TrCutsRunAction.cpp
deleted file mode 100755
index f9dea293d..000000000
--- a/Sim/GaussTools/src/Components/TrCutsRunAction.cpp
+++ /dev/null
@@ -1,245 +0,0 @@
-// $Id: TrCutsRunAction.cpp,v 1.16 2009-05-26 17:14:36 gcorti Exp $
-// Include files 
-
-// from Gaudi
-
-// G4
-#include "Geant4/G4ParticleTable.hh"
-#include "Geant4/G4ParticleDefinition.hh"
-#include "Geant4/G4ProcessManager.hh"
-
-// local
-#include "MinEkineCuts.h"
-#include "LoopCuts.h"
-#include "WorldCuts.h"
-#include "PingPongCut.h"
-#include "KillAtOriginCut.h"
-#include "ZeroStepsCut.h"
-#include "TrCutsRunAction.h"
-
-
-// ============================================================================
-/** @file 
- *
- *  Implementation file for class : TrCutsRunAction
- *
- *  @author Witek Pokorski Witold.Pokorski@cern.ch
- *  @date 10/04/2003 
- */
-// ============================================================================
-
-// Declaration of the Tool Factory
-DECLARE_COMPONENT( TrCutsRunAction )
-
-// ============================================================================
-/** standard constructor 
- */
-// ============================================================================
-TrCutsRunAction::TrCutsRunAction
-( const std::string& type   ,
-  const std::string& name   ,
-  const IInterface*  parent ) 
-  : GiGaRunActionBase( type , name , parent )
-    , m_ecut(1.0) //MeV
-    , m_phcut(1.0) //MeV
-    , m_pKpicut( 10.0 ) //MeV
-    , m_ocut(0.0) //MeV
-    , m_ncut(10.0) //MeV
-    , m_nucut(0.0) //MeV
-    , m_mcut(10.0) //MeV
-    , m_killloops(true)
-    , m_maxsteps(100)
-    , m_minstep(0.001)
-    , m_minx(-10000.0), m_miny(-10000.0), m_minz(-5000.0)
-    , m_maxx(10000.0), m_maxy(10000.0), m_maxz(25000.0)
-{  
-  declareProperty("ElectronTrCut", m_ecut);
-  declareProperty("GammaTrCut", m_phcut);
-  declareProperty("pKpiCut" , m_pKpicut ) ;
-  declareProperty("NeutronTrCut", m_ncut);
-  declareProperty("NeutrinoTrCut", m_nucut);
-  declareProperty("MuonTrCut", m_mcut);
-  declareProperty("OtherTrCut" , m_ocut ) ;
-  declareProperty("KillLoops", m_killloops);
-  declareProperty("MaxNumberSteps", m_maxsteps);
-  declareProperty("MininumStep", m_minstep);
-  declareProperty("MinX", m_minx);
-  declareProperty("MinY", m_miny);
-  declareProperty("MinZ", m_minz);
-  declareProperty("MaxX", m_maxx);
-  declareProperty("MaxY", m_maxy);
-  declareProperty("MaxZ", m_maxz);
-  declareProperty( "KillPingPong", m_killPingPong = true );
-  declareProperty( "MaxNumStepsForPingPong", m_nMaxForPingPong = 1000000 );
-  declareProperty( "MaxNumOfPingPong", m_nMaxOfPingPong = 20 );
-  declareProperty( "MaxStepLenForPingPong", m_stepLenghtPingPong = 1.0e-3 );
-  m_killAtOrigin.push_back(12);
-  m_killAtOrigin.push_back(14);
-  m_killAtOrigin.push_back(16);
-  m_killAtOrigin.push_back(-12);
-  m_killAtOrigin.push_back(-14);
-  m_killAtOrigin.push_back(-16);
-  declareProperty( "DoNotTrackParticles", m_killAtOrigin,
-                   "List of particles to discard at their origin" );
-  //
-  declareProperty( "KillZeroSteps", m_killZeroSteps = true,
-                   "Flag to activate killing particles that make step of zero lenght in a volume" );
-  declareProperty( "NmaxForZeroSteps", m_nStepsForZero = 1000000,
-                   "Number of steps after which to check for zero lenght steps");
-  declareProperty( "StepLenghAsZero", m_zeroMaxLenght = 1.0e-9,
-                   "Lenght of steps below which a steps has to be considered as of zero lenght" );
-  declareProperty( "NZeroSteps", m_maxNZeroSteps = 20,
-                   "Number of consecutive steps of zero lenght after which the particle is killed");
-  declareProperty( "WorldName", m_world = "Universe", 
-                   "Name of the world volume" );
-  
-}
-
-
-// ============================================================================
-/// destructor 
-// ============================================================================
-TrCutsRunAction::~TrCutsRunAction() {}
-
-// ============================================================================
-/** performe the action at the begin of each run 
- *  @param run pointer to Geant4 run object 
- */
-// ============================================================================
-void TrCutsRunAction::BeginOfRunAction( const G4Run* run )
-{
-  if ( 0 == run ) { 
-    Warning( "BeginOfRunAction:: G4Run* points to NULL!" );
-  }
-  
-  // Loop on particles that have been defined and attach process
-  G4ParticleTable* particleTable = G4ParticleTable::GetParticleTable();
-  if ( 0 == particleTable ) {
-    Error( "G4ParticleTable points to NULL!; return! ");
-    return; 
-  }
-  
-  int ii, ptbSiz = particleTable->size();
-  
-  for( ii = 0; ii < ptbSiz; ii++) {
-
-    G4ParticleDefinition* particle = particleTable->GetParticle( ii );
-    
-    if ( 0 == particle ) {
-      Warning ( "G4ParticleDefinition* points to NULL, skip it" ) ;
-      continue;
-    }
-      
-    std::string pname=particle->GetParticleName();
-
-    // Do not attach cuts processes to optical photons nor short lived
-    // particle as will disappear anyway for other reasons!!!
-    if( (pname!="opticalphoton") && ( ! particle->IsShortLived() ) ) {
-      
-      int particleCode = particle->GetPDGEncoding();
-
-      double acut;
-
-      if(abs(particleCode)==11)
-        {
-          acut=m_ecut;
-        }
-      else if(particleCode==22)
-        {
-          acut=m_phcut;
-        }
-      else if(abs(particleCode)==13)
-        {
-          acut=m_mcut;
-        }
-      else if(abs(particleCode)==2112)
-        {
-          acut=m_ncut;
-        }
-      else if(abs(particleCode)==12 || abs(particleCode)==14 
-              || abs(particleCode)==16)
-        {
-          acut=m_nucut;
-        }
-      else if ( (abs(particleCode) == 2212 ) || (abs(particleCode) == 321 )
-                || (abs(particleCode) == 211 ) ) 
-        {
-          acut=m_pKpicut;  
-        }
-      else 
-        {
-          acut = m_ocut ;
-        }      
-
-      if ( (pname!="opticalphoton") && ( ! particle->IsShortLived() ) )
-        {          
-          G4ProcessManager* procMgr = particle->GetProcessManager();
-          if ( 0 == procMgr ) 
-          {
-            Error("G4ProcessManager* points to NULL!") ;
-            return ;
-          }
-
-          for( std::vector<int>::iterator ik = m_killAtOrigin.begin();
-               m_killAtOrigin.end() != ik; ik++ ) {
-
-            if( particleCode == *ik ) {
-              
-              procMgr->AddDiscreteProcess( 
-                       new GiGa::KillAtOriginCut("KillAtOriginCut") );
-            }
-          } // closes loop on particles to kill
-          
-          procMgr->AddDiscreteProcess( new GiGa::MinEkineCuts("MinEkineCut",
-                                                              acut) );
-          procMgr->AddDiscreteProcess( new GiGa::WorldCuts("WorldCut",
-                                                           m_minx, m_miny,
-                                                           m_minz, m_maxx,
-                                                           m_maxy, m_maxz) );
-          if ( (pname=="e-" || pname=="gamma" ) && m_killloops) {
-            procMgr->
-              AddDiscreteProcess( new GiGa::LoopCuts("LoopCuts", m_maxsteps,
-                                                     m_minstep) );
-          }
-          
-          if ( m_killPingPong ) {
-            procMgr->AddDiscreteProcess( new GiGa::PingPongCut("PingPongCut",
-                                                         m_nMaxForPingPong,
-                                                         m_stepLenghtPingPong,
-                                                         m_nMaxOfPingPong) );
-          }
-          if ( m_killZeroSteps ) {
-            procMgr->AddDiscreteProcess( new GiGa::ZeroStepsCut("ZeroStepsCut",
-                                                         m_nStepsForZero,
-                                                         m_zeroMaxLenght,
-                                                         m_maxNZeroSteps,
-                                                         m_world) );
-          }
-          
-        }
-    }
-    
-  }
-  
-}
-
-
-// ============================================================================
-/** performe the action at the end of each run 
- *  @param run pointer to Geant4 run object 
- */
-// ============================================================================
-void TrCutsRunAction::EndOfRunAction( const G4Run* run )
-{
-  
-  if( 0 == run ) { 
-    Warning("EndOfRunAction:: G4Run* points to NULL!"); 
-  }
-
-}
-
-
-// ============================================================================
-// The End
-// ============================================================================
-
diff --git a/Sim/GaussTools/src/Components/TrCutsRunAction.h b/Sim/GaussTools/src/Components/TrCutsRunAction.h
deleted file mode 100755
index 53ac7d554..000000000
--- a/Sim/GaussTools/src/Components/TrCutsRunAction.h
+++ /dev/null
@@ -1,94 +0,0 @@
-// $Id: TrCutsRunAction.h,v 1.9 2009-05-26 17:14:34 gcorti Exp $
-#ifndef GAUSSTOOLS_COMPONENTS_TRCUTSRUNACTION_H
-#define GAUSSTOOLS_COMPONENTS_TRCUTSRUNACTION_H 1
-// Include files
-// from GiGa
-#include "GiGa/GiGaRunActionBase.h"
-
-
-/** @class TrCutsRunAction TrCutsRunAction.h
- *
- *  Class to pass Tracking Cuts to Geant4 as processes.
- *  Modified to
- *
- *
- *  @author Witek POKORSKI
- *  @date   2003-04-10
- *  @author Gloria CORTI
- *  @date   2009-03-31
- */
-
-class TrCutsRunAction: public virtual GiGaRunActionBase
-{
-
-public:
-
-  /** performe the action at the begin of each run
-   *  @param run pointer to Geant4 run object
-   */
-  void BeginOfRunAction ( const G4Run* run ) override;
-
-  /** performe the action at the end  of each event
-   *  @param run pointer to Geant4 run object
-   */
-  void EndOfRunAction   ( const G4Run* run ) override;
-
-  //protected:
-
-  /** standard constructor
-   *  @see GiGaPhysListBase
-   *  @see GiGaBase
-   *  @see AlgTool
-   *  @param type type of the object (?)
-   *  @param name name of the object
-   *  @param parent  pointer to parent object
-   */
-  TrCutsRunAction
-  ( const std::string& type   ,
-    const std::string& name   ,
-    const IInterface*  parent ) ;
-
-  // destructor (virtual and protected)
-  virtual ~TrCutsRunAction( );
-
-private:
-
-  ///no default constructor
-  TrCutsRunAction();
-  /// no copy constructor
-  TrCutsRunAction( const TrCutsRunAction& );
-  /// no assignement
-  TrCutsRunAction& operator=( const TrCutsRunAction& );
-
-private:
-
-  double m_ecut;         ///< kinetic energy cut for e+/-
-  double m_phcut;        ///< kinetic energy cut for gamma
-  double m_pKpicut ;     ///< kinetic energy cut for proton, K+/- and pi+/-
-  double m_ocut;         ///< kinetic energy cut for other particles
-  double m_ncut;         ///< kinetic energy cut for neutrons
-  double m_nucut;        ///< kinetic energy cut for neutrinos (when tracked)
-  double m_mcut;         ///< kinetic energy cut for muons
-  bool m_killloops;      ///< kill looping e- and gamma
-  int m_maxsteps;        ///< maximum number of step looping
-  double m_minstep;      ///< minimum lenght for looping cut
-  double m_minx, m_miny, m_minz, m_maxx, m_maxy, m_maxz; ///< world cut limits
-  bool m_killPingPong;   ///< kill particles ping ponging
-  int m_nMaxForPingPong; ///< maximum number of steps to check pingpong
-  int m_nMaxOfPingPong;  ///< maximum number of ping pong
-  double m_stepLenghtPingPong; ///< step lenght to consider in pingpong
-  std::vector<int> m_killAtOrigin; ///< particle to kill at origin (def=neutrino)
-  bool m_killZeroSteps;   ///< kill particle with 'zero' step
-  int m_nStepsForZero;    ///< number of steps after which to check for 'zero' steps
-  double m_zeroMaxLenght; ///< max lenght to consider a step of 'zero' lenght
-  int m_maxNZeroSteps;    ///< number of steps of zero length to trigger cut
-  std::string m_world;    ///< Name of world volume
-
-};
-// ============================================================================
-
-// ============================================================================
-// The END
-// ============================================================================
-#endif ///< GIGA_TRCUTSRUNACTION_H
-// ============================================================================
-- 
GitLab


From 2df5d03906655d83e6904c61383d59e66226fb78 Mon Sep 17 00:00:00 2001
From: Dominik Muller <dominik.muller@cern.ch>
Date: Tue, 9 Jul 2019 17:55:56 +0200
Subject: [PATCH 12/90] Basic calo classes

---
 Sim/GaussCalo/src/CaloHit.cpp        | 139 --------
 Sim/GaussCalo/src/CaloHit.h          | 305 ++++++++---------
 Sim/GaussCalo/src/CaloSensDet.cpp    | 394 ----------------------
 Sim/GaussCalo/src/CaloSensDet.h      | 474 +++++++--------------------
 Sim/GaussCalo/src/CaloSensDet.icpp   | 410 +++++++++++++++++++++++
 Sim/GaussCalo/src/CaloSensDetFAC.cpp |   0
 Sim/GaussCalo/src/CaloSensDetFAC.h   | 122 +++++++
 Sim/GaussCalo/src/CaloSubHit.cpp     | 135 --------
 Sim/GaussCalo/src/CaloSubHit.h       | 318 ++++++++----------
 9 files changed, 918 insertions(+), 1379 deletions(-)
 delete mode 100755 Sim/GaussCalo/src/CaloHit.cpp
 delete mode 100755 Sim/GaussCalo/src/CaloSensDet.cpp
 create mode 100755 Sim/GaussCalo/src/CaloSensDet.icpp
 create mode 100755 Sim/GaussCalo/src/CaloSensDetFAC.cpp
 create mode 100755 Sim/GaussCalo/src/CaloSensDetFAC.h
 delete mode 100755 Sim/GaussCalo/src/CaloSubHit.cpp

diff --git a/Sim/GaussCalo/src/CaloHit.cpp b/Sim/GaussCalo/src/CaloHit.cpp
deleted file mode 100755
index 2837a35b9..000000000
--- a/Sim/GaussCalo/src/CaloHit.cpp
+++ /dev/null
@@ -1,139 +0,0 @@
-// $Id: CaloHit.cpp,v 1.4 2006-01-17 15:52:57 odescham Exp $
-// ============================================================================
-// CVS tag $Name: not supported by cvs2svn $
-// ============================================================================
-// $Log: not supported by cvs2svn $
-// Revision 1.3  2004/01/14 13:38:10  ranjard
-// v6r0 - fix to be used with Gaudi v14r0
-//
-// Revision 1.2  2002/12/13 16:52:56  ibelyaev
-//  put updated versions of the packages
-//
-// Revision 1.1  2002/12/07 14:41:44  ibelyaev
-//  add new Calo stuff
-// 
-// ============================================================================
-// Include files
-// GiGa
-#include "GiGa/GiGaUtil.h"
-// G4 
-#include "Geant4/G4Allocator.hh"
-// local
-#include "CaloHit.h"
-
-// ============================================================================
-/** @file 
- *  Implementation file for class  CaloHit
- *
- *  @author Vanya Belyaev Ivan.Belyaev@itep.ru
- *  @date   2002-12-03
- */
-// ============================================================================
-
-namespace CaloHitLocal
-{
-  // ==========================================================================
-  /** @var  s_Allocator
-   *  allocator to make more efficient creation delete of CaloHits objects  
-   */
-  // ==========================================================================
-  G4Allocator<CaloHit>            s_Allocator ;
-  // ==========================================================================
-  
-  // ==========================================================================
-  /** @var s_Counter 
-   *  statsic instace counter for all functions 
-   */
-  // ==========================================================================
-#ifdef GIGA_DEBUG
-  static GiGaUtil::InstanceCounter<CaloHit> s_Counter   ;
-#endif 
-  // ==========================================================================
-}
-
-
-// ============================================================================
-/** standard  constructor 
- *  @param cell ID of calorimeter cell 
- */
-// ============================================================================
-CaloHit::CaloHit( const LHCb::CaloCellID& cell ) 
-  : m_cellID ( cell ) 
-  , m_map    (      ) 
-{
-#ifdef GIGA_DEBUG
-  CaloHitLocal::s_Counter.increment () ;
-#endif  
-}
-
-
-// ============================================================================
-/** copy constructor 
- *  @param right object to be copied 
- */
-// ============================================================================
-CaloHit::CaloHit( const CaloHit& right )
-  : G4VHit   ( right          ) 
-  , m_cellID ( right.cellID() )
-  , m_map    (                )
-{
-  for( CaloHit::iterator hit = right.begin() ; right.end() != hit ; ++hit ) 
-    { m_map[ hit->first ] = hit->second->clone() ; }
-#ifdef GIGA_DEBUG
-  CaloHitLocal::s_Counter.increment () ;
-#endif  
-}
-
-
-// ============================================================================
-/// clone menthod  
-// ============================================================================
-CaloHit* CaloHit::clone() const 
-{ 
-  return new CaloHit( *this ); 
-}
-
-
-// ============================================================================
-/// destructor
-// ============================================================================
-CaloHit::~CaloHit() 
-{
-  /// delete all sub hits 
-  for( TheMap::iterator ihit = m_map.begin() ; m_map.end() != ihit ; ++ihit ) 
-    {
-      CaloSubHit* hit = ihit->second ;
-      if( 0 != hit ) { delete hit ; ihit->second = 0 ; }
-    }
-  // clear the map 
-  m_map.clear();
-  ///
-#ifdef GIGA_DEBUG
-  CaloHitLocal::s_Counter.decrement () ;
-#endif
-}
-
-
-// ============================================================================
-/// overloaded 'new' oerator 
-// ============================================================================
-void* CaloHit::operator new(size_t)
-{
-  void *hit  ;
-  hit = (void *) CaloHitLocal::s_Allocator.MallocSingle () ;
-  return hit ;
-}
-
-
-// ============================================================================
-/// overloaded 'delete' oerator 
-// ============================================================================
-void CaloHit::operator delete( void *hit )
-{ 
-  CaloHitLocal::s_Allocator.FreeSingle( (CaloHit*) hit ); 
-}
-
-
-// ============================================================================
-// The End 
-// ============================================================================
diff --git a/Sim/GaussCalo/src/CaloHit.h b/Sim/GaussCalo/src/CaloHit.h
index ca51785f7..f9354287c 100755
--- a/Sim/GaussCalo/src/CaloHit.h
+++ b/Sim/GaussCalo/src/CaloHit.h
@@ -1,235 +1,198 @@
-// $Id: CaloHit.h,v 1.7 2006-01-17 15:52:57 odescham Exp $
-// ============================================================================
-// CVS tag $Name: not supported by cvs2svn $
-// ============================================================================
-// $Log: not supported by cvs2svn $
-// Revision 1.6  2004/01/14 13:38:10  ranjard
-// v6r0 - fix to be used with Gaudi v14r0
-//
-// Revision 1.5  2003/07/22 19:05:29  ibelyaev
-//  improve doxygen documentation
-//
-// Revision 1.4  2003/07/10 11:27:56  ibelyaev
-//  fixes to please the gcc3.2 compiler
-//
-// Revision 1.3  2003/07/08 19:40:57  ibelyaev
-//  Sensitive Plane Detector + improved printout
-//
-// Revision 1.2  2002/12/13 16:52:57  ibelyaev
-//  put updated versions of the packages
-//
-// Revision 1.2  2002/12/07 21:19:14  ibelyaev
-//  few optimization updates
-//
-// Revision 1.1  2002/12/07 14:41:44  ibelyaev
-//  add new Calo stuff
-// 
-// ============================================================================
-#ifndef CALOSIM_CALOHIT_H 
-#define CALOSIM_CALOHIT_H 1
+#pragma once
 // Include files
 // GaudiKernel
-#include "GaudiKernel/StatusCode.h" 
+#include "GaudiKernel/StatusCode.h"
 // Kernel
 #include "Kernel/CaloCellID.h"
-// GiGa 
+// GiGa
 #include <unordered_map>
-#include "GiGa/GiGaUtil.h"
-// G4 
-#include "Geant4/G4VHit.hh"
+// G4
+#include "Geant4/G4Allocator.hh"
 #include "Geant4/G4THitsCollection.hh"
-// local 
+#include "Geant4/G4VHit.hh"
+// local
 #include "CaloSim.h"
-#include "CaloSubHit.h"
 #include "CaloSimHash.h"
+#include "CaloSubHit.h"
 // forward decalration
-template <class T> class G4THitsCollection;
+template <class T>
+class G4THitsCollection;
 
 /** @class CaloHit CaloHit.h
- * 
+ *
  *  Elementary "hit" for calorimeter devices.
- *  The class represents an list of energy depositions 
- *  from all MC particles for given calorimeter cell 
+ *  The class represents an list of energy depositions
+ *  from all MC particles for given calorimeter cell
  *
  *  The new created hit (of type <tt>CaloHit</tt>
- *  will be attributed to the parent particle of the track 
+ *  will be attributed to the parent particle of the track
  *  with 2 exceptions
- *   - if the track is already forced to be stored 
- *   - if the track is produces outside the "forbidden" zone 
- * 
- *  
+ *   - if the track is already forced to be stored
+ *   - if the track is produces outside the "forbidden" zone
+ *
+ *
  *  @author Vanya Belyaev Ivan.Belyaev@itep.ru
  *  @date   2002-12-03
  */
 
-class CaloHit : public G4VHit
-{
-public:
-  
-  /// the actual data type for particle 
-  typedef int                               TrackID  ;
-  /// collection of sub-hits 
-  typedef std::unordered_map<TrackID,CaloSubHit*>  TheMap   ;
-  /// actual type of the iterator 
-  typedef TheMap::const_iterator            iterator ;
-  
-public:
-  
-  /** standard  constructor 
-   *  @param cell ID of calorimeter cell 
+class CaloHit : public G4VHit {
+  public:
+  /// the actual data type for particle
+  typedef int TrackID;
+  /// collection of sub-hits
+  // FIXME: Use thread-local allocator
+  typedef std::unordered_map<TrackID, CaloSubHit*> TheMap;
+  /// actual type of the iterator
+  typedef TheMap::const_iterator iterator;
+
+  public:
+  /** standard  constructor
+   *  @param cell ID of calorimeter cell
    */
-  CaloHit( const LHCb::CaloCellID& cell = LHCb::CaloCellID() ) ;
+  inline CaloHit(const LHCb::CaloCellID& cell = LHCb::CaloCellID())
+      : m_cellID{cell}, m_map{} {}
 
-  /** copy constructor 
-   *  @param right object to be copied 
+  /** copy constructor
+   *  @param right object to be copied
    */
-  CaloHit( const CaloHit& right );
-  
-  /// clone method (virtual constructor)  
-  virtual CaloHit* clone() const ;
-  
-  /// destructor / delete all subhits 
-  virtual ~CaloHit() ;
-  
-  void* operator  new    ( size_t    ) ;
-  void  operator  delete ( void *hit ) ;
-  
-  /// get the cellID 
-  const LHCb::CaloCellID& cellID () const          { return m_cellID        ; }
-  // set new cellID 
-  void  setCellID ( const LHCb::CaloCellID& cell ) {        m_cellID = cell ; }
-  
-  /** get the hit for the given particle 
-   * 
-   *  @code 
-   * 
+  inline CaloHit(const CaloHit& right)
+      : G4VHit(right), m_cellID(right.cellID()), m_map() {
+    for (auto& [id, hit] : *this)
+
+    {
+      m_map[id] = new CaloSubHit{*hit};
+    }
+  }
+
+  /// destructor / delete all subhits
+  inline virtual ~CaloHit() {
+    /// delete all sub hits
+    for (TheMap::iterator ihit = m_map.begin(); m_map.end() != ihit; ++ihit) {
+      CaloSubHit* hit = ihit->second;
+      if (0 != hit) {
+        delete hit;
+        ihit->second = 0;
+      }
+    }
+    m_map.clear();
+  }
+
+  inline void* operator new(size_t);
+  inline void operator delete(void* hit);
+
+  /// get the cellID
+  inline const LHCb::CaloCellID& cellID() const { return m_cellID; }
+  // set new cellID
+  inline void setCellID(const LHCb::CaloCellID& cell) { m_cellID = cell; }
+
+  /** get the hit for the given particle
+   *
+   *  @code
+   *
    *  CaloHit*                hit   = ... ;
    *  const CaloHit::TrackID  track = ... ;
-   *  
+   *
    *  CaloSubHit*& subhit = hit->hit( track ) ;
-   *  if ( 0 == subhit ) 
-   *        { subhit = new CaloSubHit( hit->cellID() , track ) ; } 
-   *  
+   *  if ( 0 == subhit )
+   *        { subhit = new CaloSubHit( hit->cellID() , track ) ; }
+   *
    *  @endcode
    *
-   *  @return the sub-hit for the given track id (or NULL) 
+   *  @return the sub-hit for the given track id (or NULL)
    */
-  CaloSubHit*& hit( const TrackID track )    { return m_map[ track ] ; }
-  
+  inline CaloSubHit*& hit(const TrackID track) { return m_map[track]; }
+
   /** access to 'begin' iterator of the sub-hit collections (const)
-   *  
+   *
    *  @code
    *
    *  CaloHit* hit = ... ;
-   *  
-   *  for ( CaloHit::iterator entry = hit->begin() ; 
-   *        hit->end() != entry ; ++entry  ) 
+   *
+   *  for ( CaloHit::iterator entry = hit->begin() ;
+   *        hit->end() != entry ; ++entry  )
    *       {
-   *         const CaloHit::TrackID track  = entry->first  ; 
-   *         const CaloSubHit*      subhit = entry->second ; 
+   *         const CaloHit::TrackID track  = entry->first  ;
+   *         const CaloSubHit*      subhit = entry->second ;
    *       }
    *
    *  @endcode
-   *  
+   *
    *  @return 'begin' iterator for sequence of subhits
    */
-  iterator begin     () const { return m_map.begin () ; }
+  iterator begin() const { return m_map.begin(); }
   /** access to 'end'   iterator of the sub-hit collections (const)
-   *  
+   *
    *  @code
    *
    *  CaloHit* hit = ... ;
-   *  
-   *  for ( CaloHit::iterator entry = hit->begin() ; 
-   *        hit->end() != entry ; ++entry  ) 
+   *
+   *  for ( CaloHit::iterator entry = hit->begin() ;
+   *        hit->end() != entry ; ++entry  )
    *       {
-   *         const CaloHit::TrackID track  = entry->first  ; 
-   *         const CaloSubHit*      subhit = entry->second ; 
+   *         const CaloHit::TrackID track  = entry->first  ;
+   *         const CaloSubHit*      subhit = entry->second ;
    *       }
    *
    *  @endcode
-   *  
+   *
    *  @return 'end' iterator for sequence of subhits
    */
-  iterator end       () const { return m_map.end   () ; }
-  
-  /// number of entries/map size 
-  size_t   size      () const { return m_map.size  () ; }
-  size_t   entries   () const { return       size  () ; }
-  
-  /// total number of (sub)entries 
-  size_t   totalSize () const 
-  {
-    size_t size = 0 ;
-    for( iterator hit = begin() ; end() != hit ; ++hit ) 
-      { if( 0 != hit->second ) { size += hit->second->size() ; } }
-    return size ;
+  iterator end() const { return m_map.end(); }
+
+  /// number of entries/map size
+  inline size_t size() const { return m_map.size(); }
+  inline size_t entries() const { return size(); }
+
+  /// total number of (sub)entries
+  inline size_t totalSize() const {
+    size_t size = 0;
+    for (iterator hit = begin(); end() != hit; ++hit) {
+      if (0 != hit->second) {
+        size += hit->second->size();
+      }
+    }
+    return size;
   };
   /** the total energy (integrated over all time slots  and all particles)
-   *  
+   *
    *  @code
-   * 
+   *
    *  const CaloHit*           hit = ... ;
    *  const CaloSubHit::Energy e   = hit->energy() ;
    *
-   *  @endcode 
-   *  
-   *  @return the total energy (integrated over all time 
+   *  @endcode
+   *
+   *  @return the total energy (integrated over all time
    *                             slots  and all particles)
    */
-  CaloSubHit::Energy energy () const 
-  {
-    CaloSubHit::Energy e = 0 ;
-    for( iterator entry = begin() ; end() != entry ; ++entry ) 
-      {
-        const CaloSubHit* hit = entry -> second  ;
-        if( 0 != hit ) { e += hit->energy() ; } 
+  inline CaloSubHit::Energy energy() const {
+    CaloSubHit::Energy e = 0;
+    for (iterator entry = begin(); end() != entry; ++entry) {
+      const CaloSubHit* hit = entry->second;
+      if (0 != hit) {
+        e += hit->energy();
       }
-    return e ;
+    }
+    return e;
   }
-  
-private:
-  
-  LHCb::CaloCellID  m_cellID ;
-  TheMap      m_map    ;
+
+  private:
+  LHCb::CaloCellID m_cellID;
+  TheMap m_map;
 };
 
-/// type for the hit collection 
-typedef G4THitsCollection<CaloHit> CaloHitsCollection ;
+/// type for the hit collection
+typedef G4THitsCollection<CaloHit> CaloHitsCollection;
 
-// ============================================================================
-/** @fn  caloHits
- *  Fast cast of G4VHitsCollection interface to concrete Gauss implementation
- *  @param  g4   pointer to G4VHitsCollection interface 
- *  @return cast (dynamic or static) to CaloHitsColelction*
- *  @author  Vanya Belyaev Ivan.Belyaev@itep.ru
- *  @date    2002-12-07
- */
-// ============================================================================
-inline CaloHitsCollection* caloHits( G4VHitsCollection* g4 )
-{
-  GiGaUtil::FastCast<G4VHitsCollection,CaloHitsCollection> cast ;
-  return cast( g4 );  
-}
+extern G4ThreadLocal G4Allocator<CaloHit>* aCaloHitAllocator;
 
-// ============================================================================
-/** @fn  caloHit
- *  Fast cast of G4VHit interface to concrete Gauss implementation
- *  @param  g4   pointer to G4VHit interface 
- *  @return cast (dynamic or static) to CaloHit
- *  @author  Vanya Belyaev Ivan.Belyaev@itep.ru
- *  @date    2002-12-07
- */
-// ============================================================================
-inline CaloHit* caloHit( G4VHit* g4 )
-{
-  GiGaUtil::FastCast<G4VHit,CaloHit> cast ;
-  return cast( g4 );  
+inline void* CaloHit::operator new(size_t) {
+  if (!aCaloHitAllocator) {
+    aCaloHitAllocator = new G4Allocator<CaloHit>;
+  }
+  return (void*)aCaloHitAllocator->MallocSingle();
 }
 
-
-// ============================================================================
-// The END 
-// ============================================================================
-#endif // CALOSIM_CALOHIT_H
-// ============================================================================
+inline void CaloHit::operator delete(void* aHit) {
+  aCaloHitAllocator->FreeSingle((CaloHit*)aHit);
+}
diff --git a/Sim/GaussCalo/src/CaloSensDet.cpp b/Sim/GaussCalo/src/CaloSensDet.cpp
deleted file mode 100755
index 6af945101..000000000
--- a/Sim/GaussCalo/src/CaloSensDet.cpp
+++ /dev/null
@@ -1,394 +0,0 @@
-// $Id: CaloSensDet.cpp,v 1.24 2008-07-11 10:47:44 robbep Exp $
-// Include files
-
-// SRD & STD
-#include <algorithm>
-#include <vector>
-#include <sstream>
-
-// LHCbDefintions
-#include "CLHEP/Geometry/Point3D.h"
-
-// from Gaudi
-#include "GaudiKernel/Point3DTypes.h"
-#include "GaudiKernel/MsgStream.h"
-#include "GaudiKernel/SmartDataPtr.h"
-#include "GaudiKernel/IDataProviderSvc.h"
-#include "GaudiKernel/IHistogramSvc.h"
-#include "GaudiKernel/Stat.h"
-
-// GaussTools
-#include "GaussTools/GaussTrackInformation.h"
-
-// Geant4
-#include "Geant4/G4Step.hh"
-#include "Geant4/G4TouchableHistory.hh"
-#include "Geant4/G4VPhysicalVolume.hh"
-#include "Geant4/G4LogicalVolume.hh"
-#include "Geant4/G4SDManager.hh"
-#include "Geant4/G4EnergyLossTables.hh"
-#include "Geant4/G4Material.hh"
-#include "Geant4/G4MaterialCutsCouple.hh"
-
-// GiGaCnv
-#include "GiGaCnv/GiGaVolumeUtils.h"
-
-// CaloDet
-#include "CaloDet/DeCalorimeter.h"
-
-// local
-#include "CaloSensDet.h"
-#include "CaloHit.h"
-#include "CaloSimHash.h"
-
-// AIDA
-#include "AIDA/IHistogram1D.h"
-
-// Boost
-#include "boost/format.hpp"
-
-// ============================================================================
-/** @file
- *
- *  Implementation of class CaloSensDet
- *
- *  @author Vanya Belyaev
- *  @date   23/01/2001
- */
-// ============================================================================
-
-// ============================================================================
-/** standard constructor
- *  @see GiGaSensDetBase
- *  @see GiGaBase
- *  @see AlgTool
- *  @param type type of the object (?)
- *  @param name name of the object
- *  @param parent  pointer to parent object
- */
-// ============================================================================
-CaloSensDet::CaloSensDet
-( const std::string& type   ,
-  const std::string& name   ,
-  const IInterface*  parent )
-  : G4VSensitiveDetector ( name  )
-  , GiGaSensDetBase      ( type , name , parent )
-  , m_endVolumeName      ( "World" )
-  , m_end                ( 0       )
-  , m_startVolumeNames   (         )
-  , m_start              (         )
-  , m_volumesLocated     ( false   )
-  ///
-  , m_collectionName     ( "Hits"  )
-  , m_table              ()
-  , m_hitmap             ()
-  //
-  , m_caloName           ( DeCalorimeterLocation::Ecal )
-  , m_calo               ( 0 )
-  , m_caloID             ( 0 )
-  ///
-  , m_zmin               ( -1 * CLHEP::km )  // minimal z of forbidden zone
-  , m_zmax               (  1 * CLHEP::km )  // maximal z of forbidden zone
-  ///
-  , m_collection         ( 0 )
-  // input histograms
-  , m_histoNames         (   )
-  , m_histos             (   )
-  , m_histoSvc           ( 0 )
-  //
-  , m_birk_c1            ( 0.013  * CLHEP::g/CLHEP::MeV/CLHEP::cm2 ) // 1st coef. of Birk's
-  , m_birk_c2            ( 9.6E-6 * CLHEP::g*CLHEP::g/CLHEP::MeV/CLHEP::MeV/CLHEP::cm2/CLHEP::cm2 ) // 2nd coef
-  //. of Birk's law correction of c1 for 2e charged part.
-  , m_birk_c1correction  ( 0.57142857                   )
-  /// correction to t0
-  , m_dT0                ( 0.5 * CLHEP::ns              )
-{
-  setProperty     ( "DetectorDataProvider" ,  "DetectorDataSvc"   ) ;
-
-  declareProperty ( "StartVolumes"         ,  m_startVolumeNames  ) ;
-  declareProperty ( "EndVolume"            ,  m_endVolumeName     ) ;
-  declareProperty ( "CollectionName"       ,  m_collectionName    ) ;
-  declareProperty ( "Detector"             ,  m_caloName          ) ;
-  declareProperty ( "zMin"                 ,  m_zmin              ) ;
-  declareProperty ( "zMax"                 ,  m_zmax              ) ;
-  //
-  declareProperty ( "BirkC1"               ,  m_birk_c1           ) ;
-  declareProperty ( "BirkC1cor"            ,  m_birk_c1correction ) ;
-  declareProperty ( "BirkC2"               ,  m_birk_c2           ) ;
-  //
-  declareProperty ( "dT0"                  ,  m_dT0               ) ;
-  // input histograms(parametrization)
-  declareProperty ( "Histograms"           ,  m_histoNames        ) ;
-}
-
-// ============================================================================
-/** standard initialization (Gaudi)
- *  @see GiGaSensDetBase
- *  @see GiGaBase
- *  @see   AlgTool
- *  @see  IAlgTool
- *  @return statsu code
- */
-// ============================================================================
-StatusCode CaloSensDet::initialize   ()
-{
-  // initialze the base class
-  StatusCode sc = GiGaSensDetBase::initialize();
-  if( sc.isFailure() )
-    { return Error("Could not initialize the base class!",sc);}
-  //
-  // clear collection name vector
-  collectionName.clear  () ;
-  collectionName.insert ( m_collectionName );
-  ///
-  m_calo = getDet<DeCalorimeter>(  m_caloName );
-  if( 0 == m_calo   ) { return StatusCode::FAILURE                     ; }
-  m_caloID   = CaloCellCode::CaloNumFromName( caloName()             ) ;
-  if( 0 >  caloID() ) { return Error("Invalid detector name/number!" ) ; }
-  ///
-  m_histoSvc = svc<IHistogramSvc> ( "HistogramDataSvc" , true ) ;
-  { // load all input histos
-    for( Names::const_iterator ihist = m_histoNames.begin() ;
-         m_histoNames.end() != ihist ; ++ihist )
-      {
-        SmartDataPtr<IHistogram1D> pHist( histoSvc() , *ihist );
-        IHistogram1D* hist = pHist ;
-        if( 0 == hist )
-          { return Error("Cannot load histogram '"+(*ihist)+"'"); }
-        m_histos.push_back ( hist ) ;
-      }
-    if ( histos().empty() )
-    { Warning ( "Empty vector of input time-histograms" ) ; }
-  }
-  ///
-  return StatusCode::SUCCESS ;
-}
-
-// ============================================================================
-/** standard finalization (Gaudi)
- *  @see GiGaSensDetBase
- *  @see GiGaBase
- *  @see   AlgTool
- *  @see  IAlgTool
- *  @return statsu code
- */
-// ============================================================================
-StatusCode CaloSensDet::finalize    ()
-{
-  // reset the detector element
-  m_calo         = 0 ;
-  // clear the translation table
-  m_table  .clear () ;
-  // clear hit map
-  m_hitmap .clear () ;
-  // clear volumes
-  m_start  .clear () ;
-  // clear histograms
-  m_histos .clear () ;
-  // finalize the base class
-  return GiGaSensDetBase::finalize();
-}
-
-// ============================================================================
-/** helpful method to locate start and end volumes
- *  @return status code
- */
-// ============================================================================
-StatusCode  CaloSensDet::locateVolumes()
-{
-  // locate start volumes
-  for( Names::const_iterator vol =  m_startVolumeNames.begin() ;
-       m_startVolumeNames.end() != vol ; ++vol )
-    {
-      // look through converted volumes
-      const G4LogicalVolume* lv = GiGaVolumeUtils::findLVolume   ( *vol );
-      if( 0 == lv )
-        { return Error("G4LogicalVolume* points to 0 for "+ (*vol) );}
-      m_start.push_back( lv );
-    }
-  if( m_start.empty() ) { return Error("Size of 'StartVolumes' is 0 "); }
-  // locate end volume : look through converted volumes
-  m_end = GiGaVolumeUtils::findLVolume   ( m_endVolumeName );
-  if( 0 == m_end )
-    { return Error("G4LogicalVolume* points to 0 for '"+m_endVolumeName+"'");}
-  // set flag
-  m_volumesLocated = true ;
-  //
-  return StatusCode::SUCCESS ;
-}
-
-// ============================================================================
-/** method from G4
- *  (Called at the begin of each event)
- *  @see G4VSensitiveDetector
- *  @param HCE pointer to hit collection of current event
- */
-// ============================================================================
-void CaloSensDet::Initialize( G4HCofThisEvent* HCE )
-{
-  //
-  if( !m_volumesLocated )
-  {
-    StatusCode sc = locateVolumes();
-    if ( sc.isFailure() ) { Error("Error from 'locateVolumes' method",sc); }
-  }
-  Assert ( m_volumesLocated , "Could not locate volumes!");
-  //
-  m_collection = new CaloHitsCollection ( SensitiveDetectorName ,
-                                          collectionName[0]     ) ;
-  //
-  const int id  = GetCollectionID( 0 ) ;
-
-  HCE -> AddHitsCollection( id , m_collection );
-
-  //
-  if ( msgLevel ( MSG::DEBUG ) )
-  {
-    debug() << " Initialize(): CollectionName='"
-            << m_collection->GetName   ()
-            << "' for SensDet='"
-            << m_collection->GetSDname ()
-            <<"'" << endmsg ;
-  }
-  //
-  m_hitmap.clear() ;
-}
-
-// ============================================================================
-/** method from G4
- *  (Called at the end of each event)
- *  @see G4VSensitiveDetector
- *  @param HCE pointer to hit collection of current event
- */
-// ============================================================================
-void CaloSensDet::EndOfEvent ( G4HCofThisEvent* /* HCE */ )
-{
-  /// clear the map
-  m_hitmap.clear();
-
-  if ( !printStat() && !msgLevel ( MSG::DEBUG ) ) { return ; }
-
-  if ( 0 == m_collection )
-  { Warning ( " EndOfEvent(): HitCollection points to NULL " ) ; return ; }
-  typedef std::vector<CaloHit*> Hits ;
-  const Hits* hits = m_collection ->GetVector() ;
-  if ( 0 == hits )
-  { Error   (" EndOfEvent(): HitVector* points to NULL "     ) ; return ; }
-
-  // initialize counters
-  const size_t nhits = hits->size()  ;
-  size_t nshits = 0 ;
-  size_t nslots = 0 ;
-  double energy = 0 ;
-
-  // the loop over all hits
-  for ( Hits::const_iterator ihit = hits->begin() ;
-        hits->end() != ihit ; ++ihit )
-  {
-    const CaloHit* hit = *ihit ;
-    if( 0 == hit ) { continue ; }                           // CONTINUE
-    nshits += hit -> size      () ;
-    nslots += hit -> totalSize () ;
-    energy += hit -> energy    () ;
-  }
-
-  energy /= CLHEP::GeV ;                               // NB: rescale to GeV
-
-  counter ( "#hits"    ) += nhits  ;
-  counter ( "#subhits" ) += nshits ;
-  counter ( "#tslots"  ) += nslots ;
-  counter ( "#energy"  ) += energy ;
-
-  if ( msgLevel ( MSG::DEBUG ) )
-  {
-    always() << boost::format
-      ( " #Hits=%5d #SubHits=%5d #Slots=%5d Energy=%8.3g[GeV] " )
-      % nhits % nshits % nslots % energy << endmsg ;
-  }
-
-}
-
-// ============================================================================
-/** process the hit
- *  @param step     pointer to current Geant4 step
- *  @param history  pointert to touchable history
- */
-// ============================================================================
-bool CaloSensDet::ProcessHits
-( G4Step* step                      ,
-  G4TouchableHistory* /* history */ )
-{
-
-  if( 0 == step ) { return false ; }
-  ///
-  const double                      deposit  = step-> GetTotalEnergyDeposit () ;
-  if( deposit <= 0            ) { return false ; }                 // RETURN
-
-  const G4Track*              const track    = step     -> GetTrack      () ;
-  const int                         trackID  = track    -> GetTrackID    () ;
-  const G4ParticleDefinition* const particle = track    -> GetDefinition () ;
-  const double                      charge   = particle -> GetPDGCharge  () ;
-
-  if ( 0 == int ( charge * 10 ) ) { return false ; }               // RETURN
-
-  const G4StepPoint* const          preStep  = step    -> GetPreStepPoint () ;
-  const HepGeom::Point3D<double>&   prePoint = preStep -> GetPosition     () ;
-  const double                      time     = preStep -> GetGlobalTime   () ;
-  const G4MaterialCutsCouple* const material = preStep ->
-    GetMaterialCutsCouple () ;
-
-  const LHCb::CaloCellID cellID = cell ( preStep ) ;
-  if ( LHCb::CaloCellID() == cellID ) { return false ; }
-
-  // get the existing hit
-  CaloHit*& hit = m_hitmap[ cellID ] ;
-  if ( 0 == hit )
-  {
-    // create new hit
-    hit = new CaloHit      ( cellID ) ;
-    // add it into collection
-    m_collection -> insert ( hit    ) ;
-  }
-
-  // check the status of the track
-  GaussTrackInformation* info =
-    gaussTrackInformation ( track->GetUserInformation() );
-  if( 0 == info )
-  { Error("Invalid Track information") ; return false ; }     // RETURN
-
-  // ID of the track to be stored
-  int sTrackID     = track -> GetParentID () ;
-
-  // already marked to be stored:
-  if     ( info -> toBeStored()     ) { sTrackID = trackID ; }
-  else
-  {
-    // z-position of production vertex
-    const double z0 = track->GetVertexPosition().z() ;
-    // outside the "forbidden zone" ?
-    if ( z0 < zMin() || z0 > zMax ()  ) { sTrackID = trackID ; }
-  }
-
-  // Does the hit exist for the given track?
-  CaloSubHit*& sub  = hit->hit( sTrackID ) ;                   // ATTENTION
-  // create new subhit if needed
-  if ( 0 == sub ) { sub = new CaloSubHit ( cellID , sTrackID ) ; }
-  // update the track information
-  if ( trackID == sTrackID ) { info->addToHits ( sub ) ; }
-
-  // perform the specific sub-detector action
-  StatusCode sc = fillHitInfo ( sub       ,
-                                prePoint  ,
-                                time      ,
-                                deposit   ,
-                                track     ,
-                                particle  ,
-                                material  ,
-                                step      ) ;
-
-  if ( sc.isFailure() ){ Error("The SubHit information is not filled!",sc) ; }
-
-  return true ;
-}
-
-// ============================================================================
diff --git a/Sim/GaussCalo/src/CaloSensDet.h b/Sim/GaussCalo/src/CaloSensDet.h
index 83098c788..51d8f0416 100755
--- a/Sim/GaussCalo/src/CaloSensDet.h
+++ b/Sim/GaussCalo/src/CaloSensDet.h
@@ -1,30 +1,33 @@
-// $Id: CaloSensDet.h,v 1.15 2007-03-18 21:33:19 gcorti Exp $
-#ifndef       GAUSSCALO_CaloSensDet_H
-#define       GAUSSCALO_CaloSensDet_H 1
+#pragma once
 
 // GaudiKernel
 #include "GaudiKernel/HashMap.h"
 
+// from Gaudi
+#include "GaudiKernel/Counters.h"
+#include "GaudiKernel/Point3DTypes.h"
+
 // GiGa
-#include "GiGa/GiGaSensDetBase.h"
+#include "Geant4/G4VSensitiveDetector.hh"
+#include "GiGaMTCore/IGiGaMessage.h"
 
 // AIDA
 #include "AIDA/IHistogram1D.h"
 
 // local
+#include "CaloHit.h"
 #include "CaloSim.h"
 #include "CaloSimHash.h"
-#include "CaloHit.h"
 
 // GEANT4
+#include "Geant4/G4EnergyLossTables.hh"
 #include "Geant4/G4Material.hh"
 #include "Geant4/G4MaterialCutsCouple.hh"
 
 #include "CLHEP/Geometry/Transform3D.h"
 
 // forward declarations
-class DeCalorimeter ;  // CaloDet
-class IHistogramSvc ;  // GaudiKernel
+class IHistogramSvc;  // GaudiKernel
 
 /** @class CaloSensDet CaloSensDet.h CaloSensDet.h
  *
@@ -32,42 +35,27 @@ class IHistogramSvc ;  // GaudiKernel
  *  @author  Vanya Belyaev
  *  @date    23/01/2001
  */
-class CaloSensDet: public GiGaSensDetBase
-{
-public:
+
+template <typename CELLGETTER>
+class CaloSensDet : public G4VSensitiveDetector,
+                    private virtual CELLGETTER,
+                    public virtual GiGaMessage {
+  public:
   /// useful type for list of names
-  typedef std::vector<std::string>              Names      ;
+  typedef std::vector<std::string> Names;
   /// useful type for list of logical volumes
-  typedef std::vector<const G4LogicalVolume*>   Volumes    ;
+  typedef std::vector<const G4LogicalVolume*> Volumes;
   /// translator from Path to CellID
-  typedef GaudiUtils::HashMap<CaloSim::Path,LHCb::CaloCellID> Table  ;
-  typedef GaudiUtils::HashMap<LHCb::CaloCellID,CaloHit*>      HitMap ;
+  typedef GaudiUtils::HashMap<CaloSim::Path, LHCb::CaloCellID> Table;
+  typedef GaudiUtils::HashMap<LHCb::CaloCellID, CaloHit*> HitMap;
   /// type for all histograms
-  typedef std::vector<AIDA::IHistogram1D*>            Histos     ;
+  typedef std::vector<AIDA::IHistogram1D*> Histos;
   /// the typedef for vector of fractions
-  typedef std::vector<double>                   Fractions  ;
-
-public :
-
-  /** standard initialization (Gaudi)
-   *  @see GiGaSensDetBase
-   *  @see GiGaBase
-   *  @see   AlgTool
-   *  @see  IAlgTool
-   *  @return status code
-   */
-  StatusCode initialize   () override;
-
-  /** standard finalization (Gaudi)
-   *  @see GiGaSensDetBase
-   *  @see GiGaBase
-   *  @see   AlgTool
-   *  @see  IAlgTool
-   *  @return status code
-   */
-  StatusCode finalize    () override;
+  typedef std::vector<double> Fractions;
 
-public:
+  public:
+  CaloSensDet(const std::string& name);
+  virtual ~CaloSensDet() = default;
 
   /** process the hit.
    *  The method is invoked by G4 for each step in the
@@ -87,123 +75,78 @@ public:
    *  @param history  pointert to touchable history
    *  @attention One should not redefine this method for specific sub-detectors.
    */
-  bool ProcessHits
-  ( G4Step*             step    ,
-    G4TouchableHistory* history ) override;
+  bool ProcessHits(G4Step* step, G4TouchableHistory* history) override;
+
+  // ============================================================================
+  /** helper method to locate the Calorimeter cell to which
+   *  G4 point belongs to
+   *  @param point G4 point
+   *  @retuen calorimeter cell identifier
+   */
+  // ============================================================================
+  inline LHCb::CaloCellID cell(const G4StepPoint* point) const;
 
   /** method from G4
    *  (Called at the begin of each event)
    *  @see G4VSensitiveDetector
    *  @param HCE pointer to hit collection of current event
    */
-  void Initialize( G4HCofThisEvent* HCE ) override;
+  void Initialize(G4HCofThisEvent* HCE) override;
 
   /** method from G4
    *  (Called at the end of each event)
    *  @see G4VSensitiveDetector
    *  @param HCE pointer to hit collection of current event
    */
-  void EndOfEvent( G4HCofThisEvent* HCE ) override;
-
-protected:
-
-  /** helpful method to locate start and end volumes
-   *  @return status code
-   */
-  StatusCode locateVolumes();
-
-public:
-
-  /** standard constructor
-   *  @see GiGaSensDetBase
-   *  @see GiGaBase
-   *  @see AlgTool
-   *  @param type type of the object (?)
-   *  @param name name of the object
-   *  @param parent  pointer to parent object
-   */
-  CaloSensDet
-  ( const std::string& type   ,
-    const std::string& name   ,
-    const IInterface*  parent ) ;
-
-  /// destructor (virtual and protected)
-  virtual ~CaloSensDet() {};
-
-private:
+  void EndOfEvent(G4HCofThisEvent* HCE) override;
 
+  public:
   // no default constructor
-  CaloSensDet() ;
+  CaloSensDet() = delete;
   // no copy constructor
-  CaloSensDet           ( const CaloSensDet& );
+  CaloSensDet(const CaloSensDet&) = delete;
   // no assignement
-  CaloSensDet& operator=( const CaloSensDet& ) ;
-
-protected:
-
-  /// acess to detector element
-  inline const DeCalorimeter* calo     () const  { return m_calo       ; }
-
-  /// return the (De)Calorimeter name
-  inline const std::string&   caloName () const { return m_caloName    ; }
-
-  /// return the (De)Calorimeter ID
-  inline int                  caloID   () const  { return m_caloID     ; }
+  CaloSensDet& operator=(const CaloSensDet&) = delete;
 
+  protected:
   /// access to hit collection
-  inline CaloHitsCollection*  hits     () const  { return m_collection ; }
+  inline CaloHitsCollection* hits() const { return m_collection; }
 
   /// access to translation table
-  inline Table&               table    ()        { return m_table      ; }
+  inline Table& table() { return m_table; }
 
   /// access to hit map
-  inline HitMap&              hitmap   ()        { return m_hitmap     ; }
+  inline HitMap& hitmap() { return m_hitmap; }
 
   /// access to minimal z
-  inline double               zMin     () const  { return m_zmin       ; }
+  inline double zMin() const { return m_zmin; }
 
   /// access to maximal z
-  inline double               zMax     () const  { return m_zmax       ; }
+  inline double zMax() const { return m_zmax; }
 
   /// the additive correction to 't0' evaluation
-  inline double               dT0      () const  { return m_dT0        ; }
+  inline double dT0() const { return m_dT0; }
 
   /** the evaluation of t0 for given calorimetr cell
    *  @param cellID the calorimeter cell identifier
    *  @return "time"-parameter for the given cell
    *           it is evaluated per cell basis in DeCalorimeter
    */
-  inline double               t0       ( const LHCb::CaloCellID& cellID ) const ;
+  inline double t0(const LHCb::CaloCellID& cellID) const;
 
   /// the first coefficient of Birks's law
-  inline double               birk_c1    () const { return m_birk_c1 ; }
+  inline double birk_c1() const { return m_birk_c1; }
   /// the second coefficient of Birks's law
-  inline double               birk_c2    () const { return m_birk_c2 ; }
+  inline double birk_c2() const { return m_birk_c2; }
   /// the correction to the first coefficient of Birks's law
-  inline double               birk_c1cor () const
-  { return m_birk_c1correction ; }
+  inline double birk_c1cor() const { return m_birk_c1correction; }
 
   /// the accessor to all time-histograms      (const version)
-  inline const Histos&        histos     () const { return m_histos     ; }
+  inline const Histos& histos() const { return m_histos; }
   /// the accessor to all time-histograms  (non-const version)
-  inline       Histos&        histos     ()       { return m_histos     ; }
-  /// the accessor to the names of  histograms
-  inline const Names&         histoNames () const { return m_histoNames ; }
-
-  /// accessor to histogram service
-  inline IHistogramSvc*       histoSvc   () const { return m_histoSvc   ; }
-
-protected:
-
-  /** helper method to locate the Calorimeter cell to which
-   *  G4 point belongs to
-   *  @param point G4 point
-   *  @retuen calorimeter cell identifier
-   */
-  inline LHCb::CaloCellID cell ( const G4StepPoint* point ) const ;
-
-protected:
+  inline Histos& histos() { return m_histos; }
 
+  protected:
   /** fill the hit with the concrete information about the energy and the time.
    *  The function is to be called from ProcessHits method.
    *
@@ -225,15 +168,13 @@ protected:
    *    (Birk's,timing, non-uniformities, etc ) need to be applied here!
    *
    */
-  virtual StatusCode    fillHitInfo
-  ( CaloSubHit*                 hit         ,
-    const HepGeom::Point3D<double>& prePoint    ,
-    const double                globalTime  ,
-    const double                deposit     ,
-    const G4Track*              track       ,
-    const G4ParticleDefinition* pdef        ,
-    const G4MaterialCutsCouple* material    ,
-    const G4Step*               step        ) const = 0 ;
+  virtual bool fillHitInfo(CaloSubHit* hit,
+                           const HepGeom::Point3D<double>& prePoint,
+                           const double globalTime, const double deposit,
+                           const G4Track* track,
+                           const G4ParticleDefinition* pdef,
+                           const G4MaterialCutsCouple* material,
+                           const G4Step* step) const = 0;
 
   /** The fractions of energy deposited in consequitive time-bins
    *  for the given calorimeter cell
@@ -243,19 +184,16 @@ protected:
    *  @param fracs the vector of fractions for subsequent time-bins;
    *  @return StatuscCode
    */
-  virtual StatusCode timing
-  ( const double      time      ,
-    const LHCb::CaloCellID& cell      ,
-    CaloSubHit::Time& slot      ,
-    Fractions&        fractions ) const  = 0 ;
-
-protected:
+  virtual bool timing(const double time, const LHCb::CaloCellID& cell,
+                      CaloSubHit::Time& slot,
+                      Fractions& fractions) const = 0;
 
+  protected:
   /** Correction factor from Birk's Law
    *  @param step current G4step
    *  @return the correction factor
    */
-  inline double birkCorrection ( const G4Step* step ) const ;
+  inline double birkCorrection(const G4Step* step) const;
 
   /** Birk's correction for given particle with given kinetic energy
    *  for the given material
@@ -263,10 +201,9 @@ protected:
    *  @param  Ekine    particle kinetic energy
    *  @param  maerial  pointer ot teh material
    */
-  inline double  birkCorrection
-  ( const G4ParticleDefinition* particle ,
-    const double                eKine    ,
-    const G4MaterialCutsCouple* material ) const ;
+  inline double birkCorrection(const G4ParticleDefinition* particle,
+                               const double eKine,
+                               const G4MaterialCutsCouple* material) const;
 
   /** evaluate the correction for Birk's law
    *  @param charge   the charge of the particle
@@ -274,10 +211,8 @@ protected:
    *  @param material the pointer ot teh material
    *  @return the correction coefficient
    */
-  inline double  birkCorrection
-  ( const double      charge   ,
-    const double      dEdX     ,
-    const G4Material* material ) const ;
+  inline double birkCorrection(const double charge, const double dEdX,
+                               const G4Material* material) const;
 
   /** evaluate the correction for Birk's law
    *  @param charge   the charge of the particle
@@ -285,240 +220,71 @@ protected:
    *  @param density  the density ot the material
    *  @return the correction coefficient
    */
-  inline double  birkCorrection
-  ( const double      charge   ,
-    const double      dEdX     ,
-    const double      density  ) const ;
-
-private:
+  inline double birkCorrection(const double charge, const double dEdX,
+                               const double density) const;
 
-  std::string                                 m_endVolumeName       ;
-  const G4LogicalVolume*                      m_end                 ;
+  private:
+  const G4LogicalVolume* m_end;
 
   // definition logical volumes where will be analysed signal
-  Names                                       m_startVolumeNames    ;
-  Volumes                                     m_start               ;
-
-  bool                                        m_volumesLocated      ;
-
-  /// name for created collection
-  std::string                                 m_collectionName      ;
+  Volumes m_start;
 
   // translation table
-  mutable Table                               m_table               ;
-  HitMap                                      m_hitmap              ;
-
-  std::string                                 m_caloName            ;
-  const DeCalorimeter*                        m_calo                ;
-  int                                         m_caloID              ;
-
-  double                                      m_zmin                ;
-  double                                      m_zmax                ;
+  mutable Table m_table;
+  HitMap m_hitmap;
 
-  CaloHitsCollection*                         m_collection          ;
+  CaloHitsCollection* m_collection;
 
-private:
+  bool m_geoBaseInitialized{false};
+  void GeoBaseInitialize();
 
-  /// the vector of histogram names/addresses
-  Names                                      m_histoNames ;
+  public:
   /// all histograms
-  Histos                                     m_histos     ;
-  /// histogram service
-  IHistogramSvc*                             m_histoSvc   ;
-
-private:
+  Histos m_histos;
+  std::string m_endVolumeName{};
+  Names m_startVolumeNames{};
 
   // the first coefficient of Birk's law                    (c1)
-  double                                      m_birk_c1             ;
+  double m_birk_c1{0.013 * CLHEP::g / CLHEP::MeV / CLHEP::cm2};
   // the second coefficient of Birk's law                   (c2)
-  double                                      m_birk_c2             ;
+  double m_birk_c2{9.6E-6 * CLHEP::g * CLHEP::g / CLHEP::MeV / CLHEP::MeV /
+                   CLHEP::cm2 / CLHEP::cm2};
   // the correction to the first coefficient of Birk's law  (c1')
-  double                                      m_birk_c1correction   ;
+  double m_birk_c1correction{0.57142857};
 
-private:
+  double m_zmin{-1 * CLHEP::km};
+  double m_zmax{1 * CLHEP::km};
 
   // the additive correction for the evaluation of t0
-  double   m_dT0    ;
-
+  double m_dT0{0.5 * CLHEP::ns};
+  Gaudi::Accumulators::SummingCounter<size_t>* m_nhits{nullptr};
+  Gaudi::Accumulators::SummingCounter<size_t>* m_nshits{nullptr};
+  Gaudi::Accumulators::SummingCounter<size_t>* m_nslots{nullptr};
+  Gaudi::Accumulators::SummingCounter<double>* m_energy{nullptr};
 };
-// ============================================================================
 
-// ============================================================================
-/** the evaluation of t0 for given calorimetr cell
- *  @param cellID the calorimeter cell identifier
- *  @return "time"-parameter for the given cell
- *           it is evaluated per cell basis in DeCalorimeter
- */
-// ============================================================================
-inline double CaloSensDet::t0       ( const LHCb::CaloCellID& cellID ) const
-{ return calo()->cellTime( cellID ) - dT0 () ; }
-// ============================================================================
-/** helper method to locate the Calorimeter cell to which
- *  G4 point belongs to
- *  @param point G4 point
- *  @retuen calorimeter cell identifier
- */
-// ============================================================================
-inline LHCb::CaloCellID CaloSensDet::cell ( const G4StepPoint* point ) const
-{
-  // current solution!
-  // LHCb::CaloCellID id = calo() -> Cell ( point->GetPosition() ) ;
-  // return id ;
-
-  G4TouchableHistory* tHist  =
-    (G4TouchableHistory*) point->GetTouchable()  ;
-
-  const int nLevel = tHist->GetHistoryDepth() ;
-  CaloSim::Path path ;
-  path.reserve ( nLevel ) ;
-
-  for ( int  level = 0 ; level < nLevel ; ++level )
-  {
-    const G4VPhysicalVolume* pv = tHist->GetVolume ( level ) ;
-    if      (  0     == pv  ) { continue ; }                        // CONTINUE
-    const G4LogicalVolume*   lv = pv -> GetLogicalVolume() ;
-    if      (  0     == lv  ) { continue ; }                        // CONTINUE
-    // start volume ??
-    if      (  m_end == lv  ) { break    ; }                        // BREAK
-    // useful volume ?
-    if      ( !path.empty() ) { path.push_back( pv ) ; }
-    else if ( m_start.end() !=
-              std::find ( m_start.begin () ,
-                          m_start.end   () , lv ) ) { path.push_back( pv ) ; }
-  }
-
-  if ( path.empty() )
-  { Error ( "Volume path is invalid(empty) " ) ; return LHCb::CaloCellID() ; }
-
-  // find the appropriate ID
-  Table::iterator ifound = m_table.find ( path ) ;
-  // already in the table ?
-  if ( m_table.end() != ifound ) { return ifound->second ; }    // RETURN
-
-  // if not: add it into the table!
-  // CLHEP -> ROOT
-  HepGeom::Transform3D mtrx( *(tHist->GetRotation()) , tHist->GetTranslation() );
-  auto heppoint = mtrx * HepGeom::Point3D<double>{};
-  const Gaudi::XYZPoint p ( heppoint.x(),heppoint.y(),heppoint.z() );
-  // get the right cell
-  const CellParam* par = calo()->Cell_( p ) ;
-  if ( 0 == par || !par->valid() )
-  {
-    m_table.insert ( Table::value_type( path , LHCb::CaloCellID() ) ) ;
-    return LHCb::CaloCellID() ;                                   // RETURN
+#include "CaloSensDet.icpp"
+
+// CaloDet
+#include "CaloDet/DeCalorimeter.h"
+class CellFromLHCbGeo : public virtual IGiGaMessage {
+  protected:
+  CellFromLHCbGeo() = default;
+  virtual ~CellFromLHCbGeo() = default;
+  inline double cellTime(const LHCb::CaloCellID& cellID) const {
+    return m_calo->cellTime(cellID);
+  };
+  inline LHCb::CaloCellID cellID(const Gaudi::XYZPoint& position) const {
+    const CellParam* par = m_calo->Cell_(position);
+    if (0 == par || !par->valid()) {
+      return LHCb::CaloCellID();  // RETURN
+    }
+    return par->cellID();
   }
-  //
-  m_table.insert ( Table::value_type( path , par-> cellID() ) ) ;
-  //
-  return par->cellID() ;
-}
-
-// ============================================================================
-/** evaluate the correction for Birk's law
- *  @param charge   the charge of the particle
- *  @param dEdX     the nominal dEdX in the material
- *  @param density
- *  @return the correction coefficient
- */
-// ============================================================================
-inline double  CaloSensDet::birkCorrection
-( const double      charge   ,
-  const double      dEdX     ,
-  const double      density  ) const
-{
-  const double C1 =
-    fabs( charge )  < 1.5 ? birk_c1() : birk_c1() * birk_c1cor() ;
-  const double C2 = birk_c2() ;
-
-  const double alpha = dEdX/ density ;
-
-  return 1.0 / ( 1.0 + C1 * alpha + C2 * alpha * alpha ) ;
-}
-
-// ============================================================================
-/** evaluate the correction for Birk's law
- *  @param charge   the charge of the particle
- *  @param dEdX     the nominal dEdX in the material
- *  @param material the pointer ot teh material
- *  @return the correction coefficient
- */
-// ============================================================================
-inline double  CaloSensDet::birkCorrection
-( const double      charge   ,
-  const double      dEdX     ,
-  const G4Material* material ) const
-{
-  if ( 0 == material )
-  { Error("birkCorrection(): invalid material " ) ; return 1. ; } // RETURN
-  return birkCorrection( charge , dEdX , material->GetDensity() ) ;
-}
-
-// ============================================================================
-/** Birk's correction for given particle with given kinetic energy
- *  for the given material
- *  @param  particle pointer to particle definition
- *  @param  Ekine    particle kinetic energy
- *  @param  maerial  pointer ot teh material
- */
-// ============================================================================
-inline double CaloSensDet::birkCorrection
-( const G4ParticleDefinition* particle ,
-  const double                eKine    ,
-  const G4MaterialCutsCouple* material ) const
-{
-  if (  0 == particle || 0 == material )
-  { Error("birkCorrection(): invalid parameters " ) ; return 1.0 ; } // RETURN
-
-  const double charge = particle -> GetPDGCharge() ;
-  if ( fabs ( charge ) < 0.1                      ) { return 1.0 ; } // EEUTRN
-
-  // get the nominal dEdX
-  const double dEdX  =
-    G4EnergyLossTables::GetDEDX ( particle , eKine , material ) ;
-
-  // make an actual evaluation
-  return birkCorrection
-    ( charge ,
-      dEdX   ,
-      material->GetMaterial()->GetDensity() ) ;
-}
-
-// ============================================================================
-// Birk's Law
-// ============================================================================
-/** Correction factor from Birk's Law
- *  Factor = 1/(1+C1*dEdx/rho+C2*(dEdx/rho)^2)
- *  Where :
- *      - C1 = 0.013 g/MeV/cm^2 [Ref NIM 80 (1970) 239]
- *      - C2 = 9.6.10^-6 g^2/MeV^2/cm^4
- *      - dEdx in MeV/cm
- *      - rho = density in g/cm^3
- */
-// ============================================================================
-inline double CaloSensDet::birkCorrection ( const G4Step* step ) const
-{
-  if ( !step ) { return 1 ; }                               // RETURN
 
-  // Track
-  const G4Track* track  = step->GetTrack() ;
-  const double charge   = track->GetDefinition()->GetPDGCharge()  ;
-
-  // Only for charged tracks
-  if ( fabs( charge ) < 0.1 ) { return 1 ; }                 // RETURN
-
-  // make an actual evaluation
-  return birkCorrection
-    ( track->GetDefinition         () ,
-      track->GetKineticEnergy      () ,
-      track->GetMaterialCutsCouple () ) ;
-}
-// ============================================================================
-
-
-
-
-// ============================================================================
-// The END
-// ============================================================================
-#endif  ///< GAUSSCALO_CaloSensDet_H
-// ============================================================================
+  public:
+  // Need to be set by the corresponding factory that has access to
+  // the Gaudi based functionality
+  const DeCalorimeter* m_calo{nullptr};
+  int m_caloID{0};
+};
diff --git a/Sim/GaussCalo/src/CaloSensDet.icpp b/Sim/GaussCalo/src/CaloSensDet.icpp
new file mode 100755
index 000000000..c69803ebf
--- /dev/null
+++ b/Sim/GaussCalo/src/CaloSensDet.icpp
@@ -0,0 +1,410 @@
+// $Id: CaloSensDet.cpp,v 1.24 2008-07-11 10:47:44 robbep Exp $
+// Include files
+
+// SRD & STD
+#include <algorithm>
+#include <sstream>
+#include <vector>
+
+// LHCbDefintions
+#include "CLHEP/Geometry/Point3D.h"
+
+// from Gaudi
+#include "GaudiKernel/IDataProviderSvc.h"
+#include "GaudiKernel/IHistogramSvc.h"
+#include "GaudiKernel/MsgStream.h"
+#include "GaudiKernel/Point3DTypes.h"
+#include "GaudiKernel/SmartDataPtr.h"
+#include "GaudiKernel/Stat.h"
+
+// GaussTools
+#include "GiGaMTCore/Truth/GaussinoTrackInformation.h"
+
+// Geant4
+#include "Geant4/G4LogicalVolume.hh"
+#include "Geant4/G4LogicalVolumeStore.hh"
+#include "Geant4/G4Material.hh"
+#include "Geant4/G4MaterialCutsCouple.hh"
+#include "Geant4/G4SDManager.hh"
+#include "Geant4/G4Step.hh"
+#include "Geant4/G4TouchableHistory.hh"
+#include "Geant4/G4VPhysicalVolume.hh"
+
+// local
+#include "CaloHit.h"
+#include "CaloSensDet.h"
+#include "CaloSimHash.h"
+
+// AIDA
+#include "AIDA/IHistogram1D.h"
+
+// Boost
+#include "boost/format.hpp"
+
+template <typename CELLGETTER>
+CaloSensDet<CELLGETTER>::CaloSensDet(const std::string& name)
+    : G4VSensitiveDetector(name) {
+  collectionName.insert("Hits");
+}
+// ============================================================================
+
+// ============================================================================
+/** the evaluation of t0 for given calorimetr cell
+ *  @param cellID the calorimeter cell identifier
+ *  @return "time"-parameter for the given cell
+ *           it is evaluated per cell basis in DeCalorimeter
+ */
+// ============================================================================
+template <typename CELLGETTER>
+double CaloSensDet<CELLGETTER>::t0(const LHCb::CaloCellID& cellID) const {
+  return this->cellTime(cellID) - dT0();
+}
+
+// ============================================================================
+/** evaluate the correction for Birk's law
+ *  @param charge   the charge of the particle
+ *  @param dEdX     the nominal dEdX in the material
+ *  @param density
+ *  @return the correction coefficient
+ */
+// ============================================================================
+template <typename CELLGETTER>
+double CaloSensDet<CELLGETTER>::birkCorrection(const double charge,
+                                               const double dEdX,
+                                               const double density) const {
+  const double C1 = fabs(charge) < 1.5 ? birk_c1() : birk_c1() * birk_c1cor();
+  const double C2 = birk_c2();
+
+  const double alpha = dEdX / density;
+
+  return 1.0 / (1.0 + C1 * alpha + C2 * alpha * alpha);
+}
+
+// ============================================================================
+/** method from G4
+ *  (Called at the begin of each event)
+ *  @see G4VSensitiveDetector
+ *  @param HCE pointer to hit collection of current event
+ */
+// ============================================================================
+template <typename CELLGETTER>
+void CaloSensDet<CELLGETTER>::Initialize(G4HCofThisEvent* HCE) {
+  //
+  if (!this->m_geoBaseInitialized) {
+    this->GeoBaseInitialize();
+  }
+  Assert(this->m_geoBaseInitialized, "Could not locate volumes!");
+  //
+  m_collection =
+      new CaloHitsCollection(SensitiveDetectorName, collectionName[0]);
+  //
+  const int id = GetCollectionID(0);
+
+  HCE->AddHitsCollection(id, m_collection);
+
+  m_hitmap.clear();
+}
+
+// ============================================================================
+/** evaluate the correction for Birk's law
+ *  @param charge   the charge of the particle
+ *  @param dEdX     the nominal dEdX in the material
+ *  @param material the pointer ot teh material
+ *  @return the correction coefficient
+ */
+// ============================================================================
+template <typename CELLGETTER>
+double CaloSensDet<CELLGETTER>::birkCorrection(
+    const double charge, const double dEdX, const G4Material* material) const {
+  if (0 == material) {
+    error("birkCorrection(): invalid material ");
+    return 1.;
+  }  // RETURN
+  return birkCorrection(charge, dEdX, material->GetDensity());
+}
+
+// ============================================================================
+/** Birk's correction for given particle with given kinetic energy
+ *  for the given material
+ *  @param  particle pointer to particle definition
+ *  @param  Ekine    particle kinetic energy
+ *  @param  maerial  pointer ot teh material
+ */
+// ============================================================================
+template <typename CELLGETTER>
+double CaloSensDet<CELLGETTER>::birkCorrection(
+    const G4ParticleDefinition* particle, const double eKine,
+    const G4MaterialCutsCouple* material) const {
+  if (0 == particle || 0 == material) {
+    error("birkCorrection(): invalid parameters ");
+    return 1.0;
+  }  // RETURN
+
+  const double charge = particle->GetPDGCharge();
+  if (fabs(charge) < 0.1) {
+    return 1.0;
+  }  // EEUTRN
+
+  // get the nominal dEdX
+  const double dEdX = G4EnergyLossTables::GetDEDX(particle, eKine, material);
+
+  // make an actual evaluation
+  return birkCorrection(charge, dEdX, material->GetMaterial()->GetDensity());
+}
+
+// ============================================================================
+// Birk's Law
+// ============================================================================
+/** Correction factor from Birk's Law
+ *  Factor = 1/(1+C1*dEdx/rho+C2*(dEdx/rho)^2)
+ *  Where :
+ *      - C1 = 0.013 g/MeV/cm^2 [Ref NIM 80 (1970) 239]
+ *      - C2 = 9.6.10^-6 g^2/MeV^2/cm^4
+ *      - dEdx in MeV/cm
+ *      - rho = density in g/cm^3
+ */
+// ============================================================================
+template <typename CELLGETTER>
+double CaloSensDet<CELLGETTER>::birkCorrection(const G4Step* step) const {
+  if (!step) {
+    return 1;
+  }  // RETURN
+
+  // Track
+  const G4Track* track = step->GetTrack();
+  const double charge = track->GetDefinition()->GetPDGCharge();
+
+  // Only for charged tracks
+  if (fabs(charge) < 0.1) {
+    return 1;
+  }  // RETURN
+
+  // make an actual evaluation
+  return birkCorrection(track->GetDefinition(), track->GetKineticEnergy(),
+                        track->GetMaterialCutsCouple());
+}
+
+template <typename CELLGETTER>
+LHCb::CaloCellID CaloSensDet<CELLGETTER>::cell(const G4StepPoint* point) const {
+  G4TouchableHistory* tHist = (G4TouchableHistory*)point->GetTouchable();
+
+  const int nLevel = tHist->GetHistoryDepth();
+  CaloSim::Path path;
+  path.reserve(nLevel);
+
+  for (int level = 0; level < nLevel; ++level) {
+    const G4VPhysicalVolume* pv = tHist->GetVolume(level);
+    if (0 == pv) {
+      continue;
+    }  // CONTINUE
+    const G4LogicalVolume* lv = pv->GetLogicalVolume();
+    if (0 == lv) {
+      continue;
+    }  // CONTINUE
+    // start volume ??
+    if (m_end == lv) {
+      break;
+    }  // BREAK
+    // useful volume ?
+    if (!path.empty()) {
+      path.push_back(pv);
+    } else if (m_start.end() != std::find(m_start.begin(), m_start.end(), lv)) {
+      path.push_back(pv);
+    }
+  }
+
+  if (path.empty()) {
+    error("Volume path is invalid(empty) ");
+    return LHCb::CaloCellID();
+  }
+
+  // find the appropriate ID
+  Table::iterator ifound = m_table.find(path);
+  // already in the table ?
+  if (m_table.end() != ifound) {
+    return ifound->second;
+  }  // RETURN
+
+  // if not: add it into the table!
+  // CLHEP -> ROOT
+  HepGeom::Transform3D mtrx(*(tHist->GetRotation()), tHist->GetTranslation());
+  auto heppoint = mtrx * HepGeom::Point3D<double>{};
+  const Gaudi::XYZPoint p(heppoint.x(), heppoint.y(), heppoint.z());
+
+  // get the right cell id
+  auto id = this->cellID(p);
+  m_table.insert(Table::value_type(path, id));
+
+  return id;
+}
+
+// ============================================================================
+/** method from G4
+ *  (Called at the end of each event)
+ *  @see G4VSensitiveDetector
+ *  @param HCE pointer to hit collection of current event
+ */
+// ============================================================================
+template <typename CELLGETTER>
+void CaloSensDet<CELLGETTER>::EndOfEvent(G4HCofThisEvent* /* HCE */) {
+  /// clear the map
+  m_hitmap.clear();
+
+  if (0 == m_collection) {
+    warning(" EndOfEvent(): HitCollection points to NULL ");
+    return;
+  }
+  typedef std::vector<CaloHit*> Hits;
+  const Hits* hits = m_collection->GetVector();
+  if (0 == hits) {
+    error(" EndOfEvent(): HitVector* points to NULL ");
+    return;
+  }
+
+  // initialize counters
+  const size_t nhits = hits->size();
+  size_t nshits = 0;
+  size_t nslots = 0;
+  double energy = 0;
+
+  // the loop over all hits
+  for (Hits::const_iterator ihit = hits->begin(); hits->end() != ihit; ++ihit) {
+    const CaloHit* hit = *ihit;
+    if (0 == hit) {
+      continue;
+    }  // CONTINUE
+    nshits += hit->size();
+    nslots += hit->totalSize();
+    energy += hit->energy();
+  }
+
+  energy /= CLHEP::GeV;  // NB: rescale to GeV
+
+  if (m_nhits) (*m_nhits) += nhits;
+  if (m_nshits) (*m_nshits) += nshits;
+  if (m_nslots) (*m_nslots) += nslots;
+  if (m_energy) (*m_energy) += energy;
+
+  if (printDebug()) {
+    always(
+        boost::format(" #Hits=%5d #SubHits=%5d #Slots=%5d Energy=%8.3g[GeV] ") %
+        nhits % nshits % nslots % energy);
+  }
+}
+
+// ============================================================================
+/** process the hit
+ *  @param step     pointer to current Geant4 step
+ *  @param history  pointert to touchable history
+ */
+// ============================================================================
+template <typename CELLGETTER>
+bool CaloSensDet<CELLGETTER>::ProcessHits(G4Step* step,
+                                          G4TouchableHistory* /* history */) {
+  if (0 == step) {
+    return false;
+  }
+  ///
+  const double deposit = step->GetTotalEnergyDeposit();
+  if (deposit <= 0) {
+    return false;
+  }  // RETURN
+
+  const G4Track* const track = step->GetTrack();
+  const int trackID = track->GetTrackID();
+  const G4ParticleDefinition* const particle = track->GetDefinition();
+  const double charge = particle->GetPDGCharge();
+
+  if (0 == int(charge * 10)) {
+    return false;
+  }  // RETURN
+
+  const G4StepPoint* const preStep = step->GetPreStepPoint();
+  const HepGeom::Point3D<double>& prePoint = preStep->GetPosition();
+  const double time = preStep->GetGlobalTime();
+  const G4MaterialCutsCouple* const material = preStep->GetMaterialCutsCouple();
+
+  const LHCb::CaloCellID cellID = cell(preStep);
+  if (LHCb::CaloCellID() == cellID) {
+    return false;
+  }
+
+  // get the existing hit
+  CaloHit*& hit = m_hitmap[cellID];
+  if (0 == hit) {
+    // create new hit
+    hit = new CaloHit(cellID);
+    // add it into collection
+    m_collection->insert(hit);
+  }
+
+  // check the status of the track
+  auto info = GaussinoTrackInformation::Get();
+  if (0 == info) {
+    error("Invalid Track information");
+    return false;
+  }  // RETURN
+
+  // ID of the track to be stored
+  int sTrackID = track->GetParentID();
+
+  // already marked to be stored:
+  if (info->storeTruth()) {
+    sTrackID = trackID;
+  } else {
+    // z-position of production vertex
+    const double z0 = track->GetVertexPosition().z();
+    // outside the "forbidden zone" ?
+    if (z0 < zMin() || z0 > zMax()) {
+      sTrackID = trackID;
+    }
+  }
+
+  // Does the hit exist for the given track?
+  CaloSubHit*& sub = hit->hit(sTrackID);  // ATTENTION
+  // create new subhit if needed
+  if (0 == sub) {
+    sub = new CaloSubHit(cellID, sTrackID);
+  }
+  // update the track information
+  if (trackID == sTrackID) {
+    info->addToHits(sub);
+  }
+
+  // perform the specific sub-detector action
+  bool sc = fillHitInfo(sub, prePoint, time, deposit, track, particle,
+                              material, step);
+
+  if (!sc) {
+    error("The SubHit information is not filled!", sc);
+  }
+
+  return true;
+}
+
+// ============================================================================
+/** helpful method to locate start and end volumes
+ *  @return status code
+ */
+// ============================================================================
+template <typename CELLGETTER>
+void CaloSensDet<CELLGETTER>::GeoBaseInitialize() {
+  // locate start volumes
+  for (auto& vol : m_startVolumeNames) {
+    // look through converted volumes
+    const G4LogicalVolume* lv = G4LogicalVolumeStore::GetVolume(vol);
+    if (0 == lv) {
+      throw std::runtime_error("G4LogicalVolume* points to 0 for " + (vol));
+    }
+    m_start.push_back(lv);
+  }
+  if (m_start.empty()) {
+    throw std::runtime_error("Size of 'StartVolumes' is 0 ");
+  }
+  // locate end volume : look through converted volumes
+  m_end = G4LogicalVolumeStore::GetVolume(m_endVolumeName);
+  if (0 == m_end) {
+    throw std::runtime_error("G4LogicalVolume* points to 0 for '" + m_endVolumeName + "'");
+  }
+  m_geoBaseInitialized = true;
+}
diff --git a/Sim/GaussCalo/src/CaloSensDetFAC.cpp b/Sim/GaussCalo/src/CaloSensDetFAC.cpp
new file mode 100755
index 000000000..e69de29bb
diff --git a/Sim/GaussCalo/src/CaloSensDetFAC.h b/Sim/GaussCalo/src/CaloSensDetFAC.h
new file mode 100755
index 000000000..fea742979
--- /dev/null
+++ b/Sim/GaussCalo/src/CaloSensDetFAC.h
@@ -0,0 +1,122 @@
+#pragma once
+
+#include "GiGaMTFactories/GiGaMTG4SensDetFactory.h"
+
+// Geant4 physics lists
+#include "CaloSensDet.h"
+
+// Templated base class for all CALO sensitive detector factories
+// to pass common properties to the object. First the very common
+// base class that encapsulates the properties needed independent
+// of the templated geometry access interface.
+
+template <typename CALO>
+class CaloSensDetBaseFAC : public GiGaMTG4SensDetFactory<CALO> {
+  Gaudi::Property<std::string> m_endVolumeName{this, "StartVolumes", {}};
+  Gaudi::Property<std::vector<std::string>> m_startVolumeNames{this,
+                                                               "EndVolume", ""};
+
+  // the first coefficient of Birk's law                    (c1)
+  Gaudi::Property<double> m_birk_c1{this, "BirkC1",
+                                    0.013 * CLHEP::g / CLHEP::MeV / CLHEP::cm2};
+  // the second coefficient of Birk's law                   (c2)
+  Gaudi::Property<double> m_birk_c2{this, "BirkC2",
+                                    9.6E-6 * CLHEP::g* CLHEP::g / CLHEP::MeV /
+                                        CLHEP::MeV / CLHEP::cm2 / CLHEP::cm2};
+  // the correction to the first coefficient of Birk's law  (c1')
+  Gaudi::Property<double> m_birk_c1correction{this, "BirkC1cor", 0.57142857};
+
+  Gaudi::Property<double> m_zmin{this, "zMin", -1 * CLHEP::km};
+  Gaudi::Property<double> m_zmax{this, "zMax", 1 * CLHEP::km};
+
+  // the additive correction for the evaluation of t0
+  Gaudi::Property<double> m_dT0{this, "dT0", 0.5 * CLHEP::ns};
+
+  /// the vector of histogram names/addresses
+  Gaudi::Property<std::vector<std::string>> m_histoNames{
+      this, "Histograms", {}};
+  ServiceHandle<IHistogramSvc> m_histoSvc{this, "HistogramDataSvc",
+                                          "HistogramDataSvc"};
+
+  Gaudi::Accumulators::SummingCounter<size_t> m_nhits{this, "#hits"};
+  Gaudi::Accumulators::SummingCounter<size_t> m_nshits{this, "#subhits"};
+  Gaudi::Accumulators::SummingCounter<size_t> m_nslots{this, "#tslots"};
+  Gaudi::Accumulators::SummingCounter<double> m_energy{this, "#energy"};
+
+  public:
+  using base_class = GiGaMTG4SensDetFactory<CALO>;
+  using base_class::GiGaMTG4SensDetFactory;
+  CALO* construct() const override {
+    auto tmp = base_class::construct();
+    tmp->m_endVolumeName = m_endVolumeName;
+    tmp->m_startVolumeNames = m_startVolumeNames;
+    tmp->m_birk_c1 = m_birk_c1;
+    tmp->m_birk_c2 = m_birk_c2;
+    tmp->m_birk_c1correction = m_birk_c1correction;
+    tmp->m_zmin = m_zmin;
+    tmp->m_zmax = m_zmax;
+    tmp->m_dT0 = m_dT0;
+    tmp->m_histos = m_histos;
+    return tmp;
+  }
+  StatusCode initialize() override {
+    auto sc = base_class::initialize();
+
+    {  // load all input histos
+      for (auto& histo : m_histoNames) {
+        SmartDataPtr<IHistogram1D> pHist(m_histoSvc, histo);
+        IHistogram1D* hist = pHist;
+        if (0 == hist) {
+          return Error("Cannot load histogram '" + (histo) + "'");
+        }
+        m_histos.push_back(hist);
+      }
+      if (m_histos.empty()) {
+        this->warning() << "Empty vector of input time-histograms" << endmsg;
+      }
+    }
+    return sc;
+  }
+
+  private:
+  std::vector<AIDA::IHistogram1D*> m_histos;
+};
+
+// Actual version that can be specialised depending on the used base
+// class of CALO that handles the geometry access (for CellID retrieval)
+
+template <typename CALO, typename dummy = void>
+class CaloSensDetFAC : public CaloSensDetBaseFAC<CALO> {
+  public:
+  using base_class = CaloSensDetBaseFAC<CALO>;
+  using base_class::CaloSensDetBaseFAC;
+  CALO* construct() const override { return base_class::construct(); }
+};
+
+template <typename T>
+using usesLHCbGeo =
+    typename std::enable_if<std::is_base_of<CellFromLHCbGeo, T>::value>::type;
+
+template <typename CALO>
+class CaloSensDetFAC<CALO, usesLHCbGeo<CALO>>
+    : public CaloSensDetBaseFAC<CALO> {
+  Gaudi::Property<std::string> m_caloName{"Detector", m_caloName,
+                                          DeCalorimeterLocation::Ecal};
+
+  public:
+  using base_class = CaloSensDetBaseFAC<CALO>;
+  using base_class::base_class;
+  CALO* construct() const override {
+    auto tmp = base_class::construct();
+    tmp->m_calo = this->template getDet<DeCalorimeter>(m_caloName);
+    if (0 == tmp->m_calo) {
+      throw std::runtime_error("Could not locate CALO " + m_caloName);
+    }
+    tmp->m_caloID = CaloCellCode::CaloNumFromName(m_caloName);
+
+    if (0 > tmp->m_caloID) {
+      throw std::runtime_error("Invalid detector name/number!");
+    }
+    return tmp;
+  }
+};
diff --git a/Sim/GaussCalo/src/CaloSubHit.cpp b/Sim/GaussCalo/src/CaloSubHit.cpp
deleted file mode 100755
index 9e6457420..000000000
--- a/Sim/GaussCalo/src/CaloSubHit.cpp
+++ /dev/null
@@ -1,135 +0,0 @@
-// $Id: CaloSubHit.cpp,v 1.4 2006-01-17 15:52:57 odescham Exp $
-// ============================================================================
-// CVS tag $Name: not supported by cvs2svn $
-// ============================================================================
-// $Log: not supported by cvs2svn $
-// Revision 1.3  2004/01/14 13:38:10  ranjard
-// v6r0 - fix to be used with Gaudi v14r0
-//
-// Revision 1.2  2002/12/13 16:52:57  ibelyaev
-//  put updated versions of the packages
-//
-// Revision 1.1  2002/12/07 14:41:44  ibelyaev
-//  add new Calo stuff
-//
-// ============================================================================
-// Include files
-// GiGa
-#include "GiGa/GiGaUtil.h"
-// Geant4 
-#include "Geant4/G4Allocator.hh"
-#include "Geant4/G4VHit.hh"
-// G4 
-// local
-#include "CaloSubHit.h"
-
-// ============================================================================
-/** @file 
- *  Implementation file for all non-inlined methods of class CaloSubHit
- *
- *  @author Vanya Belyaev Ivan.Belyaev@itep.ru
- *  @date   2002-12-03
- */
-// ============================================================================
-
-namespace CaloSubHitLocal
-{
-  // ==========================================================================
-  /** @var  s_Allocator
-   *  allocator to make more efficient creation delete of CaloSubHits objects  
-   */
-  // ==========================================================================
-  G4Allocator<CaloSubHit>            s_Allocator ;
-  // ==========================================================================
-  
-  // ==========================================================================
-  /** @var s_Counter 
-   *  statsic instace counter for all functions 
-   */
-  // ==========================================================================
-#ifdef GIGA_DEBUG
-  static GiGaUtil::InstanceCounter<CaloSubHit> s_Counter   ;
-#endif 
-  // ==========================================================================
-}
-
-
-
-// ============================================================================
-/** Standard constructor
- *  @param cellID  cellID  of the detector cell  
- *  @param trackID trackID of the particle
- */
-// ============================================================================
-CaloSubHit::CaloSubHit( const LHCb::CaloCellID& cellID  , 
-                        const int         trackID )
-  : GaussHitBase (        )  
-  , m_cellID     ( cellID ) 
-  , m_map        (        ) 
-{ 
-  setTrackID( trackID ) ;
-#ifdef GIGA_DEBUG
-  CaloSubHitLocal::s_Counter.increment () ;
-#endif 
-}
-
-
-// ============================================================================
-/** copy constructor 
- *  @param right object to be copied 
- */
-// ============================================================================
-CaloSubHit::CaloSubHit( const CaloSubHit& right ) 
-  : GaussHitBase( right    ) 
-  , m_cellID ( right.cellID() ) 
-  , m_map    ( right.m_map    ) 
-{
-#ifdef GIGA_DEBUG
-  CaloSubHitLocal::s_Counter.increment () ;
-#endif 
-}
-
-
-/// destructor 
-// ============================================================================
-CaloSubHit::~CaloSubHit() 
-{ 
-  m_map.clear() ; 
-#ifdef GIGA_DEBUG
-  CaloSubHitLocal::s_Counter.decrement () ;
-#endif 
-}
-
-
-// ============================================================================
-/// Clone method 
-// ============================================================================
-CaloSubHit* CaloSubHit::clone() const 
-{ 
-  return new CaloSubHit( *this ); 
-}
-
-
-// ============================================================================
-/// overloaded 'new' operator 
-// ============================================================================
-void* CaloSubHit::operator new(size_t)
-{
-  void *hit  ;
-  hit = (void *) CaloSubHitLocal::s_Allocator.MallocSingle () ;
-  return hit ;
-}
-
-
-// ============================================================================
-/// overloaded 'delete' operator 
-// ============================================================================
-void CaloSubHit::operator delete( void *hit )
-{ 
-  CaloSubHitLocal::s_Allocator.FreeSingle( (CaloSubHit*) hit ); 
-}
-
-
-// ============================================================================
-// The END 
-// ============================================================================
diff --git a/Sim/GaussCalo/src/CaloSubHit.h b/Sim/GaussCalo/src/CaloSubHit.h
index 1da2c19bb..5c1b6423d 100755
--- a/Sim/GaussCalo/src/CaloSubHit.h
+++ b/Sim/GaussCalo/src/CaloSubHit.h
@@ -1,258 +1,204 @@
-// $Id: CaloSubHit.h,v 1.7 2006-01-17 15:52:57 odescham Exp $
-// ============================================================================
-// CVS tag $Name: not supported by cvs2svn $
-// ============================================================================
-// $Log: not supported by cvs2svn $
-// Revision 1.6  2004/01/14 13:38:10  ranjard
-// v6r0 - fix to be used with Gaudi v14r0
-//
-// Revision 1.5  2003/12/09 08:28:39  ibelyaev
-//  fix for missing != operator for CaloCellID class
-//
-// Revision 1.4  2003/07/22 19:05:33  ibelyaev
-//  improve doxygen documentation
-//
-// Revision 1.3  2003/07/08 19:40:57  ibelyaev
-//  Sensitive Plane Detector + improved printout
-//
-// Revision 1.2  2002/12/13 16:52:57  ibelyaev
-//  put updated versions of the packages
-//
-// Revision 1.2  2002/12/07 21:19:14  ibelyaev
-//  few optimization updates
-//
-// Revision 1.1  2002/12/07 14:41:44  ibelyaev
-//  add new Calo stuff
-//
-// ============================================================================
-#ifndef CALOSIM_CALOSUBHIT_H 
-#define CALOSIM_CALOSUBHIT_H 1
 // Kernel
 #include "Kernel/CaloCellID.h"
-// GiGa 
+// GiGa
 #include <unordered_map>
-#include "GiGa/GiGaUtil.h"
 // Include files
-#include "GaussTools/GaussHitBase.h"
-// Local 
+#include "GaudiKernel/StatusCode.h"
+#include "GiGaMTCore/GaussHitBase.h"
+// Local
 #include "CaloSimHash.h"
+#include "Geant4/G4Allocator.hh"
 
 /** @class CaloSubHit CaloSubHit.h
- * 
+ *
  *  Elementary "sub-hit" for calorimeter devices.
- *  The class represents an list of energy depositions 
+ *  The class represents an list of energy depositions
  *  from given particle in the given calorimeter cell.
  *
- *  These objects are not expected to be stored directly 
- *  in Geant4 hits collections. 
- *  These objects are used to be collected in objects of type 
- *  <tt>CaloHit</tt> 
+ *  These objects are not expected to be stored directly
+ *  in Geant4 hits collections.
+ *  These objects are used to be collected in objects of type
+ *  <tt>CaloHit</tt>
  *
  *  @see CaloHit
  *  @see CaloSubHit
  *  @author Vanya Belyaev Ivan.Belyaev@itep.ru
  *  @date   2002-12-03
  */
-class CaloSubHit : public GaussHitBase 
-{
-public:
-  
-  /// type for the hits "Energy" deposition 
-  typedef double Energy                     ;  
-  /// type for "time" index  
-  typedef char   Time                       ;
-  // actual type of 
-  typedef std::unordered_map<Time,Energy> TheMap   ;
-  // iterator type 
-  typedef TheMap::const_iterator   iterator ;
+class CaloSubHit : public Gaussino::HitBase {
+  public:
+  /// type for the hits "Energy" deposition
+  typedef double Energy;
+  /// type for "time" index
+  typedef char Time;
+  // actual type of
+  // FIXME: Use thread-local allocator
+  typedef std::unordered_map<Time, Energy> TheMap;
+  // iterator type
+  typedef TheMap::const_iterator iterator;
 
-public:
-  
+  public:
   /** Standard constructor
-   *  @param cellID  cellID  of the detector cell  
+   *  @param cellID  cellID  of the detector cell
    *  @param trackID trackID of the particle
    */
-  CaloSubHit ( const LHCb::CaloCellID& cellID  = LHCb::CaloCellID() , 
-               const int         trackID = 0            ) ;
-  
-  /** copy constructor 
-   *  @param right object to be copied 
+  CaloSubHit(const LHCb::CaloCellID& cellID = LHCb::CaloCellID(),
+             const int trackID = 0)
+      : Gaussino::HitBase{}, m_cellID{cellID}, m_map{} {
+    m_trackID = trackID;
+  }
+
+  /** copy constructor
+   *  @param right object to be copied
    */
-  CaloSubHit ( const CaloSubHit& right                  ) ;
-  
-  /// clone method (virtual constructor) 
-  virtual CaloSubHit* clone() const ;
-  
-  /// destructor 
-  virtual ~CaloSubHit() ;
-  
-  void* operator new    ( size_t    ) ;
-  void  operator delete ( void *hit ) ;
-  
-  /// access to cell ID for given hit  
-  const LHCb::CaloCellID& cellID() const          { return m_cellID        ; }  
-  // set new cell ID for given hit 
-  void setCellID ( const LHCb::CaloCellID& cell ) {        m_cellID = cell ; }
-  
+  CaloSubHit(const CaloSubHit& right)
+      : Gaussino::HitBase(right),
+        m_cellID(right.cellID()),
+        m_map(right.m_map) {}
+
+  // virtual ~CaloSubHit() = default;
+
+  ///// clone method (virtual constructor)
+  // virtual CaloSubHit* clone() const ;
+
+  void* operator new(size_t);
+  void operator delete(void* hit);
+
+  /// access to cell ID for given hit
+  const LHCb::CaloCellID& cellID() const { return m_cellID; }
+  // set new cell ID for given hit
+  void setCellID(const LHCb::CaloCellID& cell) { m_cellID = cell; }
+
   /** add energy deposition for given hit (safe method)
    *  Error flags:
-   *   - inconsistent track ID :  300 
+   *   - inconsistent track ID :  300
    *   - inconsistent cell  ID :  301
-   * 
-   *  @code 
+   *
+   *  @code
    *
    *  CaloSubHit*        hit   = ... ;
    *  CaloSubHit::Time   time  = ... ;
    *  CaloSubHit::Energy e     = ... ;
    *  const int          track = ... ;
    *  const LHCb::CaloCellID&  cell  = ... ;
-   * 
+   *
    *  StatusCode sc  = hit->add( track , cell , time , energy ) ;
-   *  if( sc.isFailure() ) { .... } 
+   *  if( sc.isFailure() ) { .... }
+   *
+   *  @endcode
    *
-   *  @endcode 
-   * 
    *  @param track  trackID for energy deposition
    *  @param cell   cellID  for the detector cell
-   *  @param time   the time of the energy deposition 
-   *  @param energy deposition itself 
-   *  @return status code 
+   *  @param time   the time of the energy deposition
+   *  @param energy deposition itself
+   *  @return status code
    */
-  StatusCode add ( const int         track , 
-                   const LHCb::CaloCellID& cell    , 
-                   const Time        time    , 
-                   const Energy      energy  )
-  {
-    if (    trackID () != track   ) { return StatusCode( 300 ) ; }
-    if ( !( cellID  () == cell  ) ) { return StatusCode( 301 ) ; }    
-    return add( time , energy );
+  StatusCode add(const int track, const LHCb::CaloCellID& cell, const Time time,
+                 const Energy energy) {
+    if (trackID() != track) {
+      return StatusCode(300);
+    }
+    if (!(cellID() == cell)) {
+      return StatusCode(301);
+    }
+    return add(time, energy);
   };
-  
+
   /** add energy deposition for given hit (fast method)
-   * 
-   *  @code 
+   *
+   *  @code
    *
    *  CaloSubHit*        hit  = ... ;
    *  CaloSubHit::Time   time = ... ;
    *  CaloSubHit::Energy e    = ... ;
-   * 
+   *
    *  hit->add( time , energy ) ;
    *
-   *  @endcode 
-   * 
+   *  @endcode
+   *
    *  @param track  trackID for energy deposition
    *  @param cell   cellID  for the detector cell
-   *  @param time   the time of the energy deposition 
-   *  @param energy deposition itself 
-   *  @return status code 
+   *  @param time   the time of the energy deposition
+   *  @param energy deposition itself
+   *  @return status code
    */
-  StatusCode add ( const Time   time   , 
-                   const Energy energy )
-  {
-    m_map[ time ] += energy ;
-    return StatusCode::SUCCESS ;
+  StatusCode add(const Time time, const Energy energy) {
+    m_map[time] += energy;
+    return StatusCode::SUCCESS;
   };
-  
+
   /** access for map iterator "begin" (const)
-   *  
-   *  @code 
-   *  
+   *
+   *  @code
+   *
    *  CaloSubHit* hit = ... ;
    *
-   *  for( CaloSubHit::iterator entry = hit->begin() ; 
-   *       hit->end() != entry ; ++entry ) 
+   *  for( CaloSubHit::iterator entry = hit->begin() ;
+   *       hit->end() != entry ; ++entry )
    *    {
    *       CaloSubHit::Energy e = entry->first   ;
-   *       CaloSubHit::Time   t = entry->second  ; 
+   *       CaloSubHit::Time   t = entry->second  ;
    *    }
-   *  
-   *   @endcode 
-   *   @return 'begin' iterator to the sequence of entries 
+   *
+   *   @endcode
+   *   @return 'begin' iterator to the sequence of entries
    */
-  iterator begin   () const { return m_map.begin () ; }
+  iterator begin() const { return m_map.begin(); }
   /** access for map iterator "end"   (const)
-   *  
-   *  @code 
-   *  
+   *
+   *  @code
+   *
    *  CaloSubHit* hit = ... ;
    *
-   *  for( CaloSubHit::iterator entry = hit->begin() ; 
-   *       hit->end() != entry ; ++entry ) 
+   *  for( CaloSubHit::iterator entry = hit->begin() ;
+   *       hit->end() != entry ; ++entry )
    *    {
    *       CaloSubHit::Energy e = entry->first   ;
-   *       CaloSubHit::Time   t = entry->second  ; 
+   *       CaloSubHit::Time   t = entry->second  ;
    *    }
-   *  
-   *   @endcode 
-   *   @return 'end' iterator to teh sequence of entries 
+   *
+   *   @endcode
+   *   @return 'end' iterator to teh sequence of entries
    */
-  iterator end     () const { return m_map.end   () ; }
-  
-  /// number of entries/map size 
-  size_t   size    () const { return m_map.size  () ; }
-  size_t   entries () const { return       size  () ; }
-  
+  iterator end() const { return m_map.end(); }
+
+  /// number of entries/map size
+  size_t size() const { return m_map.size(); }
+  size_t entries() const { return size(); }
+
   /** overall subhit evergy  (integrated over the time )
-   * 
-   *  @code 
-   *  
+   *
+   *  @code
+   *
    *  CaloSubHit* hit = ... ;
    *  CaloSubHit::Energy e = hit->energy() ;
-   * 
-   *  @endcode 
-   *  @return total subhit energy (total energy deposition from given particle 
+   *
+   *  @endcode
+   *  @return total subhit energy (total energy deposition from given particle
    *          in the given calorimeter cell)
    */
-  Energy   energy  () const 
-  {
-    Energy e = 0 ;
-    for( iterator entry = begin() ; end() != entry ; ++entry ) 
-      { e += entry->second ; } 
-    return e ;
+  Energy energy() const {
+    Energy e = 0;
+    for (iterator entry = begin(); end() != entry; ++entry) {
+      e += entry->second;
+    }
+    return e;
   };
-  
-private:
-  
-  LHCb::CaloCellID  m_cellID ;
-  TheMap      m_map    ;
-  
+
+  private:
+  LHCb::CaloCellID m_cellID;
+  TheMap m_map;
 };
-// ============================================================================
 
-// ============================================================================
-/** @fn  caloSubHit
- *  Fast cast of G4VHit interface to concrete Gauss implementation
- *  @param  g4   pointer to G4VHit interface 
- *  @return cast (dynamic or static) to CaloSubHit
- *  @author  Vanya Belyaev Ivan.Belyaev@itep.ru
- *  @date    2002-12-07
- */
-// ============================================================================
-inline CaloSubHit* caloSubHit( G4VHit* g4 )
-{
-  GiGaUtil::FastCast<G4VHit,CaloSubHit> cast ;
-  return cast( g4 );  
-}
-// ============================================================================
+extern G4ThreadLocal G4Allocator<CaloSubHit>* aCaloSubHitAllocator;
 
-// ============================================================================
-/** @fn  caloSubHit
- *  Fast cast of GaussHitBase interface to concrete Gauss implementation
- *  @param  g4   pointer to GaussHitBase interface 
- *  @return cast (dynamic or static) to CaloSubHit
- *  @author  Vanya Belyaev Ivan.Belyaev@itep.ru
- *  @date    2002-12-07
- */
-// ============================================================================
-inline CaloSubHit* caloSubHit( GaussHitBase* g4 )
-{
-  GiGaUtil::FastCast<GaussHitBase,CaloSubHit> cast ;
-  return cast( g4 );  
+inline void* CaloSubHit::operator new(size_t) {
+  if (!aCaloSubHitAllocator) {
+    aCaloSubHitAllocator = new G4Allocator<CaloSubHit>;
+  }
+  return (void*)aCaloSubHitAllocator->MallocSingle();
 }
-// ============================================================================
 
-// ============================================================================
-// The END 
-// ============================================================================
-#endif // CALOSIM_CALOSUBHIT_H
-// ============================================================================
+inline void CaloSubHit::operator delete(void* aHit) {
+  aCaloSubHitAllocator->FreeSingle((CaloSubHit*)aHit);
+}
-- 
GitLab


From 59c96ec5c72d73a7a22e6adbab906953112f7373 Mon Sep 17 00:00:00 2001
From: Dominik Muller <dominik.muller@cern.ch>
Date: Tue, 9 Jul 2019 17:56:21 +0200
Subject: [PATCH 13/90] Save particle causing tracker hit

---
 Sim/GaussTracker/src/GiGaSensDetTracker.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Sim/GaussTracker/src/GiGaSensDetTracker.cpp b/Sim/GaussTracker/src/GiGaSensDetTracker.cpp
index 039709153..4aec95363 100755
--- a/Sim/GaussTracker/src/GiGaSensDetTracker.cpp
+++ b/Sim/GaussTracker/src/GiGaSensDetTracker.cpp
@@ -86,7 +86,7 @@ bool GiGaSensDetTracker::ProcessHits(G4Step* step,
 
         auto gi = GaussinoTrackInformation::Get(track);
         gi->setCreatedHit(true);
-        gi->storeTruth();
+        gi->setToStoreTruth(true);
         gi->addHit(newHit);
 
         // add hit to collection
-- 
GitLab


From e1b203929eb81660f03f857c390217f6e44ab9f7 Mon Sep 17 00:00:00 2001
From: Dominik Muller <dominik.muller@cern.ch>
Date: Tue, 9 Jul 2019 17:57:22 +0200
Subject: [PATCH 14/90] Migrated further settings to individual subdetectors

---
 Sim/Gauss/python/Gauss/Geometry/BCM.py        |  2 ++
 Sim/Gauss/python/Gauss/Geometry/BLS.py        |  2 ++
 Sim/Gauss/python/Gauss/Geometry/CALO.py       |  8 ++++++
 .../python/Gauss/Geometry/Configuration.py    |  5 ++++
 Sim/Gauss/python/Gauss/Geometry/FT.py         | 22 ++++++++++++++++
 Sim/Gauss/python/Gauss/Geometry/HC.py         |  2 ++
 Sim/Gauss/python/Gauss/Geometry/Helpers.py    |  1 +
 Sim/Gauss/python/Gauss/Geometry/IT.py         | 25 +++++++++++++++++-
 Sim/Gauss/python/Gauss/Geometry/Magnet.py     |  2 ++
 Sim/Gauss/python/Gauss/Geometry/Muon.py       |  5 +++-
 Sim/Gauss/python/Gauss/Geometry/OT.py         | 26 ++++++++++++++++++-
 Sim/Gauss/python/Gauss/Geometry/PuVeto.py     |  5 +++-
 Sim/Gauss/python/Gauss/Geometry/RICH.py       |  8 ++++++
 Sim/Gauss/python/Gauss/Geometry/SL.py         | 20 ++++++++++++++
 Sim/Gauss/python/Gauss/Geometry/TT.py         | 24 ++++++++++++++++-
 Sim/Gauss/python/Gauss/Geometry/UT.py         | 19 ++++++++++++++
 Sim/Gauss/python/Gauss/Geometry/VP.py         |  2 ++
 Sim/Gauss/python/Gauss/Geometry/Velo.py       |  3 ++-
 Sim/Gauss/python/Gauss/Geometry/det_base.py   | 11 +++++++-
 19 files changed, 185 insertions(+), 7 deletions(-)

diff --git a/Sim/Gauss/python/Gauss/Geometry/BCM.py b/Sim/Gauss/python/Gauss/Geometry/BCM.py
index c6d0c948f..2e63d1594 100644
--- a/Sim/Gauss/python/Gauss/Geometry/BCM.py
+++ b/Sim/Gauss/python/Gauss/Geometry/BCM.py
@@ -5,6 +5,8 @@ from Gauss.Geometry.Helpers import subdetector
 @subdetector
 class BCM(det_base):
 
+    __slots__ = {}
+
     def ApplyDetector(self, basePieces, detPieces):
         from Gauss.Geometry import LHCbGeo
         # Add the non-standard pieces of the BeforeMagnet region.
diff --git a/Sim/Gauss/python/Gauss/Geometry/BLS.py b/Sim/Gauss/python/Gauss/Geometry/BLS.py
index c3a2eba6e..e5c66dd10 100644
--- a/Sim/Gauss/python/Gauss/Geometry/BLS.py
+++ b/Sim/Gauss/python/Gauss/Geometry/BLS.py
@@ -6,6 +6,8 @@ from Gauss.Geometry.Helpers import subdetector
 @subdetector
 class BCM(det_base):
 
+    __slots__ = {}
+
     def ApplyDetector(self, basePieces, detPieces):
         from Gauss.Geometry import LHCbGeo
         # Add the non-standard pieces of the BeforeMagnet region.
diff --git a/Sim/Gauss/python/Gauss/Geometry/CALO.py b/Sim/Gauss/python/Gauss/Geometry/CALO.py
index bb650c615..465bb1e64 100644
--- a/Sim/Gauss/python/Gauss/Geometry/CALO.py
+++ b/Sim/Gauss/python/Gauss/Geometry/CALO.py
@@ -6,6 +6,8 @@ from Gauss.Geometry.BeamPipe import BeamPipe
 @subdetector
 class SPD(det_base):
 
+    __slots__ = {}
+
     def ApplyDetector(self, basePieces, detPieces):
         BeamPipe.removeBeamPipeElements("calo")
         region = 'DownstreamRegion'
@@ -16,6 +18,8 @@ class SPD(det_base):
 @subdetector
 class PRS(det_base):
 
+    __slots__ = {}
+
     def ApplyDetector(self, basePieces, detPieces):
         region = 'DownstreamRegion'
         detPieces[region] += ['Prs']
@@ -24,6 +28,8 @@ class PRS(det_base):
 @subdetector
 class ECAL(det_base):
 
+    __slots__ = {}
+
     def ApplyDetector(self, basePieces, detPieces):
         region = 'DownstreamRegion'
         detPieces[region] += ['Ecal']
@@ -32,6 +38,8 @@ class ECAL(det_base):
 @subdetector
 class HCAL(det_base):
 
+    __slots__ = {}
+
     def ApplyDetector(self, basePieces, detPieces):
         region = 'DownstreamRegion'
         detPieces[region] += ['Hcal']
diff --git a/Sim/Gauss/python/Gauss/Geometry/Configuration.py b/Sim/Gauss/python/Gauss/Geometry/Configuration.py
index 7dc7e3260..d40715e25 100644
--- a/Sim/Gauss/python/Gauss/Geometry/Configuration.py
+++ b/Sim/Gauss/python/Gauss/Geometry/Configuration.py
@@ -4,6 +4,7 @@ from GaudiKernel import SystemOfUnits
 from Gaudi.Configuration import Configurable
 from Gauss.Geometry.Helpers import checkIncompatibleDetectors
 from Gauss.Geometry.Helpers import defineGeoBasePieces
+from Configurables import LHCbApp, SimConf
 
 
 class LHCbGeo(LHCbConfigurableUser):
@@ -11,6 +12,8 @@ class LHCbGeo(LHCbConfigurableUser):
     """Main configurable to set up the LHCb geometry using the GaussGeo
     service for Run1 or Run2"""
 
+    __used_configurables__ = [LHCbApp, SimConf]
+
     __knownDetectors__ = [
         'velo', 'puveto', 'vp', 'tt', 'ut',
         'it', 'sl', 'ot', 'ft', 'ft-noshield',
@@ -161,6 +164,8 @@ class LHCbGeo(LHCbConfigurableUser):
         self.MakeItTalkToGaussino()
 
         # Setup read-out algorithms
+        # but first reset the SimConf detector list
+        SimConf().setProp('Detectors', [])
         for det in detectors_geo:
             getsubdetector(det).SetupExtraction()
 
diff --git a/Sim/Gauss/python/Gauss/Geometry/FT.py b/Sim/Gauss/python/Gauss/Geometry/FT.py
index 6d20aad56..38713ec43 100644
--- a/Sim/Gauss/python/Gauss/Geometry/FT.py
+++ b/Sim/Gauss/python/Gauss/Geometry/FT.py
@@ -6,6 +6,8 @@ from Gauss.Geometry.BeamPipe import BeamPipe
 @subdetector
 class FT(det_base):
 
+    __slots__ = {}
+
     def ApplyDetector(self, basePieces, detPieces):
         BeamPipe.removeBeamPipeElements("t")
         region = "AfterMagnetRegion"
@@ -15,3 +17,23 @@ class FT(det_base):
             detPieces[region] += ['T/PipeInT']
         region = "DownstreamRegion"
         detPieces[region] += ['NeutronShielding']
+
+    def SetupMonitor(self, slot=''):
+        from Configurables import MCHitMonitor
+        from GaudiKernel import SystemOfUnits
+        myZStations = [
+            7938.0*SystemOfUnits.mm,
+            8625.0*SystemOfUnits.mm,
+            9315.0*SystemOfUnits.mm
+            ]
+        myZStationXMax = 100.*SystemOfUnits.cm
+        myZStationYMax = 100.*SystemOfUnits.cm
+
+        moni = MCHitMonitor(
+            "FTHitMonitor"+slot,
+            mcPathString="MC/FT/Hits",
+            zStations=myZStations,
+            xMax=myZStationXMax,
+            yMax=myZStationYMax)
+        from Configurables import ApplicationMgr
+        ApplicationMgr().TopAlg += [moni]
diff --git a/Sim/Gauss/python/Gauss/Geometry/HC.py b/Sim/Gauss/python/Gauss/Geometry/HC.py
index b26d04a64..ce875bc73 100644
--- a/Sim/Gauss/python/Gauss/Geometry/HC.py
+++ b/Sim/Gauss/python/Gauss/Geometry/HC.py
@@ -7,6 +7,8 @@ from GaudiKernel import SystemOfUnits
 @subdetector
 class HC(det_base):
 
+    __slots__ = {}
+
     def ApplyDetector(self, basePieces, detPieces):
         from Gauss.Geometry import LHCbGeo
         from Configurables import LHCbApp
diff --git a/Sim/Gauss/python/Gauss/Geometry/Helpers.py b/Sim/Gauss/python/Gauss/Geometry/Helpers.py
index 0cf71eb27..f29b746c9 100644
--- a/Sim/Gauss/python/Gauss/Geometry/Helpers.py
+++ b/Sim/Gauss/python/Gauss/Geometry/Helpers.py
@@ -6,6 +6,7 @@ def subdetector(obj):
     if lname in __subdetector_configurables:
         raise RuntimeError("Class definition conflict found")
     __subdetector_configurables[lname] = obj
+    obj.name = lname
     return obj
 
 
diff --git a/Sim/Gauss/python/Gauss/Geometry/IT.py b/Sim/Gauss/python/Gauss/Geometry/IT.py
index cc75631e1..26bf6d8b6 100644
--- a/Sim/Gauss/python/Gauss/Geometry/IT.py
+++ b/Sim/Gauss/python/Gauss/Geometry/IT.py
@@ -6,6 +6,8 @@ from Gauss.Geometry.BeamPipe import BeamPipe
 @subdetector
 class IT(det_base):
 
+    __slots__ = {}
+
     def ApplyDetector(self, basePieces, detPieces):
         BeamPipe.removeBeamPipeElements("t")
         region = "AfterMagnetRegion"
@@ -14,8 +16,9 @@ class IT(det_base):
         if 'T/PipeInT' not in detPieces[region]:
             detPieces[region] += ['T/PipeInT']
 
-    def SetupExtraction(self, slot=''):
+    def SetupExtractionImpl(self, slot=''):
         from Configurables import GetTrackerHitsAlg
+        self.simconf_name = 'IT'
         region = "AfterMagnetRegion/T"
         det = "IT"
         alg = GetTrackerHitsAlg(
@@ -26,3 +29,23 @@ class IT(det_base):
         )
         from Configurables import ApplicationMgr
         ApplicationMgr().TopAlg += [alg]
+
+    def SetupMonitor(self, slot=''):
+        from Configurables import MCHitMonitor
+        from GaudiKernel import SystemOfUnits
+        myZStations = [
+            7780.0*SystemOfUnits.mm,
+            8460.0*SystemOfUnits.mm,
+            9115.0*SystemOfUnits.mm
+            ]
+        myZStationXMax = 150.*SystemOfUnits.cm
+        myZStationYMax = 150.*SystemOfUnits.cm
+
+        moni = MCHitMonitor(
+            "ITHitMonitor"+slot,
+            mcPathString="MC/IT/Hits",
+            zStations=myZStations,
+            xMax=myZStationXMax,
+            yMax=myZStationYMax)
+        from Configurables import ApplicationMgr
+        ApplicationMgr().TopAlg += [moni]
diff --git a/Sim/Gauss/python/Gauss/Geometry/Magnet.py b/Sim/Gauss/python/Gauss/Geometry/Magnet.py
index 17f8d9d97..7be7dc264 100644
--- a/Sim/Gauss/python/Gauss/Geometry/Magnet.py
+++ b/Sim/Gauss/python/Gauss/Geometry/Magnet.py
@@ -5,6 +5,8 @@ from Gauss.Geometry.Helpers import subdetector
 @subdetector
 class Magnet(det_base):
 
+    __slots__ = {}
+
     def ApplyDetector(self, basePieces, detPieces):
         detPieces["MagnetRegion"] = ['Magnet', 'BcmDown']
 
diff --git a/Sim/Gauss/python/Gauss/Geometry/Muon.py b/Sim/Gauss/python/Gauss/Geometry/Muon.py
index 8e94b7261..5091ba609 100644
--- a/Sim/Gauss/python/Gauss/Geometry/Muon.py
+++ b/Sim/Gauss/python/Gauss/Geometry/Muon.py
@@ -5,12 +5,15 @@ from Gauss.Geometry.Helpers import subdetector
 @subdetector
 class Muon(det_base):
 
+    __slots__ = {}
+
     def ApplyDetector(self, basePieces, detPieces):
         region = 'DownstreamRegion'
         detPieces[region] += ['Muon']
 
-    def SetupExtraction(self, slot=''):
+    def SetupExtractionImpl(self, slot=''):
         from Configurables import GetTrackerHitsAlg
+        self.simconf_name = 'Muon'
         det = "Muon"
         alg = GetTrackerHitsAlg(
             "Get"+det+"Hits"+slot,
diff --git a/Sim/Gauss/python/Gauss/Geometry/OT.py b/Sim/Gauss/python/Gauss/Geometry/OT.py
index e0af2bb2e..f35efce00 100644
--- a/Sim/Gauss/python/Gauss/Geometry/OT.py
+++ b/Sim/Gauss/python/Gauss/Geometry/OT.py
@@ -6,6 +6,8 @@ from Gauss.Geometry.BeamPipe import BeamPipe
 @subdetector
 class OT(det_base):
 
+    __slots__ = {}
+
     def ApplyDetector(self, basePieces, detPieces):
         BeamPipe.removeBeamPipeElements("t")
         region = "AfterMagnetRegion"
@@ -14,8 +16,9 @@ class OT(det_base):
         if 'T/PipeInT' not in detPieces[region]:
             detPieces[region] += ['T/PipeInT']
 
-    def SetupExtraction(self, slot=''):
+    def SetupExtractionImpl(self, slot=''):
         from Configurables import GetTrackerHitsAlg
+        self.simconf_name = 'OT'
         region = "AfterMagnetRegion/T"
         det = "OT"
         alg = GetTrackerHitsAlg(
@@ -26,3 +29,24 @@ class OT(det_base):
         )
         from Configurables import ApplicationMgr
         ApplicationMgr().TopAlg += [alg]
+
+    def SetupMonitor(self, slot=''):
+        from Configurables import MCHitMonitor
+        from GaudiKernel import SystemOfUnits
+
+        myZStations = [
+            7938.0*SystemOfUnits.mm,
+            8625.0*SystemOfUnits.mm,
+            9315.0*SystemOfUnits.mm
+            ]
+        myZStationXMax = 100.*SystemOfUnits.cm
+        myZStationYMax = 100.*SystemOfUnits.cm
+
+        moni = MCHitMonitor(
+            "OTHitMonitor"+slot,
+            mcPathString="MC/OT/Hits",
+            zStations=myZStations,
+            xMax=myZStationXMax,
+            yMax=myZStationYMax)
+        from Configurables import ApplicationMgr
+        ApplicationMgr().TopAlg += [moni]
diff --git a/Sim/Gauss/python/Gauss/Geometry/PuVeto.py b/Sim/Gauss/python/Gauss/Geometry/PuVeto.py
index ea91aa8cf..6842c675e 100644
--- a/Sim/Gauss/python/Gauss/Geometry/PuVeto.py
+++ b/Sim/Gauss/python/Gauss/Geometry/PuVeto.py
@@ -5,10 +5,13 @@ from Gauss.Geometry.Helpers import subdetector, getsubdetector
 @subdetector
 class PuVeto(det_base):
 
+    __slots__ = {}
+
     def ApplyDetector(self, basePieces, detPieces):
         pass
 
-    def SetupExtraction(self, slot=''):
+    def SetupExtractionImpl(self, slot=''):
+        self.simconf_name = 'PuVeto'
         det = "PuVeto"
         region = "BeforeMagnetRegion"
         from Configurables import GetTrackerHitsAlg
diff --git a/Sim/Gauss/python/Gauss/Geometry/RICH.py b/Sim/Gauss/python/Gauss/Geometry/RICH.py
index 4b7de2c8f..8beee2e76 100644
--- a/Sim/Gauss/python/Gauss/Geometry/RICH.py
+++ b/Sim/Gauss/python/Gauss/Geometry/RICH.py
@@ -6,6 +6,8 @@ from Gauss.Geometry.BeamPipe import BeamPipe
 @subdetector
 class RICH1(det_base):
 
+    __slots__ = {}
+
     def ApplyDetector(self, basePieces, detPieces):
         BeamPipe.removeBeamPipeElements("rich1")
         detPieces['BeforeMagnetRegion'] += ['Rich1']
@@ -21,6 +23,8 @@ class RICH1(det_base):
 @subdetector
 class RICH2(det_base):
 
+    __slots__ = {}
+
     def ApplyDetector(self, basePieces, detPieces):
         BeamPipe.removeBeamPipeElements("rich2")
         detPieces['AfterMagnetRegion'] += ['Rich2']
@@ -34,6 +38,8 @@ class RICH2(det_base):
 @subdetector
 class RICH1PMT(det_base):
 
+    __slots__ = {}
+
     def ApplyDetector(self, basePieces, detPieces):
         BeamPipe.removeBeamPipeElements("rich1")
         detPieces['BeforeMagnetRegion'] += ['Rich1']
@@ -52,6 +58,8 @@ class RICH1PMT(det_base):
 @subdetector
 class RICH2PMT(det_base):
 
+    __slots__ = {}
+
     def ApplyDetector(self, basePieces, detPieces):
         BeamPipe.removeBeamPipeElements("rich2")
         detPieces['AfterMagnetRegion'] += ['Rich2']
diff --git a/Sim/Gauss/python/Gauss/Geometry/SL.py b/Sim/Gauss/python/Gauss/Geometry/SL.py
index 2e1202a20..5a1b02950 100644
--- a/Sim/Gauss/python/Gauss/Geometry/SL.py
+++ b/Sim/Gauss/python/Gauss/Geometry/SL.py
@@ -14,3 +14,23 @@ class SL(det_base):
         # PSZ - line below might need to go depending on SL definition
         if 'T/PipeInT' not in detPieces[region]:
             detPieces[region] += ['T/PipeInT']
+
+    def SetupMonitor(self, slot=''):
+        from Configurables import MCHitMonitor
+        from GaudiKernel import SystemOfUnits
+        myZStations = [
+            7780.0*SystemOfUnits.mm,
+            #8460.0*SystemOfUnits.mm,
+            9115.0*SystemOfUnits.mm
+            ]
+        myZStationXMax = 150.*SystemOfUnits.cm
+        myZStationYMax = 150.*SystemOfUnits.cm
+
+        moni = MCHitMonitor(
+            "SLHitMonitor"+slot,
+            mcPathString="MC/SL/Hits",
+            zStations=myZStations,
+            xMax=myZStationXMax,
+            yMax=myZStationYMax)
+        from Configurables import ApplicationMgr
+        ApplicationMgr().TopAlg += [moni]
diff --git a/Sim/Gauss/python/Gauss/Geometry/TT.py b/Sim/Gauss/python/Gauss/Geometry/TT.py
index e8ac6ebfd..d9c955561 100644
--- a/Sim/Gauss/python/Gauss/Geometry/TT.py
+++ b/Sim/Gauss/python/Gauss/Geometry/TT.py
@@ -6,13 +6,16 @@ from Gauss.Geometry.BeamPipe import BeamPipe
 @subdetector
 class TT(det_base):
 
+    __slots__ = {}
+
     def ApplyDetector(self, basePieces, detPieces):
         BeamPipe.removeBeamPipeElements("tt")
         if 'TT' not in detPieces['BeforeMagnetRegion']:
             detPieces['BeforeMagnetRegion'] += ['TT']
 
-    def SetupExtraction(self, slot=''):
+    def SetupExtractionImpl(self, slot=''):
         from Configurables import GetTrackerHitsAlg
+        self.simconf_name = 'TT'
         region = "BeforeMagnetRegion"
         det = "TT"
         alg = GetTrackerHitsAlg(
@@ -23,3 +26,22 @@ class TT(det_base):
         )
         from Configurables import ApplicationMgr
         ApplicationMgr().TopAlg += [alg]
+
+    def SetupMonitor(self, slot=''):
+        from Configurables import MCHitMonitor
+        from GaudiKernel import SystemOfUnits
+        myZStations = [
+            2350.0*SystemOfUnits.mm,
+            2620.0*SystemOfUnits.mm
+            ]
+        myZStationXMax = 150.*SystemOfUnits.cm
+        myZStationYMax = 150.*SystemOfUnits.cm
+
+        moni = MCHitMonitor(
+            "TTHitMonitor"+slot,
+            mcPathString="MC/TT/Hits",
+            zStations=myZStations,
+            xMax=myZStationXMax,
+            yMax=myZStationYMax)
+        from Configurables import ApplicationMgr
+        ApplicationMgr().TopAlg += [moni]
diff --git a/Sim/Gauss/python/Gauss/Geometry/UT.py b/Sim/Gauss/python/Gauss/Geometry/UT.py
index 4940fa025..b38cd5b73 100644
--- a/Sim/Gauss/python/Gauss/Geometry/UT.py
+++ b/Sim/Gauss/python/Gauss/Geometry/UT.py
@@ -10,3 +10,22 @@ class UT(det_base):
         BeamPipe.removeBeamPipeElements("ut")
         if 'UT' not in detPieces['BeforeMagnetRegion']:
             detPieces['BeforeMagnetRegion'] += ['UT']
+
+    def SetupMonitor(self, slot=''):
+        from Configurables import MCHitMonitor
+        from GaudiKernel import SystemOfUnits
+        myZStations = [
+            2350.0*SystemOfUnits.mm,
+            2620.0*SystemOfUnits.mm
+            ]
+        myZStationXMax = 150.*SystemOfUnits.cm
+        myZStationYMax = 150.*SystemOfUnits.cm
+
+        moni = MCHitMonitor(
+            "UTHitMonitor"+slot,
+            mcPathString="MC/UT/Hits",
+            zStations=myZStations,
+            xMax=myZStationXMax,
+            yMax=myZStationYMax)
+        from Configurables import ApplicationMgr
+        ApplicationMgr().TopAlg += [moni]
diff --git a/Sim/Gauss/python/Gauss/Geometry/VP.py b/Sim/Gauss/python/Gauss/Geometry/VP.py
index b4a3c1ab6..be44b1dcb 100644
--- a/Sim/Gauss/python/Gauss/Geometry/VP.py
+++ b/Sim/Gauss/python/Gauss/Geometry/VP.py
@@ -6,6 +6,8 @@ from Gauss.Geometry.BeamPipe import BeamPipe
 @subdetector
 class VP(det_base):
 
+    __slots__ = {}
+
     def ApplyDetector(self, basePieces, detPieces):
         BeamPipe.removeBeamPipeElements("velo")
         if 'BeforeMagnetRegion' in detPieces:
diff --git a/Sim/Gauss/python/Gauss/Geometry/Velo.py b/Sim/Gauss/python/Gauss/Geometry/Velo.py
index cc4764117..fb153ccce 100644
--- a/Sim/Gauss/python/Gauss/Geometry/Velo.py
+++ b/Sim/Gauss/python/Gauss/Geometry/Velo.py
@@ -141,8 +141,9 @@ class Velo(det_base):
         # No need to misalign if only PuVeto exits - check me PSZ.
         self.veloMisAlignGeometry(VeloP)  # To misalign VELO
 
-    def SetupExtraction(self, slot=''):
+    def SetupExtractionImpl(self, slot=''):
         from Configurables import GetTrackerHitsAlg
+        self.simconf_name = 'Velo'
         region = "BeforeMagnetRegion"
         det = "Velo"
         alg = GetTrackerHitsAlg(
diff --git a/Sim/Gauss/python/Gauss/Geometry/det_base.py b/Sim/Gauss/python/Gauss/Geometry/det_base.py
index bf4184855..d6dc291e0 100644
--- a/Sim/Gauss/python/Gauss/Geometry/det_base.py
+++ b/Sim/Gauss/python/Gauss/Geometry/det_base.py
@@ -11,7 +11,8 @@ class det_base(LHCbConfigurableUser):
     __slots__ = {
         "active": False,
         "simulate": False,
-        "monitor": False
+        "monitor": False,
+        "simconf_name": 'NONE',
     }
 
     @property
@@ -64,6 +65,14 @@ class det_base(LHCbConfigurableUser):
         pass
 
     def SetupExtraction(self, slot=''):
+        from Configurables import SimConf
+        self.SetupExtractionImpl(slot)
+        detlist = SimConf().getProp('Detectors')
+        n = self.getProp('simconf_name')
+        if n != 'NONE' and n not in detlist:
+            detlist += [n]
+
+    def SetupExtractionImpl(self, slot=''):
         pass
 
     def SetupMonitor(self, slot=''):
-- 
GitLab


From 85bc3c561f583a78c12f4cb8b0254bc39fe6e19e Mon Sep 17 00:00:00 2001
From: Dominik Muller <dominik.muller@cern.ch>
Date: Fri, 12 Jul 2019 16:15:02 +0200
Subject: [PATCH 15/90] Base Calo and SPD&PRS converted

---
 Sim/GaussCalo/CMakeLists.txt        |  12 ++-
 Sim/GaussCalo/src/CaloSensDet.h     |   7 +-
 Sim/GaussCalo/src/CaloSensDet.icpp  |  14 +--
 Sim/GaussCalo/src/CaloSensDetFAC.h  |  31 ++++---
 Sim/GaussCalo/src/SpdPrsSensDet.cpp | 129 ++++++++++------------------
 Sim/GaussCalo/src/SpdPrsSensDet.h   | 109 +++++++----------------
 6 files changed, 115 insertions(+), 187 deletions(-)

diff --git a/Sim/GaussCalo/CMakeLists.txt b/Sim/GaussCalo/CMakeLists.txt
index 1ac199ae8..3695eba48 100644
--- a/Sim/GaussCalo/CMakeLists.txt
+++ b/Sim/GaussCalo/CMakeLists.txt
@@ -7,17 +7,21 @@ gaudi_depends_on_subdirs(Det/CaloDet
                          Det/CaloDetXmlCnv
                          Event/MCEvent
                          Kernel/LHCbKernel
-                         Sim/GaussTools)
+                         Sim/GiGaMTCore
+                         Sim/GiGaMTFactories)
 
 find_package(AIDA)
-
+AddHepMC3()
 find_package(Boost)
 find_package(CLHEP)
 include_directories(SYSTEM ${Boost_INCLUDE_DIRS} ${CLHEP_INCLUDE_DIRS} ${Geant4_INCLUDE_DIRS})
 
+add_definitions(-DG4MULTITHREADED)
+add_definitions(-DG4USE_STD11)
+
 gaudi_add_module(GaussCalo
                  src/*.cpp
-                 INCLUDE_DIRS AIDA
-                 LINK_LIBRARIES CaloDetLib MCEvent LHCbKernel GaussToolsLib)
+                 INCLUDE_DIRS AIDA GiGaMTFactories
+                 LINK_LIBRARIES CaloDetLib MCEvent LHCbKernel GiGaMTCoreTruthLib GaudiAlgLib)
 
 gaudi_env(SET GAUSSCALOOPTS \${GAUSSCALOROOT}/options)
diff --git a/Sim/GaussCalo/src/CaloSensDet.h b/Sim/GaussCalo/src/CaloSensDet.h
index 51d8f0416..3f3572241 100755
--- a/Sim/GaussCalo/src/CaloSensDet.h
+++ b/Sim/GaussCalo/src/CaloSensDet.h
@@ -26,9 +26,6 @@
 
 #include "CLHEP/Geometry/Transform3D.h"
 
-// forward declarations
-class IHistogramSvc;  // GaudiKernel
-
 /** @class CaloSensDet CaloSensDet.h CaloSensDet.h
  *
  *
@@ -38,7 +35,7 @@ class IHistogramSvc;  // GaudiKernel
 
 template <typename CELLGETTER>
 class CaloSensDet : public G4VSensitiveDetector,
-                    private virtual CELLGETTER,
+                    public virtual CELLGETTER,
                     public virtual GiGaMessage {
   public:
   /// useful type for list of names
@@ -267,7 +264,7 @@ class CaloSensDet : public G4VSensitiveDetector,
 
 // CaloDet
 #include "CaloDet/DeCalorimeter.h"
-class CellFromLHCbGeo : public virtual IGiGaMessage {
+class CellFromLHCbGeo : public virtual GiGaMessage {
   protected:
   CellFromLHCbGeo() = default;
   virtual ~CellFromLHCbGeo() = default;
diff --git a/Sim/GaussCalo/src/CaloSensDet.icpp b/Sim/GaussCalo/src/CaloSensDet.icpp
index c69803ebf..ee973b469 100755
--- a/Sim/GaussCalo/src/CaloSensDet.icpp
+++ b/Sim/GaussCalo/src/CaloSensDet.icpp
@@ -93,7 +93,9 @@ void CaloSensDet<CELLGETTER>::Initialize(G4HCofThisEvent* HCE) {
   if (!this->m_geoBaseInitialized) {
     this->GeoBaseInitialize();
   }
-  Assert(this->m_geoBaseInitialized, "Could not locate volumes!");
+  if(!this->m_geoBaseInitialized){
+    std::runtime_error("Could not locate volumes!");
+  }
   //
   m_collection =
       new CaloHitsCollection(SensitiveDetectorName, collectionName[0]);
@@ -287,8 +289,8 @@ void CaloSensDet<CELLGETTER>::EndOfEvent(G4HCofThisEvent* /* HCE */) {
 
   if (printDebug()) {
     always(
-        boost::format(" #Hits=%5d #SubHits=%5d #Slots=%5d Energy=%8.3g[GeV] ") %
-        nhits % nshits % nslots % energy);
+        boost::str(boost::format(" #Hits=%5d #SubHits=%5d #Slots=%5d Energy=%8.3g[GeV] ") %
+        nhits % nshits % nslots % energy));
   }
 }
 
@@ -376,7 +378,7 @@ bool CaloSensDet<CELLGETTER>::ProcessHits(G4Step* step,
                               material, step);
 
   if (!sc) {
-    error("The SubHit information is not filled!", sc);
+    error("The SubHit information is not filled!");
   }
 
   return true;
@@ -392,7 +394,7 @@ void CaloSensDet<CELLGETTER>::GeoBaseInitialize() {
   // locate start volumes
   for (auto& vol : m_startVolumeNames) {
     // look through converted volumes
-    const G4LogicalVolume* lv = G4LogicalVolumeStore::GetVolume(vol);
+    const G4LogicalVolume* lv = G4LogicalVolumeStore::GetInstance()->GetVolume(vol);
     if (0 == lv) {
       throw std::runtime_error("G4LogicalVolume* points to 0 for " + (vol));
     }
@@ -402,7 +404,7 @@ void CaloSensDet<CELLGETTER>::GeoBaseInitialize() {
     throw std::runtime_error("Size of 'StartVolumes' is 0 ");
   }
   // locate end volume : look through converted volumes
-  m_end = G4LogicalVolumeStore::GetVolume(m_endVolumeName);
+  m_end = G4LogicalVolumeStore::GetInstance()->GetVolume(m_endVolumeName);
   if (0 == m_end) {
     throw std::runtime_error("G4LogicalVolume* points to 0 for '" + m_endVolumeName + "'");
   }
diff --git a/Sim/GaussCalo/src/CaloSensDetFAC.h b/Sim/GaussCalo/src/CaloSensDetFAC.h
index fea742979..4eb518243 100755
--- a/Sim/GaussCalo/src/CaloSensDetFAC.h
+++ b/Sim/GaussCalo/src/CaloSensDetFAC.h
@@ -12,9 +12,9 @@
 
 template <typename CALO>
 class CaloSensDetBaseFAC : public GiGaMTG4SensDetFactory<CALO> {
-  Gaudi::Property<std::string> m_endVolumeName{this, "StartVolumes", {}};
-  Gaudi::Property<std::vector<std::string>> m_startVolumeNames{this,
-                                                               "EndVolume", ""};
+  Gaudi::Property<std::string> m_endVolumeName{this, "EndVolume", ""};
+  Gaudi::Property<std::vector<std::string>> m_startVolumeNames{
+      this, "StartVolumes", {}};
 
   // the first coefficient of Birk's law                    (c1)
   Gaudi::Property<double> m_birk_c1{this, "BirkC1",
@@ -44,10 +44,11 @@ class CaloSensDetBaseFAC : public GiGaMTG4SensDetFactory<CALO> {
   Gaudi::Accumulators::SummingCounter<double> m_energy{this, "#energy"};
 
   public:
-  using base_class = GiGaMTG4SensDetFactory<CALO>;
-  using base_class::GiGaMTG4SensDetFactory;
-  CALO* construct() const override {
-    auto tmp = base_class::construct();
+  virtual ~CaloSensDetBaseFAC() = default;
+  using gaussino_base_class = GiGaMTG4SensDetFactory<CALO>;
+  using typename gaussino_base_class::GiGaMTG4SensDetFactory;
+  virtual CALO* construct() const override {
+    auto tmp = gaussino_base_class::construct();
     tmp->m_endVolumeName = m_endVolumeName;
     tmp->m_startVolumeNames = m_startVolumeNames;
     tmp->m_birk_c1 = m_birk_c1;
@@ -60,14 +61,14 @@ class CaloSensDetBaseFAC : public GiGaMTG4SensDetFactory<CALO> {
     return tmp;
   }
   StatusCode initialize() override {
-    auto sc = base_class::initialize();
+    auto sc = gaussino_base_class::initialize();
 
     {  // load all input histos
       for (auto& histo : m_histoNames) {
-        SmartDataPtr<IHistogram1D> pHist(m_histoSvc, histo);
+        SmartDataPtr<IHistogram1D> pHist(m_histoSvc.get(), histo);
         IHistogram1D* hist = pHist;
         if (0 == hist) {
-          return Error("Cannot load histogram '" + (histo) + "'");
+          return this->Error("Cannot load histogram '" + (histo) + "'");
         }
         m_histos.push_back(hist);
       }
@@ -88,9 +89,10 @@ class CaloSensDetBaseFAC : public GiGaMTG4SensDetFactory<CALO> {
 template <typename CALO, typename dummy = void>
 class CaloSensDetFAC : public CaloSensDetBaseFAC<CALO> {
   public:
+  virtual ~CaloSensDetFAC() = default;
   using base_class = CaloSensDetBaseFAC<CALO>;
   using base_class::CaloSensDetBaseFAC;
-  CALO* construct() const override { return base_class::construct(); }
+  virtual CALO* construct() const override { return base_class::construct(); }
 };
 
 template <typename T>
@@ -100,13 +102,14 @@ using usesLHCbGeo =
 template <typename CALO>
 class CaloSensDetFAC<CALO, usesLHCbGeo<CALO>>
     : public CaloSensDetBaseFAC<CALO> {
-  Gaudi::Property<std::string> m_caloName{"Detector", m_caloName,
+  Gaudi::Property<std::string> m_caloName{this, "Detector",
                                           DeCalorimeterLocation::Ecal};
 
   public:
+  virtual ~CaloSensDetFAC() = default;
   using base_class = CaloSensDetBaseFAC<CALO>;
-  using base_class::base_class;
-  CALO* construct() const override {
+  using base_class::CaloSensDetBaseFAC;
+  virtual CALO* construct() const override {
     auto tmp = base_class::construct();
     tmp->m_calo = this->template getDet<DeCalorimeter>(m_caloName);
     if (0 == tmp->m_calo) {
diff --git a/Sim/GaussCalo/src/SpdPrsSensDet.cpp b/Sim/GaussCalo/src/SpdPrsSensDet.cpp
index f3738d194..14c35ebef 100755
--- a/Sim/GaussCalo/src/SpdPrsSensDet.cpp
+++ b/Sim/GaussCalo/src/SpdPrsSensDet.cpp
@@ -15,7 +15,7 @@
 #include "GaudiKernel/IHistogramSvc.h"
 
 // GaussTools
-#include "GaussTools/GaussTrackInformation.h"
+#include "GiGaMTCore/Truth/GaussinoTrackInformation.h"
 
 // Geant4
 #include "Geant4/G4Step.hh"
@@ -26,9 +26,6 @@
 #include "Geant4/G4EnergyLossTables.hh"
 #include "Geant4/G4MaterialCutsCouple.hh"
 
-// GiGaCnv
-#include "GiGaCnv/GiGaVolumeUtils.h"
-
 // CaloDet
 #include "CaloDet/DeCalorimeter.h"
 
@@ -55,66 +52,7 @@
  */
 // ============================================================================
 
-// Declaration of the Tool Factory
-DECLARE_COMPONENT( SpdPrsSensDet )
 
-// ============================================================================
-/** standard constructor
- *  @see GiGaSensDetBase
- *  @see GiGaBase
- *  @see AlgTool
- *  @param type type of the object (?)
- *  @param name name of the object
- *  @param parent  pointer to parent object
- */
-// ============================================================================
-SpdPrsSensDet::SpdPrsSensDet
-( const std::string& type   ,
-  const std::string& name   ,
-  const IInterface*  parent )
-  : G4VSensitiveDetector( name  )
-  , CaloSensDet        ( type , name , parent )
-  , m_BX ( 25. * CLHEP::ns )
-  , m_numBXs (6)
-  , m_sDelays ( 3, 0. )
-  , m_fracMin ( 1.e-5 )
-  , m_multiChargedBirks ( true )
-{
-  declareProperty ( "BunchCrossing"     ,  m_BX      ) ;
-  declareProperty ( "NumberBXs"         ,  m_numBXs  ) ;
-  declareProperty ( "IntegrationDelays" ,  m_sDelays ) ;
-  declareProperty ( "FracMin"           ,  m_fracMin ) ;
-}
-
-// ============================================================================
-/** standard initialization (Gaudi)
- *  @see GiGaSensDetBase
- *  @see GiGaBase
- *  @see   AlgTool
- *  @see  IAlgTool
- *  @return statsu code
- */
-// ============================================================================
-StatusCode SpdPrsSensDet::initialize   ()
-{
-  return CaloSensDet::initialize();
-}
-
-// ============================================================================
-/** standard finalization (Gaudi)
- *  @see GiGaSensDetBase
- *  @see GiGaBase
- *  @see   AlgTool
- *  @see  IAlgTool
- *  @return statsu code
- */
-// ============================================================================
-StatusCode SpdPrsSensDet::finalize    ()
-{
-  m_sDelays.clear () ;
-  // finalize the base class
-  return CaloSensDet::finalize();
-}
 
 // ============================================================================
 /** fill the hit with the concrete information about the energy and the time.
@@ -135,7 +73,8 @@ StatusCode SpdPrsSensDet::finalize    ()
  *
  */
 // ============================================================================
-StatusCode    SpdPrsSensDet::fillHitInfo
+template <typename CELLGETTER>
+bool SpdPrsSensDet<CELLGETTER>::fillHitInfo
 ( CaloSubHit*                     hit,
   const HepGeom::Point3D<double>& /* prePoint   */,
   const double                    globalTime,
@@ -145,11 +84,11 @@ StatusCode    SpdPrsSensDet::fillHitInfo
   const G4MaterialCutsCouple*     material,
   const G4Step*                   /* step       */) const
 {
-  if ( 0 == hit ) { return StatusCode::FAILURE ; }
+  if ( 0 == hit ) { return false; }
 
   // Birks' Law Correction
   double edep = deposit ;
-  edep *= birkCorrection
+  edep *= this->birkCorrection
     ( particle                  ,
       track->GetKineticEnergy() ,
       material                  ) ;
@@ -157,19 +96,19 @@ StatusCode    SpdPrsSensDet::fillHitInfo
   // add the current energy deposition to the sub-hit
   // smearing the energy deposition over a number of bunch crossings (timing)
   CaloSubHit::Time slot;
-  CaloSensDet::Fractions frac;
+  typename CaloSensDet<CELLGETTER>::Fractions frac;
   frac.reserve( m_numBXs ) ;
 
   const LHCb::CaloCellID cellID = hit->cellID();
 
-  StatusCode sc = timing( globalTime , cellID , slot , frac );
-  if ( sc.isFailure() )
-  { return Error ( "Could not smear Edep!" , sc ) ; }
+  bool sc = timing( globalTime , cellID , slot , frac );
+  if ( !sc )
+  { this->error ( "Could not smear Edep!" ) ; }
 
   for( unsigned int i = 0; i < frac.size(); i++, slot += 1 )
   { if ( frac[i] > m_fracMin ) { hit->add( slot, edep*frac[i] ) ; } }
 
-  return StatusCode::SUCCESS ;
+  return true;
 }
 // ============================================================================
 /** The fractions of energy deposited in consequitive time-slots
@@ -178,16 +117,17 @@ StatusCode    SpdPrsSensDet::fillHitInfo
  *  @param cell cellID of the cell
  *  @param slot (out) the first time slot
  *  @param fracs the vector of fractions for subsequent time-slots;
- *  @return StatusCode
+ *  @return bool
  */
 // ============================================================================
-StatusCode SpdPrsSensDet::timing
+template <typename CELLGETTER>
+bool SpdPrsSensDet<CELLGETTER>::timing
 ( const double             time      ,
   const LHCb::CaloCellID&  cell      ,
   CaloSubHit::Time&        slot      ,
-  CaloSensDet::Fractions&  fractions ) const
+  typename CaloSensDet<CELLGETTER>::Fractions&  fractions ) const
 {
-  const double locTime = time - t0( cell );
+  const double locTime = time - this->t0( cell );
 
   // number of the current 25 ns bx w.r.t. local time
   slot = static_cast<CaloSubHit::Time>( floor( locTime/m_BX ) );
@@ -197,7 +137,7 @@ StatusCode SpdPrsSensDet::timing
   // which area the cell is in: 0-Outer, 1-Middle, 2-Inner
   const unsigned int area = cell.area();
 
-  const IAxis & axis = histos()[area]->axis();
+  const IAxis & axis = this->histos()[area]->axis();
   const double lowerEdge = axis.lowerEdge();
   const double upperEdge = axis.upperEdge();
 
@@ -207,16 +147,41 @@ StatusCode SpdPrsSensDet::timing
        i++, t += m_BX )
     if( lowerEdge < t && t < upperEdge )
     {
-      fractions.push_back( histos()[area]->binHeight( axis.coordToIndex(t) ) );
+      fractions.push_back( this->histos()[area]->binHeight( axis.coordToIndex(t) ) );
     }
     else fractions.push_back(0.);
 
   slot -= 1;
 
-  return StatusCode::SUCCESS ;
+  return true ;
 }
-// ============================================================================
 
-// ============================================================================
-// The END
-// ============================================================================
+#include "CaloSensDetFAC.h"
+
+template <typename CELLGETTER>
+class SpdPrsSensDetFAC
+    : public CaloSensDetFAC<SpdPrsSensDet<CELLGETTER>> {
+  Gaudi::Property<double> m_BX{this, "BunchCrossing", 25. * CLHEP::ns};
+  Gaudi::Property<unsigned int> m_numBXs{this, "NumberBXs", 6};
+  Gaudi::Property<std::vector<double>> m_sDelays{
+      this, "IntegrationDelays", {0, 0, 0}};
+  Gaudi::Property<double> m_fracMin{this, "FracMin", 1.e-5};
+
+  public:
+  using calotype = SpdPrsSensDet<CELLGETTER>;
+  using base = CaloSensDetFAC<calotype>;
+  using typename base::CaloSensDetFAC;
+  virtual calotype* construct() const override {
+    auto tmp = base::construct();
+    tmp->m_BX = m_BX;
+    tmp->m_numBXs = m_numBXs;
+    tmp->m_sDelays = m_sDelays;
+    tmp->m_fracMin = m_fracMin;
+    return tmp;
+  }
+};
+
+
+// Declaration of the Tool Factory
+typedef SpdPrsSensDetFAC<CellFromLHCbGeo> SpdPrsSensDetLHCbGeoFAC;
+DECLARE_COMPONENT_WITH_ID( SpdPrsSensDetLHCbGeoFAC, "SpdPrsSensDet" )
diff --git a/Sim/GaussCalo/src/SpdPrsSensDet.h b/Sim/GaussCalo/src/SpdPrsSensDet.h
index a4aff6e1d..8854da3e7 100755
--- a/Sim/GaussCalo/src/SpdPrsSensDet.h
+++ b/Sim/GaussCalo/src/SpdPrsSensDet.h
@@ -1,20 +1,16 @@
-// $Id: SpdPrsSensDet.h,v 1.7 2007-01-12 15:24:50 ranjard Exp $
-#ifndef       GAUSSCALO_SpdPrsSensDet_H
-#define       GAUSSCALO_SpdPrsSensDet_H 1
+#pragma once
 
 // GaudiKernel
 /// Ntupel Svc
 #include "GaudiKernel/INTuple.h"
 #include "GaudiKernel/INTupleSvc.h"
 #include "GaudiKernel/NTuple.h"
-/// GiGa
-#include "GiGa/GiGaSensDetBase.h"
 /// local
-#include "CaloSim.h"
 #include "CaloHit.h"
 #include "CaloSensDet.h"
+#include "CaloSim.h"
 
-class DeCalorimeter ;  // CaloDet
+class DeCalorimeter;  // CaloDet
 
 /** @class SpdPrsSensDet SpdPrsSensDet.h
  *
@@ -25,31 +21,13 @@ class DeCalorimeter ;  // CaloDet
  *  @date    23/01/2001
  */
 
-class SpdPrsSensDet: public CaloSensDet
-{
-
-public :
-
-  /** standard initialization (Gaudi)
-   *  @see GiGaSensDetBase
-   *  @see GiGaBase
-   *  @see   AlgTool
-   *  @see  IAlgTool
-   *  @return status code
-   */
-  StatusCode initialize   () override;
-
-  /** standard finalization (Gaudi)
-   *  @see GiGaSensDetBase
-   *  @see GiGaBase
-   *  @see   AlgTool
-   *  @see  IAlgTool
-   *  @return status code
-   */
-  StatusCode finalize    () override;
-
-protected:
+template <typename CELLGETTER>
+class SpdPrsSensDet : public CaloSensDet<CELLGETTER>, public virtual CELLGETTER {
+  public:
+  using base_class = CaloSensDet<CELLGETTER>;
+  using base_class::CaloSensDet;
 
+  protected:
   /** fill the hit with the concrete information about the energy and the time.
    *  The function is to be called from ProcessHits method.
    *
@@ -67,15 +45,11 @@ protected:
    *                    particle definition,material etc for efficiency reasons.
    *
    */
-  StatusCode    fillHitInfo
-  ( CaloSubHit*                 hit         ,
-    const HepGeom::Point3D<double>& prePoint    ,
-    const double                globalTime  ,
-    const double                deposit     ,
-    const G4Track*              track       ,
-    const G4ParticleDefinition* pdef        ,
-    const G4MaterialCutsCouple* material    ,
-    const G4Step*               step        ) const override;
+  bool fillHitInfo(CaloSubHit* hit, const HepGeom::Point3D<double>& prePoint,
+                   const double globalTime, const double deposit,
+                   const G4Track* track, const G4ParticleDefinition* pdef,
+                   const G4MaterialCutsCouple* material,
+                   const G4Step* step) const override;
 
   /** The fractions of energy deposited in consequitive time-bins
    *  for the given calorimeter cell
@@ -83,16 +57,13 @@ protected:
    *  @param cell cellID of the cell
    *  @param slot (out) the first time slot
    *  @param fracs the vector of fractions for subsequent time-slots;
-   *  @return StatusCode
+   *  @return bool
    */
-  StatusCode timing
-  ( const double            time      ,
-    const LHCb::CaloCellID&       cell      ,
-    CaloSubHit::Time&       slot      ,
-    CaloSensDet::Fractions& fractions ) const override;
-
-public:
+  bool timing(
+      const double time, const LHCb::CaloCellID& cell, CaloSubHit::Time& slot,
+      typename CaloSensDet<CELLGETTER>::Fractions& fractions) const override;
 
+  public:
   /** standard constructor
    *  @see CaloSensDet
    *  @see GiGaSensDetBase
@@ -102,34 +73,20 @@ public:
    *  @param name name of the object
    *  @param parent  pointer to parent object
    */
-  SpdPrsSensDet
-  ( const std::string& type   ,
-    const std::string& name   ,
-    const IInterface*  parent ) ;
+  SpdPrsSensDet(const std::string& type, const std::string& name,
+                const IInterface* parent);
 
   /// destructor (virtual and protected)
-  virtual ~SpdPrsSensDet() {};
-
-private:
-
-  // no default constructor
-  SpdPrsSensDet() ;
-  // no copy constructor
-  SpdPrsSensDet           ( const SpdPrsSensDet& );
-  // no assignement
-  SpdPrsSensDet& operator=( const SpdPrsSensDet& ) ;
-
-private:
-  double                                      m_BX                ;
-  unsigned int                                m_numBXs                ;
-  std::vector<double>                         m_sDelays ;
-  double                                      m_fracMin                ;
-
-// flag controlling the correction C1'= 7.2/12.6 * C1
-// for multiply charged particles: == true  correction is applied
-//                                 == false  correction is not applied
-  bool                                      m_multiChargedBirks ;
+  virtual ~SpdPrsSensDet(){};
+
+  public:
+  double m_BX{25. * CLHEP::ns};
+  unsigned int m_numBXs{6};
+  std::vector<double> m_sDelays{{0, 0, 0}};
+  double m_fracMin{1.e-5};
+
+  // flag controlling the correction C1'= 7.2/12.6 * C1
+  // for multiply charged particles: == true  correction is applied
+  //                                 == false  correction is not applied
+  bool m_multiChargedBirks{true};
 };
-
-#endif  ///< GAUSSCALO_SpdPrsSensDet_H
-
-- 
GitLab


From 9c735b4059f7f6213048b0f240d08099f2c2306a Mon Sep 17 00:00:00 2001
From: Dominik Muller <dominik.muller@cern.ch>
Date: Fri, 12 Jul 2019 17:58:32 +0200
Subject: [PATCH 16/90] Ported GaussSensPlaneDet

---
 Sim/GaussCalo/src/CaloSensDet.icpp      |  23 +-
 Sim/GaussCalo/src/GaussSensPlaneDet.cpp | 366 +++++++++++-------------
 Sim/GaussCalo/src/GaussSensPlaneDet.h   | 137 +++------
 Sim/GaussCalo/src/GaussSensPlaneHit.cpp |  86 +-----
 Sim/GaussCalo/src/GaussSensPlaneHit.h   |  82 +-----
 Sim/GaussCalo/src/SpdPrsSensDet.h       |   2 +-
 6 files changed, 237 insertions(+), 459 deletions(-)

diff --git a/Sim/GaussCalo/src/CaloSensDet.icpp b/Sim/GaussCalo/src/CaloSensDet.icpp
index ee973b469..92c71a3d4 100755
--- a/Sim/GaussCalo/src/CaloSensDet.icpp
+++ b/Sim/GaussCalo/src/CaloSensDet.icpp
@@ -93,16 +93,19 @@ void CaloSensDet<CELLGETTER>::Initialize(G4HCofThisEvent* HCE) {
   if (!this->m_geoBaseInitialized) {
     this->GeoBaseInitialize();
   }
-  if(!this->m_geoBaseInitialized){
+  if (!this->m_geoBaseInitialized) {
     std::runtime_error("Could not locate volumes!");
   }
   //
   m_collection =
       new CaloHitsCollection(SensitiveDetectorName, collectionName[0]);
   //
-  const int id = GetCollectionID(0);
+  std::string hit_location = SensitiveDetectorName + "/" + collectionName[0];
+
+  debug("Registering location at " + hit_location);
+  int HCID = G4SDManager::GetSDMpointer()->GetCollectionID(hit_location);
 
-  HCE->AddHitsCollection(id, m_collection);
+  HCE->AddHitsCollection(HCID, m_collection);
 
   m_hitmap.clear();
 }
@@ -288,8 +291,8 @@ void CaloSensDet<CELLGETTER>::EndOfEvent(G4HCofThisEvent* /* HCE */) {
   if (m_energy) (*m_energy) += energy;
 
   if (printDebug()) {
-    always(
-        boost::str(boost::format(" #Hits=%5d #SubHits=%5d #Slots=%5d Energy=%8.3g[GeV] ") %
+    always(boost::str(
+        boost::format(" #Hits=%5d #SubHits=%5d #Slots=%5d Energy=%8.3g[GeV] ") %
         nhits % nshits % nslots % energy));
   }
 }
@@ -374,8 +377,8 @@ bool CaloSensDet<CELLGETTER>::ProcessHits(G4Step* step,
   }
 
   // perform the specific sub-detector action
-  bool sc = fillHitInfo(sub, prePoint, time, deposit, track, particle,
-                              material, step);
+  bool sc = fillHitInfo(sub, prePoint, time, deposit, track, particle, material,
+                        step);
 
   if (!sc) {
     error("The SubHit information is not filled!");
@@ -394,7 +397,8 @@ void CaloSensDet<CELLGETTER>::GeoBaseInitialize() {
   // locate start volumes
   for (auto& vol : m_startVolumeNames) {
     // look through converted volumes
-    const G4LogicalVolume* lv = G4LogicalVolumeStore::GetInstance()->GetVolume(vol);
+    const G4LogicalVolume* lv =
+        G4LogicalVolumeStore::GetInstance()->GetVolume(vol);
     if (0 == lv) {
       throw std::runtime_error("G4LogicalVolume* points to 0 for " + (vol));
     }
@@ -406,7 +410,8 @@ void CaloSensDet<CELLGETTER>::GeoBaseInitialize() {
   // locate end volume : look through converted volumes
   m_end = G4LogicalVolumeStore::GetInstance()->GetVolume(m_endVolumeName);
   if (0 == m_end) {
-    throw std::runtime_error("G4LogicalVolume* points to 0 for '" + m_endVolumeName + "'");
+    throw std::runtime_error("G4LogicalVolume* points to 0 for '" +
+                             m_endVolumeName + "'");
   }
   m_geoBaseInitialized = true;
 }
diff --git a/Sim/GaussCalo/src/GaussSensPlaneDet.cpp b/Sim/GaussCalo/src/GaussSensPlaneDet.cpp
index 6950f1ea8..ac8fb73f8 100755
--- a/Sim/GaussCalo/src/GaussSensPlaneDet.cpp
+++ b/Sim/GaussCalo/src/GaussSensPlaneDet.cpp
@@ -1,6 +1,3 @@
-// $Id: GaussSensPlaneDet.cpp,v 1.7 2008-07-11 10:47:44 robbep Exp $
-// Include files
-
 // SRD & STD
 #include <algorithm>
 #include <vector>
@@ -10,37 +7,32 @@
 #include "CLHEP/Units/PhysicalConstants.h"
 
 // GaudiKernel
-#include "GaudiKernel/MsgStream.h"
-#include "GaudiKernel/SmartDataPtr.h"
 #include "GaudiKernel/IDataProviderSvc.h"
 #include "GaudiKernel/IHistogramSvc.h"
+#include "GaudiKernel/MsgStream.h"
 #include "GaudiKernel/SmartDataPtr.h"
 
 // GaussTools
-#include "GaussTools/GaussTrackInformation.h"
+#include "GiGaMTCore/Truth/GaussinoTrackInformation.h"
 
 // Geant4
-#include "Geant4/G4Step.hh"
-#include "Geant4/G4TouchableHistory.hh"
-#include "Geant4/G4VPhysicalVolume.hh"
-#include "Geant4/G4LogicalVolume.hh"
-#include "Geant4/G4SDManager.hh"
+#include "Geant4/G4Electron.hh"
 #include "Geant4/G4EnergyLossTables.hh"
-#include "Geant4/G4Material.hh"
 #include "Geant4/G4Gamma.hh"
-#include "Geant4/G4Electron.hh"
-#include "Geant4/G4Positron.hh"
-#include "Geant4/G4MuonPlus.hh"
+#include "Geant4/G4LogicalVolume.hh"
+#include "Geant4/G4Material.hh"
 #include "Geant4/G4MuonMinus.hh"
-
-// GiGaCnv
-#include "GiGaCnv/GiGaVolumeUtils.h"
+#include "Geant4/G4MuonPlus.hh"
+#include "Geant4/G4Positron.hh"
+#include "Geant4/G4SDManager.hh"
+#include "Geant4/G4Step.hh"
+#include "Geant4/G4TouchableHistory.hh"
+#include "Geant4/G4VPhysicalVolume.hh"
 
 // CaloDet
 #include "CaloDet/DeCalorimeter.h"
 
 /// local
-#include "GaussSensPlaneHit.h"
 #include "GaussSensPlaneDet.h"
 
 using CLHEP::HepLorentzVector;
@@ -56,83 +48,13 @@ using CLHEP::HepLorentzVector;
 // ============================================================================
 
 // Declaration of the Tool Factory
-DECLARE_COMPONENT( GaussSensPlaneDet )
+// DECLARE_COMPONENT( GaussSensPlaneDet )
 
-
-// ============================================================================
-/** standard constructor
- *  @see GiGaSensDetBase
- *  @see GiGaBase
- *  @see AlgTool
- *  @param type type of the object (?)
- *  @param name name of the object
- *  @param parent  pointer to parent object
- */
-// ============================================================================
-GaussSensPlaneDet::GaussSensPlaneDet
-( const std::string& type   ,
-  const std::string& name   ,
-  const IInterface*  parent )
-  : G4VSensitiveDetector ( name  )
-  , GiGaSensDetBase      ( type , name , parent )
-  ///
-  , m_collectionName     ( "Hits"  )
-  , m_collection         ( 0 )
-  ///
-  , m_keepLinks ( false )
-    , m_oneEntry  ( true  )
-  ///
-  , m_cutForPhoton   ( 50 * CLHEP::MeV )
-  , m_cutForElectron ( 10 * CLHEP::MeV )
-  , m_cutForPositron ( 10 * CLHEP::MeV )
-  , m_cutForMuon     ( -1 * CLHEP::MeV )
-  , m_cutForCharged  ( 10 * CLHEP::MeV )
-  , m_cutForNeutral  ( 10 * CLHEP::MeV )
-  ///
-  , m_stat    (  true   )
-  , m_events  (  0      )
-  , m_hits    (  0      )
-  , m_hits2   (  0      )
-  , m_hitsMin (  1.e+10 )
-  , m_hitsMax ( -1.e+10 )
-{
-  declareProperty ( "CollectionName"       ,  m_collectionName    ) ;
-  //
-  declareProperty ( "KeepAllLinks"         , m_keepLinks      ) ;
-  declareProperty ( "OneEntry"             , m_oneEntry       ) ;
-  declareProperty ( "CutForPhoton"         , m_cutForPhoton   ) ;
-  declareProperty ( "CutForElectron"       , m_cutForElectron ) ;
-  declareProperty ( "CutForPositron"       , m_cutForPositron ) ;
-  declareProperty ( "CutForMuon"           , m_cutForMuon     ) ;
-  declareProperty ( "CutForCharged"        , m_cutForCharged  ) ;
-  declareProperty ( "CutForNeutral"        , m_cutForNeutral  ) ;
+GaussSensPlaneDet::GaussSensPlaneDet(const std::string& name)
+    : G4VSensitiveDetector(name) {
+  collectionName.insert("Hits");
 }
 
-
-// ============================================================================
-/** standard initialization (Gaudi)
- *  @see GiGaSensDetBase
- *  @see GiGaBase
- *  @see   AlgTool
- *  @see  IAlgTool
- *  @return statsu code
- */
-// ============================================================================
-StatusCode GaussSensPlaneDet::initialize   ()
-{
-  // initialze the base class
-  StatusCode sc = GiGaSensDetBase::initialize();
-  if( sc.isFailure() )
-    { return Error("Could not initialize the base class!",sc);}
-  //
-  // clear collection name vector
-  collectionName.clear  () ;
-  collectionName.insert ( m_collectionName );
-  ///
-  return StatusCode::SUCCESS ;
-}
-
-
 // ============================================================================
 /** standard finalization (Gaudi)
  *  @see GiGaSensDetBase
@@ -142,23 +64,22 @@ StatusCode GaussSensPlaneDet::initialize   ()
  *  @return statsu code
  */
 // ============================================================================
-StatusCode GaussSensPlaneDet::finalize    ()
-{
-  if( m_stat )
-    { /// statistical printout
-      MsgStream log( msgSvc() , name() ) ;
-      log << MSG::DEBUG <<
-        format ( " <#Hits>/Min/Max=(%3d+-%3d)/%d/%4d "                  ,
-                 (long) m_hits                                          ,
-                 (long) sqrt ( fabs( m_hits2 - m_hits * m_hits ) )      ,
-                 (long) m_hitsMin                                       ,
-                 (long) m_hitsMax                                       )
-           << endmsg ;
-    }
-  // finalize the base class
-  return GiGaSensDetBase::finalize();
-}
-
+// StatusCode GaussSensPlaneDet::finalize    ()
+//{
+// if( m_stat )
+//{ /// statistical printout
+// MsgStream log( msgSvc() , name() ) ;
+// log << MSG::DEBUG <<
+// format ( " <#Hits>/Min/Max=(%3d+-%3d)/%d/%4d "                  ,
+//(long) m_hits                                          ,
+//(long) sqrt ( fabs( m_hits2 - m_hits * m_hits ) )      ,
+//(long) m_hitsMin                                       ,
+//(long) m_hitsMax                                       )
+//<< endmsg ;
+//}
+//// finalize the base class
+// return GiGaSensDetBase::finalize();
+//}
 
 // ============================================================================
 /** method from G4
@@ -167,24 +88,19 @@ StatusCode GaussSensPlaneDet::finalize    ()
  *  @param HCE pointer to hit collection of current event
  */
 // ============================================================================
-void GaussSensPlaneDet::Initialize( G4HCofThisEvent* HCE )
-{
-  //
-  m_collection =
-    new GaussSensPlaneHitsCollection ( SensitiveDetectorName ,
-                                       collectionName[0]     ) ;
-  //
-  const int id  = GetCollectionID( 0 ) ;
-
-  HCE -> AddHitsCollection( id , m_collection );
-
-  //
-  Print (" Initialize(): CollectionName='" + m_collection->GetName   () +
-         "' for SensDet='"                 + m_collection->GetSDname () +
-         "'" , StatusCode::SUCCESS , MSG::VERBOSE                       ).ignore() ;
-  //
-}
+void GaussSensPlaneDet::Initialize(G4HCofThisEvent* HCE) {
+  m_collection = new GaussSensPlaneHitsCollection(SensitiveDetectorName,
+                                                  collectionName[0]);
+  std::string hit_location = SensitiveDetectorName + "/" + collectionName[0];
 
+  debug("Registering location at " + hit_location);
+  int HCID = G4SDManager::GetSDMpointer()->GetCollectionID(hit_location);
+
+  HCE->AddHitsCollection(HCID, m_collection);
+
+  verbose(" Initialize(): CollectionName='" + m_collection->GetName() +
+          "' for SensDet='" + m_collection->GetSDname() + "'");
+}
 
 // ============================================================================
 /** method from G4
@@ -193,105 +109,153 @@ void GaussSensPlaneDet::Initialize( G4HCofThisEvent* HCE )
  *  @param HCE pointer to hit collection of current event
  */
 // ============================================================================
-void GaussSensPlaneDet::EndOfEvent( G4HCofThisEvent* /* HCE */ )
-{
-  if( !m_stat ) { return ; }                               // RETURN
-    /// increase the counter of processed events
-  ++m_events ;
-  const double f1 = 1.0 / ( (double) ( m_events     ) ) ;
-  const double f2 =  f1 * ( (double) ( m_events - 1 ) ) ;
-
-  if ( 0 == m_collection )
-    { Warning ( " EndOfEvent(): HitCollection points to NULL " ) ; return ; }
-  typedef std::vector<GaussSensPlaneHit*> Hits ;
-  const Hits* hits = m_collection ->GetVector() ;
-  if ( 0 == hits )
-    { Error   (" EndOfEvent(): HitVector* points to NULL "     ) ; return ; }
-
-  const size_t nhits = hits->size() ;
-  m_hits    = m_hits  * f2 + nhits           * f1 ;
-  m_hits2   = m_hits2 * f2 + nhits  * nhits  * f1 ;
-
-  if ( nhits  > m_hitsMax   ) { m_hitsMax   = nhits  ; }
-  if ( nhits  < m_hitsMin   ) { m_hitsMin   = nhits  ; }
-
-  MsgStream log ( msgSvc() , name() ) ;
-  log << MSG::DEBUG <<
-    format ( " #GaussSensPlaneHits=%4d ", nhits ) << endmsg ;
+void GaussSensPlaneDet::EndOfEvent(G4HCofThisEvent* /* HCE */) {
+  if (!m_stat) {
+    return;
+  }  // RETURN
+  /// increase the counter of processed events
+  ++m_events;
+  const double f1 = 1.0 / ((double)(m_events));
+  const double f2 = f1 * ((double)(m_events - 1));
+
+  if (0 == m_collection) {
+    warning(" EndOfEvent(): HitCollection points to NULL ");
+    return;
+  }
+  typedef std::vector<GaussSensPlaneHit*> Hits;
+  const Hits* hits = m_collection->GetVector();
+  if (0 == hits) {
+    error(" EndOfEvent(): HitVector* points to NULL ");
+    return;
+  }
+
+  const size_t nhits = hits->size();
+  m_hits = m_hits * f2 + nhits * f1;
+  m_hits2 = m_hits2 * f2 + nhits * nhits * f1;
+
+  if (nhits > m_hitsMax) {
+    m_hitsMax = nhits;
+  }
+  if (nhits < m_hitsMin) {
+    m_hitsMin = nhits;
+  }
+
+  debug(format(" #GaussSensPlaneHits=%4d ", nhits));
 }
 
-
 // ============================================================================
 /** process the hit
  *  @param step     pointer to current Geant4 step
  *  @param history  pointert to touchable history
  */
 // ============================================================================
-bool GaussSensPlaneDet::ProcessHits( G4Step* step                      ,
-                                     G4TouchableHistory* /* history */ )
-{
-  if( 0 == step ) { return false ; }
+bool GaussSensPlaneDet::ProcessHits(G4Step* step,
+                                    G4TouchableHistory* /* history */) {
+  if (0 == step) {
+    return false;
+  }
   ///
-  const G4Track*              const track    = step     -> GetTrack      () ;
-  const int                         trackID  = track    -> GetTrackID    () ;
-  const G4ParticleDefinition* const particle = track    -> GetDefinition () ;
-  const double                      charge   = particle -> GetPDGCharge  () ;
+  const G4Track* const track = step->GetTrack();
+  const int trackID = track->GetTrackID();
+  const G4ParticleDefinition* const particle = track->GetDefinition();
+  const double charge = particle->GetPDGCharge();
 
-  const G4StepPoint* const          pre      = step    -> GetPreStepPoint  () ;
-  const G4StepPoint* const          post     = step    -> GetPostStepPoint () ;
+  const G4StepPoint* const pre = step->GetPreStepPoint();
+  const G4StepPoint* const post = step->GetPostStepPoint();
 
   // make hit only at first(last?) entry
-  if ( oneEntry() && pre -> GetPhysicalVolume() == post -> GetPhysicalVolume() )
-    { return false ; }                                               // RETURN
+  if (oneEntry() && pre->GetPhysicalVolume() == post->GetPhysicalVolume()) {
+    return false;
+  }  // RETURN
 
   // apply the cuts on energy
-  const double                       eKine     = pre   -> GetKineticEnergy  () ;
-
-  if      ( particle == G4Gamma::    Gamma     () && eKine < cutForPhoton   () )
-    { return false ; }                                               // RETURN
-  else if ( particle == G4Electron:: Electron  () && eKine < cutForElectron () )
-    { return false ; }                                               // RETURN
-  else if ( particle == G4Positron:: Positron  () && eKine < cutForPositron () )
-    { return false ; }                                               // RETURN
-  else if ( particle == G4MuonMinus::MuonMinus () && eKine < cutForMuon     () )
-    { return false ; }                                               // RETURN
-  else if ( particle == G4MuonPlus:: MuonPlus  () && eKine < cutForMuon     () )
-    { return false ; }                                               // RETURN
-  else if ( 0 != charge                           && eKine < cutForCharged  () )
-    { return false ; }                                               // RETURN
-  else if (                                          eKine < cutForNeutral  () )
-    { return false ; }                                               // RETURN
+  const double eKine = pre->GetKineticEnergy();
+
+  if (particle == G4Gamma::Gamma() && eKine < cutForPhoton()) {
+    return false;
+  }  // RETURN
+  else if (particle == G4Electron::Electron() && eKine < cutForElectron()) {
+    return false;
+  }  // RETURN
+  else if (particle == G4Positron::Positron() && eKine < cutForPositron()) {
+    return false;
+  }  // RETURN
+  else if (particle == G4MuonMinus::MuonMinus() && eKine < cutForMuon()) {
+    return false;
+  }  // RETURN
+  else if (particle == G4MuonPlus::MuonPlus() && eKine < cutForMuon()) {
+    return false;
+  }  // RETURN
+  else if (0 != charge && eKine < cutForCharged()) {
+    return false;
+  }  // RETURN
+  else if (eKine < cutForNeutral()) {
+    return false;
+  }  // RETURN
 
   // check the status of the track
-  GaussTrackInformation* info =
-    gaussTrackInformation( track->GetUserInformation() );
-  if( 0 == info )
-    { Error("Invalid Track information") ; return false ; }     // RETURN
+  auto info = GaussinoTrackInformation::Get();
+  if (!info) {
+    error("Invalid Track information");
+    return false;
+  }  // RETURN
 
   // ID of the track to be stored
   const int sTrackID =
-    keepLinks        () ? trackID :
-    info->toBeStored () ? trackID : track -> GetParentID () ;
+      keepLinks() ? trackID
+                  : info->storeTruth() ? trackID : track->GetParentID();
 
   // create new hit
-  GaussSensPlaneHit* hit =
-    new GaussSensPlaneHit
-    ( sTrackID                                           ,
-      LHCb::ParticleID       ( particle -> GetPDGEncoding () ) ,
-      HepLorentzVector ( pre      -> GetPosition    () ,
-                         pre      -> GetGlobalTime  () ) ,
-      HepLorentzVector ( pre      -> GetMomentum    () ,
-                         pre      -> GetTotalEnergy () ) ) ;
+  GaussSensPlaneHit* hit = new GaussSensPlaneHit(
+      sTrackID, LHCb::ParticleID(particle->GetPDGEncoding()),
+      HepLorentzVector(pre->GetPosition(), pre->GetGlobalTime()),
+      HepLorentzVector(pre->GetMomentum(), pre->GetTotalEnergy()));
 
   // add it into collection
-  m_collection -> insert ( hit    ) ;
+  m_collection->insert(hit);
 
   // update the track information
-  if( trackID == sTrackID ) { info->addToHits( hit ) ; }
+  if (trackID == sTrackID) {
+    info->addToHits(hit);
+  }
 
-  return true ;
+  return true;
 }
 
-// ============================================================================
-// The END
-// ============================================================================
+#include "GiGaMTFactories/GiGaMTG4SensDetFactory.h"
+
+typedef GiGaMTG4SensDetFactory<GaussSensPlaneDet> PlaneBaseFAC;
+class GaussSensPlaneDetFAC : public PlaneBaseFAC {
+  Gaudi::Property<bool> m_requireEDep{
+      this, "RequireEDep", true, "Hits must have non-zero Energy deposition"};
+
+  Gaudi::Property<bool> m_keepLinks{this, "KeepAllLinks", false};
+  Gaudi::Property<bool> m_oneEntry{this, "OneEntry", true};
+  Gaudi::Property<double> m_cutForPhoton{this, "CutForPhoton", 50 * CLHEP::MeV};
+  Gaudi::Property<double> m_cutForElectron{this, "CutForElectron",
+                                           10 * CLHEP::MeV};
+  Gaudi::Property<double> m_cutForPositron{this, "CutForPositron",
+                                           10 * CLHEP::MeV};
+  Gaudi::Property<double> m_cutForMuon{this, "CutForMuon", -1 * CLHEP::MeV};
+  Gaudi::Property<double> m_cutForCharged{this, "CutForCharged",
+                                          10 * CLHEP::MeV};
+  Gaudi::Property<double> m_cutForNeutral{this, "CutForNeutral",
+                                          10 * CLHEP::MeV};
+
+  public:
+  using PlaneBaseFAC::PlaneBaseFAC;
+  GaussSensPlaneDet* construct() const override {
+    auto tmp = PlaneBaseFAC::construct();
+    tmp->m_keepLinks = m_keepLinks;
+    tmp->m_oneEntry = m_oneEntry;
+    tmp->m_cutForPhoton = m_cutForPhoton;
+    tmp->m_cutForElectron = m_cutForElectron;
+    tmp->m_cutForPositron = m_cutForPositron;
+    tmp->m_cutForMuon = m_cutForMuon;
+    tmp->m_cutForCharged = m_cutForCharged;
+    tmp->m_cutForNeutral = m_cutForNeutral;
+    return tmp;
+  }
+};
+
+DECLARE_COMPONENT_WITH_ID(GaussSensPlaneDetFAC, "GaussSensPlaneDet")
diff --git a/Sim/GaussCalo/src/GaussSensPlaneDet.h b/Sim/GaussCalo/src/GaussSensPlaneDet.h
index 8b28722b0..077cd4485 100755
--- a/Sim/GaussCalo/src/GaussSensPlaneDet.h
+++ b/Sim/GaussCalo/src/GaussSensPlaneDet.h
@@ -1,6 +1,4 @@
-// $Id: GaussSensPlaneDet.h,v 1.4 2007-03-18 21:33:19 gcorti Exp $
-#ifndef       GAUSS_GaussSensPlaneDet_H
-#define       GAUSS_GaussSensPlaneDet_H 1
+#pragma once
 
 // GaudiKernel
 // Ntuple Svc
@@ -8,12 +6,11 @@
 #include "GaudiKernel/INTupleSvc.h"
 #include "GaudiKernel/NTuple.h"
 
-// GiGa
-#include "GiGa/GiGaSensDetBase.h"
-
+#include "Geant4/G4VSensitiveDetector.hh"
 // local
 #include "CaloHit.h"
-
+#include "GaussSensPlaneHit.h"
+#include "GiGaMTCore/IGiGaMessage.h"
 
 /** @class GaussSensPlaneDet GaussSensPlaneDet.h GaussSensPlaneDet.h
  *
@@ -21,33 +18,12 @@
  *  @date    23/01/2001
  */
 
-class GaussSensPlaneDet: public GiGaSensDetBase
-{
+class GaussSensPlaneDet : public G4VSensitiveDetector,
+                          public virtual GiGaMessage {
   /// friend factory
   //  friend class GiGaFactory<GaussSensPlaneDet>;
 
-public :
-
-  /** standard initialization (Gaudi)
-   *  @see GiGaSensDetBase
-   *  @see GiGaBase
-   *  @see   AlgTool
-   *  @see  IAlgTool
-   *  @return status code
-   */
-  StatusCode initialize   () override;
-
-  /** standard finalization (Gaudi)
-   *  @see GiGaSensDetBase
-   *  @see GiGaBase
-   *  @see   AlgTool
-   *  @see  IAlgTool
-   *  @return status code
-   */
-  StatusCode finalize    () override;
-
-public:
-
+  public:
   /** process the hit.
    *  The method is invoked by G4 for each step in the
    *  sensitive detector. This implementation performs the
@@ -66,106 +42,79 @@ public:
    *  @param history  pointert to touchable history
    *  @attention One should not redefine this method for specific sub-detectors.
    */
-  bool ProcessHits
-  ( G4Step*             step    ,
-    G4TouchableHistory* history ) override;
+  bool ProcessHits(G4Step* step, G4TouchableHistory* history) override;
 
   /** method from G4
    *  (Called at the begin of each event)
    *  @see G4VSensitiveDetector
    *  @param HCE pointer to hit collection of current event
    */
-  void Initialize( G4HCofThisEvent* HCE ) override;
+  void Initialize(G4HCofThisEvent* HCE) override;
 
   /** method from G4
    *  (Called at the end of each event)
    *  @see G4VSensitiveDetector
    *  @param HCE pointer to hit collection of current event
    */
-  void EndOfEvent( G4HCofThisEvent* HCE ) override;
-
+  void EndOfEvent(G4HCofThisEvent* HCE) override;
 
-  /** standard constructor
-   *  @see GiGaSensDetBase
-   *  @see GiGaBase
-   *  @see AlgTool
-   *  @param type type of the object (?)
-   *  @param name name of the object
-   *  @param parent  pointer to parent object
-   */
-  GaussSensPlaneDet
-  ( const std::string& type   ,
-    const std::string& name   ,
-    const IInterface*  parent ) ;
+  GaussSensPlaneDet(const std::string& name);
 
   /// destructor (virtual and protected)
-  virtual ~GaussSensPlaneDet() {};
-
-protected:
+  virtual ~GaussSensPlaneDet(){};
 
+  protected:
   /// keep all original links to G4Tracks/MCParticles
-  inline bool   keepLinks       () const { return m_keepLinks       ; }
+  inline bool keepLinks() const { return m_keepLinks; }
   /// only one entry ?
-  inline bool   oneEntry        () const { return m_oneEntry        ; }
+  inline bool oneEntry() const { return m_oneEntry; }
 
   /// cut for photons to create hit
-  inline double cutForPhoton    () const { return m_cutForPhoton    ; }
+  inline double cutForPhoton() const { return m_cutForPhoton; }
 
   /// cut for e-   to create hit
-  inline double cutForElectron  () const { return m_cutForElectron  ; }
+  inline double cutForElectron() const { return m_cutForElectron; }
 
   /// cut for e+   to create hit
-  inline double cutForPositron  () const { return m_cutForPositron  ; }
+  inline double cutForPositron() const { return m_cutForPositron; }
 
   /// cut for muon to create hit
-  inline double cutForMuon      () const { return m_cutForMuon      ; }
+  inline double cutForMuon() const { return m_cutForMuon; }
 
   /// cut for other charged particle to create hit
-  inline double cutForCharged   () const { return m_cutForCharged   ; }
+  inline double cutForCharged() const { return m_cutForCharged; }
 
   /// cut for othe rneutral particle to create hit
-  inline double cutForNeutral   () const { return m_cutForNeutral   ; }
-
-private:
+  inline double cutForNeutral() const { return m_cutForNeutral; }
 
+  private:
   // no default constructor
-  GaussSensPlaneDet() ;
+  GaussSensPlaneDet();
   // no copy constructor
-  GaussSensPlaneDet           ( const GaussSensPlaneDet& );
+  GaussSensPlaneDet(const GaussSensPlaneDet&);
   // no assignement
-  GaussSensPlaneDet& operator=( const GaussSensPlaneDet& ) ;
-
-protected:
+  GaussSensPlaneDet& operator=(const GaussSensPlaneDet&);
 
-  std::string                   m_collectionName ;
-  GaussSensPlaneHitsCollection* m_collection     ;
+  protected:
+  GaussSensPlaneHitsCollection* m_collection{nullptr};
 
-  bool   m_keepLinks       ;
-  bool   m_oneEntry        ;
+  public:
+  bool m_keepLinks{false};
+  bool m_oneEntry{true};
 
-  double m_cutForPhoton    ;
-  double m_cutForElectron  ;
-  double m_cutForPositron  ;
-  double m_cutForMuon      ;
-  double m_cutForCharged   ;
-  double m_cutForNeutral   ;
-
-private:
+  double m_cutForPhoton{50 * CLHEP::MeV};
+  double m_cutForElectron{10 * CLHEP::MeV};
+  double m_cutForPositron{10 * CLHEP::MeV};
+  double m_cutForMuon{-1 * CLHEP::MeV};
+  double m_cutForCharged{10 * CLHEP::MeV};
+  double m_cutForNeutral{10 * CLHEP::MeV};
 
+  private:
   // final statistics
-  bool   m_stat    ;
-  long   m_events  ;
-  double m_hits    ;
-  double m_hits2   ;
-  double m_hitsMin ;
-  double m_hitsMax ;
-
+  bool m_stat{true};
+  long m_events{0};
+  double m_hits{0};
+  double m_hits2{0};
+  double m_hitsMin{1.e+10};
+  double m_hitsMax{-1.e+10};
 };
-// ============================================================================
-
-
-// ============================================================================
-// The END
-// ============================================================================
-#endif  ///< GAUSSCALO_GaussSensPlaneDet_H
-// ============================================================================
diff --git a/Sim/GaussCalo/src/GaussSensPlaneHit.cpp b/Sim/GaussCalo/src/GaussSensPlaneHit.cpp
index 246eb7b40..9132b349a 100755
--- a/Sim/GaussCalo/src/GaussSensPlaneHit.cpp
+++ b/Sim/GaussCalo/src/GaussSensPlaneHit.cpp
@@ -1,22 +1,3 @@
-// $Id: GaussSensPlaneHit.cpp,v 1.4 2006-01-17 15:52:57 odescham Exp $
-// ============================================================================
-// CVS tag $Name: not supported by cvs2svn $
-// ============================================================================
-// $Log: not supported by cvs2svn $
-// Revision 1.3  2004/12/14 14:53:18  gcorti
-// fix for compilation
-//
-// Revision 1.2  2004/01/14 13:38:10  ranjard
-// v6r0 - fix to be used with Gaudi v14r0
-//
-// Revision 1.1  2003/07/07 16:09:39  ibelyaev
-//  add Calorimeter Sensitive Palne hits and the converter
-//
-// ============================================================================
-// Include files
-// ============================================================================
-// from GiGa
-#include "GiGa/GiGaUtil.h"
 // Geant4
 #include "Geant4/G4Allocator.hh"
 // local
@@ -35,27 +16,7 @@ using CLHEP::HepLorentzVector;
  */
 // ============================================================================
 
-namespace GaussSensPlaneHitLocal
-{
-  // ==========================================================================
-  /** @var  s_Allocator
-   *  allocator to make more efficient creation delete
-   *  of GaussSensPlaneHits objects
-   */
-  // ==========================================================================
-  G4Allocator<GaussSensPlaneHit>            s_Allocator ;
-  // ==========================================================================
-
-  // ==========================================================================
-  /** @var s_Counter
-   *  statsic instace counter for all functions
-   */
-  // ==========================================================================
-#ifdef GIGA_DEBUG
-  static GiGaUtil::InstanceCounter<GaussSensPlaneHit> s_Counter   ;
-#endif
-  // ==========================================================================
-}
+G4ThreadLocal G4Allocator<GaussSensPlaneHit>* aGaussSensPlaneHitAllocator{nullptr};
 
 
 // ============================================================================
@@ -70,29 +31,12 @@ GaussSensPlaneHit::GaussSensPlaneHit
   const LHCb::ParticleID&       pid      ,
   const HepLorentzVector& position ,
   const HepLorentzVector& momentum )
-  : GaussHitBase ()
+  : Gaussino::HitBase()
   , m_pid        ( pid      )
   , m_position   ( position )
   , m_momentum   ( momentum )
 {
   setTrackID ( track ) ;
-  // ==========================================================================
-#ifdef GIGA_DEBUG
-  GaussSensPlaneHitLocal::s_Counter.increment () ;
-#endif
-  // ==========================================================================
-}
-
-// ============================================================================
-/// destructor
-// ============================================================================
-GaussSensPlaneHit::~GaussSensPlaneHit()
-{
-  // ==========================================================================
-#ifdef GIGA_DEBUG
-  GaussSensPlaneHitLocal::s_Counter.decrement () ;
-#endif
-  // ==========================================================================
 }
 
 // ============================================================================
@@ -102,7 +46,7 @@ GaussSensPlaneHit::~GaussSensPlaneHit()
 // ============================================================================
 GaussSensPlaneHit::GaussSensPlaneHit
 ( const GaussSensPlaneHit& hit )
-  : GaussHitBase ( hit             )
+  : Gaussino::HitBase( hit             )
   , m_pid        ( hit.pid      () )
   , m_position   ( hit.position () )
   , m_momentum   ( hit.momentum () )
@@ -113,27 +57,3 @@ GaussSensPlaneHit::GaussSensPlaneHit
 #endif
   // ==========================================================================
 }
-
-
-// ============================================================================
-/// overloaded 'new' oerator
-// ============================================================================
-void* GaussSensPlaneHit::operator new(size_t)
-{
-  void *hit  ;
-  hit = (void *) GaussSensPlaneHitLocal::s_Allocator.MallocSingle () ;
-  return hit ;
-}
-
-
-// ============================================================================
-/// overloaded 'delete' oerator
-// ============================================================================
-void GaussSensPlaneHit::operator delete( void *hit )
-{ GaussSensPlaneHitLocal::s_Allocator.FreeSingle( (GaussSensPlaneHit*) hit ); }
-
-
-// ============================================================================
-// The END
-// ============================================================================
-
diff --git a/Sim/GaussCalo/src/GaussSensPlaneHit.h b/Sim/GaussCalo/src/GaussSensPlaneHit.h
index 19daaf1f8..372a0aa53 100755
--- a/Sim/GaussCalo/src/GaussSensPlaneHit.h
+++ b/Sim/GaussCalo/src/GaussSensPlaneHit.h
@@ -1,17 +1,4 @@
-// $Id: GaussSensPlaneHit.h,v 1.3 2006-01-17 15:52:57 odescham Exp $
-// ============================================================================
-// CVS tag $Name: not supported by cvs2svn $
-// ============================================================================
-// $Log: not supported by cvs2svn $
-// Revision 1.2  2004/01/14 13:38:10  ranjard
-// v6r0 - fix to be used with Gaudi v14r0
-//
-// Revision 1.1  2003/07/07 16:09:39  ibelyaev
-//  add Calorimeter Sensitive Palne hits and the converter
-//
-// ============================================================================
-#ifndef GAUSSTOOLS_GAUSSSENSITIVEPLANEHIT_H
-#define GAUSSTOOLS_GAUSSSENSITIVEPLANEHIT_H 1
+#pragma once
 // ============================================================================
 // Include files
 // ============================================================================
@@ -20,7 +7,7 @@
 // Event
 #include "Kernel/ParticleID.h"
 // GaussTools
-#include "GaussTools/GaussHitBase.h"
+#include "GiGaMTCore/GaussHitBase.h"
 // Geant4
 #include "Geant4/G4THitsCollection.hh"
 // ============================================================================
@@ -32,7 +19,7 @@
  *  @author Vanya BELYAEV Ivan.Belyaev@itep.ru
  *  @date   2003-07-07
  */
-class GaussSensPlaneHit : public GaussHitBase
+class GaussSensPlaneHit : public Gaussino::HitBase
 {
 public :
   /// the actual type of TrackID
@@ -63,9 +50,6 @@ public:
   GaussSensPlaneHit
   ( const GaussSensPlaneHit& hit ) ;
 
-  /// destructor
-  virtual ~GaussSensPlaneHit() ;
-
   /// access to actual particle ID
   inline const LHCb::ParticleID&       pid         () const { return m_pid      ; }
   // set new value for particle ID
@@ -104,59 +88,15 @@ private:
 typedef G4THitsCollection<GaussSensPlaneHit>
 GaussSensPlaneHitsCollection ;
 
-// ============================================================================
-/** @fn  gaussSensPlaneHit
- *  Fast cast of G4VHit interface to concrete Gauss implementation
- *  @param  g4   pointer to G4VHit interface
- *  @return cast (dynamic or static) to GaussSensitivelaneHit
- *  @author  Vanya Belyaev Ivan.Belyaev@itep.ru
- *  @date    2002-12-07
- */
-// ============================================================================
-inline GaussSensPlaneHit*
-gaussSensPlaneHitHit ( G4VHit* g4 )
-{
-  GiGaUtil::FastCast<G4VHit,GaussSensPlaneHit> cast ;
-  return cast( g4 );
-}
-
+extern G4ThreadLocal G4Allocator<GaussSensPlaneHit>* aGaussSensPlaneHitAllocator;
 
-// ============================================================================
-/** @fn  gaussSensPlaneHit
- *  Fast cast of GaussHitBaseto concrete Gauss implementation
- *  @param  g4   pointer to GaussHitBase interface
- *  @return cast (dynamic or static) to GaussSensPlaneHit
- *  @author  Vanya Belyaev Ivan.Belyaev@itep.ru
- *  @date    2002-12-07
- */
-// ============================================================================
-inline GaussSensPlaneHit*
-gaussSensPlaneHitHit ( GaussHitBase* g4 )
-{
-  GiGaUtil::FastCast<GaussHitBase,GaussSensPlaneHit> cast ;
-  return cast( g4 );
+inline void* GaussSensPlaneHit::operator new(size_t) {
+  if (!aGaussSensPlaneHitAllocator) {
+    aGaussSensPlaneHitAllocator = new G4Allocator<GaussSensPlaneHit>;
+  }
+  return (void*)aGaussSensPlaneHitAllocator->MallocSingle();
 }
 
-
-// ============================================================================
-/** @fn  caloHits
- *  Fast cast of G4VHitsCollection interface to concrete Gauss implementation
- *  @param  g4   pointer to G4VHitsCollection interface
- *  @return cast (dynamic or static) to CaloHitsColelction*
- *  @author  Vanya Belyaev Ivan.Belyaev@itep.ru
- *  @date    2002-12-07
- */
-// ============================================================================
-inline GaussSensPlaneHitsCollection*
-gaussSensPlaneHits ( G4VHitsCollection* g4 )
-{
-  GiGaUtil::FastCast<G4VHitsCollection,GaussSensPlaneHitsCollection> cast ;
-  return cast( g4 );
+inline void GaussSensPlaneHit::operator delete(void* aHit) {
+  aGaussSensPlaneHitAllocator->FreeSingle((GaussSensPlaneHit*)aHit);
 }
-
-
-// ============================================================================
-// The END
-// ============================================================================
-#endif // GAUSSTOOLS_GAUSSSENSITIVEPLANEHIT_H
-// ============================================================================
diff --git a/Sim/GaussCalo/src/SpdPrsSensDet.h b/Sim/GaussCalo/src/SpdPrsSensDet.h
index 8854da3e7..b5dd98f22 100755
--- a/Sim/GaussCalo/src/SpdPrsSensDet.h
+++ b/Sim/GaussCalo/src/SpdPrsSensDet.h
@@ -22,7 +22,7 @@ class DeCalorimeter;  // CaloDet
  */
 
 template <typename CELLGETTER>
-class SpdPrsSensDet : public CaloSensDet<CELLGETTER>, public virtual CELLGETTER {
+class SpdPrsSensDet : public CaloSensDet<CELLGETTER> {
   public:
   using base_class = CaloSensDet<CELLGETTER>;
   using base_class::CaloSensDet;
-- 
GitLab


From f495d6a8181c6972e970ac1f8caef26e520abed9 Mon Sep 17 00:00:00 2001
From: Dominik Muller <dominik.muller@cern.ch>
Date: Thu, 18 Jul 2019 11:44:30 +0200
Subject: [PATCH 17/90] Cleaned main Gauss configuration

---
 Sim/Gauss/python/Gauss/Configuration.py | 4684 +----------------------
 1 file changed, 145 insertions(+), 4539 deletions(-)

diff --git a/Sim/Gauss/python/Gauss/Configuration.py b/Sim/Gauss/python/Gauss/Configuration.py
index 2195f8c2b..a0e84b979 100755
--- a/Sim/Gauss/python/Gauss/Configuration.py
+++ b/Sim/Gauss/python/Gauss/Configuration.py
@@ -3,274 +3,66 @@ High level configuration tools for Gauss
 Beampipe configuration added.
 """
 __version__ = "$Id: Configuration.py,v 1.30 2010/05/09 18:14:28 gcorti Exp $"
-__author__  = "Gloria Corti <Gloria.Corti@cern.ch>"
+__author__ = "Gloria Corti <Gloria.Corti@cern.ch>"
 
-from Gaudi.Configuration import *
-import GaudiKernel.ProcessJobOptions
-from GaudiKernel import SystemOfUnits
+from Gaudi.Configuration import log, GaudiSequencer, FileCatalog
+from Gaudi.Configuration import ApplicationMgr
 from Configurables import LHCbConfigurableUser, LHCbApp, SimConf
+from Configurables import Gaussino
+from Gauss.Geometry import LHCbGeo
+from Gauss import G4Physics
 
 
-# CRJ - Its un-neccessary to import everythting by default. Better to
-#       import as and when you need it ...
-from Configurables import ( EventClockSvc, FakeEventTime )
-from Configurables import ( GenInit, Generation, MinimumBias, Inclusive,
-#from Configurables import ( GenInit, Generation,
-# Double imports
-                            SignalPlain, SignalRepeatedHadronization,
-                            SignalForcedFragmentation, StandAloneDecayTool,
-                            Special,
-                            PythiaProduction, HijingProduction,
-                            CRMCProduction,
-# Not used
-                            CollidingBeams, FixedTarget,
-                            BeamSpotSmearVertex, FlatZSmearVertex,
-                            EvtGenDecay )
-from Configurables import ( SimInit, GaussGeo, GiGaGeo, GiGaInputStream, GiGa,
-                            GiGaDataStoreAlgorithm,
-                            GiGaPhysListModular, GiGaRunActionSequence,
-                            TrCutsRunAction, GiGaRunActionCommand,
-                            GiGaEventActionSequence, GiGaMagFieldGlobal,
-                            GiGaTrackActionSequence, GaussPostTrackAction,
-                            GiGaStepActionSequence, SimulationSvc,
-                            GiGaFieldMgr, GiGaRunManager, GiGaSetSimAttributes,
-                            GiGaPhysConstructorOp, GiGaPhysConstructorHpd,
-                            SpdPrsSensDet, EcalSensDet, HcalSensDet,
-                            GaussSensPlaneDet )
-from Configurables import ( GenerationToSimulation, GiGaFlushAlgorithm,
-                            GiGaCheckEventStatus, SimulationToMCTruth,
-                            GiGaGetEventAlg, GiGaGetHitsAlg,
-                            GetTrackerHitsAlg, GetCaloHitsAlg,
-                            GetMCRichHitsAlg, GetMCRichOpticalPhotonsAlg,
-                            GetMCRichSegmentsAlg, #GetMCRichTracksAlg,
-                            Rich__MC__MCPartToMCRichTrackAlg,
-                            Rich__MC__MCRichHitToMCRichOpPhotAlg)
-from Configurables import ( GenMonitorAlg, MuonHitChecker, MCTruthMonitor,
-                            VeloGaussMoni, MCHitMonitor, MCCaloMonitor,
-                            DumpHepMC )
-from Configurables import ( PackMCParticle, PackMCVertex,
-                            UnpackMCParticle, UnpackMCVertex,
-                            CompareMCParticle, CompareMCVertex )
-
-# Various options for the RICH
-from Configurables import (GaussRICHConf, GaussCherenkovConf)
-
-# All GaussRedecay includes
-from Configurables import ( GaussRedecay, GaussRedecayCopyToService,
-                            GaussRedecayRetrieveFromService,
-                            GaussRedecayPrintMCParticles,
-                            GaussRedecayCtrFilter,
-                            GaussRedecaySorter,
-                            GaussHepMCSplitter,
-                            GaussRedecayMergeAndClean)
-
-from DetCond.Configuration import CondDB
-
-## @class Gauss
-#  Configurable for Gauss application
-#  @author Gloria Corti <Gloria.Corti@cern.ch>
-#  @date   2009-07-13
-
 class Gauss(LHCbConfigurableUser):
 
-    __knownDetectors__ = [
-        'velo', 'puveto', 'vp',
-        'tt' , 'ut',
-        'it' , 'sl',
-        'ot' , 'ft', 'ft-noshield',
-        'rich',  'rich1', 'rich2', 'torch' ,
-        'calo',  'spd', 'prs', 'ecal', 'hcal' ,
-        'muon' ,
-        'magnet',
-        'rich1pmt', 'rich2pmt',
-        'hc'
-#        'bcm', 'bls'
-        ]
-
-    ## Possible used Configurables
-    __used_configurables__ = [ LHCbApp, SimConf,
-                               (GaussRICHConf,None),
-                               (GaussCherenkovConf,None)
-                               ]
+    # Possible used Configurables
+    __used_configurables__ = [LHCbApp, SimConf, Gaussino,
+                              LHCbGeo, G4Physics
+                              # (GaussRICHConf,None),
+                              # (GaussCherenkovConf,None)
+                              ]
 
-    ## Map to contain PDG ids for beam particles
-    __ion_pdg_id__ = { 'Pb': 1000822080 , 'Ar': 1000180400 , 'p': 2212 , 'Ne': 1000100200 , 'He': 1000020040 , 'Kr': 1000360840 ,
-                       'Xe': 1000541320 }
-
-    ## Steering options
+    # Steering options
     __slots__ = {
-        "Histograms"        : "DEFAULT"
-        ,"DatasetName"       : "Gauss"
-        ,"DataType"          : ""
-        # Simple lists of sub detectors
-        ,"DetectorGeo"       : {"Detectors": ['PuVeto', 'Velo', 'TT', 'IT', 'OT', 'Rich1', 'Rich2', 'Spd', 'Prs', 'Ecal', 'Hcal', 'Muon', 'Magnet'] }
-        ,"DetectorSim"       : {"Detectors": ['PuVeto', 'Velo', 'TT', 'IT', 'OT', 'Rich1', 'Rich2', 'Spd', 'Prs', 'Ecal', 'Hcal', 'Muon', 'Magnet'] }
-        ,"DetectorMoni"      : {"Detectors": ['PuVeto', 'Velo', 'TT', 'IT', 'OT', 'Rich1', 'Rich2', 'Spd', 'Prs', 'Ecal', 'Hcal', 'Muon'] }
-        ,"SpilloverPaths"    : []
-        ,"PhysicsList"       : {"Em":'NoCuts', "Hadron":'FTFP_BERT', "GeneralPhys":True, "LHCbPhys":True, "Other": '' }
-        ,"UserProductionCuts": {}
-        ,"UserTrackingCuts"  : {}
-        ,"DeltaRays"         : True
-        ,"RICHRandomHits"    : False
-        ,"Phases"            : ["Generator","Simulation"] # The Gauss phases to include in the SIM file
-        ,"BeamMomentum"      : 3.5*SystemOfUnits.TeV
-        ,"BeamHCrossingAngle" : -0.520*SystemOfUnits.mrad
-        ,"BeamVCrossingAngle" : 0.0
-        ,"BeamEmittance"     : 0.0037*SystemOfUnits.mm
-        ,"BeamBetaStar"      : 3.1*SystemOfUnits.m
-        ,"BeamLineAngles"    : [ -0.075*SystemOfUnits.mrad,
-                                  0.035*SystemOfUnits.mrad ]
-        ,"InteractionPosition" : [  0.459*SystemOfUnits.mm ,
-                                   -0.015*SystemOfUnits.mm ,
-                                    0.5*SystemOfUnits.mm ]
-        ,"BunchRMS"          : 82.03*SystemOfUnits.mm
-        ,"Luminosity"        : 0.247*(10**30)/(SystemOfUnits.cm2*SystemOfUnits.s)
-        ,"TotalCrossSection" : 91.1*SystemOfUnits.millibarn
-        ,"OutputType"        : 'SIM'
-        ,"Production"        : 'PHYS'
-        ,"EnablePack"        : True
-        ,"DataPackingChecks" : True
-        ,"WriteFSR"          : True
-        ,"MergeGenFSR"       : False
-        ,"Debug"             : False
-        ,"BeamPipe" : "BeamPipeOn" # _beamPipeSwitch = 1
-        ,"ReplaceWithGDML"   : [ { "volsToReplace" : [], "gdmlFile" : "", 'volsToInstrument' : {} } ]
-        #,"BeamPipe" : "BeamPipeOff"  # _beamPipeSwitch = 0
-        #,"BeamPipe" : "BeamPipeInDet"  # _beamPipeSwitch = -1
-        ,"RandomGenerator"   : 'Ranlux'
-        ## Add properties for fixed target and heavy ion simulation
-        ## energy of the beam 2 (beam 1 is taken from the BeamMomentum property
-        ## if this energy is 0, or if BeamMomentum is 0, it is fixed target simulation
-        , "B2Momentum" : 3.5*SystemOfUnits.TeV
-        ## type of particle in the beam or in the fixed target
-        , "B1Particle" : 'p'
-        , "B2Particle" : 'p'
-        , "UseGaussGeo" : True
-        , "Redecay" : {"N": 100, 'active': False, 'rd_mode': 1}
-        , "CurrentRICHSimRunOption" : 'GTB'
-        , "UpgradeRICHSimRunOption"  : 'GTB'
-        , "SplitSim" : False
-        , "PostSimFilters"  : []
-        , "SaveGDML"  : ""
-      }
+        # The Gauss phases to include in the SIM file
+        "Histograms": "DEFAULT",
+        "DatasetName": "Gauss",
+        "Phases": ["Generator", "Simulation"],
+        "DataType": "", "SpilloverPaths": [],
+        "OutputType": 'SIM', "EnablePack": True,
+        "DataPackingChecks": True,
+        "WriteFSR": False,
+        "MergeGenFSR": False,
+        "Debug": False,
+        "ForceRandomEngine": 'NONE'
+        }
 
-    _detectorsDefaults = {"Detectors": ['PuVeto', 'Velo', 'TT', 'IT', 'OT', 'Rich1', 'Rich2', 'Spd', 'Prs', 'Ecal', 'Hcal', 'Muon', 'Magnet'] }
     _propertyDocDct = {
-        'Histograms'     : """ Type of histograms: ['NONE','DEFAULT'] """
-       ,'DatasetName'    : """ String used to build output file names """
-       ,"DataType"       : """ Must specify 'Upgrade' for upgrade simulations, otherwise not used """
-       ,"DetectorGeo"    : """ Dictionary specifying the detectors to take into account in Geometry """
-       ,"DetectorSim"    : """ Dictionary specifying the detectors to simulated (should be in geometry): """
-       ,"DetectorMoni"   : """ Dictionary specifying the detectors to monitor (should be simulated) :"""
-       ,'SpilloverPaths' : """ Spillover paths to fill: [] means no spillover, otherwise put ['Next', 'Prev', 'PrevPrev'] """
-       ,'PhysicsList'    : """ Name of physics modules to be passed 'Em':['Std','Opt1,'Opt2','Opt3','NoCuts','LHCb', 'LHCbNoCuts', 'LHCbOldForE', 'LHCbNoCutsOldForE', 'LHCbTest', 'LHCbTestNoCut' ], 'GeneralPhys':[True,False], 'Hadron':['QGSP_BERT','QGSP_BERT_HP','QGSP_FTFP_BERT','FTFP_BERT','FTFP_BERT_HP'], 'LHCbPhys': [True,False], 'Other': [''] """
-       ,'UserProductionCuts' : """ A dictionary of particle production cuts, e.g {'CutForElectron': 0.1 * SystemOfUnits.mm}. Dictionary key naming is same as the  property names of ModularPL """
-       ,'UserTrackingCuts'   : """ A dictionary of tracking cuts, e.g {'MuonTrCut': 0. * SystemOfUnits.MeV}. Dictionary key naming is same as the  property names of TrCutsRunAction """
-       ,"DeltaRays"      : """ Simulation of delta rays enabled (default True) """
-       ,'Phases'         : """ List of phases to run (Generator, Simulation, GenToMCTree) """
-       ,'OutputType'     : """ Output: [ 'NONE', 'GEN', 'XGEN', 'RGEN', 'SIM', 'XSIM' ] (default 'SIM') """
-       ,'Production'     : """ Generation type : ['PHYS', 'PGUN', 'MIB' (default 'PHYS')"""
-       ,'EnablePack'     : """ Flag to turn on or off the packing of the SIM data """
-       ,'DataPackingChecks' : """ Flag to turn on or off the running of some test algorithms to check the quality of the data packing """
-       ,"WriteFSR"       : """Add file summary record, default True"""
-       ,"MergeGenFSR"    : """Flags whether to merge the generator level FSRs"""
-       ,"BeamPipe"       : """Switch for beampipe definition; BeamPipeOn: On everywhere, BeamPipeOff: Off everywhere, BeamPipeInDet: Only in named detectors """
-       ,"ReplaceWithGDML": """Replace a list of specified volumes with GDML description from file provided """
-       ,"RandomGenerator": """Name of randon number generator engine: Ranlux or MTwist"""
-       ,"UseGaussGeo"    : """Use GaussGeo (True: default) or GiGaGeo (False) for geometry conversion"""
-       ,"Redecay"        : """ Dict with redecay settings, default: {'N': 100, 'active': False, 'rd_mode': 1}."""
-       ,"CurrentRICHSimRunOption" : """ GaussRICH run options: ['Formula1', 'GTB', 'SUV','HGV', 'clunker', 'FareFiasco'] (default 'GTB') """
-       ,"UpgradeRICHSimRunOption" : """ GaussCherenkov run options: ['Formula1', 'GTB', 'SUV','HGV', 'clunker' , 'FareFiasco'] (default 'GTB') """
-       , "SplitSim"      : """ Split the simulation phase for gamma-conversion. (default: False)"""
-       ,"PostSimFilters" : """ List of filters that are executed after Geant has run (default: none)"""
-       , "SaveGDML"      : """ Filename to save the geometry in GDML, empty string -> no output (default)"""
+        'Histograms'     : """ Type of histograms: ['NONE','DEFAULT'] """  # NOQA
+       , 'DatasetName'    : """ String used to build output file names """  # NOQA
+       , 'Phases'         : """ List of phases to run (Generator, Simulation, GenToMCTree) """  # NOQA
+       , "DataType"       : """ Must specify 'Upgrade' for upgrade simulations, otherwise not used """  # NOQA
+       , 'SpilloverPaths' : """ Spillover paths to fill: [] means no spillover, otherwise put ['Next', 'Prev', 'PrevPrev'] """  # NOQA
+       , "DeltaRays"      : """ Simulation of delta rays enabled (default True) """  # NOQA
+       , 'OutputType'     : """ Output: [ 'NONE', 'GEN', 'XGEN', 'RGEN', 'SIM', 'XSIM' ] (default 'SIM') """  # NOQA
+       , 'Production'     : """ Generation type : ['PHYS', 'PGUN', 'MIB' (default 'PHYS')"""  # NOQA
+       , 'EnablePack'     : """ Flag to turn on or off the packing of the SIM data """  # NOQA
+       , 'DataPackingChecks' : """ Flag to turn on or off the running of some test algorithms to check the quality of the data packing """  # NOQA
+       , "ForceRandomEngine"   : """Force the random number generator for all AlgSeeders"""  # NOQA
        }
-    KnownHistOptions     = ['NONE','DEFAULT']
-    TrackingSystem       = ['VELO','TT','IT','OT']
-    PIDSystem            = ['RICH','CALO','MUON']
+    KnownHistOptions = ['NONE', 'DEFAULT']
+    TrackingSystem = ['VELO', 'TT', 'IT', 'OT']
+    PIDSystem = ['RICH', 'CALO', 'MUON']
 
-    Run1DataTypes = [ "2009", "2010", "2011", "2012", "2013" ]
-    Run2DataTypes = [ "2015", "2016", "2017", "2018" ]
+    Run1DataTypes = ["2009", "2010", "2011", "2012", "2013"]
+    Run2DataTypes = ["2015", "2016", "2017", "2018"]
 
-    _beamPipeStates = ['beampipeon', 'beampipeoff', 'beampipeindet']
-
-    KnownPostSimFilters    = [ "ConversionFilter" ]
-
-    _incompatibleDetectors = {
-        "Velo"       : [ "Velo", "VP" ],
-        "VeloPuVeto" : [ "PuVeto", "VP" ],
-        "TT"         : [ "TT", "UT" ],
-        "Muon"       : [ "Muon", "MuonNoM1" ],
-        "MuonTorch"  : [ "Muon", "Torch" ]
-        }
-
-    _beamPipeElements = {
-        #"upstreamregion" : [
-        #"/dd/Structure/LHCb/UpstreamRegion/PipeUpstream" ,
-        #"/dd/Structure/LHCb/UpstreamRegion/MBXWHUp" ],
-        #"beforemagnetregion" : [
-        #    "/dd/Structure/LHCb/BeforeMagnetRegion/PipeJunctionBeforeVelo",
-        #    "/dd/Structure/LHCb/BeforeMagnetRegion/BeforeVelo/PipeBeforeVelo",
-        #    "/dd/Structure/LHCb/BeforeMagnetRegion/BeforeVelo/PipeSupportBeforeVelo" ],
-                         "velo" : [
-            "/dd/Structure/LHCb/BeforeMagnetRegion/Velo/DownStreamWakeFieldCone",
-            "/dd/Structure/LHCb/BeforeMagnetRegion/Velo/UpStreamWakeFieldCone",
-            "/dd/Structure/LHCb/BeforeMagnetRegion/Velo/DownstreamPipeSections",
-            "/dd/Structure/LHCb/BeforeMagnetRegion/Velo/VacTank" ],
-                         "rich1" : [
-            "/dd/Structure/LHCb/BeforeMagnetRegion/Rich1/PipeInRich1BeforeSubM",
-            "/dd/Structure/LHCb/BeforeMagnetRegion/Rich1/PipeInRich1SubMaster",
-            "/dd/Structure/LHCb/BeforeMagnetRegion/Rich1/PipeInRich1AfterSubM",
-            "/dd/Structure/LHCb/BeforeMagnetRegion/Rich1/Rich1BeamPipe" ],
-                         "tt" : [
-            "/dd/Structure/LHCb/BeforeMagnetRegion/TT/PipeInTT" ],
-                         "ut" : [
-            "/dd/Structure/LHCb/BeforeMagnetRegion/UT/PipeInUT" ],
-                         "magnet" : [
-            "/dd/Structure/LHCb/MagnetRegion/PipeInMagnet",
-            "/dd/Structure/LHCb/MagnetRegion/PipeSupportsInMagnet" ],
-                         "AfterMagnetRegion" : [
-            "/dd/Structure/LHCb/AfterMagnetRegion/PipeAfterT",
-            "/dd/Structure/LHCb/AfterMagnetRegion/PipeSupportsAfterMagnet" ],
-                         "t" : [
-            "/dd/Structure/LHCb/AfterMagnetRegion/T/PipeInT" ],
-                         "rich2" : [
-            "/dd/Structure/LHCb/AfterMagnetRegion/Rich2/Rich2BeamPipe" ],
-                         "downstreamregion" : [
-            "/dd/Structure/LHCb/DownstreamRegion/PipeDownstream",
-            "/dd/Structure/LHCb/DownstreamRegion/PipeSupportsDownstream",
-            "/dd/Structure/LHCb/DownstreamRegion/PipeBakeoutDownstream" ]
-                         #"aftermuon" : [
-                         #"/dd/Structure/LHCb/DownstreamRegion/AfterMuon/PipeAfterMuon",
-            #"/dd/Structure/LHCb/DownstreamRegion/AfterMuon/MBXWSDown" ]
-        }
-
-    # List of geometry objects which will be converted, it's content is used in
-    # GaussGeo or in GiGaInputStream if GiGaGeo is used for conversion
-    _listOfGeoObjects_ = []
-
-#"""
-#Helper
-#HELPER
-#
-#  ><<     ><<             ><<
-#  ><<     ><<             ><<
-#  ><<     ><<    ><<      ><< >< ><<      ><<     >< ><<<
-#  ><<<<<< ><<  ><   ><<   ><< ><  ><<   ><   ><<   ><<
-#  ><<     ><< ><<<<< ><<  ><< ><   ><< ><<<<< ><<  ><<
-#  ><<     ><< ><          ><< ><< ><<  ><          ><<
-#  ><<     ><<   ><<<<     ><< ><<        ><<<<     ><<<
-#                              ><<
-#
-#"""
-    ##
-    ##
-    def slotName(self,slot) :
+    def slotName(self, slot):
         name = slot
-        if slot == '' : name = "Main"
+        if slot == '':
+            name = "Main"
         return name
 
-
     def isGaussMP(self):
         import argparse
         parser = argparse.ArgumentParser(description='Hello')
@@ -279,4339 +71,153 @@ class Gauss(LHCbConfigurableUser):
         args = parser.parse_known_args()
         return args[0].ncpus != 0
 
-    ##
-    ## Helper functions for spill-over
-    def slot_( self, slot ):
+    def slot_(self, slot):
         if slot != '':
             return slot + '/'
         return slot
 
-    ##
-    def setTrackersHitsProperties( self, alg , det , slot , dd ):
-        alg.MCHitsLocation = '/Event/' + self.slot_(slot) + 'MC/' + det + '/Hits'
-        if det == 'PuVeto':
-            det = 'VeloPu'
-        alg.CollectionName = det + 'SDet/Hits'
-        alg.Detectors = ['/dd/Structure/LHCb/'+dd]
-
-    ##
     def evtMax(self):
         return LHCbApp().evtMax()
 
-    ##
     def eventType(self):
         from Configurables import Generation
         evtType = ''
         if Generation("Generation").isPropertySet("EventType"):
-            evtType = str( Generation("Generation").EventType )
+            evtType = str(Generation("Generation").EventType)
         return evtType
 
     def setLHCbAppDetectors(self):
         from Configurables import LHCbApp
         # If detectors set in LHCbApp then use those
-        if hasattr(LHCbApp(),"Detectors"):
+        if hasattr(LHCbApp(), "Detectors"):
             if not LHCbApp().Detectors:
                 LHCbApp().Detectors = self.getProp("DetectorGeo")["Detectors"]
             else:
-                log.warning("Value of 'LHCbApp().Detectors' already set, using that value: %s" %(LHCbApp().Detectors))
+                log.warning(
+                    "Value of 'LHCbApp().Detectors' already"
+                    "set, using that value: %s" %
+                    (LHCbApp().Detectors))
         return
 
-#"""
-##########################################################################
-##########################################################################
-##########################################################################
-##########################################################################
-##########################################################################
-#"""
-
-
-
-# ><< ><<
-# ><    ><<                                                ><
-# ><     ><<    ><<        ><<     ><<< ><< ><<  >< ><<       >< ><<      ><<
-# ><<< ><     ><   ><<   ><<  ><<   ><<  ><  ><< ><  ><<  ><< ><  ><<   ><   ><<
-# ><     ><< ><<<<< ><< ><<   ><<   ><<  ><  ><< ><   ><< ><< ><   ><< ><<<<< ><<
-# ><      >< ><         ><<   ><<   ><<  ><  ><< ><< ><<  ><< ><< ><<  ><
-# ><<<< ><<    ><<<<      ><< ><<< ><<<  ><  ><< ><<      ><< ><<        ><<<<
-#                                                ><<          ><<
-
-    def validateBeamPipeSwitch ( self, bpString ):
-        import string
-        bpLower = self.getProp("BeamPipe").lower()
-        if bpLower not in self._beamPipeStates:
-            raise RuntimeError("ERROR: BeamPipe configuration '%s' not recognised!" %bpString)
-
-    def removeBeamPipeElements( self, det ):
-        det = det.lower()
-        # Remove beampipe elements in <det> - will be included automatically
-        if det in self._beamPipeElements.keys():
-            for element in self._beamPipeElements[det]:
-                # remove all instances of the element
-                while element in self._listOfGeoObjects_:
-                    self._listOfGeoObjects_.remove(element)
-
-    def removeAllBeamPipeElements( self ):
-        # Remove all beampipe elements
-        for det in self._beamPipeElements.keys():
-            for element in self._beamPipeElements[det]:
-                # remove all instances of the element
-                while element in self._listOfGeoObjects_:
-                    self._listOfGeoObjects_.remove(element)
-
-    def defineBeamPipeGeo ( self, basePieces, detPieces ):
-        # Add all BeamPipe Elements in the BeamPipeElements dictionary
-
-        # Here commences a hack to deal with daft DDDB structure
-        ignoreList = ['ut', 'tt']
-        # decide if TT or UT in dets to simulate
-        ttDetectorList = [det for det in ['UT', 'TT'] if det in self.getProp('DetectorGeo')['Detectors']]
-        # lower strings
-        if ttDetectorList:
-            # lower everything in ttDetectorList
-            ttDetectorList = [det.lower() for det in ttDetectorList]
-            # get the elements to ignore
-            ignoreList = [det for det in ignoreList if det not in ttDetectorList]
-
-        for region in self._beamPipeElements.keys():
-            if region in ignoreList:
-                continue
-            for element in self._beamPipeElements[region]:
-                self._listOfGeoObjects_.append(element)
-
-        # Finally add in the TT or UT beampipe if we're not defining the detectors but want the BP anyway depending on DataType
-        # Nasty and unclean - change the DDDB s.t. it makes sense please!
-        if (
-            ("UT" not in self.getProp("DetectorGeo")["Detectors"])
-            and
-            ("TT" not in self.getProp("DetectorGeo")["Detectors"])
-            ):
-            if self.getProp("DataType") not in ["Upgrade"]:
-                for element in self._beamPipeElements["tt"]:
-                    self._listOfGeoObjects_.append(element)
-            else:
-                for element in self._beamPipeElements["ut"]:
-                    self._listOfGeoObjects_.append(element)
-
+    def propagateSimConf(self):
+        # Propagate properties to SimConf
+        SimConf().setProp("Writer", "GaussTape")
+        self.setOtherProps(
+            SimConf(), [
+                "SpilloverPaths", "EnablePack", "Phases", "DataType"])
+        # if we have post-sim filters, we only want to write if the filter is
+        # passed
+        # if self.getProp("PostSimFilters"):
+        # OutputStream("GaussTape").RequireAlgs.append("PostSimFilterSeq")
 
-    def defineGDMLGeo ( self, geoCnvSvc, gdmlDict ):
+        # Don't want SIM data unpacking enabled in DoD service
+        SimConf().EnableUnpack = False
 
-        # Define the GDML reader tool and add it to the sequence
-        from Configurables import GDMLReader
-        import os
-        gdmlFile = gdmlDict["gdmlFile"]
-        instrumentation = gdmlDict['volsToInstrument'] if 'volsToInstrument' in gdmlDict else {}
-        parsed_instr = {}
+        class dummy:
+            def __init__(self):
+                self.Members = []
 
-        if gdmlFile:
-            gdmlToolName = os.path.splitext(os.path.basename(gdmlFile))[0]
-            gdmlTool = GDMLReader( gdmlToolName,
-                                   FileName = gdmlFile )
-            reader = geoCnvSvc.addTool(gdmlTool, gdmlToolName)
-            import Configurables
-            for vol, instr in instrumentation.items():
-                tool, name, kwargs = instr
-                reader.addTool( getattr(Configurables, tool)(name, **kwargs), name=name )
-                parsed_instr[vol] = tool + "/" + name
-            reader.SensitiveDetectors = parsed_instr
-            geoCnvSvc.GdmlReaders.append(gdmlToolName)
+        packing = dummy()
+        for so in self.defineCrossingList():
+            SimConf().PackingSequencers[so] = packing
 
-            # Remove the corresponding geometry from the Geo.InputStreams
-            for item in [g for g in gdmlDict["volsToReplace"] if g != '']:
-                if item in self._listOfGeoObjects_:
-                    self._listOfGeoObjects_.remove(item)
-                else:
-                    raise RuntimeError("ERROR: Volume not in list of existing volumes, '%s'" %item)
-        else:
-           raise RuntimeError("ERROR: Invalid GDML file provided, '%s'" %gdmlFile)
+        from Gaudi.Configuration import appendPostConfigAction
 
+        def runit():
+            for a in packing.Members:
+                ApplicationMgr().TopAlg += [a]
 
+        appendPostConfigAction(runit)
+        SimConf().SaveHepMC = False
 
-#"""
-#><<         ><<             ><<               ><<<<<     ><<<<<     ><<<<<     ><< ><<
-# ><<       ><<              ><<               ><<   ><<  ><<   ><<  ><<   ><<  ><    ><<
-#  ><<     ><<      ><<      ><<    ><<        ><<    ><< ><<    ><< ><<    ><< ><     ><<
-#   ><<   ><<     ><   ><<   ><<  ><<  ><<     ><<    ><< ><<    ><< ><<    ><< ><<< ><
-#    ><< ><<     ><<<<< ><<  ><< ><<    ><<    ><<    ><< ><<    ><< ><<    ><< ><     ><<
-#     ><<<<      ><          ><<  ><<  ><<     ><<   ><<  ><<   ><<  ><<   ><<  ><      ><
-#      ><<         ><<<<    ><<<    ><<        ><<<<<     ><<<<<     ><<<<<     ><<<< ><<
-#"""
+    def defineCrossingList(self):
+        crossingList = ['']
+        spillOverList = self.getProp("SpilloverPaths")
+        while '' in spillOverList:
+            spillOverList.remove('')
+        crossingList += spillOverList
+        return crossingList
 
-    def checkVeloDDDB( self ):
+    def defineOutput(self, SpillOverSlots):
         """
-        Check if the Velo geometry is compatible with the chosen tags
+        Set up output stream according to phase processed,
+        the spill-over slots and the type of output
         """
-        # set validity limits for  Velo geometry
-        # first postMC09 Velo geometry
-        GTagLimit1 = "head-20091120"
-        GTagLimit1 = GTagLimit1.split('-')[1].strip()
-        VeloLTagLimit1 = "velo-20091116"
-        VeloLTagLimit1 = VeloLTagLimit1.split('-')[1].strip()
-        # Thomas L. Velo geometry
-        GTagLimit2 = "head-20100119"
-        GTagLimit2 = GTagLimit2.split('-')[1].strip()
-        VeloLTagLimit2 = "velo-20100114"
-        VeloLTagLimit2 = VeloLTagLimit2.split('-')[1].strip()
-
-        # DDDB global tag used
-        DDDBDate = LHCbApp().DDDBtag
-        DDDBDate = DDDBDate.split('-')
-
-        # Check if DDDB tag has a regular format (instead of e.g. a user git branch)
-        if len(DDDBDate) > 1 :
-          DDDBDate = DDDBDate[1].strip()
-          if DDDBDate.isdigit() :
-
-            # check if/which local tag is used for Velo
-            cdb = CondDB()
-            cdbVeloDate = 0
-            for p in cdb.LocalTags:
-                if p == "DDDB":
-                    taglist = list(cdb.LocalTags[p])
-                    for ltag in taglist:
-                        if ltag.find("velo")!=-1 :
-                            cdbVeloDate = ltag.split('-')[1].strip()
-
-            # Put this here rather than as an argument
-            VeloPostMC09 = 0
-            # check if the selected tags require one of the postMC09 Velo geometries
-            if (DDDBDate >= GTagLimit1) or (cdbVeloDate >= VeloLTagLimit1):
-                VeloPostMC09 = 1
-            if (DDDBDate >= GTagLimit2) or (cdbVeloDate >= VeloLTagLimit2):
-                VeloPostMC09 = 2
-
-            return VeloPostMC09
-
-        log.warning("DDDB tag not parsable as date. Using post-MC09 velo geometry : %s" %(DDDBDate))
-        return 2
-
-
-
-    ##
-    ##
-
 
-#"""
-# ><<         ><< ><<<<<<<< ><<           ><<<<
-#  ><<       ><<  ><<       ><<         ><<    ><<
-#   ><<     ><<   ><<       ><<       ><<        ><<
-#    ><<   ><<    ><<<<<<   ><<       ><<        ><<
-#     ><< ><<     ><<       ><<       ><<        ><<
-#      ><<<<      ><<       ><<         ><<     ><<
-#       ><<       ><<<<<<<< ><<<<<<<<     ><<<<
-#"""
-
-
-    ##
-    ##
-    def veloMisAlignGeometry( self, VeloPostMC09 ):
-
-        print "veloMisAlignGeometry: %s" %(VeloPostMC09)
-
-        """
-        File containing the list of detector element to explicitely set
-        to have misalignement in the VELO.
-        """
-        # remove Automatically included detector elements
-        self.removeBeamPipeElements( "velo" )
+        #
+        knownOptions = ['NONE', 'GEN', 'XGEN', 'RGEN', 'SIM', 'XSIM']
+        output = self.getProp("OutputType").upper()
+        if output == 'NONE':
+            log.warning("No event data output produced")
+            return
 
+        simWriter = SimConf().writer()
 
-        if "/dd/Structure/LHCb/BeforeMagnetRegion/Velo" in self._listOfGeoObjects_:
-            self._listOfGeoObjects_.remove("/dd/Structure/LHCb/BeforeMagnetRegion/Velo")
+        # define default file extensions depending on the phase that has been
+        # run
+        fileDefaultExtension = ".gen"
+        fileAllowedExtension = [fileDefaultExtension]
+        if "GenToMCTree" in self.getProp("Phases"):
+            fileDefaultExtension = ".xgen"
+            fileAllowedExtension = [fileDefaultExtension, ".rgen"]
+        elif "Simulation" in self.getProp("Phases"):
+            fileDefaultExtension = ".sim"
+            fileAllowedExtension = [fileDefaultExtension, ".xsim"]
 
-        self._listOfGeoObjects_.append("/dd/Structure/LHCb/BeforeMagnetRegion/Velo/VeloLeft/ModulePU00")
-        self._listOfGeoObjects_.append("/dd/Structure/LHCb/BeforeMagnetRegion/Velo/VeloLeft/ModulePU02")
-        self._listOfGeoObjects_.append("/dd/Structure/LHCb/BeforeMagnetRegion/Velo/VeloRight/ModulePU01")
-        self._listOfGeoObjects_.append("/dd/Structure/LHCb/BeforeMagnetRegion/Velo/VeloRight/ModulePU03")
+        # choose the file extension from the one selected compatibly with the
+        # phase run
+        if output not in knownOptions:
+            print "WARNING: OutputType not supported." \
+                  "Use default for chosen phases : %s" % (fileDefaultExtension)
+        fileExtension = "." + output.lower()
+        if fileExtension not in fileAllowedExtension:
+            fileExtension = fileDefaultExtension
+            print "WARNING: OutputType not supported" \
+                  " for this phase. Use default : %s" % (fileExtension)
 
-        txt = "/dd/Structure/LHCb/BeforeMagnetRegion/Velo/VeloLeft/ModuleXX"
-        import math
-        for i in range(42):
-            nr = str(i)
-            if len(nr) == 1 : nr = '0'+str(i)
-            temp1 = txt.replace('XX',nr)
-            if math.modf(float(nr)/2.)[0] > 0.1 :  temp1 = temp1.replace('Left','Right')
-            self._listOfGeoObjects_.append(temp1)
+        # set saving or not of HepMC depending on chosen file extension
+        if SimConf().isPropertySet("SaveHepMC"):
+            print "WARNING: SimConf().SaveHepMC will" \
+                  " be ignored. Value set by Gauss()"
+        saveHepMC = False
+        if fileExtension in ['.gen', '.xgen', '.xsim']:
+            saveHepMC = True
+        SimConf().setProp("SaveHepMC", saveHepMC)
 
-        self._listOfGeoObjects_.append("/dd/Structure/LHCb/BeforeMagnetRegion/Velo/DownStreamWakeFieldCone")
-        self._listOfGeoObjects_.append("/dd/Structure/LHCb/BeforeMagnetRegion/Velo/UpStreamWakeFieldCone")
-        if (VeloPostMC09==1):
-            # description postMC09 of Velo (head-20091120), problem with Velo Tank simulation
-            self._listOfGeoObjects_.append("/dd/Structure/LHCb/BeforeMagnetRegion/Velo/VacTank")
-            self._listOfGeoObjects_.append("/dd/Structure/LHCb/BeforeMagnetRegion/Velo/DownstreamPipeSections")
-            self._listOfGeoObjects_.append("/dd/Structure/LHCb/BeforeMagnetRegion/Velo/UpstreamPipeSections")
-        elif (VeloPostMC09==2):
-            # Thomas L. newer description postMC09 of Velo
-            # --- Velo Right
-            self._listOfGeoObjects_.append("/dd/Structure/LHCb/BeforeMagnetRegion/Velo/VeloRight/RFBoxRight")
-            self._listOfGeoObjects_.append("/dd/Structure/LHCb/BeforeMagnetRegion/Velo/VeloRight/DetSupportRight")
-            self._listOfGeoObjects_.append("/dd/Structure/LHCb/BeforeMagnetRegion/Velo/VeloRight/ConstSysRight")
-            # --- Velo Left
-            self._listOfGeoObjects_.append("/dd/Structure/LHCb/BeforeMagnetRegion/Velo/VeloLeft/RFBoxLeft")
-            self._listOfGeoObjects_.append("/dd/Structure/LHCb/BeforeMagnetRegion/Velo/VeloLeft/DetSupportLeft")
-            self._listOfGeoObjects_.append("/dd/Structure/LHCb/BeforeMagnetRegion/Velo/VeloLeft/ConstSysLeft")
-            # --- Velo
-            self._listOfGeoObjects_.append("/dd/Structure/LHCb/BeforeMagnetRegion/Velo/DownstreamPipeSections")
-            self._listOfGeoObjects_.append("/dd/Structure/LHCb/BeforeMagnetRegion/Velo/UpstreamPipeSections")
-            self._listOfGeoObjects_.append("/dd/Structure/LHCb/BeforeMagnetRegion/Velo/VacTank")
+        outputFile = ""
+        from GaudiConf import IOHelper
+        if simWriter.isPropertySet("Output"):
+            outputFile = IOHelper().undressFile(simWriter.getProp("Output"))
         else:
-            self._listOfGeoObjects_.append("/dd/Structure/LHCb/BeforeMagnetRegion/Velo/UpStreamVacTank")
-            self._listOfGeoObjects_.append("/dd/Structure/LHCb/BeforeMagnetRegion/Velo/DownStreamVacTank")
-
-        self._listOfGeoObjects_.append("/dd/Structure/LHCb/BeforeMagnetRegion/Velo/VeloRight/RFFoilRight")
-        self._listOfGeoObjects_.append("/dd/Structure/LHCb/BeforeMagnetRegion/Velo/VeloLeft/RFFoilLeft")
-    ##
-    ##
-
-
-    def defineVeloGeo( self , basePieces , detPieces ):
-        # Alter in place BasePieces
-        # check if the new velo geometry is required with the chosen DDDB tags
-
-        VeloP = self.checkVeloDDDB()
-        if (VeloP==1 or VeloP==2):
-            basePieces['BeforeMagnetRegion']=[]
-
-        # Also sort out mis-alignment
-        VeloP = self.checkVeloDDDB()
-        # No need to check, this is the case if this is called.
-        # No need to misalign if only PuVeto exits - check me PSZ.
-        if "Velo" in self.getProp('DetectorGeo')['Detectors']:
-            self.veloMisAlignGeometry(VeloP) # To misalign VELO
-
-
-
-
-
-    def configureVeloSim( self, slot, detHits ):
-        region = "BeforeMagnetRegion"
-        det = "Velo"
-        moni = GetTrackerHitsAlg(
-            'Get' + det + 'Hits' + slot,
-            MCHitsLocation = 'MC/' + det  + '/Hits',
-            CollectionName = det + 'SDet/Hits',
-            Detectors = [ '/dd/Structure/LHCb/' + region + '/' + det ]
-            )
-        detHits.Members += [ moni ]
-        self.configure_redecay_mchits(slot, 'MC/' + det  + '/Hits')
-
-
-
-
-    def configureVeloMoni( self, slot, packCheckSeq, detMoniSeq, checkHits ):
-        # reinstate checkHits default value
-        checkHits.VeloHits = 'MC/Velo/Hits'
-
-        ## Set the VeloMonitor
-        detMoniSeq.Members += [ VeloGaussMoni( "VeloGaussMoni" + slot ) ]
-        if self.getProp("EnablePack") and self.getProp("DataPackingChecks") :
-            from Configurables import DataPacking__Unpack_LHCb__MCVeloHitPacker_
-            upVelo = DataPacking__Unpack_LHCb__MCVeloHitPacker_("UnpackVeloHits"+slot,
-                                                                OutputName = "MC/Velo/HitsTest" )
-            packCheckSeq.Members += [upVelo]
-
-            from Configurables import DataPacking__Check_LHCb__MCVeloHitPacker_
-            cVelo = DataPacking__Check_LHCb__MCVeloHitPacker_("CheckVeloHits"+slot)
-            packCheckSeq.Members += [cVelo]
-
-
-
-
-#"""
-#><<         ><< ><<<<<<<< ><<           ><<<<      ><<<<<<<
-# ><<       ><<  ><<       ><<         ><<    ><<   ><<    ><<  ><
-#  ><<     ><<   ><<       ><<       ><<        ><< ><<    ><<     ><<   ><<
-#   ><<   ><<    ><<<<<<   ><<       ><<        ><< ><<<<<<<   ><<   >< ><<
-#    ><< ><<     ><<       ><<       ><<        ><< ><<        ><<    ><
-#     ><<<<      ><<       ><<         ><<     ><<  ><<        ><<  ><  ><<
-#      ><<       ><<<<<<<< ><<<<<<<<     ><<<<      ><<        ><< ><<   ><<
-#"""
-
-
-    def defineVPGeo( self, detPieces ):
-        self.removeBeamPipeElements( "velo" )
-        if detPieces.has_key('BeforeMagnetRegion'):
-            detPieces['BeforeMagnetRegion'] += ['VP']
-
-
-
-
-    def configureVPSim( self, slot, detHits ):
-        region = "BeforeMagnetRegion"
-        det = "VP"
-        moni = GetTrackerHitsAlg(
-            'Get' + det + 'Hits' + slot,
-            MCHitsLocation = 'MC/' + det  + '/Hits',
-            CollectionName = det + 'SDet/Hits',
-            Detectors = [ '/dd/Structure/LHCb/' + region + '/' + det ]
-            )
-        detHits.Members += [ moni ]
-        self.configure_redecay_mchits(slot, 'MC/' + det  + '/Hits')
-
-
-
-
-
-
-    def configureVPMoni( self, slot, packCheckSeq, detMoniSeq, checkHits ):
-        ## in case of a non default detector, need to be overwritten
-        #detMoniSeq = GaudiSequencer( "DetectorsMonitor" + slot )
-        from Configurables import VPGaussMoni
-        detMoniSeq.Members += [ VPGaussMoni( "VPGaussMoni" + slot ) ]
-
-        if self.getProp("EnablePack") and self.getProp("DataPackingChecks") :
-            packCheckSeq = GaudiSequencer( "DataUnpackTest"+slot )
-            from Configurables import DataPacking__Unpack_LHCb__MCVPHitPacker_
-            checkHits.VeloHits =  'MC/VP/Hits'
-            # This is not done in the PuVeto Moni config
-            #checkHits.PuVetoHits = ''
-            upVP = DataPacking__Unpack_LHCb__MCVPHitPacker_("UnpackVPHits"+slot,
-                                                                      OutputName = "MC/VP/HitsTest" )
-            packCheckSeq.Members += [upVP]
-
-            from Configurables import DataPacking__Check_LHCb__MCVPHitPacker_
-            cVP = DataPacking__Check_LHCb__MCVPHitPacker_("CheckVPHits"+slot)
-            packCheckSeq.Members += [cVP]
-
-
-
-#"""
-#  ><<<<<<<     ><<     ><<    ><<     ><<
-#  ><<    ><<   ><<  ><<   ><< ><<     ><<
-#  ><<    ><<   ><< ><<        ><<     ><<
-#  >< ><<       ><< ><<        ><<<<<< ><<
-#  ><<  ><<     ><< ><<        ><<     ><<
-#  ><<    ><<   ><<  ><<   ><< ><<     ><<
-#  ><<      ><< ><<    ><<<<   ><<     ><<
-#
-#"""
-
-
-    def defineRich1GeoDet( self , detPieces ):
-        self.removeBeamPipeElements( "rich1" )
-        detPieces['BeforeMagnetRegion']+=['Rich1']
-
-    def defineRich1GeoStream( self ):
-        self._listOfGeoObjects_.append("/dd/Geometry/BeforeMagnetRegion/Rich1/Rich1Surfaces")
-        self._listOfGeoObjects_.append("/dd/Geometry/BeforeMagnetRegion/Rich1/RichHPDSurfaces")
-
-    def defineRich2GeoDet( self , detPieces ):
-        self.removeBeamPipeElements( "rich2" )
-        detPieces['AfterMagnetRegion']+=['Rich2']
-
-    def defineRich2GeoStream( self ):
-        self._listOfGeoObjects_.append("/dd/Geometry/AfterMagnetRegion/Rich2/Rich2Surfaces")
-
-    def defineRichPhys( self, gmpl ):
-        gmpl.PhysicsConstructors.append("GiGaPhysConstructorOp")
-        gmpl.PhysicsConstructors.append("GiGaPhysConstructorHpd")
-
-    ##
-    ##
-    def configureRichSim (self, slot, detHits ):
-        from Configurables import (
-            GetMCRichHitsAlg,
-            GetMCRichOpticalPhotonsAlg,
-            GetMCRichSegmentsAlg,
-            GetMCRichTracksAlg
-            )
-
-        #for slot in SpillOverSlots:
-        richHitsSeq = GaudiSequencer( "RichHits" + slot )
-        detHits.Members += [ richHitsSeq ]
-        richHitsSeq.Members = [ GetMCRichHitsAlg( "GetRichHits"+slot),
-                                GetMCRichOpticalPhotonsAlg("GetRichPhotons"+slot),
-                                GetMCRichSegmentsAlg("GetRichSegments"+slot),
-                                GetMCRichTracksAlg("GetRichTracks"+slot),
-                                Rich__MC__MCPartToMCRichTrackAlg("MCPartToMCRichTrack"+slot),
-                                Rich__MC__MCRichHitToMCRichOpPhotAlg("MCRichHitToMCRichOpPhot"+slot) ]
-
-
-    def configureRichMoni ( self, slot, packCheckSeq, detMoniSeq, checkHits, configuredRichMoni ):
-
-        # reinstate checkHits default value
-        checkHits.RichHits = 'MC/Rich/Hits'
-
-        if self.getProp("EnablePack") and self.getProp("DataPackingChecks") :
-            from Configurables import DataPacking__Unpack_LHCb__MCRichHitPacker_
-            from Configurables import DataPacking__Unpack_LHCb__MCRichOpticalPhotonPacker_
-            from Configurables import DataPacking__Unpack_LHCb__MCRichSegmentPacker_
-            from Configurables import DataPacking__Unpack_LHCb__MCRichTrackPacker_
-
-            upRichHit  = DataPacking__Unpack_LHCb__MCRichHitPacker_("UnpackRichHits"+slot,
-                                                                    OutputName = "MC/Rich/HitsTest" )
-            upRichOpPh = DataPacking__Unpack_LHCb__MCRichOpticalPhotonPacker_("UnpackRichOpPhot"+slot,
-                                                                              OutputName = "MC/Rich/OpticalPhotonsTest" )
-            upRichSeg  = DataPacking__Unpack_LHCb__MCRichSegmentPacker_("UnpackRichSegments"+slot,
-                                                                        OutputName = "MC/Rich/SegmentsTest" )
-            upRichTrk  = DataPacking__Unpack_LHCb__MCRichTrackPacker_("UnpackRichTracks"+slot,
-                                                                      OutputName = "MC/Rich/TracksTest" )
-            packCheckSeq.Members += [upRichHit,upRichOpPh,upRichSeg,upRichTrk]
-
-
-            from Configurables import DataPacking__Check_LHCb__MCRichHitPacker_
-            from Configurables import DataPacking__Check_LHCb__MCRichOpticalPhotonPacker_
-            from Configurables import DataPacking__Check_LHCb__MCRichSegmentPacker_
-            from Configurables import DataPacking__Check_LHCb__MCRichTrackPacker_
-            cRichHit  = DataPacking__Check_LHCb__MCRichHitPacker_("CheckRichHits"+slot )
-            cRichOpPh = DataPacking__Check_LHCb__MCRichOpticalPhotonPacker_("CheckRichOpPhot"+slot )
-            cRichSeg  = DataPacking__Check_LHCb__MCRichSegmentPacker_("CheckRichSegments"+slot )
-            cRichTrk  = DataPacking__Check_LHCb__MCRichTrackPacker_("CheckRichTracks"+slot )
-            packCheckSeq.Members += [cRichHit,cRichOpPh,cRichSeg,cRichTrk]
-        # Out of loop
-        if ( self.getProp("CurrentRICHSimRunOption") == "clunker" ):
-            if not configuredRichMoni[1]:
-                importOptions("$GAUSSRICHROOT/options/RichAnalysis.opts")
-                configuredRichMoni[1] = True
-        elif (GaussRICHConf().getProp("MakeRichG4MonitorHistoSet2") ):
-            if not configuredRichMoni[1]:
-                configuredRichMoni[1] = True
+            outputFile = Gaussino().outputName() + fileExtension
 
-#"""
-#  ><<<<<<<     ><<     ><<    ><<     ><<    ><<<<<<<   ><<       ><< ><<< ><<<<<<
-#  ><<    ><<   ><<  ><<   ><< ><<     ><<    ><<    ><< >< ><<   ><<<      ><<
-#  ><<    ><<   ><< ><<        ><<     ><<    ><<    ><< ><< ><< > ><<      ><<
-#  >< ><<       ><< ><<        ><<<<<< ><<    ><<<<<<<   ><<  ><<  ><<      ><<
-#  ><<  ><<     ><< ><<        ><<     ><<    ><<        ><<   ><  ><<      ><<
-#  ><<    ><<   ><<  ><<   ><< ><<     ><<    ><<        ><<       ><<      ><<
-#  ><<      ><< ><<    ><<<<   ><<     ><<    ><<        ><<       ><<      ><<
-#
-#"""
-
-    def defineRich1MaPmtGeoDet( self , detPieces ):
-        self.removeBeamPipeElements( "rich1" )
-        detPieces['BeforeMagnetRegion']+=['Rich1']
-
-    def defineRich1MaPmtGeoStream( self, geoCnvSvc ):
-        self._listOfGeoObjects_.append("/dd/Geometry/BeforeMagnetRegion/Rich1/Rich1Surfaces")
-        self._listOfGeoObjects_.append("/dd/Geometry/BeforeMagnetRegion/Rich1/RichPMTSurfaces")
-        geoCnvSvc.UseAlignment = False
-        geoCnvSvc.AlignAllDetectors = False
-
-
-    def defineRich2MaPmtGeoDet( self , detPieces ):
-        self.removeBeamPipeElements( "rich2" )
-        detPieces['AfterMagnetRegion']+=['Rich2']
-
-    def defineRich2MaPmtGeoStream( self, geoCnvSvc ):
-        self._listOfGeoObjects_.append("/dd/Geometry/AfterMagnetRegion/Rich2/Rich2Surfaces")
-        geoCnvSvc.UseAlignment = False
-        geoCnvSvc.AlignAllDetectors = False
-
-
-    def defineRichMaPmtPhys( self, gmpl):
-        gmpl.PhysicsConstructors.append("GiGaPhysConstructorOpCkv")
-        gmpl.PhysicsConstructors.append("GiGaPhysConstructorPhotoDetector")
-
-
-
-
-    def configureRichMaPmtSim (self, slot, detHits ):
-        from Configurables import (
-            GetMCCkvHitsAlg,
-            GetMCCkvOpticalPhotonsAlg,
-            GetMCCkvSegmentsAlg,
-            GetMCCkvTracksAlg
-            )
-        richHitsSeq = GaudiSequencer( "RichHits" + slot )
-        detHits.Members += [ richHitsSeq ]
-        richHitsSeq.Members = [ GetMCCkvHitsAlg( "GetRichHits"+slot),
-                                GetMCCkvOpticalPhotonsAlg("GetRichPhotons"+slot),
-                                GetMCCkvSegmentsAlg("GetRichSegments"+slot),
-                                GetMCCkvTracksAlg("GetRichTracks"+slot),
-                                Rich__MC__MCPartToMCRichTrackAlg("MCPartToMCRichTrack"+slot),
-                                Rich__MC__MCRichHitToMCRichOpPhotAlg("MCRichHitToMCRichOpPhot"+slot) ]
-
-
-    def configureRichMaPmtMoni ( self, slot, packCheckSeq, detMoniSeq, checkHits, configuredRichMoni ):
-        checkHits.RichHits = 'MC/Rich/Hits'
-
-        if self.getProp("EnablePack") and self.getProp("DataPackingChecks") :
-            from Configurables import DataPacking__Unpack_LHCb__MCRichHitPacker_
-            from Configurables import DataPacking__Unpack_LHCb__MCRichOpticalPhotonPacker_
-            from Configurables import DataPacking__Unpack_LHCb__MCRichSegmentPacker_
-            from Configurables import DataPacking__Unpack_LHCb__MCRichTrackPacker_
-
-            upRichHit  = DataPacking__Unpack_LHCb__MCRichHitPacker_("UnpackRichHits"+slot,
-                                                                    OutputName = "MC/Rich/HitsTest" )
-            upRichOpPh = DataPacking__Unpack_LHCb__MCRichOpticalPhotonPacker_("UnpackRichOpPhot"+slot,
-                                                                              OutputName = "MC/Rich/OpticalPhotonsTest" )
-            upRichSeg  = DataPacking__Unpack_LHCb__MCRichSegmentPacker_("UnpackRichSegments"+slot,
-                                                                        OutputName = "MC/Rich/SegmentsTest" )
-            upRichTrk  = DataPacking__Unpack_LHCb__MCRichTrackPacker_("UnpackRichTracks"+slot,
-                                                                      OutputName = "MC/Rich/TracksTest" )
-            packCheckSeq.Members += [upRichHit,upRichOpPh,upRichSeg,upRichTrk]
-
-
-            from Configurables import DataPacking__Check_LHCb__MCRichHitPacker_
-            from Configurables import DataPacking__Check_LHCb__MCRichOpticalPhotonPacker_
-            from Configurables import DataPacking__Check_LHCb__MCRichSegmentPacker_
-            from Configurables import DataPacking__Check_LHCb__MCRichTrackPacker_
-            cRichHit  = DataPacking__Check_LHCb__MCRichHitPacker_("CheckRichHits"+slot )
-            cRichOpPh = DataPacking__Check_LHCb__MCRichOpticalPhotonPacker_("CheckRichOpPhot"+slot )
-            cRichSeg  = DataPacking__Check_LHCb__MCRichSegmentPacker_("CheckRichSegments"+slot )
-            cRichTrk  = DataPacking__Check_LHCb__MCRichTrackPacker_("CheckRichTracks"+slot )
-            packCheckSeq.Members += [cRichHit,cRichOpPh,cRichSeg,cRichTrk]
-        # Out of indent
-
-
-        if ( self.getProp("UpgradeRICHSimRunOption") == "clunker" ):
-            if not configuredRichMoni[1]:
-                importOptions("$GAUSSCHERENKOVROOT/options/GaussCherenkovAnalysis.opts")
-                configuredRichMoni[1] = True
-        elif (GaussCherenkovConf().getProp("MakeCkvG4MonitorHistoSet2")):
-            if not configuredRichMoni[1]:
-                configuredRichMoni[1] = True
-
-
-
-#"""
-#><<< ><<<<<<     ><<<<      ><<<<<<<         ><<    ><<     ><<
-#     ><<       ><<    ><<   ><<    ><<    ><<   ><< ><<     ><<
-#     ><<     ><<        ><< ><<    ><<   ><<        ><<     ><<
-#     ><<     ><<        ><< >< ><<       ><<        ><<<<<< ><<
-#     ><<     ><<        ><< ><<  ><<     ><<        ><<     ><<
-#     ><<       ><<     ><<  ><<    ><<    ><<   ><< ><<     ><<
-#     ><<         ><<<<      ><<      ><<    ><<<<   ><<     ><<
-#
-#"""
-    def defineTorchGeo( self ):
-        log.warning("Geo not defined for TORCH")
-        pass
-
-    def configureTorchSim( self, slot, detHits ):
-        log.warning("Sim not defined for TORCH")
-        pass
-
-    def configureTorchMoni( self, slot, packCheckSeq, detMoniSeq, checkHits ):
-        #detMoniSeq = GaudiSequencer( "DetectorsMonitor" + slot )
-        log.warning ("Moni not defined for TORCH")
-        pass
-
-
-
-
-#"""
-#><<< ><<<<<< ><<< ><<<<<<
-#     ><<          ><<
-#     ><<          ><<
-#     ><<          ><<
-#     ><<          ><<
-#     ><<          ><<
-#     ><<          ><<
-#"""
-
-
-    def defineTTGeo( self , detPieces ):
-        self.removeBeamPipeElements( "tt" )
-        if 'TT' not in detPieces['BeforeMagnetRegion']:
-            detPieces['BeforeMagnetRegion']+=['TT']
-
-
-    def configureTTSim( self, slot, detHits ):
-        region   = "BeforeMagnetRegion"
-        det = "TT"
-        moni = GetTrackerHitsAlg(
-            'Get' + det + 'Hits' + slot,
-            MCHitsLocation = 'MC/' + det  + '/Hits',
-            CollectionName = det + 'SDet/Hits',
-            Detectors = [ '/dd/Structure/LHCb/' + region + '/' + det ]
-            )
-        detHits.Members += [ moni ]
-        self.configure_redecay_mchits(slot, 'MC/' + det  + '/Hits')
-
-
-    def configureTTMoni( self, slot, packCheckSeq, detMoniSeq, checkHits ):
-        # reinstate checkHits default value
-        checkHits.TTHits = 'MC/TT/Hits'
-
-        myZStations = [
-            2350.0*SystemOfUnits.mm,
-            2620.0*SystemOfUnits.mm
-            ]
-        myZStationXMax = 150.*SystemOfUnits.cm
-        myZStationYMax = 150.*SystemOfUnits.cm
-
-        detMoniSeq.Members += [
-            MCHitMonitor(
-                "TTHitMonitor" + slot ,
-                mcPathString = "MC/TT/Hits",
-                zStations = myZStations,
-                xMax = myZStationXMax,
-                yMax = myZStationYMax
-                )
-            ]
-        if self.getProp("EnablePack") and self.getProp("DataPackingChecks") :
-
-            packCheckSeq = GaudiSequencer( "DataUnpackTest"+slot )
-
-            from Configurables import DataPacking__Unpack_LHCb__MCTTHitPacker_
-            from Configurables import DataPacking__Check_LHCb__MCTTHitPacker_
-            upTT   = DataPacking__Unpack_LHCb__MCTTHitPacker_("UnpackTTHits"+slot,
-                                                              OutputName = "MC/TT/HitsTest" )
-            cTT   = DataPacking__Check_LHCb__MCTTHitPacker_("CheckTTHits"+slot )
-            packCheckSeq.Members += [upTT, cTT]
-
-
-
-#"""
-# ><<     ><< ><<< ><<<<<<
-# ><<     ><<      ><<
-# ><<     ><<      ><<
-# ><<     ><<      ><<
-# ><<     ><<      ><<
-# ><<     ><<      ><<
-#   ><<<<<         ><<
-#"""
-
-
-    def defineUTGeo( self , detPieces ):
-        self.removeBeamPipeElements( "ut" )
-        if 'UT' not in detPieces['BeforeMagnetRegion']:
-            detPieces['BeforeMagnetRegion']+=['UT']
-
-
-    def configureUTSim( self, slot, detHits ):
-        region   = "BeforeMagnetRegion"
-        det = "UT"
-        moni = GetTrackerHitsAlg(
-            'Get' + det + 'Hits' + slot,
-            MCHitsLocation = 'MC/' + det  + '/Hits',
-            CollectionName = det + 'SDet/Hits',
-            Detectors = [ '/dd/Structure/LHCb/' + region + '/' + det ]
-            )
-        detHits.Members += [ moni ]
-        self.configure_redecay_mchits(slot, 'MC/' + det  + '/Hits')
-
-
-    def configureUTMoni( self, slot, packCheckSeq, detMoniSeq, checkHits ):
-        # reinstate checkHits default value
-        checkHits.UTHits = 'MC/UT/Hits'
-
-        myZStations = [
-            2350.0*SystemOfUnits.mm,
-            2620.0*SystemOfUnits.mm
-            ]
-        myZStationXMax = 150.*SystemOfUnits.cm
-        myZStationYMax = 150.*SystemOfUnits.cm
-
-        detMoniSeq.Members += [
-            MCHitMonitor(
-                "UTHitMonitor" + slot ,
-                mcPathString = "MC/UT/Hits",
-                zStations = myZStations,
-                xMax = myZStationXMax,
-                yMax = myZStationYMax
-                )
-            ]
-        if self.getProp("EnablePack") and self.getProp("DataPackingChecks") :
-
-            packCheckSeq = GaudiSequencer( "DataUnpackTest"+slot )
-
-            from Configurables import DataPacking__Unpack_LHCb__MCUTHitPacker_
-            from Configurables import DataPacking__Check_LHCb__MCUTHitPacker_
-            upUT   = DataPacking__Unpack_LHCb__MCUTHitPacker_("UnpackUTHits"+slot,
-                                                              OutputName = "MC/UT/HitsTest" )
-            cUT   = DataPacking__Check_LHCb__MCUTHitPacker_("CheckUTHits"+slot )
-            packCheckSeq.Members += [upUT, cUT]
-
-
-
-
-#"""
-#  ><<  ><<< ><<<<<<
-#  ><<       ><<
-#  ><<       ><<
-#  ><<       ><<
-#  ><<       ><<
-#  ><<       ><<
-#  ><<       ><<
-#
-#"""
-
-    def defineITGeo( self , detPieces ):
-        self.removeBeamPipeElements( "t" )
-        region = "AfterMagnetRegion"
-        if 'T' not in detPieces[region]:
-            detPieces[region]+=['T/IT']
-        if 'T/PipeInT' not in detPieces[region]:
-            detPieces[region]+=['T/PipeInT']
-
-
-    def configureITSim( self, slot, detHits ):
-        region   = "AfterMagnetRegion/T"
-        det = "IT"
-        moni = GetTrackerHitsAlg(
-            'Get' + det + 'Hits' + slot,
-            MCHitsLocation = 'MC/' + det  + '/Hits',
-            CollectionName = det + 'SDet/Hits',
-            Detectors = [ '/dd/Structure/LHCb/' + region + '/' + det ]
-            )
-        detHits.Members += [ moni ]
-        self.configure_redecay_mchits(slot, 'MC/' + det  + '/Hits')
-
-
-    def configureITMoni( self, slot, packCheckSeq, detMoniSeq, checkHits ):
-        # reinstate checkHits default value
-        checkHits.ITHits = 'MC/IT/Hits'
-
-        myZStations = [
-            7780.0*SystemOfUnits.mm,
-            8460.0*SystemOfUnits.mm,
-            9115.0*SystemOfUnits.mm
-            ]
-        myZStationXMax = 150.*SystemOfUnits.cm
-        myZStationYMax = 150.*SystemOfUnits.cm
-
-        # Upgrade
-        #if self.getProp("DataType") == "Upgrade" :
-        #    myZStations = [
-        #        8015.0*SystemOfUnits.mm,
-        #        8697.0*SystemOfUnits.mm,
-        #        9363.0*SystemOfUnits.mm
-        #        ]
-
-        detMoniSeq.Members += [
-            MCHitMonitor(
-                "ITHitMonitor" + slot ,
-                mcPathString = "MC/IT/Hits",
-                zStations = myZStations,
-                xMax = myZStationXMax,
-                yMax = myZStationYMax
-                )
-            ]
-
-        if self.getProp("EnablePack") and self.getProp("DataPackingChecks") :
-
-            packCheckSeq = GaudiSequencer( "DataUnpackTest"+slot )
-            from Configurables import DataPacking__Unpack_LHCb__MCITHitPacker_
-            upIT   = DataPacking__Unpack_LHCb__MCITHitPacker_("UnpackITHits"+slot,
-                                                              OutputName = "MC/IT/HitsTest" )
-            from Configurables import DataPacking__Check_LHCb__MCITHitPacker_
-            cIT   = DataPacking__Check_LHCb__MCITHitPacker_("CheckITHits"+slot )
-            packCheckSeq.Members += [upIT, cIT]
-
-
-#"""
-#
-#     Si IT
-#
-#"""
-
-    def defineSLGeo( self , detPieces ):
-        self.removeBeamPipeElements( "t" )
-        region = "AfterMagnetRegion"
-        if 'T' not in detPieces[region]:
-            detPieces[region]+=['T/SL']
-        # PSZ - line below might need to go depending on SL definition
-        if 'T/PipeInT' not in detPieces[region]:
-            detPieces[region]+=['T/PipeInT']
-
-
-    def configureSLSim( self, slot, detHits ):
-        region   = "AfterMagnetRegion/T"
-        det = "SL"
-        moni = GetTrackerHitsAlg(
-            'Get' + det + 'Hits' + slot,
-            MCHitsLocation = 'MC/' + det  + '/Hits',
-            CollectionName = det + 'SDet/Hits',
-            Detectors = [ '/dd/Structure/LHCb/' + region + '/' + det ]
-            )
-        detHits.Members += [ moni ]
-        self.configure_redecay_mchits(slot, 'MC/' + det  + '/Hits')
-        pass
-
-    #def configureSLMoni( self, slot, packCheckSeq, detMoniSeq, checkHits ):
-    #    pass
-    def configureSLMoni( self, slot, packCheckSeq, detMoniSeq, checkHits ):
-        # reinstate checkHits default value
-        checkHits.SLHits = 'MC/SL/Hits'
-
-        myZStations = [
-            7780.0*SystemOfUnits.mm,
-            #8460.0*SystemOfUnits.mm,
-            9115.0*SystemOfUnits.mm
-            ]
-        myZStationXMax = 150.*SystemOfUnits.cm
-        myZStationYMax = 150.*SystemOfUnits.cm
-
-        detMoniSeq.Members += [
-            MCHitMonitor(
-                "SLHitMonitor" + slot ,
-                mcPathString = "MC/SL/Hits",
-                zStations = myZStations,
-                xMax = myZStationXMax,
-                yMax = myZStationYMax
-                )
-            ]
-
-        if self.getProp("EnablePack") and self.getProp("DataPackingChecks") :
-
-            packCheckSeq = GaudiSequencer( "DataUnpackTest"+slot )
-            from Configurables import DataPacking__Unpack_LHCb__MCSLHitPacker_
-            upSL   = DataPacking__Unpack_LHCb__MCSLHitPacker_("UnpackSLHits"+slot,
-                                                              OutputName = "MC/SL/HitsTest" )
-            from Configurables import DataPacking__Check_LHCb__MCSLHitPacker_
-            cSL   = DataPacking__Check_LHCb__MCSLHitPacker_("CheckSLHits"+slot )
-            packCheckSeq.Members += [upSL, cSL]
-
-
-
-#"""
-#   ><<<<<<<< ><<< ><<<<<<
-#   ><<            ><<
-#   ><<            ><<
-#   ><<<<<<        ><<
-#   ><<            ><<
-#   ><<            ><<
-#   ><<            ><<
-#
-#"""
-    def defineFTGeo( self , detType , detPieces ):
-        self.removeBeamPipeElements( "t" )
-        region = "AfterMagnetRegion"
-        if 'T' not in detPieces[region]:
-            detPieces[region]+=['T/FT']
-        if 'T/PipeInT' not in detPieces[region]:
-            detPieces[region]+=['T/PipeInT']
-        if detType == "ft":
-            region = "DownstreamRegion"
-            detPieces[region]+=['NeutronShielding']
-
-
-    def configureFTSim( self, slot, detHits ):
-        region   = "AfterMagnetRegion/T"
-        det = "FT"
-        moni = GetTrackerHitsAlg(
-            'Get' + det + 'Hits' + slot,
-            MCHitsLocation = 'MC/' + det  + '/Hits',
-            CollectionName = det + 'SDet/Hits',
-            Detectors = [ '/dd/Structure/LHCb/' + region + '/' + det ]
-            )
-        detHits.Members += [ moni ]
-        self.configure_redecay_mchits(slot, 'MC/' + det  + '/Hits')
-
-
-    def configureFTMoni( self, slot, packCheckSeq, detMoniSeq, checkHits ):
-        # reinstate checkHits default value
-        checkHits.FTHits = 'MC/FT/Hits'
-
-
-        # Upgrade
-        myZStations = [
-            7938.0*SystemOfUnits.mm,
-            8625.0*SystemOfUnits.mm,
-            9315.0*SystemOfUnits.mm
-            ]
-        myZStationXMax = 100.*SystemOfUnits.cm
-        myZStationYMax = 100.*SystemOfUnits.cm
-
-        detMoniSeq.Members += [
-            MCHitMonitor(
-                "FTHitMonitor" + slot ,
-                mcPathString = "MC/FT/Hits",
-                zStations = myZStations,
-                xMax = myZStationXMax,
-                yMax = myZStationYMax
-                )
-            ]
-        if self.getProp("EnablePack") and self.getProp("DataPackingChecks") :
-            packCheckSeq = GaudiSequencer( "DataUnpackTest"+slot )
-            from Configurables import DataPacking__Unpack_LHCb__MCFTHitPacker_
-            upFT = DataPacking__Unpack_LHCb__MCFTHitPacker_("UnpackFTHits"+slot,
-                                                              OutputName = "MC/FT/HitsTest" )
-            from Configurables import DataPacking__Check_LHCb__MCFTHitPacker_
-            cFT  = DataPacking__Check_LHCb__MCFTHitPacker_("CheckFTHits"+slot )
-            packCheckSeq.Members += [upFT, cFT]
-
-
-#"""
-#    ><<<<      ><<< ><<<<<<
-#  ><<    ><<        ><<
-#><<        ><<      ><<
-#><<        ><<      ><<
-#><<        ><<      ><<
-#  ><<     ><<       ><<
-#    ><<<<           ><<
-#"""
-
-    def defineOTGeo( self , detPieces ):
-        self.removeBeamPipeElements( "t" )
-        region = "AfterMagnetRegion"
-        if 'T' not in detPieces[region]:
-            detPieces[region]+=['T/OT']
-        if 'T/PipeInT' not in detPieces[region]:
-            detPieces[region]+=['T/PipeInT']
-
-
-
-    def configureOTSim( self, slot, detHits ):
-        region   = "AfterMagnetRegion/T"
-        det = "OT"
-        moni = GetTrackerHitsAlg(
-            'Get' + det + 'Hits' + slot,
-            MCHitsLocation = 'MC/' + det  + '/Hits',
-            CollectionName = det + 'SDet/Hits',
-            Detectors = [ '/dd/Structure/LHCb/' + region + '/' + det ]
-            )
-        detHits.Members += [ moni ]
-        self.configure_redecay_mchits(slot, 'MC/' + det  + '/Hits')
-
-    def configureOTMoni( self, slot, packCheckSeq, detMoniSeq, checkHits ):
-        # reinstate checkHits default value
-        checkHits.OTHits = 'MC/OT/Hits'
-
-        myZStations = [
-            7938.0*SystemOfUnits.mm,
-            8625.0*SystemOfUnits.mm,
-            9315.0*SystemOfUnits.mm
-            ]
-        myZStationXMax = 100.*SystemOfUnits.cm
-        myZStationYMax = 100.*SystemOfUnits.cm
-
-        # Upgrade
-        #if self.getProp("DataType") == "Upgrade" :
-        #    myZStations = [
-        #        7672.0*SystemOfUnits.mm,
-        #        8354.0*SystemOfUnits.mm,
-        #        9039.0*SystemOfUnits.mm
-        #        ]
-
-        detMoniSeq.Members += [
-            MCHitMonitor(
-                "OTHitMonitor" + slot ,
-                mcPathString = "MC/OT/Hits",
-                zStations = myZStations,
-                xMax = myZStationXMax,
-                yMax = myZStationYMax
-                )
-            ]
-        if self.getProp("EnablePack") and self.getProp("DataPackingChecks") :
-
-            packCheckSeq = GaudiSequencer( "DataUnpackTest"+slot )
-            from Configurables import DataPacking__Unpack_LHCb__MCOTHitPacker_
-            upOT   = DataPacking__Unpack_LHCb__MCOTHitPacker_("UnpackOTHits"+slot,
-                                                              OutputName = "MC/OT/HitsTest" )
-            from Configurables import DataPacking__Check_LHCb__MCOTHitPacker_
-            cOT   = DataPacking__Check_LHCb__MCOTHitPacker_("CheckOTHits"+slot )
-            packCheckSeq.Members += [upOT, cOT]
-
-
-
-#"""
-#   ><<       ><<
-#   >< ><<   ><<<
-#   ><< ><< > ><< ><<  ><<    ><<     ><< ><<
-#   ><<  ><<  ><< ><<  ><<  ><<  ><<   ><<  ><<
-#   ><<   ><  ><< ><<  ><< ><<    ><<  ><<  ><<
-#   ><<       ><< ><<  ><<  ><<  ><<   ><<  ><<
-#   ><<       ><<   ><<><<    ><<     ><<<  ><<
-#
-#"""
-
-    def defineMuonGeo( self, detPieces ):
-        #self.removeBeamPipeElements( "muon" )
-        region = 'DownstreamRegion'
-        detPieces[region]+=['Muon']
-
-
-    def configureMuonSim ( self, slot, detHits ):
-        det = "Muon"
-        moni = GetTrackerHitsAlg( "Get"+det+"Hits"+slot,
-                                  MCHitsLocation = 'MC/' + det + '/Hits',
-                                  CollectionName = det + 'SDet/Hits',
-                                  Detectors = ['/dd/Structure/LHCb/DownstreamRegion/'+det] )
-        detHits.Members += [ moni ]
-        self.configure_redecay_mchits(slot, 'MC/' + det  + '/Hits')
-
-
-    def configureMuonMoni( self, slot, packCheckSeq, detMoniSeq, checkHits ):
-        # reinstate checkHits default value
-        det = "Muon"
-        checkHits.MuonHits = 'MC/Muon/Hits'
-
-        detMoniSeq.Members += [ MuonHitChecker( det + "HitChecker" + slot,
-                                                FullDetail = True )]
-## The following should only be done in expert checks
-#        from Configurables import MuonMultipleScatteringChecker
-#        detMoniSeq.Members += [
-#            MuonMultipleScatteringChecker( "MuonMultipleScatteringChecker"+ slot )]
-
-        if self.getProp("EnablePack") and self.getProp("DataPackingChecks") :
-
-            packCheckSeq = GaudiSequencer( "DataUnpackTest"+slot )
-
-            from Configurables import DataPacking__Unpack_LHCb__MCMuonHitPacker_
-            upMu   = DataPacking__Unpack_LHCb__MCMuonHitPacker_("UnpackMuonHits"+slot,
-                                                                OutputName = "MC/Muon/HitsTest" )
-            from Configurables import DataPacking__Check_LHCb__MCMuonHitPacker_
-            cMu   = DataPacking__Check_LHCb__MCMuonHitPacker_("CheckMuonHits"+slot )
-            packCheckSeq.Members += [upMu, cMu]
-
-
-
-
-#"""
-#       ><<          ><        ><<           ><<<<
-#    ><<   ><<      >< <<      ><<         ><<    ><<
-#   ><<            ><  ><<     ><<       ><<        ><<
-#   ><<           ><<   ><<    ><<       ><<        ><<
-#   ><<          ><<<<<< ><<   ><<       ><<        ><<
-#    ><<   ><<  ><<       ><<  ><<         ><<     ><<
-#      ><<<<   ><<         ><< ><<<<<<<<     ><<<<
-#
-#"""
-
-    def defineSpdGeo( self, detPieces ):
-        self.removeBeamPipeElements("calo")
-        region = 'DownstreamRegion'
-        detPieces[region]+=['Spd']
-        detPieces[region]+=['Converter']
-
-    def definePrsGeo( self, detPieces ):
-        region = 'DownstreamRegion'
-        detPieces[region]+=['Prs']
-
-    def defineEcalGeo( self, detPieces ):
-        region = 'DownstreamRegion'
-        detPieces[region]+=['Ecal']
-
-    def defineHcalGeo( self, detPieces ):
-        region = 'DownstreamRegion'
-        detPieces[region]+=['Hcal']
-
-
-    def configureSpdSim ( self, slot, detHits ):
-        det = "Spd"
-        moni = GetCaloHitsAlg(
-            "Get"+det+"Hits"+slot,
-            MCHitsLocation = 'MC/' + det + '/Hits',
-            CollectionName = det + 'Hits'
-            )
-        detHits.Members += [ moni ]
-        self.configure_redecay_mccalohits(slot, 'MC/' + det + '/Hits')
-
-    def configurePrsSim ( self, slot, detHits ):
-        det = "Prs"
-        moni = GetCaloHitsAlg(
-            "Get"+det+"Hits"+slot,
-            MCHitsLocation = 'MC/' + det + '/Hits',
-            CollectionName = det + 'Hits'
-            )
-        detHits.Members += [ moni ]
-        self.configure_redecay_mccalohits(slot, 'MC/' + det + '/Hits')
-
-    def configureEcalSim ( self, slot, detHits ):
-        det = "Ecal"
-        moni = GetCaloHitsAlg(
-            "Get"+det+"Hits"+slot,
-            MCHitsLocation = 'MC/' + det + '/Hits',
-            CollectionName = det + 'Hits'
-            )
-        detHits.Members += [ moni ]
-        self.configure_redecay_mccalohits(slot, 'MC/' + det + '/Hits')
-
-    def configureHcalSim ( self, slot, detHits ):
-        det = "Hcal"
-        moni = GetCaloHitsAlg(
-            "Get"+det+"Hits"+slot,
-            MCHitsLocation = 'MC/' + det + '/Hits',
-            CollectionName = det + 'Hits'
-            )
-        detHits.Members += [ moni ]
-        self.configure_redecay_mccalohits(slot, 'MC/' + det + '/Hits')
+        # Merge genFSRs
+        if self.getProp("WriteFSR"):
+            seqGenFSR = GaudiSequencer("GenFSRSeq")
+            ApplicationMgr().TopAlg += [seqGenFSR]
 
+            if self.getProp("MergeGenFSR"):
+                seqGenFSR.Members += ["GenFSRMerge"]
 
+        IOHelper().outStream(outputFile, simWriter, self.getProp("WriteFSR"))
 
+        if not FileCatalog().isPropertySet("Catalogs"):
+            FileCatalog().Catalogs = ["xmlcatalog_file:NewCatalog.xml"]
 
-    def configureSpdMoni( self, slot, packCheckSeq, detMoniSeq, checkHits ):
-        # reinstate checkHits default value
-        checkHits.CaloHits.append('MC/Spd/Hits')
+    # Apply the configuration
+    def __apply_configuration__(self):
 
-        det = "Spd"
-        detMoniSeq.Members += [
-            MCCaloMonitor(
-                det + "Monitor" + slot,
-                OutputLevel = 4,
-                Detector = det,
-                Regions = True,
-                MaximumEnergy = 10.*SystemOfUnits.MeV,
-                Threshold = 1.5*SystemOfUnits.MeV
-                )
-            ]
-        if self.getProp("EnablePack") and self.getProp("DataPackingChecks") :
+        self.setOtherProps(Gaussino(), [
+            "Histograms", "DatasetName", "Phases", "SpilloverPaths"])
 
-            packCheckSeq = GaudiSequencer( "DataUnpackTest"+slot )
-            from Configurables import DataPacking__Unpack_LHCb__MCSpdHitPacker_
-            upSpd  = DataPacking__Unpack_LHCb__MCSpdHitPacker_("UnpackSpdHits"+slot,
-                                                               OutputName = "MC/Spd/HitsTest" )
-            from Configurables import DataPacking__Check_LHCb__MCSpdHitPacker_
-            cSpd  = DataPacking__Check_LHCb__MCSpdHitPacker_("CheckSpdHits"+slot)
-            packCheckSeq.Members += [upSpd,cSpd]
+        LHCbApp(Simulation=True)  # in Boole? where?
+        if Gaussino().getProp('EnableHive') is True:
+            LHCbApp().EnableHive = True
 
+        self.propagateSimConf()
+        G4Physics()
+        LHCbGeo()
 
-
-    def configurePrsMoni( self, slot, packCheckSeq, detMoniSeq, checkHits):
-        # reinstate checkHits default value
-        checkHits.CaloHits.append('MC/Prs/Hits')
-
-        det = "Prs"
-        detMoniSeq.Members += [
-            MCCaloMonitor(
-                det + "Monitor" + slot,
-                OutputLevel = 4,
-                Detector = 'Prs',
-                Regions = True,
-                MaximumEnergy = 10.*SystemOfUnits.MeV,
-                Threshold = 1.5*SystemOfUnits.MeV
-                )
-            ]
-        if self.getProp("EnablePack") and self.getProp("DataPackingChecks") :
-
-            packCheckSeq = GaudiSequencer( "DataUnpackTest"+slot )
-            from Configurables import DataPacking__Unpack_LHCb__MCPrsHitPacker_
-            upPrs  = DataPacking__Unpack_LHCb__MCPrsHitPacker_("UnpackPrsHits"+slot,
-                                                               OutputName = "MC/Prs/HitsTest" )
-            from Configurables import DataPacking__Check_LHCb__MCPrsHitPacker_
-            cPrs  = DataPacking__Check_LHCb__MCPrsHitPacker_("CheckPrsHits"+slot)
-            packCheckSeq.Members += [upPrs,cPrs]
-
-
-
-
-    def configureEcalMoni( self, slot, packCheckSeq, detMoniSeq, checkHits ):
-        # reinstate checkHits default value
-        checkHits.CaloHits.append('MC/Ecal/Hits')
-
-        det = "Ecal"
-        detMoniSeq.Members += [
-            MCCaloMonitor(
-                det + "Monitor" + slot,
-                OutputLevel = 4,
-                Detector = det,
-                Regions = True,
-                MaximumEnergy = 1000.*SystemOfUnits.MeV,
-                Threshold = 10.*SystemOfUnits.MeV
-                )
-            ]
-        if self.getProp("EnablePack") and self.getProp("DataPackingChecks") :
-
-            packCheckSeq = GaudiSequencer( "DataUnpackTest"+slot )
-            from Configurables import DataPacking__Unpack_LHCb__MCEcalHitPacker_
-            upEcal = DataPacking__Unpack_LHCb__MCEcalHitPacker_("UnpackEcalHits"+slot,
-                                                                OutputName = "MC/Ecal/HitsTest" )
-            from Configurables import DataPacking__Check_LHCb__MCEcalHitPacker_
-            cEcal = DataPacking__Check_LHCb__MCEcalHitPacker_("CheckEcalHits"+slot)
-            packCheckSeq.Members += [upEcal,cEcal]
-
-
-
-
-    def configureHcalMoni( self, slot, packCheckSeq, detMoniSeq, checkHits ):
-        # reinstate checkHits default value
-        checkHits.CaloHits.append('MC/Hcal/Hits')
-
-        det = "Hcal"
-        detMoniSeq.Members += [
-            MCCaloMonitor(
-                det + "Monitor" + slot,
-                OutputLevel = 4,
-                Detector = det,
-                Regions = True,
-                MaximumEnergy = 1000.*SystemOfUnits.MeV,
-                Threshold = 5.*SystemOfUnits.MeV
-                )
-            ]
-        if self.getProp("EnablePack") and self.getProp("DataPackingChecks") :
-
-            packCheckSeq = GaudiSequencer( "DataUnpackTest"+slot )
-            from Configurables import DataPacking__Unpack_LHCb__MCHcalHitPacker_
-            upHcal = DataPacking__Unpack_LHCb__MCHcalHitPacker_("UnpackHcalHits"+slot,
-                                                                OutputName = "MC/Hcal/HitsTest" )
-            from Configurables import DataPacking__Check_LHCb__MCHcalHitPacker_
-            cHcal = DataPacking__Check_LHCb__MCHcalHitPacker_("CheckHcalHits"+slot)
-            packCheckSeq.Members += [upHcal,cHcal]
-
-
-########################################################################################################
-#
-# Herschel
-#
-########################################################################################################
-
-    def defineHCGeo(self, detPieces):
-      year = self.getProp("DataType")
-      if year not in self.Run2DataTypes:
-        log.warning( "Check your options: you have asked to simulate Herschel but not in %s."%year )
-        log.warning( "Simulating only the LHC tunnel.")
-      # Add the non-standard pieces of the BeforeMagnet region.
-      region = 'BeforeMagnetRegion'
-      if detPieces.has_key(region):
-        pieces = ['PipeJunctionBeforeVelo', 'BeforeVelo']
-        for piece in pieces:
-          if piece in detPieces[region]: continue
-          detPieces[region] += [piece]
-      # Add the AfterMuon part of the Downstream region.
-      region = 'DownstreamRegion'
-      if detPieces.has_key(region):
-        pieces = ['AfterMuon']
-        for piece in pieces:
-          if piece in detPieces[region]: continue
-          detPieces[region] += [piece]
-      # Add the entire Upstream, BeforeUpstream, and AfterDownstream regions.
-      regions = ['UpstreamRegion', 'BeforeUpstreamRegion',
-                 'AfterDownstreamRegion']
-      for region in regions:
-        if detPieces.has_key(region):
-          detPieces[region] = []
-        self._listOfGeoObjects_.append("/dd/Structure/LHCb/" + region)
-
-      # Extend the world volume.
-      if self.getProp('UseGaussGeo'):
-        GaussGeo().ZsizeOfWorldVolume = 300.0 * SystemOfUnits.m
-      else:
-        GiGaGeo().ZsizeOfWorldVolume = 300.0 * SystemOfUnits.m
-
-    def configureHCSim(self, slot, detHits):
-      year = self.getProp("DataType")
-      if year not in self.Run2DataTypes:
-        raise RuntimeError( "Asking to simulate Herschel response but not present in %s" %year )
-
-      det = "HC"
-      getHits = GetTrackerHitsAlg("Get" + det + "Hits" + slot)
-      getHits.MCHitsLocation = "MC/" + det + "/Hits"
-      getHits.CollectionName = det + "SDet/Hits"
-      getHits.Detectors = ["/dd/Structure/LHCb/UpstreamRegion/HCB0",
-                           "/dd/Structure/LHCb/UpstreamRegion/HCB1",
-                           "/dd/Structure/LHCb/BeforeUpstreamRegion/HCB2",
-                           "/dd/Structure/LHCb/DownstreamRegion/AfterMuon/HCF1",
-                           "/dd/Structure/LHCb/AfterDownstreamRegion/HCF2"]
-      detHits.Members += [getHits]
-
-    def configureHCMoni(self, slot, packCheckSeq, detMoniSeq, checkHits):
-      from Configurables import HCHitChecker
-      detMoniSeq.Members += [HCHitChecker("HCHitChecker" + slot)]
-
-      if self.getProp("EnablePack") and self.getProp("DataPackingChecks"):
-        packCheckSeq = GaudiSequencer("DataUnpackTest" + slot)
-        from Configurables import DataPacking__Unpack_LHCb__MCHCHitPacker_
-        upHC = DataPacking__Unpack_LHCb__MCHCHitPacker_("UnpackHCHits" + slot,
-                                                        OutputName = "MC/HC/HitsTest")
-        packCheckSeq.Members += [upHC]
-
-        from Configurables import DataPacking__Check_LHCb__MCHCHitPacker_
-        cHC = DataPacking__Check_LHCb__MCHCHitPacker_("CheckHCHits" + slot)
-        packCheckSeq.Members += [cHC]
-
-
-########################################################################################################
-#
-# Beam Condition Monitors
-#
-########################################################################################################
-
-    def defineBcmGeo(self, detPieces):
-      # Add the non-standard pieces of the BeforeMagnet region.
-      region = 'BeforeMagnetRegion'
-      if detPieces.has_key(region):
-        pieces = ['PipeJunctionBeforeVelo', 'BeforeVelo']
-        for piece in pieces:
-          if piece in detPieces[region]: continue
-          detPieces[region] += [piece]
-      # Add the entire Upstream region.
-      region = 'UpstreamRegion'
-      if detPieces.has_key(region):
-        detPieces[region] = []
-      self._listOfGeoObjects_.append("/dd/Structure/LHCb/" + region)
-      # Add the AfterMuon part of the Downstream region.
-      region = 'DownstreamRegion'
-      if detPieces.has_key(region):
-        pieces = ['AfterMuon']
-        for piece in pieces:
-          if piece in detPieces[region]: continue
-          detPieces[region] += [piece]
-
-    def configureBcmSim(self, slot, detHits):
-      det = "Bcm"
-      getHits = GetTrackerHitsAlg("Get" + det + "Hits" + slot)
-      getHits.MCHitsLocation = "MC/" + det + "/Hits"
-      getHits.CollectionName = det + "SDet/Hits"
-      getHits.Detectors = ["/dd/Structure/LHCb/BeforeMagnetRegion/BeforeVelo/BcmUp",
-                           "/dd/Structure/LHCb/MagnetRegion/BcmDown"]
-      detHits.Members += [getHits]
-
-    def configureBcmMoni(self, slot, packCheckSeq, detMoniSeq, checkHits):
-      from Configurables import BcmHitChecker
-      checkerUp = BcmHitChecker("BcmHitCheckerUp" + slot)
-      checkerUp.BcmDetLocation = "/dd/Structure/LHCb/BeforeMagnetRegion/BeforeVelo/BcmUp"
-      checkerUp.MonitorInDetail = False
-      checkerDn = BcmHitChecker("BcmHitCheckerDown" + slot)
-      checkerDn.BcmDetLocation = "/dd/Structure/LHCb/MagnetRegion/BcmDown"
-      checkerDn.MonitorInDetail = False
-      detMoniSeq.Members += [checkerUp, checkerDn]
-
-      if self.getProp("EnablePack") and self.getProp("DataPackingChecks"):
-        packCheckSeq = GaudiSequencer("DataUnpackTest" + slot)
-        from Configurables import DataPacking__Unpack_LHCb__MCBcmHitPacker_
-        upBcm = DataPacking__Unpack_LHCb__MCBcmHitPacker_("UnpackBcmHits" + slot,
-                                                          OutputName = "MC/Bcm/HitsTest")
-        packCheckSeq.Members += [upBcm]
-
-        from Configurables import DataPacking__Check_LHCb__MCBcmHitPacker_
-        cBcm = DataPacking__Check_LHCb__MCBcmHitPacker_("CheckBcmHits" + slot)
-        packCheckSeq.Members += [cBcm]
-
-
-########################################################################################################
-#
-# Beam Loss Scintillators
-#
-########################################################################################################
-#
-
-    def defineBlsGeo(self, detPieces):
-      # Add the non-standard pieces of the BeforeMagnet region.
-      region = 'BeforeMagnetRegion'
-      if detPieces.has_key(region):
-        pieces = ['PipeJunctionBeforeVelo', 'BeforeVelo']
-        for piece in pieces:
-          if piece in detPieces[region]: continue
-          detPieces[region] += [piece]
-      # Add the non-standard pieces of the Upstream region,
-      # unless the Upstream region has been added as a whole.
-      region = 'UpstreamRegion'
-      path = '/dd/Structure/LHCb/' + region
-      if detPieces.has_key(region) and path not in self._listOfGeoObjects_:
-        pieces = ['BlockWallUpstr']
-        for piece in pieces:
-          if piece in detPieces[region]: continue
-          detPieces[region] += [piece]
-
-    def configureBlsSim(self, slot, detHits):
-      det = "Bls"
-      getHits = GetTrackerHitsAlg("Get" + det + "Hits" + slot)
-      getHits.MCHitsLocation = "MC/" + det + "/Hits"
-      getHits.CollectionName = det + "SDet/Hits"
-      # The geometry of the BLS changed in 2011
-      idBLS = ["3", "4", "5", "6", "7", "8"]
-      if self.getProp("DataType") in [ "2009", "2010" ]:
-          idBLS = ["1", "2"]
-      getHits.Detectors = []
-      for iDet in idBLS:
-         getHits.Detectors.append("/dd/Structure/LHCb/BeforeMagnetRegion/BeforeVelo/Bls"+iDet)
-      detHits.Members += [getHits]
-
-
-    def configureBlsMoni(self, slot, packCheckSeq, detMoniSeq, checkHits):
-      from Configurables import BlsHitChecker
-      checkerA = BlsHitChecker("BlsHitCheckerBlsA" + slot)
-      checkerA.HistoDir = "BlsHitChecker/BlsHitCheckerBlsA"
-      checkerA.BlsAOn = TRUE
-      checkerA.HistogramTitlePrefix = "BlsA: "
-      checkerC = BlsHitChecker("BlsHitCheckerBlsC" + slot)
-      checkerC.HistoDir = "BlsHitChecker/BlsHitCheckerBlsC"
-      checkerC.BlsCOn = TRUE
-      checkerC.HistogramTitlePrefix = "BlsC: "
-      detMoniSeq.Members += [checkerA, checkerC]
-
-      if self.getProp("EnablePack") and self.getProp("DataPackingChecks"):
-        packCheckSeq = GaudiSequencer("DataUnpackTest" + slot)
-        from Configurables import DataPacking__Unpack_LHCb__MCBlsHitPacker_
-        upBls = DataPacking__Unpack_LHCb__MCBlsHitPacker_("UnpackBlsHits" + slot,
-                                                          OutputName = "MC/Bls/HitsTest")
-        packCheckSeq.Members += [upBls]
-
-        from Configurables import DataPacking__Check_LHCb__MCBlsHitPacker_
-        cBls = DataPacking__Check_LHCb__MCBlsHitPacker_("CheckBlsHits" + slot)
-        packCheckSeq.Members += [cBls]
-
-
-#"""
-#    ><<       ><<                                             ><<
-#    >< ><<   ><<<                                             ><<
-#    ><< ><< > ><<    ><<        ><<    ><< ><<      ><<     ><>< ><
-#    ><<  ><<  ><<  ><<  ><<   ><<  ><<  ><<  ><<  ><   ><<    ><<
-#    ><<   ><  ><< ><<   ><<  ><<   ><<  ><<  ><< ><<<<< ><<   ><<
-#    ><<       ><< ><<   ><<   ><<  ><<  ><<  ><< ><           ><<
-#    ><<       ><<   ><< ><<<      ><<  ><<<  ><<   ><<<<       ><<
-#                           ><<
-#"""
-
-    def defineMagnetGeo( self , basePieces, detPieces ):
-        # Turn off magnet if false
-        path = "dd/Structure/LHCb/MagnetRegion/"
-        detPieces["MagnetRegion"] = ['Magnet','BcmDown']
-        # PSZ - check why this is here
-        #if False:
-        #    for element in detPieces['MagnetRegion']:
-        #        myElement = path + element
-        #        if myElement in self._listOfGeoObjects_:
-        #            self._listOfGeoObjects_.remove([ path + element ])
-
-        # PSZ - clean me up
-        #if False:
-        #    GiGaGeo().FieldManager           = "GiGaFieldMgr/FieldMgr"
-        #    GiGaGeo().addTool( GiGaFieldMgr("FieldMgr"), name="FieldMgr" )
-        #    GiGaGeo().FieldMgr.Stepper       = "ClassicalRK4"
-        #    GiGaGeo().FieldMgr.Global        = True
-        #    GiGaGeo().FieldMgr.MagneticField = "GiGaMagFieldGlobal/LHCbField"
-        #    GiGaGeo().FieldMgr.addTool( GiGaMagFieldGlobal("LHCbField"), name="LHCbField" )
-        #    GiGaGeo().FieldMgr.LHCbField.MagneticFieldService = "MagneticFieldSvc"
-
-
-    def defineMagnetGeoField( self ):
-        # Only bother with the FIELD Geometry if simulated.
-        simDets = self.getProp('DetectorSim')['Detectors']
-        if "Magnet" in simDets or "HC" in simDets:
-            if self.getProp('UseGaussGeo'):
-                GaussGeo().FieldManager           = "GiGaFieldMgr/FieldMgr"
-                GaussGeo().addTool( GiGaFieldMgr("FieldMgr"), name="FieldMgr" )
-                GaussGeo().FieldMgr.Stepper       = "ClassicalRK4"
-                GaussGeo().FieldMgr.Global        = True
-                GaussGeo().FieldMgr.MagneticField = "GiGaMagFieldGlobal/LHCbField"
-                GaussGeo().FieldMgr.addTool( GiGaMagFieldGlobal("LHCbField"), name="LHCbField" )
-                GaussGeo().FieldMgr.LHCbField.MagneticFieldService = "MagneticFieldSvc"
-            else:
-                GiGaGeo().FieldManager           = "GiGaFieldMgr/FieldMgr"
-                GiGaGeo().addTool( GiGaFieldMgr("FieldMgr"), name="FieldMgr" )
-                GiGaGeo().FieldMgr.Stepper       = "ClassicalRK4"
-                GiGaGeo().FieldMgr.Global        = True
-                GiGaGeo().FieldMgr.MagneticField = "GiGaMagFieldGlobal/LHCbField"
-                GiGaGeo().FieldMgr.addTool( GiGaMagFieldGlobal("LHCbField"), name="LHCbField" )
-                GiGaGeo().FieldMgr.LHCbField.MagneticFieldService = "MagneticFieldSvc"
-
-        if "HC" in simDets:
-            from Configurables import MagneticFieldSvc, MultipleMagneticFieldSvc
-            # Use MultipleMagneticFieldSvc instead of default MagneticFieldSvc.
-            if self.getProp('UseGaussGeo'):
-                GaussGeo().FieldMgr.LHCbField.MagneticFieldService = "MultipleMagneticFieldSvc"
-            else:
-                GiGaGeo().FieldMgr.LHCbField.MagneticFieldService = "MultipleMagneticFieldSvc"
-            # Add LHCb dipole magnet and compensators.
-            if "Magnet" in simDets:
-              MultipleMagneticFieldSvc().MagneticFieldServices += ["MagneticFieldSvc"]
-              importOptions("$MAGNETROOT/options/UseCompensators.py")
-            # Import LSS fields.
-            importOptions("$MAGNETROOT/options/UseTripletLeft.py")
-            importOptions("$MAGNETROOT/options/UseTripletRight.py")
-            # Scale dipoles and quadrupoles.
-            scalableMagnets = ["Q1", "Q2", "Q3", "D1", "MCBX"]
-            magnets = MultipleMagneticFieldSvc().getProp("MagneticFieldServices")
-            scale =  self.getProp("BeamMomentum") / (3.5 * SystemOfUnits.TeV )
-            for magnet in magnets:
-              if any(m in magnet for m in scalableMagnets):
-                 MagneticFieldSvc(magnet).ForcedSignedCurrentScaling = scale
-                 print "Scaling", magnet, "by", scale
-
-
-
-
-#"""
-# ><<<<<<<            ><<         ><<              ><<
-# ><<    ><<           ><<       ><<               ><<
-# ><<    ><< ><<  ><<   ><<     ><<      ><<     ><>< ><    ><<
-# ><<<<<<<   ><<  ><<    ><<   ><<     ><   ><<    ><<    ><<  ><<
-# ><<        ><<  ><<     ><< ><<     ><<<<< ><<   ><<   ><<    ><<
-# ><<        ><<  ><<      ><<<<      ><           ><<    ><<  ><<
-# ><<          ><<><<       ><<         ><<<<       ><<     ><<
-#
-#"""
-
-    def definePuVetoGeo( self ):
-        pass
-
-    def configurePuVetoSim( self, slot, detHits ):
-        region = "BeforeMagnetRegion"
-        det = "PuVeto"
-        # This is still awful - PSZ
-        detextra, detextra1 = 'VeloPu', 'Velo'
-        if 'VP' not in self.getProp('DetectorSim')['Detectors']:
-            moni = GetTrackerHitsAlg(
-                'Get' + det + 'Hits' + slot,
-                MCHitsLocation = 'MC/' + det  + '/Hits',
-                CollectionName = 'VeloPuSDet/Hits',
-                Detectors = [ '/dd/Structure/LHCb/' + region + '/Velo' ]
-                )
-            detHits.Members += [ moni ]
-            self.configure_redecay_mchits(slot, 'MC/' + det  + '/Hits')
-
-    def configurePuVetoMoni( self, slot, packCheckSeq, detMoniSeq, checkHits ):
-
-        checkHits.PuVetoHits = 'MC/PuVeto/Hits'
-        # Turn off the PuVeto hits if using modified detector
-        if 'VP' not in self.getProp('DetectorSim')['Detectors']:
-            checkHits.PuVetoHits = ''
-
-        from Configurables import DataPacking__Unpack_LHCb__MCPuVetoHitPacker_
-        upPuVe = DataPacking__Unpack_LHCb__MCPuVetoHitPacker_("UnpackPuVetoHits"+slot,
-                                                              OutputName = "MC/PuVeto/HitsTest" )
-        if self.getProp("EnablePack") and self.getProp("DataPackingChecks") :
-            packCheckSeq.Members += [upPuVe]
-
-            from Configurables import DataPacking__Check_LHCb__MCPuVetoHitPacker_
-            # if there's no VP do PuVeto stuff
-            if 'VP' not in self.getProp('DetectorSim')['Detectors']:
-                cPuVe = DataPacking__Check_LHCb__MCPuVetoHitPacker_("CheckPuVetoHits"+slot)
-                packCheckSeq.Members += [cPuVe]
-
-
-
-
-#"""
-##########################################################################
-##########################################################################
-##########################################################################
-##########################################################################
-##########################################################################
-#"""
-
-
-
-#"""
-#    ><<                          ><<    ><<<<<<<                  ><<
-# ><<   ><<                     ><       ><<    ><<                ><<
-#><<          ><<    ><< ><<  ><>< ><    ><<    ><<  ><< ><<       ><<
-#><<        ><<  ><<  ><<  ><<  ><<      >< ><<       ><<  ><< ><< ><<
-#><<       ><<    ><< ><<  ><<  ><<      ><<  ><<     ><<  ><<><   ><<
-# ><<   ><< ><<  ><<  ><<  ><<  ><<      ><<    ><<   ><<  ><<><   ><<
-#   ><<<<     ><<    ><<<  ><<  ><<      ><<      ><<><<<  ><< ><< ><<
-#"""
-
-
-    ##
-    ## Functions to configuration various services that are used
-    ##
-    def configureRndmEngine( self ):
-        # Random number service
-        rndmSvc = RndmGenSvc()
-        rndmGenName = self.getProp("RandomGenerator")
-        if rndmGenName == "Ranlux":
-            from Configurables import HepRndm__Engine_CLHEP__RanluxEngine_
-            engine = HepRndm__Engine_CLHEP__RanluxEngine_("RndmGenSvc.Engine")
-            engine.SetSingleton = True
-        elif rndmGenName == "MTwist" :
-            rndmSvc.Engine = "HepRndm::Engine<CLHEP::MTwistEngine>"
-            from Configurables import HepRndm__Engine_CLHEP__MTwistEngine_
-            engine = HepRndm__Engine_CLHEP__MTwistEngine_("RndmGenSvc.Engine")
-            engine.SetSingleton = True
-        else :
-            raise RuntimeError("ERROR: RandomNumber engine '%s' not recognised!" %rndmGenName)
-
-
-
-#"""
-#    ><<                          ><<    ><<                             ><<
-# ><<   ><<                     ><       ><<                             ><<
-#><<          ><<    ><< ><<  ><>< ><    ><< ><< ><<   >< ><<  ><<  ><<><>< ><
-#><<        ><<  ><<  ><<  ><<  ><<      ><<  ><<  ><< ><  ><< ><<  ><<  ><<
-#><<       ><<    ><< ><<  ><<  ><<      ><<  ><<  ><< ><   ><<><<  ><<  ><<
-# ><<   ><< ><<  ><<  ><<  ><<  ><<      ><<  ><<  ><< ><< ><< ><<  ><<  ><<
-#   ><<<<     ><<    ><<<  ><<  ><<      ><< ><<<  ><< ><<       ><<><<   ><<
-#                                                      ><<
-#"""
-
-    def configureInput(self):
-        # No events are read as input (this is not true if gen phase is
-        # switched off
-        ApplicationMgr().EvtSel = 'NONE'
-        # Transient store setup
-        EventDataSvc().ForceLeaves = True
-        # May be needed by some options
-        importOptions("$STDOPTS/PreloadUnits.opts")
-
-
-
-#"""
-#    ><<                                ><<         ><<<<<                   ><<
-# ><<   ><< ><<                         ><<         ><<   ><<   ><           ><<
-#><<        ><<         ><<        ><<< ><<  ><<    ><<    ><<        ><<< ><>< ><  ><<<<
-#><<        >< ><     ><   ><<   ><<    ><< ><<     ><<    ><< ><<  ><<      ><<   ><<
-#><<        ><<  ><< ><<<<< ><< ><<     ><><<       ><<    ><< ><< ><<       ><<     ><<<
-# ><<   ><< ><   ><< ><          ><<    ><< ><<     ><<   ><<  ><<  ><<      ><<       ><<
-#   ><<<<   ><<  ><<   ><<<<       ><<< ><<  ><<    ><<<<<     ><<    ><<<    ><<  ><< ><<
-#
-#"""
-
-    ## Raise an error if DetectorGeo/DetectorSim/DetectorMoni are not compatible
-    def fixGeoSimMoniDictionary ( self ) :
-        pass
-
-    def checkGeoSimMoniDictionary ( self ) :
-        for subdet in self.TrackingSystem + self.PIDSystem:
-            # Could do something smarter here
-            for det in self.getProp('DetectorSim')['Detectors']:
-                if self.getProp('DetectorGeo')['Detectors'].count(det) == 0 :
-                    if (det not in ['FT', 'FT-NoShield']) or ( ('FT' not in self.getProp('DetectorGeo')['Detectors']) and ('FT-NoShield' not in self.getProp('DetectorGeo')['Detectors']) ):
-                        raise RuntimeError("Simulation has been required for '%s' sub-detector but it has been removed from Geometry" %det)
-            for det in self.getProp('DetectorMoni')['Detectors']:
-                if self.getProp('DetectorSim')['Detectors'].count(det) == 0 :
-                    if (det not in ['FT', 'FT-NoShield']) or ( ('FT' not in self.getProp('DetectorSim')['Detectors']) and ('FT-NoShield' not in self.getProp('DetectorSim')['Detectors']) ):
-                        raise RuntimeError("Monitoring has been required for '%s' sub-detector but it has been removed from Simulation" %det)
-
-
-    def checkIncompatibleDetectors ( self ) :
-        for section in self._incompatibleDetectors.keys():
-            incompatList = self._incompatibleDetectors[section]
-            myList = [det for det in self.getProp("DetectorGeo")['Detectors'] if det in incompatList]
-            if len(myList) > 1:
-                raise RuntimeError ( "Incompatible detectors: %s in %s section." %(myList, section) )
-
-
-
-    ##
-    def outputName(self):
-        """
-        Build a name for the output file, based on input options.
-        Combines DatasetName, EventType, Number of events and Date
-        """
-        import time
-        outputName = self.getProp("DatasetName")
-        if self.eventType() != "":
-            if outputName != "": outputName += '-'
-            outputName += self.eventType()
-        if ( self.evtMax() > 0 ): outputName += '-' + str(self.evtMax()) + 'ev'
-        if outputName == "": outputName = 'Gauss'
-        idFile = str(time.localtime().tm_year)
-        if time.localtime().tm_mon < 10:
-            idFile += '0'
-        idFile += str(time.localtime().tm_mon)
-        if time.localtime().tm_mday < 10:
-            idFile += '0'
-        idFile += str(time.localtime().tm_mday)
-        outputName += '-' + idFile
-        return outputName
-
-
-#"""
-# ><<<<<                  ><<   ><<<<<<<                                        ><<
-# ><<   ><<             ><      ><<    ><<                          ><          ><<
-# ><<    ><<   ><<    ><>< ><   ><<    ><<   ><<    >< ><<< ><<<<       ><<<< ><>< ><
-# ><<    ><< ><   ><<   ><<     ><<<<<<<   ><   ><<  ><<   ><<     ><< ><<      ><<
-# ><<    ><<><<<<< ><<  ><<     ><<       ><<<<< ><< ><<     ><<<  ><<   ><<<   ><<
-# ><<   ><< ><          ><<     ><<       ><         ><<       ><< ><<     ><<  ><<
-# ><<<<<      ><<<<     ><<     ><<         ><<<<   ><<<   ><< ><< ><< ><< ><<   ><<
-#"""
-
-
-    ##
-
-#"""
-#
-# ><<<<<<<                                   ><< <<                        ><<                            ><<
-# ><<    ><<                               ><<    ><<  ><               ><<   ><<                       ><
-# ><<    ><< >< ><<<   ><<     >< ><<       ><<           ><<< ><< ><< ><<          ><<     ><< ><<   ><>< ><
-# ><<<<<<<    ><<    ><<  ><<  ><  ><<        ><<     ><<  ><<  ><  ><<><<        ><<  ><<   ><<  ><<   ><<
-# ><<         ><<   ><<    ><< ><   ><<          ><<  ><<  ><<  ><  ><<><<       ><<    ><<  ><<  ><<   ><<
-# ><<         ><<    ><<  ><<  ><< ><<     ><<    ><< ><<  ><<  ><  ><< ><<   ><< ><<  ><<   ><<  ><<   ><<
-# ><<        ><<<      ><<     ><<           ><< <<   ><< ><<<  ><  ><<   ><<<<     ><<     ><<<  ><<   ><<
-#                              ><<
-#
-#"""
-
-    def propagateSimConf( self ):
-        # Propagate properties to SimConf
-        SimConf().setProp("Writer","GaussTape")
-        self.setOtherProps( SimConf(), ["SpilloverPaths","EnablePack","Phases","DataType"] )
-        # if we have post-sim filters, we only want to write if the filter is passed
-        if self.getProp("PostSimFilters") :
-            OutputStream("GaussTape").RequireAlgs.append( "PostSimFilterSeq" )
-
-
-        # CRJ : Propagate detector list to SimConf. Probably could be simplified a bit
-        #       by sychronising the options in Gauss() and SimConf()
-        detlist = []
-        if 'Velo'    in self.getProp('DetectorSim')['Detectors'] : detlist += ['Velo']
-        if 'PuVeto'  in self.getProp('DetectorSim')['Detectors'] : detlist += ['PuVeto']
-        if 'TT'      in self.getProp('DetectorSim')['Detectors'] : detlist += ['TT']
-        if 'IT'      in self.getProp('DetectorSim')['Detectors'] : detlist += ['IT']
-        if 'OT'      in self.getProp('DetectorSim')['Detectors'] : detlist += ['OT']
-        if [det for det in ['Rich1', 'Rich2', 'Rich1Pmt', 'Rich2Pmt'] if det in self.getProp('DetectorSim')['Detectors']] :
-            detlist += ['Rich']
-        if 'Muon'    in self.getProp('DetectorSim')['Detectors'] : detlist += ['Muon']
-        if 'Spd'     in self.getProp('DetectorSim')['Detectors'] : detlist += ['Spd']
-        if 'Prs'     in self.getProp('DetectorSim')['Detectors'] : detlist += ['Prs']
-        if 'Ecal'    in self.getProp('DetectorSim')['Detectors'] : detlist += ['Ecal']
-        if 'Hcal'    in self.getProp('DetectorSim')['Detectors'] : detlist += ['Hcal']
-        if 'HC'      in self.getProp('DetectorSim')['Detectors'] : detlist += ['HC']
-        # GC - 20160323 Bmc and Bls Off for now
-        ## if 'Bcm'     in self.getProp('DetectorSim')['Detectors'] : detlist += ['Bcm']
-        ## if 'Bls'     in self.getProp('DetectorSim')['Detectors'] : detlist += ['Bls']
-        # PSZ - add upgrade detectors here
-        if 'VP'      in self.getProp('DetectorSim')['Detectors'] : detlist += ['VP']
-        if 'UT'      in self.getProp('DetectorSim')['Detectors'] : detlist += ['UT']
-        if ('FT' in self.getProp('DetectorSim')['Detectors']) or ('FT-NoShield' in self.getProp('DetectorSim')['Detectors']) :
-            detlist += ['FT']
-        if 'SL'    in self.getProp('DetectorSim')['Detectors'] : detlist += ['SL']
-        # if Skip4 then dont propagate the detector list
-        if "GenToMCTree" in self.getProp("Phases"):
-            detlist = []
-
-        SimConf().setProp("Detectors",detlist)
-
-
-        # Don't want SIM data unpacking enabled in DoD service
-        SimConf().EnableUnpack = False
-
-
-#"""
-#      ><<                                                              ><<                     ><<
-#   ><<   ><<                                  ><                       ><<        ><           ><<
-#  ><<        >< ><<<   ><<     ><<<<  ><<<<      ><< ><<      ><<      ><<            ><<<<  ><>< ><
-#  ><<         ><<    ><<  ><< ><<    ><<     ><<  ><<  ><<  ><<  ><<   ><<       ><< ><<       ><<
-#  ><<         ><<   ><<    ><<  ><<<   ><<<  ><<  ><<  ><< ><<   ><<   ><<       ><<   ><<<    ><<
-#   ><<   ><<  ><<    ><<  ><<     ><<    ><< ><<  ><<  ><<  ><<  ><<   ><<       ><<     ><<   ><<
-#     ><<<<   ><<<      ><<    ><< ><<><< ><< ><< ><<<  ><<      ><<    ><<<<<<<< ><< ><< ><<    ><<
-#                                                            ><<
-#"""
-    def defineCrossingList( self ):
-        crossingList = [ '' ]
-        spillOverList = self.getProp("SpilloverPaths")
-        while '' in spillOverList :
-            spillOverList.remove('')
-        crossingList += spillOverList
-        return crossingList
-
-
-#"""
-#
-#  ><< ><<                                          ><<<<<<<
-#  ><    ><<                                        ><<    ><<
-#  ><     ><<    ><<        ><<     ><<< ><< ><<    ><<    ><<    ><<     >< ><<<    ><<     ><<< ><< ><<   ><<<<
-#  ><<< ><     ><   ><<   ><<  ><<   ><<  ><  ><<   ><<<<<<<    ><<  ><<   ><<     ><<  ><<   ><<  ><  ><< ><<
-#  ><     ><< ><<<<< ><< ><<   ><<   ><<  ><  ><<   ><<        ><<   ><<   ><<    ><<   ><<   ><<  ><  ><<   ><<<
-#  ><      >< ><         ><<   ><<   ><<  ><  ><<   ><<        ><<   ><<   ><<    ><<   ><<   ><<  ><  ><<     ><<
-#  ><<<< ><<    ><<<<      ><< ><<< ><<<  ><  ><<   ><<          ><< ><<< ><<<      ><< ><<< ><<<  ><  ><< ><< ><<
-#"""
-    #--Set the energy of the beam,
-    #--the half effective crossing angle (in LHCb coordinate system),
-    #--beta* and emittance
-    #--and configure the colliding beam tool for all type of events in
-    #--pp collisions.
-    def setBeamParameters( self, CrossingSlots, genInit):
-
-        from Configurables import ( MinimumBias , FixedNInteractions , HijingProduction )
-        from Configurables import ( Special , Pythia8Production )
-        from Configurables import ( Generation )
-
-        #
-        beamMom                        = self.getProp("BeamMomentum")
-        xAngle                         = self.getProp("BeamHCrossingAngle")
-        yAngle                         = self.getProp("BeamVCrossingAngle")
-        xAngleBeamLine, yAngleBeamLine = self.getProp("BeamLineAngles")
-        emittance                      = self.getProp("BeamEmittance")
-        betaStar                       = self.getProp("BeamBetaStar")
-        lumiPerBunch                   = self.getProp("Luminosity")
-        totCrossSection                = self.getProp("TotalCrossSection")
-        meanX, meanY, meanZ            = self.getProp("InteractionPosition")
-        sigmaS                         = self.getProp("BunchRMS")
-        b2Mom                          = self.getProp("B2Momentum")
-        B1Particle                     = self.getProp("B1Particle")
-        B2Particle                     = self.getProp("B2Particle")
-
-        # Give beam parameters to GenInit algorithm
-        genInit.CreateBeam              = True
-        genInit.BeamEnergy              = beamMom
-        genInit.HorizontalCrossingAngle = xAngle
-        genInit.VerticalCrossingAngle   = yAngle
-        genInit.NormalizedEmittance     = emittance
-        genInit.BetaStar                = betaStar
-        genInit.HorizontalBeamlineAngle = xAngleBeamLine
-        genInit.VerticalBeamlineAngle   = yAngleBeamLine
-        genInit.Luminosity              = lumiPerBunch
-        genInit.TotalCrossSection       = totCrossSection
-        genInit.XLuminousRegion         = meanX
-        genInit.YLuminousRegion         = meanY
-        genInit.ZLuminousRegion         = meanZ
-        genInit.BunchLengthRMS          = sigmaS
-
-        gen_t0 = Generation("Generation")
-
-        # the following is for beam gas events, the values are just to give the
-        # nominal beam conditions in the data but 1 single interaction is
-        # forced selecting the appropriate pileup tool in the eventtype
-        gen_t0.addTool(FixedNInteractions,name="FixedNInteractions")
-        gen_t0.FixedNInteractions.NInteractions = 1
-
-        # Default initialisation of pInGev
-        pInGeV   = beamMom*SystemOfUnits.GeV/SystemOfUnits.TeV
-
-        ## handle the information for HI generation (EPOS or HIJING)
-        ## Is it a fixed target generation ?
-        isFixedTarget = ( ( beamMom == 0. ) or (b2Mom == 0. ) )
-
-        ## pass collision energy to Hijing (must be in CMS and in GeV)
-        if ( isFixedTarget ):
-            if ( b2Mom == 0 ):
-                pInGeV   = beamMom*SystemOfUnits.GeV/SystemOfUnits.TeV
-            else:
-                pInGeV   = b2Mom*SystemOfUnits.GeV/SystemOfUnits.TeV
-        else:
-            p1InGeV = beamMom*SystemOfUnits.GeV/SystemOfUnits.TeV
-            p2InGeV = b2Mom*SystemOfUnits.GeV/SystemOfUnits.TeV
-            ## beam energies in CMS for pPb collision system
-            if B1Particle != 'p' or B2Particle != 'p':
-                import math
-                massProton = 0.938272046 #in GeV
-                e1InGeV = math.sqrt( p1InGeV**2 + massProton**2 )
-                e2InGeV = math.sqrt( p2InGeV**2 + massProton**2 )
-                pInGeV = math.sqrt( ( e1InGeV + e2InGeV )**2 - ( p1InGeV + p2InGeV )**2 )
-
-        txtP = "hijinginit efrm "+str(pInGeV)
-        gen_t0.addTool(MinimumBias,name="MinimumBias")
-        gen_t0.MinimumBias.addTool(HijingProduction,name="HijingProduction")
-        gen_t0.MinimumBias.HijingProduction.Commands += [ txtP ]
-
-        ## Setup EPOS particle type
-        gen_t0.MinimumBias.addTool(CRMCProduction,name="CRMCProduction")
-        if ( B1Particle not in self.__ion_pdg_id__.keys() ):
-            raise RuntimeError( "Unknown particle type: %s"  % B1Particle )
-        if ( B2Particle not in self.__ion_pdg_id__.keys() ):
-            raise RuntimeError( "Unknown particle type: %s"  % B2Particle )
-        gen_t0.MinimumBias.CRMCProduction.ProjectileID = self.__ion_pdg_id__[ B1Particle ]
-        gen_t0.MinimumBias.CRMCProduction.TargetID = self.__ion_pdg_id__[ B2Particle ]
-        gen_t0.MinimumBias.CRMCProduction.ProjectileMomentum = beamMom / SystemOfUnits.GeV
-        gen_t0.MinimumBias.CRMCProduction.TargetMomentum = b2Mom / SystemOfUnits.GeV
-
-        ## Setup HIJING particle type
-        if ( B1Particle != 'p' ):
-            Zproj = str( self.__ion_pdg_id__[ B1Particle ] )[ 4:6 ]
-            Aproj = str( self.__ion_pdg_id__[ B1Particle ] )[ 6:9 ]
-            textOptionHijing = "hijinginit izp %s," % Zproj
-            textOptionHijing+= "hijinginit iap %s," % Aproj
-            textOptionHijing+= "hijinginit proj A,"
-        else:
-            textOptionHijing = "hijinginit izp 1,"
-            textOptionHijing+= "hijinginit iap 1,"
-            textOptionHijing+= "hijinginit proj P,"
-        if ( B2Particle != 'p' ):
-            Ztarg = str( self.__ion_pdg_id__[ B2Particle ] )[ 4:6 ]
-            Atarg = str( self.__ion_pdg_id__[ B2Particle ] )[ 6:9 ]
-            textOptionHijing+= "hijinginit izt %s," % Ztarg
-            textOptionHijing+= "hijinginit iat %s," % Atarg
-            textOptionHijing+= "hijinginit targ A,"
-        else:
-            textOptionHijing+= "hijinginit izt 1,"
-            textOptionHijing+= "hijinginit iat 1,"
-            textOptionHijing+= "hijinginit targ P,"
-
-        if isFixedTarget:
-            textOptionHijing+= "hijinginit frame LAB,"
-            if ( beamMom == 0 ):
-                textOptionHijing+= "hijinginit beam2"
-            else:
-                textOptionHijing+= "hijinginit beam1"
-        else:
-            textOptionHijing+= "hijinginit frame CMS"
-        gen_t0.MinimumBias.HijingProduction.Commands += textOptionHijing.split(",")
-
-    #--For beam gas events (with hijing) only the energy of the beams is set
-
-    #--Set location for histogram particle guns based on beam energy
-        from Configurables import ParticleGun, MomentumSpectrum
-        pgun = ParticleGun("ParticleGun")
-        pgun.addTool( MomentumSpectrum , name = "MomentumSpectrum" )
-        txtPInGeV = str(pInGeV).split(".")[0]
-        hFileName = pgun.MomentumSpectrum.getProp("InputFile")
-        hFileName = hFileName.replace("Ebeam4000GeV","Ebeam"+txtPInGeV+"GeV")
-        pgun.MomentumSpectrum.InputFile = hFileName
-        print hFileName
-
-    ## end of functions to set beam paramters and propagate them
-    ##########################################################################
-
-
-
-#"""
-#      ><<                             ><<       ><<<<
-#   ><<   ><<                        ><        ><    ><<
-#  ><<           ><<     ><< ><<   ><>< ><    ><<            ><<     ><< ><<
-#  ><<         ><<  ><<   ><<  ><<   ><<      ><<          ><   ><<   ><<  ><<
-#  ><<        ><<    ><<  ><<  ><<   ><<      ><<   ><<<< ><<<<< ><<  ><<  ><<
-#   ><<   ><<  ><<  ><<   ><<  ><<   ><<       ><<    ><  ><          ><<  ><<
-#     ><<<<      ><<     ><<<  ><<   ><<        ><<<<<      ><<<<    ><<<  ><<
-#
-#"""
-    def configureGen( self, SpillOverSlots ):
-        """
-        Set up the generator execution sequence and its sub-phases
-        """
-
-##         if "Gen" not in self.getProp("MainSequence") :
-##             log.warning("No generator phase. Need input file")
-##             return
-
-        do_redecay = self.Redecay['active']
-        if self.evtMax() <= 0:
-            raise RuntimeError( "Generating events but selected '%s' events. Use LHCbApp().EvtMax " %self.evtMax() )
-
-        gaussGeneratorSeq = GaudiSequencer( "Generator", IgnoreFilterPassed = True )
-        gaussSeq = GaudiSequencer("GaussSequencer")
-        gaussSeq.Members += [ gaussGeneratorSeq ]
-
-        from Configurables import ( EvtGenDecay )
-        EvtGenDecay().DecayFile = "$DECFILESROOT/dkfiles/DECAY.DEC"
-
-
-        from Configurables import ( GenInit, Generation, MaskParticles )
-        for slot in SpillOverSlots:
-            genSequence = GaudiSequencer("GeneratorSlot"+self.slotName(slot)+"Seq" )
-            gaussGeneratorSeq.Members += [ genSequence ]
-
-            TESNode = "/Event/"+self.slot_(slot)
-            genInit = GenInit("GaussGen"+slot,
-                              MCHeader = TESNode+"Gen/Header")
-            if self.isGaussMP():
-                genInit.EvtCounter = "EvtCounter"
-
-            FSRNode = "/FileRecords/"+self.slot_(slot)
-
-            if slot != '':
-                genInitT0 = GenInit("GaussGen")
-                if genInitT0.isPropertySet("RunNumber"):
-                    genInit.RunNumber = genInitT0.RunNumber
-                if genInitT0.isPropertySet("FirstEventNumber"):
-                    genInit.FirstEventNumber = genInitT0.FirstEventNumber
-
-
-            genProc = 0
-            genType = self.getProp("Production").upper()
-            from Configurables import ParticleGun, MIBackground
-            KnownGenTypes = ['PHYS','PGUN','MIB']
-            if genType not in KnownGenTypes:
-                raise RuntimeError("Unknown Generation type '%s'"%genType)
-            if genType == 'PHYS':
-                genProc = Generation("Generation"+slot)
-            elif genType == 'PGUN':
-                genProc = ParticleGun("ParticleGun"+slot)
-            else:
-                genProc = MIBackground("MIBackground"+slot)
-
-            genProc.GenHeaderLocation = TESNode+"Gen/Header"
-            genProc.HepMCEventLocation = TESNode+"Gen/HepMCEvents"
-            genProc.GenCollisionLocation = TESNode+"Gen/Collisions"
-
-            if "GenFSRLocation" in genProc.properties():
-                if not genProc.isPropertySet("GenFSRLocation"):
-                    genProc.GenFSRLocation = FSRNode+"GenFSR"
-
-            if slot != '':
-                genProc.PileUpTool = 'FixedLuminosityForSpillOver'
-
-            if do_redecay:
-                # This filter checks if a new event needs to be generated,
-                # if not rest of the sequencer is not run.
-                gaussrdfilter = GaussRedecayCtrFilter('RegisterNewEvent{}'.format(slot))
-                gaussrdfilter.RegisterNewEvent = True
-                genSequence.Members += [ genInit, gaussrdfilter, genProc ]
-            else:
-                genSequence.Members += [ genInit , genProc ]
-            # When HC simulation is switched on the very forward protons must be
-            # removed from the HepMC record since they cause showers in it
-            if 'HC' in self.getProp('DetectorSim')['Detectors']:
-                genMask = MaskParticles("MaskDiffractiveProton"+slot,
-                                        HepMCEventLocation = TESNode+"Gen/HepMCEvents")
-                genSequence.Members += [genMask]
-
-            if slot == '' and do_redecay:
-                genSequence.Members += [ GaussRedecaySorter() ]
-
-
-    ## end of Gen configuration
-    ##########################################################################
-
-
-#"""
-#     ><<                             ><<    ><<<<<<<
-#  ><<   ><<                        ><       ><<    ><< ><<
-# ><<           ><<     ><< ><<   ><>< ><    ><<    ><< ><<         ><<      ><<<<     ><<      ><<<<
-# ><<         ><<  ><<   ><<  ><<   ><<      ><<<<<<<   >< ><     ><<  ><<  ><<      ><   ><<  ><<
-# ><<        ><<    ><<  ><<  ><<   ><<      ><<        ><<  ><< ><<   ><<    ><<<  ><<<<< ><<   ><<<
-#  ><<   ><<  ><<  ><<   ><<  ><<   ><<      ><<        ><   ><< ><<   ><<      ><< ><             ><<
-#    ><<<<      ><<     ><<<  ><<   ><<      ><<        ><<  ><<   ><< ><<< ><< ><<   ><<<<    ><< ><<
-#"""
-    def configurePhases( self, SpillOverSlots  ):
-        """
-        Set up the top level sequence and its phases
-        """
-
-        gaussSeq = GaudiSequencer("GaussSequencer")
-        ApplicationMgr().TopAlg = [ gaussSeq ]
-##         mainSeq = self.getProp("MainSequence")
-##         if len( mainSeq ) == 0:
-##             mainSeq = self.DefaultSequence
-
-##         mainSeq = map(lambda ph: ph.capitalize(), mainSeq)
-##         self.setProp("MainSequence",mainSeq)
-##         for phase in mainSeq:
-##             raise RuntimeError("Unknown phase '%s'"%phase)
-
-        # if the filter sequence is non-empty, add it here
-        if self.getProp("PostSimFilters") :
-            filterSeq = GaudiSequencer("PostSimFilterSeq")
-            if not self.getProp("SplitSim"):
-                ApplicationMgr().TopAlg += [ filterSeq ]
-            self.configurePostSimFilters( filterSeq )
-
-
-        ### Check for configuration consistency
-        if ( ( "GenToMCTree" in self.getProp("Phases") ) and ( "Simulation" in self.getProp("Phases") ) ):
-            raise RuntimeError("GenToMCTree and Simulation cannot be part of Phases simultaneously")
-
-        self.configureGen( SpillOverSlots )
-        if "GenToMCTree" in self.getProp("Phases"):
-            self.configureSkipGeant4( SpillOverSlots )
-
-        # Redecay and splitted simulation both hack the simulation sequence
-        # and need a specialised configuration and so does their combination,
-        # which are intertwined such that a combination is difficult
-        if self.Redecay['active'] and self.getProp("SplitSim"):
-            self.configureRedecaySplitSim( SpillOverSlots )
-            self.configureRedecay(SpillOverSlots)
-        elif self.Redecay['active'] and not self.getProp("SplitSim"):
-            self.configureRedecaySim( SpillOverSlots )
-            self.configureRedecay(SpillOverSlots)
-        elif self.getProp("SplitSim"):
-            self.configureSplitSim( SpillOverSlots )
-        else:
-            self.configureSim( SpillOverSlots )
-        self.configureMoni( SpillOverSlots ) #(expert or default)
-    ## end of phase configuration
-    ##########################################################################
-
-#"""
-# ><<<<<<<<  ><  ><    ><
-# ><<<<<<<<  ><  ><    ><
-# ><<            ><  ><><><     ><<     >< ><<<   ><<<
-# ><<<<<     ><  ><    ><     ><   ><<   ><<     ><<
-# ><<        ><  ><    ><    ><<<<< ><<  ><<       ><<<
-# ><<        ><  ><    ><    ><          ><<         ><<
-# ><<        ><  ><<<  ><<     ><<<<    ><<<      <<><<
-#
-#"""
-
-    def configurePostSimFilters(self, filterSeq):
-        # essentially just a list of ifs for the different filters...
-        for filter in self.PostSimFilters:
-            if filter in self.KnownPostSimFilters:
-                # check for the name of the know filters and add them one by one
-                if filter == "ConversionFilter":
-                    from Configurables import ConversionFilter
-                    filterSeq.Members.append( ConversionFilter("ConversionFilter") )
-            else:
-                raise RuntimeError("Unknown Filter '%s'"%filter)
-
-
-#"""
-# ><<<<<                    ><<       ><<<<                 ><<                       ><<
-# ><<   ><<               ><        ><<    ><<              ><<                       ><<
-# ><<    ><<    ><<     ><>< ><   ><<        ><< ><<  ><< ><>< >< >< ><<   ><<  ><< ><>< ><
-# ><<    ><<  ><   ><<    ><<     ><<        ><< ><<  ><<   ><<   ><  ><<  ><<  ><<   ><<
-# ><<    ><< ><<<<< ><<   ><<     ><<        ><< ><<  ><<   ><<   ><   ><< ><<  ><<   ><<
-# ><<   ><<  ><           ><<       ><<     ><<  ><<  ><<   ><<   ><< ><<  ><<  ><<   ><<
-# ><<<<<       ><<<<      ><<         ><<<<        ><<><<    ><<  ><<        ><<><<    ><<
-#                                                                 ><<
-#"""
-
-    def defineOutput( self, SpillOverSlots ):
-        """
-        Set up output stream according to phase processed, the spill-over slots and the type of output
-        """
-
-        #
-        knownOptions = ['NONE','GEN','XGEN','RGEN','SIM','XSIM']
-        output = self.getProp("OutputType").upper()
-        if output == 'NONE':
-            log.warning("No event data output produced")
-            return
-
-        simWriter = SimConf().writer()
-
-        # define default file extensions depending on the phase that has been run
-        fileDefaultExtension = ".gen"
-        fileAllowedExtension = [fileDefaultExtension]
-        if "GenToMCTree" in self.getProp("Phases"):
-            fileDefaultExtension = ".xgen"
-            fileAllowedExtension = [fileDefaultExtension, ".rgen"]
-        elif "Simulation" in self.getProp("Phases"):
-            fileDefaultExtension = ".sim"
-            fileAllowedExtension = [fileDefaultExtension, ".xsim"]
-
-        # choose the file extension from the one selected compatibly with the phase run
-        if output not in knownOptions:
-            print "WARNING: OutputType not supported. Use default for chosen phases : %s" %(fileDefaultExtension)
-        fileExtension = "." + output.lower()
-        if fileExtension not in fileAllowedExtension:
-            fileExtension = fileDefaultExtension
-            print "WARNING: OutputType not supported for this phase. Use default : %s" %(fileExtension)
-
-        # set saving or not of HepMC depending on chosen file extension
-        if SimConf().isPropertySet( "SaveHepMC" ):
-            print "WARNING: SimConf().SaveHepMC will be ignored. Value set by Gauss()"
-        saveHepMC = False
-        if fileExtension in ['.gen','.xgen','.xsim']:
-            saveHepMC = True
-        SimConf().setProp("SaveHepMC", saveHepMC )
-
-        outputFile=""
-        from GaudiConf import IOHelper
-        if simWriter.isPropertySet( "Output" ):
-            outputFile=IOHelper().undressFile(simWriter.getProp("Output"))
-        else:
-            outputFile=self.outputName() + fileExtension
-
-        # Merge genFSRs
-        if self.getProp("WriteFSR"):
-            seqGenFSR = GaudiSequencer("GenFSRSeq")
-            ApplicationMgr().TopAlg += [ seqGenFSR ]
-
-            if self.getProp("MergeGenFSR"):
-                seqGenFSR.Members += [ "GenFSRMerge" ]
-
-        IOHelper().outStream( outputFile, simWriter, self.getProp("WriteFSR") )
-
-        simWriter.RequireAlgs.append( 'GaussSequencer' )
-        if not FileCatalog().isPropertySet("Catalogs"):
-            FileCatalog().Catalogs = [ "xmlcatalog_file:NewCatalog.xml" ]
-
-#"""
-#
-# ><<<<<                    ><<   ><<       ><<                            ><<
-# ><<   ><<               ><      >< ><<   ><<<                       ><   ><<
-# ><<    ><<    ><<     ><>< ><   ><< ><< > ><<    ><<     ><< ><<       ><>< ><    ><<     >< ><<<  ><<<<
-# ><<    ><<  ><   ><<    ><<     ><<  ><<  ><<  ><<  ><<   ><<  ><< ><<   ><<    ><<  ><<   ><<    ><<
-# ><<    ><< ><<<<< ><<   ><<     ><<   ><  ><< ><<    ><<  ><<  ><< ><<   ><<   ><<    ><<  ><<      ><<<
-# ><<   ><<  ><           ><<     ><<       ><<  ><<  ><<   ><<  ><< ><<   ><<    ><<  ><<   ><<        ><<
-# ><<<<<       ><<<<      ><<     ><<       ><<    ><<     ><<<  ><< ><<    ><<     ><<     ><<<    ><< ><<
-#
-#"""
-
-    def defineMonitors( self ):
-
-        from Configurables import ApplicationMgr, AuditorSvc, SequencerTimerTool
-        ApplicationMgr().ExtSvc += [ 'AuditorSvc' ]
-        ApplicationMgr().AuditAlgorithms = True
-        AuditorSvc().Auditors += [ 'TimingAuditor' ]
-        #SequencerTimerTool().OutputLevel = WARNING
-
-        # Set printout level and longer algorithm" identifier in printout
-        MessageSvc().OutputLevel = INFO
-        #ToolSvc.EvtGenTool.OutputLevel = 4 is it still necessary to reduce print?
-        MessageSvc().setWarning.append( 'XmlGenericCnv' )
-        if not MessageSvc().isPropertySet("Format"):
-            MessageSvc().Format = '% F%24W%S%7W%R%T %0W%M'
-
-
-#"""
-#   ><< <<                                        ><<     ><<               ><<
-# ><<    ><<                                      ><<     ><<  ><           ><<
-#  ><<          ><<     ><<     ><<    ><<        ><<     ><<      ><<<<  ><>< ><    ><<      ><<<<
-#    ><<      ><<  ><<   ><<   ><<   ><   ><<     ><<<<<< ><< ><< ><<       ><<    ><<  ><<  ><<
-#       ><<  ><<   ><<    ><< ><<   ><<<<< ><<    ><<     ><< ><<   ><<<    ><<   ><<    ><<   ><<<
-# ><<    ><< ><<   ><<     ><><<    ><            ><<     ><< ><<     ><<   ><<    ><<  ><<      ><<
-#   ><< <<     ><< ><<<     ><<       ><<<<       ><<     ><< ><< ><< ><<    ><<     ><<     ><< ><<
-#"""
-
-    def saveHistos( self ):
-        """
-        Set up histogram service and file name unless done in job
-        """
-
-        # ROOT persistency for histograms
-        importOptions('$STDOPTS/RootHist.opts')
-        from Configurables import RootHistCnv__PersSvc
-        RootHistCnv__PersSvc('RootHistCnv').ForceAlphaIds = True
-
-        histOpt = self.getProp("Histograms").upper()
-        if histOpt not in self.KnownHistOptions:
-            raise RuntimeError("Unknown Histograms option '%s'"%histOpt)
-            # HistogramPersistency needed to read in histogram for calorimeter
-            # so do not set ApplicationMgr().HistogramPersistency = "NONE"
-            return
-
-        # If not saving histograms do not set the name of the file
-        if ( histOpt == 'NONE') :
-            log.warning("No histograms produced")
-            return
-
-        # Use a default histogram file name if not already set
-        if not HistogramPersistencySvc().isPropertySet( "OutputFile" ):
-            histosName = self.getProp("DatasetName")
-            histosName = self.outputName() + '-histos.root'
-            HistogramPersistencySvc().OutputFile = histosName
-
-
-
-
-
-
-
-
-#"""
-#GEO
-#Geo
-#
-#     ><<<<
-#   ><    ><<
-#  ><<            ><<        ><<
-#  ><<          ><   ><<   ><<  ><<
-#  ><<   ><<<< ><<<<< ><< ><<    ><<
-#   ><<    ><  ><          ><<  ><<
-#    ><<<<<      ><<<<       ><<
-#
-#"""
-
-
-
-    def defineGeoBasePieces( self, basePieces ):
-        #basePieces['BeforeMagnetRegion']=['Velo2Rich1']
-        basePieces['BeforeUpstreamRegion']  = []
-        basePieces['UpstreamRegion']        = []
-        basePieces['BeforeMagnetRegion']    = []
-        basePieces['MagnetRegion']          = []
-        basePieces['AfterMagnetRegion']     = []
-        basePieces['DownstreamRegion']      = []
-        basePieces['AfterDownstreamRegion'] = []
-
-        #basePieces['UpstreamRegion']=[]
-        #basePieces['BeforeMagnetRegion']=[]
-        #basePieces['MagnetRegion']=['PipeInMagnet','PipeSupportsInMagnet']
-        #basePieces['AfterMagnetRegion']=['PipeAfterT','PipeSupportsAfterMagnet']
-        #basePieces['DownstreamRegion']=['PipeDownstream','PipeSupportsDownstream','PipeBakeoutDownstream']
-
-    # This is where everything is parsed into geo items
-    def defineStreamItemsGeo( self, basePieces, detPieces ):
-        for region in basePieces.keys():
-            path = "/dd/Structure/LHCb/"+region+"/"
-            if len(detPieces[region])==0 : continue
-            # This should preserve order
-            for element in basePieces[region] + detPieces[region]:
-                myStreamItem = path + element
-                if myStreamItem not in self._listOfGeoObjects_:
-                    self._listOfGeoObjects_.append(myStreamItem)
-            #for element in detPieces[region]:
-            #    myStreamItem = path + element
-            #    if myStreamItem not in self._listOfGeoObjects_:
-            #        self._listOfGeoObjects_.append(myStreamItem)
-
-
-
-#"""
-#  ><<<<<                    ><<       ><<<<
-#  ><<   ><<               ><        ><    ><<
-#  ><<    ><<    ><<     ><>< ><    ><<            ><<        ><<
-#  ><<    ><<  ><   ><<    ><<      ><<          ><   ><<   ><<  ><<
-#  ><<    ><< ><<<<< ><<   ><<      ><<   ><<<< ><<<<< ><< ><<    ><<
-#  ><<   ><<  ><           ><<       ><<    ><  ><          ><<  ><<
-#  ><<<<<       ><<<<      ><<        ><<<<<      ><<<<       ><<
-#
-#"""
-
-    def defineDetectorGeo( self, basePieces, detPieces, det ):
-        import string
-        lDet = det.lower()
-        if lDet not in self.__knownDetectors__:
-            log.warning("Geo Detector not known : %s" %(det))
-
-        if lDet == "magnet":
-            self.defineMagnetGeo( basePieces, detPieces )
-        elif lDet == "puveto":
-            self.definePuVetoGeo( )
-        elif lDet == "velo":
-            self.defineVeloGeo( basePieces, detPieces )
-        elif lDet == "tt":
-            self.defineTTGeo( detPieces )
-        elif lDet == "it":
-            self.defineITGeo( detPieces )
-        elif lDet == "ot":
-            self.defineOTGeo( detPieces )
-        elif lDet == "muon":
-            self.defineMuonGeo( detPieces )
-        elif lDet == "rich1":
-            self.defineRich1GeoDet( detPieces )
-        elif lDet == "rich2":
-            self.defineRich2GeoDet( detPieces )
-        elif lDet == "spd":
-            self.defineSpdGeo( detPieces )
-        elif lDet == "prs":
-            self.definePrsGeo( detPieces )
-        elif lDet == "ecal":
-            self.defineEcalGeo( detPieces )
-        elif lDet == "hcal":
-            self.defineHcalGeo( detPieces )
-        elif lDet == "hc":
-            self.defineHCGeo(detPieces)
-        # GC - 20160323 Bcm and Bls off for now
-        ## elif lDet == "bcm":
-        ##     self.defineBcmGeo(detPieces)
-        ## elif lDet == "bls":
-        ##     self.defineBlsGeo(detPieces)
-        # Upgrade detectors below
-        elif lDet == "vp":
-            self.defineVPGeo( detPieces )
-        elif lDet == "torch":
-            self.defineTorchGeo()
-        elif (lDet == "ft") or (lDet == "ft-noshield"):
-            self.defineFTGeo( lDet, detPieces )
-        elif lDet == "rich1pmt":
-            self.defineRich1MaPmtGeoDet( detPieces )
-        elif lDet == "rich2pmt":
-            self.defineRich2MaPmtGeoDet( detPieces )
-        elif lDet == "ut":
-            self.defineUTGeo( detPieces )
-        elif lDet == "sl":
-            self.defineSLGeo( detPieces )
-        else:
-            log.warning("Geo Detector not known : %s" %(det))
-
-    def defineDetectorGeoStream ( self, geoCnvSvc, det ):
-        import string
-        lDet = det.lower()
-        if lDet not in self.__knownDetectors__:
-            log.warning("Geo Stream Detector not known : %s" %(det))
-
-        if lDet == "rich1":
-            self.defineRich1GeoStream()
-        elif lDet == "rich2":
-            self.defineRich2GeoStream()
-        elif lDet == "rich1pmt":
-            self.defineRich1MaPmtGeoStream( geoCnvSvc )
-        elif lDet == "rich2pmt":
-            self.defineRich2MaPmtGeoStream( geoCnvSvc )
-        elif lDet == "magnet":
-            self.defineMagnetGeoField()
-
-
-
-    def defineGDMLGeoStream ( self, geoCnvSvc ):
-        if self.getProp("ReplaceWithGDML"):
-            gdmlOpt = self.getProp("ReplaceWithGDML")
-            if gdmlOpt[0]["volsToReplace"]:
-                for gdmlDict in self.getProp("ReplaceWithGDML"):
-                    self.defineGDMLGeo ( geoCnvSvc, gdmlDict )
-
-
-
-
-    def defineGeo( self ):
-        # Define the simulated geometry
-        geo = GiGaInputStream( "Geo",
-                               ExecuteOnce = True,
-                               ConversionSvcName = "GiGaGeo",
-                               DataProviderSvcName  = "DetectorDataSvc" )
-
-        gaussSimulationSeq = GaudiSequencer("Simulation")
-
-        if not self.getProp('UseGaussGeo'):
-            gaussSimulationSeq.Members += [ geo ]
-
-        # Detector geometry to simulate
-        detPieces = {'BeforeUpstreamRegion':[], 'UpstreamRegion':[],
-                     'BeforeMagnetRegion':[], 'MagnetRegion':[], 'AfterMagnetRegion':[],
-                     'DownstreamRegion':[], 'AfterDownstreamRegion':[]}
-        #detPieces = {'BeforeMagnetRegion':[],'AfterMagnetRegion':[],'DownstreamRegion':[],'MagnetRegion':[]}
-        basePieces = {}
-
-        # Must be first!
-        # This used to list all the beampipe detector elements
-        # which are not "inside" another detector.
-        # i.e. top-level detector elements
-        # DDDB structure may change in future
-        self.defineGeoBasePieces( basePieces )
-
-        # Define beampipe
-        self.validateBeamPipeSwitch ( self.getProp("BeamPipe") )
-        if ("BeamPipeOn" == self.getProp("BeamPipe")):
-            # BeamPipe on - add BP elements
-            self.defineBeamPipeGeo ( basePieces, detPieces )
-
-        # Set geometry conversion service
-        geoCnvSvc = None
-        if self.getProp('UseGaussGeo'):
-            geoCnvSvc = GaussGeo()
-        else:
-            geoCnvSvc = GiGaGeo()
-
-        # Use information from SIMCOND and GeometryInfo
-        # Allows to be set to False by RichXPmt
-        geoCnvSvc.UseAlignment      = True
-        geoCnvSvc.AlignAllDetectors = True
-
-        # Define detectors
-        for det in self.getProp('DetectorGeo')['Detectors']:
-            det = "%s" %det
-            self.defineDetectorGeo( basePieces, detPieces, det )
-
-        # StreamItems definition needs to be after det definition
-        self.defineStreamItemsGeo( basePieces, detPieces )
-
-        # Define detector streams for RICHes
-        for det in self.getProp('DetectorGeo')['Detectors']:
-            det = "%s" %det
-            self.defineDetectorGeoStream( geoCnvSvc, det )
-
-        # Seperate Calo opts
-        # Returns a list containing all the elments common to both lists
-        if self.getProp('UseGaussGeo'):
-            if [det for det in ['Spd', 'Prs', 'Ecal', 'Hcal'] if det in self.getProp('DetectorGeo')['Detectors']]:
-                importOptions("$GAUSSCALOROOT/options/GaussGeo-Calo.py")
-        else:
-            if [det for det in ['Spd', 'Prs', 'Ecal', 'Hcal'] if det in self.getProp('DetectorGeo')['Detectors']]:
-                importOptions("$GAUSSCALOROOT/options/Calo.opts")
-
-
-        # Call GDML description
-        self.defineGDMLGeoStream( geoCnvSvc )
-
-        if self.getProp("Debug"):
-            print "\nDEBUG Detector Geometry Elements:"
-            print "\nkey : detPieces[key]"
-            for key in detPieces.keys():
-                print "%s : %s" %(key, detPieces[key])
-            print "\nkey : detPieces[key]"
-
-            for key in sorted(detPieces.keys()):
-                print "%s : %s" %(key, detPieces[key])
-
-            print "\nkey : basePieces[key]"
-            for key in basePieces.keys():
-                print "%s : %s" %(key, basePieces[key])
-
-            print "\nkey : Sorted basePieces[key]"
-            for key in sorted(basePieces.keys()):
-                print "%s : %s" %(key, basePieces[key])
-
-            print "\ngeo items:"
-            for item in self._listOfGeoObjects_:
-                print "%s" %(item)
-
-            print "\ngeo items SORTED:"
-            mySortedGeoStream = self._listOfGeoObjects_[:]
-            mySortedGeoStream.sort()
-            for item in mySortedGeoStream:
-                print "%s" %(item)
-
-        # No BP requested - therefore remove all elements from Geo.StreamItems
-        if ("BeamPipeOff" == self.getProp("BeamPipe")):
-            self.removeAllBeamPipeElements()
-
-        # Populate the list of geometry elements in the requested conversion service
-        for el in self._listOfGeoObjects_:
-            if self.getProp('UseGaussGeo'):
-                GaussGeo().GeoItemsNames.append(el)
-            else:
-                geo.StreamItems.append(el)
-
-
-#"""
-#     ><<                             ><<      ><< <<
-#  ><<   ><<                        ><       ><<    ><<  ><
-# ><<           ><<     ><< ><<   ><>< ><     ><<           ><<< ><< ><<
-# ><<         ><<  ><<   ><<  ><<   ><<         ><<     ><<  ><<  ><  ><<
-# ><<        ><<    ><<  ><<  ><<   ><<            ><<  ><<  ><<  ><  ><<
-#  ><<   ><<  ><<  ><<   ><<  ><<   ><<      ><<    ><< ><<  ><<  ><  ><<
-#    ><<<<      ><<     ><<<  ><<   ><<        ><< <<   ><< ><<<  ><  ><<
-#"""
-
-    def configureDetectorSim( self, slot, detHits, det, configuredRichSim ):
-        import string
-        det = det.lower()
-        if det not in self.__knownDetectors__:
-            log.warning("Sim Detector not known : %s" %(det))
-
-        if det == "puveto":
-            self.configurePuVetoSim( slot, detHits )
-        elif det == "velo":
-            self.configureVeloSim( slot, detHits )
-        elif det == "tt":
-            self.configureTTSim( slot, detHits )
-        elif det == "it":
-            self.configureITSim( slot, detHits )
-        elif det == "ot":
-            self.configureOTSim( slot, detHits )
-        elif det == "muon":
-            self.configureMuonSim( slot, detHits )
-        elif det in ['rich1', 'rich2']:
-            if not configuredRichSim[0]:
-                self.configureRichSim( slot, detHits )
-                configuredRichSim[0] = True
-        elif det == "spd":
-            self.configureSpdSim( slot, detHits )
-        elif det == "prs":
-            self.configurePrsSim( slot, detHits )
-        elif det == "ecal":
-            self.configureEcalSim( slot, detHits )
-        elif det == "hcal":
-            self.configureHcalSim( slot, detHits )
-        elif det == "hc":
-            self.configureHCSim(slot, detHits)
-        # GC - 20160323 Bcm and Bls off for now
-        ## elif det == "bcm":
-        ##    self.configureBcmSim(slot, detHits)
-        ## elif det == "bls":
-        ##    self.configureBlsSim(slot, detHits)
-        # Upgrade detectors below
-        elif det == "vp":
-            self.configureVPSim( slot, detHits )
-        elif det == "torch":
-            self.configureTorchSim( slot, detHits )
-        elif (det == "ft") or (det == "ft-noshield"):
-            self.configureFTSim( slot, detHits )
-        elif det in ['rich1pmt', 'rich2pmt']:
-            if not configuredRichSim[0]:
-                self.configureRichMaPmtSim( slot, detHits )
-                configuredRichSim[0] = True
-        elif det == "ut":
-            self.configureUTSim( slot, detHits )
-        elif det == "sl":
-            self.configureSLSim( slot, detHits )
-        else:
-            if det != "magnet":
-            ## Magnetic field defined in defineMagnetGeoField called
-            ## via defineDetectorGeoStream in defineGeo
-                log.warning("Sim Detector not known : %s" %(det))
-
-    ##
-    ##
-    def configureSim( self, SpillOverSlots ):
-
-        """
-        Set up the simulation sequence
-        """
-
-        if "Simulation" not in self.getProp("Phases"):
-            log.warning("No simulation phase.")
-            return
-
-        ApplicationMgr().ExtSvc += [ "GiGa" ]
-        EventPersistencySvc().CnvServices += [ "GiGaKine" ]
-
-        gaussSimulationSeq = GaudiSequencer( "Simulation" )
-        gaussSeq = GaudiSequencer("GaussSequencer")
-        gaussSeq.Members += [ gaussSimulationSeq ]
-
-        gigaStore = GiGaDataStoreAlgorithm( "GiGaStore" )
-        gigaStore.ConversionServices = [ "GiGaKine" ]
-        gaussSimulationSeq.Members += [ gigaStore ]
-
-        self.defineGeo()
-
-        self.configureGiGa()
-
-        if self.getProp('UseGaussGeo'):
-            GiGa().GeometrySource = "GaussGeo"
-        else:
-            GiGa().GeometrySource = "GiGaGeo"
-
-        for slot in SpillOverSlots:
-            TESNode = "/Event/"+self.slot_(slot)
-
-            mainSimSequence = GaudiSequencer( self.slotName(slot)+"EventSeq" )
-
-            gaussSimulationSeq.Members += [ mainSimSequence ]
-
-            mainSimSequence.Members +=  [ SimInit( self.slotName(slot)+"EventGaussSim",
-                                                   GenHeader = TESNode + "Gen/Header" ,
-                                                   MCHeader = TESNode + "MC/Header" ) ]
-
-            simSeq = GaudiSequencer( self.slotName(slot)+"Simulation",
-                                     RequireObjects = [ TESNode + "Gen/HepMCEvents" ] )
-            mainSimSequence.Members += [ simSeq ]
-
-            simSlotSeq = GaudiSequencer( "Make"+self.slotName(slot)+"Sim" )
-            simSeq.Members += [simSlotSeq]
-
-            # CRJ : Set RootInTES - Everything down stream will then use the correct location
-            #       (assuming they use GaudiAlg get and put) so no need to set data locations
-            #       by hand any more ...
-            if slot != '' : simSlotSeq.RootInTES = slot
-
-            genToSim = GenerationToSimulation( "GenToSim" + slot,
-                                               LookForUnknownParticles = True )
-            simSlotSeq.Members += [ genToSim ]
-
-            simSlotSeq.Members += [ GiGaFlushAlgorithm( "GiGaFlush"+slot ) ]
-            simSlotSeq.Members += [ GiGaCheckEventStatus( "GiGaCheckEvent"+slot ) ]
-            simToMC = SimulationToMCTruth( "SimToMCTruth"+slot )
-            simSlotSeq.Members += [ simToMC ]
-
-            ## Detectors hits
-            TESNode = TESNode + "MC/"
-            detHits = GaudiSequencer( "DetectorsHits" + slot )
-            simSlotSeq.Members += [ detHits ]
-
-            # Slight trick - configuredRichSim is a list and therefore MUTABLE!
-            configuredRichSim = [ False ]
-            for det in self.getProp('DetectorSim')['Detectors']:
-                self.configureDetectorSim( slot, detHits, det, configuredRichSim )
-
-
-            # Data packing ...
-            if self.getProp("EnablePack") :
-                packing = GaudiSequencer(self.slotName(slot)+"EventDataPacking")
-                simSlotSeq.Members += [ packing ]
-                SimConf().PackingSequencers[slot] = packing
-
-        # End of Sim Configuration
-
-
-
-
-#"""
-#  ><<       ><<
-#  >< ><<   ><<<                       ><
-#  ><< ><< > ><<    ><<     ><< ><<
-#  ><<  ><<  ><<  ><<  ><<   ><<  ><< ><<
-#  ><<   ><  ><< ><<    ><<  ><<  ><< ><<
-#  ><<       ><<  ><<  ><<   ><<  ><< ><<
-#  ><<       ><<    ><<     ><<<  ><< ><<
-#
-#
-#"""
-
-
-    def configureGeneratorMoni ( self, SpillOverSlots ):
-
-        # Monitors for the generator:
-        for slot in SpillOverSlots:
-
-            genSequence = GaudiSequencer("GeneratorSlot" + self.slotName(slot) + "Seq" )
-            genMoniSeq = GaudiSequencer("GenMonitor" + slot )
-            genSequence.Members += [ genMoniSeq ]
-
-            TESLocation = "/Event/"+self.slot_(slot)+"Gen/HepMCEvents"
-            genMoniSeq.Members += [
-                GenMonitorAlg(
-                "GenMonitorAlg"+slot,
-                HistoProduce=True,
-                Input = TESLocation
-                )
-                ]
-            #            if moniOpt == 'Debug':
-            #                genMoniSeq.Members += [ DumpHepMC( "DumpHepMC"+slot,
-            #                                                   OutputLevel=1,
-            #                                                   Addresses = [TESLocation] ) ]
-
-
-    def configureDetectorMoni(
-        self,
-        slot,
-        packCheckSeq,
-        detMoniSeq,
-        checkHits,
-        det,
-        configuredRichMoni
-        ):
-        import string
-        det = det.lower()
-        if det not in self.__knownDetectors__:
-            log.warning("Moni Detector not known : %s" %(det))
-
-        if det == "puveto":
-            self.configurePuVetoMoni( slot, packCheckSeq, detMoniSeq, checkHits )
-        elif det == "velo":
-            self.configureVeloMoni( slot, packCheckSeq, detMoniSeq, checkHits )
-        elif det == "tt":
-            self.configureTTMoni( slot, packCheckSeq, detMoniSeq, checkHits )
-        elif det == "it":
-            self.configureITMoni( slot, packCheckSeq, detMoniSeq, checkHits )
-        elif det == "ot":
-            self.configureOTMoni( slot, packCheckSeq, detMoniSeq, checkHits )
-        elif det == "muon":
-            self.configureMuonMoni( slot, packCheckSeq, detMoniSeq, checkHits )
-        # Since I'm switching on the subcomponents I shouldn't configure this twice.
-        elif (det == "rich1") or (det == "rich2"):
-            if not configuredRichMoni[0]:
-                self.configureRichMoni(
-                    slot,
-                    packCheckSeq,
-                    detMoniSeq,
-                    checkHits,
-                    configuredRichMoni
-                    )
-                configuredRichMoni[0] = True
-        elif det == "prs":
-            self.configurePrsMoni( slot, packCheckSeq, detMoniSeq, checkHits )
-        elif det == "spd":
-            self.configureSpdMoni( slot, packCheckSeq, detMoniSeq, checkHits )
-        elif det == "ecal":
-            self.configureEcalMoni( slot, packCheckSeq, detMoniSeq, checkHits )
-        elif det == "hcal":
-            self.configureHcalMoni( slot, packCheckSeq, detMoniSeq, checkHits )
-        elif det == "hc":
-            self.configureHCMoni(slot, packCheckSeq, detMoniSeq, checkHits)
-        # GC - 20160323 Bls and Bc off for now
-        ## elif det == "bcm":
-        ##     self.configureBcmMoni(slot, packCheckSeq, detMoniSeq, checkHits)
-        ## elif det == "bls":
-        ##     self.configureBlsMoni(slot, packCheckSeq, detMoniSeq, checkHits)
-        # Upgrade detectors below
-        elif det == "vp":
-            self.configureVPMoni( slot, packCheckSeq, detMoniSeq, checkHits )
-        elif det == "torch":
-            self.configureTorchMoni( slot, packCheckSeq, detMoniSeq, checkHits )
-        elif (det == "ft") or (det =="ft-noshield"):
-            self.configureFTMoni( slot, packCheckSeq, detMoniSeq, checkHits )
-        elif (det == "rich1pmt") or (det == "rich2pmt"):
-            if not configuredRichMoni[0]:
-                self.configureRichMaPmtMoni(
-                    slot,
-                    packCheckSeq,
-                    detMoniSeq,
-                    checkHits,
-                    configuredRichMoni
-                    )
-                configuredRichMoni[0] = True
-        elif det == "ut":
-            self.configureUTMoni( slot, packCheckSeq, detMoniSeq, checkHits )
-        elif det == "sl":
-            self.configureSLMoni( slot, packCheckSeq, detMoniSeq, checkHits )
-        else:
-            log.warning("Moni Detector not known : %s" %(det))
-
-    def resetCheckHits( self, checkHits ):
-        checkHits.TTHits     = ''
-        checkHits.OTHits     = ''
-        checkHits.ITHits     = ''
-        checkHits.PuVetoHits = ''
-        checkHits.VeloHits   = ''
-        checkHits.MuonHits   = ''
-        checkHits.RichHits   = ''
-        checkHits.CaloHits   = []
-
-        # checkHits has as default values:
-        # |-TTHits                    = 'MC/TT/Hits'
-        # |-OTHits                    = 'MC/OT/Hits'
-        # |-ITHits                    = 'MC/IT/Hits'
-        # |-PuVetoHits                = 'MC/PuVeto/Hits'
-        # |-VeloHits                  = 'MC/Velo/Hits'
-        # |-MuonHits                  = 'MC/Muon/Hits'
-        # |-RichTracks                = ''
-        # |-RichHits                  = 'MC/Rich/Hits'
-        # |-CaloHits                  = ['MC/Spd/Hits', 'MC/Prs/Hits', 'MC/Ecal/Hits', 'MC/Hcal/Hits']
-
-
-
-    def configureSimulationMoni( self, SpillOverSlots ):
-
-        configuredRichMoni = [ False , False ]
-
-        # Monitors for simulation
-        for slot in SpillOverSlots:
-            # Reset param to configure rich for slots.
-            configuredRichMoni[0] = False
-            TESNode = "/Event/"+self.slot_(slot)
-
-            simSequence = GaudiSequencer( self.slotName(slot)+"Simulation" )
-            simMoniSeq = GaudiSequencer( "SimMonitor" + slot )
-            simSequence.Members += [ simMoniSeq ]
-
-            # CRJ : Set RootInTES - Everything down stream will then use the correct location
-            #       (assuming they use GaudiAlg get and put) so no need to set data locations
-            #       by hand any more ...
-            if slot != '' : simMoniSeq.RootInTES = slot
-
-            # Basic monitors
-            simMoniSeq.Members += [
-                GiGaGetEventAlg("GiGaGet"+self.slotName(slot)+"Event"),
-                MCTruthMonitor( self.slotName(slot)+"MCTruthMonitor" ) ]
-
-            # can switch off detectors, or rather switch them on (see options
-            # of algorithm)
-            checkHits = GiGaGetHitsAlg( "GiGaGetHitsAlg" + slot )
-
-            # Possibly dangerous - set all strings to ''
-            # due to silly default values
-            self.resetCheckHits( checkHits )
-
-
-
-            simMoniSeq.Members += [ checkHits ]
-
-            # checkHits had default values:
-            # |-TTHits                    = 'MC/TT/Hits'
-            # |-OTHits                    = 'MC/OT/Hits'
-            # |-ITHits                    = 'MC/IT/Hits'
-            # |-PuVetoHits                = 'MC/PuVeto/Hits'
-            # |-VeloHits                  = 'MC/Velo/Hits'
-            # |-MuonHits                  = 'MC/Muon/Hits'
-            # |-RichTracks                = ''
-            # |-RichHits                  = 'MC/Rich/Hits'
-            # |-CaloHits                  = ['MC/Spd/Hits', 'MC/Prs/Hits', 'MC/Ecal/Hits', 'MC/Hcal/Hits']
-            # | (default: ['MC/Spd/Hits', 'MC/Prs/Hits', 'MC/Ecal/Hits', 'MC/Hcal/Hits'])
-
-
-            # Should add here the switching off of properties of
-            # GiGaGetHitsAlg when a given detector is not monitored
-            #self.configureTTMoni( checkHits )
-
-            # OverWrite some things if using VP
-            #self.configureVPMoni( checkHits )
-
-
-            #if moniOpt == 'Debug':
-            #    checkHits.OutputLevel = DEBUG
-
-            detMoniSeq = GaudiSequencer( "DetectorsMonitor" + slot )
-            simMoniSeq.Members += [ detMoniSeq ]
-
-            packCheckSeq = None
-            if self.getProp("EnablePack") and self.getProp("DataPackingChecks") :
-
-                packCheckSeq = GaudiSequencer( "DataUnpackTest"+slot )
-                simMoniSeq.Members += [packCheckSeq]
-
-                upMCV = UnpackMCVertex("UnpackMCVertex"+slot,
-                                       OutputName = "MC/VerticesTest" )
-                upMCP = UnpackMCParticle( "UnpackMCParticle"+slot,
-                                          OutputName = "MC/ParticlesTest" )
-                packCheckSeq.Members += [ upMCV, upMCP ]
-
-                compMCV = CompareMCVertex( "CompareMCVertex"+slot,
-                                           TestName = "MC/VerticesTest" )
-                compMCP = CompareMCParticle( "CompareMCParticle"+slot,
-                                             TestName = "MC/ParticlesTest" )
-                packCheckSeq.Members += [ compMCV, compMCP ]
-            #=================================================
-
-
-            # Define detectors
-            for det in self.getProp('DetectorMoni')['Detectors']:
-                self.configureDetectorMoni(slot, packCheckSeq, detMoniSeq, checkHits, det, configuredRichMoni)
-
-
-#"""
-#     ><<                             ><<    ><<<<<                  ><<              ><<<<<<<                      ><<
-#  ><<   ><<                        ><       ><<   ><<               ><<              ><<    ><<                    ><<
-# ><<           ><<     ><< ><<   ><>< ><    ><<    ><<    ><<     ><>< ><    ><<     ><<    ><<    ><<        ><<< ><<  ><<
-# ><<         ><<  ><<   ><<  ><<   ><<      ><<    ><<  ><<  ><<    ><<    ><<  ><<  ><<<<<<<    ><<  ><<   ><<    ><< ><<
-# ><<        ><<    ><<  ><<  ><<   ><<      ><<    ><< ><<   ><<    ><<   ><<   ><<  ><<        ><<   ><<  ><<     ><><<
-#  ><<   ><<  ><<  ><<   ><<  ><<   ><<      ><<   ><<  ><<   ><<    ><<   ><<   ><<  ><<        ><<   ><<   ><<    ><< ><<
-#    ><<<<      ><<     ><<<  ><<   ><<      ><<<<<       ><< ><<<    ><<    ><< ><<< ><<          ><< ><<<    ><<< ><<  ><<
-#
-#"""
-#    def configureDataPackingMoni( self, SpillOverSlots, simMoniSeq ):
-#        # Data packing checks
-#        for slot in SpillOverSlots:
-#            if self.getProp("EnablePack") and self.getProp("DataPackingChecks") :
-#
-#                packCheckSeq = GaudiSequencer( "DataUnpackTest"+slot )
-#                simMoniSeq.Members += [packCheckSeq]
-#
-#                upMCV = UnpackMCVertex("UnpackMCVertex"+slot,
-#                                       OutputName = "MC/VerticesTest" )
-#                upMCP = UnpackMCParticle( "UnpackMCParticle"+slot,
-#                                          OutputName = "MC/ParticlesTest" )
-#                packCheckSeq.Members += [ upMCV, upMCP ]
-#
-#                compMCV = CompareMCVertex( "CompareMCVertex"+slot,
-#                                           TestName = "MC/VerticesTest" )
-#                compMCP = CompareMCParticle( "CompareMCParticle"+slot,
-#                                             TestName = "MC/ParticlesTest" )
-#                packCheckSeq.Members += [ compMCV, compMCP ]
-#            #=================================================
-
-
-
-
-#"""
-#    ><<                             ><<    ><<       ><<
-# ><<   ><<                        ><       >< ><<   ><<<                       ><
-#><<           ><<     ><< ><<   ><>< ><    ><< ><< > ><<    ><<     ><< ><<
-#><<         ><<  ><<   ><<  ><<   ><<      ><<  ><<  ><<  ><<  ><<   ><<  ><< ><<
-#><<        ><<    ><<  ><<  ><<   ><<      ><<   ><  ><< ><<    ><<  ><<  ><< ><<
-# ><<   ><<  ><<  ><<   ><<  ><<   ><<      ><<       ><<  ><<  ><<   ><<  ><< ><<
-#   ><<<<      ><<     ><<<  ><<   ><<      ><<       ><<    ><<     ><<<  ><< ><<
-#
-#"""
-
-
-
-
-    def configureMoni( self, SpillOverSlots ):
-        self.configureGeneratorMoni( SpillOverSlots )
-        # Per-detector configuration done here:
-        self.configureSimulationMoni( SpillOverSlots )
-        #self.configureDataPackingMoni( SpillOverSlots , simMoniSeq )
-
-        #if histOpt == 'Expert':
-        #    # For the moment do nothing
-        #    log.Warning("Not yet implemented")
-
-        # END OF MONI CONFIG
-
-
-
-
-
-
-
-#"""
-#     ><<                             ><<       ><<<<
-#  ><<   ><<                        ><        ><    ><<   ><
-# ><<           ><<     ><< ><<   ><>< ><    ><<                ><<       ><<
-# ><<         ><<  ><<   ><<  ><<   ><<      ><<         ><<  ><<  ><<  ><<  ><<
-# ><<        ><<    ><<  ><<  ><<   ><<      ><<   ><<<< ><< ><<   ><< ><<   ><<
-#  ><<   ><<  ><<  ><<   ><<  ><<   ><<       ><<    ><  ><<  ><<  ><< ><<   ><<
-#    ><<<<      ><<     ><<<  ><<   ><<        ><<<<<    ><<      ><<    ><< ><<<
-#                                                              ><<
-#"""
-    ##
-    ##
-    def configureGiGa(self , skipG4 = False ):
-         """
-         Set up the configuration for the G4 settings: physics list, cuts and actions
-         """
-         richUpgradeConfig = False
-         UpgradeRichPmtDetector=False
-         Run1Run2RichDetector=False
-
-         giga = GiGa()
-
-
-         # PSZ - Use self.getProp('DataType') in future
-         # This modification now being applied.  SE
-         if self.getProp("DataType") == "Upgrade" :
-             richUpgradeConfig=True
-
-         # Do some sanity checks for RICH
-         if [det for det in ['Rich1Pmt', 'Rich2Pmt'] if det in self.getProp('DetectorSim')['Detectors']]:
-             UpgradeRichPmtDetector = True
-             if richUpgradeConfig == False :
-                 log.warning( "Incompatible Datatype and Detector configuration for RICH Upgrade. Please check your Configration" )
-             else:
-                 log.info( "Using RICH simulation  configuration for Upgrade Run ")
-
-
-         if [det for det in ['Rich1', 'Rich2'] if det in self.getProp('DetectorSim')['Detectors']]:
-             Run1Run2RichDetector = True
-             if richUpgradeConfig == True :
-                 log.warning( "Incompaticle Datatype and Detector configuration for RICH in RUN1 and RUN2. Please check your Configuration")
-             else:
-                 log.info( "Using RICH simulation configuration for RUN1 and RUN2 ")
-
-         #end of sanity checks for RICH
-
-
-
-         ## setup the Physics list and the productions cuts
-         ## the following 2 lines commented out.
-         #if skipG4:
-         #    richPmt = False
-
-         self.setPhysList(richUpgradeConfig)
-
-         ## Mandatory G4 Run action
-         giga.addTool( GiGaRunActionSequence("RunSeq") , name="RunSeq" )
-         giga.RunAction = "GiGaRunActionSequence/RunSeq"
-         if not skipG4:
-             giga.RunSeq.addTool( TrCutsRunAction("TrCuts") , name = "TrCuts" )
-             # To simulate Herschel or BCM, we need to change the default cuts.
-             if 'HC' in self.getProp('DetectorSim')['Detectors']:
-               giga.RunSeq.TrCuts.MinZ = -125.0 * SystemOfUnits.m
-               giga.RunSeq.TrCuts.MaxZ =  125.0 * SystemOfUnits.m
-             # GC - 20160323 Bcm off for now
-             ## elif 'Bcm' in self.getProp('DetectorSim')['Detectors']:
-             ##   giga.RunSeq.TrCuts.MinZ = -25.0 * SystemOfUnits.m
-             giga.RunSeq.Members += [ "TrCutsRunAction/TrCuts" ]
-             giga.RunSeq.addTool( GiGaRunActionCommand("RunCommand") , name = "RunCommand" )
-             giga.RunSeq.Members += [ "GiGaRunActionCommand/RunCommand" ]
-             giga.RunSeq.RunCommand.BeginOfRunCommands = [
-                 "/tracking/verbose 0",
-                 "/tracking/storeTrajectory  1",
-                 "/process/eLoss/verbose -1" ]
-             if self.getProp("SaveGDML") != "":
-                 from Configurables import GDMLRunAction
-                 propval = self.getProp("SaveGDML")
-                 propval = propval.split(':')
-
-                 giga.RunSeq.addTool( GDMLRunAction(), "GDMLRunAction" )
-                 giga.RunSeq.Members.append( "GDMLRunAction" )
-                 if len(propval) == 2:
-                    giga.RunSeq.GDMLRunAction.Output = propval[0]
-                    giga.RunSeq.GDMLRunAction.Schema = propval[1]
-                 else:
-                    giga.RunSeq.GDMLRunAction.Output = propval[0]
-
-
-         giga.EventAction = "GiGaEventActionSequence/EventSeq"
-         giga.addTool( GiGaEventActionSequence("EventSeq") , name="EventSeq" )
-         giga.EventSeq.Members += [ "GaussEventActionHepMC/HepMCEvent" ]
-
-         giga.TrackingAction =   "GiGaTrackActionSequence/TrackSeq"
-         giga.addTool( GiGaTrackActionSequence("TrackSeq") , name = "TrackSeq" )
-         giga.TrackSeq.Members += [ "GaussPreTrackAction/PreTrack" ]
-
-         giga.SteppingAction =   "GiGaStepActionSequence/StepSeq"
-         giga.addTool( GiGaStepActionSequence("StepSeq") , name = "StepSeq" )
-
-         #Now Configure the  RICH Simulation. The old setup using options is kept for backward
-         #compatibility and may be removed in the future.
-
-         # RICH simulation configuration
-         if (richUpgradeConfig):
-             if (self.getProp("UpgradeRICHSimRunOption") != "clunker"):
-                mGaussCherenkovConf = GaussCherenkovConf()
-                mGaussCherenkovConf.InitializeGaussCherenkovConfiguration()
-                mGaussCherenkovConf.setUpgradeRichDetExistFlag(UpgradeRichPmtDetector)
-                mGaussCherenkovConf.setSkipUpgradeGeant4Flag(skipG4)
-                mGaussCherenkovConf.ApplyGaussCherenkovConfiguration(giga)
-
-             else:
-                 #keep the old options for backward compatibility for now. It may be removed in the future
-                 #The method has the following in but it shoul not be tied to the RICH!!
-                 #SimulationSvc().SimulationDbLocation = "$GAUSSROOT/xml/Simulation.xml"
-
-                 self.GaussCherenkovOldSetup(giga,UpgradeRichPmtDetector,skipG4 )
-         else:
-
-             if (self.getProp("CurrentRICHSimRunOption") != "clunker" ):
-                mGaussRICHConf= GaussRICHConf()
-                mGaussRICHConf.InitializeGaussRICHConfiguration()
-                mGaussRICHConf.setRichDetectorExistFlag(Run1Run2RichDetector)
-                mGaussRICHConf.setSkipGeant4RichFlag(skipG4 )
-                mGaussRICHConf.ApplyGaussRICHConfiguration(giga)
-
-             else:
-                 #keep the old options for backward compatibility for now. It may be removed in the future.
-                 self.GaussRICHOldSetup(giga,Run1Run2RichDetector ,skipG4 )
-
-         # End of RICH simulation configuration
-
-         giga.TrackSeq.Members += [ "GaussPostTrackAction/PostTrack" ]
-         giga.TrackSeq.Members += [ "GaussTrackActionHepMC/HepMCTrack" ]
-         giga.TrackSeq.addTool( GaussPostTrackAction("PostTrack") , name = "PostTrack" )
-
-         giga.TrackSeq.PostTrack.StoreAll          = False
-         giga.TrackSeq.PostTrack.StorePrimaries    = True
-         giga.TrackSeq.PostTrack.StoreMarkedTracks = True
-         giga.TrackSeq.PostTrack.StoreForcedDecays = True
-         giga.TrackSeq.PostTrack.StoreByOwnEnergy   = True
-         giga.TrackSeq.PostTrack.OwnEnergyThreshold = 100.0 * SystemOfUnits.MeV
-
-         giga.TrackSeq.PostTrack.StoreByChildProcess  = True
-         giga.TrackSeq.PostTrack.StoredChildProcesses = [ "RichG4Cerenkov", "Decay" ]
-         giga.TrackSeq.PostTrack.StoreByOwnProcess  = True
-         giga.TrackSeq.PostTrack.StoredOwnProcesses = [ "Decay" ]
-         giga.StepSeq.Members += [ "GaussStepAction/GaussStep" ]
-
-
-         giga.addTool( GiGaRunManager("GiGaMgr") , name="GiGaMgr" )
-         giga.GiGaMgr.RunTools += [ "GiGaSetSimAttributes" ]
-         giga.GiGaMgr.RunTools += [ "GiGaRegionsTool" ]
-         giga.GiGaMgr.addTool( GiGaSetSimAttributes() , name = "GiGaSetSimAttributes" )
-         giga.GiGaMgr.GiGaSetSimAttributes.OutputLevel = 4
-
-         # Second part went here
-
-         #return giga
-
-    def GaussRICHOldSetup(self,giga,Run1Run2RichDetector=True, skipG4=False):
-        #Old setup for GaussRICH which can be removed in the future.
-
-        from Configurables import ( GiGaPhysConstructorOp,GiGaPhysConstructorHpd )
-        if self.getProp("DataType") in self.Run2DataTypes :
-            # Line to remove AEROGEL warnings
-            SimulationSvc().SimulationDbLocation = "$GAUSSROOT/xml/SimulationRICHesOff.xml"
-        else:
-            SimulationSvc().SimulationDbLocation = "$GAUSSROOT/xml/Simulation.xml"
-
-        giga.ModularPL.addTool( GiGaPhysConstructorOp,name = "GiGaPhysConstructorOp" )
-        giga.ModularPL.addTool( GiGaPhysConstructorHpd,name = "GiGaPhysConstructorHpd" )
-        if Run1Run2RichDetector:
-            importOptions("$GAUSSRICHROOT/options/Rich.opts")
-            if self.getProp("DataType") in self.Run2DataTypes :
-                importOptions("$GAUSSRICHROOT/options/RichRemoveAerogel.opts")
-
-            giga.ModularPL.GiGaPhysConstructorOp.RichActivateRichPhysicsProcVerboseTag = True
-            giga.StepSeq.Members += [ "RichG4StepAnalysis4/RichStepAgelExit" ]
-            giga.StepSeq.Members += [ "RichG4StepAnalysis5/RichStepMirrorRefl" ]
-            if self.getProp("RICHRandomHits") == True :
-                giga.ModularPL.GiGaPhysConstructorOp.Rich2BackgrHitsActivate = True
-                giga.ModularPL.GiGaPhysConstructorOp.Rich2BackgrHitsProbabilityFactor = 0.5
-        else:
-            if not skipG4:
-                giga.ModularPL.GiGaPhysConstructorOp.RichOpticalPhysicsProcessActivate = False
-                giga.ModularPL.GiGaPhysConstructorHpd.RichHpdPhysicsProcessActivate = False
-
-
-    def GaussCherenkovOldSetup(self, giga, UpgradeRichPmtDetector=True, skipG4=False):
-        #Old set up for GaussCherenkov which can removed in the future
-        from Configurables import ( GiGaPhysConstructorOpCkv, GiGaPhysConstructorPhotoDetector)
-        # Line to remove AEROGEL warnings
-        SimulationSvc().SimulationDbLocation = "$GAUSSROOT/xml/SimulationRICHesOff.xml"
-        if UpgradeRichPmtDetector :
-            importOptions("$GAUSSCHERENKOVROOT/options/GaussCherenkov.opts")
-            giga.ModularPL.addTool( GiGaPhysConstructorOpCkv, name="GiGaPhysConstructorOpCkv" )
-            giga.ModularPL.addTool(GiGaPhysConstructorPhotoDetector, name="GiGaPhysConstructorPhotoDetector")
-            giga.ModularPL.GiGaPhysConstructorOpCkv.RichActivateRichPhysicsProcVerboseTag = True
-            giga.StepSeq.Members += [ "RichG4StepAnalysis4/RichStepAgelExit" ]
-            giga.StepSeq.Members += [ "RichG4StepAnalysis5/RichStepMirrorRefl" ]
-            if skipG4:
-                giga.ModularPL.GiGaPhysConstructorOpCkv.RichOpticalPhysicsProcessActivate = False
-                giga.ModularPL.GiGaPhysConstructorPhotoDetector.RichPmtPhysicsProcessActivate = False
-
-
-
-
-#"""
-#
-#     ><<                             ><<       ><<<<
-#  ><<   ><<                        ><        ><    ><<        ><<
-# ><<           ><<     ><< ><<   ><>< ><    ><<             > ><<
-# ><<         ><<  ><<   ><<  ><<   ><<      ><<            >< ><<
-# ><<        ><<    ><<  ><<  ><<   ><<      ><<   ><<<<  ><<  ><<
-#  ><<   ><<  ><<  ><<   ><<  ><<   ><<       ><<    ><  ><<<< >< ><<
-#    ><<<<      ><<     ><<<  ><<   ><<        ><<<<<          ><<
-#
-#
-#"""
-
-    ##
-    ## Configure the sequence to transform HepMC into MCParticles
-    ## skipping Geant4
-    def configureSkipGeant4( self, SpillOverSlots ):
-
-        """
-        Set up the sequence to transform HepMC into MCParticles
-        """
-
-        if "GenToMCTree" not in self.getProp("Phases"):
-            log.warning("No GenToMCTree phase.")
-            return
-
-        # Do not do detector simulation in this case
-        self.getProp('DetectorSim')['Detectors'] = []
-        self.getProp('DetectorGeo')['Detectors'] = []
-        self.getProp('DetectorMoni')['Detectors'] = []
-
-        ApplicationMgr().ExtSvc += [ "GiGa" ]
-
-        gaussSkipGeant4Seq = GaudiSequencer( "SkipGeant4" )
-        gaussSeq = GaudiSequencer("GaussSequencer")
-        gaussSeq.Members += [ gaussSkipGeant4Seq ]
-
-        self.configureGiGa( True )
-
-        for slot in SpillOverSlots:
-
-            TESNode = "/Event/"+self.slot_(slot)
-
-            mainSkipGeant4Sequence = GaudiSequencer( self.slotName(slot)+"EventSeq" )
-
-            gaussSkipGeant4Seq.Members += [ mainSkipGeant4Sequence ]
-
-            mainSkipGeant4Sequence.Members +=  [ SimInit( self.slotName(slot)+"EventGaussSkipGeant4",
-                                                          GenHeader = TESNode + "Gen/Header" ,
-                                                          MCHeader = TESNode + "MC/Header" ) ]
-
-            skipGeant4Seq = GaudiSequencer( self.slotName(slot)+"SkipGeant4",
-                                            RequireObjects = [ TESNode + "Gen/HepMCEvents" ] )
-            mainSkipGeant4Sequence.Members += [ skipGeant4Seq ]
-
-            skipGeant4SlotSeq = GaudiSequencer( "Make"+self.slotName(slot)+"SkipGeant4" )
-            skipGeant4Seq.Members += [skipGeant4SlotSeq]
-
-            # CRJ : Set RootInTES - Everything down stream will then use the correct location
-            #       (assuming they use GaudiAlg get and put) so no need to set data locations
-            #       by hand any more ...
-            if slot != '' : skipGeant4SlotSeq.RootInTES = slot
-
-            genToSim = GenerationToSimulation( "GenToSim" + slot,
-                                               SkipGeant = True )
-            skipGeant4SlotSeq.Members += [ genToSim ]
-
-            # Data packing ...
-            if self.getProp("EnablePack") :
-                packing = GaudiSequencer(self.slotName(slot)+"EventDataPacking")
-                skipGeant4SlotSeq.Members += [ packing ]
-                SimConf().PackingSequencers[slot] = packing
-
-
-#"""
-#   ><< <<                ><<      ><<<<<<<
-# ><<    ><<              ><<      ><<    ><< ><<
-#  ><<          ><<     ><>< ><    ><<    ><< ><<      ><<   ><<  ><<<<
-#    ><<      ><   ><<    ><<      ><<<<<<<   >< ><     ><< ><<  ><<
-#       ><<  ><<<<< ><<   ><<      ><<        ><<  ><<    ><<<     ><<<
-# ><<    ><< ><           ><<      ><<        ><   ><<     ><<       ><<
-#   ><< <<     ><<<<       ><<     ><<        ><<  ><<    ><<    ><< ><<
-#                                                       ><<
-#"""
-
-    def setPhysList( self, richUpgradeConfig ):
-
-        giga = GiGa()
-        giga.addTool( GiGaPhysListModular("ModularPL") , name="ModularPL" )
-        giga.PhysicsList = "GiGaPhysListModular/ModularPL"
-        gmpl = giga.ModularPL
-
-        ## set production cuts
-        ecut = 5.0 * SystemOfUnits.mm
-        if not self.getProp("DeltaRays"):
-            ecut = 10000.0 * SystemOfUnits.m
-        print 'Ecut value =', ecut
-        gmpl.CutForElectron = ecut
-        gmpl.CutForPositron = 5.0 * SystemOfUnits.mm
-        gmpl.CutForGamma    = 5.0 * SystemOfUnits.mm
-
-        ## set up the physics list
-        hadronPhys = self.getProp('PhysicsList')['Hadron']
-        emPhys     = self.getProp('PhysicsList')['Em']
-        lhcbPhys   = self.getProp('PhysicsList')['LHCbPhys']
-        genPhys    = self.getProp('PhysicsList')['GeneralPhys']
-        otherPhys  = ''
-        if self.getProp('PhysicsList').has_key('Other'):
-            otherPhys = self.getProp('PhysicsList')['Other']
-
-        def gef(name):
-            import Configurables
-            return getattr(Configurables, "GiGaExtPhysics_%s_" % name)
-        def addConstructor(template, name):
-            gmpl.addTool(gef(template), name = name)
-            gmpl.PhysicsConstructors.append(getattr(gmpl, name))
-
-        ## --- EM physics:
-        if  (emPhys == "Opt1"):
-            addConstructor("G4EmStandardPhysics_option1", "EmOpt1Physics")
-        elif(emPhys == "Opt2"):
-            addConstructor("G4EmStandardPhysics_option2", "EmOpt2Physics")
-        elif(emPhys == "Opt3"):
-            addConstructor("G4EmStandardPhysics_option3", "EmOpt3Physics")
-        elif(emPhys == "Std"):
-            addConstructor("G4EmStandardPhysics", "EmPhysics")
-        elif(emPhys == "NoCuts"):
-            addConstructor("G4EmStandardPhysics_option1NoApplyCuts", "EmOpt1NoCutsPhysics")
-        elif(emPhys.find("LHCb") != -1):
-            if(emPhys.find("Test") != -1 ):
-                addConstructor("G4EmStandardPhysics_LHCbTest", "EmOpt1LHCbPhysics")
-            else:
-                addConstructor("G4EmStandardPhysics_option1LHCb", "EmOpt1LHCbPhysics")
-            # overwrite cuts depending on choice of list
-            if(emPhys.find("NoCuts") != -1 ):
-                gmpl.EmOpt1LHCbPhysics.ApplyCuts = False
-            if(emPhys.find("OldForE") != -1 ):
-                gmpl.EmOpt1LHCbPhysics.NewModelForE = False
-
-            #gmpl.EmOpt1LHCbPhysics.OutputLevel = VERBOSE
-        else:
-            raise RuntimeError("Unknown Em PhysicsList chosen ('%s')"%emPhys)
-
-        ## --- general  physics (common to all PL):
-        if (genPhys == True):
-        ## Decays
-            addConstructor("G4DecayPhysics", "DecayPhysics" )
-        ## EM physics: Synchroton Radiation & gamma,electron-nuclear Physics
-            addConstructor("G4EmExtraPhysics", "EmExtraPhysics")
-        ## Hadron physics: Hadron elastic scattering
-        ##    addConstructor("G4HadronElasticPhysics", "ElasticPhysics")
-        ## now specialised for different constructors
-        ## Ions physics
-            addConstructor("G4IonPhysics", "IonPhysics")
-        elif (genPhys == False):
-            log.warning("The general physics (Decays, hadron elastic, ion ...) is disabled")
-        else:
-            raise RuntimeError("Unknown setting for GeneralPhys PhysicsList chosen ('%s')"%genPhys)
-
-        ## --- Hadron physics:
-        if(hadronPhys == "QGSP_BERT"):
-            addConstructor("G4HadronElasticPhysics", "ElasticPhysics")
-            addConstructor("G4HadronPhysicsQGSP_BERT", "QGSP_BERTPhysics")
-            addConstructor("G4StoppingPhysics", "StoppingPhysics")
-            addConstructor("G4NeutronTrackingCut", "NeutronTrkCut")
-        elif(hadronPhys == "QGSP_BERT_HP"):
-            addConstructor("G4HadronElasticPhysicsHP", "ElasticPhysicsHP")
-            addConstructor("G4HadronPhysicsQGSP_BERT_HP", "QGSP_BERT_HPPhysics")
-            addConstructor("G4StoppingPhysics", "StoppingPhysics")
-            # overwrite the defaut value of the HighPrecision property of the
-            # G4HadronElasticPhysics constructor: no longer true, use dedicated
-            # constructor
-            #gmpl.ElasticPhysics.HighPrecision = True
-            #gmpl.ElasticPhysics.OutputLevel = VERBOSE
-        elif(hadronPhys == "QGSP_FTFP_BERT"):
-            addConstructor("G4HadronElasticPhysics", "ElasticPhysics")
-            addConstructor("G4HadronPhysicsQGSP_FTFP_BERT", "QGSP_FTFP_BERTPhysics")
-            addConstructor("G4StoppingPhysics", "StoppingPhysics")
-            addConstructor("G4NeutronTrackingCut", "NeutronTrkCut")
-        elif(hadronPhys == "FTFP_BERT"):
-            addConstructor("G4HadronElasticPhysics", "ElasticPhysics")
-            addConstructor("G4HadronPhysicsFTFP_BERT", "FTFP_BERTPhysics")
-            addConstructor("G4StoppingPhysics", "StoppingPhysics")
-            addConstructor("G4NeutronTrackingCut", "NeutronTrkCut")
-        elif(hadronPhys == "FTFP_BERT_HP"):
-            addConstructor("G4HadronElasticPhysicsHP", "ElasticPhysicsHP")
-            addConstructor("G4HadronPhysicsFTFP_BERT_HP", "FTFP_BERT_HPPhysics")
-            addConstructor("G4StoppingPhysics", "StoppingPhysics")
-        else:
-            raise RuntimeError("Unknown Hadron PhysicsList chosen ('%s')"%hadronPhys)
-
-
-        # Add Redecay tag particle physics list if necessary
-        # This is also necessary for the pure SplitSim setting as the ReDecay
-        # infrastructure is used.
-        if self.Redecay['active'] or self.getProp("SplitSim"):
-            from Configurables import GiGaPhysG4RDTag
-            gmpl.addTool(GiGaPhysG4RDTag)
-            gmpl.PhysicsConstructors.append(gmpl.GiGaPhysG4RDTag)
-
-
-        ## --- LHCb specific physics:
-        if  (lhcbPhys == True):
-            if (richUpgradeConfig == True):
-                self.defineRichMaPmtPhys(gmpl)
-            else:
-                self.defineRichPhys(gmpl)
-
-        ## LHCb particles unknown to default Geant4
-            gmpl.PhysicsConstructors.append("GiGaPhysUnknownParticles")
-        elif (lhcbPhys == False):
-            log.warning("The lhcb-related physics (RICH processed, UnknownParticles) is disabled")
-        else:
-            raise RuntimeError("Unknown setting for LHCbPhys PhysicsList chosen ('%s')"%lhcbPhys)
-
-        ## and other exotic physics
-        if (otherPhys == 'Higgs'):
-            log.info("Enabling physics processe for Higgs particles")
-            gmpl.PhysicsConstructors.append("GiGaHiggsParticles")
-        else:
-            if (otherPhys != '' ):
-               raise RuntimeError("Unknown setting for OtherPhys PhysicsList chosen ('%s')"%otherPhys)
-
-        ## --- user physics cuts
-        prodCuts = self.getProp('UserProductionCuts')
-        if prodCuts:
-            assert isinstance(prodCuts, dict)
-            self.applyPhysicsCuts(gmpl, prodCuts, 'mm')
-
-        trackCuts = self.getProp('UserTrackingCuts')
-        if trackCuts:
-            assert isinstance(trackCuts, dict)
-            giga.addTool( GiGaRunActionSequence('RunSeq') , name='RunSeq' )
-            gtr = giga.RunSeq.addTool( TrCutsRunAction('TrCuts') , name = 'TrCuts' )
-            self.applyPhysicsCuts(gtr, trackCuts, 'MeV')
-
-    def applyPhysicsCuts(self, gigaTool, cuts, units):
-        """Apply custom production and tracking cuts if set by user.
-        Can be used to set any other GiGa tool properties.
-        gigaTool: the GiGa.RunSeq tool to set the cuts
-        cuts: A dictionary of cuts from the configuration
-        units: Default units for the property (i.e the relevant unit of value 1.0 in GaudiKernel.SystemOfUnits.
-               Used for log message formatting only.)
-        """
-        for cutAttr, cutVal in cuts.iteritems():
-            try:
-                setattr(gigaTool, cutAttr, cutVal)
-            except AttributeError:
-                raise RuntimeError('Unknown physics cut {}'.format(cutAttr))
-            print 'Custom Physics Cut Set: {} Set To {} {}'.format(cutAttr, cutVal, units)
-
-#"""
-#      ><                           ><<                 ><<                             ><<
-#     >< <<                         ><<              ><<   ><<                        ><
-#    ><  ><<     >< ><<   >< ><<    ><< ><<   ><<   ><<           ><<     ><< ><<   ><>< ><
-#   ><<   ><<    ><  ><<  ><  ><<   ><<  ><< ><<    ><<         ><<  ><<   ><<  ><<   ><<
-#  ><<<<<< ><<   ><   ><< ><   ><<  ><<    ><<<     ><<        ><<    ><<  ><<  ><<   ><<
-# ><<       ><<  ><< ><<  ><< ><<   ><<     ><<      ><<   ><<  ><<  ><<   ><<  ><<   ><<
-#><<         ><< ><<      ><<      ><<<    ><<         ><<<<      ><<     ><<<  ><<   ><<
-#                ><<      ><<            ><<
-#"""
-
-    ##
-    ##
-    ## Apply the configuration
-    def __apply_configuration__(self):
-
-        GaudiKernel.ProcessJobOptions.PrintOff()
-
-        #defineDB() in Boole and
-        self.configureRndmEngine()
-        self.configureInput()  #defineEvents() in both Boole and Brunel
-        LHCbApp( Simulation = True ) # in Boole? where?
-
-        # raise an error if DetectorGeo/Sim/Moni dictionaries are incompatible
-        self.checkGeoSimMoniDictionary()
-
-        self.checkIncompatibleDetectors()
-
-        self.setLHCbAppDetectors()
-
-        #propagate info to SimConf
-        self.propagateSimConf()
-
-        #Construct Crossing List
         crossingList = self.defineCrossingList()
 
-        # We want to pass this GenInit object to configure phases later
-        from Configurables import ( Generation )
-        genInitPrime = GenInit( "GaussGen" )
-
-        self.setBeamParameters( crossingList, genInitPrime )
-        # PSZ - everything happens here
-        self.configurePhases( crossingList  )  # in Boole, defineOptions() in Brunel
-
-
-        #--Configuration of output files and 'default' outputs files that can/should
-        #--be overwritten in Gauss-Job.py
-        self.defineOutput( crossingList )
-
-        self.defineMonitors()
-        self.saveHistos()
-
-        GaudiKernel.ProcessJobOptions.PrintOn()
-        log.info( self )
-        GaudiKernel.ProcessJobOptions.PrintOff()
-
-        # Print out TES contents at the end of each event
-        #from Configurables import StoreExplorerAlg
-        #GaudiSequencer("GaussSequencer").Members += [ StoreExplorerAlg() ]
-
-        def propagateRootInTES(head_seq, rootInTes=''):
-            if head_seq.getProp('RootInTES') != '':
-                current_root = head_seq.getProp('RootInTES')
-            else:
-                current_root = rootInTes
-
-            for alg in head_seq.Members:
-                if type(alg) == GaudiSequencer:
-                    propagateRootInTES(alg, current_root)
-                else:
-                    alg.RootInTES = current_root
-
-        def fixRootInTESAction():
-            for alg in ApplicationMgr().TopAlg:
-                propagateRootInTES(alg)
-
-        from Gaudi.Configuration import appendPostConfigAction
-        appendPostConfigAction(fixRootInTESAction)
-
-# _____          _
-#|  __ \        | |
-#| |__) |___  __| | ___  ___ __ _ _   _
-#|  _  // _ \/ _` |/ _ \/ __/ _` | | | |
-#| | \ \  __/ (_| |  __/ (_| (_| | |_| |
-#|_|  \_\___|\__,_|\___|\___\__,_|\__, |
-#                                  __/ |
-#                                 |___/
-
-    def configure_redecay_mchits(self, slot, loc):
-        if 'Signal' not in slot:
-            GaussRedecayCopyToService('GaussRedecayCopyToService' + slot).MCHitsLocation += [loc]
-            GaussRedecayRetrieveFromService('GaussRedecayRetrieveFromService' + slot).MCHitsLocation += [loc]
-
-
-    def configure_redecay_mccalohits(self, slot, loc):
-        if 'Signal' not in slot:
-            GaussRedecayCopyToService('GaussRedecayCopyToService' + slot).MCCaloHitsLocation += [loc]
-            GaussRedecayRetrieveFromService('GaussRedecayRetrieveFromService' + slot).MCCaloHitsLocation += [loc]
-
-
-    def configureRedecay(self, SpillOverSlots ):
-        """Apply final configuration to the redecay configurables, especially set
-        the correct GaussRedecay Service instances for the different spillover
-        slots"""
-        n_redecays = self.Redecay['N']
-        rd_mode = self.Redecay['rd_mode']
-
-        genInit = GenInit('SignalGen')
-        if self.isGaussMP():
-            genInit.EvtCounter = "EvtCounter"
-        genInitT0 = GenInit("GaussGen")
-        if genInitT0.isPropertySet("RunNumber"):
-            genInit.RunNumber = genInitT0.RunNumber
-        if genInitT0.isPropertySet("FirstEventNumber"):
-            genInit.FirstEventNumber = genInitT0.FirstEventNumber
-
-        for slot in SpillOverSlots:
-            svcname = 'GaussRedecay' + slot
-            ApplicationMgr().ExtSvc += ['GaussRedecay/GaussRedecay' + slot]
-            GaussRedecay(svcname).Phase = 1
-            GaussRedecay(svcname).nRedecay = n_redecays
-            GaussRedecay(svcname).RedecayMode = rd_mode
-
-            if slot == '':
-                continue
-            GaussRedecayCopyToService(
-                'GaussRedecayCopyToService' + slot).GaussRedecay = svcname
-            GaussRedecayRetrieveFromService(
-                'GaussRedecayRetrieveFromService' + slot).GaussRedecay = svcname
-            GaussRedecayCtrFilter(
-                'RegisterNewEvent' + slot).GaussRedecay = svcname
-            GaussRedecayCtrFilter(
-                'CheckIfFullOrUESim' + slot).GaussRedecay = svcname
-            GaussRedecayCtrFilter(
-                'CheckIfSignalSim2' + slot).GaussRedecay = svcname
-
-        from Configurables import RedecayProduction
-        from Configurables import GaussRedecayFakePileUp
-
-        sig_gen = Generation('GenerationSignal')
-        org_gen = Generation('Generation')
-
-        # Original SampleGenerationTool to get the PIDList and CutTool
-        org_sgt_name = org_gen.SampleGenerationTool.split('/')[-1]
-        org_sgt = getattr(org_gen, org_sgt_name)
-
-        if type(org_sgt) is Inclusive:
-            GaussRedecay().RedecayMode = 99
-            sig_gen.SampleGenerationTool = "Inclusive"
-            sig_gen.addTool(Inclusive)
-            # Signal SampleGenerationTool
-            sig_sgt = sig_gen.Inclusive
-            sig_sgt.ProductionTool = "RedecayProduction"
-            sig_sgt.addTool(RedecayProduction)
-            sig_sgt.InclusivePIDList = org_sgt.InclusivePIDList
-            GaussRedecaySorter().SpecialPIDs = org_sgt.InclusivePIDList
-        else:
-            sig_gen.SampleGenerationTool = "SignalPlain"
-            sig_gen.addTool(SignalPlain)
-            # Signal SampleGenerationTool
-            sig_sgt = sig_gen.SignalPlain
-            sig_sgt.ProductionTool = "RedecayProduction"
-            sig_sgt.addTool(RedecayProduction)
-            sig_sgt.RevertWhenBackward = False
-
-        # Set the correct names for the used decay tools
-        if hasattr(org_sgt, 'DecayTool'):
-            sig_sgt.DecayTool = org_sgt.DecayTool
-
-        sig_gen.EventType = org_gen.EventType
-        sig_gen.PileUpTool = "GaussRedecayFakePileUp"
-        sig_gen.addTool(GaussRedecayFakePileUp)
-        sig_gen.VertexSmearingTool = ""
-
-
-        # Turn of GenFSR for the Signal portion (not needed as it gives
-        # biased efficiencies anyway and is a pain to set up)
-        sig_gen.GenFSRLocation = ""
-        sig_sgt.GenFSRLocation = ""
-
-        if type(org_sgt) is not Special and type(org_sgt) is not Inclusive:
-            sig_sgt.SignalPIDList = org_sgt.SignalPIDList
-        elif type(org_sgt) is Special:
-            print "Special production detected"
-            org_prd_name = org_sgt.ProductionTool
-            org_prod = getattr(org_sgt, org_prd_name)
-
-            # Now try to import and test two special production tools
-            # In tries to avoid crashes just because it cannot be imported
-            try:
-                PIDList = []
-                from Configurables import BcVegPyProduction
-                from Configurables import GenXiccProduction
-                if type(org_prod) is BcVegPyProduction:
-                    print "Modifying ReDecay with BcVegPy"
-                    violate = hasattr(org_prod, "ViolateGaugeInvariance")
-                    violate = getattr(org_prod, "ViolateGaugeInvariance") if violate else False
-                    if hasattr(org_prod, "MesonState") and violate:
-                        abspid = abs(getattr(org_prod, "MesonState"))
-                    else:
-                        abspid = 541
-                    PIDList = [abspid, -abspid]
-
-                elif type(org_prod) is GenXiccProduction:
-                    baryon_names = {
-                        "Xi_cc++": 4422,
-                        "Xi_cc+": 4412,
-                        "Xi_bc+": 5242,
-                        "Xi_bc0": 5142,
-                        "Xi_bb0": 5522,
-                        "Xi_bb-": 5512
-                    }
-                    print "Modifying ReDecay with GenXicc"
-                    baryon = hasattr(org_prod, "BaryonState")
-                    baryon = getattr(org_prod, "BaryonState") if baryon else "Xi_cc+"
-                    abspid = baryon_names[baryon]
-                    PIDList = [abspid, -abspid]
-
-                elif hasattr(org_sgt, 'CutTool'):
-                    # Maybe it is one of those productions using the cut tool
-                    # to do things. Try to assign the SignalPID property of
-                    # the cut tool to the PIDList
-                    org_ctl_name = org_sgt.CutTool.split('/')[-1]
-
-                    if hasattr(org_sgt, org_ctl_name):
-                        org_ctl = getattr(org_sgt, org_ctl_name)
-                        PIDList = [org_ctl.SignalPID]
-            except:
-                if PIDList == []:
-                    raise RuntimeError("Failed to find PIDList for Special")
-
-            sig_sgt.DecayTool = ""
-            sig_sgt.SignalPIDList = PIDList
-
-        # Set the correct names for the used decay tools
-        if hasattr(org_gen, 'DecayTool'):
-            sig_gen.DecayTool = org_gen.DecayTool
-
-        # Copy the CutTool if it exists
-        if hasattr(org_sgt, 'CutTool'):
-            org_ctl_name = org_sgt.CutTool.split('/')[-1]
-            sig_sgt.CutTool = org_sgt.CutTool
-            # Check if the cuttool is configured, might not be in case of
-            # simple ones like DaughtersInLHCb
-            if hasattr(org_sgt, org_ctl_name):
-                org_ctl = getattr(org_sgt, org_ctl_name)
-                sig_sgt.addTool(org_ctl, org_ctl_name)
-
-        # Copy the FullGenEventCutTool if it exists
-        if hasattr(org_gen, 'FullGenEventCutTool'):
-                org_ctl_name = org_gen.FullGenEventCutTool.split('/')[-1]
-                sig_gen.FullGenEventCutTool = org_gen.FullGenEventCutTool
-                # Check if the cuttool is configured
-                if hasattr(org_gen, org_ctl_name):
-                    org_ctl = getattr(org_gen, org_ctl_name)
-                    sig_gen.addTool(org_ctl, org_ctl_name)
-
-
-    def configureRedecaySim( self, SpillOverSlots ):
-
-        """
-        Set up the simulation sequence
-        """
-
-        if "Simulation" not in self.getProp("Phases"):
-            log.warning("No simulation phase.")
-            return
-
-        ApplicationMgr().ExtSvc += [ "GiGa" ]
-        EventPersistencySvc().CnvServices += [ "GiGaKine" ]
-
-        gaussSimulationSeq = GaudiSequencer( "Simulation" )
-        gaussSeq = GaudiSequencer("GaussSequencer")
-        gaussSeq.Members += [ gaussSimulationSeq ]
-
-        gigaStore = GiGaDataStoreAlgorithm( "GiGaStore" )
-        gigaStore.ConversionServices = [ "GiGaKine" ]
-        gaussSimulationSeq.Members += [ gigaStore ]
-
-        self.defineGeo()
-
-        self.configureGiGa()
-
-        if self.getProp('UseGaussGeo'):
-            GiGa().GeometrySource = "GaussGeo"
-        else:
-            GiGa().GeometrySource = "GiGaGeo"
-
-        for slot in SpillOverSlots:
-
-            TESNode = "/Event/"+self.slot_(slot)
-
-            mainSimSequence = GaudiSequencer( self.slotName(slot)+"EventSeq" )
-
-            gaussSimulationSeq.Members += [ mainSimSequence ]
-
-            mainSimSequence.Members +=  [ SimInit( self.slotName(slot)+"EventGaussSim",
-                                                   GenHeader = TESNode + "Gen/Header" ,
-                                                   MCHeader = TESNode + "MC/Header" ) ]
-
-            # We might not have a HepMC events in the redecays, hence
-            # the requirement is removed and explicitly checked using an
-            # algorithm running at the beginning.
-            simSeq = GaudiSequencer( self.slotName(slot)+"Simulation" )
-
-            # simSeq used to have a requireObjects. Cannot do that anymore
-            # as redecay events do not have a HepMC event. Hence make a filter
-            # that decides based on the original event.
-            hepmcfilterseq = GaudiSequencer('HepMCFilterSeq' + self.slotName(slot), ModeOR=True)
-            hepmcfilter = GaussRedecayCtrFilter('HepMCFilter' + self.slotName(slot))
-            hepmcfilter.CheckFor = TESNode + "Gen/HepMCEvents"
-            hepmcfilterseq.Members += [hepmcfilter]
-
-            mainSimSequence.Members += [ hepmcfilterseq]
-            hepmcfilterseq.Members += [simSeq]
-
-            simSlotSeq = GaudiSequencer( "Make"+self.slotName(slot)+"Sim",
-                                         RequireObjects = [ TESNode + "Gen/HepMCEvents" ])
-            simSlotFullSeq = GaudiSequencer( "Make"+self.slotName(slot)+"FullSim",
-                                            ModeOR=True)
-
-            simSlotSeq.Members += [simSlotFullSeq]
-            simSeq.Members += [simSlotSeq]
-
-            # CRJ : Set RootInTES - Everything down stream will then use the correct location
-            #       (assuming they use GaudiAlg get and put) so no need to set data locations
-            #       by hand any more ...
-            if slot != '' : simSlotFullSeq.RootInTES = slot
-
-            # Following is the main sim of the event, either normal event or
-            # the underlying event component for redecay, filter out if this
-            # event does not need this information.
-            #
-            # Make a filter to turn this part off for the signal redecay part.
-            # Ask whether phase is 1 and set it to 2 later on. Only applies for
-            # redecay, setting to 2 ignored otherwise!
-            grdfilter = GaussRedecayCtrFilter(
-                'CheckIfFullOrUESim{}'.format(slot))
-            grdfilter.IsPhaseEqual = 2
-            simSlotFullSeq.Members += [ grdfilter]
-
-            # Migrate the actual work into a new sequence, only activated when
-            # the previous filter return false due to the OR mode
-            simSlotFullSeqImpl = GaudiSequencer(
-                "Make"+self.slotName(slot)+"FullSimImpl")
-            simSlotFullSeq.Members += [ simSlotFullSeqImpl]
-
-            genToSim = GenerationToSimulation( "GenToSim" + slot,
-                                               LookForUnknownParticles = True )
-            simSlotFullSeqImpl.Members += [ genToSim ]
-
-            simSlotFullSeqImpl.Members += [ GiGaFlushAlgorithm( "GiGaFlush"+slot ) ]
-            simSlotFullSeqImpl.Members += [ GiGaCheckEventStatus( "GiGaCheckEvent"+slot ) ]
-            simToMC = SimulationToMCTruth( "SimToMCTruth"+slot )
-            simSlotFullSeqImpl.Members += [ simToMC ]
-
-            ## Detectors hits
-            TESNode = TESNode + "MC/"
-            detHits = GaudiSequencer( "DetectorsHits" + slot )
-            simSlotFullSeqImpl.Members += [ detHits ]
-            simSlotFullSeqImpl.Members += [ GaussRedecayCopyToService(
-                'GaussRedecayCopyToService{}'.format(slot)
-            ) ]
-
-            # Slight trick - configuredRichSim is a list and therefore MUTABLE!
-            configuredRichSim = [ False ]
-            for det in self.getProp('DetectorSim')['Detectors']:
-                self.configureDetectorSim( slot, detHits, det, configuredRichSim )
-
-            # ################################################
-            # Signal part here
-            # ################################################
-            if slot == '':
-                TESNode = "/Event/"+self.slot_(slot)+"Signal/"
-                simSlotSignal = GaudiSequencer( "SignalSimulation")
-
-                gdh = GenInit('SignalGen')
-                if self.isGaussMP():
-                    gdh.EvtCounter = "EvtCounter"
-                self.setBeamParameters(self.defineCrossingList(), gdh)
-
-                gdh.MCHeader = TESNode+"Gen/Header"
-                gdh.CreateBeam = False
-                sdh = SimInit('SignalSim')
-
-                sdh.MCHeader = TESNode+"MC/Header"
-
-                simSlotSignal.Members += [ gdh]
-                simSlotSignal.Members += [ sdh]
-
-                simSlotSignalSeq = GaudiSequencer( "Make"+self.slotName(slot)+"SignalSim", ModeOR=True)
-                simSlotSignalSeqImpl = GaudiSequencer( "Make"+self.slotName(slot)+"SignalSimImpl")
-                simSeq.Members += [simSlotSignal]
-                simSlotSignal.Members += [simSlotSignalSeq]
-
-                grdfilter = GaussRedecayCtrFilter('CheckIfSignalSim')
-                grdfilter.IsPhaseEqual = 0
-                simSlotSignalSeq.Members = [grdfilter, simSlotSignalSeqImpl]
-
-                simSlotSignalSeqImpl.Members += [Generation("GenerationSignal")]
-                simSlotSignalSeqImpl.RootInTES = '{}Signal'.format(slot)
-
-                genToSim = GenerationToSimulation( "GenToSim" + slot + 'Signal',
-                                                LookForUnknownParticles = True )
-                # genToSim.SelectiveSimulationStep = 2
-                simSlotSignalSeqImpl.Members += [ genToSim ]
-
-                simSlotSignalSeqImpl.Members += [ GiGaFlushAlgorithm( "GiGaFlush"+slot + 'Signal' ) ]
-                simSlotSignalSeqImpl.Members += [ GiGaCheckEventStatus( "GiGaCheckEvent"+slot + 'Signal' ) ]
-                simToMC = SimulationToMCTruth( "SimToMCTruth"+slot + 'Signal' )
-                simSlotSignalSeqImpl.Members += [ simToMC ]
-
-                detHits = GaudiSequencer( "DetectorsHits" + slot + 'Signal' )
-                simSlotSignalSeqImpl.Members += [ detHits ]
-                simSlotSignalSeqImpl.Members += [ GaussRedecayPrintMCParticles('SignalPrint') ]
-
-                configuredRichSim = [ False ]
-                for det in self.getProp('DetectorSim')['Detectors']:
-                    self.configureDetectorSim( slot+'Signal', detHits, det, configuredRichSim )
-
-            # ##############################################
-            # End signal part
-            # ##############################################
-            loadSlotSeq = GaudiSequencer( "Load"+self.slotName(slot)+"Sim", ModeOR=True )
-            grdfilter = GaussRedecayCtrFilter('CheckIfSignalSim2{}'.format(slot))
-            grdfilter.IsPhaseNotEqual = 2
-            loadSlotSeq.RootInTES = slot
-            loadSlotSeq.Members += [
-                grdfilter,
-                GaussRedecayRetrieveFromService('GaussRedecayRetrieveFromService{}'.format(slot))]
-            simSeq.Members += [loadSlotSeq]
-            if slot == '':
-                grdfilter = GaussRedecayCtrFilter('CheckIfMerge')
-                grdfilter.IsPhaseEqual = 0
-                mergeSlotSeq = GaudiSequencer( "Merge"+self.slotName(slot)+"Sim", ModeOR=True )
-                GaussRedecayMergeAndClean().MCHitsLocation = GaussRedecayCopyToService().MCHitsLocation
-                GaussRedecayMergeAndClean().MCCaloHitsLocation = GaussRedecayCopyToService().MCCaloHitsLocation
-                mergeSlotSeq.Members += [
-                    #StoreExplorerAlg('BeforeMerge'),
-                    grdfilter,
-                    GaussRedecayMergeAndClean()]
-                    #GaussRedecayPrintMCParticles('FullPrint'),
-                    #StoreExplorerAlg('AfterMerge')]
-                simSeq.Members += [mergeSlotSeq]
-                GaudiSequencer('RichHitsSignal').Members = GaudiSequencer('RichHitsSignal').Members[:4]
-            richpaddingSlotSeq = GaudiSequencer( "RichPadding"+self.slotName(slot) )
-            richpaddingSlotSeq.RootInTES = slot
-            richpaddingSlotSeq.Members = GaudiSequencer('RichHits' + slot).Members[4:]
-            GaudiSequencer('RichHits' + slot).Members = GaudiSequencer('RichHits' + slot).Members[:4]
-            simSeq.Members += [richpaddingSlotSeq]
-
-
-            # Data packing ...
-            if self.getProp("EnablePack") :
-                packing = GaudiSequencer(self.slotName(slot)+"EventDataPacking")
-                simSeq.Members += [ packing ]
-                SimConf().PackingSequencers[slot] = packing
-
-
-    def configureSplitSim( self, SpillOverSlots ):
-
-        """
-        Set up the simulation sequence
-        """
-
-        if "Simulation" not in self.getProp("Phases"):
-            log.warning("No simulation phase.")
-            return
-
-        ApplicationMgr().ExtSvc += [ "GiGa" ]
-        EventPersistencySvc().CnvServices += [ "GiGaKine" ]
-
-        gaussSimulationSeq = GaudiSequencer( "Simulation" )
-        gaussSeq = GaudiSequencer("GaussSequencer")
-        gaussSeq.Members += [ gaussSimulationSeq ]
-
-        gigaStore = GiGaDataStoreAlgorithm( "GiGaStore" )
-        gigaStore.ConversionServices = [ "GiGaKine" ]
-        gaussSimulationSeq.Members += [ gigaStore ]
-
-        self.defineGeo()
-
-        self.configureGiGa()
-
-        if self.getProp('UseGaussGeo'):
-            GiGa().GeometrySource = "GaussGeo"
-        else:
-            GiGa().GeometrySource = "GiGaGeo"
-
-        for slot in SpillOverSlots:
-
-            if slot == '':
-                ApplicationMgr().ExtSvc += ['GaussRedecay/GaussRedecay']
-                GaussRedecay().Phase = 1
-                GaussRedecay().nRedecay = 1
-
-            TESNode = "/Event/"+self.slot_(slot)
-
-            mainSimSequence = GaudiSequencer( self.slotName(slot)+"EventSeq" )
-
-            gaussSimulationSeq.Members += [ mainSimSequence ]
-
-            mainSimSequence.Members +=  [ SimInit( self.slotName(slot)+"EventGaussSim",
-                                                   GenHeader = TESNode + "Gen/Header" ,
-                                                   MCHeader = TESNode + "MC/Header" ) ]
-
-            simSeq = GaudiSequencer( self.slotName(slot)+"Simulation",
-                                     RequireObjects = [ TESNode + "Gen/HepMCEvents" ] )
-            mainSimSequence.Members += [ simSeq ]
-
-            simSlotSeq = GaudiSequencer( "Make"+self.slotName(slot)+"Sim" )
-            simSeq.Members += [simSlotSeq]
-
-            # CRJ : Set RootInTES - Everything down stream will then use the correct location
-            #       (assuming they use GaudiAlg get and put) so no need to set data locations
-            #       by hand any more ...
-            if slot != '' : simSlotSeq.RootInTES = slot
-
-            if slot == '':
-                gaussrdfilter = GaussRedecayCtrFilter('RegisterNewEvent')
-                gaussrdfilter.RegisterNewEvent = True
-                from Configurables import RedecayProduction
-                splitter = GaussHepMCSplitter()
-                splitter.ProductionTool = "RedecayProduction"
-                splitter.addTool(RedecayProduction)
-                simSlotSeq.Members += [ gaussrdfilter, splitter ]
-
-                # ################################################
-                # Split part here
-                # ################################################
-                if slot == '':
-                    TESNode = "/Event/Split/"
-                    simSlotSplit = GaudiSequencer( "SplitSimulation")
-                    simSlotSeq.Members += [ simSlotSplit ]
-
-                    gdh = GenInit('SignalGen')
-                    if self.isGaussMP():
-                        gdh.EvtCounter = "EvtCounter"
-                    self.setBeamParameters(self.defineCrossingList(), gdh)
-
-                    gdh.MCHeader = TESNode+"Gen/Header"
-                    gdh.CreateBeam = False
-                    # Dummy SimInit to make GenToSim happy
-                    # This will reset seeds but no simulation has yet been
-                    # done so everyone is happy
-                    sdh = SimInit('SplitSim')
-                    sdh.GenHeader = "/Event/Gen/Header"  # Use the main gen header to get the event and run number
-                    sdh.MCHeader = TESNode+"MC/Header"
-
-                    simSlotSplit.Members += [ sdh]
-
-                    simSlotSplitSeq = GaudiSequencer( "Make"+self.slotName(slot)+"SplitSim")
-                    simSlotSplit.Members += [simSlotSplitSeq]
-
-                    simSlotSplitSeq.RootInTES = '{}Split'.format(slot)
-
-                    genToSim = GenerationToSimulation( "GenToSim" + slot + 'Split',
-                                                    LookForUnknownParticles = True )
-                    # genToSim.SelectiveSimulationStep = 2
-                    simSlotSplitSeq.Members += [ genToSim ]
-
-                    simSlotSplitSeq.Members += [ GiGaFlushAlgorithm( "GiGaFlush"+slot + 'Split' ) ]
-                    simSlotSplitSeq.Members += [ GiGaCheckEventStatus( "GiGaCheckEvent"+slot + 'Split' ) ]
-                    simToMC = SimulationToMCTruth( "SimToMCTruth"+slot + 'Split' )
-                    simSlotSplitSeq.Members += [ simToMC ]
-
-                    detHits = GaudiSequencer( "DetectorsHits" + slot + 'Split' )
-                    simSlotSplitSeq.Members += [ detHits ]
-                    simSlotSplitSeq.Members += [ GaussRedecayPrintMCParticles('SplitPrint') ]
-
-                    configuredRichSim = [ False ]
-                    for det in self.getProp('DetectorSim')['Detectors']:
-                        self.configureDetectorSim( slot+'Split', detHits, det, configuredRichSim )
-
-                    if self.getProp("PostSimFilters") :
-                        filterSeq = GaudiSequencer("PostSimFilterSeq")
-                        filterSeq.RootInTES = '{}Split'.format(slot)
-                        simSlotSplitSeq.Members += [ filterSeq ]
-                # ################################################
-                # Split part end
-                # ################################################
-
-            genToSim = GenerationToSimulation( "GenToSim" + slot,
-                                               LookForUnknownParticles = True )
-            simSlotSeq.Members += [ genToSim ]
-
-            simSlotSeq.Members += [ GiGaFlushAlgorithm( "GiGaFlush"+slot ) ]
-            simSlotSeq.Members += [ GiGaCheckEventStatus( "GiGaCheckEvent"+slot ) ]
-            simToMC = SimulationToMCTruth( "SimToMCTruth"+slot )
-            simSlotSeq.Members += [ simToMC ]
-
-            ## Detectors hits
-            TESNode = TESNode + "MC/"
-            detHits = GaudiSequencer( "DetectorsHits" + slot )
-            simSlotSeq.Members += [ detHits ]
-
-            # Slight trick - configuredRichSim is a list and therefore MUTABLE!
-            configuredRichSim = [ False ]
-            for det in self.getProp('DetectorSim')['Detectors']:
-                self.configureDetectorSim( slot, detHits, det, configuredRichSim )
-
-            # Merge the split
-            if slot == '':
-                mergeSlotSeq = GaudiSequencer( "Merge"+self.slotName(slot)+"Sim")
-                GaussRedecayMergeAndClean().SignalTESROOT = 'Split/'
-                GaussRedecayMergeAndClean().MCHitsLocation = GaussRedecayCopyToService().MCHitsLocation
-                GaussRedecayMergeAndClean().MCCaloHitsLocation = GaussRedecayCopyToService().MCCaloHitsLocation
-                mergeSlotSeq.Members += [
-                    GaussRedecayMergeAndClean()]
-                simSlotSeq.Members += [mergeSlotSeq]
-                GaudiSequencer('RichHitsSplit').Members = GaudiSequencer('RichHitsSplit').Members[:4]
-                richpaddingSlotSeq = GaudiSequencer( "RichPadding"+self.slotName(slot) )
-                richpaddingSlotSeq.RootInTES = slot
-                richpaddingSlotSeq.Members = GaudiSequencer('RichHits' + slot).Members[4:]
-                GaudiSequencer('RichHits' + slot).Members = GaudiSequencer('RichHits' + slot).Members[:4]
-                mergeSlotSeq.Members += [richpaddingSlotSeq]
-
-            # Data packing ...
-            if self.getProp("EnablePack") :
-                packing = GaudiSequencer(self.slotName(slot)+"EventDataPacking")
-                simSlotSeq.Members += [ packing ]
-                SimConf().PackingSequencers[slot] = packing
-        # End of Sim Configuration
-
-
-    def configureRedecaySplitSim( self, SpillOverSlots ):
-
-        """
-        Set up the simulation sequence for the combination of redecay with a
-        split simulation phase for the signal portion
-        AKA the Franken-Config
-
-        The plan:
-            1. Have the normal GaussRedecay setup in place with its services
-            2. Hook in another Redecay service for the split simulation
-            3. Hope for the best
-        """
-
-        if "Simulation" not in self.getProp("Phases"):
-            log.warning("No simulation phase.")
-            return
-
-        ApplicationMgr().ExtSvc += [ "GiGa" ]
-        EventPersistencySvc().CnvServices += [ "GiGaKine" ]
-
-        gaussSimulationSeq = GaudiSequencer( "Simulation" )
-        gaussSeq = GaudiSequencer("GaussSequencer")
-        gaussSeq.Members += [ gaussSimulationSeq ]
-
-        gigaStore = GiGaDataStoreAlgorithm( "GiGaStore" )
-        gigaStore.ConversionServices = [ "GiGaKine" ]
-        gaussSimulationSeq.Members += [ gigaStore ]
-
-        self.defineGeo()
-
-        self.configureGiGa()
-
-        if self.getProp('UseGaussGeo'):
-            GiGa().GeometrySource = "GaussGeo"
-        else:
-            GiGa().GeometrySource = "GiGaGeo"
-
-        # Configure the new service
-        svcname = 'GaussSplitRedecay'
-        ApplicationMgr().ExtSvc += ['GaussRedecay/'+svcname]
-        GaussRedecay(svcname).Phase = 1
-        GaussRedecay(svcname).nRedecay = 1
-        GaussRedecay(svcname).Offset = 50  # offset pdg placeholder by 50 to not collide with the actual redecay service
-
-        for slot in SpillOverSlots:
-
-            TESNode = "/Event/"+self.slot_(slot)
-
-            mainSimSequence = GaudiSequencer( self.slotName(slot)+"EventSeq" )
-
-            gaussSimulationSeq.Members += [ mainSimSequence ]
-
-            mainSimSequence.Members +=  [ SimInit( self.slotName(slot)+"EventGaussSim",
-                                                   GenHeader = TESNode + "Gen/Header" ,
-                                                   MCHeader = TESNode + "MC/Header" ) ]
-
-            # We might not have a HepMC events in the redecays, hence
-            # the requirement is removed and explicitly checked using an
-            # algorithm running at the beginning.
-            simSeq = GaudiSequencer( self.slotName(slot)+"Simulation" )
-
-            # simSeq used to have a requireObjects. Cannot do that anymore
-            # as redecay events do not have a HepMC event. Hence make a filter
-            # that decides based on the original event.
-            hepmcfilterseq = GaudiSequencer('HepMCFilterSeq' + self.slotName(slot), ModeOR=True)
-            hepmcfilter = GaussRedecayCtrFilter('HepMCFilter' + self.slotName(slot))
-            hepmcfilter.CheckFor = TESNode + "Gen/HepMCEvents"
-            hepmcfilterseq.Members += [hepmcfilter]
-
-            mainSimSequence.Members += [ hepmcfilterseq]
-            hepmcfilterseq.Members += [simSeq]
-
-            simSlotSeq = GaudiSequencer( "Make"+self.slotName(slot)+"Sim",
-                                         RequireObjects = [ TESNode + "Gen/HepMCEvents" ])
-            simSlotFullSeq = GaudiSequencer( "Make"+self.slotName(slot)+"FullSim",
-                                            ModeOR=True)
-
-            simSlotSeq.Members += [simSlotFullSeq]
-            simSeq.Members += [simSlotSeq]
-
-            # CRJ : Set RootInTES - Everything down stream will then use the correct location
-            #       (assuming they use GaudiAlg get and put) so no need to set data locations
-            #       by hand any more ...
-            if slot != '' : simSlotFullSeq.RootInTES = slot
-
-            # Following is the main sim of the event, either normal event or
-            # the underlying event component for redecay, filter out if this
-            # event does not need this information.
-            #
-            # Make a filter to turn this part off for the signal redecay part.
-            # Ask whether phase is 1 and set it to 2 later on. Only applies for
-            # redecay, setting to 2 ignored otherwise!
-            grdfilter = GaussRedecayCtrFilter(
-                'CheckIfFullOrUESim{}'.format(slot))
-            grdfilter.IsPhaseEqual = 2
-            simSlotFullSeq.Members += [ grdfilter]
-
-            # Migrate the actual work into a new sequence, only activated when
-            # the previous filter return false due to the OR mode
-            simSlotFullSeqImpl = GaudiSequencer(
-                "Make"+self.slotName(slot)+"FullSimImpl")
-            simSlotFullSeq.Members += [ simSlotFullSeqImpl]
-
-            genToSim = GenerationToSimulation( "GenToSim" + slot,
-                                               LookForUnknownParticles = True )
-            simSlotFullSeqImpl.Members += [ genToSim ]
-
-            simSlotFullSeqImpl.Members += [ GiGaFlushAlgorithm( "GiGaFlush"+slot ) ]
-            simSlotFullSeqImpl.Members += [ GiGaCheckEventStatus( "GiGaCheckEvent"+slot ) ]
-            simToMC = SimulationToMCTruth( "SimToMCTruth"+slot )
-            simSlotFullSeqImpl.Members += [ simToMC ]
-
-            ## Detectors hits
-            TESNode = TESNode + "MC/"
-            detHits = GaudiSequencer( "DetectorsHits" + slot )
-            simSlotFullSeqImpl.Members += [ detHits ]
-            simSlotFullSeqImpl.Members += [ GaussRedecayCopyToService(
-                'GaussRedecayCopyToService{}'.format(slot)
-            ) ]
-
-            # Slight trick - configuredRichSim is a list and therefore MUTABLE!
-            configuredRichSim = [ False ]
-            for det in self.getProp('DetectorSim')['Detectors']:
-                self.configureDetectorSim( slot, detHits, det, configuredRichSim )
-
-            # ################################################
-            # Signal part here
-            # ################################################
-            if slot == '':
-                TESNode = "/Event/"+self.slot_(slot)+"Signal/"
-                simSlotSignal = GaudiSequencer( "SignalSimulation")
-
-                gdh = GenInit('SignalGen')
-                if self.isGaussMP():
-                    gdh.EvtCounter = "EvtCounter"
-                self.setBeamParameters(self.defineCrossingList(), gdh)
-
-                gdh.MCHeader = TESNode+"Gen/Header"
-                gdh.CreateBeam = False
-                sdh = SimInit('SignalSim')
-
-                sdh.MCHeader = TESNode+"MC/Header"
-
-                simSlotSignal.Members += [ gdh]
-                simSlotSignal.Members += [ sdh]
-
-                simSlotSignalSeq = GaudiSequencer( "Make"+self.slotName(slot)+"SignalSim", ModeOR=True)
-                simSlotSignalSeqImpl = GaudiSequencer( "Make"+self.slotName(slot)+"SignalSimImpl")
-                simSeq.Members += [simSlotSignal]
-                simSlotSignal.Members += [simSlotSignalSeq]
-
-                grdfilter = GaussRedecayCtrFilter('CheckIfSignalSim')
-                grdfilter.IsPhaseEqual = 0
-                simSlotSignalSeq.Members = [grdfilter, simSlotSignalSeqImpl]
-
-                simSlotSignalSeqImpl.Members += [Generation("GenerationSignal")]
-                simSlotSignalSeqImpl.RootInTES = '{}Signal'.format(slot)
-
-                splitter = GaussHepMCSplitter()
-                splitter.ProductionTool = "RedecayProduction"
-                splitter.GaussRedecay = svcname
-
-                from Configurables import RedecayProduction
-                splitter.addTool(RedecayProduction)
-                splitter.RedecayProduction.GaussRedecay = svcname
-                gaussrdfilter = GaussRedecayCtrFilter('RegisterNewSplitEvent')
-                gaussrdfilter.RegisterNewEvent = True
-                gaussrdfilter.GaussRedecay = svcname
-                simSlotSignalSeqImpl.Members += [gaussrdfilter, splitter]
-
-                # ################################################
-                # Split part here
-                # ################################################
-                TESNode = "/Event/Signal/Split/"
-                simSlotSplit = GaudiSequencer( "SplitSimulation")
-                simSlotSignalSeqImpl.Members += [ simSlotSplit ]
-
-                gdh = GenInit('SplitGen')
-                if self.isGaussMP():
-                    gdh.EvtCounter = "EvtCounter"
-                self.setBeamParameters(self.defineCrossingList(), gdh)
-
-                gdh.MCHeader = TESNode+"Gen/Header"
-                gdh.CreateBeam = False
-                # Dummy SimInit to make GenToSim happy
-                # This will reset seeds but no simulation has yet been
-                # done so everyone is happy
-                sdh = SimInit('SplitSim')
-                sdh.GenHeader = "/Event/Gen/Header"  # Use the main gen header to get the event and run number
-                sdh.MCHeader = "Split/MC/Header"
-
-                simSlotSplit.Members += [ sdh]
-
-                simSlotSplitSeq = GaudiSequencer( "Make"+self.slotName(slot)+"SplitSim")
-                simSlotSplit.Members += [simSlotSplitSeq]
-
-                simSlotSplitSeq.RootInTES = 'Signal/Split'.format(slot)
-
-                genToSim = GenerationToSimulation( "GenToSim" + slot + 'Split',
-                                                LookForUnknownParticles = True )
-                # genToSim.SelectiveSimulationStep = 2
-                simSlotSplitSeq.Members += [ genToSim ]
-
-                simSlotSplitSeq.Members += [ GiGaFlushAlgorithm( "GiGaFlush"+slot + 'Split' ) ]
-                simSlotSplitSeq.Members += [ GiGaCheckEventStatus( "GiGaCheckEvent"+slot + 'Split' ) ]
-                simToMC = SimulationToMCTruth( "SimToMCTruth"+slot + 'Split' )
-                simSlotSplitSeq.Members += [ simToMC ]
-
-                detHits = GaudiSequencer( "DetectorsHits" + slot + 'Split' )
-                simSlotSplitSeq.Members += [ detHits ]
-                simSlotSplitSeq.Members += [ GaussRedecayPrintMCParticles('SplitPrint') ]
-
-                configuredRichSim = [ False ]
-                for det in self.getProp('DetectorSim')['Detectors']:
-                    self.configureDetectorSim( slot+'Split', detHits, det, configuredRichSim )
-
-                if self.getProp("PostSimFilters") :
-                    filterSeq = GaudiSequencer("PostSimFilterSeq")
-                    simSlotSplitSeq.Members += [ filterSeq ]
-                # ################################################
-                # Split part end
-                # ################################################
-
-                genToSim = GenerationToSimulation( "GenToSim" + slot + 'Signal',
-                                                LookForUnknownParticles = True )
-                simSlotSignalSeqImpl.Members += [ genToSim ]
-
-                simSlotSignalSeqImpl.Members += [ GiGaFlushAlgorithm( "GiGaFlush"+slot + 'Signal' ) ]
-                simSlotSignalSeqImpl.Members += [ GiGaCheckEventStatus( "GiGaCheckEvent"+slot + 'Signal' ) ]
-                simToMC = SimulationToMCTruth( "SimToMCTruth"+slot + 'Signal' )
-                simSlotSignalSeqImpl.Members += [ simToMC ]
-
-                detHits = GaudiSequencer( "DetectorsHits" + slot + 'Signal' )
-                simSlotSignalSeqImpl.Members += [ detHits ]
-                simSlotSignalSeqImpl.Members += [ GaussRedecayPrintMCParticles('SignalPrint') ]
-
-                configuredRichSim = [ False ]
-                for det in self.getProp('DetectorSim')['Detectors']:
-                    self.configureDetectorSim( slot+'Signal', detHits, det, configuredRichSim )
-
-                # Now merge the Split part back into the signal bit
-                mergeSlotSeq = GaudiSequencer( "Merge"+self.slotName(slot)+"SignalSplitSim")
-                GaussRedecayMergeAndClean('GaussRedecayMergeAndCleanSignal').SignalTESROOT = 'Split/'
-                GaussRedecayMergeAndClean('GaussRedecayMergeAndCleanSignal').GaussRedecay = svcname
-                mergeSlotSeq.Members += [
-                    GaussRedecayMergeAndClean('GaussRedecayMergeAndCleanSignal')]
-                simSlotSignalSeqImpl.Members += [mergeSlotSeq]
-
-            # ##############################################
-            # End signal part
-            # ##############################################
-            loadSlotSeq = GaudiSequencer( "Load"+self.slotName(slot)+"Sim", ModeOR=True )
-            grdfilter = GaussRedecayCtrFilter('CheckIfSignalSim2{}'.format(slot))
-            grdfilter.IsPhaseNotEqual = 2
-            loadSlotSeq.RootInTES = slot
-            loadSlotSeq.Members += [
-                grdfilter,
-                GaussRedecayRetrieveFromService('GaussRedecayRetrieveFromService{}'.format(slot))]
-            simSeq.Members += [loadSlotSeq]
-            if slot == '':
-                grdfilter = GaussRedecayCtrFilter('CheckIfMerge')
-                grdfilter.IsPhaseEqual = 0
-                mergeSlotSeq = GaudiSequencer( "Merge"+self.slotName(slot)+"Sim", ModeOR=True )
-                GaussRedecayMergeAndClean().MCHitsLocation = GaussRedecayCopyToService().MCHitsLocation
-                GaussRedecayMergeAndClean().MCCaloHitsLocation = GaussRedecayCopyToService().MCCaloHitsLocation
-                GaussRedecayMergeAndClean('GaussRedecayMergeAndCleanSignal').MCHitsLocation = GaussRedecayCopyToService().MCHitsLocation
-                GaussRedecayMergeAndClean('GaussRedecayMergeAndCleanSignal').MCCaloHitsLocation = GaussRedecayCopyToService().MCCaloHitsLocation
-                mergeSlotSeq.Members += [
-                    #StoreExplorerAlg('BeforeMerge'),
-                    grdfilter,
-                    GaussRedecayMergeAndClean()]
-                    #GaussRedecayPrintMCParticles('FullPrint'),
-                    #StoreExplorerAlg('AfterMerge')]
-                simSeq.Members += [mergeSlotSeq]
-                GaudiSequencer('RichHitsSignal').Members = GaudiSequencer('RichHitsSignal').Members[:4]
-            richpaddingSlotSeq = GaudiSequencer( "RichPadding"+self.slotName(slot) )
-            richpaddingSlotSeq.RootInTES = slot
-            richpaddingSlotSeq.Members = GaudiSequencer('RichHits' + slot).Members[4:]
-            GaudiSequencer('RichHits' + slot).Members = GaudiSequencer('RichHits' + slot).Members[:4]
-            simSeq.Members += [richpaddingSlotSeq]
-
-
-            # Data packing ...
-            if self.getProp("EnablePack") :
-                packing = GaudiSequencer(self.slotName(slot)+"EventDataPacking")
-                simSeq.Members += [ packing ]
-                SimConf().PackingSequencers[slot] = packing
+        self.defineOutput(crossingList)
-- 
GitLab


From cd86a19a26f6a421fe830bd3e20bc7ba94b1594e Mon Sep 17 00:00:00 2001
From: Dominik Muller <dominik.muller@cern.ch>
Date: Thu, 18 Jul 2019 11:46:56 +0200
Subject: [PATCH 18/90] Ported calo hit conversion and monitoring, fully
 integrated SPD and PRS

---
 Calo/CaloMoniSim/src/MCCaloMonitor.cpp  | 285 +++++++++++-------------
 Calo/CaloMoniSim/src/MCCaloMonitor.h    | 140 +++++-------
 Sim/Gauss/python/Gauss/Geometry/CALO.py |  76 +++++++
 Sim/Gauss/python/Gauss/Physics.py       |   6 +-
 Sim/Gauss/python/Gauss/Utilities.py     |  13 ++
 Sim/GaussCalo/options/GaussGeo-Prs.opts |   6 +-
 Sim/GaussCalo/options/GaussGeo-Spd.opts |   6 +-
 Sim/GaussCalo/src/CaloSensDet.icpp      |   6 +-
 Sim/GaussCalo/src/CaloSensDetFAC.h      |  13 +-
 Sim/GaussCalo/src/CaloSubHit.h          |   1 +
 Sim/GaussCalo/src/GetCaloHitsAlg.cpp    | 229 +++++++------------
 Sim/GaussCalo/src/GetCaloHitsAlg.h      |  60 +++--
 12 files changed, 409 insertions(+), 432 deletions(-)

diff --git a/Calo/CaloMoniSim/src/MCCaloMonitor.cpp b/Calo/CaloMoniSim/src/MCCaloMonitor.cpp
index 1d568b85a..9ec2b7d71 100755
--- a/Calo/CaloMoniSim/src/MCCaloMonitor.cpp
+++ b/Calo/CaloMoniSim/src/MCCaloMonitor.cpp
@@ -2,20 +2,21 @@
 
 // STL
 #include <stdio.h>
-#include <string>
 #include <algorithm>
+#include <string>
 
 // from Gaudi
 #include "Kernel/CaloCellID.h"
 // from Event
+#include "Event/MCCaloDigit.h"
 #include "Event/MCHit.h"
 #include "Event/MCParticle.h"
 #include "Event/MCVertex.h"
-#include "Event/MCCaloDigit.h"
 // OD : RENAMING >>>> WAIT FOR NEW NAME/LOCATION - COMMENTED IN THE MEANTIME
 //#include "Event/MCCaloSensPlaneHit.h"
 
 // Gaudi Histograms:
+#include "AIDA/IHistogram1D.h"
 #include "GaudiAlg/GaudiHistoAlg.h"
 
 // local
@@ -32,121 +33,56 @@ using namespace LHCb;
 //-----------------------------------------------------------------------------
 
 // Declaration of the Algorithm Factory
-DECLARE_COMPONENT( MCCaloMonitor )
-
-
-//=============================================================================
-// Standard constructor, initializes variables
-//=============================================================================
-MCCaloMonitor::MCCaloMonitor( const std::string& name,
-                              ISvcLocator* pSvcLocator)
-  : GaudiHistoAlg ( name , pSvcLocator )
-  , m_nameOfMCHits              ( "" )
-  , m_GeometryRoot        ( "/dd/Structure/LHCb/DownstreamRegion/" )
-  , m_DivMonitor                ( false      )
-  , m_MaxE                 (  10 * Gaudi::Units::MeV  )
-  , m_MinE                 (   0 * Gaudi::Units::MeV  )
-  , m_Threshold                 ( 1.5 * Gaudi::Units::MeV  )
-  , m_MaxT                   (  7   )
-  , m_MinT                   (  -1   )
-  , m_hDir                  ( " "   )
-  , m_nEvents                   (   0   )
-  , m_DetectorName              ( " "   )
-  , m_textNorm ("Norm")
-{
-  declareProperty("GeometryRoot"    , m_GeometryRoot    );
-  declareProperty("Regions"         , m_DivMonitor            );
-  declareProperty("MaximumEnergy"   , m_MaxE            );
-  declareProperty("MinimumEnergy"   , m_MinE            );
-  declareProperty("MaximumTime"     , m_MaxT              );
-  declareProperty("Threshold"       , m_Threshold            );
-  declareProperty("MinimumTime"     , m_MinT              );
-  declareProperty("hDir"            , m_hDir             );
-  declareProperty("Detector"        , m_Detector             );
-  declareProperty("DetectorName"    , m_DetectorName         );
-  declareProperty("MCParticles"     , m_mcParticles = MCParticleLocation::Default ) ;
-}
-
-//=============================================================================
-// Destructor
-//=============================================================================
-MCCaloMonitor::~MCCaloMonitor() {}
+DECLARE_COMPONENT(MCCaloMonitor)
 
 //=============================================================================
 // Initialisation. Check parameters
 //=============================================================================
 StatusCode MCCaloMonitor::initialize() {
-  StatusCode sc = GaudiHistoAlg::initialize(); // must be executed first
-  if ( sc.isFailure() ) return sc;  // error printed already by GaudiAlgorithm
+  StatusCode sc = GaudiHistoAlg::initialize();  // must be executed first
+  if (sc.isFailure()) return sc;  // error printed already by GaudiAlgorithm
 
   info() << "==> Initialise Monitoring " << m_Detector << endmsg;
 
   m_hDir = m_Detector;
-  m_nameOfMCHits = "MC/" + m_Detector + "/Hits";
-  if (m_Detector == "Spd"){
+  if (m_Detector == "Spd") {
     m_DetectorName = "SPD";
-  }
-  if (m_Detector == "Prs"){
+  } else if (m_Detector == "Prs") {
     m_DetectorName = "PS";
-  }
-  if (m_Detector == "Ecal"){
+  } else if (m_Detector == "Ecal") {
     m_DetectorName = "ECAL";
-  }
-  if (m_Detector == "Hcal"){
+  } else if (m_Detector == "Hcal") {
     m_DetectorName = "HCAL";
+  } else {
+    return Error("Invalid detector provided: " + m_Detector);
   }
 
   // Histograms
 
-  m_hName1  = "Subhits in the " + m_DetectorName;
-  m_hName1a = "Subhits in the INNER " + m_DetectorName;
-  m_hName1b = "Subhits in the MIDDLE " + m_DetectorName;
-  m_hName1c = "Subhits in the OUTER " + m_DetectorName;
-  m_hName2  = "Energy Weighted Subhits in the " + m_DetectorName;
-  m_hName2a = "Energy Weighted Subhits in the INNER " + m_DetectorName;
-  m_hName2b = "Energy Weighted Subhits in the MIDDLE " + m_DetectorName;
-  m_hName2c = "Energy Weighted Subhits in the OUTER" + m_DetectorName;
-  m_hName3  = "Accumulated Energy in the " + m_DetectorName;
-  m_hName3a = "Accumulated Energy in the INNER " + m_DetectorName;
-  m_hName3b = "Accumulated Energy in the MIDDLE " + m_DetectorName;
-  m_hName3c = "Accumulated Energy in the OUTER " + m_DetectorName;
-  m_hName4  = "Number of Subhits in the " + m_DetectorName;
-  m_hName40 = "Number of Subhits in the " + m_DetectorName + " ( BC = -1 )";
-  m_hName41 = "Number of Subhits in the " + m_DetectorName + " ( BC = 0  )";
-  m_hName42 = "Number of Subhits in the " + m_DetectorName + " ( BC = 1  )";
-  m_hName43 = "Number of Subhits in the " + m_DetectorName + " ( BC = 2  )";
-  m_hName44 = "Number of Subhits in the " + m_DetectorName + " ( BC = 3  )";
-  m_hName45 = "Number of Subhits in the " + m_DetectorName + " ( BC = 4  )";
-  m_Bin = int(m_MaxT-m_MinT+1);
-  MinT = 1.*m_MinT - 0.5;
-  MaxT = 1.*m_MaxT + 0.501;
-
-  m_detector = getDet<DeCalorimeter>(m_GeometryRoot + m_Detector);
-  if( 0 == m_detector ) {
-    error() <<
-      "Cannot locate Detector Element ="<< m_GeometryRoot+m_Detector << endmsg;
-    return StatusCode::FAILURE ;
+  m_Bin = int(m_MaxT - m_MinT + 1);
+  MinT = 1. * m_MinT - 0.5;
+  MaxT = 1. * m_MaxT + 0.501;
+
+  m_detector = getDet<DeCalorimeter>(m_GeometryRoot.value() + m_Detector.value());
+  if (0 == m_detector) {
+    error() << "Cannot locate Detector Element =" << m_GeometryRoot.value() + m_Detector.value()
+            << endmsg;
+    return StatusCode::FAILURE;
   }
-  
+
+  bookHistograms();
+
   return StatusCode::SUCCESS;
 }
 
 //=============================================================================
 // Main execution
 //=============================================================================
-StatusCode MCCaloMonitor::execute() {
-
-  ++m_nEvents;
-  m_nEvents  = 1;
+void MCCaloMonitor::operator()(const LHCb::MCCaloHits& CaloHits) const {
   debug() << "Execute Monitoring " << m_Detector << endmsg;
 
-  MCCaloHits::const_iterator iHit;
-
-  // Get the MCHits
-  const MCCaloHits * CaloHits = get<MCCaloHits>(m_nameOfMCHits);
-
   // Get the MCParticles
-  //const MCParticles * mcParts = get<MCParticles>(m_mcParticles);
+  // const MCParticles * mcParts = get<MCParticles>(m_mcParticles);
 
   int hits_Counter = 0;
 
@@ -157,92 +93,135 @@ StatusCode MCCaloMonitor::execute() {
   int hits_CounterBC3 = 0;
   int hits_CounterBC4 = 0;
 
-  for ( iHit = CaloHits->begin(); iHit != CaloHits->end() ; ++iHit ){
-
+  std::lock_guard<std::mutex> locker{m_histo_mutex};
+  for (auto hit : CaloHits) {
     // NORMAL ENERGY SUBHITS HISTOGRAMS
     int binTime;
-    if ( (*iHit)->time() >= 7){
-      binTime = 7 ;
-    }
-    else {
-      binTime=(*iHit)->time();
+    if (hit->time() >= 7) {
+      binTime = 7;
+    } else {
+      binTime = hit->time();
     }
-    CaloCellID ID = (*iHit)->cellID();
+    CaloCellID ID = hit->cellID();
     int zone = ID.area();
 
-    plot1D( (*iHit)->activeE(),11,m_hName1,m_MinE,m_MaxE,100,1./m_nEvents) ;
-    plot1D( (*iHit)->activeE(),12,m_hName2,m_MinE,m_MaxE,100,((*iHit)->activeE())/m_nEvents) ;
-    plot1D( binTime,13,m_hName3,MinT,MaxT,m_Bin,((*iHit)->activeE())/m_nEvents) ;
+    m_hName1->fill(hit->activeE(), 1.);
+    m_hName2->fill(hit->activeE(), hit->activeE());
+    m_hName3->fill(binTime, hit->activeE());
     if (m_DivMonitor) {
-      if ( ( 2 == zone && m_DetectorName != "Hcal" ) ||
-           ( 1 == zone && m_DetectorName == "Hcal" ) ){
-        if ( m_detector->valid(ID) ){
-          plot1D((*iHit)->activeE(),111,m_hName1a,m_MinE,m_MaxE,100,1./m_nEvents) ;
-          plot1D((*iHit)->activeE(),121,m_hName2a,m_MinE,m_MaxE,100,((*iHit)->activeE())/m_nEvents) ;
-          plot1D(binTime,131,m_hName3a,MinT,MaxT,m_Bin,((*iHit)->activeE())/m_nEvents) ;
+      if ((2 == zone && m_DetectorName != "Hcal") ||
+          (1 == zone && m_DetectorName == "Hcal")) {
+        if (m_detector->valid(ID)) {
+          m_hName1a->fill(hit->activeE(), 1.);
+          m_hName2a->fill(hit->activeE(), hit->activeE());
+          m_hName3a->fill(binTime, hit->activeE());
         }
       }
-      if ( ( 1 == zone   && m_DetectorName != "Hcal" ) ){
-        if ( m_detector->valid(ID) ){
-          plot1D((*iHit)->activeE(),112,m_hName1b,m_MinE,m_MaxE,100,1./m_nEvents) ;
-          plot1D((*iHit)->activeE(),122,m_hName2b,m_MinE,m_MaxE,100,((*iHit)->activeE())/m_nEvents) ;
-          plot1D(binTime,132,m_hName3b,MinT,MaxT,m_Bin,((*iHit)->activeE())/m_nEvents) ;
+      if ((1 == zone && m_DetectorName != "Hcal")) {
+        if (m_detector->valid(ID)) {
+          m_hName1b->fill(hit->activeE(), 1.);
+          m_hName2b->fill(hit->activeE(), hit->activeE());
+          m_hName3b->fill(binTime, hit->activeE());
         }
       }
-      if ( 0 == zone ) {
-        if ( m_detector->valid(ID) ){
-          plot1D((*iHit)->activeE(),113,m_hName1c,m_MinE,m_MaxE,100,1./m_nEvents) ;
-          plot1D((*iHit)->activeE(),123,m_hName2c,m_MinE,m_MaxE,100,((*iHit)->activeE())/m_nEvents) ;
-          plot1D(binTime,133,m_hName3c,MinT,MaxT,m_Bin,((*iHit)->activeE())/m_nEvents) ;
+      if (0 == zone) {
+        if (m_detector->valid(ID)) {
+          m_hName1c->fill(hit->activeE(), 1.);
+          m_hName2c->fill(hit->activeE(), hit->activeE());
+          m_hName3c->fill(binTime, hit->activeE());
         }
       }
     }
     // BUNCH CROSSING HISTOGRAMS
-    if ( (*iHit)->activeE() >= m_Threshold ){
+    if (hit->activeE() >= m_Threshold) {
       hits_Counter = hits_Counter + 1;
-      switch ((*iHit)->time()){
-      case -1:
-        ++hits_CounterBC_1;
-        break;
-      case 0:
-        ++hits_CounterBC0 ;
-        break;
-      case 1:
-        ++hits_CounterBC1 ;
-        break;
-      case 2:
-        ++hits_CounterBC2 ;
-        break;
-      case 3:
-        ++hits_CounterBC3;
-        break;
-      case 4:
-        ++hits_CounterBC4;
-        break;
+      switch (hit->time()) {
+        case -1:
+          ++hits_CounterBC_1;
+          break;
+        case 0:
+          ++hits_CounterBC0;
+          break;
+        case 1:
+          ++hits_CounterBC1;
+          break;
+        case 2:
+          ++hits_CounterBC2;
+          break;
+        case 3:
+          ++hits_CounterBC3;
+          break;
+        case 4:
+          ++hits_CounterBC4;
+          break;
       }
     }
-  } // end for
-
-  plot1D(hits_Counter,14,m_hName4,0,1000,100,1.);
-  plot1D(hits_CounterBC_1,140,m_hName40,0,1000,100,1.);
-  plot1D(hits_CounterBC0,141,m_hName41,0,1000,100,1.);
-  plot1D(hits_CounterBC1,142,m_hName42,0,1000,100,1.);
-  plot1D(hits_CounterBC2,143,m_hName43,0,1000,100,1.);
-  plot1D(hits_CounterBC3,144,m_hName44,0,1000,100,1.);
-  plot1D(hits_CounterBC4,145,m_hName45,0,1000,100,1.);
-  return StatusCode::SUCCESS;
+  }  // end for
+
+  m_hName4->fill(hits_Counter, 1.);
+  m_hName40->fill(hits_CounterBC_1, 1.);
+  m_hName41->fill(hits_CounterBC0, 1.);
+  m_hName42->fill(hits_CounterBC1, 1.);
+  m_hName43->fill(hits_CounterBC2, 1.);
+  m_hName44->fill(hits_CounterBC3, 1.);
+  m_hName45->fill(hits_CounterBC4, 1.);
 }
 
 //=============================================================================
 //  Finalize
 //=============================================================================
 StatusCode MCCaloMonitor::finalize() {
-
-  info()<< "Finalize Monitoring " << m_Detector << endmsg;
+  info() << "Finalize Monitoring " << m_Detector << endmsg;
   return GaudiHistoAlg::finalize();  // must be called after all other actions
 }
 
-
-// ============================================================================
-// The END
-// ============================================================================
+void MCCaloMonitor::bookHistograms() {
+  std::string tmp_hName1 = "Subhits in the " + m_DetectorName;
+  std::string tmp_hName1a = "Subhits in the INNER " + m_DetectorName;
+  std::string tmp_hName1b = "Subhits in the MIDDLE " + m_DetectorName;
+  std::string tmp_hName1c = "Subhits in the OUTER " + m_DetectorName;
+  std::string tmp_hName2 = "Energy Weighted Subhits in the " + m_DetectorName;
+  std::string tmp_hName2a =
+      "Energy Weighted Subhits in the INNER " + m_DetectorName;
+  std::string tmp_hName2b =
+      "Energy Weighted Subhits in the MIDDLE " + m_DetectorName;
+  std::string tmp_hName2c =
+      "Energy Weighted Subhits in the OUTER" + m_DetectorName;
+  std::string tmp_hName3 = "Accumulated Energy in the " + m_DetectorName;
+  std::string tmp_hName3a = "Accumulated Energy in the INNER " + m_DetectorName;
+  std::string tmp_hName3b =
+      "Accumulated Energy in the MIDDLE " + m_DetectorName;
+  std::string tmp_hName3c = "Accumulated Energy in the OUTER " + m_DetectorName;
+  std::string tmp_hName4 = "Number of Subhits in the " + m_DetectorName;
+  std::string tmp_hName40 =
+      "Number of Subhits in the " + m_DetectorName + " ( BC = -1 )";
+  std::string tmp_hName41 =
+      "Number of Subhits in the " + m_DetectorName + " ( BC = 0  )";
+  std::string tmp_hName42 =
+      "Number of Subhits in the " + m_DetectorName + " ( BC = 1  )";
+  std::string tmp_hName43 =
+      "Number of Subhits in the " + m_DetectorName + " ( BC = 2  )";
+  std::string tmp_hName44 =
+      "Number of Subhits in the " + m_DetectorName + " ( BC = 3  )";
+  std::string tmp_hName45 =
+      "Number of Subhits in the " + m_DetectorName + " ( BC = 4  )";
+  m_hName1 = book1D(11, tmp_hName1, m_MinE, m_MaxE, 100);
+  m_hName1a = book1D(111, tmp_hName1a, m_MinE, m_MaxE, 100);
+  m_hName1b = book1D(112, tmp_hName1b, m_MinE, m_MaxE, 100);
+  m_hName1c = book1D(113, tmp_hName1c, m_MinE, m_MaxE, 100);
+  m_hName2 = book1D(12, tmp_hName2, m_MinE, m_MaxE, 100);
+  m_hName2a = book1D(121, tmp_hName2a, m_MinE, m_MaxE, 100);
+  m_hName2b = book1D(122, tmp_hName2b, m_MinE, m_MaxE, 100);
+  m_hName2c = book1D(123, tmp_hName2c, m_MinE, m_MaxE, 100);
+  m_hName3 = book1D(13, tmp_hName3, MinT, MaxT, m_Bin);
+  m_hName3a = book1D(131, tmp_hName3a, MinT, MaxT, m_Bin);
+  m_hName3b = book1D(132, tmp_hName3b, MinT, MaxT, m_Bin);
+  m_hName3c = book1D(133, tmp_hName3c, MinT, MaxT, m_Bin);
+  m_hName4 = book1D(14, tmp_hName4, 0, 1000, 100);
+  m_hName40 = book1D(140, tmp_hName40, 0, 1000, 100);
+  m_hName41 = book1D(141, tmp_hName41, 0, 1000, 100);
+  m_hName42 = book1D(142, tmp_hName42, 0, 1000, 100);
+  m_hName43 = book1D(143, tmp_hName43, 0, 1000, 100);
+  m_hName44 = book1D(144, tmp_hName44, 0, 1000, 100);
+  m_hName45 = book1D(145, tmp_hName45, 0, 1000, 100);
+}
diff --git a/Calo/CaloMoniSim/src/MCCaloMonitor.h b/Calo/CaloMoniSim/src/MCCaloMonitor.h
index 009275901..f10ee752d 100755
--- a/Calo/CaloMoniSim/src/MCCaloMonitor.h
+++ b/Calo/CaloMoniSim/src/MCCaloMonitor.h
@@ -1,31 +1,14 @@
-// $Id: MCCaloMonitor.h,v 1.5 2009-10-23 10:45:22 jonrob Exp $
-// ============================================================================
-// CVS tag $Name: not supported by cvs2svn $
-// ============================================================================
-// $Log: not supported by cvs2svn $
-// Revision 1.4  2009/03/26 21:55:03  robbep
-// changes for spill over generation
-//
-// Revision 1.3  2006/02/13 12:03:00  odescham
-// v2r1 migration to GaudiHistoAlg completed - structure pathes adapted to new enveloppes
-//
-// Revision 1.2  2005/12/16 17:53:59  odescham
-// v2r0 - LHCb v20 migration
-//
-// Revision 1.1.1.1  2004/10/25 08:53:25  ibelyaev
-// // New Package: code imported from Calo/CaloMonitor
-//
-// ============================================================================
-#ifndef MCCALOMONITOR_H
-#define MCCALOMONITOR_H 1
+#pragma once
 
 // Include files
 // from STL
 #include <cmath>
 #include <string>
 #include <vector>
+#include "GaudiAlg/Consumer.h"
 // from Calo
 #include "CaloDet/DeCalorimeter.h"
+#include "Event/MCCaloHit.h"
 
 /** @class MCCaloMonitor MCCaloMonitor.h
  *
@@ -38,79 +21,62 @@
 
 // histograms
 
-class MCCaloMonitor : public GaudiHistoAlg {
-public:
+class MCCaloMonitor
+    : public Gaudi::Functional::Consumer<
+          void(const LHCb::MCCaloHits&),
+          Gaudi::Functional::Traits::BaseClass_t<GaudiHistoAlg>> {
+  public:
   /// Standard constructor
-  MCCaloMonitor( const std::string& name, ISvcLocator* pSvcLocator );
+  MCCaloMonitor(const std::string& name, ISvcLocator* pSvcLocator)
+      : Consumer(name, pSvcLocator,
+                 {KeyValue{"MCCaloHits", LHCb::MCCaloHitLocation::Ecal}}){};
 
-  virtual ~MCCaloMonitor( ); ///< Destructor
+  virtual ~MCCaloMonitor() = default;  ///< Destructor
 
-  StatusCode initialize() override;    ///< Algorithm initialization
-  StatusCode execute   () override;    ///< Algorithm execution
-  StatusCode finalize  () override;    ///< Algorithm finalization
+  StatusCode initialize() override;  ///< Algorithm initialization
+  void operator()(const LHCb::MCCaloHits&) const override;
+  StatusCode finalize() override;  ///< Algorithm finalization
 
-
-private:
+  private:
   // histograms:
 
-  std::string m_nameOfMCHits           ;
-  std::string m_hName1;
-  std::string m_hName1a;
-  std::string m_hName1b;
-  std::string m_hName1c;
-  std::string m_hName2;
-  std::string m_hName2a;
-  std::string m_hName2b;
-  std::string m_hName2c;
-  std::string m_hName3;
-  std::string m_hName3a;
-  std::string m_hName3b;
-  std::string m_hName3c;
-  std::string m_hName4;
-  std::string m_hName40;
-  std::string m_hName41;
-  std::string m_hName42;
-  std::string m_hName43;
-  std::string m_hName44;
-  std::string m_hName45;
-
-  std::string m_hNameNorm1;
-  std::string m_hNameNorm2;
-
-
-
-
-
-
-  std::string m_GeometryRoot ;
-  bool m_DivMonitor;
-  double m_MaxE;
-  double m_MinE;
-  double m_Threshold;
-  int m_MaxT;
-  double MaxT;
-  int m_MinT;
-  double MinT;
-  std::string m_hDir;
-  int m_nEvents;
-  std::string m_Detector;
-  std::string m_DetectorName;
-  std::string m_mcParticles ;
-
-  const std::string m_textNorm;
-
+  AIDA::IHistogram1D* m_hName1{nullptr};
+  AIDA::IHistogram1D* m_hName1a{nullptr};
+  AIDA::IHistogram1D* m_hName1b{nullptr};
+  AIDA::IHistogram1D* m_hName1c{nullptr};
+  AIDA::IHistogram1D* m_hName2{nullptr};
+  AIDA::IHistogram1D* m_hName2a{nullptr};
+  AIDA::IHistogram1D* m_hName2b{nullptr};
+  AIDA::IHistogram1D* m_hName2c{nullptr};
+  AIDA::IHistogram1D* m_hName3{nullptr};
+  AIDA::IHistogram1D* m_hName3a{nullptr};
+  AIDA::IHistogram1D* m_hName3b{nullptr};
+  AIDA::IHistogram1D* m_hName3c{nullptr};
+  AIDA::IHistogram1D* m_hName4{nullptr};
+  AIDA::IHistogram1D* m_hName40{nullptr};
+  AIDA::IHistogram1D* m_hName41{nullptr};
+  AIDA::IHistogram1D* m_hName42{nullptr};
+  AIDA::IHistogram1D* m_hName43{nullptr};
+  AIDA::IHistogram1D* m_hName44{nullptr};
+  AIDA::IHistogram1D* m_hName45{nullptr};
+  void bookHistograms();
+
+  Gaudi::Property<std::string> m_GeometryRoot{
+      this, "GeometryRoot", "/dd/Structure/LHCb/DownstreamRegion/"};
+  Gaudi::Property<bool> m_DivMonitor{this, "Regions", false};
+  Gaudi::Property<double> m_MaxE{this, "MaximumEnergy", 10 * Gaudi::Units::MeV};
+  Gaudi::Property<double> m_MinE{this, "MinimumEnergy", 0 * Gaudi::Units::MeV};
+  Gaudi::Property<double> m_Threshold{this, "Threshold",
+                                      1.5 * Gaudi::Units::MeV};
+  Gaudi::Property<int> m_MaxT{this, "MaximumTime", 7};
+  Gaudi::Property<int> m_MinT{this, "MinimumTime", -1};
+  double MinT, MaxT;
   int m_Bin;
+  std::string m_hDir;
+  Gaudi::Property<std::string> m_Detector{this, "Detector", ""};
+  std::string m_DetectorName{};
 
-  DeCalorimeter * m_detector;
-
-protected:
-
+  // FIXME: Split this out to support different geometries
+  DeCalorimeter* m_detector{nullptr};
+  mutable std::mutex m_histo_mutex;
 };
-
-// ============================================================================
-// The END
-// ============================================================================
-#endif // MCCALOMONITOR_H
-// ============================================================================
-
-
diff --git a/Sim/Gauss/python/Gauss/Geometry/CALO.py b/Sim/Gauss/python/Gauss/Geometry/CALO.py
index 465bb1e64..d56518d9a 100644
--- a/Sim/Gauss/python/Gauss/Geometry/CALO.py
+++ b/Sim/Gauss/python/Gauss/Geometry/CALO.py
@@ -1,6 +1,16 @@
 from Gauss.Geometry.det_base import det_base
 from Gauss.Geometry.Helpers import subdetector
 from Gauss.Geometry.BeamPipe import BeamPipe
+from Gauss.Utilities import GaussImportOptions
+from Gaussino.Utilities import run_once
+from GaudiKernel import SystemOfUnits
+
+
+@run_once
+def add_histos():
+    from Configurables import HistogramDataSvc
+    HistogramDataSvc().Input += [
+        "GaussCalo DATAFILE='$PARAMFILESROOT/data/gausscalo.root' TYP='ROOT'"]
 
 
 @subdetector
@@ -14,6 +24,39 @@ class SPD(det_base):
         detPieces[region] += ['Spd']
         detPieces[region] += ['Converter']
 
+    def SetupExtractionImpl(self, slot=''):
+        add_histos()
+        from Configurables import GetCaloHitsAlg
+        self.simconf_name = 'Spd'
+        det = "Spd"
+        GaussImportOptions("$GAUSSCALOROOT/options/GaussGeo-Spd.opts")
+        alg = GetCaloHitsAlg(
+            "Get"+det+"Hits"+slot,
+            MCHitsLocation='MC/'+det+'/Hits',
+            CollectionName=det+'/Hits'
+            )
+        from Configurables import ApplicationMgr
+        ApplicationMgr().TopAlg += [alg]
+
+    def SetupMonitor(self, slot=''):
+        if slot != '':
+            # Histograms are currently not split by SpillOver slot so skip
+            # for now
+            return
+        from Configurables import MCCaloMonitor
+        det = 'Spd'
+        moni = MCCaloMonitor(
+            det + "Monitor" + slot,
+            MCCaloHits='MC/'+det+'/Hits',
+            OutputLevel=4,
+            Detector='Spd',
+            Regions=True,
+            MaximumEnergy=10.*SystemOfUnits.MeV,
+            Threshold=1.5*SystemOfUnits.MeV
+            )
+        from Configurables import ApplicationMgr
+        ApplicationMgr().TopAlg += [moni]
+
 
 @subdetector
 class PRS(det_base):
@@ -24,6 +67,39 @@ class PRS(det_base):
         region = 'DownstreamRegion'
         detPieces[region] += ['Prs']
 
+    def SetupExtractionImpl(self, slot=''):
+        add_histos()
+        from Configurables import GetCaloHitsAlg
+        GaussImportOptions("$GAUSSCALOROOT/options/GaussGeo-Prs.opts")
+        self.simconf_name = 'Prs'
+        det = "Prs"
+        alg = GetCaloHitsAlg(
+            "Get"+det+"Hits"+slot,
+            MCHitsLocation='MC/'+det+'/Hits',
+            CollectionName=det+'/Hits'
+            )
+        from Configurables import ApplicationMgr
+        ApplicationMgr().TopAlg += [alg]
+
+    def SetupMonitor(self, slot=''):
+        from Configurables import MCCaloMonitor
+        if slot != '':
+            # Histograms are currently not split by SpillOver slot so skip
+            # for now
+            return
+        det = "Prs"
+        moni = MCCaloMonitor(
+            det + "Monitor" + slot,
+            MCCaloHits='MC/'+det+'/Hits',
+            OutputLevel=4,
+            Detector='Prs',
+            Regions=True,
+            MaximumEnergy=10.*SystemOfUnits.MeV,
+            Threshold=1.5*SystemOfUnits.MeV
+            )
+        from Configurables import ApplicationMgr
+        ApplicationMgr().TopAlg += [moni]
+
 
 @subdetector
 class ECAL(det_base):
diff --git a/Sim/Gauss/python/Gauss/Physics.py b/Sim/Gauss/python/Gauss/Physics.py
index b0dc40a38..da407d11f 100644
--- a/Sim/Gauss/python/Gauss/Physics.py
+++ b/Sim/Gauss/python/Gauss/Physics.py
@@ -57,7 +57,6 @@ class G4Physics(LHCbConfigurableUser):
         ecut = 5.0 * SystemOfUnits.mm
         if not self.getProp("DeltaRays"):
             ecut = 10000.0 * SystemOfUnits.m
-        print 'Ecut value =', ecut
         gmpl.CutForElectron = ecut
         gmpl.CutForPositron = 5.0 * SystemOfUnits.mm
         gmpl.CutForGamma = 5.0 * SystemOfUnits.mm
@@ -119,6 +118,8 @@ class G4Physics(LHCbConfigurableUser):
         genPhys = self.getProp('GeneralPhys')
         # Decays
         if genPhys:
+            log.info("Applying general physics (Decays,"
+                     "hadron elastic, ion ...)")
             addConstructor(pl, "G4DecayPhysics", "DecayPhysics")
             addConstructor(pl, "G4EmExtraPhysics", "EmExtraPhysics")
             addConstructor(pl, "G4IonPhysics", "IonPhysics")
@@ -154,6 +155,7 @@ class G4Physics(LHCbConfigurableUser):
                 ("G4StoppingPhysics", "StoppingPhysics")],
         }
         if hadronPhys in _all:
+            log.info("Applying hadronic physics {}.".format(hadronPhys))
             for hp in _all[hadronPhys]:
                 addConstructor(pl, *hp)
             return True
@@ -165,6 +167,7 @@ class G4Physics(LHCbConfigurableUser):
         lhcbPhys = self.getProp('LHCbPhys')
         richUpgradeConfig = self.getProp('RichUpgradeConfig')
         if lhcbPhys:
+            log.info("Applying LHCb specific physics.")
             if richUpgradeConfig:
                 self.defineRichMaPmtPhys(pl)
             else:
@@ -186,6 +189,7 @@ class G4Physics(LHCbConfigurableUser):
                                    "PhysicsList chosen ('%s')" % otherPhys)
 
     def AddTrackingCuts(self, pl):
+        log.info("Adding tracking cuts.")
         from Configurables import TrCutsRunAction
         pl.addTool(TrCutsRunAction("TrCuts"), name="TrCuts")
         pl.PhysicsConstructors.append("TrCutsRunAction/TrCuts")
diff --git a/Sim/Gauss/python/Gauss/Utilities.py b/Sim/Gauss/python/Gauss/Utilities.py
index bd5216900..66dff20b2 100644
--- a/Sim/Gauss/python/Gauss/Utilities.py
+++ b/Sim/Gauss/python/Gauss/Utilities.py
@@ -1,3 +1,16 @@
+from Gaudi.Configuration import importOptions
+from Gaussino.Utilities import run_once
+
+
+@run_once
+def _importBaseOptions():
+    importOptions("$STDOPTS/PreloadUnits.opts")
+
+
+def GaussImportOptions(options):
+    _importBaseOptions()
+    importOptions(options)
+
 
 class HelperBase:
 
diff --git a/Sim/GaussCalo/options/GaussGeo-Prs.opts b/Sim/GaussCalo/options/GaussGeo-Prs.opts
index 2b9e64189..120570064 100644
--- a/Sim/GaussCalo/options/GaussGeo-Prs.opts
+++ b/Sim/GaussCalo/options/GaussGeo-Prs.opts
@@ -14,12 +14,12 @@ GaussGeo.Prs.StartVolumes = {
 };
 
 GaussGeo.Prs.EndVolume      =  "/dd/Geometry/DownstreamRegion/Prs/Installation/Prs" ;
-GaussGeo.Prs.CollectionName =  "PrsHits"                            ;
+// GaussGeo.Prs.CollectionName =  "PrsHits"                            ;
 GaussGeo.Prs.Detector       =  "/dd/Structure/LHCb/DownstreamRegion/Prs"             ;
 GaussGeo.Prs.zMin           =  12300. * mm ;
 GaussGeo.Prs.zMax           =  15000. * mm ;
 
-GaussGeo.Prs.DetectorPath   =  "/LHCb/Calo"             ;
+// GaussGeo.Prs.DetectorPath   =  "/LHCb/Calo"             ;
 
 GaussGeo.Prs.IntegrationDelays = { 18.5 * ns , 17.5 * ns , 16.5 * ns } ;
 
@@ -32,7 +32,7 @@ GaussGeo.Prs.Histograms = {
 
 // Conversion of Hits
 GetPrsHits.MCHitsLocation = "/Event/MC/Prs/Hits" ;
-GetPrsHits.CollectionName = "PrsHits" ;
+GetPrsHits.CollectionName = "Prs/Hits" ;
 
 // ============================================================================
 // The END 
diff --git a/Sim/GaussCalo/options/GaussGeo-Spd.opts b/Sim/GaussCalo/options/GaussGeo-Spd.opts
index b0cea2703..98ee17307 100644
--- a/Sim/GaussCalo/options/GaussGeo-Spd.opts
+++ b/Sim/GaussCalo/options/GaussGeo-Spd.opts
@@ -14,12 +14,12 @@ GaussGeo.Spd.StartVolumes = {
 };
 
 GaussGeo.Spd.EndVolume      =  "/dd/Geometry/DownstreamRegion/Spd/Installation/Spd" ;
-GaussGeo.Spd.CollectionName =  "SpdHits"                            ;
+// GaussGeo.Spd.CollectionName =  "SpdHits"                            ;
 GaussGeo.Spd.Detector       =  "/dd/Structure/LHCb/DownstreamRegion/Spd"             ;
 GaussGeo.Spd.zMin           =  12300. * mm ;
 GaussGeo.Spd.zMax           =  15000. * mm ;
 
-GaussGeo.Spd.DetectorPath   =  "/LHCb/Calo"             ;
+// GaussGeo.Spd.DetectorPath   =  "/LHCb/Calo"             ;
 
 GaussGeo.Spd.IntegrationDelays = { 18.5 * ns , 17.5 * ns , 16.5 * ns } ;
 
@@ -32,7 +32,7 @@ GaussGeo.Spd.Histograms = {
 
 // Conversion of Hits
 GetSpdHits.MCHitsLocation = "/Event/MC/Spd/Hits" ;
-GetSpdHits.CollectionName = "SpdHits" ;
+GetSpdHits.CollectionName = "Spd/Hits" ;
 
 // ============================================================================
 // The END 
diff --git a/Sim/GaussCalo/src/CaloSensDet.icpp b/Sim/GaussCalo/src/CaloSensDet.icpp
index 92c71a3d4..2610f2338 100755
--- a/Sim/GaussCalo/src/CaloSensDet.icpp
+++ b/Sim/GaussCalo/src/CaloSensDet.icpp
@@ -400,17 +400,17 @@ void CaloSensDet<CELLGETTER>::GeoBaseInitialize() {
     const G4LogicalVolume* lv =
         G4LogicalVolumeStore::GetInstance()->GetVolume(vol);
     if (0 == lv) {
-      throw std::runtime_error("G4LogicalVolume* points to 0 for " + (vol));
+      throw std::runtime_error(std::string(__PRETTY_FUNCTION__) + "G4LogicalVolume* points to 0 for " + (vol));
     }
     m_start.push_back(lv);
   }
   if (m_start.empty()) {
-    throw std::runtime_error("Size of 'StartVolumes' is 0 ");
+    throw std::runtime_error(std::string(__PRETTY_FUNCTION__) + "Size of 'StartVolumes' is 0 ");
   }
   // locate end volume : look through converted volumes
   m_end = G4LogicalVolumeStore::GetInstance()->GetVolume(m_endVolumeName);
   if (0 == m_end) {
-    throw std::runtime_error("G4LogicalVolume* points to 0 for '" +
+    throw std::runtime_error(std::string(__PRETTY_FUNCTION__) + "G4LogicalVolume* points to 0 for '" +
                              m_endVolumeName + "'");
   }
   m_geoBaseInitialized = true;
diff --git a/Sim/GaussCalo/src/CaloSensDetFAC.h b/Sim/GaussCalo/src/CaloSensDetFAC.h
index 4eb518243..0c3ff731a 100755
--- a/Sim/GaussCalo/src/CaloSensDetFAC.h
+++ b/Sim/GaussCalo/src/CaloSensDetFAC.h
@@ -38,10 +38,10 @@ class CaloSensDetBaseFAC : public GiGaMTG4SensDetFactory<CALO> {
   ServiceHandle<IHistogramSvc> m_histoSvc{this, "HistogramDataSvc",
                                           "HistogramDataSvc"};
 
-  Gaudi::Accumulators::SummingCounter<size_t> m_nhits{this, "#hits"};
-  Gaudi::Accumulators::SummingCounter<size_t> m_nshits{this, "#subhits"};
-  Gaudi::Accumulators::SummingCounter<size_t> m_nslots{this, "#tslots"};
-  Gaudi::Accumulators::SummingCounter<double> m_energy{this, "#energy"};
+  mutable Gaudi::Accumulators::SummingCounter<size_t> m_nhits{this, "#hits"};
+  mutable Gaudi::Accumulators::SummingCounter<size_t> m_nshits{this, "#subhits"};
+  mutable Gaudi::Accumulators::SummingCounter<size_t> m_nslots{this, "#tslots"};
+  mutable Gaudi::Accumulators::SummingCounter<double> m_energy{this, "#energy"};
 
   public:
   virtual ~CaloSensDetBaseFAC() = default;
@@ -58,11 +58,16 @@ class CaloSensDetBaseFAC : public GiGaMTG4SensDetFactory<CALO> {
     tmp->m_zmax = m_zmax;
     tmp->m_dT0 = m_dT0;
     tmp->m_histos = m_histos;
+    tmp->m_nhits = &m_nhits;
+    tmp->m_nshits = &m_nshits;
+    tmp->m_nslots = &m_nslots;
+    tmp->m_energy = &m_energy;
     return tmp;
   }
   StatusCode initialize() override {
     auto sc = gaussino_base_class::initialize();
 
+    m_histoSvc.retrieve();
     {  // load all input histos
       for (auto& histo : m_histoNames) {
         SmartDataPtr<IHistogram1D> pHist(m_histoSvc.get(), histo);
diff --git a/Sim/GaussCalo/src/CaloSubHit.h b/Sim/GaussCalo/src/CaloSubHit.h
index 5c1b6423d..877eafbf2 100755
--- a/Sim/GaussCalo/src/CaloSubHit.h
+++ b/Sim/GaussCalo/src/CaloSubHit.h
@@ -1,3 +1,4 @@
+#pragma once
 // Kernel
 #include "Kernel/CaloCellID.h"
 // GiGa
diff --git a/Sim/GaussCalo/src/GetCaloHitsAlg.cpp b/Sim/GaussCalo/src/GetCaloHitsAlg.cpp
index 5c5d9cd17..07e95e198 100755
--- a/Sim/GaussCalo/src/GetCaloHitsAlg.cpp
+++ b/Sim/GaussCalo/src/GetCaloHitsAlg.cpp
@@ -1,24 +1,16 @@
 // $Id: GetCaloHitsAlg.cpp,v 1.6 2009-03-26 21:38:44 robbep Exp $
-// Include files 
+// Include files
 
 // from Gaudi
 
-// from GiGa 
-#include "GiGa/IGiGaSvc.h"
-#include "GiGa/GiGaHitsByName.h"
-
-// from GiGaCnv
-#include "GiGaCnv/IGiGaKineCnvSvc.h" 
-#include "GiGaCnv/IGiGaCnvSvcLocation.h"
-#include "GiGaCnv/GiGaKineRefTable.h"
-
-// Event 
+// Event
 #include "Event/MCCaloHit.h"
 
 // local
 #include "CaloHit.h"
 #include "CaloSubHit.h"
 #include "GetCaloHitsAlg.h"
+#include "GiGaMTCore/Truth/MCTruthConverter.h"
 
 //-----------------------------------------------------------------------------
 // Implementation file for class : GetCaloHitsAlg
@@ -27,140 +19,91 @@
 //-----------------------------------------------------------------------------
 
 // Declaration of the Algorithm Factory
-DECLARE_COMPONENT( GetCaloHitsAlg )
-
-
-//=============================================================================
-// Standard constructor, initializes variables
-//=============================================================================
-GetCaloHitsAlg::GetCaloHitsAlg( const std::string& name,
-                                ISvcLocator* pSvcLocator)
-  : GaudiAlgorithm ( name , pSvcLocator ) ,
-    m_gigaSvc( 0 ) , 
-    m_gigaKineCnvSvc( 0 ) {
-    declareProperty( "GiGaService" , m_gigaSvcName = "GiGa" ) ;
-    declareProperty( "KineCnvService" , 
-                     m_kineSvcName = IGiGaCnvSvcLocation::Kine ) ;
-    declareProperty( "MCHitsLocation" , m_hitsLocation = "" ) ;
-    declareProperty( "CollectionName" , m_colName = "" ) ;
-    declareProperty( "MCParticles"    , 
-                     m_mcParticles = LHCb::MCParticleLocation::Default ) ;
-  }
-
-//=============================================================================
-// Destructor
-//=============================================================================
-GetCaloHitsAlg::~GetCaloHitsAlg() {}
-
-//=============================================================================
-// Initialisation. Check parameters
-//=============================================================================
-StatusCode GetCaloHitsAlg::initialize() {
-  // Initialize base class
-  StatusCode sc = GaudiAlgorithm::initialize() ;
-  if ( sc.isFailure() ) return sc ;
-
-  debug() << "==> Initialise" << endmsg ;
-
-  // Get GiGa Service 
-  m_gigaSvc = svc< IGiGaSvc >( m_gigaSvcName ) ;
-
-  // Check GiGa service exists
-  if ( 0 == m_gigaSvc ) 
-    return Error( "execute() : IGiGaSvc* points to NULL" ) ;
-  
-  // get kineCnv service holding MCParticle/Geant4 table
-  m_gigaKineCnvSvc = svc< IGiGaKineCnvSvc >( m_kineSvcName ) ;
-  
-  return StatusCode::SUCCESS;
-}
+DECLARE_COMPONENT(GetCaloHitsAlg)
 
 //=============================================================================
 // Main execution
 //=============================================================================
-StatusCode GetCaloHitsAlg::execute() {
-  debug() << "==> Execute" << endmsg ;
-
-  // Register output container to contain MCCaloHits
-  LHCb::MCCaloHits * hits = new LHCb::MCCaloHits( ) ;
-  put( hits , m_hitsLocation ) ;
-  
-  // Get the G4 hit collections corresponding to Calo
-  GiGaHitsByName col( m_colName ) ;
-  *m_gigaSvc >> col ;
-  if ( 0 == col.hits( ) ) 
-    return Warning( "The hit collection='" + m_colName + "' is not found ! " ,
-                    StatusCode::SUCCESS ) ;
-  
-  // Now cast to Calo hits collections
-  const CaloHitsCollection * hitCollection = caloHits( col.hits( ) ) ;
-  if ( 0 == hitCollection ) return Error( "Wrong collection type" ) ;
-  
-  // Get the reference table between G4 tracks and MC particles
-  if ( ! exist< LHCb::MCParticles >( m_mcParticles ) ) 
-    return Error( "LHCb::MCParticles do not exist at'" +
-                  m_mcParticles + "'" ) ;
-  const GiGaKineRefTable & table = m_gigaKineCnvSvc -> table() ;
-
-  const size_t numOfHits = hitCollection -> entries() ;
-  if ( numOfHits > 0 ) {
-    hits->reserve( numOfHits );
-  }
-  
-  // transform G4Hit in MCHits:
-  // Loop over all hits in collection
-  for ( size_t iHit = 0 ; iHit < numOfHits ; ++iHit ) {
-    // The calo hit in the calorimeter
-    const CaloHit * hit = (*hitCollection)[ iHit ] ;
-    if ( 0 == hit ) continue ;
-
-    // Loop over all sub hits of this calo hit
-    for ( CaloHit::iterator iter = hit -> begin() ; iter != hit -> end( ) ;
-          ++iter ) {
-      // The sub hit
-      const CaloSubHit * subhit = iter -> second ;
-      if ( 0 == subhit ) continue ;
-      
-      // Pointer to the corresponding LHCb::MCParticle using trackID of the subhit
-      const LHCb::MCParticle * mcp = table( subhit -> trackID() ).particle( ) ;
-      if ( 0 == mcp ) 
-        warning() << "No pointer to LHCb::MCParticle for MCHit associated to G4 "
-                  << "trackID: " << subhit -> trackID() << endmsg ;
-      
-      // Loop over all energy/time deposits strored in the subhit
-      for ( CaloSubHit::iterator entry = subhit -> begin() ; 
-            entry != subhit -> end() ; ++entry ) {
-        // Create the new MCHit
-        LHCb::MCCaloHit * mchit = new LHCb::MCCaloHit() ;
-        // Fill it with:
-        //   - Calorimeter CellID of the hit
-        mchit -> setCellID( hit -> cellID() ) ;
-        //   - Time when the energy is deposited
-        mchit -> setTime( entry -> first ) ;
-        //   - Active energy deposited
-        mchit -> setActiveE( entry -> second ) ;
-        //   - Pointer to the LHCb::MCParticle giving the hit
-        mchit -> setParticle( mcp ) ;
-
-        // Now insert in output container
-        hits -> add( mchit ) ;
-      }
-    } 
-  }
-  
-  return StatusCode::SUCCESS;
-}
-
-//=============================================================================
-//  Finalize
-//=============================================================================
-StatusCode GetCaloHitsAlg::finalize() {
-  debug() << "==> Finalize" << endmsg ;
-
-  release( m_gigaSvc ) ;
-  release( m_gigaKineCnvSvc ) ;
-
-  return GaudiAlgorithm::finalize( ) ;
+LHCb::MCCaloHits GetCaloHitsAlg::operator()(
+    const G4EventProxies& eventproxies,
+    const LinkedParticleMCParticleLinks& mcplinks) const {
+    debug() << "==> Execute" << endmsg;
+
+    // Register output container to contain MCCaloHits
+    LHCb::MCCaloHits hits{};
+    size_t total_numHits{0};
+
+    for (auto& ep : eventproxies) {
+        auto hitCollection = ep.GetHitCollection<CaloHitsCollection>(m_colName);
+        if (hitCollection) {
+            total_numHits += hitCollection->entries();
+        }
+    }
+    if (total_numHits > 0) {
+        hits.reserve(total_numHits);
+    }
+
+    for (auto& ep : eventproxies) {
+        auto hitCollection = ep.GetHitCollection<CaloHitsCollection>(m_colName);
+        if (!hitCollection) {
+            warning() << "The hit collection='" + m_colName + "' is not found!"
+                      << endmsg;
+            continue;
+        }
+        // reserve elements on output container
+        size_t numOfHits = hitCollection->entries();
+        // transform G4Hit in MCHits:
+        // Loop over all hits in collection
+        for (size_t iHit = 0; iHit < numOfHits; ++iHit) {
+            // The calo hit in the calorimeter
+            const CaloHit* hit = (*hitCollection)[iHit];
+            if (0 == hit) continue;
+
+            // Loop over all sub hits of this calo hit
+            for (CaloHit::iterator iter = hit->begin(); iter != hit->end();
+                 ++iter) {
+                // The sub hit
+                const CaloSubHit* subhit = iter->second;
+                if (0 == subhit) continue;
+
+                // Loop over all energy/time deposits strored in the subhit
+                for (CaloSubHit::iterator entry = subhit->begin();
+                     entry != subhit->end(); ++entry) {
+                    // Create the new MCHit
+                    LHCb::MCCaloHit* mchit = new LHCb::MCCaloHit();
+                    // Fill it with:
+                    //   - Calorimeter CellID of the hit
+                    mchit->setCellID(hit->cellID());
+                    //   - Time when the energy is deposited
+                    mchit->setTime(entry->first);
+                    //   - Active energy deposited
+                    mchit->setActiveE(entry->second);
+                    //   - Pointer to the LHCb::MCParticle giving the hit
+                    int trackID = subhit->GetTrackID();
+                    if (auto lp = ep.truth()->GetParticleFromTrackID(trackID);
+                        lp) {
+                        if (auto it = mcplinks.find(lp);
+                            it != std::end(mcplinks)) {
+                            mchit->setParticle(it->second);
+                        } else {
+                            warning() << "No pointer to MCParticle for MCHit "
+                                         "associated to G4 "
+                                         "trackID: "
+                                      << trackID << endmsg;
+                        }
+                    } else {
+                        warning() << "No LinkedParticle found. Something went "
+                                     "seriously wrong. "
+                                     "trackID: "
+                                  << trackID << endmsg;
+                    }
+
+                    // Now insert in output container
+                    hits.add(mchit);
+                }
+            }
+        }
+    }
+
+    return hits;
 }
-
-//=============================================================================
diff --git a/Sim/GaussCalo/src/GetCaloHitsAlg.h b/Sim/GaussCalo/src/GetCaloHitsAlg.h
index 9a327dd97..73a811bcc 100755
--- a/Sim/GaussCalo/src/GetCaloHitsAlg.h
+++ b/Sim/GaussCalo/src/GetCaloHitsAlg.h
@@ -1,14 +1,11 @@
-// $Id: GetCaloHitsAlg.h,v 1.2 2009-03-26 21:38:44 robbep Exp $
-#ifndef GAUSSCALO_GETCALOHITSALG_H
-#define GAUSSCALO_GETCALOHITSALG_H 1
+#pragma once
 
-// Include files
-// from Gaudi
+#include "Defaults/Locations.h"
+#include "Event/MCCaloHit.h"
 #include "GaudiAlg/GaudiAlgorithm.h"
-
-// forward declarations
-class IGiGaSvc ;
-class IGiGaKineCnvSvc ;
+#include "GaudiAlg/Transformer.h"
+#include "GiGaMTCore/G4EventProxy.h"
+#include "MCTruthToEDM/LinkedParticleMCParticleLink.h"
 
 /** @class GetCaloHitsAlg GetCaloHitsAlg.h
  *  Conversion from G4 hits to MC CaloHits
@@ -16,34 +13,27 @@ class IGiGaKineCnvSvc ;
  *  @author Patrick Robbe
  *  @date   2005-11-14
  */
-class GetCaloHitsAlg : public GaudiAlgorithm {
+class GetCaloHitsAlg
+    : public Gaudi::Functional::Transformer<LHCb::MCCaloHits(
+          const G4EventProxies&, const LinkedParticleMCParticleLinks&)> {
 public:
-  /// Standard constructor
-  GetCaloHitsAlg( const std::string& name, ISvcLocator* pSvcLocator );
-
-  virtual ~GetCaloHitsAlg( ); ///< Destructor
-
-  StatusCode initialize() override;    ///< Algorithm initialization
-  StatusCode execute   () override;    ///< Algorithm execution
-  StatusCode finalize  () override;    ///< Algorithm finalization
+    /// Standard constructor
+    GetCaloHitsAlg(const std::string& name, ISvcLocator* pSvcLocator)
+        : Transformer(
+              name, pSvcLocator,
+              {{KeyValue{"Input", Gaussino::G4EventsLocation::Default},
+                KeyValue{
+                    "LinkedParticleMCParticleLinks",
+                    Gaussino::LinkedParticleMCParticleLinksLocation::Default}}},
+              KeyValue{"MCHitsLocation", ""}) {}
+
+    virtual ~GetCaloHitsAlg() = default;
+
+    virtual LHCb::MCCaloHits operator()(
+        const G4EventProxies&,
+        const LinkedParticleMCParticleLinks&) const override;
 
 protected:
-
 private:
-/// Name of the GiGa service
-  std::string m_gigaSvcName ;
-  /// Name of the GiGaCnv service
-  std::string m_kineSvcName ;
-  /// Name of the output location of MCHits
-  std::string m_hitsLocation ;
-  /// Name of the G4 hits collection
-  std::string m_colName ;
-  /// Name of the MCParticles location
-  std::string m_mcParticles ;
-
-  /// Pointer to the GiGa service
-  IGiGaSvc * m_gigaSvc ;
-  /// Pointer to the GiGaKine service
-  IGiGaKineCnvSvc * m_gigaKineCnvSvc ;
+    Gaudi::Property<std::string> m_colName{this, "CollectionName", ""};
 };
-#endif // GAUSSCALO_GETCALOHITSALG_H
-- 
GitLab


From b75789ecc458eec5a20735faf4d61f34721a541f Mon Sep 17 00:00:00 2001
From: Dominik Muller <dominik.muller@cern.ch>
Date: Thu, 18 Jul 2019 17:02:08 +0200
Subject: [PATCH 19/90] Ported Ecal and HCal support

---
 Sim/Gauss/python/Gauss/Geometry/CALO.py  |  66 +++++++
 Sim/GaussCalo/options/GaussGeo-Ecal.opts |   6 +-
 Sim/GaussCalo/options/GaussGeo-Hcal.opts |   6 +-
 Sim/GaussCalo/src/CaloSensDet.h          |   8 +-
 Sim/GaussCalo/src/EHCalSensDet.cpp       |  99 -----------
 Sim/GaussCalo/src/EHCalSensDet.h         | 112 ------------
 Sim/GaussCalo/src/EcalSensDet.cpp        | 217 ++++++++++++-----------
 Sim/GaussCalo/src/EcalSensDet.h          | 192 ++++++++------------
 Sim/GaussCalo/src/HcalSensDet.cpp        | 154 ++++++++--------
 Sim/GaussCalo/src/HcalSensDet.h          |  75 +++-----
 10 files changed, 378 insertions(+), 557 deletions(-)
 delete mode 100755 Sim/GaussCalo/src/EHCalSensDet.cpp
 delete mode 100755 Sim/GaussCalo/src/EHCalSensDet.h

diff --git a/Sim/Gauss/python/Gauss/Geometry/CALO.py b/Sim/Gauss/python/Gauss/Geometry/CALO.py
index d56518d9a..3d160e555 100644
--- a/Sim/Gauss/python/Gauss/Geometry/CALO.py
+++ b/Sim/Gauss/python/Gauss/Geometry/CALO.py
@@ -110,6 +110,39 @@ class ECAL(det_base):
         region = 'DownstreamRegion'
         detPieces[region] += ['Ecal']
 
+    def SetupExtractionImpl(self, slot=''):
+        add_histos()
+        from Configurables import GetCaloHitsAlg
+        GaussImportOptions("$GAUSSCALOROOT/options/GaussGeo-Ecal.opts")
+        self.simconf_name = 'Ecal'
+        det = "Ecal"
+        alg = GetCaloHitsAlg(
+            "Get"+det+"Hits"+slot,
+            MCHitsLocation='MC/'+det+'/Hits',
+            CollectionName=det+'/Hits'
+            )
+        from Configurables import ApplicationMgr
+        ApplicationMgr().TopAlg += [alg]
+
+    def SetupMonitor(self, slot=''):
+        from Configurables import MCCaloMonitor
+        if slot != '':
+            # Histograms are currently not split by SpillOver slot so skip
+            # for now
+            return
+        det = "Ecal"
+        moni = MCCaloMonitor(
+            det + "Monitor" + slot,
+            MCCaloHits='MC/'+det+'/Hits',
+            OutputLevel=4,
+            Detector=det,
+            Regions=True,
+            MaximumEnergy=1000.*SystemOfUnits.MeV,
+            Threshold=10.*SystemOfUnits.MeV
+            )
+        from Configurables import ApplicationMgr
+        ApplicationMgr().TopAlg += [moni]
+
 
 @subdetector
 class HCAL(det_base):
@@ -119,3 +152,36 @@ class HCAL(det_base):
     def ApplyDetector(self, basePieces, detPieces):
         region = 'DownstreamRegion'
         detPieces[region] += ['Hcal']
+
+    def SetupExtractionImpl(self, slot=''):
+        add_histos()
+        from Configurables import GetCaloHitsAlg
+        GaussImportOptions("$GAUSSCALOROOT/options/GaussGeo-Hcal.opts")
+        self.simconf_name = 'Hcal'
+        det = "Hcal"
+        alg = GetCaloHitsAlg(
+            "Get"+det+"Hits"+slot,
+            MCHitsLocation='MC/'+det+'/Hits',
+            CollectionName=det+'/Hits'
+            )
+        from Configurables import ApplicationMgr
+        ApplicationMgr().TopAlg += [alg]
+
+    def SetupMonitor(self, slot=''):
+        from Configurables import MCCaloMonitor
+        if slot != '':
+            # Histograms are currently not split by SpillOver slot so skip
+            # for now
+            return
+        det = "Hcal"
+        moni = MCCaloMonitor(
+            det + "Monitor" + slot,
+            MCCaloHits='MC/'+det+'/Hits',
+            OutputLevel=4,
+            Detector=det,
+            Regions=True,
+            MaximumEnergy=1000.*SystemOfUnits.MeV,
+            Threshold=5.*SystemOfUnits.MeV
+            )
+        from Configurables import ApplicationMgr
+        ApplicationMgr().TopAlg += [moni]
diff --git a/Sim/GaussCalo/options/GaussGeo-Ecal.opts b/Sim/GaussCalo/options/GaussGeo-Ecal.opts
index d685720b7..b0cfb040a 100644
--- a/Sim/GaussCalo/options/GaussGeo-Ecal.opts
+++ b/Sim/GaussCalo/options/GaussGeo-Ecal.opts
@@ -14,12 +14,12 @@ GaussGeo.Ecal.StartVolumes = {
 };
 
 GaussGeo.Ecal.EndVolume      =  "/dd/Geometry/DownstreamRegion/Ecal/Installation/Ecal" ;
-GaussGeo.Ecal.CollectionName =  "EcalHits"                            ;
+// GaussGeo.Ecal.CollectionName =  "EcalHits"                            ;
 GaussGeo.Ecal.Detector       =  "/dd/Structure/LHCb/DownstreamRegion/Ecal"             ;
 GaussGeo.Ecal.zMin           =  12300. * mm ;
 GaussGeo.Ecal.zMax           =  15000. * mm ;
 
-GaussGeo.Ecal.DetectorPath   =  "/LHCb/Calo"             ;
+// GaussGeo.Ecal.DetectorPath   =  "/LHCb/Calo"             ;
 
 // Input Root histograms
 GaussGeo.Ecal.Histograms = { 
@@ -29,7 +29,7 @@ GaussGeo.Ecal.Histograms = {
 
 // Conversion of Hits
 GetEcalHits.MCHitsLocation = "/Event/MC/Ecal/Hits" ;
-GetEcalHits.CollectionName = "EcalHits" ;
+// GetEcalHits.CollectionName = "EcalHits" ;
 
 // ============================================================================
 // The END 
diff --git a/Sim/GaussCalo/options/GaussGeo-Hcal.opts b/Sim/GaussCalo/options/GaussGeo-Hcal.opts
index 01c4949f8..e9fd1eb0e 100644
--- a/Sim/GaussCalo/options/GaussGeo-Hcal.opts
+++ b/Sim/GaussCalo/options/GaussGeo-Hcal.opts
@@ -14,12 +14,12 @@ GaussGeo.Hcal.StartVolumes = {
 };
 
 GaussGeo.Hcal.EndVolume      =  "/dd/Geometry/DownstreamRegion/Hcal/Installation/lvHcal" ;
-GaussGeo.Hcal.CollectionName =  "HcalHits"                            ;
+// GaussGeo.Hcal.CollectionName =  "HcalHits"                            ;
 GaussGeo.Hcal.Detector       =  "/dd/Structure/LHCb/DownstreamRegion/Hcal"             ;
 GaussGeo.Hcal.zMin           =  12300. * mm ;
 GaussGeo.Hcal.zMax           =  15000. * mm ;
 
-GaussGeo.Hcal.DetectorPath   =  "/LHCb/Calo"             ;
+// GaussGeo.Hcal.DetectorPath   =  "/LHCb/Calo"             ;
 
 // Input Root histograms
 GaussGeo.Hcal.Histograms = { 
@@ -34,7 +34,7 @@ GaussGeo.Hcal.Histograms = {
 
 // Conversion of Hits
 GetHcalHits.MCHitsLocation = "/Event/MC/Hcal/Hits" ;
-GetHcalHits.CollectionName = "HcalHits" ;
+// GetHcalHits.CollectionName = "HcalHits" ;
 
 // ============================================================================
 // The END 
diff --git a/Sim/GaussCalo/src/CaloSensDet.h b/Sim/GaussCalo/src/CaloSensDet.h
index 3f3572241..859765f5d 100755
--- a/Sim/GaussCalo/src/CaloSensDet.h
+++ b/Sim/GaussCalo/src/CaloSensDet.h
@@ -260,7 +260,6 @@ class CaloSensDet : public G4VSensitiveDetector,
   Gaudi::Accumulators::SummingCounter<double>* m_energy{nullptr};
 };
 
-#include "CaloSensDet.icpp"
 
 // CaloDet
 #include "CaloDet/DeCalorimeter.h"
@@ -271,6 +270,11 @@ class CellFromLHCbGeo : public virtual GiGaMessage {
   inline double cellTime(const LHCb::CaloCellID& cellID) const {
     return m_calo->cellTime(cellID);
   };
+
+  inline double cellX(const LHCb::CaloCellID& id) const {return m_calo->cellX( id);};
+  inline double cellY(const LHCb::CaloCellID& id) const {return m_calo->cellY( id);};
+  inline double cellSize(const LHCb::CaloCellID& id) const {return m_calo->cellSize(id);}
+
   inline LHCb::CaloCellID cellID(const Gaudi::XYZPoint& position) const {
     const CellParam* par = m_calo->Cell_(position);
     if (0 == par || !par->valid()) {
@@ -285,3 +289,5 @@ class CellFromLHCbGeo : public virtual GiGaMessage {
   const DeCalorimeter* m_calo{nullptr};
   int m_caloID{0};
 };
+
+#include "CaloSensDet.icpp"
diff --git a/Sim/GaussCalo/src/EHCalSensDet.cpp b/Sim/GaussCalo/src/EHCalSensDet.cpp
deleted file mode 100755
index 4676cf923..000000000
--- a/Sim/GaussCalo/src/EHCalSensDet.cpp
+++ /dev/null
@@ -1,99 +0,0 @@
-// $Id: EHCalSensDet.cpp,v 1.6 2008-07-11 10:47:44 robbep Exp $ 
-// Include files 
-
-// SRD & STD 
-#include <algorithm>
-#include <vector>
-
-// CLHEP 
-#include "CLHEP/Geometry/Point3D.h"
-#include "CLHEP/Units/PhysicalConstants.h"
-
-// GaudiKernel
-#include "GaudiKernel/MsgStream.h"
-#include "GaudiKernel/SmartDataPtr.h" 
-#include "GaudiKernel/IDataProviderSvc.h"
-
-// GaussTools 
-#include "GaussTools/GaussTrackInformation.h"
-
-// Geant4 
-#include "Geant4/G4Step.hh"
-#include "Geant4/G4TouchableHistory.hh"
-#include "Geant4/G4VPhysicalVolume.hh"
-#include "Geant4/G4LogicalVolume.hh"
-#include "Geant4/G4SDManager.hh"
-#include "Geant4/G4EnergyLossTables.hh"
-
-// GiGaCnv 
-#include "GiGaCnv/GiGaVolumeUtils.h"
-
-// CaloDet
-#include "CaloDet/DeCalorimeter.h"
-
-// local
-#include "CaloHit.h"
-#include "CaloSimHash.h"
-#include "EHCalSensDet.h"
-
-//
-#include "AIDA/IHistogram1D.h"
-
-//-----------------------------------------------------------------------------
-//
-//  Implementation of class EHCalSensDet
-//
-//  2001-01-23 : Vanya Belyaev, Patrick Robbe
-//
-//-----------------------------------------------------------------------------
-
-//=============================================================================
-// Standard constructor, initializes variables
-//=============================================================================
-EHCalSensDet::EHCalSensDet
-( const std::string& type   ,
-  const std::string& name   ,
-  const IInterface*  parent )
-  : G4VSensitiveDetector( name  )
-  , CaloSensDet        ( type , name , parent )
-  , m_slotWidth( 25 * CLHEP::ns )
-{
-  declareProperty( "SlotWidth" , m_slotWidth );
-}
-
-//=============================================================================
-// The fractions of energy deposited in consequitive time-slots
-// in the given Ecal/Hcal cell
-//=============================================================================
-StatusCode EHCalSensDet::timing 
-( const double             time      , 
-  const LHCb::CaloCellID&        cell      ,
-  CaloSubHit::Time&        slot    ,
-  CaloSensDet::Fractions&  fractions ) const 
-{
-  // clear input data 
-  slot = 0 ; fractions.clear();
-  
-  // evaluate the real delta time  
-  const double deltaT = time - t0 ( cell ) ;
-  
-  // find the absolute time slot 
-  slot  = (CaloSubHit::Time) floor( deltaT / slotWidth() ) ;
-  
-  // the time into the slot 
-  const double dt  = deltaT - slot * slotWidth() ;
-  
-  for ( Histos::const_iterator ihist = histos().begin() ; 
-        histos().end() != ihist ; ++ihist ) 
-    {
-      const AIDA::IHistogram1D* histo = *ihist ;
-      const int           bin   = histo -> coordToIndex ( dt / CLHEP::ns ) ;
-      const double        frac  = histo -> binHeight    ( bin     ) ;
-      fractions.push_back( frac ) ;
-    };
-  
-  if( fractions.empty() ) 
-    { Warning("timing()::no time information is available!"); }
-  
-  return StatusCode::SUCCESS ;
-}
diff --git a/Sim/GaussCalo/src/EHCalSensDet.h b/Sim/GaussCalo/src/EHCalSensDet.h
deleted file mode 100755
index db02d88ff..000000000
--- a/Sim/GaussCalo/src/EHCalSensDet.h
+++ /dev/null
@@ -1,112 +0,0 @@
-// $Id: EHCalSensDet.h,v 1.5 2007-03-18 21:33:19 gcorti Exp $
-// ============================================================================
-// CVS tag $Name: not supported by cvs2svn $
-// ============================================================================
-// $Log: not supported by cvs2svn $
-// Revision 1.4  2007/01/12 15:24:46  ranjard
-// v9r0 - use GAUDI v19r0
-//
-// Revision 1.3  2006/01/17 15:52:57  odescham
-// v8r0 - Adapt to new Event Model & LHCb v20 migration
-//
-// Revision 1.2  2004/01/14 13:38:10  ranjard
-// v6r0 - fix to be used with Gaudi v14r0
-//
-// Revision 1.1  2003/07/07 08:21:08  ibelyaev
-//  split the general CaloSensDet class
-//
-// ============================================================================
-#ifndef       GAUSSCALO_EHCalSensDet_H
-#define       GAUSSCALO_EHCalSensDet_H 1
-// ============================================================================
-// GaudiKernel
-/// Ntupel Svc
-#include "GaudiKernel/INTuple.h"
-#include "GaudiKernel/INTupleSvc.h"
-#include "GaudiKernel/NTuple.h"
-/// GiGa
-#include "GiGa/GiGaSensDetBase.h"
-/// local
-#include "CaloSim.h"
-#include "CaloHit.h"
-#include "CaloSubHit.h"
-#include "CaloSensDet.h"
-/// forward declarations
-class DeCalorimeter ;
-
-/** @class EHCalSensDet EHCalSensDet.h
- *
- *  The common base class fro Ecal/Hcal sensitive detectors.
- *  It includes the common timing treatment.
- *
- *  @author  Vanya Belyaev Ivan.Belyaev@itep.ru
- *  @author  Patrick Robbe robbe@lal.in2p3.fr
- *
- *  @date    23/01/2001
- */
-
-class EHCalSensDet: public CaloSensDet
-{
-public:
-
-  /** standard constructor
-   *  @see CaloSensDet
-   *  @see GiGaSensDetBase
-   *  @see GiGaBase
-   *  @see AlgTool
-   *  @param type type of the object (?)
-   *  @param name name of the object
-   *  @param parent  pointer to parent object
-   */
-  EHCalSensDet
-  ( const std::string& type   ,
-    const std::string& name   ,
-    const IInterface*  parent ) ;
-
-  /// destructor (virtual and protected)
-  virtual ~EHCalSensDet() {};
-
-private:
-
-  // no default constructor
-  EHCalSensDet() ;
-  // no copy constructor
-  EHCalSensDet           ( const EHCalSensDet& );
-  // no assignement
-  EHCalSensDet& operator=( const EHCalSensDet& ) ;
-
-protected:
-
-  /** The fractions of energy deposited in consequitive time-bins
-   *  in the given Ecal/Hcal cell
-   *  @see CaloSensDet
-   *  @param time global time of energy deposition
-   *  @param cell cellID of the cell
-   *  @param slot (out) the first time bin
-   *  @param fracs (out) the vector of fractions for subsequent time-slots;
-   *  @return StatuscCode
-   */
-  StatusCode timing
-  ( const double            time      ,
-    const LHCb::CaloCellID&       cell      ,
-    CaloSubHit::Time&       slot      ,
-    CaloSensDet::Fractions& fractions ) const override;
-
-protected:
-
-  /// width of time-slot (25ns)
-  inline double slotWidth() const { return m_slotWidth ; }
-
-private:
-
-  /// width of time-slot (25ns)
-  double  m_slotWidth ;
-
-};
-// ============================================================================
-
-// ============================================================================
-// The END
-// ============================================================================
-#endif  ///< GAUSSCALO_EHCalSensDet_H
-// ============================================================================
diff --git a/Sim/GaussCalo/src/EcalSensDet.cpp b/Sim/GaussCalo/src/EcalSensDet.cpp
index 269473cf2..926d8048a 100755
--- a/Sim/GaussCalo/src/EcalSensDet.cpp
+++ b/Sim/GaussCalo/src/EcalSensDet.cpp
@@ -1,6 +1,3 @@
-// $Id: EcalSensDet.cpp,v 1.12 2008-07-11 10:47:44 robbep Exp $
-// Include files
-
 // SRD & STD
 #include <algorithm>
 #include <vector>
@@ -10,29 +7,20 @@
 #include "CLHEP/Units/PhysicalConstants.h"
 
 // GaudiKernel
+#include "GaudiKernel/IDataProviderSvc.h"
 #include "GaudiKernel/MsgStream.h"
 #include "GaudiKernel/SmartDataPtr.h"
-#include "GaudiKernel/IDataProviderSvc.h"
 
 // LHCb
 #include "LHCbMath/LHCbMath.h"
 
-// GaussTools
-#include "GaussTools/GaussTrackInformation.h"
-
 // Geant4
-#include "Geant4/G4Step.hh"
-#include "Geant4/G4TouchableHistory.hh"
-#include "Geant4/G4VPhysicalVolume.hh"
-#include "Geant4/G4LogicalVolume.hh"
-#include "Geant4/G4SDManager.hh"
-#include "Geant4/G4EnergyLossTables.hh"
-
-// GiGaCnv
-#include "GiGaCnv/GiGaVolumeUtils.h"
-
-// CaloDet
-#include "CaloDet/DeCalorimeter.h"
+//#include "Geant4/G4EnergyLossTables.hh"
+//#include "Geant4/G4LogicalVolume.hh"
+//#include "Geant4/G4SDManager.hh"
+//#include "Geant4/G4Step.hh"
+//#include "Geant4/G4TouchableHistory.hh"
+//#include "Geant4/G4VPhysicalVolume.hh"
 
 // local
 #include "CaloHit.h"
@@ -54,58 +42,6 @@
  */
 // ============================================================================
 
-// Declaration of the Tool Factory
-DECLARE_COMPONENT( EcalSensDet )
-
-// ============================================================================
-/** standard constructor
- *  @see GiGaSensDetBase
- *  @see GiGaBase
- *  @see AlgTool
- *  @param type type of the object (?)
- *  @param name name of the object
- *  @param parent  pointer to parent object
- */
-// ============================================================================
-EcalSensDet::EcalSensDet
-( const std::string& type   ,
-  const std::string& name   ,
-  const IInterface*  parent )
-  : G4VSensitiveDetector( name  )
-  , EHCalSensDet        ( type , name , parent )
-  //
-  //  , m_a_local_inner_ecal  ( 0.008 ) // local non uniformity amplitude
-  // inner ecal
-  //  , m_a_local_middle_ecal  ( 0.008 ) // local non uniformity amplitude
-  //  middle ecal
-  //  , m_a_local_outer_ecal   ( 0.03  ) // local non uniformity amplitude
-  // outer ecal
-  // For the moment put 0 for the local N.U.
-    , m_a_local_inner_ecal ( 0. )
-    , m_a_local_middle_ecal ( 0. )
-    , m_a_local_outer_ecal ( 0. )
-    , m_a_global_inner_ecal  ( 0.0004  ) // global non uniformity amplitude
-  //inner ecal
-    , m_a_global_middle_ecal ( 0.002  ) // global non uniformity amplitude
-  //  middle ecal
-    , m_a_global_outer_ecal  ( 0.03  ) // global non uniformity amplitude
-  // outer ecal
-    , m_a_reflection_height ( 0.09 ) // reflection on the edges - height
-    , m_a_reflection_width  ( 6. * CLHEP::mm ) // reflection on the edges - width
-{
-  ///
-  declareProperty ( "a_local_inner_ecal"   ,  m_a_local_inner_ecal ) ;
-  declareProperty ( "a_local_middle_ecal"  ,  m_a_local_middle_ecal ) ;
-  declareProperty ( "a_local_outer_ecal"   ,  m_a_local_outer_ecal ) ;
-  declareProperty ( "a_global_inner_ecal"   ,  m_a_global_inner_ecal ) ;
-  declareProperty ( "a_global_middle_ecal"  ,  m_a_global_middle_ecal ) ;
-  declareProperty ( "a_global_outer_ecal"   ,  m_a_global_outer_ecal ) ;
-  declareProperty ( "a_reflection_height"  , m_a_reflection_height ) ;
-  declareProperty ( "a_reflection_width"   , m_a_reflection_width  ) ;
-  //
-}
-
-
 // ============================================================================
 /** fill the hit with the concrete information about the energy and the time.
  *  The function is to be called from ProcessHits method.
@@ -125,60 +61,127 @@ EcalSensDet::EcalSensDet
  *
  */
 // ============================================================================
-StatusCode    EcalSensDet::fillHitInfo
-( CaloSubHit*                    hit           ,
-  const HepGeom::Point3D<double>& prePoint      ,
-  const double                   time ,
-  const double                   deposit       ,
-  const G4Track*                 track   ,
-  const G4ParticleDefinition*    particle   ,
-  const G4MaterialCutsCouple*    material   ,
-  const G4Step*                  step          ) const
-{
-
-  if( 0 == hit || 0 == step ) { return StatusCode::FAILURE ; }
+template <typename CELLGETTER>
+bool EcalSensDet<CELLGETTER>::fillHitInfo(
+    CaloSubHit* hit, const HepGeom::Point3D<double>& prePoint,
+    const double time, const double deposit, const G4Track* track,
+    const G4ParticleDefinition* particle, const G4MaterialCutsCouple* material,
+    const G4Step* step) const {
+  if (0 == hit || 0 == step) {
+    return false;
+  }
 
   // get the cell
-  const LHCb::CaloCellID& cellID = hit->cellID() ;
+  const LHCb::CaloCellID& cellID = hit->cellID();
 
   // Birk's Law Correction
-  double ecorrected = deposit *
-    birkCorrection( particle ,
-                    track->GetKineticEnergy() ,
-                    material ) ;
+  double ecorrected =
+      deposit *
+      this->birkCorrection(particle, track->GetKineticEnergy(), material);
 
-  //Local NonUniformity
+  // Local NonUniformity
   // if the cell is not valid do not apply the correction
   // (Anyway it will not be used)
-  //if ( calo() -> valid ( cellID ) ) {
-  ecorrected *= localNonUniformity( prePoint , cellID ) ;
+  // if ( calo() -> valid ( cellID ) ) {
+  ecorrected *= localNonUniformity(prePoint, cellID);
   //}
 
   // Timing
   // Uses method in EHCalSensDet
-  CaloSubHit::Time slot = 0   ;
-  Fractions fractions ;
-  StatusCode sc = timing( time , cellID , slot , fractions ) ;
+  CaloSubHit::Time slot = 0;
+  typename base_class::Fractions fractions;
+  bool sc = timing(time, cellID, slot, fractions);
 
-  if ( sc.isFailure() ) {
-    return Error( "Error in timing()" , sc ) ;
+  if (!sc) {
+    this->error("Error in timing()");
+    return false;
   }
 
-  if ( fractions.empty() ) {
-    Warning("The vector of fractions of energy is empty.") ;
+  if (fractions.empty()) {
+    this->warning("The vector of fractions of energy is empty.");
   }
 
-  for ( Fractions::const_iterator ifr = fractions.begin() ;
-        fractions.end() != ifr ; ++ifr ) {
-    const double fr = *ifr ;
-    if ( fr > 1.e-5 ) hit->add( slot , ecorrected * fr ) ;
-    slot++ ;
+  for (double fr : fractions) {
+    if (fr > 1.e-5) hit->add(slot, ecorrected * fr);
+    slot++;
   }
 
-  return StatusCode::SUCCESS ;
+  return true;
 }
 
+//=============================================================================
+// The fractions of energy deposited in consequitive time-slots
+// in the given Ecal/Hcal cell
+//=============================================================================
+template <typename CELLGETTER>
+bool EcalSensDet<CELLGETTER>::timing(
+    const double time, const LHCb::CaloCellID& cell, CaloSubHit::Time& slot,
+    typename base_class::Fractions& fractions) const {
+  // clear input data
+  slot = 0;
+  fractions.clear();
+
+  // evaluate the real delta time
+  const double deltaT = time - this->t0(cell);
+
+  // find the absolute time slot
+  slot = (CaloSubHit::Time)floor(deltaT / m_slotWidth);
+
+  // the time into the slot
+  const double dt = deltaT - slot * m_slotWidth;
+
+  for (auto histo : this->histos()) {
+    const int bin = histo->coordToIndex(dt / CLHEP::ns);
+    const double frac = histo->binHeight(bin);
+    fractions.push_back(frac);
+  };
+
+  if (fractions.empty()) {
+    this->warning("timing()::no time information is available!");
+  }
 
-// ============================================================================
-// The END
-// ============================================================================
+  return true;
+}
+
+#include "CaloSensDetFAC.h"
+
+template <typename CELLGETTER>
+class EcalSensDetFAC : public CaloSensDetFAC<EcalSensDet<CELLGETTER>> {
+  Gaudi::Property<double> m_a_local_inner_ecal{this, "a_local_inner_ecal", 0.};
+  Gaudi::Property<double> m_a_local_middle_ecal{this, "a_local_middle_ecal",
+                                                0.};
+  Gaudi::Property<double> m_a_local_outer_ecal{this, "a_local_outer_ecal", 0.};
+  Gaudi::Property<double> m_a_global_inner_ecal{this, "a_global_inner_ecal",
+                                                0.0004};
+  Gaudi::Property<double> m_a_global_middle_ecal{this, "a_global_middle_ecal",
+                                                 0.002};
+  Gaudi::Property<double> m_a_global_outer_ecal{this, "a_global_outer_ecal",
+                                                0.03};
+  Gaudi::Property<double> m_a_reflection_height{this, "a_reflection_height",
+                                                0.09};
+  Gaudi::Property<double> m_a_reflection_width{this, "a_reflection_width",
+                                               6. * CLHEP::mm};
+  Gaudi::Property<double> m_slotWidth{this, "SlotWidth", 25 * CLHEP::ns};
+
+  public:
+  using calotype = EcalSensDet<CELLGETTER>;
+  using base = CaloSensDetFAC<calotype>;
+  using typename base::CaloSensDetFAC;
+  virtual calotype* construct() const override {
+    auto tmp = base::construct();
+    tmp->m_a_local_inner_ecal = m_a_local_inner_ecal;
+    tmp->m_a_local_middle_ecal = m_a_local_middle_ecal;
+    tmp->m_a_local_outer_ecal = m_a_local_outer_ecal;
+    tmp->m_a_global_inner_ecal = m_a_global_inner_ecal;
+    tmp->m_a_global_middle_ecal = m_a_global_middle_ecal;
+    tmp->m_a_global_outer_ecal = m_a_global_outer_ecal;
+    tmp->m_a_reflection_height = m_a_reflection_height;
+    tmp->m_a_reflection_width = m_a_reflection_width;
+    tmp->m_slotWidth = m_slotWidth;
+    return tmp;
+  }
+};
+
+// Declaration of the Tool Factory
+typedef EcalSensDetFAC<CellFromLHCbGeo> EcalSensDetLHCbGeoFAC;
+DECLARE_COMPONENT_WITH_ID(EcalSensDetLHCbGeoFAC, "EcalSensDet")
diff --git a/Sim/GaussCalo/src/EcalSensDet.h b/Sim/GaussCalo/src/EcalSensDet.h
index 3045c98f3..faf834ae8 100755
--- a/Sim/GaussCalo/src/EcalSensDet.h
+++ b/Sim/GaussCalo/src/EcalSensDet.h
@@ -1,23 +1,17 @@
-// $Id: EcalSensDet.h,v 1.11 2008-05-30 13:51:07 gcorti Exp $
-#ifndef       GAUSSCALO_EcalSensDet_H
-#define       GAUSSCALO_EcalSensDet_H 1
+#pragma once
 
 // Ntuple Svc
 #include "GaudiKernel/INTuple.h"
 #include "GaudiKernel/INTupleSvc.h"
 #include "GaudiKernel/NTuple.h"
+#include "LHCbMath/LHCbMath.h"
 
 // GiGa
-#include "GiGa/GiGaSensDetBase.h"
+#include "CaloSensDet.h"
 
 // local
-#include "CaloSim.h"
 #include "CaloHit.h"
-#include "EHCalSensDet.h"
-/// forward declarations
-//template <class SD> class GiGaSensDetFactory;
-
-class DeCalorimeter ;
+#include "CaloSim.h"
 
 /** @class EcalSensDet EcalSensDet.h
  *
@@ -28,13 +22,13 @@ class DeCalorimeter ;
  *  @date    23/01/2001
  */
 
-class EcalSensDet: public EHCalSensDet
-{
-  /// friend factory
-  //  friend class GiGaFactory<EcalSensDet>;
-
-protected:
+template <typename CELLGETTER>
+class EcalSensDet : public CaloSensDet<CELLGETTER> {
+  public:
+  using base_class = CaloSensDet<CELLGETTER>;
+  using base_class::CaloSensDet;
 
+  protected:
   /** fill the hit with the concrete information about the energy and the time.
    *  The function is to be called from ProcessHits method.
    *
@@ -53,73 +47,52 @@ protected:
    *                    etc for efficiency reasons.
    *
    */
-  StatusCode    fillHitInfo
-  ( CaloSubHit*                 hit         ,
-    const HepGeom::Point3D<double>& prePoint    ,
-    const double                globalTime  ,
-    const double                deposit     ,
-    const G4Track*              track       ,
-    const G4ParticleDefinition* pdef        ,
-    const G4MaterialCutsCouple* material    ,
-    const G4Step*               step        ) const override;
-
-public:
-
-  /** standard constructor
+  bool fillHitInfo(CaloSubHit* hit, const HepGeom::Point3D<double>& prePoint,
+                   const double globalTime, const double deposit,
+                   const G4Track* track, const G4ParticleDefinition* pdef,
+                   const G4MaterialCutsCouple* material,
+                   const G4Step* step) const override;
+
+  /** The fractions of energy deposited in consequitive time-bins
+   *  in the given Ecal/Hcal cell
    *  @see CaloSensDet
-   *  @see GiGaSensDetBase
-   *  @see GiGaBase
-   *  @see AlgTool
-   *  @param type type of the object (?)
-   *  @param name name of the object
-   *  @param parent  pointer to parent object
+   *  @param time global time of energy deposition
+   *  @param cell cellID of the cell
+   *  @param slot (out) the first time bin
+   *  @param fracs (out) the vector of fractions for subsequent time-slots;
+   *  @return StatuscCode
    */
-  EcalSensDet
-  ( const std::string& type   ,
-    const std::string& name   ,
-    const IInterface*  parent ) ;
-
-  /// destructor (virtual and protected)
-  virtual ~EcalSensDet() {};
-
-private:
-
-  // no default constructor
-  EcalSensDet() ;
-  // no copy constructor
-  EcalSensDet           ( const EcalSensDet& );
-  // no assignement
-  EcalSensDet& operator=( const EcalSensDet& ) ;
-
-protected:
+  bool timing(
+      const double time, const LHCb::CaloCellID& cell, CaloSubHit::Time& slot,
+      typename CaloSensDet<CELLGETTER>::Fractions& fractions) const override;
 
+  protected:
   /** Correction due to the local non uniformity due to the light
    *  collection efficiency in cell cell
    */
-  inline double localNonUniformity
-  ( const HepGeom::Point3D<double>& prePoint    ,
-    const LHCb::CaloCellID& cell    ) const ;
+  inline double localNonUniformity(const HepGeom::Point3D<double>& prePoint,
+                                   const LHCb::CaloCellID& cell) const;
 
-private :
+  public:
   // Amplitudes of the local non uniformity correction
   // depending on the region of the Ecal
-  double                                      m_a_local_inner_ecal  ;
-  double                                      m_a_local_middle_ecal ;
-  double                                      m_a_local_outer_ecal  ;
+  double m_a_local_inner_ecal{0.};
+  double m_a_local_middle_ecal{0.};
+  double m_a_local_outer_ecal{0.};
   // Amplitudes of the global non uniformity correction
   // depending on the region of the Ecal
-  double                                      m_a_global_inner_ecal  ;
-  double                                      m_a_global_middle_ecal ;
-  double                                      m_a_global_outer_ecal  ;
+  double m_a_global_inner_ecal{0.0004};
+  double m_a_global_middle_ecal{0.002};
+  double m_a_global_outer_ecal{0.03};
   // Correction for light reflection at the edges
-  double                                      m_a_reflection_height ;
-  double                                      m_a_reflection_width  ;
+  double m_a_reflection_height{0.09};
+  double m_a_reflection_width{6. * CLHEP::mm};
+
+  /// width of time-slot (25ns)
+  double m_slotWidth{25 * CLHEP::ns};
 };
 // ============================================================================
 
-
-
-
 // ============================================================================
 // Local Non Uniformity
 // ============================================================================
@@ -127,77 +100,68 @@ private :
  *  collection efficiency in cell cell
  */
 
-inline double EcalSensDet::localNonUniformity
-( const HepGeom::Point3D<double>& prePoint ,
-  const LHCb::CaloCellID& cell ) const
-{
-
+template <typename CELLGETTER>
+inline double EcalSensDet<CELLGETTER>::localNonUniformity(
+    const HepGeom::Point3D<double>& prePoint,
+    const LHCb::CaloCellID& cell) const {
   // Only for ECal for the moment
-  double correction = 1. ;
+  double correction = 1.;
 
   // Find the position of the step
-  double x        = prePoint.x() ;
-  double y        = prePoint.y() ;
+  double x = prePoint.x();
+  double y = prePoint.y();
   // Center of the cell
-  double x0       = calo()->cellX( cell ) ;
-  double y0       = calo()->cellY( cell ) ;
+  double x0 = this->cellX(cell);
+  double y0 = this->cellY(cell);
 
   // Distance between fibers
   // and correction amplitude
-  double d        = 10.1 * CLHEP::mm ;
-  double A_local  = m_a_local_inner_ecal ; // in inner Ecal
-  double A_global = m_a_global_inner_ecal ;
+  double d = 10.1 * CLHEP::mm;
+  double A_local = m_a_local_inner_ecal;  // in inner Ecal
+  double A_global = m_a_global_inner_ecal;
 
   // Cell size
-  double cellSize = calo()->cellSize( cell ) ;
+  double cellSize = this->cellSize(cell);
 
   // Assign amplitude of non uniformity as a function of the
   // Ecal region
 
-  if ( cell.area() == 0 ) { // outer Ecal
-    A_local  = m_a_local_outer_ecal ;
-    A_global = m_a_global_outer_ecal ;
-    d        = 15.25 * CLHEP::mm ;
-  }
-  else if ( cell.area() == 1 ) { // middle Ecal
-    A_local  = m_a_local_middle_ecal ;
-    A_global = m_a_global_middle_ecal ;
+  if (cell.area() == 0) {  // outer Ecal
+    A_local = m_a_local_outer_ecal;
+    A_global = m_a_global_outer_ecal;
+    d = 15.25 * CLHEP::mm;
+  } else if (cell.area() == 1) {  // middle Ecal
+    A_local = m_a_local_middle_ecal;
+    A_global = m_a_global_middle_ecal;
   }
 
   // Local uniformity is product of x and y sine-like functions
   // The Amplitude of the sin-like function is a function of x and
   // y
-  if ( A_local > LHCb::Math::lowTolerance )
-    correction += A_local / 2. * ( 1. - cos( 2. * CLHEP::pi * (x-x0)/d ) ) *
-      ( 1. - cos( 2. * CLHEP::pi * (y-y0)/d ) ) ;
+  if (A_local > LHCb::Math::lowTolerance)
+    correction += A_local / 2. * (1. - cos(2. * CLHEP::pi * (x - x0) / d)) *
+                  (1. - cos(2. * CLHEP::pi * (y - y0) / d));
 
-  double rX(0.) , rY(0.) , hCell(0.) ;
+  double rX(0.), rY(0.), hCell(0.);
 
   // Global non uniformity
-  if ( A_global > LHCb::Math::lowTolerance ) {
-    rX = x - x0 ;
-    rY = y - y0 ;
-    hCell = cellSize / 2. ;
-    correction +=
-      A_global * ( hCell - rX ) * ( rX + hCell ) / ( hCell * hCell )
-      * ( hCell - rY ) * ( rY + hCell ) / ( hCell * hCell ) ;
+  if (A_global > LHCb::Math::lowTolerance) {
+    rX = x - x0;
+    rY = y - y0;
+    hCell = cellSize / 2.;
+    correction += A_global * (hCell - rX) * (rX + hCell) / (hCell * hCell) *
+                  (hCell - rY) * (rY + hCell) / (hCell * hCell);
   }
 
   // Light Reflexion on the edges
-  if ( m_a_reflection_height > LHCb::Math::lowTolerance ) {
-    rX = rX / m_a_reflection_width ;
-    rY = rY / m_a_reflection_width ;
-    hCell = hCell / m_a_reflection_width ;
+  if (m_a_reflection_height > LHCb::Math::lowTolerance) {
+    rX = rX / m_a_reflection_width;
+    rY = rY / m_a_reflection_width;
+    hCell = hCell / m_a_reflection_width;
     correction += m_a_reflection_height *
-      ( exp( - fabs ( rX + hCell ) ) + exp( - fabs ( rX - hCell ) )
-        + exp( - fabs ( rY + hCell ) ) + exp( - fabs ( rY - hCell ) ) ) ;
+                  (exp(-fabs(rX + hCell)) + exp(-fabs(rX - hCell)) +
+                   exp(-fabs(rY + hCell)) + exp(-fabs(rY - hCell)));
   }
 
-  return correction ;
+  return correction;
 }
-
-// ============================================================================
-// The END
-// ============================================================================
-#endif  ///< GAUSSCALO_EcalSensDet_H
-// ============================================================================
diff --git a/Sim/GaussCalo/src/HcalSensDet.cpp b/Sim/GaussCalo/src/HcalSensDet.cpp
index 1371063b0..81f349294 100755
--- a/Sim/GaussCalo/src/HcalSensDet.cpp
+++ b/Sim/GaussCalo/src/HcalSensDet.cpp
@@ -9,27 +9,13 @@
 #include "CLHEP/Units/PhysicalConstants.h"
 
 // from Gaudi
+#include "GaudiKernel/IDataProviderSvc.h"
 #include "GaudiKernel/MsgStream.h"
 #include "GaudiKernel/SmartDataPtr.h"
-#include "GaudiKernel/IDataProviderSvc.h"
 
 // LHCb
 #include "LHCbMath/LHCbMath.h"
 
-// Gauss
-#include "GaussTools/GaussTrackInformation.h"
-
-// Geant4
-#include "Geant4/G4Step.hh"
-#include "Geant4/G4TouchableHistory.hh"
-#include "Geant4/G4VPhysicalVolume.hh"
-#include "Geant4/G4LogicalVolume.hh"
-#include "Geant4/G4SDManager.hh"
-#include "Geant4/G4EnergyLossTables.hh"
-
-// GiGaCnv
-#include "GiGaCnv/GiGaVolumeUtils.h"
-
 // CaloDet
 #include "CaloDet/DeCalorimeter.h"
 
@@ -52,27 +38,6 @@
  */
 // ============================================================================
 
-// Declaration of the Tool Factory
-DECLARE_COMPONENT( HcalSensDet )
-
-// ============================================================================
-/** standard constructor
- *  @see GiGaSensDetBase
- *  @see GiGaBase
- *  @see AlgTool
- *  @param type type of the object (?)
- *  @param name name of the object
- *  @param parent  pointer to parent object
- */
-// ============================================================================
-HcalSensDet::HcalSensDet
-( const std::string& type   ,
-  const std::string& name   ,
-  const IInterface*  parent )
-  : G4VSensitiveDetector( name  )
-  , EHCalSensDet        ( type , name , parent )
-{}
-
 // ============================================================================
 /** fill the hit with the concrete information about the energy and the time.
  *  The function is to be called from ProcessHits method.
@@ -92,49 +57,98 @@ HcalSensDet::HcalSensDet
  *
  */
 // ============================================================================
-StatusCode    HcalSensDet::fillHitInfo
-( CaloSubHit*                    hit           ,
-  const HepGeom::Point3D<double>& /* prePoint */   ,
-  const double                   time          ,
-  const double                   deposit       ,
-  const G4Track*                 track         ,
-  const G4ParticleDefinition*    particle      ,
-  const G4MaterialCutsCouple*    material      ,
-  const G4Step*                  step          ) const
-{
-
-  if( 0 == hit || 0 == step ) { return StatusCode::FAILURE ; }
+template <typename CELLGETTER>
+bool HcalSensDet<CELLGETTER>::fillHitInfo(
+    CaloSubHit* hit, const HepGeom::Point3D<double>& /* prePoint */,
+    const double time, const double deposit, const G4Track* track,
+    const G4ParticleDefinition* particle, const G4MaterialCutsCouple* material,
+    const G4Step* step) const {
+  if (0 == hit || 0 == step) {
+    return false;
+  }
 
   // Birk's Law Correction
-  const double energy = deposit *
-    birkCorrection ( particle                   ,
-                     track->GetKineticEnergy () ,
-                     material                   ) ;
+  const double energy =
+      deposit *
+      this->birkCorrection(particle, track->GetKineticEnergy(), material);
 
   // get the cell
-  const LHCb::CaloCellID& cellID = hit->cellID() ;
+  const LHCb::CaloCellID& cellID = hit->cellID();
 
   // add current energy deposition to the sub-hit
-  CaloSubHit::Time slot = 0   ;
+  CaloSubHit::Time slot = 0;
+
+  typename base_class::Fractions fractions;
+  bool sc = timing(time, cellID, slot, fractions);
+
+  if (!sc) {
+    this->error("Error from timing()");
+    return false;
+  }
+  if (fractions.empty()) {
+    this->warning("The empty vector of fractions()");
+  }
+
+  for (auto fr : fractions) {
+    if (fr > 1.e-5) {
+      hit->add(slot, energy * fr);
+    }
+  }
 
-  Fractions  fractions ;
-  StatusCode sc = timing ( time , cellID , slot , fractions ) ;
+  return true;
+}
 
-  if ( sc.isFailure()    ) { return Error ( "Error from timing()" , sc ) ; }
-  if ( fractions.empty() )
-    { Warning("The empty vector of fractions()"); }
+//=============================================================================
+// The fractions of energy deposited in consequitive time-slots
+// in the given Ecal/Hcal cell
+//=============================================================================
+template <typename CELLGETTER>
+bool HcalSensDet<CELLGETTER>::timing(
+    const double time, const LHCb::CaloCellID& cell, CaloSubHit::Time& slot,
+    typename base_class::Fractions& fractions) const {
+  // clear input data
+  slot = 0;
+  fractions.clear();
+
+  // evaluate the real delta time
+  const double deltaT = time - this->t0(cell);
+
+  // find the absolute time slot
+  slot = (CaloSubHit::Time)floor(deltaT / m_slotWidth);
+
+  // the time into the slot
+  const double dt = deltaT - slot * m_slotWidth;
+
+  for (auto histo : this->histos()) {
+    const int bin = histo->coordToIndex(dt / CLHEP::ns);
+    const double frac = histo->binHeight(bin);
+    fractions.push_back(frac);
+  };
+
+  if (fractions.empty()) {
+    this->warning("timing()::no time information is available!");
+  }
+
+  return true;
+}
 
-  for( Fractions::const_iterator ifr = fractions.begin() ;
-       fractions.end() != ifr ; ++ifr , ++slot )
-    {
-      const double fr = *ifr ;
-      if( fr > 1.e-5 ) { hit->add( slot , energy * fr ) ; }
-    }
+#include "CaloSensDetFAC.h"
 
-  return StatusCode::SUCCESS ;
-}
+template <typename CELLGETTER>
+class HcalSensDetFAC : public CaloSensDetFAC<HcalSensDet<CELLGETTER>> {
+  Gaudi::Property<double> m_slotWidth{this, "SlotWidth", 25 * CLHEP::ns};
 
+  public:
+  using calotype = HcalSensDet<CELLGETTER>;
+  using base = CaloSensDetFAC<calotype>;
+  using typename base::CaloSensDetFAC;
+  virtual calotype* construct() const override {
+    auto tmp = base::construct();
+    tmp->m_slotWidth = m_slotWidth;
+    return tmp;
+  }
+};
 
-// ============================================================================
-// The END
-// ============================================================================
+// Declaration of the Tool Factory
+typedef HcalSensDetFAC<CellFromLHCbGeo> HcalSensDetLHCbGeoFAC;
+DECLARE_COMPONENT_WITH_ID(HcalSensDetLHCbGeoFAC, "HcalSensDet")
diff --git a/Sim/GaussCalo/src/HcalSensDet.h b/Sim/GaussCalo/src/HcalSensDet.h
index 23234a7ce..bf74ae96d 100755
--- a/Sim/GaussCalo/src/HcalSensDet.h
+++ b/Sim/GaussCalo/src/HcalSensDet.h
@@ -1,20 +1,14 @@
-// $Id: HcalSensDet.h,v 1.4 2007-01-12 15:24:49 ranjard Exp $
-#ifndef       GAUSSCALO_HcalSensDet_H
-#define       GAUSSCALO_HcalSensDet_H 1
+#pragma once
 
 // GaudiKernel
 /// Ntupel Svc
 #include "GaudiKernel/INTuple.h"
 #include "GaudiKernel/INTupleSvc.h"
 #include "GaudiKernel/NTuple.h"
-/// GiGa
-#include "GiGa/GiGaSensDetBase.h"
 /// local
-#include "CaloSim.h"
 #include "CaloHit.h"
-#include "EHCalSensDet.h"
-
-class DeCalorimeter ;
+#include "CaloSensDet.h"
+#include "CaloSim.h"
 
 /** @class HcalSensDet HcalSensDet.h
  *
@@ -25,11 +19,13 @@ class DeCalorimeter ;
  *  @date    23/01/2001
  */
 
-class HcalSensDet: public EHCalSensDet
-{
-
-protected:
+template <typename CELLGETTER>
+class HcalSensDet : public CaloSensDet<CELLGETTER> {
+  public:
+  using base_class = CaloSensDet<CELLGETTER>;
+  using base_class::CaloSensDet;
 
+  protected:
   /** fill the hit with the concrete information about the energy and the time.
    *  The function is to be called from ProcessHits method.
    *
@@ -48,43 +44,26 @@ protected:
    *                    etc for efficiency reasons.
    *
    */
-  StatusCode    fillHitInfo
-  ( CaloSubHit*                 hit         ,
-    const HepGeom::Point3D<double>& prePoint    ,
-    const double                globalTime  ,
-    const double                deposit     ,
-    const G4Track*              track       ,
-    const G4ParticleDefinition* pdef        ,
-    const G4MaterialCutsCouple* material    ,
-    const G4Step*               step        ) const override;
+  bool fillHitInfo(CaloSubHit* hit, const HepGeom::Point3D<double>& prePoint,
+                   const double globalTime, const double deposit,
+                   const G4Track* track, const G4ParticleDefinition* pdef,
+                   const G4MaterialCutsCouple* material,
+                   const G4Step* step) const override;
 
-public:
-
-  /** standard constructor
+  /** The fractions of energy deposited in consequitive time-bins
+   *  in the given Ecal/Hcal cell
    *  @see CaloSensDet
-   *  @see GiGaSensDetBase
-   *  @see GiGaBase
-   *  @see AlgTool
-   *  @param type type of the object (?)
-   *  @param name name of the object
-   *  @param parent  pointer to parent object
+   *  @param time global time of energy deposition
+   *  @param cell cellID of the cell
+   *  @param slot (out) the first time bin
+   *  @param fracs (out) the vector of fractions for subsequent time-slots;
+   *  @return StatuscCode
    */
-  HcalSensDet
-  ( const std::string& type   ,
-    const std::string& name   ,
-    const IInterface*  parent ) ;
-
-  /// destructor (virtual and protected)
-  virtual ~HcalSensDet() {};
-
-private:
-
-  // no default constructor
-  HcalSensDet() ;
-  // no copy constructor
-  HcalSensDet           ( const HcalSensDet& );
-  // no assignement
-  HcalSensDet& operator=( const HcalSensDet& ) ;
+  bool timing(
+      const double time, const LHCb::CaloCellID& cell, CaloSubHit::Time& slot,
+      typename CaloSensDet<CELLGETTER>::Fractions& fractions) const override;
 
+  public:
+  /// width of time-slot (25ns)
+  double m_slotWidth{25 * CLHEP::ns};
 };
-#endif  ///< GAUSSCALO_HcalSensDet_H
-- 
GitLab


From e520b0d891d1a0e48619e4780641c3c18c481a09 Mon Sep 17 00:00:00 2001
From: Dominik Muller <dominik.muller@cern.ch>
Date: Tue, 6 Aug 2019 16:59:03 +0200
Subject: [PATCH 20/90] Added service for region definitions

---
 .../python/Gauss/Geometry/Configuration.py    |  19 ++-
 Sim/GaussCalo/src/CaloHit.cpp                 |   3 +
 Sim/GaussCalo/src/CaloSubHit.cpp              |   3 +
 Sim/GaussGeo/src/component/GaussGeo.cpp       |   7 ++
 Sim/GaussPhysics/CMakeLists.txt               |   3 +-
 Sim/SimSvc/CMakeLists.txt                     |  11 +-
 Sim/SimSvc/SimSvc/ISimulationSvc.h            |  87 -------------
 Sim/SimSvc/SimSvc/RegionCuts.h                | 104 ----------------
 Sim/SimSvc/SimSvc/SimAttribute.h              |  90 --------------
 Sim/SimSvc/doc/release.notes                  | 114 ------------------
 ...lationSvc.cpp => RegionsDefinitionSvc.cpp} |  78 +++---------
 ...SimulationSvc.h => RegionsDefinitionSvc.h} |  41 ++-----
 12 files changed, 66 insertions(+), 494 deletions(-)
 create mode 100644 Sim/GaussCalo/src/CaloHit.cpp
 create mode 100644 Sim/GaussCalo/src/CaloSubHit.cpp
 delete mode 100755 Sim/SimSvc/SimSvc/ISimulationSvc.h
 delete mode 100755 Sim/SimSvc/SimSvc/RegionCuts.h
 delete mode 100755 Sim/SimSvc/SimSvc/SimAttribute.h
 delete mode 100755 Sim/SimSvc/doc/release.notes
 rename Sim/SimSvc/src/{SimulationSvc.cpp => RegionsDefinitionSvc.cpp} (87%)
 rename Sim/SimSvc/src/{SimulationSvc.h => RegionsDefinitionSvc.h} (72%)

diff --git a/Sim/Gauss/python/Gauss/Geometry/Configuration.py b/Sim/Gauss/python/Gauss/Geometry/Configuration.py
index d40715e25..aafcf5d91 100644
--- a/Sim/Gauss/python/Gauss/Geometry/Configuration.py
+++ b/Sim/Gauss/python/Gauss/Geometry/Configuration.py
@@ -1,6 +1,5 @@
 from Gaudi.Configuration import log
 from Configurables import LHCbConfigurableUser
-from GaudiKernel import SystemOfUnits
 from Gaudi.Configuration import Configurable
 from Gauss.Geometry.Helpers import checkIncompatibleDetectors
 from Gauss.Geometry.Helpers import defineGeoBasePieces
@@ -181,6 +180,24 @@ class LHCbGeo(LHCbConfigurableUser):
                                "GiGaMTProxyDetectorConstructionFAC")
         dettool.GiGaMTGeoSvc = "GaussGeo"
 
+        # Now add the tools automatically set up after the construction
+        # of the geometry to configure the regions
+        dettool.AfterGeoConstructionTools = [
+            'GiGaSetSimAttributes',
+            'GiGaRegionsTool']
+        from Configurables import GiGaSetSimAttributes
+        dettool.addTool(GiGaSetSimAttributes(), name="GiGaSetSimAttributes")
+        dettool.GiGaSetSimAttributes.OutputLevel = 4
+        from Configurables import GiGaRegionsTool
+        dettool.addTool(GiGaRegionsTool(), name="GiGaRegionsTool")
+        dettool.GiGaRegionsTool.OutputLevel = 4
+        # FIXME: This is all just temporary, especially the provided xml is only
+        # for Run1+2 MC
+        from Configurables import RegionsDefinitionSvc
+        svc = RegionsDefinitionSvc()
+        xmlfile = "$GAUSSROOT/xml/SimulationRICHAerogelOff.xml"
+        svc.RegionsDefinitionDbLocation = xmlfile
+
     def PrintDebugDump(self, detPieces, basePieces):
         if self.getProp("Debug"):
             print "\nDEBUG Detector Geometry Elements:"
diff --git a/Sim/GaussCalo/src/CaloHit.cpp b/Sim/GaussCalo/src/CaloHit.cpp
new file mode 100644
index 000000000..0ea235047
--- /dev/null
+++ b/Sim/GaussCalo/src/CaloHit.cpp
@@ -0,0 +1,3 @@
+#include "CaloHit.h"
+
+G4ThreadLocal G4Allocator<CaloHit>* aCaloHitAllocator{nullptr};
diff --git a/Sim/GaussCalo/src/CaloSubHit.cpp b/Sim/GaussCalo/src/CaloSubHit.cpp
new file mode 100644
index 000000000..db3b4f4eb
--- /dev/null
+++ b/Sim/GaussCalo/src/CaloSubHit.cpp
@@ -0,0 +1,3 @@
+#include "CaloSubHit.h"
+
+G4ThreadLocal G4Allocator<CaloSubHit>* aCaloSubHitAllocator{nullptr};
diff --git a/Sim/GaussGeo/src/component/GaussGeo.cpp b/Sim/GaussGeo/src/component/GaussGeo.cpp
index 665185fe3..2ec47a08f 100644
--- a/Sim/GaussGeo/src/component/GaussGeo.cpp
+++ b/Sim/GaussGeo/src/component/GaussGeo.cpp
@@ -1522,6 +1522,10 @@ G4LogicalVolume* GaussGeo::createG4LVolume(G4VSolid* g4_solid, G4Material* g4_ma
     prefixOut();
   }
 
+  debug() << "Created G4LogicalVolume: " << g4_lvolume->GetName() << endmsg;
+  if(!G4LogicalVolumeStore::GetInstance()->GetVolume(volume_name, true)){
+      error() << "Not in STORE!!!!!!!!!!!!!!!!!!!!!!!!!" << endmsg;
+  };
   return g4_lvolume;
 }
 
@@ -1694,6 +1698,9 @@ StatusCode GaussGeo::register_sensitive(const std::string& name, G4LogicalVolume
       mmap_sensdet_to_lvols[sensdet] = {};
     }
     mmap_sensdet_to_lvols[sensdet].insert(vol);
+    if(vol){
+      debug() << "Asked to use sens det " << name << " for " << vol->GetName() << "" << endmsg;
+    }
   }
   return StatusCode::SUCCESS;
 }
diff --git a/Sim/GaussPhysics/CMakeLists.txt b/Sim/GaussPhysics/CMakeLists.txt
index b56839c23..a122716ee 100644
--- a/Sim/GaussPhysics/CMakeLists.txt
+++ b/Sim/GaussPhysics/CMakeLists.txt
@@ -5,6 +5,7 @@ gaudi_subdir(GaussPhysics v11r1p1)
 
 gaudi_depends_on_subdirs(Sim/GiGaMTFactories
                          Sim/GiGaMT
+                         Sim/GiGaMTCore
                          LHCbG4PhysLists)
 
 add_definitions(-DG4MULTITHREADED)
@@ -25,4 +26,4 @@ gaudi_add_module(GaussParticlesPhysics
 gaudi_add_module(GaussCutPhysics
                  src/cuts/*.cpp
                  INCLUDE_DIRS GiGaMTFactories CLHEP Geant4
-                 LINK_LIBRARIES GaudiAlgLib CLHEP ${GEANT4_LIBS})
+                 LINK_LIBRARIES GaudiAlgLib CLHEP ${GEANT4_LIBS} GiGaMTCoreMessageLib)
diff --git a/Sim/SimSvc/CMakeLists.txt b/Sim/SimSvc/CMakeLists.txt
index 6acf555f6..f5a291ba1 100644
--- a/Sim/SimSvc/CMakeLists.txt
+++ b/Sim/SimSvc/CMakeLists.txt
@@ -3,7 +3,10 @@
 ################################################################################
 gaudi_subdir(SimSvc v6r0p1)
 
-gaudi_depends_on_subdirs(Det/DetDescCnv)
+gaudi_depends_on_subdirs(Det/DetDescCnv
+                         Sim/GiGaMTGeo
+                         Sim/GiGaMTCore
+                         Sim/GaussGeo)
 
 find_package(Boost)
 find_package(XercesC)
@@ -12,7 +15,5 @@ include_directories(SYSTEM ${Boost_INCLUDE_DIRS}
 
 gaudi_add_module(SimSvc
                  src/*.cpp
-                 LINK_LIBRARIES DetDescCnvLib)
-
-gaudi_install_headers(SimSvc)
-
+                 INCLUDE_DIRS GiGaMTRegions
+                 LINK_LIBRARIES GiGaMTCoreCutLib DetDescCnvLib) 
diff --git a/Sim/SimSvc/SimSvc/ISimulationSvc.h b/Sim/SimSvc/SimSvc/ISimulationSvc.h
deleted file mode 100755
index 7e67f0ba1..000000000
--- a/Sim/SimSvc/SimSvc/ISimulationSvc.h
+++ /dev/null
@@ -1,87 +0,0 @@
-// $ID:  $
-
-#ifndef SIMSVC_ISIMULATIONSVC_H
-#define SIMSVC_ISIMULATIONSVC_H
-
-// Include files
-#include "GaudiKernel/IInterface.h"
-
-#include "SimSvc/SimAttribute.h"
-#include "SimSvc/RegionCuts.h"
-#include <map>
-
-// Forward and external declarations
-class ILVolume;
-
-/// Declaration of the interface ID (interface id, major version, minor version)
-static const InterfaceID IID_ISimulationSvc(948, 1 , 0);
-
-
-/** @class ISimulationSvc ISimulationSvc.h SimDesc/ISimulationSvc.h
- *
- *  this interface defines a Simulation service that is able to answer
- *  many question concerning the simulation of the detector. It
- *  is able to associate simulation attributes to logical volumes.
- *  These describe the way these volumes should be simulated
- *
- *  @author Sebastien Ponce
- */
-
-class ISimulationSvc : virtual public IInterface {
-  
-public:
-
-  // typedefs used  
-  typedef std::map<int, const SimAttribute*> PartAttr;
-  typedef std::vector<RegionCuts> VectOfRegCuts;
-
-  /// Retrieve interface ID
-  static const InterfaceID& interfaceID() { return IID_ISimulationSvc; }
-
-  /**
-   * This method returns the simulation attribute associated to a given
-   * logical volume.
-   * @param vol the logical volume
-   * @return the simulation attribute that should be used to simulate
-   * this logical volume
-   */
-  virtual const PartAttr* simAttribute (const ILVolume* vol) const = 0;
-
-  /**
-   * This method returns the simulation attribute associated to a given
-   * logical volume.
-   * @param vol the logical volume
-   * @return the simulation attribute that should be used to simulate
-   * this logical volume
-   */
-  virtual const PartAttr* simAttribute (const std::string volname) const = 0;
-
-  /**
-   * This method tells whether a simulation attribute is associated to a given
-   * logical volume or not
-   * @param vol the logical volume
-   */
-  virtual bool hasSimAttribute (const ILVolume* vol) const = 0;
-
-  /**
-   * This method tells whether a simulation attribute is associated to a given
-   * logical volume or not
-   * @param vol the logical volume
-   */
-  virtual bool hasSimAttribute (const std::string volname) const = 0;
-
-  /**
-   * This method returns the pointer to the vector of region definitions.
-   * @param 
-   * @return std::vector<RegionCuts>
-   */
-  virtual const std::vector<RegionCuts>* regionsDefs () const = 0;
-
-  /**
-   * this method erases the current set of attributes and loads a new set
-   */
-  virtual void reload () = 0;
-
-};
-
-#endif // SIMSVC_ISIMULATIONSVC_H
diff --git a/Sim/SimSvc/SimSvc/RegionCuts.h b/Sim/SimSvc/SimSvc/RegionCuts.h
deleted file mode 100755
index f7986b0be..000000000
--- a/Sim/SimSvc/SimSvc/RegionCuts.h
+++ /dev/null
@@ -1,104 +0,0 @@
-// $Id: RegionCuts.h,v 1.3 2009-10-15 12:41:13 silviam Exp $
-#ifndef SIMSVC_REGIONCUTS_H 
-#define SIMSVC_REGIONCUTS_H 1
-
-// Include files
-#include <string>
-#include <vector>
-
-/** @class RegionCuts RegionCuts.h SimSvc/RegionCuts.h
- *  
- *
- *  @author Witold POKORSKI
- *  @date   2003-06-03
- */
-class RegionCuts {
-public:
-  /// Default constructor
-  RegionCuts( ):
-    m_regionName("unknown"),
-    m_volumes(),
-    m_gammacut(-1.0),
-    m_electroncut(-1.0),
-    m_positroncut(-1.0),
-    m_protoncut(-1.0),
-    m_aprotoncut(-1.0),
-    m_neutroncut(-1.0),
-    m_aneutroncut(-1.0)
-  {}; 
-  
-  /// Standard constructor
-  RegionCuts(std::string name,
-             std::vector<std::string> volumes,
-             double gammacut,
-             double electroncut,
-             double positroncut,
-             double protoncut,
-             double aprotoncut,
-             double neutroncut,
-             double aneutroncut):
-    m_regionName(name),
-    m_volumes(volumes),
-    m_gammacut(gammacut),
-    m_electroncut(electroncut),
-    m_positroncut(positroncut),
-    m_protoncut(protoncut),
-    m_aprotoncut(-aprotoncut),
-    m_neutroncut(neutroncut),
-    m_aneutroncut(aneutroncut)
-  {};
-  
-  const std::string& region() const 
-  {
-    return m_regionName;
-  }
-
-  const std::vector<std::string>& volumes() const
-  {
-    return m_volumes;
-  }
-  
-  double gammaCut() const
-  {
-    return m_gammacut;
-  }
-  double electronCut() const
-  {
-    return m_electroncut;
-  }
-  double positronCut() const
-  {
-    return m_positroncut;
-  }
-  double protonCut() const
-  {
-    return m_protoncut;
-  }
-  double antiProtonCut() const
-  {
-    return m_aprotoncut;
-  }
-  double neutronCut() const
-  {
-    return m_neutroncut;
-  }
-  double antiNeutronCut() const
-  {
-    return m_aneutroncut;
-  }
-  
-private:
-
-  std::string m_regionName;
-  std::vector<std::string> m_volumes;
-
-  double m_gammacut;
-  double m_electroncut;
-  double m_positroncut;
-  double m_protoncut;
-  double m_aprotoncut;
-  double m_neutroncut;
-  double m_aneutroncut;  
-
-};
-#endif // SIMSVC_REGIONCUTS_H
diff --git a/Sim/SimSvc/SimSvc/SimAttribute.h b/Sim/SimSvc/SimSvc/SimAttribute.h
deleted file mode 100755
index 7149b6936..000000000
--- a/Sim/SimSvc/SimSvc/SimAttribute.h
+++ /dev/null
@@ -1,90 +0,0 @@
-// $Id: SimAttribute.h,v 1.3 2009-10-15 12:41:20 silviam Exp $
-#ifndef SIMATTRIBUTE_H 
-#define SIMATTRIBUTE_H 1
-
-// Include files
-
-/** @class SimAttribute SimAttribute.h
- *  This encapsulated the definition of simulation attributes for
- *  a logical volume. Included attributes are :
- *     - the maximum number of steps
- *     - the maximum track length
- *     - the maximum time
- *     - the minimal kinetic energy
- *     - the minimal remaining range
- *
- *  @author Sebastien Ponce
- */
-class SimAttribute {
-
-public:
-  /// Default constructor
-  SimAttribute () :
-    m_maxAllowedStep(-1.0),
-    m_maxTrackLength(-1.0),
-    m_maxTime(-1.0),
-    m_minEkine(-1.0),
-    m_minRange(-1.0)
-  {};
-
-  /// Standard constructor
-  SimAttribute (double maxAllowedStep,
-                double maxTrackLength,
-                double maxTime,
-                double minEkine,
-                double minRange) :
-    m_maxAllowedStep(maxAllowedStep),
-    m_maxTrackLength(maxTrackLength),
-    m_maxTime(maxTime),
-    m_minEkine(minEkine),
-    m_minRange(minRange)
-  {};  
-
-  /**
-   * Get accessor to member m_maxAllowedStep
-   * @return the current value of m_maxAllowedStep
-   */
-  double maxAllowedStep () const {
-    return m_maxAllowedStep;
-  }
-
-  /**
-   * Get accessor to member m_maxTrackLength
-   * @return the current value of m_maxTrackLength
-   */
-  double maxTrackLength () const {
-    return m_maxTrackLength;
-  }
-
-  /**
-   * Get accessor to member m_maxTime
-   * @return the current value of m_maxTime
-   */
-  double maxTime () const {
-    return m_maxTime;
-  }
-
-  /**
-   * Get accessor to member m_minEkine
-   * @return the current value of m_minEkine
-   */
-  double minEkine () const {
-    return m_minEkine;
-  }
-
-  /**
-   * Get accessor to member m_minRange
-   * @return the current value of m_minRange
-   */
-  double minRange () const {
-    return m_minRange;
-  }
-
-private:
-  double m_maxAllowedStep;
-  double m_maxTrackLength;
-  double m_maxTime;
-  double m_minEkine;
-  double m_minRange;
-};
-#endif // SIMATTRIBUTE_H
diff --git a/Sim/SimSvc/doc/release.notes b/Sim/SimSvc/doc/release.notes
deleted file mode 100755
index 41905f21e..000000000
--- a/Sim/SimSvc/doc/release.notes
+++ /dev/null
@@ -1,114 +0,0 @@
-!-----------------------------------------------------------------------------
-! Package     : Sim/SimSvc
-! Responsible : Gloria Corti, originally Sebastien Ponce
-! Purpose     : description of simulation parameters associated to logical
-!               volumes
-!-----------------------------------------------------------------------------
-
-!========================== SimSvc v6r0p1 2015-01-16 =========================
-! 2014-11-20 - Gloria Corti
- - Fixes for warning with --pedantic
- 
-! 2014-11-19 - Marco Clemencic
- - Updated CMake configuration
-
-!=========================== SimSvc v6r0 2014-02-02 ==========================
-! 2013-12-20 - Marco Clemencic
- - Removed obsolete file (not working with Gaudi >= v25).
-
-!========================== SimSvc v5r2p1 2013-10-10 =========================
-! 2013-09-23 - Marco Clemencic
- - Added CMake configuration file.
-
-!=========================== SimSvc v5r2 2009-11-04 ==========================
-! 2009-10-15 - Silvia Miglioranzi
- - Fix compilation warnings on slc5 "type qualifiers ignored on function return 
-   type" in:
-   - ISimulationSvc.h
-   - RegionCuts.h
-   - SimAttribute.h
-   - SimulationSvc.cpp
-   - SimulationSvc.h
-
-!=========================== SimSvc v5r1 2007-02-08 ==========================
-! 2007-12-12 - Gloria Corti
- - Adapt to location of Simulation.xml in Gauss package for default file
-   . SimulationSvc.cpp
-
-!==================== SimSvc v5r0 2007-03-16 =================================
-! 2007-03-16 - Gloria Corti
- - Modified to follow the changes in LHCb v22r1 XmlTools
-   . SimulationSvc.cpp
-
-! 2007-01-12 - Gloria Corti
- - Use install area for includes for Gaudi v19r0
-   . requirements
- - Use Gaudi macros for factory declarations (Gaudi v19r0)
-   . SimSvc_load.cpp
-   . SimulationSvc.cpp
-
-!======================== SimSvc v4r2 ==================================
-! 2005-11-10 - Gloria CORTI
- - src/SimulationSvc.cpp
-   . From Sajan EASO - Fix usage of terms "Regions" and "Region" where 
-     there was a mismatch between the value and what found in the XML 
-   . Use msg instead of log (and endmsg)
-
-!======================== SimSvc v4r1 ==================================
-! 2004-08-27 - Florence RANJARD
- - SimulationSvc.cpp - fix for WIN32
-
-! 2004-08-02 - Gloria CORTI
- - SimulationSvc.{h,cpp}
-   . use InterfaceID instead of IID to adapt to Gaudi v16
-
-!======================== SimSvc v4r0 ==================================
-! 2003-12-10 - Florence RANJARD
- - SimSvc_dll.cpp - use LOAD_FACTORY_ENTRIES macro
-
-!============================ SimSvc v3r2 ============================
-! 2003-07-07 - Florence RANJARD
- - fix for gcc3.2 (S.Ponce)
-
-!========================== SimSvc v3r1 ===========================
-! 2003-07-04 - Florence Ranjard
- - Simulation.h - comment 2 lines introduced to compile on W2000 but create
-                  a segmentation faiult on Linux when finalizing SimSvc.
-
-! 2003-07-01 - Florence RANJARD
- - Simulation.cpp - adapt to Xerces 2.2
-
-!========================== SimSvc v3r0 ============================
-
-! 2003-04-04 - Witek Pokorski
- - major change, added handling of cuts per region
-
-! 2003-06-02 - Witek Pokorski
- - typedef Particles changed to a more suitable name
-
-!========================== SimSvc v2r0 =============================
-
-! 2003-05-05 - Witek Pokorski
- - major change in the code, the cuts can be now specified per volume
-   and per particle; the default cuts (applicable to "all other" particles)
-   should be specified with pdg=0
-
-!========================== SimSvc v1r1 =============================
-
-! 2003-04-16 - Sebastien Ponce
- - added const keywords on the accessors
-
-!========================== SimSvc v1r0 ==============================
-
-! 2003-02-18 - Florence Ranjard
- - replace all the patterns used with the component_library one.
-
-! 2003-01-30 - Witek Pokorski
- - Added methods simAttribute and hasSimAttribute with name of the logical
-   volume as argument
-
-! 2003-01-29 - Sebastien Ponce
- - Added method hasSimAttribute to the interface
-
-! 2003-01-24 - Sebastien Ponce
- - package creation
diff --git a/Sim/SimSvc/src/SimulationSvc.cpp b/Sim/SimSvc/src/RegionsDefinitionSvc.cpp
similarity index 87%
rename from Sim/SimSvc/src/SimulationSvc.cpp
rename to Sim/SimSvc/src/RegionsDefinitionSvc.cpp
index fcfa35484..5ecb6e4c2 100755
--- a/Sim/SimSvc/src/SimulationSvc.cpp
+++ b/Sim/SimSvc/src/RegionsDefinitionSvc.cpp
@@ -7,9 +7,8 @@
 #include <xercesc/dom/DOMNodeList.hpp>
 
 #include "XmlTools/IXmlSvc.h"
-#include <DetDesc/ILVolume.h>
 
-#include "SimulationSvc.h"
+#include "RegionsDefinitionSvc.h"
 
 
 // -----------------------------------------------------------------------
@@ -18,7 +17,7 @@
 // -----------------------------------------------------------------------
 
 // Declaration of the Service Factory
-DECLARE_COMPONENT( SimulationSvc )
+DECLARE_COMPONENT( RegionsDefinitionSvc )
 
 
 
@@ -39,12 +38,12 @@ const std::string dom2Std (const XMLCh* domString) {
 // -----------------------------------------------------------------------
 // Standard Constructor
 // ------------------------------------------------------------------------
-SimulationSvc::SimulationSvc (const std::string& name, ISvcLocator* svc) :
+RegionsDefinitionSvc::RegionsDefinitionSvc (const std::string& name, ISvcLocator* svc) :
   Service (name, svc) {
-  declareProperty ("SimulationDbLocation", m_simDbLocation="empty" );
+  declareProperty ("RegionsDefinitionDbLocation", m_simDbLocation="empty" );
 }
 
-SimulationSvc::~SimulationSvc() 
+RegionsDefinitionSvc::~RegionsDefinitionSvc() 
 {
   for (AttributeSet::iterator it=m_attributeSet.begin();
        it!= m_attributeSet.end();it++)  delete (*it).second;
@@ -60,7 +59,7 @@ SimulationSvc::~SimulationSvc()
 // -----------------------------------------------------------------------
 // Initialize the service.
 // -----------------------------------------------------------------------
-StatusCode SimulationSvc::initialize() {
+StatusCode RegionsDefinitionSvc::initialize() {
   // Before anything we have to initialize grand mother
   StatusCode status = Service::initialize();
   if (!status.isSuccess()) {
@@ -69,7 +68,7 @@ StatusCode SimulationSvc::initialize() {
   if( m_simDbLocation.empty() || "empty" == m_simDbLocation ) { 
     if ( 0 != getenv("GAUSSROOT") ) {
       m_simDbLocation  = getenv("GAUSSROOT");
-      m_simDbLocation += "/xml/Simulation.xml";
+      m_simDbLocation += "/xml/RegionsDefinition.xml";
     } else {
       m_simDbLocation = "";
     }
@@ -83,7 +82,7 @@ StatusCode SimulationSvc::initialize() {
 // -----------------------------------------------------------------------
 // clear
 // ------------------------------------------------------------------------
-void SimulationSvc::clear () {
+void RegionsDefinitionSvc::clear () {
   m_attributeSet.clear();
   m_logvol2Sim.clear();
   m_regionsDefs.clear();
@@ -92,8 +91,8 @@ void SimulationSvc::clear () {
 // -----------------------------------------------------------------------
 // reload
 // ------------------------------------------------------------------------
-void SimulationSvc::reload () {
-  MsgStream msg (msgSvc(), "SimulationSvc");
+void RegionsDefinitionSvc::reload () {
+  MsgStream msg (msgSvc(), "RegionsDefinitionSvc");
 
   // erases the old set of attributes
   clear();
@@ -155,7 +154,7 @@ void SimulationSvc::reload () {
     double minRange = -1.0;
     if (!mASAttribute.empty()) {
       maxAllowedStep = xmlSvc->eval(mASAttribute, false);
-    }
+   }
     if (!mTRAttribute.empty()) {
       maxTrackLength = xmlSvc->eval(mTRAttribute, true);
     }
@@ -372,27 +371,11 @@ void SimulationSvc::reload () {
   xmlSvc->releaseDoc(iovDoc);
 
 }
- 
-
-// -----------------------------------------------------------------------
-//  hasSimAttribute (ILVolume*)
-// -----------------------------------------------------------------------
-bool SimulationSvc::hasSimAttribute (const ILVolume* vol) const {
-  if (0 != vol) {
-    // try first to find an attribute associated directly to the logical volume
-    std::string bnn = vol->name();
-    Dict::const_iterator it = m_logvol2Sim.find (bnn);
-    if (it != m_logvol2Sim.end()) {
-      return true;
-    }    
-  }
-  return false;
-}
 
 // -----------------------------------------------------------------------
 //  hasSimAttribute (std::string)
 // -----------------------------------------------------------------------
-bool SimulationSvc::hasSimAttribute (const std::string volname) const {
+bool RegionsDefinitionSvc::hasSimAttribute (const std::string volname) const {
 
   // try first to find an attribute associated directly to the logical volume
   Dict::const_iterator it = m_logvol2Sim.find (volname);
@@ -402,36 +385,11 @@ bool SimulationSvc::hasSimAttribute (const std::string volname) const {
   return false;
 }
 
-// -----------------------------------------------------------------------
-//  simAttribute (ILVolume*)
-// -----------------------------------------------------------------------
-const SimulationSvc::PartAttr*
-SimulationSvc::simAttribute (const ILVolume* vol) const {
-  PartAttr* part = 0;
-  
-  if (0 != vol) {
-    // try first to find an attribute associated directly to the logical volume
-    std::string bnn = vol->name();
-    Dict::const_iterator it = m_logvol2Sim.find (bnn);
-    if (it != m_logvol2Sim.end()) 
-      {
-        part=it->second;
-      } 
-    else 
-      {
-        MsgStream msg (msgSvc(), name());
-        msg << MSG::WARNING << "No SimAttribute for " 
-            << vol->name() << endmsg;
-      } 
-  }
-  return part;
-}
-
 // -----------------------------------------------------------------------
 //  simAttribute (std::string)
 // -----------------------------------------------------------------------
-const SimulationSvc::PartAttr*
-SimulationSvc::simAttribute (std::string volname) const {
+const RegionsDefinitionSvc::PartAttr*
+RegionsDefinitionSvc::simAttribute (std::string volname) const {
   PartAttr* part = 0;
   
   // try first to find an attribute associated directly to the logical volume
@@ -453,7 +411,7 @@ SimulationSvc::simAttribute (std::string volname) const {
 // regionsDefs()
 //------------------------------------------------------------------------
 
-const std::vector<RegionCuts>* SimulationSvc::regionsDefs () const
+const std::vector<RegionCuts>* RegionsDefinitionSvc::regionsDefs () const
 {
   return &m_regionsDefs;
 }
@@ -463,9 +421,9 @@ const std::vector<RegionCuts>* SimulationSvc::regionsDefs () const
 // Query interface
 // -----------------------------------------------------------------------
 StatusCode
-SimulationSvc::queryInterface(const InterfaceID& riid, void** ppvInterface) {
-  if (IID_ISimulationSvc.versionMatch(riid))  {
-    *ppvInterface = (ISimulationSvc*)this;
+RegionsDefinitionSvc::queryInterface(const InterfaceID& riid, void** ppvInterface) {
+  if (IID_IRegionsDefinitionSvc.versionMatch(riid))  {
+    *ppvInterface = (IRegionsDefinitionSvc*)this;
   } else {
     // Interface is not directly availible: try out a base class
     return Service::queryInterface(riid, ppvInterface);
diff --git a/Sim/SimSvc/src/SimulationSvc.h b/Sim/SimSvc/src/RegionsDefinitionSvc.h
similarity index 72%
rename from Sim/SimSvc/src/SimulationSvc.h
rename to Sim/SimSvc/src/RegionsDefinitionSvc.h
index f7bc5486b..3b601569f 100755
--- a/Sim/SimSvc/src/SimulationSvc.h
+++ b/Sim/SimSvc/src/RegionsDefinitionSvc.h
@@ -1,28 +1,23 @@
-#ifndef SIMSVC_SIMULATIONSVC_H
-#define SIMSVC_SIMULATIONSVC_H
-
+#pragma once
 // Include files
 #include "GaudiKernel/Service.h"
 
-#include "SimSvc/ISimulationSvc.h"
+#include "GiGaMTRegions/IRegionsDefinitionSvc.h"
 
 #include <map>
 
-// Forward and external declarations
-template <class TYPE> class SvcFactory;
-
 
-/** @class SimulationSvc SimulationSvc.h SimDesc/SimulationSvc.h
+/** @class RegionsDefinitionSvc RegionsDefinitionSvc.h SimDesc/RegionsDefinitionSvc.h
  *
- *  this interface defines a Simulation service that is able to answer
+ *  this interface defines a RegionsDefinition service that is able to answer
  *  many question concerning the simulation of the detector. It
  *  is able to associate simulation attributes to logical volumes.
  *  These describe the way these volumes should be simulated
  *
  * @author Sebastien Ponce
  */
-class SimulationSvc : public Service,
-                      virtual public ISimulationSvc {
+class RegionsDefinitionSvc : public Service,
+                      virtual public IRegionsDefinitionSvc {
 public:
 
   /**
@@ -30,12 +25,12 @@ public:
    * @param name   String with service name
    * @param svc    Pointer to service locator interface
    */
-  SimulationSvc (const std::string& name, ISvcLocator* svc);
+  RegionsDefinitionSvc (const std::string& name, ISvcLocator* svc);
 
   /**
    * default destructor
    */
-  virtual ~SimulationSvc();
+  virtual ~RegionsDefinitionSvc();
 
   //  inline void operator delete (void* p) throw()
   // { operator delete( const_cast<void*> (p)) ; }
@@ -55,18 +50,9 @@ public:
   StatusCode queryInterface (const InterfaceID& riid, void** ppvInterface) override;
 
   ///////////////////////////////////////////////////////
-  // implementation of the ISimulationSvc interface //
+  // implementation of the IRegionsDefinitionSvc interface //
   ///////////////////////////////////////////////////////
 
-  /**
-   * This method returns the simulation attribute associated to a given
-   * logical volume
-   * @param vol the logical volume
-   * @return the simulation attribute that should be used to simulate
-   * this logical volume
-   */
-  const PartAttr* simAttribute (const ILVolume* vol) const override;
-
   /**
    * This method returns the simulation attribute associated to a given
    * logical volume
@@ -76,13 +62,6 @@ public:
    */
   const PartAttr* simAttribute (const std::string volname) const override;
 
-  /**
-   * This method tells whether a simulation attribute is associated to a given
-   * logical volume or not
-   * @param vol the logical volume
-   */
-  bool hasSimAttribute (const ILVolume* vol) const override;
-
   /**
    * This method tells whether a simulation attribute is associated to a given
    * logical volume or not
@@ -146,5 +125,3 @@ private:
   std::string m_simDbLocation;
 
 };
-
-#endif // SIMSVC_SIMULATIONSVC_H
-- 
GitLab


From 0b0aad2ea1864afafb8e76b7821385d48978713d Mon Sep 17 00:00:00 2001
From: Dominik Muller <dominik.muller@cern.ch>
Date: Fri, 9 Aug 2019 17:52:25 +0200
Subject: [PATCH 21/90] Removed Gen/Generators. Taken out EvtGenDecay
 components to LbEvtGen. Initial port to new framework with recursive mutex
 lock

---
 Gen/Generators/Generators/ExternalGenerator.h |  190 ---
 Gen/Generators/Generators/F77Utils.h          |  153 ---
 Gen/Generators/Generators/GenCounters.h       |  266 ----
 Gen/Generators/Generators/HepMCUtils.h        |   10 -
 Gen/Generators/Generators/IBeamTool.h         |   40 -
 Gen/Generators/Generators/ICounterLogFile.h   |   54 -
 Gen/Generators/Generators/IDecayTool.h        |   10 -
 .../Generators/IFullGenEventCutTool.h         |   10 -
 Gen/Generators/Generators/IGenCutTool.h       |   10 -
 Gen/Generators/Generators/IPileUpTool.h       |   33 -
 Gen/Generators/Generators/IProductionTool.h   |   86 --
 .../Generators/ISampleGenerationTool.h        |   45 -
 .../Generators/IVertexSmearingTool.h          |   33 -
 .../Generators/LHAPDFCommonBlocks.h           |   60 -
 Gen/Generators/Generators/LbPhotos.h          |   18 -
 Gen/Generators/Generators/LbTaula.h           |   18 -
 Gen/Generators/Generators/LhaPdf.h            |   23 -
 .../Generators/RandomForGenerator.h           |   27 -
 Gen/Generators/Generators/Signal.h            |  198 ---
 .../Generators/StreamForGenerator.h           |   24 -
 Gen/Generators/Generators/StringParse.h       |   50 -
 ...hainSampleVertex-4D-PDF-Mathematica.nb.bz2 |  Bin 12266 -> 0 bytes
 Gen/Generators/doc/release.notes              | 1154 -----------------
 Gen/Generators/src/Lib/EvtReport.cpp          |   35 -
 Gen/Generators/src/Lib/ExternalGenerator.cpp  |  356 -----
 Gen/Generators/src/Lib/F77Utils.cpp           |  241 ----
 Gen/Generators/src/Lib/GenCounters.cpp        |  607 ---------
 Gen/Generators/src/Lib/LBPHOTOS.F             |   19 -
 Gen/Generators/src/Lib/LBTAULA.F              |   19 -
 Gen/Generators/src/Lib/LHAPDFCommonBlocks.cpp |   78 --
 Gen/Generators/src/Lib/LHAPDFUtils.F          |   54 -
 Gen/Generators/src/Lib/LbPhotos.cpp           |   25 -
 Gen/Generators/src/Lib/LbTaula.cpp            |   25 -
 Gen/Generators/src/Lib/LhaPdf.cpp             |   13 -
 Gen/Generators/src/Lib/RandomForGenerator.cpp |   16 -
 Gen/Generators/src/Lib/Signal.cpp             |  387 ------
 Gen/Generators/src/Lib/StreamForGenerator.cpp |   11 -
 Gen/Generators/src/Lib/StringParse.cpp        |   55 -
 Gen/Generators/src/Lib/cpyr.cpp               |   23 -
 Gen/Generators/src/Lib/f77units.F             |  221 ----
 Gen/Generators/src/Lib/getaddr.cpp            |   22 -
 Gen/Generators/src/Lib/pythiaoutput_utils.F   |   44 -
 Gen/Generators/src/component/ApplyPhotos.cpp  |  140 --
 Gen/Generators/src/component/ApplyPhotos.h    |   35 -
 .../component/AsymmetricCollidingBeams.cpp    |  128 --
 .../src/component/AsymmetricCollidingBeams.h  |   53 -
 .../BeamSpotMarkovChainSampleVertex.cpp       |  219 ----
 .../BeamSpotMarkovChainSampleVertex.h         |   99 --
 .../src/component/BeamSpotSmearVertex.cpp     |  102 --
 .../src/component/BeamSpotSmearVertex.h       |   57 -
 .../src/component/CollidingBeams.cpp          |  127 --
 Gen/Generators/src/component/CollidingBeams.h |   52 -
 Gen/Generators/src/component/EvtGenTool.cpp   |   76 --
 Gen/Generators/src/component/EvtGenTool.h     |   77 --
 .../src/component/FixedLuminosity.cpp         |  116 --
 .../src/component/FixedLuminosity.h           |   65 -
 .../FixedLuminosityForRareProcess.cpp         |  110 --
 .../component/FixedLuminosityForRareProcess.h |   63 -
 .../component/FixedLuminosityForSpillOver.cpp |  119 --
 .../component/FixedLuminosityForSpillOver.h   |   67 -
 .../src/component/FixedNInteractions.cpp      |   65 -
 .../src/component/FixedNInteractions.h        |   44 -
 Gen/Generators/src/component/FixedTarget.cpp  |  101 --
 Gen/Generators/src/component/FixedTarget.h    |   47 -
 .../src/component/FlatSmearVertex.cpp         |  127 --
 .../src/component/FlatSmearVertex.h           |   64 -
 .../src/component/FlatZSmearVertex.cpp        |  127 --
 .../src/component/FlatZSmearVertex.h          |   63 -
 Gen/Generators/src/component/Generation.cpp   |  670 ----------
 Gen/Generators/src/component/Generation.h     |  187 ---
 .../src/component/HistoSmearVertex.cpp        |  103 --
 .../src/component/HistoSmearVertex.h          |   40 -
 Gen/Generators/src/component/IEvtGenTool.h    |   39 -
 Gen/Generators/src/component/Inclusive.cpp    |  255 ----
 Gen/Generators/src/component/Inclusive.h      |  148 ---
 .../src/component/MergedEventsFilter.cpp      |  108 --
 .../src/component/MergedEventsFilter.h        |   39 -
 Gen/Generators/src/component/MinimumBias.cpp  |   63 -
 Gen/Generators/src/component/MinimumBias.h    |   39 -
 .../src/component/ReadHepMCAsciiFile.cpp      |  201 ---
 Gen/Generators/src/component/RepeatDecay.cpp  |  164 ---
 Gen/Generators/src/component/RepeatDecay.h    |   89 --
 .../src/component/SaveSignalBInformation.cpp  |  179 ---
 .../src/component/SaveSignalBInformation.h    |   45 -
 .../component/SignalForcedFragmentation.cpp   |  337 -----
 .../src/component/SignalForcedFragmentation.h |   57 -
 Gen/Generators/src/component/SignalPlain.cpp  |  183 ---
 Gen/Generators/src/component/SignalPlain.h    |   39 -
 .../component/SignalRepeatedHadronization.cpp |  298 -----
 .../component/SignalRepeatedHadronization.h   |   60 -
 Gen/Generators/src/component/Special.cpp      |  255 ----
 Gen/Generators/src/component/Special.h        |   84 --
 .../src/component/StandAloneDecayTool.cpp     |  114 --
 .../src/component/StandAloneDecayTool.h       |   35 -
 .../src/component/UniformSmearVertex.cpp      |  124 --
 .../src/component/UniformSmearVertex.h        |   64 -
 .../src/component/VariableLuminosity.cpp      |  139 --
 .../src/component/VariableLuminosity.h        |   77 --
 .../src/component/WriteHepMCAsciiFile.cpp     |  163 ---
 .../src/component/XmlCounterLogFile.cpp       |  154 ---
 .../src/component/XmlCounterLogFile.h         |   67 -
 Gen/{Generators => LbEvtGen}/CMakeLists.txt   |   30 +-
 .../src}/EvtGenDecay.cpp                      |  156 +--
 .../component => LbEvtGen/src}/EvtGenDecay.h  |  136 +-
 .../src}/EvtGenDecayWithCutTool.cpp           |   37 +-
 .../src}/EvtGenDecayWithCutTool.h             |   18 +-
 .../src}/EvtGenInPhSpDecay.cpp                |   36 +-
 .../src}/EvtGenInPhSpDecay.h                  |   32 +-
 Sim/Gauss/python/Gauss/Configuration.py       |    3 +
 109 files changed, 147 insertions(+), 12026 deletions(-)
 delete mode 100755 Gen/Generators/Generators/ExternalGenerator.h
 delete mode 100755 Gen/Generators/Generators/F77Utils.h
 delete mode 100755 Gen/Generators/Generators/GenCounters.h
 delete mode 100755 Gen/Generators/Generators/HepMCUtils.h
 delete mode 100755 Gen/Generators/Generators/IBeamTool.h
 delete mode 100644 Gen/Generators/Generators/ICounterLogFile.h
 delete mode 100755 Gen/Generators/Generators/IDecayTool.h
 delete mode 100755 Gen/Generators/Generators/IFullGenEventCutTool.h
 delete mode 100755 Gen/Generators/Generators/IGenCutTool.h
 delete mode 100755 Gen/Generators/Generators/IPileUpTool.h
 delete mode 100755 Gen/Generators/Generators/IProductionTool.h
 delete mode 100755 Gen/Generators/Generators/ISampleGenerationTool.h
 delete mode 100755 Gen/Generators/Generators/IVertexSmearingTool.h
 delete mode 100755 Gen/Generators/Generators/LHAPDFCommonBlocks.h
 delete mode 100644 Gen/Generators/Generators/LbPhotos.h
 delete mode 100644 Gen/Generators/Generators/LbTaula.h
 delete mode 100755 Gen/Generators/Generators/LhaPdf.h
 delete mode 100755 Gen/Generators/Generators/RandomForGenerator.h
 delete mode 100755 Gen/Generators/Generators/Signal.h
 delete mode 100755 Gen/Generators/Generators/StreamForGenerator.h
 delete mode 100755 Gen/Generators/Generators/StringParse.h
 delete mode 100644 Gen/Generators/doc/BeamSpotMarkovChainSampleVertex-4D-PDF-Mathematica.nb.bz2
 delete mode 100755 Gen/Generators/doc/release.notes
 delete mode 100755 Gen/Generators/src/Lib/EvtReport.cpp
 delete mode 100755 Gen/Generators/src/Lib/ExternalGenerator.cpp
 delete mode 100755 Gen/Generators/src/Lib/F77Utils.cpp
 delete mode 100755 Gen/Generators/src/Lib/GenCounters.cpp
 delete mode 100644 Gen/Generators/src/Lib/LBPHOTOS.F
 delete mode 100644 Gen/Generators/src/Lib/LBTAULA.F
 delete mode 100755 Gen/Generators/src/Lib/LHAPDFCommonBlocks.cpp
 delete mode 100755 Gen/Generators/src/Lib/LHAPDFUtils.F
 delete mode 100644 Gen/Generators/src/Lib/LbPhotos.cpp
 delete mode 100644 Gen/Generators/src/Lib/LbTaula.cpp
 delete mode 100755 Gen/Generators/src/Lib/LhaPdf.cpp
 delete mode 100755 Gen/Generators/src/Lib/RandomForGenerator.cpp
 delete mode 100755 Gen/Generators/src/Lib/Signal.cpp
 delete mode 100755 Gen/Generators/src/Lib/StreamForGenerator.cpp
 delete mode 100755 Gen/Generators/src/Lib/StringParse.cpp
 delete mode 100755 Gen/Generators/src/Lib/cpyr.cpp
 delete mode 100755 Gen/Generators/src/Lib/f77units.F
 delete mode 100755 Gen/Generators/src/Lib/getaddr.cpp
 delete mode 100755 Gen/Generators/src/Lib/pythiaoutput_utils.F
 delete mode 100644 Gen/Generators/src/component/ApplyPhotos.cpp
 delete mode 100644 Gen/Generators/src/component/ApplyPhotos.h
 delete mode 100755 Gen/Generators/src/component/AsymmetricCollidingBeams.cpp
 delete mode 100755 Gen/Generators/src/component/AsymmetricCollidingBeams.h
 delete mode 100644 Gen/Generators/src/component/BeamSpotMarkovChainSampleVertex.cpp
 delete mode 100644 Gen/Generators/src/component/BeamSpotMarkovChainSampleVertex.h
 delete mode 100755 Gen/Generators/src/component/BeamSpotSmearVertex.cpp
 delete mode 100755 Gen/Generators/src/component/BeamSpotSmearVertex.h
 delete mode 100755 Gen/Generators/src/component/CollidingBeams.cpp
 delete mode 100755 Gen/Generators/src/component/CollidingBeams.h
 delete mode 100755 Gen/Generators/src/component/EvtGenTool.cpp
 delete mode 100755 Gen/Generators/src/component/EvtGenTool.h
 delete mode 100755 Gen/Generators/src/component/FixedLuminosity.cpp
 delete mode 100755 Gen/Generators/src/component/FixedLuminosity.h
 delete mode 100755 Gen/Generators/src/component/FixedLuminosityForRareProcess.cpp
 delete mode 100755 Gen/Generators/src/component/FixedLuminosityForRareProcess.h
 delete mode 100644 Gen/Generators/src/component/FixedLuminosityForSpillOver.cpp
 delete mode 100644 Gen/Generators/src/component/FixedLuminosityForSpillOver.h
 delete mode 100755 Gen/Generators/src/component/FixedNInteractions.cpp
 delete mode 100755 Gen/Generators/src/component/FixedNInteractions.h
 delete mode 100755 Gen/Generators/src/component/FixedTarget.cpp
 delete mode 100755 Gen/Generators/src/component/FixedTarget.h
 delete mode 100755 Gen/Generators/src/component/FlatSmearVertex.cpp
 delete mode 100755 Gen/Generators/src/component/FlatSmearVertex.h
 delete mode 100755 Gen/Generators/src/component/FlatZSmearVertex.cpp
 delete mode 100755 Gen/Generators/src/component/FlatZSmearVertex.h
 delete mode 100755 Gen/Generators/src/component/Generation.cpp
 delete mode 100755 Gen/Generators/src/component/Generation.h
 delete mode 100755 Gen/Generators/src/component/HistoSmearVertex.cpp
 delete mode 100644 Gen/Generators/src/component/HistoSmearVertex.h
 delete mode 100644 Gen/Generators/src/component/IEvtGenTool.h
 delete mode 100755 Gen/Generators/src/component/Inclusive.cpp
 delete mode 100755 Gen/Generators/src/component/Inclusive.h
 delete mode 100755 Gen/Generators/src/component/MergedEventsFilter.cpp
 delete mode 100755 Gen/Generators/src/component/MergedEventsFilter.h
 delete mode 100755 Gen/Generators/src/component/MinimumBias.cpp
 delete mode 100755 Gen/Generators/src/component/MinimumBias.h
 delete mode 100755 Gen/Generators/src/component/ReadHepMCAsciiFile.cpp
 delete mode 100755 Gen/Generators/src/component/RepeatDecay.cpp
 delete mode 100755 Gen/Generators/src/component/RepeatDecay.h
 delete mode 100644 Gen/Generators/src/component/SaveSignalBInformation.cpp
 delete mode 100644 Gen/Generators/src/component/SaveSignalBInformation.h
 delete mode 100755 Gen/Generators/src/component/SignalForcedFragmentation.cpp
 delete mode 100755 Gen/Generators/src/component/SignalForcedFragmentation.h
 delete mode 100755 Gen/Generators/src/component/SignalPlain.cpp
 delete mode 100755 Gen/Generators/src/component/SignalPlain.h
 delete mode 100755 Gen/Generators/src/component/SignalRepeatedHadronization.cpp
 delete mode 100755 Gen/Generators/src/component/SignalRepeatedHadronization.h
 delete mode 100755 Gen/Generators/src/component/Special.cpp
 delete mode 100755 Gen/Generators/src/component/Special.h
 delete mode 100755 Gen/Generators/src/component/StandAloneDecayTool.cpp
 delete mode 100755 Gen/Generators/src/component/StandAloneDecayTool.h
 delete mode 100755 Gen/Generators/src/component/UniformSmearVertex.cpp
 delete mode 100755 Gen/Generators/src/component/UniformSmearVertex.h
 delete mode 100755 Gen/Generators/src/component/VariableLuminosity.cpp
 delete mode 100755 Gen/Generators/src/component/VariableLuminosity.h
 delete mode 100755 Gen/Generators/src/component/WriteHepMCAsciiFile.cpp
 delete mode 100644 Gen/Generators/src/component/XmlCounterLogFile.cpp
 delete mode 100644 Gen/Generators/src/component/XmlCounterLogFile.h
 rename Gen/{Generators => LbEvtGen}/CMakeLists.txt (50%)
 rename Gen/{Generators/src/component => LbEvtGen/src}/EvtGenDecay.cpp (82%)
 rename Gen/{Generators/src/component => LbEvtGen/src}/EvtGenDecay.h (67%)
 rename Gen/{Generators/src/component => LbEvtGen/src}/EvtGenDecayWithCutTool.cpp (57%)
 rename Gen/{Generators/src/component => LbEvtGen/src}/EvtGenDecayWithCutTool.h (68%)
 rename Gen/{Generators/src/component => LbEvtGen/src}/EvtGenInPhSpDecay.cpp (86%)
 rename Gen/{Generators/src/component => LbEvtGen/src}/EvtGenInPhSpDecay.h (56%)

diff --git a/Gen/Generators/Generators/ExternalGenerator.h b/Gen/Generators/Generators/ExternalGenerator.h
deleted file mode 100755
index 2a4afc873..000000000
--- a/Gen/Generators/Generators/ExternalGenerator.h
+++ /dev/null
@@ -1,190 +0,0 @@
-// $Id: ExternalGenerator.h,v 1.14 2009-12-03 15:32:49 robbep Exp $
-#ifndef GENERATORS_EXTERNALGENERATOR_H
-#define GENERATORS_EXTERNALGENERATOR_H 1
-
-// Include files
-#include <set>
-
-// from Gaudi
-#include "GaudiAlg/GaudiTool.h"
-#include "Generators/ISampleGenerationTool.h"
-
-// from LHCb
-#include "Kernel/ParticleID.h"
-
-// forward declarations
-class IProductionTool ;
-class IDecayTool ;
-class IGenCutTool ;
-class ICounterLogFile ;
-namespace LHCb { class IParticlePropertySvc ; }
-
-namespace HepMC {
-  class GenEvent ;
-  class GenParticle ;
-}
-
-/** @class ExternalGenerator ExternalGenerator.h "Generators/ExternalGenerator.h"
- *
- *  Base class for sample generation tools which use external generators
- *  (Pythia, Herwig, ...)
- *  This class provides common utility functions which can be used to generate
- *  samples of events of various types.
- *
- *  @author Patrick Robbe
- *  @date   2005-08-18
- */
-
-class ExternalGenerator : public GaudiTool ,
-                          public ISampleGenerationTool {
- public:
-  /// Vector of HepMC particles
-  typedef std::vector< HepMC::GenParticle * > ParticleVector ;
-
-  /// Ordered set of integer to contain PID of particles to generate
-  typedef std::set< int >                     PIDs           ;
-
-  /// Vector of string to pass configuration commands to the external generator
-  typedef std::vector< std::string >          CommandVector  ;
-
-  /// Standard constructor
-  ExternalGenerator( const std::string & type , const std::string & name ,
-                     const IInterface * parent ) ;
-
-  virtual ~ExternalGenerator( ) ; ///< Destructor
-
-  /** Initialization function.
-   *  The function:
-   *  -# configures the LHAPDF library with a default set of commands (enabling
-   *     or disabling LHAPDF output depending on the output level) and with
-   *     optional user commands.
-   *  -# loop over all particles defined in the particle property service
-   *     and declare them stable for the production tool if they are known
-   *     by the decay tool.
-   */
-  StatusCode initialize( ) override;
-
-  /** Finalization funtion.
-   *  This function closes the file used to redirect LHAPDF output messages
-   *  in case the output is disabled.
-   */
-  StatusCode finalize( ) override;
-
- protected:
-  /** Decay heavy excited particles.
-   *  This function decay heavy excited particles with the DecayTool. It
-   *  is necessary to decay excited particles earlier than the other because
-   *  the signal particle can be produced by the decay of an excited particle
-   *  eg. B*0 -> B0 gamma
-   *  @param[in,out] theEvent  HepMC event which contains the particles to
-   *                           decay. The event is updated with the resulting
-   *                           decay trees.
-   *  @param[in]     mass      Mass above which particles are considered "heavy
-   *                           excited particles" and must be decayed with the
-   *                           decay tool.
-   *  @param[in]     pid       PID of the particle which is the ligther to
-   *                           decay, the decay chain is stopped when this
-   *                           particle is found.
-   *  @return     StatusCode::SUCCESS
-   *  @return     StatusCode::ERROR if an unkown excited particle is found (in
-   *                                this case, this particle has to be added to
-   *                                the ParticlePropertySvc or/and the EvtGen
-   *                                decay table).
-   */
-  StatusCode decayHeavyParticles( HepMC::GenEvent * theEvent ,
-                                  const LHCb::ParticleID::Quark theQuark ,
-                                  const int signalPid ) const ;
-
-
-  /** Find particles of given PIDs in an event
-   *  @param[in]  pidList       Ordered (for efficiency) set of PIDs to look
-   *                            for in this event.
-   *  @param[in]  theEvent      Event to study.
-   *  @param[out] particleList  List of particles contained in the event whose
-   *                            PID is in the pidList.
-   *  @return     true if the event contains a particle with correct PID.
-   */
-  bool checkPresence( const PIDs & pidList , const HepMC::GenEvent * theEvent ,
-                      ParticleVector & particleList ) const ;
-
-  /** Parity flip (z -> -z and pz -> -pz) the event
-   *  @param[in,out] theEvent   Event to flip
-   */
-  void revertEvent( HepMC::GenEvent * theEvent ) const ;
-
-  /** Count the number of particle with pz > 0
-   *  @param[in] particleList  List of particles
-   *  @return    Number of particle with pz > 0 in particleList.
-   */
-  unsigned int nPositivePz( const ParticleVector & particleList ) const ;
-
-  /** Prepare interaction before generating it.
-   *  Performs all necessary actions required to prepare LHCb event model
-   *  classes before being able to generate interactions.
-   *  @param[in,out] theEventVector  Vector containing the generated events
-   *  @param[in,out] theHardVector   Vector containing the hard process
-   *                                 informations.
-   *  @param[out]    theGenEvent     Event where to store particles of the
-   *                                 next generated interaction.
-   *  @param[out]    theHardInfo     Object where to store hard process
-   *                                 informations of the next interaction.
-   */
-  void prepareInteraction( LHCb::HepMCEvents * theEvents ,
-                           LHCb::GenCollisions * theCollisions ,
-                           HepMC::GenEvent * & theGenEvent ,
-                           LHCb::GenCollision * & theGenCollision ) const ;
-
-  /** Production tool (interface to external generator) to use to
-   *  generate interactions */
-  IProductionTool * m_productionTool ;
-
-  /// Decay tool to use to decay excited heavy particles (B**)
-  IDecayTool      * m_decayTool      ;
-
-  /// Generator level cut tool to apply to generated interactions
-  IGenCutTool     * m_cutTool        ;
-
-  /// Log file tool
-  ICounterLogFile * m_xmlLogTool ;
-
-  /// Name assigned to the HepMC event and stored with it
-  std::string m_hepMCName ;
-
-  /// Location where to store FSR counters (set by options)
-  /// Not used in this class directly but by almost all 
-  /// derived classes
-  std::string  m_FSRName;
-
-  /// Keep original particle properties of the production generator
-  bool m_keepOriginalProperties ;
-
-  /// Particle property service
-  LHCb::IParticlePropertySvc * m_ppSvc ;
- private:
-  /** Decode commands (given by job options) to configure LHAPDF library.
-   *  @param[in] theCommandVector  Vector of string to configure LHAPDF. The
-   *                               syntax of the command is "lhacontrol block
-   *                               index value" where block is lhaparm (in this
-   *                               the common variable LHAPARM( index ) is set
-   *                               to value) or lhavalue (to set
-   *                               LHAVALUE( index ) to value).
-   */
-  StatusCode parseLhaPdfCommands( const CommandVector & theCommandVector )
-    const ;
-
-  /// Name of the production tool (external generator) to use
-  std::string m_productionToolName ;
-
-  /// Name of the decay tool to use
-  std::string m_decayToolName ;
-
-  /// Name of the generator level cut tool to use
-  std::string m_cutToolName ;
-
-  /// Commands to set the default configuration of LHAPDF (hardcoded)
-  CommandVector m_defaultLhaPdfSettings ;
-
-  /// Optional additional user commands to configure LHAPDF (by job options)
-  CommandVector m_userLhaPdfSettings ;
-};
-#endif // GENERATORS_EXTERNALGENERATOR_H
diff --git a/Gen/Generators/Generators/F77Utils.h b/Gen/Generators/Generators/F77Utils.h
deleted file mode 100755
index b82549e7c..000000000
--- a/Gen/Generators/Generators/F77Utils.h
+++ /dev/null
@@ -1,153 +0,0 @@
-// $Id: F77Utils.h,v 1.2 2007-06-29 13:21:06 ibelyaev Exp $
-// ============================================================================
-#ifndef GENERATORS_F77UTILS_H 
-#define GENERATORS_F77UTILS_H 1
-// ============================================================================
-// Include files
-// ============================================================================
-// STD & STL 
-// ============================================================================
-#include <string>
-// ============================================================================
-// GaudiKernel
-// ============================================================================
-#include "GaudiKernel/StatusCode.h"
-// ============================================================================
-/** @namespace  F77Utils F77Utils.h Generators/F77Utils.h
- *  Collection of primitive utilities to open/close FORTRAN units 
- *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
- *  @date   2006-10-03
- */
-namespace F77Utils 
-{
-  // ==========================================================================
-  /** Close the opened F77 file 
-   *  @param lun logical file number 
-   *  @param verbose verbosity flag
-   *  @return status code 
-   *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
-   *  @date   2006-10-03
-   */
-  StatusCode close       
-  ( int lun , const bool verbose = false ) ;
-  // ==========================================================================
-  /** Open Fortran file with status="NEW" 
-   *  @param lun logical file number 
-   *  @param file file name 
-   *  @param verbose verbosity flag
-   *  @return status code 
-   *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
-   *  @date   2006-10-03
-   */
-  StatusCode openNew    
-  ( int   lun                          , 
-    const std::string& file            , 
-    const bool         verbose = false ) ;
-  // ==========================================================================
-  /** Open Fortran file with status="OLD" 
-   *  @param lun logical file number 
-   *  @param file file name 
-   *  @param verbose verbosity flag
-   *  @return status code 
-   *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
-   *  @date   2006-10-03
-   */
-  StatusCode openOld     
-  ( int   lun                          , 
-    const std::string& file            ,
-    const bool         verbose = false ) ;
-  // ==========================================================================
-  /** Open Fortran file with status="UNKNOWN" 
-   *  @param lun logical file number 
-   *  @param file file name 
-   *  @param verbose verbosity flag
-   *  @return status code 
-   *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
-   *  @date   2006-10-03
-   */
-  StatusCode openUnknown 
-  ( int                lun             , 
-    const std::string& file            ,
-    const bool         verbose = false ) ;
-  // ==========================================================================
-  /** Open Fortran file with status="UNKNOWN" 
-   *  @param lun logical file number 
-   *  @param file file name 
-   *  @param verbose verbosity flag
-   *  @return status code 
-   *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
-   *  @date   2006-10-03
-   */
-  StatusCode open 
-  ( int                lun             , 
-    const std::string& file            ,
-    const bool         verbose = false ) ;
-  // ==========================================================================
-  /** @fn openNewFormatted 
-   *  Open "FORMATTED" Fortran file with status="NEW" 
-   *  @param lun logical file number 
-   *  @param verbose verbosity flag
-   *  @param file file name 
-   *  @return status code 
-   *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
-   *  @date   2006-10-03
-   */
-  StatusCode openNewFormatted
-  ( int                lun             , 
-    const std::string& file            ,
-    const bool         verbose = false ) ;
-  // ==========================================================================
-  /** Open "FORMATTED" Fortran file with status="OLD" 
-   *  @param lun logical file number 
-   *  @param file file name 
-   *  @param verbose verbosity flag
-   *  @return status code 
-   *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
-   *  @date   2006-10-03
-   */
-  StatusCode openOldFormatted 
-  ( int                lun             , 
-    const std::string& file            ,
-    const bool         verbose = false ) ;
-  // ==========================================================================
-  /** Open "FORMATTED" Fortran file with status="UNKNOWN" 
-   *  @param lun logical file number 
-   *  @param file file name 
-   *  @param verbose verbosity flag
-   *  @return status code 
-   *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
-   *  @date   2006-10-03
-   */
-  StatusCode openUnknownFormatted 
-  ( int                lun             , 
-    const std::string& file            ,
-    const bool         verbose = false ) ;
-  // ==========================================================================
-  /** Open "FORMATTED" Fortran file with status="UNKNOWN" 
-   *  @param lun logical file number 
-   *  @param file file name 
-   *  @param verbose verbosity flag
-   *  @return status code 
-   *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
-   *  @date   2006-10-03
-   */
-  StatusCode openFormatted
-  ( int                lun             , 
-    const std::string& file            ,
-    const bool         verbose = false ) ;
-  // ==========================================================================
-  /** find free fortran units
-   *  Program scans fortran units from 99 to 10 to find "free" units, 
-   *  @param verbose verbosity flag
-   *  @return unit 
-   *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
-   *  @date   2006-10-03
-   */
-  int getUnit( const bool verbose = false ) ;
-  // ==========================================================================
-} // end of namespace F77Utils 
-// ============================================================================
-// The END 
-// ============================================================================
-#endif // GENERATORS_F77UTILS_H
-// ============================================================================
diff --git a/Gen/Generators/Generators/GenCounters.h b/Gen/Generators/Generators/GenCounters.h
deleted file mode 100755
index 45c48d890..000000000
--- a/Gen/Generators/Generators/GenCounters.h
+++ /dev/null
@@ -1,266 +0,0 @@
-// $Id: GenCounters.h,v 1.5 2006-09-19 21:41:43 gcorti Exp $
-#ifndef GENERATORS_GENCOUNTERS_H 
-#define GENERATORS_GENCOUNTERS_H 1
-
-// Include files
-#include "GaudiKernel/MsgStream.h"
-#include "Generators/ICounterLogFile.h"
-
-#include <cmath>
-#include <numeric>
-#include <algorithm>
-
-namespace boost {
-  template< typename T , std::size_t N > class array ;
-}
-
-namespace HepMC {
-  class GenEvent ;
-}
-
-namespace LHCb 
-{
-  class GenFSR ;
-  class GenCountersFSR ;  
-}
-
-
-/** @namespace GenCounters
- *  
- *  Utility functions to print counters and compute efficiencies
- * 
- *  @author Patrick Robbe
- *  @date   2005-11-30
- */
-
-namespace GenCounters {
-  /// Type for hadron counter
-  typedef boost::array< unsigned int , 5 > BHadronCounter ;
-  typedef boost::array< unsigned int , 4 > DHadronCounter ;
-  typedef boost::array< std::string  , 5 > BHadronCNames  ;
-  typedef boost::array< std::string  , 4 > DHadronCNames  ;
-
-  enum bHadronCounterType{ Bd = 0 , ///< counter of B0
-                           Bu , ///< counter of B+
-                           Bs , ///< counter of Bs0
-                           bBaryon , ///< counter of b-baryon
-                           Bc , ///< counter of Bc+
-  } ;
-  
-  enum cHadronCounterType{ D0 , ///< counter of D0
-                           Dch , ///< counter of D+
-                           Ds , ///< counter of Ds
-                           cBaryon , ///< counter of c-baryon
-  } ;
-
-
-  /// Type for excited states counters
-  typedef boost::array< unsigned int , 3 > ExcitedCounter ;
-  typedef boost::array< std::string  , 3 > ExcitedCNames  ;
-
-  enum excitedCounterType { _0star , ///< counter of X (spin 0, ang mom 0)
-                            _1star , ///< counter of X* (spin 1, ang mom 0)
-                            _2star  ///< counter of X** (ang mom 1)
-  } ;
-
-  /** Compute fraction of two numbers A/B
-   *  @param[in] A  Numerator 
-   *  @param[in] B  Denominator
-   *  @return A/B
-   */
-  inline double fraction( const unsigned int A , const unsigned int B ) {
-    return ( (double) A / (double) B ) ;
-  }
-  
-  /** Compute statistical error on fraction
-   *  @param[in] A  Numberator
-   *  @param[in] B  Denominator
-   *  @return Error on A/B
-   */
-  inline double err_fraction( const unsigned int A , const unsigned int B ) {
-    return sqrt( A * ( 1. - ( (double) A / (double) B ) ) ) / ( (double) B ) ;
-  }
-  
-  /** Print efficiency computed with 2 counters.
-   *  @param[in] theStream  Print facility to print the counters and efficiency
-   *                        after/before.
-   *  @param[in] cutName    Description of the cut
-   *  @param[in] after      Number of events after the cut
-   *  @param[in] before     Number of events before the cut
-   */
-  inline void printEfficiency( MsgStream & theStream , 
-                               const std::string & cutName , 
-                               const unsigned int after , 
-                               const unsigned int before ) {
-    if ( 0 == before ) return ;
-    theStream << "Number of events for " << cutName << ", before : " << before
-              << ", after : " << after 
-              << std::endl ;
-    theStream << "Efficiency of the " << cutName << " : " 
-              << format( "%.5g +/- %.5g" , fraction( after , before ) , 
-                         err_fraction( after , before ) ) << std::endl ;
-  }
-
-  /** Print efficiency computed with 2 counters.
-   *  @param[in] theLogFile Log file where to print the counters and efficiency
-   *                        after/before.
-   *  @param[in] cutName    Description of the cut
-   *  @param[in] after      Number of events after the cut
-   *  @param[in] before     Number of events before the cut
-   */
-  inline void printEfficiency( ICounterLogFile * theLogFile , 
-                               const std::string & cutName , 
-                               const unsigned int after , 
-                               const unsigned int before ) {
-    if ( 0 == before ) return ;
-    theLogFile -> addEfficiency( cutName , after , before , 
-                                 fraction( after , before ) , 
-                                 err_fraction( after , before ) ) ;
-  }  
-
-  /** Print a simple counter.
-   *  @param[in] theStream  Print facility to print the counter
-   *  @param[in] name       Description of the counter
-   *  @param[in] value      Value of the counter
-   */  
-  inline void printCounter( MsgStream & theStream , const std::string & name , 
-                            const unsigned int value ) {
-    theStream << "Number of " << name << " : " << value << std::endl ; 
-  }
-
-  /** Print a simple counter.
-   *  @param[in] theLogFile Log file to print the counter
-   *  @param[in] name       Description of the cut
-   *  @param[in] after      Number of events after the cut
-   *  @param[in] before     Number of events before the cut
-   */  
-  inline void printCounter( ICounterLogFile * theLogFile , const std::string & name , 
-                            const unsigned int value ) {
-    theLogFile -> addCounter( name , value ) ;
-  }
-  
-  /** Print fraction computed from two counters.
-   *  @param[in] theStream  Print facility to print the counters and fraction
-   *                        number/total.
-   *  @param[in] name       Description of the fraction
-   *  @param[in] number     Number of particles contained in the fraction
-   *  @param[in] total      Total number of particles.
-   */
-  inline void printFraction( MsgStream & theStream , 
-                             const std::string & name , 
-                             const unsigned int number , 
-                             const unsigned int total ) {
-    theStream << "Number of " << name << " : " << number ;
-    theStream << " [fraction : " 
-              << format( "%.5g +/- %.5g]" , fraction( number , total ) ,
-                         err_fraction( number , total ) ) << std::endl ;  
-  }
-
-  /** Print fraction computed from two counters.
-   *  @param[in] theLogFile Log file where to print the counters and fraction
-   *                        number/total.
-   *  @param[in] name       Description of the fraction
-   *  @param[in] number     Number of particles contained in the fraction
-   *  @param[in] total      Total number of particles.
-   */
-  inline void printFraction( ICounterLogFile * theLogFile , 
-                             const std::string & name , 
-                             const unsigned int number , 
-                             const unsigned int total ) {
-    theLogFile -> addFraction( name , number , fraction( number , total ) , 
-                               err_fraction( number , total ) ) ; 
-  }
-
-  /** Utility function to add an array to another one
-   *  @param[in,out] A   Adds content of B to A
-   *  @param[in]     B   Array to add to content of A 
-   */
-  template< typename T , std::size_t N > 
-  inline void AddTo( boost::array< T , N > & A ,
-                     const boost::array< T , N > & B ) {
-    std::transform( A.begin() , A.end() , B.begin() , A.begin() , 
-                    std::plus< unsigned int >( ) ) ;
-  }
-
-  /** Utility function to print Fractions from a array of counters
-   *  @param[in] 
-   */
-  template< typename T , std::size_t N >
-  inline void printArray( MsgStream & theStream ,
-                          boost::array< T , N > A ,
-                          boost::array< std::string , N > AName ,
-                          const std::string & root ) {
-    unsigned int total = std::accumulate( A.begin() , A.end() , 0 ) ;
-    for ( unsigned int i = 0 ; i < A.size() ; ++i ) 
-      printFraction( theStream , root + " " + AName[ i ] , A[ i ] , total ) ;
-  }
-
-  /** Utility function to print Fractions from a array of counters
-   *  @param[in] 
-   */
-  template< typename T , std::size_t N >
-  inline void printArray( ICounterLogFile * theLogFile ,
-                          boost::array< T , N > A ,
-                          boost::array< std::string , N > AName ,
-                          const std::string & root ) {
-    unsigned int total = std::accumulate( A.begin() , A.end() , 0 ) ;
-    for ( unsigned int i = 0 ; i < A.size() ; ++i ) 
-      printFraction( theLogFile , root + " " + AName[ i ] , A[ i ] , total ) ;
-  }
-
-  /** Utility function to setup names of B hadron counters 
-   *  @param[in] BC      Names of B hadron counters
-   *  @param[in] antiBC  Names of anti-B hadron counters
-   */
-  void setupBHadronCountersNames( BHadronCNames & BC , 
-                                  BHadronCNames & antiBC ) ;
-
-  /** Utility function to setup names of D hadron counters 
-   *  @param[in] DC      Names of D hadron counters
-   *  @param[in] antiDC  Names of anti-D hadron counters
-   */
-  void setupDHadronCountersNames( DHadronCNames & DC , 
-                                  DHadronCNames & antiDC ) ;
-
-  /** Utility function to setup names of excited states counters 
-   *  @param[in] DC      Names of excited states counters
-   *  @param[in] root    Basename 
-   */
-  void setupExcitedCountersNames( ExcitedCNames & B , 
-                                  const std::string & root ) ;
-
-  /** Update counters for excited states.
-   *  @param[in]  theEvent     The event where to count.
-   *  @param[out] thebExcitedC Counters for B(**) 
-   *  @param[out] thecExcitedC Counters for D(**)
-   */
-  void updateExcitedStatesCounters( const HepMC::GenEvent * theEvent ,
-                                    ExcitedCounter & thebExcitedC ,
-                                    ExcitedCounter & thecExcitedC ) ;
-
-  /** Update counters for flavour fractions.
-   *  @param[in]  theEvent     The event where to count.
-   *  @param[out] thebHadC     Counters for b-hadrons
-   *  @param[out] theantibHadC Counters for anti-b-hadrons
-   *  @param[out] thecHadC     Counters for c-hadrons
-   *  @param[out] theanticHadC Counters for anti-c-hadrons
-   *  @param[out] thebbCounter Counters for (bb) states
-   *  @param[out] theccCounter Counters for (cc) states
-   */
-  void updateHadronCounters( const HepMC::GenEvent * theEvent , 
-                             BHadronCounter & thebHadC , 
-                             BHadronCounter & theantibHadC ,
-                             DHadronCounter & thecHadC ,
-                             DHadronCounter & theanticHadC , 
-                             unsigned int & thebbCounter , 
-                             unsigned int & theccCounter ) ;
-  
-  void updateHadronFSR( const HepMC::GenEvent* theEvent,
-                        LHCb::GenFSR * genFSR,
-                        const std::string option);
-  
-
-
-}
-
-#endif // GENERATORS_GENCOUNTERS_H
diff --git a/Gen/Generators/Generators/HepMCUtils.h b/Gen/Generators/Generators/HepMCUtils.h
deleted file mode 100755
index 4f6556860..000000000
--- a/Gen/Generators/Generators/HepMCUtils.h
+++ /dev/null
@@ -1,10 +0,0 @@
-// $Id: HepMCUtils.h,v 1.8 2008-07-23 17:21:55 cattanem Exp $
-#ifndef GENERATORS_HEPMCUTILS_H 
-#define GENERATORS_HEPMCUTILS_H 1
-
-// This include has been moved to Event/GenEvent package.
-// This file is provided for backward compatibility.
-#warning "You should now include GenEvent/HepMCUtils.h instead"
-#include "GenEvent/HepMCUtils.h"
-
-#endif // GENERATORS_HEPMCUTILS_H
diff --git a/Gen/Generators/Generators/IBeamTool.h b/Gen/Generators/Generators/IBeamTool.h
deleted file mode 100755
index 57c8b195a..000000000
--- a/Gen/Generators/Generators/IBeamTool.h
+++ /dev/null
@@ -1,40 +0,0 @@
-// $Id: IBeamTool.h,v 1.4 2008-05-29 14:21:46 gcorti Exp $
-#ifndef GENERATORS_IBEAMTOOL_H 
-#define GENERATORS_IBEAMTOOL_H 1
-
-// Include files
-// from Gaudi
-#include "GaudiKernel/IAlgTool.h"
-#include "GaudiKernel/Vector3DTypes.h"
-
-/** @class IBeamTool IBeamTool.h "Generators/IBeamTool.h"
- *  
- *  Abstract interface to beam tool providing beam parameters 
- *  for each generated event.
- * 
- *  @author Patrick Robbe
- *  @date   2005-08-17
- */
-
-static const InterfaceID IID_IBeamTool( "IBeamTool" , 2 , 0 ) ;
-
-class IBeamTool : virtual public IAlgTool {
- public:
-  static const InterfaceID& interfaceID() { return IID_IBeamTool ; }
-  
-  /** Mean beam parameters.
-   *  Provides mean beam parameters (useful to initialize generators).
-   *  @param[out] pBeam1  Mean 3-momentum of beam 1 (pz > 0)
-   *  @param[out] pBeam2  Mean 3-momentum of beam 2 (pz < 0)
-   */
-  virtual void getMeanBeams( Gaudi::XYZVector & pBeam1, 
-                             Gaudi::XYZVector & pBeam2 ) const = 0 ;
-  
-  /** Generate beam parameters.
-   *  @param[out] pBeam1  3-momentum of beam 1 (pz > 0)
-   *  @param[out] pBeam2  3-momentum of beam 2 (pz > 0)
-   */
-  virtual void getBeams( Gaudi::XYZVector & pBeam1, 
-                         Gaudi::XYZVector & pBeam2 ) = 0 ;
-};
-#endif // GENERATORS_IBEAMTOOL_H
diff --git a/Gen/Generators/Generators/ICounterLogFile.h b/Gen/Generators/Generators/ICounterLogFile.h
deleted file mode 100644
index 410d61717..000000000
--- a/Gen/Generators/Generators/ICounterLogFile.h
+++ /dev/null
@@ -1,54 +0,0 @@
-#ifndef GENERATORS_ICOUNTERLOGFILE_H 
-#define GENERATORS_ICOUNTERLOGFILE_H 1
-
-// Include files
-// from Gaudi
-#include "GaudiKernel/IAlgTool.h"
-
-static const InterfaceID IID_ICounterLogFile ( "ICounterLogFile", 1, 0 );
-
-/** @class ICounterLogFile ICounterLogFile.h Generators/ICounterLogFile.h
- *  
- *
- *  @author Patrick Robbe
- *  @date   2013-01-15
- */
-class ICounterLogFile : virtual public IAlgTool {
-public: 
-
-  // Return the interface ID
-  static const InterfaceID& interfaceID() { return IID_ICounterLogFile; }
-
-  virtual void addEfficiency( const std::string & name , const unsigned int after , 
-                              const unsigned int before , const double fraction , 
-                              const double err_fraction ) = 0 ;
-
-  virtual void addCounter( const std::string & name , const unsigned int value ) = 0 ; 
-
-  virtual void addFraction( const std::string & name , const unsigned int number , 
-                            const double fraction , const double err_fraction ) = 0 ;
-
-  /// Add cross section value, in mb
-  virtual void addCrossSection( const std::string & name , 
-                                const unsigned int processId , 
-                                const unsigned int number , 
-                                const double value ) = 0 ;
-
-  /// Add the event type number
-  virtual void addEventType( const unsigned int evType ) = 0 ;
-
-  /// Add the Gauss version
-  virtual void addGaussVersion( const std::string & version ) = 0 ;
-
-  /// Add the method type
-  virtual void addMethod( const std::string & type ) = 0 ;
-
-  /// Add the generator
-  virtual void addGenerator( const std::string & generator ) = 0 ;
-  
-protected:
-
-private:
-
-};
-#endif // GENERATORS_ICOUNTERLOGFILE_H
diff --git a/Gen/Generators/Generators/IDecayTool.h b/Gen/Generators/Generators/IDecayTool.h
deleted file mode 100755
index 056817fd3..000000000
--- a/Gen/Generators/Generators/IDecayTool.h
+++ /dev/null
@@ -1,10 +0,0 @@
-// $Id: HepMCUtils.h,v 1.8 2008-07-23 17:21:55 cattanem Exp $
-#ifndef GENERATORS_IGENCUTTOOL_H 
-#define GENERATORS_IGENCUTTOOL_H 1
-
-// This include has been moved to Event/GenEvent package.
-// This file is provided for backward compatibility.
-#warning "You should now include MCInterfaces/IDecayTool.h instead"
-#include "MCInterfaces/IDecayTool.h"
-
-#endif // GENERATORS_IGENCUTTOOL_H
diff --git a/Gen/Generators/Generators/IFullGenEventCutTool.h b/Gen/Generators/Generators/IFullGenEventCutTool.h
deleted file mode 100755
index cf72f2378..000000000
--- a/Gen/Generators/Generators/IFullGenEventCutTool.h
+++ /dev/null
@@ -1,10 +0,0 @@
-// $Id: HepMCUtils.h,v 1.8 2008-07-23 17:21:55 cattanem Exp $
-#ifndef GENERATORS_IFULLGENEVENTCUTTOOL_H 
-#define GENERATORS_IFULLGENEVENTCUTTOOL_H 1
-
-// This include has been moved to Event/GenEvent package.
-// This file is provided for backward compatibility.
-#warning "You should now include MCInterfaces/IFullGenEventCutTool.h instead"
-#include "MCInterfaces/IFullGenEventCutTool.h"
-
-#endif // GENERATORS_IFULLGENEVENTCUTTOOL_H
diff --git a/Gen/Generators/Generators/IGenCutTool.h b/Gen/Generators/Generators/IGenCutTool.h
deleted file mode 100755
index 561365646..000000000
--- a/Gen/Generators/Generators/IGenCutTool.h
+++ /dev/null
@@ -1,10 +0,0 @@
-// $Id: HepMCUtils.h,v 1.8 2008-07-23 17:21:55 cattanem Exp $
-#ifndef GENERATORS_IGENCUTTOOL_H 
-#define GENERATORS_IGENCUTTOOL_H 1
-
-// This include has been moved to Event/GenEvent package.
-// This file is provided for backward compatibility.
-#warning "You should now include MCInterfaces/IGenCutTool.h instead"
-#include "MCInterfaces/IGenCutTool.h"
-
-#endif // GENERATORS_IGENCUTTOOL_H
diff --git a/Gen/Generators/Generators/IPileUpTool.h b/Gen/Generators/Generators/IPileUpTool.h
deleted file mode 100755
index a6e11bf3f..000000000
--- a/Gen/Generators/Generators/IPileUpTool.h
+++ /dev/null
@@ -1,33 +0,0 @@
-// $Id: IPileUpTool.h,v 1.4 2009-04-07 16:18:32 gcorti Exp $
-#ifndef GENERATORS_IPILEUPTOOL_H 
-#define GENERATORS_IPILEUPTOOL_H 1
-
-// Include files
-// from Gaudi
-#include "GaudiKernel/IAlgTool.h"
-
-/** @class IPileUpTool IPileUpTool.h "Generators/IPileUpTool.h"
- *  
- *  Abstract interface to pile up tools. Generates the number of pile-up
- *  interactions to generate for each event.
- * 
- *  @author Patrick Robbe
- *  @date   2005-08-17
- */
-
-static const InterfaceID IID_IPileUpTool( "IPileUpTool" , 3 , 0 ) ;
-
-class IPileUpTool : virtual public IAlgTool {
-public:
-  static const InterfaceID& interfaceID() { return IID_IPileUpTool ; }
-
-  /** Computes the number of pile-up interactions in the event.
-   *  @param[out] currentLuminosity  Luminosity of the current event.
-   *  @return Number of pile-up interactions to generate.
-   */
-  virtual unsigned int numberOfPileUp( ) = 0 ;
-
-  /// Print various counters at the end of the job
-  virtual void printPileUpCounters( ) = 0 ;
-};
-#endif // GENERATORS_IPILEUPTOOL_H
diff --git a/Gen/Generators/Generators/IProductionTool.h b/Gen/Generators/Generators/IProductionTool.h
deleted file mode 100755
index 6fdd8a3d8..000000000
--- a/Gen/Generators/Generators/IProductionTool.h
+++ /dev/null
@@ -1,86 +0,0 @@
-// $Id: IProductionTool.h,v 1.7 2007-03-08 13:40:09 robbep Exp $
-#ifndef GENERATORS_IPRODUCTIONTOOL_H 
-#define GENERATORS_IPRODUCTIONTOOL_H 1
-
-// Include files
-// from Gaudi
-#include "GaudiKernel/IAlgTool.h"
-
-// Forward declarations
-namespace HepMC { class GenEvent ; }
-namespace LHCb { class GenCollision ; 
-  class ParticleProperty ;
-}
-
-
-
-/** @class IProductionTool IProductionTool.h "Generators/IProductionTool.h"
- *  
- *  Abstract interface to production generators. Concrete tools are 
- *  interface to production generators (Pythia, HERWIG, ...) 
- * 
- *  @author Patrick Robbe
- *  @date   2005-08-16
- */
-
-static const InterfaceID IID_IProductionTool( "IProductionTool" , 4 , 0 ) ;
-
-class IProductionTool : virtual public IAlgTool {
-public:
-  static const InterfaceID& interfaceID() { return IID_IProductionTool ; }
-  
-  /** Generate a primary interaction. 
-   *  The generated event contains all what happens up to the decay of
-   *  hadrons. Decay of hadrons will be performed in general by the decay
-   *  tool. Then all hadrons must be declared stable in the production
-   *  generator. This is done thanks to IProductionTool::setStable.
-   *  @param[out] theEvent  Event generated by the production generator.
-   *  @param[out] theInfo   Informations about the hard process of the
-   *                        generated interaction.
-   */
-  virtual StatusCode generateEvent( HepMC::GenEvent * theEvent , 
-                                    LHCb::GenCollision * theInfo ) = 0 ;
-
-  /// Declare a particle stable to the production generator.
-  virtual void setStable( const LHCb::ParticleProperty * thePP ) = 0 ;
-
-  /** Update the properties of the particle in the production generator
-   *  with values from the particle property service.
-   */
-  virtual void updateParticleProperties( const LHCb::ParticleProperty * thePP ) = 0 ;
-
-  /// Turn off the fragmentation step in the generation.
-  virtual void turnOffFragmentation( ) = 0 ;
-
-  /// Turn on the fragmentation step in the generation.
-  virtual void turnOnFragmentation( )  = 0 ;
-
-  /** Hadronize the event.
-   *  @param[in,out] theEvent  Unfragmented event to hadronize.
-   *  @param[out]    theInfo   Informations about the hard process of the 
-   *                           generated interaction.
-   */
-  virtual StatusCode hadronize( HepMC::GenEvent * theEvent , 
-                                LHCb::GenCollision * theInfo ) = 0 ;
-
-  /// Save the parton level event (when the fragmentation is turned off)
-  virtual void savePartonEvent( HepMC::GenEvent * theEvent ) = 0 ;
-
-  /// Retrieve the previously saved parton event to re-hadronize it.
-  virtual void retrievePartonEvent( HepMC::GenEvent * theEvent ) = 0 ;
-
-  /// Print configuration of production generator 
-  virtual void printRunningConditions( ) = 0 ;
-
-  /** Define special particles whose properties must not be updated from 
-   *  the particle property service (like mass of top quark, ...)
-   */
-  virtual bool isSpecialParticle( const LHCb::ParticleProperty * thePP ) const = 0 ;
-
-  /// Prepare the generator to force fragmentationto in the thePdgId flavour.
-  virtual StatusCode setupForcedFragmentation( const int thePdgId ) = 0 ;
-
-  /// Specific initialization of the Generator
-  virtual StatusCode initializeGenerator( ) = 0 ;
-};
-#endif // GENERATORS_IPRODUCTIONTOOL_H
diff --git a/Gen/Generators/Generators/ISampleGenerationTool.h b/Gen/Generators/Generators/ISampleGenerationTool.h
deleted file mode 100755
index c2197a432..000000000
--- a/Gen/Generators/Generators/ISampleGenerationTool.h
+++ /dev/null
@@ -1,45 +0,0 @@
-// $Id: ISampleGenerationTool.h,v 1.4 2005-12-31 17:30:37 robbep Exp $
-#ifndef GENERATORS_ISAMPLEGENERATIONTOOL_H 
-#define GENERATORS_ISAMPLEGENERATIONTOOL_H 1
-
-// Include files
-// from Gaudi
-#include "GaudiKernel/IAlgTool.h"
-
-// From Event
-#include "Event/HepMCEvent.h"
-#include "Event/GenCollision.h"
-
-/** @class ISampleGenerationTool ISampleGenerationTool.h "Generators/ISampleGenerationTool.h"
- *  
- *  Abstract interface to generation of event samples. Concrete tools implement
- *  the algorithms used to generate the various event types generated in LHCb
- *  (Minimum bias, inclusive, signal with repeated hadronization, ...)
- * 
- *  @author Patrick Robbe
- *  @date   2005-08-17
- */
-
-static const InterfaceID IID_ISampleGenerationTool( "ISampleGenerationTool" , 
-                                                    2 , 0 ) ;
-
-class ISampleGenerationTool : virtual public IAlgTool {
- public:
-  static const InterfaceID& interfaceID() { return IID_ISampleGenerationTool; }
-
-  /** Generate a set of pile-up interactions to form an event
-   *  @param[in]  nPileUp        Number of pile-up event to generate for 
-   *                             this event.
-   *  @param[out] theEvents      Container of the generated pile-up 
-   *                             interactions.
-   *  @param[out] theCollisions  Container of the hard process information
-   *                             for each pile-up interaction.
-   */
-  virtual bool generate( const unsigned int nPileUp ,
-                         LHCb::HepMCEvents * theEvents ,
-                         LHCb::GenCollisions * theCollisions ) = 0 ;
-
-  /// Print counters and efficiencies at the end of the job.
-  virtual void printCounters( ) const = 0 ;
-};
-#endif // GENERATORS_ISAMPLEGENERATIONTOOL_H
diff --git a/Gen/Generators/Generators/IVertexSmearingTool.h b/Gen/Generators/Generators/IVertexSmearingTool.h
deleted file mode 100755
index 173e013cd..000000000
--- a/Gen/Generators/Generators/IVertexSmearingTool.h
+++ /dev/null
@@ -1,33 +0,0 @@
-// $Id: IVertexSmearingTool.h,v 1.3 2005-12-31 17:30:37 robbep Exp $
-#ifndef GENERATORS_IVERTEXSMEARINGTOOL_H 
-#define GENERATORS_IVERTEXSMEARINGTOOL_H 1
-
-// Include files
-// from Gaudi
-#include "GaudiKernel/IAlgTool.h"
-
-// Forward declaration
-namespace LHCb {
-  class HepMCEvent ;
-}
-
-/** @class IVertexSmearingTool IVertexSmearingTool.h "Generators/IVertexSmearingTool.h"
- *  
- *  Abstract interface to vertex smearing tools. Concrete implementations 
- *  apply vertex smearing algorithms to each generated pile-up interactions.
- * 
- *  @author Patrick Robbe
- *  @date   2005-08-17
- */
-
-static const InterfaceID IID_IVertexSmearingTool( "IVertexSmearingTool" , 2 , 
-                                                  0 ) ;
-
-class IVertexSmearingTool : virtual public IAlgTool {
-public:
-  static const InterfaceID& interfaceID() { return IID_IVertexSmearingTool ; }
-  
-  /// Smear the vertex of the interaction (independantly of the others)
-  virtual StatusCode smearVertex( LHCb::HepMCEvent * theEvent ) = 0 ;
-};
-#endif // GENERATORS_ISMEARINGTOOL_H
diff --git a/Gen/Generators/Generators/LHAPDFCommonBlocks.h b/Gen/Generators/Generators/LHAPDFCommonBlocks.h
deleted file mode 100755
index 018261657..000000000
--- a/Gen/Generators/Generators/LHAPDFCommonBlocks.h
+++ /dev/null
@@ -1,60 +0,0 @@
-// $Id: LHAPDFCommonBlocks.h,v 1.3 2009-10-22 16:43:05 robbep Exp $
-
-#ifndef GENERATORS_LHAPDFCOMMONBLOCKS_H
-#define GENERATORS_LHAPDFCOMMONBLOCKS_H 1
-
-#include <string>
-
-/** @class Lhacontrol LHAPDFCommonBlocks.h "Generators/LHAPDFCommonBlocks.h"
- *
- *  Class to access LHACONTROL LhaPdf Common block from C++ code.
- * 
- *  @author Patrick Robbe
- *  @date   2005-12-06
- */
-
-class Lhacontrol {
- public:
-  Lhacontrol(); ///< Constructor 
-
-  ~Lhacontrol(); ///< Destructor
-
-  /** Set value of LHAVALUE array in common LHACONTROL.
-   *  @param[in] n     Index of the array to modify.
-   *  @param[in] value Value to set to LHAVALUE(n).
-   */
-  void setlhavalue( const int n , const double value) ;
-
-  /** Set value of LHAPARM array in common LHACONTROL.
-   *  @param[in] n     Index of the array to modify.
-   *  @param[in] value Value to set to LHAPARM(n).
-   */
-  void setlhaparm( const int n , const std::string & value ) ;
-
-  /** Set value of LHAVALUE array in common LHACONTROL.
-   *  @param[in]  n     Index of the array to modify.
-   *  @param[out] value Value of LHAVALUE(n).
-   */  
-  void getlhavalue( int n , double & value) ;
-
-  /** Set value of LHAPARM array in common LHACONTROL.
-   *  @param[in]  n     Index of the array to modify.
-   *  @param[out] value Value of LHAPARM(n).
-   */  
-  void getlhaparm( int n , std::string & value ) ;  
-  
- private:
-  /// Length of the LHAPARM and LHAVALUE arrays
-  int lenlhaparm() const { return s_lenlhaparm ; }
-
-  /// Size of the LHAPARM and LHAVALUE arrays
-  static const int s_lenlhaparm = 20 ;
-
-  /// Dummy string value to return in case of error.
-  const char * m_dummystr ;
-
-  /// Dummy value double value to return in case of error.
-  double m_dummy;
-};
-#endif // GENERATORS_LHAPDFCOMMONBLOCKS_H
- 
diff --git a/Gen/Generators/Generators/LbPhotos.h b/Gen/Generators/Generators/LbPhotos.h
deleted file mode 100644
index c5207153c..000000000
--- a/Gen/Generators/Generators/LbPhotos.h
+++ /dev/null
@@ -1,18 +0,0 @@
-#ifndef GENERATORS_LBPHOTOS_H 
-#define GENERATORS_LBPHOTOS_H 1
-
-// Include files
-
-/** @class LbPhotos LbPhotos.h Generators/LbPhotos.h
- *  
- *
- *  @author Patrick Robbe
- *  @date   2013-05-31
- */
-class LbPhotos {
-public: 
-  /// Set output unit of Photos
-  static void setOutputUnit( int outputUnit ) ;
-
-};
-#endif // GENERATORS_LBPHOTOS_H
diff --git a/Gen/Generators/Generators/LbTaula.h b/Gen/Generators/Generators/LbTaula.h
deleted file mode 100644
index 85ea175a2..000000000
--- a/Gen/Generators/Generators/LbTaula.h
+++ /dev/null
@@ -1,18 +0,0 @@
-#ifndef GENERATORS_LBTAULA_H 
-#define GENERATORS_LBTAULA_H 1
-
-// Include files
-
-/** @class LbTaula LbTaula.h Generators/LbTaula.h
- *  
- *
- *  @author Patrick Robbe
- *  @date   2013-05-31
- */
-class LbTaula {
-public: 
-  /// Set output unit of Taula
-  static void setOutputUnit( int outputUnit ) ;
-
-};
-#endif // GENERATORS_LBTAULA_H
diff --git a/Gen/Generators/Generators/LhaPdf.h b/Gen/Generators/Generators/LhaPdf.h
deleted file mode 100755
index e3029b38a..000000000
--- a/Gen/Generators/Generators/LhaPdf.h
+++ /dev/null
@@ -1,23 +0,0 @@
-// $Id: LhaPdf.h,v 1.3 2008-05-23 11:55:05 robbep Exp $
-#ifndef GENERATORS_LHAPDF_H 
-#define GENERATORS_LHAPDF_H 1
-
-// Include files
-#include "Generators/LHAPDFCommonBlocks.h"
-
-/** @class LhaPdf LhaPdf.h "Generators/LhaPdf.h"
- * 
- *  Utility class to access LHAPDF Fortran Functions. 
- *
- *  @author Patrick Robbe
- *  @date   2005-12-06
- */
-class LhaPdf {
- public:
-  /// Access to LHACONTROL common block
-  static Lhacontrol & lhacontrol() { return s_lhacontrol ; }
-  
- private:
-  static Lhacontrol s_lhacontrol ; ///< LHACONTROL Common Block data
-};
-#endif // GENERATORS_LHAPDF_H
diff --git a/Gen/Generators/Generators/RandomForGenerator.h b/Gen/Generators/Generators/RandomForGenerator.h
deleted file mode 100755
index b4cb07bd9..000000000
--- a/Gen/Generators/Generators/RandomForGenerator.h
+++ /dev/null
@@ -1,27 +0,0 @@
-// $Id: RandomForGenerator.h,v 1.2 2007-10-11 13:23:26 robbep Exp $
-#ifndef GENERATORS_RANDOMFORGENERATOR_H 
-#define GENERATORS_RANDOMFORGENERATOR_H 1
-
-// Include files
-#include "GaudiKernel/RndmGenerators.h"
-
-/** @class RandomForGenerator RandomForGenerator.h Generators/RandomForGenerator.h
- *  Simple class to interface with Gaudi Random generator
- *
- *  @author Patrick Robbe
- *  @date   2007-10-10
- */
-class RandomForGenerator {
-public:
-  virtual ~RandomForGenerator() {};
-
-  static Rndm::Numbers & getNumbers() ;
-
-  static double flat( ) ;
-
-protected:
-
-private:
-  static Rndm::Numbers s_randgaudi ;
-};
-#endif // GENERATORS_RANDOMFORGENERATOR_H
diff --git a/Gen/Generators/Generators/Signal.h b/Gen/Generators/Generators/Signal.h
deleted file mode 100755
index c7f411f5b..000000000
--- a/Gen/Generators/Generators/Signal.h
+++ /dev/null
@@ -1,198 +0,0 @@
-// $Id: Signal.h,v 1.8 2007-02-22 13:30:24 robbep Exp $
-#ifndef GENERATORS_SIGNAL_H
-#define GENERATORS_SIGNAL_H 1
-
-// Include files
-// from Gaudi
-#include "GaudiAlg/GaudiTool.h"
-#include "GaudiKernel/RndmGenerators.h"
-
-#include "Generators/ExternalGenerator.h"
-
-#include "Generators/GenCounters.h"
-
-#include <boost/array.hpp>
-
-// Forward declarations
-namespace HepMC {
-  class GenParticle ;
-}
-
-/** @class Signal Signal.h "Generators/Signal.h"
- *
- *  Base class for signal samples generation tools. It contains utility
- *  function that can be used when generating signal samples.
- *
- *  @author Patrick Robbe
- *  @date   2005-08-18
- */
-class Signal : public ExternalGenerator {
- public:
-  /// Vector of particles
-  typedef std::vector< HepMC::GenParticle * > GenParticles ;
-
-  /// Standard constructor
-  Signal( const std::string& type, const std::string& name,
-          const IInterface* parent);
-
-  virtual ~Signal( ); ///< Destructor
-
-  /// Initialize
-  StatusCode initialize( ) override;
-
-  /// Print counters and cut efficiencies at the end of the job.
-  void printCounters( ) const override;
-
-protected:
-  /// PID of the signal particle for this job (set by job options)
-  PIDs          m_pids             ;
-
-  /** Flag to indicate if clean events have to be generated (set by job
-   *  options). Clean events are events where only the signal decay tree
-   *  is kept.
-   */
-  bool          m_cleanEvents      ;
-
-  /// Number of events before the generator level cut.
-  unsigned int  m_nEventsBeforeCut ;
-
-  /** Number of events accepted by the generator level cut. This counter is
-   *  used to compute the generator cut efficiency on inclusive events.
-   */
-  unsigned int  m_nEventsAfterCut  ;
-
-  /** Number of signal particles (w/r to anti-particles) before the generator
-   *  level cut.
-   */
-  unsigned int  m_nParticlesBeforeCut ;
-
-  /// Number of signal anti-particles before the generator level cut.
-  unsigned int  m_nAntiParticlesBeforeCut ;
-
-  /** Number of signal particles accepted by the generator level cut. This
-   *  counter is used to compute the generator level cut efficiency to compute
-   *  signal yields.
-   */
-  unsigned int  m_nParticlesAfterCut ;
-
-  /// Number of signal anti-particles accepted by the generator level cut.
-  unsigned int  m_nAntiParticlesAfterCut ;
-
-  /// Number of events parity-flipped. (z -> -z, pz -> -pz)
-  unsigned int  m_nInvertedEvents  ;
-
-  /// Heavier quark of the signal particle
-  LHCb::ParticleID::Quark m_signalQuark ;
-
-  unsigned int  m_signalPID        ; ///< PDG Id of the signal particles
-
-  unsigned int  m_bbCounter        ; ///< Counter of (bb) states in tag side
-
-  unsigned int  m_ccCounter        ; ///< Counter of (cc) states in tag side
-
-  unsigned int  m_nSig             ; ///< Counter of generated signal
-
-  unsigned int  m_nSigBar          ; ///< Counter of generated anti-signal
-
-  std::string   m_sigName          ; ///< Name of signal
-
-  std::string   m_sigBarName       ; ///< Name of anti-signal
-
-  GenCounters::BHadronCounter m_bHadC ; ///< Counter of B hadron (tag side)
-
-  /// Counter of Bbar hadron (tag side)
-  GenCounters::BHadronCounter m_antibHadC ;
-
-  GenCounters::DHadronCounter m_cHadC ; ///< Counter of D hadron (tag side)
-
-  /// Counter of Dbar hadron (tag side)
-  GenCounters::DHadronCounter m_anticHadC ;
-
-  GenCounters::BHadronCNames m_bHadCNames ; ///< Array of B counter names
-
-  /// Array of Bbar hadron names
-  GenCounters::BHadronCNames m_antibHadCNames ;
-
-  GenCounters::DHadronCNames m_cHadCNames ; ///< Array of D counter names
-
-  /// Array of Dbar hadron counter names
-  GenCounters::DHadronCNames m_anticHadCNames ;
-
-  GenCounters::ExcitedCounter m_bExcitedC ; ///< Counter of B(**) (signal side)
-
-  GenCounters::ExcitedCounter m_cExcitedC ; ///< Counter of D(**) (signal side)
-
-  GenCounters::ExcitedCNames m_bExcitedCNames ; ///< Names excited B couters
-
-  GenCounters::ExcitedCNames m_cExcitedCNames ; ///< Names excited D counters
-
-  /// Flag to indicate that a mixture of signal particles and anti-particles.
-  bool          m_cpMixture        ;
-
-  /** Branching fraction of the signal forced decay mode in the main decay
-   *  table.
-   */
-  double        m_signalBr         ;
-
-  Rndm::Numbers m_flatGenerator    ; ///< Flat random nunmber generator
-
-  /** Isolate signal particle decay tree for clean events. The resulting
-   *  event is stored in the container /Event/Gen/SignalDecayTree.
-   */
-  StatusCode isolateSignal( const HepMC::GenParticle * theSignal ) const ;
-
-  /** Choose randomly a particle in a list of particles
-   *  and returns the chosen particle. Invert the event if pz(Signal)<0.
-   *  isInverted is set to true when the chosen particle is inverted.
-   *  The signal particle is forced to decay inside this function.
-   *  hasFlipped is set to true if the particle is flipped by EvtGen
-   *  to generate CP violation.
-   */
-  HepMC::GenParticle * chooseAndRevert( const ParticleVector & particleList ,
-                                        bool & isInverted ,
-                                        bool & hasFlipped ,
-					bool & hasFailed ) ;
-
-  /** Ensures correct multiplicity of signal particles with an accept/reject
-   *  algorithm.
-   *  @param[in] nSignal  Number of particles in the event with flavour
-   *                      corresponding to the flavour of the signal particles.
-   *  @return true if the event has to kept.
-   *  @return false if the event has to be rejected.
-   */
-  bool ensureMultiplicity( const unsigned int nSignal ) ;
-
-  /** Update counters for efficiency calculations.
-   *  @param[in]  particleList         List of particles to count.
-   *  @param[out] particleCounter      Number of particles (w/r to
-   *                                   antiparticles) in particleList.
-   *  @param[out] antiparticleCounter  Number of anti-particles in particleList
-   *  @param[in]  onlyForwardParticles If true, count only particles and
-   *                                   anti-particles with pz>0.
-   *  @param[in]  isInverted           If true, the first particle in the
-   *                                   particleList has been inverted z -> -z
-   */
-  void updateCounters( const ParticleVector & particleList ,
-                       unsigned int & particleCounter ,
-                       unsigned int & antiparticleCounter ,
-                       bool onlyForwardParticles ,
-                       bool isInverted ) const ;
-
- private:
-  /** Add to an existing event a new decay tree.
-   *  @param[out] theNewParticle  Particle to update with the decay tree
-   *                              of theOldParticle.
-   *  @param[in]  theOldParticle  Particle containing the decay tree to add
-   *                              to theNewParticle.
-   */
-  StatusCode fillHepMCEvent( HepMC::GenParticle * theNewParticle ,
-                             const HepMC::GenParticle * theOldParticle )
-    const ;
-
-  /// Temporary ector to obtain PIDs from job options.
-  std::vector< int > m_pidVector   ;
-
-  /// Boolean to control if signal should be reverted if backward
-  bool m_revertWhenBackward = true;
-};
-#endif // GENERATORS_SIGNAL_H
diff --git a/Gen/Generators/Generators/StreamForGenerator.h b/Gen/Generators/Generators/StreamForGenerator.h
deleted file mode 100755
index f1d4adadc..000000000
--- a/Gen/Generators/Generators/StreamForGenerator.h
+++ /dev/null
@@ -1,24 +0,0 @@
-// $Id: StreamForGenerator.h,v 1.2 2007-10-11 13:23:26 robbep Exp $
-#ifndef GENERATORS_STREAMFORGENERATOR_H 
-#define GENERATORS_STREAMFORGENERATOR_H 1
-
-// Include files
-#include "GaudiKernel/MsgStream.h"
-
-/** @class StreamForGenerator StreamForGenerator.h Generators/StreamForGenerator.h
- *  Simple class to interface with Gaudi Output MsgStream
- *
- *  @author Patrick Robbe
- *  @date   2007-10-10
- */
-class StreamForGenerator {
-public:
-
-  static MsgStream *& getStream() ;
-
-protected:
-
-private:
-  static MsgStream * s_gaudiStream ;
-};
-#endif 
diff --git a/Gen/Generators/Generators/StringParse.h b/Gen/Generators/Generators/StringParse.h
deleted file mode 100755
index 8e8b7d794..000000000
--- a/Gen/Generators/Generators/StringParse.h
+++ /dev/null
@@ -1,50 +0,0 @@
-// $Id: StringParse.h,v 1.3 2006-04-04 14:58:24 robbep Exp $
-
-#ifndef GENERATORS_STRINGPARSE_H
-#define GENERATORS_STRINGPARSE_H
-
-// Include files
-#include <string>
-#include <vector>
-
-/** @class StringParse StringParse.h "Generators/StringParse.h"
- * 
- *   Utility class to parse a string.
- *   It breaks it into components which are seperated by spaces  
- *   in the original.
- * 
- *  @author Ian Hinchliffe
- *  @date   200-04-01
- */
-
-class StringParse {
- public:
-  StringParse( const std::string & input); ///< Constructor with string
-  
-  StringParse(); ///< Default constructor
-  
-  ~StringParse(); ///< Destructor
-  
-  /// Returns the num-th component of the input string as a string.
-  std::string piece( const int & num ) ;
-  
-  /// Returns the num-th component of the input string as an integer.
-  int intpiece( const int & num ) ; 
-  
-  /// Returns the num-th component of the input string as a double
-  double numpiece(const int & num); 
-
- private:
-  /// Input string
-  std::string m_lstring;
-
-  /// Vector of substrings in input string
-  std::vector<std::string> m_lsubstring;
-
-  /// Number of words in input string.
-  int m_nword;
-
-  /// String to return if past end.
-  std::string m_past_end;
-};
-#endif  //GENERATORS_STRINGPARSE_H
diff --git a/Gen/Generators/doc/BeamSpotMarkovChainSampleVertex-4D-PDF-Mathematica.nb.bz2 b/Gen/Generators/doc/BeamSpotMarkovChainSampleVertex-4D-PDF-Mathematica.nb.bz2
deleted file mode 100644
index d8e1a02692c9dacccaaf1e7a484cf26e334d526d..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 12266
zcmXY1cQ_kf)J9cNTDwNIMiP5P5~JFpMiNrQj8!uTQCm@dcI^@|5~@a`R&1%=s=fCf
z9X3T<)jhs`-}9Zn?s)D!&$;)U_uS{bN7vR<Lq!JzGRLrYJp(bCG5;6+-`|%Eet-Y|
zy}i4B^54ndA5OO2AHE5YOT_8%OB47dC@Cdo_1q)n2*)GoAvF6{7usI&YpvsH`}DSG
z+4gxcC6u&v+6A3;vrk}4A)y-#Z_Y*Z!XFLb>)pPthCb3xs#J^E_}satq@#7KR`~pR
z1CsUv{QUj2!;^;5oogMQmy<<<-sSR&rkOG@5RexqUNPui@sUFINR)PX+w9jdFz^ve
zgEJZLB<{^!u-*IeQd8DKfL2tyQo@Mj0WdOwV%=ukJo9JG`KI@#!jt#4bi>m*!Cqx5
z%;jX(ER@9=!{<0Ih_GPv5Ca3`oHk?%_aD^)N#e){8M6+TOENn#q@|HK$evED%te(5
z83MNQNT!lrNe(xcG=Xz~g><s^m|*4NWP`LR6cUZ9G%+aIbBC4nb8=puhYWc#7Bl=4
zcBBk5Q+Nz_R`y&`=JY=2wKARL@^l7HPKL`@2=$$RCS~uY12TVIks|%|mJ2br(aj<@
ze+}76NSZ?nr*!&~B?zg)96o4#ZSL{GsvVUPLB<hiB3=N6dY8NWpG#q)f9&EE{k_r)
zQ&m(_R$^iXR#>LSDB~8Y=pvPY8xwp3&ZSq$t@DP0*f^3oM5PP{_PO|?IiP*yn$URR
zT3gA0s(7NLKpe)eNg$_<Kbdd1u5~_GdQNYj&OeYgU*(1)8*2p2ENttQUkooG%Z(hn
z$1hAbX9cwv;0;z*bCv13JGp&yRjdKYrgyG7ix2M!<$t$B%|=PjvbSBb*LgWFcL&{M
zwGL}(pjVaoNQm3!z?vn*akAnHaD6nfJPTSSy8?E#G%&{f+ZU0HSPab2h-r`?@~7IF
zzRDFgb+^h?9w&3{&@7EtS(B`&C>m>$ZAy|6n%jaZg8<Rz+y<)B^64oG^y*>T9b+`m
ztWri|X>Q)`B6UJN$)?QKcE+Dn$(anJYT7p4i3hf*>J48*&0=W|p_T(RGYcjD$<T5^
zuvem>C#J@2+}0JG-zaE9N=<2f_ojZN$uc{a6WY8twTVZOr|Q&##_vuypjv`l6$n%y
z6zGyIh8#IsbP#e)w=9q!Hz=_855T=0yjnA+IilG@%~eoEj@vAa^vZLzSF2zxN#N>K
zs9+<cd3I2PQ~+<zQMD-0yOQpmi5?Q<k`Zyk_8-x9<`^wMcXHs2B;Y<zH*|Rne?~Sn
zq@}}_*6!#=C$-7^{r*X(9GsadF2>+q%wVFZ`RkTe)dMAQpyUYeXD_q7b&BpQH#cK*
zIB3;&VYw+;(n^NY{T%tc)m8WMm9en_SKC(Bn$`jJwt+T&PJa@9Sa&wf?`_31VT&DE
z|I*5pO4EDXk(@G`o+&%rS0HBMOJhD`1q$NgsuGlJ0~DZyp2}$}NGJcN8_dVQ#@`tG
zfXNJu1da*U$J-g<eCXo{zToziDN>T8Q2e+!={jwdq#_x9NHF*oihgl@@Z;aQozwll
z_ebyLaOQe;e~DAgZQ{UsVecKr8CxB~4^dV7j|v`NqP&^;*q5%3x8oSD|Lu?WeW4KH
z5Om7z*3b<4vC<8P#-Wexe5%uhsEJp7>C5*DK73n`(yy*7hZE2U0HH((>;@ps|6o5I
z0Scg)g=Aj4$MB5s#hW7ac}S2~G6;F}xI`{kdz_lzkd=wkWpG&OJYLGzz7yZMK6Gy^
zIV~mgzk6H%870-%FAc1cT?Id1Xm7T|bIdM2k8>HiD9L85RAxOjIvOTVl23{O%1D9`
zIRxo}lx(L)Dj^G4wD81@Lg4)e37}*c#2^zT$ZQ4_yTfxUYE$jiuWNs+{!9*kd7+B8
zUi<M!*tDZX|Hv6|bJWZ-tocSGdq>-d2BEg_9nelxCD2+;1rK)|TO32kr!F?;L`3Xi
zX1@Odyk8Bm4RPERmz+O)@!GJlC?n**DD#Ph;U7y;Ru`uF5Yw@zKPFS}N5#sXe(!v<
znr)V&aN*PF%r;2kNX}};!B*$Q22Wq{aasaQiAw;=vzX3_v%;B&Vs%xF&6xr9S!_Jq
ztfe|BUms5196WqD8A>}o{1o}K%aPbGve7D`2Z!syQ@F$dLwy$%Q?*OP5PX;0?nyN3
zkonu&{O1u|;=U?5@oabQgs5l$h%5%n5=n87SXk@l!eY3lUdC#Q(?`-1-`w1_RDxNC
zTc_hzBYu27qlG!P*lm9i;|i&+CGY`z`UIq7S<Dh++*HKHVDa(m?@z8-oEFhq4%RzK
za8_10TbwRPa&%$!dA3^pv<_T`AEAOKz9EqknV4C%OC^#+9gG&by0q%h#L80XbeUYZ
zg}xA$lw^P@cabKh6MbfUJYuw@_ZL(W3t%uj<Wp$R-EAeoiLv9i6E?0w|JIOXuHicm
zKB03U`rK6TFniJpcwCh$t;x90Oh!a{nKI&NHQ(O;f73O=%jV=vx<%z0vEy$0QR#`?
z_*{;Bj#5)dYaarMM556o;<$`~LzS_AA|?_4=6&Tl+)mnZXg9c4L_^UR>R%92Xb*m8
z*59kpiml>Q*6avw{mkOOaZRqr7?IK$Jb#(<3YJrOGrebNv)1}j=R$4!KQE^ckZ3FH
za=(4>%cHfR#%c0)K}K!m#=87=Z>>=9FsW@cSN%xJBjic7nzfC`CF!l8<)vLtd#jzf
zu^=^A?Gu?kVswH()%lgDm)SCbrCf7^afi_?RFwYh4KY2NB`EOy!J&EGz1rI~9o6rD
z-1d!<+U&md_edc(bi4V_ANwDzlV!x<u0Ph_!+%DMehJq!*_BmEyO)HADbv2`zz_%*
zcB5a<kHTqxe{6&y<~u62Xgfc?-gjK=bfR_rLX<~C#C_P<1mNj(*cR|}UhHH{UlQw=
z$iRGe)@Yi+V6di=b?O?N=C`YnalBLa)YHum@>$GXT98xQSx>f}Wj+;@);ua2oDTJ>
z7H-`XJnHYwPJJXLmxsFYAf&dVVqfkFwE5tMwNxl>?`=;{Z$eLo|BaLJPAT&z;~m$~
zr#&ruXU(I=4U0CjR^*2243&&Edkyv0fPl83>0r^b#b8ljU^)GXA#UsV$l<EGy1HMh
z%7j#8;C;5a-9X>LiZknygMVOZrIH9$H6H5~JPYf(7JGK(QB2yK);9w|4vuI2dtH~!
z)!mCW6SXcY_s*Yq#TmQwFei)dE2%!dwAu3Ka^P;PW5G9pmYar3Dw{j+XWLg>kB?ed
z-05xgA}(~Ap#8$K?YsqOh3pD$S*MNVd<yCOINLf~J3sy`q&97agfuqL0k|Xe69@3=
ziK@y2H81Xu?tYE>@595_Wz+x3+qpj1^0r=od9~C2oL56LXHpavrY342Y34PQbU@we
z-dGXj0{h+7CC1!ARnA`#j68W>H*8{pJoUKi_aECCB4`jH@U^UWbZate|I&EhUzC<=
zcG283>t4<2fzV{10m!=n51)YuB|>xm{%wCi7?<QMCw&zkD;CY)Tuwhb{{F}M)?n{s
z_2#FCoc<XqzU|nh8PpcFj=u}{i&R+oS98@iXurAh#_9A~Yp|E>4BRqVc3znFpx}XB
z(7{2@zY$Byle)n5&l?^Guj2|{tP$XY^!Uni@dU#bllRD8kKi};Ds))i>0_ps_qo{h
zlBF}5DFZwJg5Ixo*IT|XE(`8v96q>jo=3gB!1SG~tfFF7Q-|xN9)}1hJt=i`vPgy5
zX*f?`2AE0cNyF|uS954v$KCK>AK0e#P4~TR%FM8{&?wv_zmqIr-DT6j4vaPC5|G0P
zgoE#TsLS!Y!?vw;vbmC6Ev5Zn-RK``*)C-=#z;8hM*cSid4b_188@QaJdij5PnJU<
zkN|zG9y9%Ymcn3gx?sEIsAh=7Y}NZ$7XwoEpG&llyfL7zf*SV2Hp13-b7+ew*|4=y
z0q2R?$*(US&fXgR{N2Lw&(D;u5rSX?r7uyQ*0_om81*7A7kInBksM`xS7Bz5lF~0M
zE61NQz!~SX#953NmwT7J@h9aWPnhZShXB)i8TYGCU&Fd14(_qHH})`@n@jIl`PmDc
z6X3Y(t}f6BCxK<?^WWEf%PBL1E8e-^p9l_yqrmRD-U3G4?kJQfe(lghc-)<U02ENy
z)r1zx0`Y4#^J=UUD2qYXUbezj*qQ}aSHT!6=%wB|N;1Sa=Qj2#xK~%&Ul98LX0rX0
zesaywp*y0|LlLrE?&XTJx5#hxlhP=##qDQ}H~Y=`*UUFT7VEy;{QCOKTG5O9hd=-e
zWroCy#-fEAv#o^daU&=jZ_r%%43#8+9y5|}wEetw4hdC}G`6!fE06)x!OmnFMwNvm
z4P;cNRt!{fssf4G=mM-2B}c(V#Ag5l0SUQH<wNLXTQY(&GPhC;YJpX-8Q`jnENPJ&
z?J{C6#2f(0ZMq>Jk*`ebm+?fR(y>_B%E!%r&ip$0xNhMa(c)JmKN(-Uil<M$u#WF@
zlSf;O`Amo;;&A0HH4C{-D2#ufHL%v!N~T}N8#Pd~T{G^50?%Sp$z$$?f&PU%yQ-P#
zNwr?5y<bBE?ooI9O}6@XiFHDdk<wA7!l8oM9Fuo5c^|#5S4%8@@>BN|@Ur7+sg%zj
zH?nEMB!Z_YBP;0!E<!IJagWp8(;QDz6a8i?hoc;&t#8EPc$MSvfDAS(?Zy?L6LHvz
zYMf>YwFQjiQ(pGNvS&4Xsw!Ovy3`)pCDU8q{CC~g9VyZ^aW)aKzRfSQzWMF9uq!3h
z-*x=O$k!;DDgB!(6>omt_WfN0wT=I!iXB_P+3qxCyS1f&y{WUdC%u1z-OP|f&kXNA
zQ7u^B^I-99Qd6xH8Le#-1zv{k7*>b9J)~L*oX3zW=1KB%&0!H}okI%$4ZRiL^-}Fo
z-`aG@qB|7`p<An5TKBSt?@?=iLBCSF<f1cemtnx(#1UB@Q*i^<LV_t&f^S$^LqYZ0
z*w6q8%6G^PNAk&ortPhR=emkE9D`S1eL7wEr~(*ivO_lE8XGrixpY|KbeOqxn1%da
zHOtFpszT&BJe@tOP#ki)uPT`w0-4340b<<oTxndf3|$Y4CieUJYEp2Ah3n7msH+B(
zhWk73E4FV15w#Xc*IITT)$WD{$+I^>&8oqeO3(cc82n~X>@&{-)M_(a2tPkvPJZ7^
zDbF3*5nrXrC5!U4Y#e+w3b&T7!wxqnUWJ*N5@Ohu^|lBxm0abBm|?H{FIWS}aK$ql
zw61B1Gk}dbXFXWS<9XhbkPn@mXPw3f87pruE4-DJb#*+KPVv<L+QMQlZY#hK7a|L=
zK$M#;L5ch&&K5D`wH{V6Hdbb5X32jxfi`GO-Z&dfqVfPW-82Ztxs2gQR?AoEV=}$9
z`I%j&_yx3cvMj0^M<|vgmS#p%0|iDiH$~q-Ts3$sX>6Wmgt2lbag(ZTb87<&t7;k*
zEO8R^Rv3Y*7H*B_+$4FvMpLZOdHEb){L0bTDvX&+n}bVNH{R^At%>Zm167|`iYNf4
z6W<w8l4r0a^%~=fFht)gStH~!l8QDaxzAhj5%BU}qeOzu@jwc{CSu*by1Ak;9tapG
z42<{#XY}5x8W&oDEVL-^ocV!NA1b;MWZZaAm4blfLbgW`@}aK!dguP>CGzTx6E-fg
z^h>5TmuKh604ldvD#<~_m3m?|yQL((&{%@XKI3j_F{3Y~J_s`sk?A8L1S&|Sc0D#r
z6#o$7Ou#lEN2|k9^)8{niYLbzNeP)vj<+bWHLj{6!zsIhJHx(bo6oOB!NRmi)<RNB
zQo#I(!ATR705r}F<;1hLbq1R#kl6nGoG2u%iqgAto>-og$jFd5GlEG<yeNa>=3rvv
zq!Jrv5bm-Fd1K+^%#Bwbf}du6A*-v_D(UHDZvIb--oU^V@4&#&IwekFHFbkfv!RVS
zq<>OQp;>^Ay+6{P_x#3(u+4Ty+Xu5=>o*%VwLC$O!S60eJ`z`NwQsYNyMG#W_<r<7
zQSQ;VE2wxIrcv*=tMRkOc1(Esvkh;WRpGj-1U9$dU<H8^a>o)W74F~!BOvJ9<(#K+
z9UqKN!&8&Kl}pM0%4Iyy$+9$X^r2=Cq;f6>%<v{&n?3)>uyUU|^sm&%`-k_9Sv=`;
zbH*;l#w_tK4Tz|Mv@w+!GL{XCTo9gtSy=p3zZ)54LMeb5EDTI}zgd)6mVp(gB7hP+
zJ|eS+usMMygYtqtVLBjFSp@N8@(};@{YLkPu$^xMpDmVA6jd|f=G<XA?Zo$>U;u%V
zL`j!t>19KVmFQa(g1!KnNU4PAxeCe1$mbe`cT`YRy25O8P93W@{?>B_AEkQ<a~rz|
z*Hml#xOL|Y0?2&m*tB`8>`SEHNaSsL(cg;vQD7#o;kO?ZQUAqX`|NQfdJ!_9qhq1B
zVIviy@u7oq`uXVIewOeE?u1(m9<s3wp>LFct5;W-S35G}5kO`&F-AR`gS})?cBHN>
zXMcgFf;CLepwNrgL&h^MVSR17KKYyQr?A4H_at+$aiJLN$@ohbITf~|1lHR%Cr0`S
zu~g)#jO%-O0gw=*q;tJEC|+gLNSuPrRS+J&rRyq>gDtsZj1`1925Q_f)Wm*bZ`Jt^
z5By%t9lqP26!Ci@>i6RIZP!!zxj>a(Xymd3H1Nqz$j`-4M{B^!nQWK+_G*UZfJT|y
z+x1!XvFVw$ZPAb$9Vkz{X7DU{)5>|_$*#sTP(Q3>QReMtf6=w8s_pJ=xr=gY2fsb4
zWow39aAv!XTCJlVVE=4u{@&?9*?ercmgo%u4~(XN;R(zs^lp%ExxuHy<d)vt^sMdO
z?1_(~fjynBj&fNd!(qEN+kPpVokjTe;}qleqwU#h(cs<;%|m){Zop=?rvHU&&$5&I
z-+Xk1lKlq5tyZ;E(rWWPE^+s2rCt*v)>#l}7%v4!|HY8Rn8lbUcd=_8BI@pi`mX$8
zojE*63K}Vc!MCGF){*F$DW*oMqxF9CX`day=h5N2Zn@W8pXQsv?O(le%}><}-u7yY
zrVVHms=NAgMQ27$Y`iQ7f{vN8lA+If61cf$d8E#C(z&)X*i3hvO%AkIaunU!o{7&=
zeLI5jfz|n&R8?yke?{nBho$E~9$8ykI|Q{K&dYwT6Qu6O>=rzG8uBEx0FyIdIM=5=
zmDO|l@GrqovGj4Xr-U9W_Tqb{FAU{j-~m6(fXzf|-$}wwr`*eS<w93gvsw<LIO*^Q
zvfSt4rf><)_|`RfI3W|BB^k8ptfSAzSCs-11;|Pl2mNC*Vx^rDIk?_&^Qc^shFfry
zOqH1FJA`lK-8WaV&Z{tieR3=}3O{4Yl(@D3Lh+mC?^n}m*B&JZK7OaRqizTM{afp3
ze9<waV>KA~<%VQIcmHzhpzH`Spq2ks{Rv972{f(M|El@qPGQF0lE#crm69uId8pRd
zrUX$_BKo#a%D{nLUF_BV3Ov-v(qh755m20a@GK{|&CnZhvoq{d82*qTSv$~Z7!1F(
zqG}C=jAs%GyutK-O6CYq7hzTj_JZ=|8I|Ny0Un{!JQ>Ghv!Rws54%&EtEnf4UC<3!
zTlzuuPF42}Z~EfEp&PR{hyk(fu#W$izn>4B(k#f9lw1^>EScZCd9`+ZP(;LcVq)Om
z1GE~UnDkTjX@u^|vIw`UL;?5Le)OL<SL{sxk1+C1@e*eN6N#2nbDlU2P6fu!W8>UX
zmbe=&#uDonazHL6!tT;oqP&ars!1IUgbPw6iv;8ciiCG7U5<MbN;tw}yxn{t^N1`T
z%1XarI;DXnn+xq`i^o~b8DMpJu*N)YX?mXN!YVo-4pK8IpC$<^13809^i?^Cow-Gy
zKCDRsUgOPQo|~f}Yt<vp5HG_E2JpzBENB=OA{wx4I@E-H3CcO24Wc9)xs~V0P?BZf
ziC*b7V|{VwVRHsXNOyzsRa~qtBP$x@1_zi!(Jd5VGkCW99f|P*2C{{KF_{2VAdoG}
z2>_~uP&o&|ss&wDfRhALmGQ#y?qG~O2{w~MAQ&Mr|01n<6r_j6NRO)Ik3o$TT&-Lo
zs&^nYoL1(tSSv`yc<HLuuxDexe#0FXpQ@EtjpfGaMy4Yyl`xBWVuQJ`O&Tv0kF;Gi
z7pSyqz&9|;uOulGiR6{^YBW{SXC}QuRft5&Z^YRoRX|<gLy1BVFL}b!l(^dp8z|0(
zS~bO!Kv_ZXz*#Hk^Za;s*fIh@E$_2KlE=MxY|`M^WCX{I9?smLrVPX1ECO1^j^DY+
zLdA}AyJF{-0p&d{mMu1wSeSD?-qNQg!JU{Uue^Z52=^JGNMKuH3w@@%+Gn}St(l4^
zqlA*>ao$2$3?>b%fSb;AQORb>O>yg?mXZu)$7Nm2Ed}F;Ic$aHX(&zsWQ!#GJdi*W
zHZ~?h@=0>eMhYsBpOLW7AK&3SBcmdYPIo)TEM@k_R_IF&X;iCxq7}=G58aMs#3xn6
zv)LA^&u`@A4Zv2-si>L}M;fZYHMt`z^cim$v_b|Novq7~86V%HSmQOL^h6Xo_Brz;
z0xhHA7)YCe35%d01g~hw3_N$PGdauS##E;qm(_er4+1j4>NM~Y4}q`@J)QXZ=XFQ6
zugmz?$obLs2NNF9z@W`R#m6iU0#oth9-1|waj7*VQX^`0F)Z9^Jx}uPq~)T{#Ngf4
zRPy$~uJ8WFnwq^2omE?!k&9h?8nO+07mG#4;&}c6X`}a5mCSh?byrpFM4`z!L!oCe
zwe^QW1MaTs4zBP3a7%#*42#JIH>nCeuDM&arzLQnfc_VG!;~yA25Af?5ZN-XfO|P^
z|9Dr|nzzwc0I!+)AR(1oG&uA%VA=7>lG2qIXB}IMbz%1vJ`k#Ye!bW7B{FrOOJed_
ztV4ix<xx1gyZr|XlB4_f6`J=#9sE(o)eI^`PvfPwc*|?PkboNxk^&z|R-(8s`Ejx0
zLzCWb1=j&`nHX7h#hG)(qcO_p4$@sa7ko%(V3DR>QE1V9t>>4$t*tp)hCgsB-4eKT
z8HTm#RRwclTm<>Kna)Y%APX|{6ablX6`g)JE#(Gl&vs5n{Y>5K+BUkMT0Hw)ROrjn
z;O|nxm7_5qu%7%|9%@wq#UW(X+}H1l<*5^l9!rWn)Vwd5?YeW^E8UwaMhL=PmoCk2
zaP;wpJS^R;<8w;c<xrl(Jlr=^U5j*B>1)e-<S0GXnP<?o|LU#Y*g|22?!YbVaZ?+x
z$<kmOd9{tk^(w5NttWD8gLhc={orh;zNl%<+r@}iHP-AHFQN6p(;t@$zrWM->u2`y
zJt<bjd)z!*4I3W`nbST0G5UenEx;_EzWgm=oBM8>$yNYn;Kz*kRYS#xv|DJYaQ>Tl
z&9r%&keTEG$<GO?L>VJ!o}{@W=h)>J7e=mM4t@JRfYs!(PC~)Qi8AG3t+KJVcQwsI
zRA0Yv{2eU);q{x5W1&x5#<%Xb8q!U;@s&c8@_JtpcK$eJKw?_%!q$zCabDmCf?d~v
z`zVB}VB9t{Mmt-`u|4b@ES7XmOhsAj)|^TNfyhtZI?i{F4igpU=;Ozhq}3KmazxwL
zuWb^K{9FDDKwHmqf4$9>-w_IfUJKJ{op9sYCju}a4wgPB>Z$y5uZ}0<EJ8tT&zCwY
zgqV7wuBj#+oHV^<NGJQ`CdN9MxUCdv-e9_+-eC%UrIwzS7vTv{7jn_*cbBcbxXr2C
zt@kv3>tMgzLyn~k-rR4fkflB<Js+{4h!<bOT*-bN6TwHgRiRq+SYt=q65$HEEYdYX
zN|q9k+?cys801jZ7=%Py+xA(BMZ1fFoMK%&I^uze^)uq763X4QPj|@=m?kxhwdad?
zrM1-Iwv6l+T2a@WHm{z%oq1sO#IfR@gqYZ+Xke@29kqoOp8G7H$MlA0YR#M&)|v4S
zYhCjo4(p*WcE3kG+PUYw&Yc3b)s6F1sgjmAb4gEk8HIxS<Ibmw=<BDXf=XmB-%2^j
z3+vc|Oq)mwlK=)($AW-%E2n2L=dwG(9+d4;wWZ(}^7s<X6*sC_oV~7;zO8bTT#HA4
zYW3Xk!M)O7wO2r;d=e($$g6d>_tU=*s}L-bwfdQh{B}N6_?WYj(?6*u(s=tWcHhyk
zzfO3n*4xAKM4_kF|FJ-BnD4H}`p*{{lIa$yPmjMxUa9TgasDE8VUjR4i@CYq*8f5w
zEF(g{S-XXWv9fHcqhm)5<7DdOdxaY&mj5!=JDFSVN)lwl4=XbB#E<4QlMO1QOa~nA
z&uwj{*QL0$o90+sZ6(T@ZQSPCGaDs6I(*qUCXDn)m|B;*9XV@FplX-eI#mqVQ~Q1%
zph`c|ng&yQYy1zrP7}g6-WVo{2|qf7e=n((ZXkQ7L&`H2+N7l&tDV^-64^Ft6&+g#
zylm<R+#Gt$6Fk7*4eYa<HcnTj<zcW+IXBjt+Bvt}5`kT-(9Y;2Kx1g!=#rFj(O_cO
zK#TdVkgvbVg{uz<bOlSoUYTs!^Q65FsH^!{KlE`>&<ziD)fBnbQ3uVIkf!Zb-u#ab
z0(81FwXw!rStBK)XU{^+1k=ux&%b{Oom9x|>)&nQiq>W1iWOtH$0Ru)5P5aqxJub0
zQRHA~+gvN!wB%a<J{yN`(&Lbb*P<BncdcKGDof46#71SmIo$6$tJ%M$I_Af3UXiE~
zLVI~R8+3V*===4_*-CcUr;2LLfDHAsCqT>Bh>ZJ>Tr=zE^>2}YrfGXeqB|{yEOi?n
zCe>-Kx0zTOZfyAN*B&^SmnIhgo;oHxUs+dr$HaO|^VZKvh4AFF&Do3UUuSuCps61t
z-@0LzV<yyhlX8=&jBa0Y*T0u|TnF=#&5%sPXOYK;dbp%F8Edx+8-e0F(_B}NNWIAG
zCh4jzTP9h{WqomW)7WL#hHGJkjp3F@<Sk3{u2H?MBhkE7?iIP%t#Rp&u)d5hnX4!A
zRj-=KbDz%acOxPLb|YrnW{6Izpu3^@4j4n#I!(pM?$=o`n0lMkD->YjnHLhumHFI`
zEru}P7Uu%kWSI@#bAm4{tn$J1$nZVAOgZeCxs|2!6Hb>cwR6N#Zu2EWYK~XmN_^ZH
z;5kxkZcc?;#C0;|TWjl3bi}s9TjaUeDTiyVMTS|-D`Je0idi=X3Yj_0F}s_uDu&k!
zpn@so5pfqb+MpE@<d~}=jOX3<3et}^vs-!sn()hg2z&PHkDmdYQihMo88I&BsiI1n
z3ND&g)~d5LCXVhK-*W@t1$szVR0AQ9t9K1@pU*{`C`TJ<q@8>HBIJHJ=^%34K4K-Y
zZ1qdE(SFYtJrkzZA5$4;fh9}h#j4?-lnTpp4rP;5t{ZX%MTX&og>-AA-aT*8`sDc$
z!#e!LZF+Ts8s~77tC`H*eLiVJ7P}K{byNZQ_`oDzWBOB_I{0KFBd{&@>QW=Gl&v|?
z*V--S+U=9Q&!>imE`PNJAKQ!WCs%bwJ-+UHdgU2UD9?Ox#k@1S!w9RRNJrHVhtDUY
zMTv8D!8g_)9*Y|iq;_B31Jo2f?b)3OEd9V`0Y}KFu<G8L{BybDGbJRcyhBjX^(o^P
zoBO?QWgkjd9lK-h6-U(-N8Nq@=);!86>|-?3nN^TQj2`b0N#Kfuk$Z*b@zz<Ua-4B
zN&raGSM+*BciuhA?X(8QFZB^z;TXYcl^;(>-h68|0b#LGWj_q;tWjzvgFQRz#SeIg
zoU_@MMn1neGcgz1T~}of9lR8<nmSUZJeb{UuCh^NQ>5jfrqaJ?a52p9uy^qBxl~y#
za3?q-`{M<~@6+V(VFHHRRlgE$=VyQ6`s4Ym(eSJ1!#9x(zx(gGn|~AkPwn(=GQ9<l
zDtB49jJsLA5^>q{OZBpnr(^$n>*kwr%h!4$%$J^8H>9<A9bK6}yLZREan7J(4$5hY
z!*Oulf365DC#lA^AKxD;$|e@ba0_d|pUFnU*#TJ=1Q-L1p@f@08s`KB*S1`N$){bB
ziDA1KpUQfXWzQ%G=&umpqUtSC;=z<P=97f;exz}H7GU4nkf&8W874EmLle4M7yU_Y
zsO~{fP;JiCHzl^XweX_1$9`Wgarh0g*tfx2-+lOiRc~uYIr187s1`nB$?G!Ey>lKZ
zvBESZ5UW38_V0s0Cp9tN)8G+<ba4u6ad9+-kIz+b@TT2BL|Z_SH>qD^kpE$)skjrf
zqORUZB6B_S7hTM`JmsxGf%57E;#FZ!&xB$(uq{?Y#Kr5LdqT7kqc+sE^^N+Jx$e1m
zK+7erdX`m|fkBa)*a^Q(r-t&xi%a#MHhONw>vzoZdkzo2e-Ha{o!1hV^MP;Gf=qek
ztgilypKf4KF)!ljG%sAn!f7#&vTYtPm+7koVzH5q|C!+1)^;5qRZlKT{u6U^gS2Yd
zc`HlL;cO6xu&}UAgUkFs)|Y;!?s{G6zW;GMb1fkD9do_yDv4jskijnyG7FqhQ?%C^
zQ{>C?Hd5U|a;BHa`!v?Dc?f~k#C_aNp+@1KDlJW`<nJ1^DfNza?+g%N7VMY$ww&Y*
zcJy@Uv^SYBm|IL2^Cxy}wfFRWr?e|Nf!cF4Z*=(rOhm5krsTtpZp5ic_0BE5p?BW~
zpaCDW>SSp4fzGKh)7xQo_W!!F3x#rWrvs)!=NK+(pC4n`V$`Q3dk?K?6vktp+bX0#
z7cW5ckz|l&S4#u)x6j3jP*;8VUNhf~IPi$IH(sN%4b6L3mJb4)4EmpD{$wrrQd-w0
zXVOsdgXCa&Gz<K?px0;)(b2hRhEq%iv`@toGy(i3$jD|T`s21+KW+{E?8PLixVb-W
zd;jB4UFF6{!|KN`h91R#`O=lW%>5qz#WdpHh3Ux4Rg)=CFOcPsRr!o83_5MyXtndD
zYiis<@mDAhx4u8VPyO7T@Y!&vYqz4y(5U!j;yDo(4X$C9OCsV$z3UNWQ*ILhfQ#qN
zEU7sOPS(r`6#!6X99kvK)n~kGl2{k{@uB&6SY6%_C*4jV#z$-!m^lI;fe#Ue_$-PA
z&S$w3SR04rV`E>vI=&eDvhk%r4~=HwU0dv_kerynnZwUk$*Z>M3Yz$J@cpUgQ)CgY
z`y3@G-KrXdLKz!KB4-+0dO3w5G`V@huIe|lTf>8IZ@Yh)9V<c}@4pSx`ovy6Wl_}-
zae2AJ8C?YY;AUa`Xdiic>lPcZe*zvGK7V=5^XZdcicz!Z+YfBnd_BJY>5l4>7ni%P
zHul$W_eaWaxbx#@2U_kx3B8?E+y_gm83|R(Yj?&RtgY>7-T}d@fmN20KF6!%6~d~%
zUF}gzsk1qIJf4Y?LaF3dFqm6FxqIu86%t&`IN0^$_$(HPEfjjJge0S9QXHN|o|%P7
zIoVt~-BeE}I=YX+)>wEr8465F^+Kg2Ly}2ea%c<{fyN-SZF-uQ^&zDMsAa01#Vl?b
zl<Mjn1Fv^UA<yJC=T7PAIVo^+;fwpDqhA_u%er${u_h^V2}WN;#9>rGlm>3ROoJIH
zOH~1gGlEpg8p)u&1z`o!<wP@qg!+=S2CC1(a($TsY{tzDLj~4Qk;vR0b8mnM08GZ9
zp_p=SysDMe9bUF)8biu8WY%ReuMpDP4tIcUC$B%c(Y~BOR9xs8es(?$F>V2i$4jr6
zD~|!*j*AGi1^VKf*ikiX&k^QwFbv>rA<lj#v7eKGsZ66`nv|CmVROm0`Bild%6sXw
z7%!L+zNV*YV3o02d8H26((a?vJZsZ{X-s+Ll|%hkST>w4^pDxkQ<Re9$2TBU;R($m
zc;V71ddjL3J#n~kNzfq8ZEg%VZh_ONDqJQNcrHv=(D($FVbioSGh1ocvYlBY5}j=X
zS;eDsS`Qof&1E3jh;vW`AU6w<Hn5DeLliuOR@F^@ivrzwvv{SKw&<bH^ReT?iKdCj
z>HVm(Z&7OV59bI*#w>O!6!^Fh*a~V8r$@OX;YJ}!0Bpus$5oLA=-gh=OU{Fp75X6^
ziIOpAU|6Ad*jW??Dv`)zZ+4f{4l_Ouc#F<U>6H_5LS}076bYf$_O;8qdAZb`J*{JP
zk6>Tlz|fpLkZT8}?n?Sb5Dy%#BXy%=QnMs1I4CI_$kjtHEb!7^B`RxI#D{)a&7fT#
zG+7hldFt`S@Htgl=P3O#_l-bfmFs6M%9BIulre2x>4Z|=lmv~%9l77PQ?Bz!y=Q%G
z_re99s<Gy>7+b&_EnIy4>;AI_$?u76H#mD=e7_U*^SAxT$z$G+Hf9mdw}qdP4J6r0
zYzyw-jC3lYW)zHN?8{~>DH}3wXD3wc?FvnCbE*F6da8Q+#-mFdW1Ek7qbi$Vi?UIc
zvnmXPq(M59T7t@U%?IC~%l+;e^ApGmGD=MsrYuT!4|fvo-@dE7dizpf;mVgz)S>LY
zirC&OujV<Kg~xm<3+~<f!*_TIr$eVLW!yV%g;s2B&5@JW6))OaXg2JKLUu{W|6WM7
z_1y5B>)b;zXhU$qo?UAC{;Dxb%{<!IXN)=w?=Id_I^lWI%^-S-`ejK^=`g49hF%;-
zVCGW%z0R3qJ%TpDjFQwK#-pnpIa6?w(bRBJ`b_kLNzp0n<lv`XT)u_lRM$O^_|B>r
zPz3FcvTt#*3?Pe*^P=~)9HW4m$9`sCPQrgPMP)p{r<P~+Yo|}wb8Y_JrB)F4t>@rD
zrTR;4rPV>O5>XEmDa7Kd?wi&sspD;b>uyF}JBf<Kojr|TT!{Q#oZ*5HG&`o5C@*DN
z*KG35e$8SNoAkNd*E<I(IU%()LB$U&B<iG6=MTbQ^as9Qhi^!qMx8OvN9<)SeY?!+
zcR}TG{{%WSm9s<z5_9Xf#okZb%m=g2pAh4V-(xP4PFb0Hu8XFeX&i>IfYAk{q{QNM
zxB5S9?+eo{Tgb#Wruw6P`rsr$P&ryhRnbgof7qyegfrO)D(;=ez3Q8Ha563OXp*7g
zcbk(gNUnj^bA}HBurNY(l=EA0+o4|G;0E#}@&eKt#PZd~K1pqPsB!Gh*M#2I0GPhF
zqjW|J=ig+3w{2b(n=VEuPQVO#wc5TpN9bBi*cB?o+HXEp(#wzNX3qH_#+AqVRhPiS
zV^o*-l7*io?ms^Yz9TaUc=G=7f0WJgFrOGeeAY^<%osBuZ}nP<n6|ip)}H_cap6bE
zus?6F@iPJd=bp+#lz1=HeJ&Hnd{GL88m{Y?Wd6Hd{L5?7Q5gTG`%hbc@y_o)fAIQJ
zAPiyoeG2(;5B*DAhFCF_9CUP~+0`BOsB3vC(alz7;te1^nqWW`l;yL(dT;t8>vOqc
z1RG=Bh6IFoN$~fu5jSW2>%zd}^xv9d%&~?RAH%hap5*>&_`$LEwR@W<A^~~T9%Lh|
z*POXR<<_pZ1jbkF)<e(-S`fn1W&PhY#(th=@t=La&q}f>#UmM|b*b}<uN;3(V%E4=
zPYSE=DS~!F@9wkaZf`OD<A^OoiyA+K<F1{=CV!N4ot=IExROF(&d-klux7DTO1|l#
z-K<!Sd2waq0=J5kfGG!QF@{lZK2^7@N?Q2F7;#3Y!MItqkV6~rvR$o2ADL&2yW^-F
zJ(m3Hm7&GLgYVC8bY9pCBi*9weq-|3gt@QB+AbMH|2u%OyLjL<5CpW`ciekfaBa;o
ztl;BK`!Bx=KR#_DRGO!#Y<Y=|4*gIQy|Lca9WjYp%&SWIfYEY;x&yHSjTKuSl0#)#
zp)~nXLD{3O7mR`27P;SbN@KsaM_?F%iVjWLPrY@7lL3U7Xj0C_SL5%#^Xxh9#E)_R
zEHVi#dr<WW;y@G11&!JifJWUbjlAXQdc0ON0Z&X-@iNDxsyvN9sG8AqoDGlrq4auX
zp7xP`J*>Z`mj8+^6b%gebEy}1b!{`l_tI^{tb2pMMSHSkqS9~F-;9z@fwrXMGppGt
zD<b%MezL`?#jv|&L%J=SssY5C&ytEW5^wTq##;%3AzAg6<Z+>jrShraCR7zBQNRx7
z)~i6x?Q<K>A<xJ(7bplr%R#GnTE44@b2>md(TSPR=Q6A!&X6TN%V!42Lb@}1Ww8{4
zc=@I)0fbxx5@m!SO1l{wn7UO0iNr<>q!KXouWTg-2wvtG>ouS$W6RB8=?E%SCL4~`
zr!+Jmkaj=>22D;}t~8e>CE}9Frml8A%h(jWL1_yCUi~S2@mp$}M4>eNyyI*(!~X!g
CNHA*v

diff --git a/Gen/Generators/doc/release.notes b/Gen/Generators/doc/release.notes
deleted file mode 100755
index 4a3bfd3ad..000000000
--- a/Gen/Generators/doc/release.notes
+++ /dev/null
@@ -1,1154 +0,0 @@
-!-----------------------------------------------------------------------------
-! Package     : Gen/Generators
-! Responsible : Patrick ROBBE
-! Purpose     : Common algorithms and tools for all production engines
-!-----------------------------------------------------------------------------
-
-! 2016-07-01 - Davide Fazzini
-	- Added the possibility to store the generator counters in genFSR
-
-!======================= Generators v16r0 2016-03-23 =========================
-! 2016-02-03 - Gloria Corti
- - Changed the default production tool from Pythia6 to Pythia8.
-   . src/Lib/ExternalGenerators.cpp, changed value of property ProductionTool
-   . src/component/Special.cpp, changed value of property PileUpTool
-
-!======================= Generators v15r1 2016-03-02 =========================
-! 2016-02-03 - John Back
- - src/component/EvtGenDecay.cpp: Corrected the name of the m_imHelZero double
-   property from ImHelOne to ImHelZero, which specifies the imaginary part of
-   the helicity 0 spin density matrix element for polarised J/psi and chi_c1.
-   See: https://its.cern.ch/jira/browse/LHCBGAUSS-628.
-
-! 2015-11-18 - Marco Clemencic
- - Disabled warnings for FORTRAN code.
-
-! 2015-11-15 - Marco Clemencic
- - Fixed compilation with CLHEP 2.
-
-! 2015-09-29 - Gerhard Raven
- - add missing #include <algorithm>
-
-!======================= Generators v15r0 2015-08-05 =========================
-! 2015-08-01 - Patrick Robbe
- - Generation.cpp: add the possibility to generate all interactions at the
-   same PV -- used for signal embeding between different generators. The signal
-   is seen as a separate interaction.
-
-!======================= Generators v14r8 2015-05-12 =========================
-! 2015-05-07 - Patrick Robbe
- - Special.cpp: fix to allow not reinitializing the generator, mandatory
-   when reading events from file (in that case the same events would be
-   processed several times)
-
-!======================= Generators v14r7 2014-12-16 =========================
-! 20014-11-28 - Gloria Corti
- - Try to fix warnings when compiling with --pedantic
-
-! 2014-11-19 - Marco Clemencic
- - Updated CMake configuration
-
-! 2014-11-04 - Gloria Corti
- - Move here HistoSmearVertex and FlatSmearVertex tools from LbPGuns
-
-!======================= Generators v14r6 2013-10-10 =========================
-! 2013-09-23 - Marco Clemencic
- - Added CMake configuration file.
-
-! 2013-08-20 - Patrick Robbe
- - Generation.cpp: add extra informations to the xml log file
- - SignalPlain.cpp: fix the generator level cut efficiency counter
-
-!======================= Generators v14r5 2013-07-23 =========================
-! 2013-07-15 - Patrick Robbe
- - src/components/XmlCounterLogFile.cpp: fix cross-section format
-
-! 2013-07-07 - Patrick Robbe
- - src/components/SaveSignalBInformation.h/.cpp : algorithm to save
- in locate "Gen/BInfo" the string from which the B signal comes from
-
-!======================= Generators v14r4 2013-06-27 =========================
-! 2013-06-26 - Patrick Robbe
- - Fix coverity warnings
-
-! 2013-05-31 - Patrick Robbe
- - Add interface code to TAULA and PHOTOS to suppress part of their outputs:
-   . src/Lib/LbTaula.cpp
-   . src/Lib/LBTAULA.F
-   . src/Lib/LbPhotos.cpp
-   . src/Lib/LBPHOTOS.F
-   . Generators/LbPhotos.h
-   . Generators/LbTaula.h
- - EvtGenDecay: suppress PHOTOS and TAULA outputs
-
-! 2013-05-29 - Patrick Robbe
- - Inclusive.cpp: fix problem with release of particle property service
-
-!======================= Generators v14r3 2013-05-16 =========================
-! 2013-05-14 - Aurelien Martens
- - move the call to setIsSignal() in SRH.cpp before the call of generateEvent
-this allows the production tool to know if it is generating a signal of pile up
-at the generatio time to avoid double storing of parton level HepMC
-
-!======================= Generators v14r2 2013-03-27 =========================
-! 2013-03-22 - Stephane Tourneur
- - Minor modification to allow the inclusive production of baryons with
-   no charm nor bottom content
-
-!======================= Generators v14r1 2013-03-13 =========================
-! 2013-02-13 - Patrick Robbe
- - Fix compilation warnings with gcc46
-
-!======================= Generators v14r0 2013-02-04 =========================
-! 2013-02-01 - Aurelien Martens
- - ExternalGenerator.cpp: add call to initializeGenerator, so that
-particle properties are set before initialization of the pythia instance
-
-
-! 2013-01-31 - Patrick Robbe
- - Use Gaudi random number in ApplyPhotos
-
-! 2013-01-27 - Patrick Robbe
- - ApplyPhotos.cpp: adapt to new photos++ interface
-
-! 2013-01-21 - Patrick Robbe
- - EvtGenInPhSpDecay.cpp: remove Photos functions
- - ICounterLogFile, XmlCounterLogFile: add counters for cross-section
-
-! 2013-01-20 - Patrick Robbe
- - Remove Pythia6 from EvtGenDecay tool
-
-! 2013-01-16 - Patrick Robbe
- - Add ICounterLogFile and XmlCounterLogFile classes to store in XML
-   files the counters that allow to compute the generator level cut
-   efficiencies.
-
-! 2012-12-19 - Aurelien Martens
- - Fix SignalRH for pythia8 so that it also hadronize pile-up events.
-
-!======================= Generators v13r0 2012-11-29 =========================
-! 2012-09-27 - Patrick Robbe
- - Added an option to switch off the reinitialization of the pile-up
-   production in the Special method.
- - Fix the bug that events are not smeared (vertex) when there is no
-   decay tool.
-
-! 2012-09-11 - John Back
- - Added the use of the namespace Photospp for src/component/ApplyPhotos.cpp,
-   which is required for Photos++ version 3.5.
-
-! 2012-07-13 - Patrick Robbe
- - Use LHCb::ParticlePropertySvc for the new particle property service
-   name
-
-! 2012-07-22 - Gloria Corti
- - Fix bug in FlatZSmearVertex where the location where to take the beam
-   parameters was empty. (merge from v11r4b)
-
-! 2012-06-11 - Alex Shires
- - update EvtGenInPhSpDecay to allow a configurable input file name
-
-! 2012-05-27 - Patrick Robbe
- - use new ParticlePropertySvc
-
-! 2012-05-08 - Gloria Corti
- - Fix linking problems with boost newer version from building with Gaudi v23r2
-
-! 2012-05-04 - John Back
- - Changed src/component/ApplyPhotos.cpp to use Photos++
- - Removed src/Lib/photos_utils.F
-
-! 2012-04-16 - John Back
- - Some changes in EvtGenDecay.cpp to be compatible with the trunk of EvtGen:
-    a) use updated static instance for EvtGen/EvtDecayTable functions
-    b) added EvtPythia6 include header to still allow Pythia6 initialisation
-      (for some reason, this is still needed here for the initial p-p event)
-    c) commented out photos external fortran function calls.
-   Branch v11r4b is a copy of the trunk prior to the above changes.
-
-!==================== Generators v12 series on a branch ======================
-
-!======================= Generators v11r4 2012-02-12 =========================
-! 2012-02-12 - Gloria Corti
- - Few changes in Generation.cpp and GenCounters for counting in Pythia8 and
-   excited particles in November by Aureliens Martens
-
-! 2012-02-04 - Patrick Robbe
- - Fix decayHeavyParticle function in ExternalGenerator for generation
-   of signal Ks.
-
-!======================= Generators v11r3 2011-11-11 =========================
-! 2011-11-08 - Patrick Robbe
- - cleanup of Generator code
-
-! 2011-10-28 - Alex Shires
- - Added IEvtGenTool to allow sharing of a sibgle EvtGen instance
-   between DecayTools
-   A EvtGenTool.{h,cpp}
-   A IEvtGenTool.h
-   M EvtGenDecay.{h,cpp}
-
-! 2011-10-20 - Patrick Robbe
- - EvtGenDecay.cpp
- - Generation.cpp
- - LHAPDFCommonBlocks.cpp:
-   Fix coverity warnings
-
-!======================= Generators v11r2 2011-10-17 =========================
-! 2011-10-14 - Patrick Robbe
- - EvtGenDecay.cpp
- - SignalPlain.cpp
- - SignalForcedFragmentation.cpp
- - SignalRepeatedHadronization.cpp
- - Generation.cpp
- - Signal.cpp
- - Signal.h
-   Modifications to skip event in case of EvtGen failure
-
-! 2011-09-28 - Alex Shires
- - Added configurable call limit to EvtGenInPhSpDecay
-
-! 2011-09-28 - Patrick Robbe
- - Rename EvtGenDecayInPhSp as EvtGenInPhSpDecay
-
-!======================= Generators v11r1 2011-09-19 =========================
-! 2011-09-14 - Alex Shires
- - Fixes and new parameter file location for EvtGenDecayInPhSp
-
-! 2011-09-13 - Alex Shires
- - Add new DecayTool, EvtGenDecayInPhSp, for reweighting the Kstmumu phase space
-    distribution such that it is flat in q2.
-
-!======================= Generators v11r0 2011-07-15 =========================
-! 2011-07-15 - Gloria Corti
- - Apply pattern not to build on windows, so that conditional use can be
-   removed from GaussSys
-
-! 2011-07-07 - Patrick Robbe
- - Fix coverity warnings
-
-! 2011-06-23 - Patrick Robbe
- - clean header files
- - move IDecayTool.h to MCInterfaces
-
-! 2011-06-22 - Patrick Robbe
- - Move IGenCutTool.h and IFullGenEventCutTool.h to MCInterfaces package
- - Move cut tools to a new Gen/GenCuts package
-
-! 2011-06-20 - Patrick Robbe
- - src/component/ApplyPhotos.cpp: add the possibility to use it for more
-   than one particle type.
-
-! 2011-06-16 - Patrick Robbe
- - src/component/ApplyPhotos.cpp: new algorithm to be able to apply Photos
-   on Z0 decays.
-
-! 2011-06-05 - Vanya Belyaev
-
- - add ``generic'' full-event cut:
-   it analyses the event and accept them according to cuts.
-     e.g. accept ebents with at least two J/psi :
-    xxx.Code = " count( 'J/psi(1S)' == GID ) > 1.5 "
-     in a similar way one can use anyproerteis, including the acceptance
-
-! 2011-05-31 - Victor Coco
- - BiasedBB: add some cuts on number of stable charged daugthers of the B and
-   on minimal R displacement. By default gives the same result than without
-   those cuts
-
-! 2011-05-31 - Patrick Robbe
- - SemilepCutForADS: fix warnings
-
-! 2011-05-29 - Patrick Robbe
- - Generators/IPileUpTool.h: change interface (remove unneeded GenHeader argument,
-   replaced by new beam parameters object)
- - src/component/FixedLuminosity.h
- - src/component/FixedTarget.h
- - src/component/CollidingBeams.h
- - src/component/BeamSpotSmearVertex.cpp
- - src/component/FixedLuminosityForRareProcess.cpp
- - src/component/VariableLuminosity.cpp
- - src/component/Generation.cpp
- - src/component/FixedNInteractions.cpp
- - src/component/BeamSpotSmearVertex.h
- - src/component/FlatZSmearVertex.cpp
- - src/component/FixedLuminosityForSpillOver.h
- - src/component/FixedLuminosityForRareProcess.h
- - src/component/VariableLuminosity.h
- - src/component/FixedLuminosity.cpp
- - src/component/FixedLuminosityForSpillOver.cpp
- - src/component/FixedNInteractions.h
- - src/component/FixedTarget.cpp
- - src/component/FlatZSmearVertex.h
- - src/component/CollidingBeams.cpp
-     Adapt for new BeamParameters event model class
-
-! 2011-05-23 - Alex T. Grecu
- - Replace HepMC::IO_Ascii with HepMC::IO_GenEvent in WriteHepMCAsciiFile
-   algorithm. This way Gauss may be used as MC generator for rivet analyses.
-
-!====================== Generators v10r10 2011-03-17 =========================
-! 2011-03-16 - Alex Shires
- - Rename tool from DaughtersInLHCbAcceptance to DaughtersInLHCbAndWithMinP
-
-! 2011-03-15 - Alex Shires
- - Add in DaughtersInLHCbAcceptance tool to src/components.
-   Allows both DecProdCut and a momentum cut to be made on tracks -
-   default values are 3 GeV for muons and 1 GeV for other charged tracks
-
-! 2011-03-10 - Paolo Gandini
- - Introdude a new cut for applying a cut on minimum value on invariant mass
-   of D0 mu in Bu->D0 mu nu decay. The value can be set via the property
-   "MassMin" with default value at 4600 MeV.
-   Cuts on acceptance of charged and neutral particle are also applied:
-   "ChargedThetaMin" (default = 10mrad), "ChargedThetaMax" (default = 400mrad),
-   "NeutralThetaMin" (defalut = 5mrad), "NeutralThetaMax" (default = 400mrad)
-   . src/component/SemilepCutForADS.{h,cpp}
-
-!====================== Generators v10r9 2010-12-10 ==========================
-! 2010-12-10 - Gloria Corti
- - Allow for a rotation of the beam line with respect to the nominal one.
-   . CollidingBeams.{h,cpp}: the px and py components will be modified
-     accordingly. Angle controllable via properties, by default set to
-     zero.
-   . Not yet implemented in other tools for FixedTarget and Smearing to be
-     used for beam gas simulation.
-
-! 2010-09-19 - Patrick Robbe
- - UpsilonInAcceptance.h/.cpp: add and print counter to be able to
-   determine generator level efficiencies for Upsilon productions.
-
-! 2010-08-01 - Vanya Belyaev
-
- - GenericGenCutTool.cpp
-
-      New generic generator cut tool.
-      It allows fine tuning and configuration of generator
-      level cuts, inclusing 'LHCb-acceptance'-cuts
-
-      One can specify different crietria for different particles,
-      ignore certain particles (e.g. neutrinos) etc...
-
-      The tool also produce the generatorcut efficiencty 2D-histogram.
-      The histogram can be cofigured therough property
-
-!====================== Generators v10r8 2010-05-09 ==========================
-! 2010-05-06 - Gloria CORTI
- - Introduce possibility to have beam spot centered in a given value in the
-   x and y axis. The same for interactions for beam-gas vertex smearing.
-   Values given in options. Default set to zero.
-   . BeamSpotSmearVertex.{h,cpp}
-   . FlatZSmearVertex.{h,cpp}
- - Introduce possibility to have crossing angle included in smearing of
-   interaction, togheter with beam direction, for tools used in beam-gas
-   vertex smearing. The value of the crossing angle can be set by options.
-   Default set to zero.
-   . FlatZSmearVertex.{h,cpp}
-
-! 2010-05-05 - Patrick Robbe
- - EvtGenDecay.cpp: use tmpnam to have unique files when creating the
-   temporary files for photos and EvtGen particle table
-
-!====================== Generators v10r7 2010-03-22 ==========================
-! 2010-03-21 - Patrick Robbe
- - EvtGenDecay.cpp: force Pythia LHCb interface to be initialized to be sure
-   that Pythia is using the correct LHCb settings, even if Pythia is not used
-   as production generator
-
-!====================== Generators v10r6 2009-12-17 ==========================
-! 2009-12-03 - Patrick Robbe
- - src/Lib/ExternalGenerator.h/.cpp: remove the contraint that only
-   B and D excited states can be pre-decayed.
-
-!====================== Generators v10r5 2009-11-04 ==========================
-! 2009-10-22 - Patrick Robbe
- - src/Lib/Signal.cpp: remove the constraint that the signal has a b
-   or a c quark. This will allow Sigma+ signal generation for example.
- - Small fixes for SLC5 compilation
-
-!====================== Generators v10r4 2009-10-05 ==========================
-! 2009-10-02 - Jibo He
- - Correct the Initialize/Finalize (mis)balance for UpsilonDaughtersInLHCb.
-
-! 2009-09-20 - Patrick Robbe
- - Special.cpp: fix initialization sequence for LHAPDF
-
-!====================== Generators v10r3 2009-09-18 ==========================
-! 2009-09-09 - Thomas BLAKE
- - DiLeptonInAcceptance.cpp: Fix bug in mass calculation
-
-! 2009-08-10 - Thomas BLAKE
- - DiLeptonInAcceptance.cpp: Updated code to allow for same sign combinations.
-
-!====================== Generators v10r2 2009-07-15 ==========================
-! 2009-06-19 - Patrick Robbe
- - EvtGenDecay.cpp: reactivates computing of branching fraction in
-    DECAY.DEC
-
-! 2009-06-15 - Gloria CORTI
- - Fix compilation warning of unused variable removing leftover old variable
-   when modified how to store luminosity
-   . Generation.cpp
-
-!====================== Generators v10r1 2009-05-27 ==========================
-! 2009-04-23 - Patrick Robbe
- - Add possibility to obtain Upsilon from higher mass states, in
-   UpsilonDaughtersInLHCb
-
-!====================== Generators v10r0 2009-04-07 ==========================
-! 2009-04-07 - Gloria CORTI
- - Fill new information in GenHeader (frequency and total cross section) in
-   order to be able to reproduce n_mean (collisions/bunch). In order to
-   fill information modify IPileUpTool interface to pass GenHeader rather
-   than "current luminosity". Modify all implemementations of PileUp tools
-   to adopt new interface and fill GenHeader.
-   . IPileUpTool.h
-   . FixedLuminosity.{h,cpp}
-   . FixedLuminosityForRareProcess.{h,cpp}
-   . FixedLuminosityForSpillOver.{h,cpp}
-   . FixedNInteractions.{h,cpp}
-   . VariableLuminosity.{h,cpp}
-   . Generation.cpp
-
-!====================== Generators v9r4 2009-04-06 ===========================
-! 2009-04-06 - Gloria CORTI
- - Tag only, to keep next changes separate
-
-! 2009-04-01 - Patrick Robbe
- - Generation: make it a filter to skip the generation and simulation
-   sequence for 0 interaction
- - Add new pile-up tool: FixedLuminosityForSpillOver which allows 0
-   interaction
-
-! 2009-03-16 - Patrick Robbe
- - EvtGenDecay: fixes for new EvtGen version
-
-! 2009-03-02 - Patrick Robbe
- - ReadHepMCAsciiFile.cpp: move to new method IO_GenEvent instead
-   of deprecated IO_Ascii method for external input files
-
-! 2009-02-26 - Patrick Robbe
- - UpsilonDaughtersInLHCb: add new cut tool specific for Upsilon
-   generation
-
-!====================== Generators v9r3 2009-02-09 ===========================
-! 2009-01-20 - Will REECE
- - EvtGenDecay: Passes the list of models from EvtGenExtras into EvtGen.
-   requirements: Adds dependency on EvtGenExtras.
-
-!====================== Generators v9r2 2009-01-13 ===========================
-! 2008-12-11 - Patrick Robbe
- - Signal.cpp: associate production_vertex to signal_vertex for clean
-   events, to allow correct primary vertex assignment for Geant4.
-
-!====================== Generators v9r1 2008-10-10 ===========================
-! 2008-09-20 - Patrick Robbe
- - ExternalGenerator.cpp: create ParticlePropertySvc if not existing (needed
-   if DecayTool is not used)
- - Signal.cpp: protect in case of empty decay tool
-
-!====================== Generators v9r0 2008-08-25 ===========================
-! 2008-07-24 - Patrick Robbe
- - Move to HEPMC2
-
-! 2008-07-23 - Marco Cattaneo
- - Removed DumpHepMCTree, DumpMC, DumpMCDecay algorithms, moved to
-   Sim/SimComponents, last two renamed DumpHepMC and DumpHepMCDecay
- - Generator/HepMCUtils.h has been moved to GenEvent package. A dummy file is
-   kept for backwards compatibility, forwarding to the new include
-
-! 2008-07-21 - Patrick Robbe
- - EvtGenDecay.cpp: add possibility to generate polarized charmonium
-
-! 2008-07-20 - Patrick Robbe
- - Special.cpp: suppress LHAPDF output
-
-!====================== Generators v8r2 2008-07-18 ===========================
-! 2008-07-18 - Patrick Robbe
- - Generation.cpp: fix compilation warning
-
-! 2008-07-16 - Gloria CORTI
- - Remove use of SEAL from requirements file
-
-! 2008-07-10 - Patrick Robbe
- - Remove completly SEAL functions and replace them with BOOST
-   functions for file handling
-   . src/component/EvtGenDecay.cpp/.h
-
-! 2008-07-09 - Patrick ROBBE and Gloria CORTI
- - Use Gaudi units explicitely instead of CLHEP implecitely via HepMC
-   (preparation for migration to HepMC 2.0)
- - Replace use of SEAL utility for environment variables with that of Gaudi
-   . src/component/BiasedBB.cpp
-   . src/component/DaughtersInLHCb.cpp
-   . src/component/EvtGenDecay.cpp
-   . src/component/Generation.cpp
-   . src/component/LHCbAcceptance.cpp
-   . src/component/LeptonInAcceptance.cpp
-   . src/component/ListOfDaughtersInLHCb.cpp
-   . src/component/ReadHepMCAsciiFile.cpp
-   . src/component/SelectedDaughterInLHCb.cpp
-   . src/component/WriteHepMCAsciiFile.cpp
-
-!====================== Generators v8r2 2008-07-06 ===========================
-! 2008-07-04 - Patrick Robbe
- - src/component/Inclusive.cpp: protect againts inexistent PDG Id for
-   inclusive production
-
-!====================== Generators v8r1 2008-06-09 ===========================
-! 2008-05-29 - Gloria CORTI
- - Modify code to pick Vector{3D,4D}Types, etc. from GaudiKernel since
-   LHCbDefinitions has been removed from GAUSS, given that the package
-   will no longer be used with Gauss DC06.
-   . Generators/IBeamTool.h
-   . src/component/BiasedBB.cpp
-   . src/component/DaughtersInLHCb.{h,cpp}
-   . src/component/EvtGenDecay.h
-   . src/component/FlatZSmearVertex.cpp
-   . src/component/ListOfDaughtersInLHCb.{h,cpp}
-   . src/component/SelectedDaughterInLHCb.{h,cpp}
-   . src/component/SignalForcedFragmentation.{h,cpp}
-   . src/component/UniformSmearVertex.cpp
-
-! 2008-05-23 - Patrick Robbe
- - Move Photos fortran files to GENSER
- - Remove unnecessary LHAPDF routines
-
-!====================== Generators v8r0 2008-05-06 ===========================
-! 2008-05-06 - Gloria CORTI
- - New algorithm to allow filtering of "merged" events, i.e. events where
-   a pp-collision is alwasys forced togheter with a MIB event, eg. beam
-   gas in Experimental area, in Long Straight Section or quartiary halo.
-   In this case two algorithms are executed one after the other and global
-   event cuts need to be applied afterward, since the one in "Generation" is
-   only applied on the event generated by the given instance of the algorithm.
-   . src/component/MergedEventsFilter.{h,cpp} - NEW
-
- - Introduce options to allow generation of pp-collisions elsewhere than
-   in IP8, for example in the center of the cavern. This can also be used
-   for interactions of satellite bunches.
-   Give mean z position of vertex as an option, "MeanZ" (Default = 0.0 as
-   in IP8, for center of the cavern it should be set to 11.22 m).
-   Can also set option to fix if time of interaction vs T0 of IP8 occured
-   before, after or at the same time, setting "SignOfTimeVsT0" (Default = 0.0
-   as in IP8, can be -1 or 1 in addition)
-   . src/component/BeamSpotSmearVertex.{h,cpp}
-
-! 2008-05-05 - Gloria CORTI
- - Introduce direction of beam to take into account that time of interaction
-   for beam 2 with beam gas has to be negative to have the beam arriving at
-   t = 0 in IP8. To allow for events where beam 1 and beam 2 are togheter
-   the "BeamDirection" can be set to "dummy" zero value in which case the
-   time of interaction is set to zero. The option is called "BeamDirection"
-   and can have integer values -1, 1 and 0 (Default = 1, as for beam 1)
-   . src/component/FlatZSmearVertex.{h,cpp}
-   . src/component/UniformSmearVertex.{h,cpp}
-
-! 2008-03-20 - Gloria CORTI
- - Temporarly exclude from library MuXMaxBias.cpp because of compilation
-   problems
-   . cmt/requirements
- - Put time of vertex as z/c, assuming these smearing are used for beam
-   gas so the time on which the occur is the time the beam has travelled
-   at that z from IP.
-   . src/component/FlatZSmearVertex.cpp, UniformSmearVertex.cpp
-
-! 2008-03-16 - Patrick Robbe
- - src/Lib/pyr.F: move to GENSER package
-
-! 2008-01-25 - Patrick Robbe
- - Special.cpp: set pile-up generation tool as a private tool
-
-!====================== Generators v7r7 2007-12-19 ===========================
-! 2007-12-06 - Vanya BELYAEV
- - src/Lib/ExternalGenerator.cpp
-   src/Lib/Signal.cpp
-   Allow the production of inclusive taus with SignalPlain tool
-
-!====================== Generators v7r6 2007-12-06 ===========================
-! 2007-11-30 - Gloria Corti
- - On Win32 put Signal and ExternalGenerators base classes in component
-   library rather then linker to allow compilation.
-   . requirements
-
-!====================== Generators v7r6 2007-12-06 ===========================
-! 2007-11-26 - Chris Jones
- - Add three new Signal selection 'Cut' tools
-  + SignalIsFromBDecay      : Selects only decays that originate from a b
-  + LHCbAcceptanceAndFromB  : The AND of the SignalIsFromBDecay and
-    LHCbAcceptance selections
-  + DaughtersInLHCbAndFromB : The AND of the SignalIsFromBDecay and
-    DaughtersInLHCb selections
-
-! 2007-11-08 - Gloria Corti for Karl Harrison
- - Linking of HepMCfio for WIN32
-
-! 2007-10-11 - Patrick Robbe
- - Move inline functions in StreamForGenerator and RandomForGenerator in
-   the .cpp files
-
-!====================== Generators v7r5 2007-10-11 ===========================
-! 2007-10-11 - Gloria Corti
- - Really add src/component/UniforSmearVertex.{h,cpp}
-
-! 2007-10-10 - Patrick Robbe
- - Add static class to hold external Gaudi random generator and message
-   stream to interface with Pythia and EvtGen
-   . Generators/StreamForGenerator.h, src/Lib/StreamForGenerator.cpp
-   . Generators/RandomForGenerator.h, src/Lib/RandomForGenerator.cpp
-   . src/Lib/EvtReport.cpp
-   . src/component/EvtGenDecay.cpp
-   . src/component/Generation.cpp
-
-!====================== Generators v7r4 2007-09-27 ===========================
-! 2007-09-27 - Gloria Corti for Massimiliano Ferro-Luzzi
- - Add new tool for uniform distribution in z and xy (within max radius)
-   of primary vertex
-   . src/component/UniformSmearVertex.{h,cpp} - NEW
-   . src/component/Generators_load.cpp - add factory also for other vertex
-                                         smearing tools that were missing
-                                         (Necessary for DC06 compatibility)
-
-! 2007-09-11 - Patrick Robbe
- - src/Lib/GenCounters.cpp: fix problem with D counters
-
-! 2007-09-09 - Patrick Robbe
- - src/component/SignalForcedFragmentation: fix problem with particles
-   already decayed (bug introduced when fixing CP violation with other
-   generation methods).
- - src/Lib/Signal.cpp: change name of iterators in nested loops for Windows
-   compilation.
- - src/Lib/LHAPDFCommonBlocks.cpp, LHAPDFUtils.F: rename routine whose names
-   are used in the new LHAPDF version
- - Various fixes for Windows compilation:
-   . StandAloneDecayTool.h
-   . EvtGenDecay.{h,cpp}
-
-!====================== Generators v7r3 2007-08-22 ===========================
-! 2007-07-17 - Patrick Robbe
- - src/Lib/Signal.cpp: fix generation of clean events
-
-!====================== Generators v7r2 2007-07-03 ===========================
-! 2007-07-03 - Gloria Corti
- - Allow possibility of running different instances of Generation algorithm
-   (ex. pp collisions and p-gas) in the same job. To do this the collisions
-   and hepmc events are kept in temporary containers and contents added to
-   containers in TES that are created in case they do not already exist.
-   The header information is updated accordingly.
-   . src/component/Generation.cpp
-
-! 2007-06-29 - Vanya BELYAEV
- - Generators/F77Utils.h, src/Lib/F77Utils.h
-     a) add  new function F77Utils::getUnit to obtain free FORTRAN unit
-        trrough scan of all available units between 99 and 10
-     b) for other function add optional argument "verbose"
-        with the default value equal to "false"(backward compatible).
-        It is *VERY* convinient for debugging...
- - src/Lib/f77units.F
-     add new function: INTEGER FUNCITON F77GETUNIT
-
-!====================== Generators v7r1 2007-05-08 ===========================
-! 2007-05-08 - Patrick Robbe
- - Clean cut tools to remove unused functions:
-    . src/component/DaughtersInLHCb.cpp
-    . src/component/DaughtersInLHCb.h
-    . src/component/ListOfDaughtersInLHCb.cpp
-    . src/component/ListOfDaughtersInLHCb.h
-    . src/component/SelectedDaughterInLHCb.cpp
-    . src/component/SelectedDaughterInLHCb.h
-
-! 2007-05-03 - Gloria CORTI
- - Slighlty change message levels at initialization to see in info()
-   primary interation vertex for flat vertex ( FlatZSmearVertex.cpp )
- - Explicitely use LHCbDefinitions so that package is compatible with
-   Gauss version using latest Gaudi v19r3 as well as DC06 version.
-
-! 2007-04-01 - Patrick Robbe
- - Add new tool (RepeatDecay) to re-use the same event several times,
-   calling only the decay phase.
-
-!====================== Generators v7r0 2007-03-13 ===========================
-! 2007-03-08 - Patrick Robbe
- - IProductionTool: Add new function "initializeGenerator()" which will
-   contain the generator specific initialization procedure.
- - ReadHepMCAsciiFile: adapt for new production tool interface
- - Special: Add the possibility to generate pile-up for special production
- - FixedLuminosityForRareProcess: new pile-up tool to generate correctly
-   pile-up distributions for rare process events
-
-! 2007-03-08 - Patrick Robbe for Thomas Blake
- - DiLeptonInAcceptance: new FullEventGenCutTool to accept events with dimuons.
-
-! 2007-02-27 - Patrick Robbe
- - Fix output level of Special production tool
-
-! 2007-02-23 - Gloria Corti
- - Increase major version due to change in IGenCutTool interface
-
-! 2007-02-22 - Gloria CORTI
- - Change default values of ZMin and ZMax of flat primary vertex according
-   to what chosen for Luminosity studies for beam gas (+/- 1500 mm) as
-   communicated by Daniele GREGORI
-   . FlatZSmearVertex.cpp
-
-! 2007-02-20 - Patrick Robbe
- - Fix efficiency counters for CP violation decay modes (=> change IGenCutTool
-   applyCut function arguments). The signal decay is now always performed
-   before applying any generator cut.
-
-!====================== Generators v6r8 2007-02-08 ===========================
-! 2007-02-08 - Gloria Corti
- - Slighlty change message levels at initialization to see beam energy and
-   primary interation vertex ( CollidingBeams.cpp, FixedTarget.cpp,
-   BeamSpotSmearVertex.cpp, FixedNInteractions.cpp)
-
-! 2007-02-06 - Patrick Robbe
- - Fix problem with biased hadron fractions (SignalPlain and
-   SignalRepeatedHadronization)
-
-! 2007-01-30 - Patrick Robbe
- - Fix problem with flip by EvtGen in Cut tools (DaughtersInLHCb,
-   SelectedDaughtersInLHCb and ListOfDaughtersInLHCb)
-
-! 2007-01-23 - Gloria Corti
- - Modify requirements to have a version with all changes in code but
-   compatible with DC06.
- - Change default for flat smearing of primary vertex, to have correct values
-   at 7 TeV for beam gas, i.e. 100 microns in x and y
-
-! 2007-01-08 - Florence Ranjard
- - update in many *.cpp to use new FACTORY and SystemOfUnits from GaudiKernel
-
-!====================== Generators v6r7p1 2006-12-04 =========================
-! 2006-11-30 - Vanya BELYAEV
- - src/componet/Generation.cpp
-   add a guard for "0 != m_pileUpTool" in
-   Generation::finalize method
-
-!======================= Generators v6r7 2006-11-09 ==========================
-! 2006-10-31 - Patrick Robbe
- - src/Lib/Signal.cpp: fix unitialized variable.
-
-! 2006-10-25 - Vanya BELYAEV
- - src/component/DumpHepMCTree.cpp
-     simple algorithm to dump the HepMC-tree in readable format
- - src/component/DumpMCDecay.h, src/component/DumpMCDecay.cpp
-     reshuffling of lines to allow the reuse functionality
-     in DumpHepMCTree algorithm
- - src/component/Generators_load.cpp
-     add a factory for new algorithm
-
-!======================= Generators v6r6 2006-10-23 ==========================
-! 2006-10-23 - Patrick Robbe
- - src/component/ListOfDaugthersInLHCb.h/.cpp: cut on a list of
-   daughters of the signal to be in the acceptance.
-
-! 2006-10-19 - Vanya BELYAEV
- - src/component/DumpMCDecay.cpp
-     - improve the printout
-     - introduce benw property "MaxLevels" to represent the maximal
-       printout level pit is much more easier to debug now!]
-     - reshuffle the lines a bit
- - src/component/DumpMCDecay.h  - remove the file
-
-!======================= Generators v6r5 2006-10-10 ==========================
-! 2006-10-09 - Patrick Robbe
- - SelectedDaughterInLHCb: modify to be able to give more than
-   1 PID in list of daughters to select on.
-
-! 2006-10-06 - Vanya BELYAEV
- - src/component/ReadHepMCAsciiFile.cpp
-
-    Simple "production tool", which actually reads HepMC events
-    from  ascii input file. The tool could be useful to read
-    information from external generators, if their integration
-   into Gauss is impossible, difficult or not needed.
-
-   The tool has 2 properties:
-
-     - <c>Input</c>  : The name of input fiel in HepMC Ascii format
-                     ( the default value is <c>""</c> (empty string))
-     - <c>Rescale<c> : Boolean flag to rescal the input event from
-                      Pythia units to LHCb units.
-                      The default value is <c>true</c>.
- - src/component/WriteHepMCAsciiFile.cpp
-
-    Simple class to dump generators events in plain
-    output file in HepMC Ascii format. It coudl be used for portable
-    cross-transitions of events inbetween different degerators
-
-    The algorithm has 3 properties:
-
-     - <c>Input</c>  : The TES location of LHCb::HepMCEvent::Container
-               ( the default value is <c>LHCb::HepMCEventLocation::Default</c>)
-     - <c>Ouput</c>  : The name of output HepMC Ascii file.
-                      The file is opened in "new/overwrite" mode.
-                      ( the default value is <c>""</c> (empty string)
-     - <c>Rescale<c> : Boolean flag to rescal the event from
-                       LHCb units to Pythia units.
-                       The default value is <c>true</c>.
-
- - src/components/Generators_load.cpp
-      declare 2 new componenst
-
- - Generators/Scale.h, src/Lib/Scale.cpp
-     simple utility to scale HepMC event inbetween Pythia and LHCb units
-
-!======================= Generators v6r4 2006-10-05 ==========================
-! 2006-10-04 - Patrick Robbe
- - Add a new tool (SelectedDaughterInLHCb) to cut only on the daughters
-  of a single daughter of the signal particle (for example daughter
- from a J/psi, Ds, ...), and require they are in the LHCb acceptance.
-
-! 2006-10-04 - Vanya BELYAEV
-
- - Generators/F77Utils.h
-       new file with few C++ utilities to manipulate(open&close) FORTRAN file
-      (Old/New/Unknown & their "Formatted" counterpartters)
- - src/Lib/F77Utils.cpp
- - src/Lib/f77units.F
-      Implementation of the functions from the file Generators/F77Utils.h
- - cmt/requirements
-      version incrmeent to v6r4
-
-
-! 2006-10-01 - Patrick Robbe
- - Add possibility to cut on daughters of signal particle (New
-   DaughtersInLHCb cut tool). Change of IGenCutTool interface to
-   allow this.
-
-!======================= Generators v6r3 2006-09-19 ==========================
-! 2006-09-06 - Gloria Corti
- - Generators/GenCounters.h: put explicitely include of <cmath> to compile
-   on slc4
-
-! 2006-08-30 - Patrick Robbe
- - src/Lib/phocin.F: put XPHCUT in double precision explicitly
-
-!======================= Generators v6r2 2006-08-29 ==========================
-! 2006-08-28 - Patrick Robbe
- - src/component/Generation.cpp: protect against b quark without production
-   vertex.
- - src/Lib/ExternalGenerator.cpp: order HepMC particles to be sure to
-   reproduce events.
- - src/component/StandAloneDecayTool.cpp: add a flag (Inclusive) to
-   be able to generate generic decays with the decay tool.
-
-!======================= Generators v6r1 2006-07-27 ==========================
-! 2006-07-27 - Gloria CORTI
- - Move update of EventType in GenHeader at beginning of execution to allow
-   production tools to access its value.
-   . src/component/Generation.cpp
-
-!=================== Generators v6r0 2006-07-04 ===========================
-! 2006-07-04 - Gloria CORTI
- - Introduce use of Gaudi::Units namespace as required by LHCb v21r1
-   . BeamSpotSmearVertex.cpp, EvtGenDecay.cpp, FlatZSmearVertex.cpp
- - Follow general LHCb convention for name of componenet libraries
-   loading and declaration file.
-   . factories declared in Generators_load.cpp (modified)
-   . remove Generators_entries.cpp and add Generators_dll.cpp
-
-!=================== Generators v5r3 2006-06-22 ===========================
-! 2006-06-22 - Gloria CORTI
- - Always print Event type code requested at initialization
-   . src/component/Generation.cpp
-
-! 2006-06-16 - Patrick Robbe
- - src/Lib/ExternalGenerator.cpp: set default value for job option
-   parameter (not in constructor).
-
-!=================== Generators v5r2 2006-06-07 ===========================
-! 2006-06-05 - Patrick Robbe
- - src/Lib/EVLCTEQ.F: Fix use of uninitialized value.
- - src/component/BiasedBB.h/.cpp : new cut tool to implement maximum
-   bias b/bbar sample for DC06.
- - src/component/Generators_entries.cpp: declare new cut tol BiasedBB.
- - src/component/SignalForcedFragmentation: Use ns for HepMC unit
-
-!=================== Generators v5r1 2006-05-19 ===========================
-! 2006-05-08 - Vanya BELYAEV
- - src/component/MuXMaxBias.cpp
-    really commit new tool..
- - cmt/requirement
-    (re)add the usage of Phys/LoKiGen v*
-
-! 2006-05-02 - Patrick Robbe
- - src/Lib/Signal.cpp: rename counters to be consistent with inclusive.
-
-! 2006-04-23 - Patrick Robbe
- - Add new tool to use EvtGen in standalone mode: StandAloneDecayTool
-
-! 2006-04-08 - Vanya BELYAEV
- - src/component/MuXMaxBias.cpp
-   new tool ("generator cut") for the
-   selection of "maximum bias sample for Bs -> mu+ mu- backhround studies"
- - src/component/Generators_entries.cpp
-   new tool is declared
- - cmt/requirement
-   add the usage of Phys/LoKiGen v*
-
-!=================== Generators v5r0 2006-04-07 ===========================
-! 2006-04-06 - Patrick Robbe
- - SignalForcedFragmentation: Fix counters.
- - GenCounters: do not count Bc with D hadrons.
-
-! 2006-04-05 - Patrick Robbe
- - requirements: GENSER 1.3.0 compiles now LHAPDF with -O2, remove
-   -O in requirements
-
-! 2006-04-04 - Patrick Robbe
- - ExternalGenerators.h/.cpp: add a switch (KeepOriginalProperties) in
-   options to be able to keep the original particle properties of the
-   external generator.
- - StringParse.h/.cpp: returns a double instead of a float when decoding
-   job option commands.
- - requirements: use "-O" flag to compile LHAPDF code instead of -O2.
- - Generation.cpp: improve counting of B hadrons
-
-! 2006-04-04 - Gloria CORTI
- - Adapt to changes in put method signature in GaudiAlgorithm base class
-   . src/Lib/Signal.cpp
-   . src/component/Generation.cpp
-
-! 2006-03-29 - Florence Ranjard
- - use HepMC from lcg/external : link with HepMCfio
-
-!=================== Generators v4r2 2006-03-22 ===========================
-! 2006-03-22 - Patrick Robbe
- - ExternalGenerators: adapt to new HepMCEvent constructor and set to false
-   isSignal for pile up collisions
- - Signal: use new HepMCEvent constructor and set HepMC container name of
-   clean events.
- - BeamSpotSmearVertex, FlatZSmearVertex: use mm
- - EvtGenDecay: use MeV and interface EvtGen engine with GeV in the tool
- - Inclusive: set IsSignal flag of collision containing the inclusive type.
- - LeptonInAcceptance: use MeV
- - SignalPlain, SignalForcedFragmentation, SignalRepeatedHadronization,
-   Special: set IsSignal flag for collision with signal.
-
-!=================== Generators v4r1 2006-03-16 ===========================
-! 2006-03-12 - Patrick Robbe
- - Generation: fix interaction counters to count direct B from protons
-   as b quark.
-
-! 2006-03-07 - Patrick Robbe
- - phocin: set up PHOTOS to work with more than 2 charged tracks
-   and interferences
- - SignalPlain: add counters
-
-! 2006-02-22 - Patrick Robbe
- - requirements: use names with double underscore
- - ExternalGenerator, EvtGenDecay: use names with __
- - GenCounters: fix counter when there is a B oscillating
- - Signal: use end vertex as signal process
- - Generation: number HepMC::GenEvent with pile up number
-
-! 2006-02-17 - Patrick Robbe
- - HepMCUtils: add utility functions to help with HepMC structures.
- - ExternalGenerator: change decay heavy particle methods to be able
-     to reproduce events.
- - Signal: add counters of excited states and B hadron types,
-     fix clean events.
- - EvtReport, EvtGenDecay: fix overload of EvtGen output facility.
- - GenCouters: add counters for signal event types.
- - DumpMC: order particles when printing them.
- - Generation: improve reproducibility of events.
- - Inclusive, Signal...: use new function to decay heavy particles.
-
-! 2006-02-07 - Patrick Robbe
- - EvtGenDecay: finalize random generator at destruction of EvtGenGaudiRandom
- - LHAPdf interface: fix memoty leaks
-
-! 2006-02-06 - Patrick Robbe
- - Generation: fix problem with HepMCEvents (crashing for inclusive and
-       signal productions)
- - GenCounters: add several utility functions to handle array of counters.
-
-! 2006-02-05 - Patrick Robbe
- - requirements: use SEAL
- - Generation: use arrays to contain counters
- - Use temporary file class from SEAL to make temporary files.
-
-! 2006-02-01 - Patrick Robbe
- - ExternalGenerator and src/Lib/EVLCTEQ.F: remove warnings when not in DEBUG
-     mode for LHAPDF.
- - Remove includes of CLHEP SystemOfUnits
-
-!=================== Generators v4r0 2006-01-19 ===========================
-! 2006-01-19 - Gloria CORTI
- - Generation: do not create new GenHeader but unpdate info already in TES
-
-! 2006-01-18 - Patrick Robbe
- - ExternalGenerator: create HepMC::GenEvent by hand to store in
-   HepMCEvent
-
-! 2005-12-31 - Patrick Robbe
- - Adapt to new event model and new vector classes.
-
-! 2005-12-21 - Patrick Robbe
- - phocin.F: activate exponentiation in PHOTOS
- - GenCounters.h: print shorter fractions
-
-!=================== Generators v3r0 2005-12-15 ===========================
-! 2005-12-15 - Patrick Robbe
- - ExternalGenerator: Do not decay signal particle with status
-   code equal to 3.
-
-! 2005-12-10 - Patrick Robbe
- - Add comments for doxygen
-
-! 2005-12-08 - Patrick Robbe
- - Remove old structure
- - ExternalGenerators: allow possibility to change LHAPDF settings by job
-   option.
-
-! 2005-12-07 - Patrick Robbe
- - GenCounters.h: common functions to print counters and compute efficiencies
- - VariableLuminosity, Special, Generation, SignalPlain: use common function
-   to print counters.
- - SignalRepeatedHadronization: remove HepMCUtils dependency  and add
-   Clear function to clear content of HepMC Event
- - Inclusive: fix counters
- - ExternalGenerator: manage LHAPDF output and remove HepMC dependency
- - LHAPDFCommonBlocks.{h,cpp}: wrapper for LHAPDF common blocks
- - LhaPdf.{h,cpp}: static class to access LHAPDF functions from C++
- - LHAPDFUtils.F: Fortran functions to access LHAPDF common blocks
- - FixedLuminosity: new luminosity tool for fixed luminosity
-
-! 2005-11-29 - Patrick Robbe
- - LeptonInAcceptance: add full event cut tool to keep events with one
-   lepton with pT > 4 GeV
- - ExternalGenerator: add computation of efficiencies and counters
- - Signal, Generation, Inclusive, Special, VariableLuminosity: add print out
-   and computation of various counters
-
-! 2005-11-21 - Patrick Robbe
- - Signal.h/.cpp: add functions and counters to be able to compute
-   the generator level cut efficiencies. Each tool deriving from
-   "Signal" has to increment at the correct place these counters.
- - ExternalGenerator.cpp: use HepMC::GenEvent iterators (which are
-   sorted according to barcodes) in order to remove need to call
-   sort function (to reproduce events with HepMC)
- - IFullGenEventCutTool: add new tool to be able to cut on full event
-   properties.
- - Generation.cpp:
-       . sort GenParticles when using HepMC::GenParticle
-         iterators (which are not sorted) according to the barcode.
-       . use new Full event cut tool
- - SignalPlain, SignalForcedFragmentation, SignalRepeatedHadronization:
-   increment counters to compute generator level cut efficiencies.
-
-! 2005-11-17 - Patrick Robbe
- - src/component/Signal*.cpp : add possibility to generate clean events
- - src/component/SignalForcedFragmentation: add forced fragmentation
-   method
- - src/component/Special.cpp : add special generation method.
-
-!========================= Generators v2r1 ===========================
-! 2005-11-07 - Patrick Robbe
- - src/Lib/EvtReport.cpp: add function to overwrite EvtGen printing
-   utilities.
- - EvtGenDecay: use this new function.
- - ExternalGenerator and IProductionTool: set particle properties from
-   ParticlePropertySvc.
-
-! 2005-11-04 - Patrick Robbe
- - src/component/SignalRepeatedHadronization.h/cpp: tool to generate
-   signal events with repeated hadronization.
- - ExternalGenerator: add utility function to deal with event model
-   classes and prepare them before each generation of interactions.
- - HepMCUtils: add function to clear HepMC events
- - IProductionTool: add virtual functions for repeated hadronization
-   method.
- - Signal: add utility functions (choose one B amongst several and
-   function to choose correct signal multiplicity).
- - phocin.F: adapt for PHOTOS 2.15
- - pythiaoutput_utils.F : adapt for PYTHIA 6.3
- - Generation: correct status of particles to decay with EvtGen.
-
-!========================= Generators v2r0 ===========================
-! 2005-10-17 - Patrick Robbe
- - EvtGenTool : add possibility to control polarization parameters
-   by job options.
-
-! 2005-10-13 - Patrick Robbe
- - Generators/GenBaseAlg : remove forward declaration not used
-
-! 2005-10-03 - Patrick Robbe
- - HepMCUtils : use a static class instead of a namespace and add
-   IsBAtProduction utility function.
- - EvtDecayAlg : use new name of sort function.
- - EvtGenTool : declare global stream variable extern to avoid conflicts
- - Generators/IBeamTool.h : New abstract interface to tools to obtain beam
-     parameters in generator interfaces.
- - Generators/IDecayTool.h : New abstract interface to decay generators.
- - Generators/IGenCutTool.h : New abstract interface to generator level cut
-     tools.
- - Generators/IPileUpTool.h : New abstract interface to tools computing the
-     number of pile up interactions.
- - Generators/IProductionTool.h : New abstract interface to production
-     generators.
- - Generators/ISampleGenerationTool.h : New abstract interface to tools
-     producing the different samples.
- - Generators/IVertexSmearingTool.h : New abstract interface to vertex smearing
-     tools.
- - VariableLuminosity: pile up tool to decide the number of pile up
-     interactions depending on the current luminosity.
- - FixedNInteractions: pile up tool with fixed number of interactions per
-     event.
- - CollidingBeams: Beam tool for colliding beams and beam smearing
- - FixedTarget: Beam tool for fixed target
- - BeamSpotSmearVertex: vertex smearing tool for gaussian smearing.
- - FlatZSmearVertex: vertex smearing with flat Z distribution.
- - LHCbAcceptance: generator level cut tool with angular cut.
- - ExternalGenerator: base class for sample generation tool using an
-     external generator.
- - Signal: base class for sample generation tool using an external generator
-     and generating signal samples.
- - EvtGenDecay: Decay tool interfacing EvtGen
- - Generation: Main algorithm steering production of event samples with an
-     external generator.
- - MinimumBias: Sample generation tool to generate minimum bias.
- - Inclusive: Sample generation tool to generate inclusive events.
- - SignalPlain: Sample generation tool to generate signal events with plain
-     method.
-
-!========================= Generators v1r2 ===========================
-! 2005-08-22 - Florence RANJARD
- - phocin.F - remove the #include nmxhep.inc, replace it with 10000.
-
-!========================== Generators v1r1 ===========================
-! 2005-07-11 - Gloria CORTI
- - requirements: introduce macro for fortran flags (no second underscore)
-
-! 2005-06-24 - Gloria CORTI
- - Import changes as done in GeneratorModules v15r3 for merging of
-   beam gas with min bias events
-  + Changes to add possibility to set with properties the Generator data
-   paths in the TES. By defaut they are set to XxxLocation::Default
-   . src/component/EvtDecayAlg.{h,cpp} - property "HepMCEventLocation"
-   . src/component/SetDecayAlg.{h,cpp} - property "HepMCEventLocation"
-   . src/component/SmearVertexAlg.{h,cpp} - property "HepMCEventLocation"
-   . Generators/GenBaseAlg.h
-     src/Lib/GenBaseAlg.cpp - property "HepMCEventLocation"
-                              property "HardInfoLocation"
-                              property "GenHeaderLocation"
-  + Changes to add possibility to apply smearing of primary vertex only
-   to events produced with a certain generator (identified by name in
-   HepMCEvent container). Controlled by setting name of generator in
-   property "ApplyTo". The default is set to an empty string, in which
-   case the smearing is applied to all events in container
-   . src/component/SmearVertexAlg.{h,cpp}
-
-
-!========================== Generators v1r0 ===========================
-! 2005-06-20 - Patrick Robbe
- - new package. This package contains the base classes used by the
-   generator algorithms and tools. It also contains generic algorithms
-   and tools for debugging (DumpMC, DumpMCDecay), for EvtGen access
-   (EvtGenTool, SetDecayAlg, EvtDecayAlg), for vertex smearing (SmearVertexAlg)
-   and also utility functions (random number interfaces, HepMC help functions,
-   String utilities to read generator Fortran-like options)
-
-! ====================================================================
diff --git a/Gen/Generators/src/Lib/EvtReport.cpp b/Gen/Generators/src/Lib/EvtReport.cpp
deleted file mode 100755
index ded6486fd..000000000
--- a/Gen/Generators/src/Lib/EvtReport.cpp
+++ /dev/null
@@ -1,35 +0,0 @@
-// $Id: EvtReport.cpp,v 1.3 2007-10-10 20:07:24 robbep Exp $
-// Overwrite EvtGen output messages
-
-#include "Generators/StreamForGenerator.h" 
-#include "EvtGenBase/EvtReport.hh"
-
-std::ostringstream dummyStr ;
-
-//=============================================================================
-// Reimplementation of print facility of EvtGen
-//=============================================================================
-std::ostream & report( Severity severity , const char * facility ) 
-{  
-  dummyStr.str("") ;
-  if ( severity < WARNING ) {
-    if ( 0 != facility[0] ) { 
-      (*StreamForGenerator::getStream()) << MSG::ERROR << facility << " Error from EvtGen" 
-                      << endmsg ; 
-    }
-    else (*StreamForGenerator::getStream()) << MSG::ERROR << "Error from EvtGen" 
-                         << endmsg ;
-  } else if ( severity < INFO ) {
-    if ( 0 != facility[0] ) {
-      (*StreamForGenerator::getStream()) << MSG::INFO ; 
-      if ( StreamForGenerator::getStream()->isActive() ) std::cout << facility << ":" ;
-    } else (*StreamForGenerator::getStream()) << MSG::INFO ;
-  } else {
-    if ( 0 != facility[0] ) {
-      (*StreamForGenerator::getStream()) << MSG::DEBUG ;
-      if ( StreamForGenerator::getStream()->isActive() ) std::cout << facility << ":" ;
-    } else ( *StreamForGenerator::getStream() ) << MSG::DEBUG ;
-  }
-  if ( StreamForGenerator::getStream()->isActive() ) return std::cout ;
-  else return dummyStr ;
-}
diff --git a/Gen/Generators/src/Lib/ExternalGenerator.cpp b/Gen/Generators/src/Lib/ExternalGenerator.cpp
deleted file mode 100755
index ad9c1570d..000000000
--- a/Gen/Generators/src/Lib/ExternalGenerator.cpp
+++ /dev/null
@@ -1,356 +0,0 @@
-// $Id: ExternalGenerator.cpp,v 1.27 2009-12-03 15:32:49 robbep Exp $
-// Include files 
-
-// local
-#include "Generators/ExternalGenerator.h"
-
-// Boost
-#include "boost/tokenizer.hpp"
-#include "boost/algorithm/string/erase.hpp"
-// Gaudi
-#include "Kernel/IParticlePropertySvc.h" 
-#include "Kernel/ParticleProperty.h"
-// Kernal
-#include "MCInterfaces/IGenCutTool.h"
-#include "MCInterfaces/IDecayTool.h"
-
-// from Generators
-#include "Generators/IProductionTool.h"
-#include "Generators/LhaPdf.h"
-#include "Generators/StringParse.h"
-#include "Generators/ICounterLogFile.h"
-#include "GenEvent/HepMCUtils.h"
-#include "Event/GenFSR.h"
-
-//-----------------------------------------------------------------------------
-// Implementation file for class : ExternalGenerator
-//
-// 2005-08-18 : Patrick Robbe
-//-----------------------------------------------------------------------------
-
-//=============================================================================
-// Standard constructor, initializes variables
-//=============================================================================
-ExternalGenerator::ExternalGenerator( const std::string& type,
-                                      const std::string& name,
-                                      const IInterface* parent )
-  : GaudiTool ( type, name , parent ) , 
-    m_productionTool( 0 ) ,
-    m_decayTool( 0 ) ,
-    m_cutTool  ( 0 ) , 
-    m_xmlLogTool( 0 ) ,
-    m_ppSvc    ( 0 ) { 
-    m_defaultLhaPdfSettings.clear() ;
-    declareInterface< ISampleGenerationTool >( this ) ;
-    declareProperty( "ProductionTool" , 
-                     m_productionToolName = "Pythia8Production" ) ; 
-    declareProperty( "DecayTool" , m_decayToolName = "EvtGenDecay" ) ;
-    declareProperty( "CutTool" , m_cutToolName = "LHCbAcceptance" ) ;
-    declareProperty( "LhaPdfCommands" , m_userLhaPdfSettings ) ;
-    declareProperty( "KeepOriginalProperties" , m_keepOriginalProperties = 
-                     false ) ;
-    declareProperty ( "GenFSRLocation", m_FSRName =
-                      LHCb::GenFSRLocation::Default);
-    m_defaultLhaPdfSettings.push_back( "lhacontrol lhaparm 17 LHAPDF" ) ;
-    m_defaultLhaPdfSettings.push_back( "lhacontrol lhaparm 16 NOSTAT" ) ;
-  }
-
-//=============================================================================
-// Destructor
-//=============================================================================
-ExternalGenerator::~ExternalGenerator( ) { ; }
-
-//=============================================================================
-// Initialization method
-//=============================================================================
-StatusCode ExternalGenerator::initialize( ) {
-  StatusCode sc = GaudiTool::initialize( ) ;
-  if ( sc.isFailure() ) return sc ;
-
-  if ( msgLevel( MSG::DEBUG ) ) {
-    LhaPdf::lhacontrol().setlhaparm( 19 , "DEBUG" ) ;
-  }
-  else {
-    LhaPdf::lhacontrol().setlhaparm( 19 , "SILENT" ) ;
-  }
-  
-  // Set default LHAPDF parameters:
-  sc = parseLhaPdfCommands( m_defaultLhaPdfSettings ) ;
-  // Set user LHAPDF parameters:
-  sc = parseLhaPdfCommands( m_userLhaPdfSettings ) ;
-  if ( ! sc.isSuccess() ) 
-    return Error( "Unable to read LHAPDF commands" , sc ) ;
-
-  // retrieve the particle property service
-  m_ppSvc = svc< LHCb::IParticlePropertySvc >( "LHCb::ParticlePropertySvc" , true ) ;
-
-  // obtain the Decay Tool 
-  // (ATTENTION: it has to be initialized before the production tool)
-  if ( "" != m_decayToolName ) 
-    m_decayTool = tool< IDecayTool >( m_decayToolName ) ;
-
-  // obtain the Production Tool
-  if ( "" != m_productionToolName ) 
-    m_productionTool = tool< IProductionTool >( m_productionToolName , this ) ;
-
-  // update the particle properties of the production tool
-  if ( 0 != m_productionTool ) {
-    LHCb::IParticlePropertySvc::iterator iter ;
-    for ( iter = m_ppSvc -> begin() ; iter != m_ppSvc -> end() ; ++iter ) {
-      if ( ( ! m_productionTool -> isSpecialParticle( *iter ) ) && 
-           ( ! m_keepOriginalProperties ) ) 
-        m_productionTool -> updateParticleProperties( *iter ) ;
-      // set stable in the Production generator all particles known to the
-      // decay tool
-      if ( 0 != m_decayTool )
-        if ( m_decayTool -> isKnownToDecayTool( (*iter)->pdgID().pid() ) ) 
-          m_productionTool -> setStable( *iter ) ;    
-    }
-  }
-
-  // obtain the cut tool
-  if ( "" != m_cutToolName ) 
-    m_cutTool = tool< IGenCutTool >( m_cutToolName , this ) ;
-
-  if ( 0 != m_productionTool ) 
-    m_productionTool -> initializeGenerator();
-
-  // obtain the log tool
-  m_xmlLogTool = tool< ICounterLogFile >( "XmlCounterLogFile" ) ;
-
-  // now debug printout of Production Tool 
-  // has to be after all initializations to be sure correct values are printed
-  if ( 0 != m_productionTool ) { 
-    m_productionTool -> printRunningConditions( ) ;  
-    
-    boost::char_separator<char> sep(".");
-    boost::tokenizer< boost::char_separator<char> > 
-      strList( m_productionTool -> name() , sep ) ;
-
-    
-    std::string result = "" ;
-    for ( boost::tokenizer< boost::char_separator<char> >::iterator 
-            tok_iter = strList.begin();
-          tok_iter != strList.end(); ++tok_iter)
-      result = (*tok_iter) ;
-    m_hepMCName = boost::algorithm::ierase_last_copy( result , "Production" ) ;
-  } else {
-    m_hepMCName = "DecayAlone" ;
-  }
-
-  return StatusCode::SUCCESS ;
-}
-
-//=============================================================================
-// Decay heavy excited particles
-//=============================================================================
-StatusCode ExternalGenerator::decayHeavyParticles( HepMC::GenEvent * theEvent,
-     const LHCb::ParticleID::Quark theQuark , const int signalPid ) const {
-  StatusCode sc ;
-  
-  if ( 0 == m_decayTool ) return StatusCode::SUCCESS ;
-
-  m_decayTool -> disableFlip() ;
-
-  HepMCUtils::ParticleSet particleSet ;  
-
-  HepMC::GenEvent::particle_iterator it ;
-  switch ( theQuark ) {
-    
-  case LHCb::ParticleID::bottom: // decay only B
-    for ( it = theEvent -> particles_begin() ; 
-          it != theEvent -> particles_end() ; ++it )
-      if ( LHCb::ParticleID( (*it) -> pdg_id() ).hasQuark( theQuark ) ) 
-        particleSet.insert( *it ) ;
-    break ;
-    
-  case LHCb::ParticleID::charm: // decay B + D
-    for ( it = theEvent -> particles_begin() ;
-          it != theEvent -> particles_end() ; ++it ) {
-      LHCb::ParticleID pid( (*it) -> pdg_id() ) ;
-      if ( ( pid.hasQuark( theQuark ) ) || 
-           ( pid.hasQuark( LHCb::ParticleID::bottom ) ) ) 
-        particleSet.insert( *it ) ;
-    }
-    break ;
-    
-  default:
-    
-    if ( 15 == LHCb::ParticleID(signalPid).abspid() ) // tau ?
-    {
-      for ( it = theEvent -> particles_begin() ;
-            it != theEvent -> particles_end() ; ++it ) {
-        LHCb::ParticleID pid( (*it) -> pdg_id() ) ;
-        if ( ( pid.hasQuark( LHCb::ParticleID::charm  ) ) || 
-             ( pid.hasQuark( LHCb::ParticleID::bottom ) ) ) 
-          particleSet.insert( *it ) ;
-      }
-      break ; 
-    }
-    else 
-    {
-      // decay all what is heavier than the signal
-      for ( it = theEvent -> particles_begin() ;
-            it != theEvent -> particles_end() ; ++it ) {
-        LHCb::ParticleID pid( (*it) -> pdg_id() ) ;
-        if ( (*it) -> generated_mass() > 
-             m_ppSvc -> find( LHCb::ParticleID( signalPid ) ) -> mass() )
-          particleSet.insert( *it ) ;
-        // if signal is KS then decay also K0
-        else if ( ( signalPid == 310 ) && ( pid.abspid() == 311 ) )
-          particleSet.insert( *it ) ;
-      }      
-    }
-    break ; 
-  }
-  
-  for ( HepMCUtils::ParticleSet::iterator itHeavy = particleSet.begin() ; 
-        itHeavy != particleSet.end() ; ++itHeavy ) 
-    
-    if ( ( LHCb::HepMCEvent::StableInProdGen == (*itHeavy) -> status() ) && 
-         ( signalPid != abs( (*itHeavy) -> pdg_id() ) ) ) {
-      
-      if ( m_decayTool -> isKnownToDecayTool( (*itHeavy) -> pdg_id() ) ) {
-        sc = m_decayTool -> generateDecayWithLimit( *itHeavy , signalPid ) ;
-        if ( ! sc.isSuccess() ) return sc ;
-      } 
-    }
-  
-  return StatusCode::SUCCESS ;
-}
-
-//=============================================================================
-// Check the presence of a particle of given type in event
-// Attention : pidList must be sorted before begin used in this function
-//=============================================================================
-bool ExternalGenerator::checkPresence( const PIDs & pidList ,
-                                       const HepMC::GenEvent * theEvent ,
-                                       ParticleVector & particleList ) const {
-  particleList.clear( ) ;
-  HepMC::GenEvent::particle_const_iterator it ;
-  for ( it = theEvent -> particles_begin() ; 
-        it != theEvent -> particles_end() ; ++it ) 
-    if ( std::binary_search( pidList.begin() , pidList.end() ,
-                             (*it) -> pdg_id() ) ) 
-      if ( ( LHCb::HepMCEvent::DocumentationParticle != (*it) -> status() ) 
-           && ( HepMCUtils::IsBAtProduction( *it ) ) )
-        particleList.push_back( *it ) ;
-
-  std::sort( particleList.begin() , particleList.end() , 
-             HepMCUtils::compareHepMCParticles ) ;
-
-  return ( ! particleList.empty() ) ;
-}
-
-//=============================================================================
-// invert the event
-//=============================================================================
-void ExternalGenerator::revertEvent( HepMC::GenEvent * theEvent ) const {
-  HepMC::GenEvent::vertex_iterator itv ;
-  double x, y, z, t ;
-  for ( itv = theEvent -> vertices_begin() ;
-        itv != theEvent -> vertices_end() ; ++itv ) {
-    x = (*itv) -> position().x() ;
-    y = (*itv) -> position().y() ;
-    z = (*itv) -> position().z() ;
-    t = (*itv) -> position().t() ;
-    (*itv) -> set_position( HepMC::FourVector( x, y, -z, t ) ) ;
-  }
-
-  HepMC::GenEvent::particle_iterator itp ;
-  double px, py, pz, E ;
-  for ( itp = theEvent -> particles_begin() ;
-        itp != theEvent -> particles_end() ; ++itp ) {
-    px = (*itp) -> momentum().px() ;
-    py = (*itp) -> momentum().py() ;
-    pz = (*itp) -> momentum().pz() ;
-    E  = (*itp) -> momentum().e() ;
-    (*itp) -> set_momentum( HepMC::FourVector( px, py, -pz, E ) ) ;
-  }      
-}
-
-//=============================================================================
-// count the number of particles with pz > 0
-//=============================================================================
-unsigned int ExternalGenerator::nPositivePz( const ParticleVector 
-                                             & particleList ) const {
-  ParticleVector::const_iterator iter ;
-  unsigned int nP = 0 ;
-  for ( iter = particleList.begin() ; iter != particleList.end() ; ++iter ) 
-    if ( (*iter)->momentum().pz() > 0 ) nP++ ;
-  
-  return nP ;
-}
-
-
-//=============================================================================
-// Set up event
-//=============================================================================
-void ExternalGenerator::prepareInteraction( LHCb::HepMCEvents * theEvents ,
-    LHCb::GenCollisions * theCollisions , HepMC::GenEvent * & theGenEvent ,  
-    LHCb::GenCollision * & theGenCollision ) const {
-  LHCb::HepMCEvent * theHepMCEvent = new LHCb::HepMCEvent( ) ;
-  theHepMCEvent -> setGeneratorName( m_hepMCName ) ;
-  theGenEvent = theHepMCEvent -> pGenEvt() ;
-
-  theGenCollision = new LHCb::GenCollision() ;  
-  theGenCollision -> setEvent( theHepMCEvent ) ;
-  theGenCollision -> setIsSignal( false ) ;
-
-  theEvents -> insert( theHepMCEvent ) ;
-  theCollisions -> insert( theGenCollision ) ;
-}
-
-//=============================================================================
-// Parse LHAPDF commands stored in a vector
-//=============================================================================
-StatusCode ExternalGenerator::parseLhaPdfCommands( const CommandVector & 
-                                                   theCommandVector ) const {
-  //
-  // Parse Commands and Set Values from Properties Service...
-  //
-  CommandVector::const_iterator iter ;
-  for ( iter = theCommandVector.begin() ; theCommandVector.end() != iter ; 
-        ++iter ) {
-    debug() << " Command is: " << (*iter) << endmsg ;
-    StringParse mystring( *iter ) ;
-    std::string block = mystring.piece(1);
-    std::string entry = mystring.piece(2);
-    std::string str   = mystring.piece(4);
-    int    int1  = mystring.intpiece(3);
-    double fl1   = mystring.numpiece(3);
-    
-    // Note that Pythia needs doubles hence the convert here
-    debug() << block << " block  " << entry << " item  " << int1 
-            << "  value " << fl1 << " str " << str << endmsg ;
-    if ( "lhacontrol" == block )  
-      if      ( "lhaparm" == entry ) 
-        LhaPdf::lhacontrol().setlhaparm( int1 , str ) ;
-      else if ( "lhavalue" == entry ) 
-        LhaPdf::lhacontrol().setlhavalue( int1 , fl1 ) ;
-      else return Error( std::string( "LHAPDF ERROR, block LHACONTROL has " ) +
-                         std::string( "LHAPARM and LHAVALUE: YOU HAVE " ) + 
-                         std::string( "SPECIFIED " ) + std::string( entry ) ) ;
-    else return Error( std::string( " ERROR in LHAPDF PARAMETERS   " ) +
-                       std::string( block ) +
-                       std::string( " is and invalid common block name !" ) ) ;
-  }
-  
-  return StatusCode::SUCCESS ;
-}
-//=============================================================================
-// Finalize method
-//=============================================================================
-StatusCode ExternalGenerator::finalize( ) {
-  if ( 0 != m_decayTool ) release( m_decayTool ) ;
-  if ( 0 != m_productionTool ) release( m_productionTool ) ;
-  if ( 0 != m_cutTool ) release( m_cutTool ) ;
-  if ( 0 != m_ppSvc ) release( m_ppSvc ) ;
-
-  // set the name of the method
-  m_xmlLogTool -> addMethod( this -> name() ) ;
-  // set the name of the generator
-  m_xmlLogTool -> addGenerator( m_hepMCName ) ;
-
-  return GaudiTool::finalize() ;
-}
diff --git a/Gen/Generators/src/Lib/F77Utils.cpp b/Gen/Generators/src/Lib/F77Utils.cpp
deleted file mode 100755
index 3bb6dc8b8..000000000
--- a/Gen/Generators/src/Lib/F77Utils.cpp
+++ /dev/null
@@ -1,241 +0,0 @@
-// $Id: F77Utils.cpp,v 1.2 2007-06-29 13:21:06 ibelyaev Exp $
-// ============================================================================
-// Include files
-// ============================================================================
-// STD & STL 
-// ============================================================================
-#include <ctype.h>
-#include <iostream>
-// ============================================================================
-// Generators 
-// ============================================================================
-#include "Generators/F77Utils.h"
-// ============================================================================
-/** @file 
- *  Implementation file for functionf from namespace F77Units
- *  @date 2006-10-03 
- *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
- */
-// ============================================================================
-//  Open Fortran file with status="UNKNOWN" 
-// ============================================================================
-StatusCode F77Utils::open 
-( int                lun     , 
-  const std::string& file    , 
-  const bool         verbose )  
-{ return openUnknown ( lun , file , verbose ) ; }
-// ============================================================================
-// Open "FORMATTED" Fortran file with status="UNKNOWN" 
-// ============================================================================
-StatusCode F77Utils::openFormatted 
-( int                lun     , 
-  const std::string& file    , 
-  const bool         verbose )  
-{ return openUnknownFormatted ( lun , file , verbose ) ; }
-// ============================================================================
-extern "C"
-{
-#ifdef WIN32 
-  int __stdcall F77CLFILE   (int* LUN );
-  int __stdcall F77ONFILE   (int* LUN ,const char* FILE, int LEN );
-  int __stdcall F77OOFILE   (int* LUN ,const char* FILE, int LEN );
-  int __stdcall F77OUFILE   (int* LUN ,const char* FILE, int LEN );
-  int __stdcall F77ONFFILE  (int* LUN ,const char* FILE, int LEN );
-  int __stdcall F77OOFFILE  (int* LUN ,const char* FILE, int LEN );
-  int __stdcall F77OUFFILE  (int* LUN ,const char* FILE, int LEN );
-  int __stdcall F77GETUNIT  (int* LUN ) ;
-#define f77clfile  F77CLFILE  
-#define f77onfile  F77ONFILE  
-#define f77oofile  F77OOFILE  
-#define f77oufile  F77OUFILE  
-#define f77onffile F77ONFFILE  
-#define f77ooffile F77OOFFILE  
-#define f77ouffile F77OUFFILE
-#define f77getunit F77GETUNIT
-#else 
-  int           f77clfile_  (int* LUN ) ;
-  int           f77onfile_  (int* LUN , const char* FILE, int LEN ) ;
-  int           f77oofile_  (int* LUN , const char* FILE, int LEN ) ;
-  int           f77oufile_  (int* LUN , const char* FILE, int LEN ) ;
-  int           f77onffile_ (int* LUN , const char* FILE, int LEN ) ;
-  int           f77ooffile_ (int* LUN , const char* FILE, int LEN ) ;
-  int           f77ouffile_ (int* LUN , const char* FILE, int LEN ) ;
-  int           f77getunit_ (int* LUN ) ;
-#define f77clfile  f77clfile_
-#define f77onfile  f77onfile_
-#define f77oofile  f77oofile_
-#define f77oufile  f77oufile_
-#define f77onffile f77onffile_
-#define f77ooffile f77ooffile_
-#define f77ouffile f77ouffile_
-#define f77getunit f77getunit_
-#endif 
-}
-// ==========================================================================
-// close the opened F77 file 
-// ==========================================================================
-StatusCode F77Utils::close ( int lun , const bool verbose ) 
-{ 
-  const int result = f77clfile( &lun )  ;
-  if ( result != lun ) 
-  { 
-    std::cerr << "F77Utils::close()               ERROR Error in closing LUN=" 
-              << lun << std::endl ; 
-  }
-  else if ( verbose ) 
-  { 
-    std::cout << "F77Utils::close()               INFO  LUN=" 
-              << lun << " is closed " << std::endl ; 
-  }
-  return result != lun ?  StatusCode::FAILURE : StatusCode::SUCCESS ;
-} 
-// ==========================================================================
-// Open Fortran file with status="NEW" 
-// ==========================================================================
-StatusCode F77Utils::openNew 
-( int                lun     , 
-  const std::string& file    , 
-  const bool         verbose )  
-{
-  const int result = f77onfile ( &lun , file.c_str() , file.size() ) ;
-  if ( result != lun ) 
-  { 
-    std::cerr << "F77Utils::openNew               ERROR Error in opening LUN=" << lun 
-              << " FILE='"<< file << "' "<< std::endl ; 
-  }
-  else if ( verbose ) 
-  {
-    std::cout << "F77Utils::openNew               INFO  LUN=" << lun 
-              << " FILE='"<< file << "' is opened "<< std::endl ; 
-  }
-  return result != lun ? StatusCode::FAILURE : StatusCode::SUCCESS ;
-} 
-// ==========================================================================
-// Open Fortran file with status="OLD" 
-// ==========================================================================
-StatusCode F77Utils::openOld 
-( int                lun     , 
-  const std::string& file    , 
-  const bool         verbose )  
-{
-  const int result = f77oofile ( &lun , file.c_str() , file.size() ) ;
-  if ( result != lun ) 
-  { 
-    std::cerr << "F77Utils::openOld               ERROR Error in opening LUN=" << lun 
-              << " FILE='"<< file << "' "<< std::endl ; 
-  }
-  else if ( verbose ) 
-  {
-    std::cout << "F77Utils::openOld               INFO  LUN=" << lun 
-              << " FILE='"<< file << "' is opened "<< std::endl ; 
-  }  
-  return result != lun ? StatusCode::FAILURE : StatusCode::SUCCESS ;
-} 
-// ==========================================================================
-// Open Fortran file with status="UNKNOWN" 
-// ==========================================================================
-StatusCode F77Utils::openUnknown 
-( int                lun     , 
-  const std::string& file    , 
-  const bool         verbose )  
-{
-  const int result = f77oufile ( &lun , file.c_str() , file.size() ) ;
-  if ( result != lun ) 
-  { 
-    std::cerr << "F77Utils::openUnknown           ERROR Error in opening LUN=" << lun 
-              << " FILE='"<< file << "' "<< std::endl ; 
-  }
-  else if ( verbose ) 
-  {
-    std::cout << "F77Utils::openUnknown           INFO  LUN=" << lun 
-              << " FILE='"<< file << "' is opened "<< std::endl ; 
-  }    
-  return result != lun ? StatusCode::FAILURE : StatusCode::SUCCESS ;
-} 
-// ==========================================================================
-// Open "FORMATTED" Fortran file with status="NEW" 
-// ==========================================================================
-StatusCode F77Utils::openNewFormatted 
-( int                lun     , 
-  const std::string& file    , 
-  const bool         verbose )  
-{
-  const int result = f77onffile ( &lun , file.c_str() , file.size() ) ;
-  if ( result != lun ) 
-  { 
-    std::cerr << "F77Utils::openNewFormatted      ERROR Error in opening LUN=" << lun 
-              << " FILE='"<< file << "' "<< std::endl ; 
-  }
-  else if ( verbose ) 
-  {
-    std::cout << "F77Utils::openNewFormatted      INFO  LUN=" << lun 
-              << " FILE='"<< file << "' is opened "<< std::endl ; 
-  }    
-  return result != lun ? StatusCode::FAILURE : StatusCode::SUCCESS ;
-}
-// ==========================================================================
-// Open "FORMATTED" Fortran file with status="OLD" 
-// ==========================================================================
-StatusCode F77Utils::openOldFormatted 
-( int                lun     , 
-  const std::string& file    , 
-  const bool         verbose )  
-{
-  const int result = f77ooffile ( &lun , file.c_str() , file.size() ) ;
-  if ( result != lun ) 
-  { 
-    std::cerr << "F77Utils::openOldFormatted      ERROR Error in opening LUN=" << lun 
-              << " FILE='"<< file << "' "<< std::endl ; 
-  }
-  else if ( verbose ) 
-  {
-    std::cout << "F77Utils::openOldFormatted      INFO  LUN=" << lun 
-              << " FILE='"<< file << "' is opened "<< std::endl ; 
-  }  
-  return result != lun ? StatusCode::FAILURE : StatusCode::SUCCESS ;
-}
-// ==========================================================================
-// Open "FORMATTED" Fortran file with status="UNKNOWN" 
-// ==========================================================================
-StatusCode F77Utils::openUnknownFormatted 
-( int                lun     , 
-  const std::string& file    , 
-  const bool         verbose )  
-{
-  const int result = f77ouffile ( &lun , file.c_str() , file.size() ) ;
-  if ( result != lun ) 
-  { 
-    std::cerr << "F77Utils::openUnknownFormatted  ERROR Error in opening LUN=" << lun 
-              << " FILE='"<< file << "' "<< std::endl ; 
-  }
-  else if ( verbose )
-  {
-    std::cout << "F77Utils::openUnknownFormatted  INFO  LUN=" << lun 
-              << " FILE='"<< file << "' is opened "<< std::endl ; 
-  }  
-  return result != lun ? StatusCode::FAILURE : StatusCode::SUCCESS ;
-}
-// ==========================================================================
-// find free fortran unit
-// ==========================================================================
-int F77Utils::getUnit( const bool verbose ) 
-{
-  int n = 0 ;
-  const int result = f77getunit ( &n ) ;
-  if ( 0 >= result || 100 <= result ) 
-  {
-    std::cerr << "F77Utils::getUnit               ERROR No free units" << std::endl ;
-  } 
-  else if ( verbose )  
-  {
-    std::cout << "F77Utils::getUnit               INFO  Free unit LUN=" << result << std::endl ;
-  }
-  return result ;
-}
-// ==========================================================================
-
-
-
-// ============================================================================
-// The END 
-// ============================================================================
diff --git a/Gen/Generators/src/Lib/GenCounters.cpp b/Gen/Generators/src/Lib/GenCounters.cpp
deleted file mode 100755
index 29b114940..000000000
--- a/Gen/Generators/src/Lib/GenCounters.cpp
+++ /dev/null
@@ -1,607 +0,0 @@
-// $Id: GenCounters.cpp,v 1.5 2007-09-11 17:48:32 robbep Exp $
-// Include files
-
-// local
-#include "Generators/GenCounters.h"
-
-// Generators
-#include "GenEvent/HepMCUtils.h"
-
-// Boost
-#include <boost/array.hpp>
-
-// HepMC
-#include "HepMC/GenEvent.h"
-
-// Event
-#include "Event/HepMCEvent.h"
-#include "Event/GenFSR.h"
-#include "Event/GenCountersFSR.h"
-
-// LHCb
-#include "Kernel/ParticleID.h"
-
-//=============================================================================
-// Function to test if a HepMC::GenParticle is a B hadron at root of decay
-//=============================================================================
-struct isRootB : std::unary_function< const HepMC::GenParticle * , bool > {
-
-  /// test operator, returns true if it is a root B
-  bool operator() ( const HepMC::GenParticle * part ) const {
-
-    // Do not consider documentation and special particles
-    if ( part -> status() == LHCb::HepMCEvent::DocumentationParticle ) 
-      return false ;
-    
-    // Check if particle has a b quark
-    LHCb::ParticleID thePid( part -> pdg_id() ) ;
-    if ( ! thePid.hasBottom() ) return false ;
-
-    // Check if particle has a mother
-    if ( 0 == part -> production_vertex() ) return true ;
-
-    // Check all parents of the B 
-    HepMC::GenVertex::particles_in_const_iterator parent ;
-    const HepMC::GenVertex * thePV = part -> production_vertex() ;
-    for ( parent = thePV -> particles_in_const_begin() ;
-          parent != thePV -> particles_in_const_end() ; ++parent ) {
-      LHCb::ParticleID parentID( (*parent) -> pdg_id() ) ;
-      if ( parentID.hasBottom() && (thePid.abspid()==5 || parentID.abspid()!=5)) return false ;
-    }
-
-    // If no parent is a B, then it is a root B
-    return true ;
-  }
-};
-
-//=============================================================================
-// Function to test if a HepMC::GenParticle is a D hadron at root of decay
-//=============================================================================
-struct isRootD : std::unary_function< const HepMC::GenParticle * , bool > {
-
-  /// test operator, returns true if it is a root D
-  bool operator() ( const HepMC::GenParticle * part ) const {
-
-    // Do not consider documentation and special particles
-    if ( part -> status() == LHCb::HepMCEvent::DocumentationParticle ) 
-      return false ;
-
-    // Check if particle has a c quark
-    LHCb::ParticleID thePid( part -> pdg_id() ) ;
-    if ( ! thePid.hasCharm() ) return false ;
-    if ( thePid.hasBottom() ) return false ;
-
-    // Check if particle has a mother
-    if ( 0 == part -> production_vertex() ) return true ;
-
-    // Check all parents of the D
-    HepMC::GenVertex::particles_in_const_iterator parent ;
-    const HepMC::GenVertex * thePV = part -> production_vertex() ;
-    for ( parent = thePV -> particles_in_const_begin() ;
-          parent != thePV -> particles_in_const_end() ; ++parent ) {
-      LHCb::ParticleID parentID( (*parent) -> pdg_id() ) ;
-      if ( parentID.hasCharm()  && (parentID.abspid()!=4 || thePid.abspid()==4)) return false ;
-    }
-
-    // If no parent is a D, then it is a root D
-    return true ;
-  }
-};
-
-//=============================================================================
-// Function to test if a HepMC::GenParticle is a B hadron at end of decay tree
-//=============================================================================
-struct isEndB : std::unary_function< const HepMC::GenParticle * , bool > {
-
-  /// Test operator. Returns true if particle is the last B
-  bool operator() ( const HepMC::GenParticle * part ) const {
-
-    // Do not look at special particles
-    if ( part -> status() == LHCb::HepMCEvent::DocumentationParticle ) 
-      return false ;
-
-    // Test if particle has a b quark
-    LHCb::ParticleID thePid( part -> pdg_id() ) ;
-    if ( ! thePid.hasBottom() ) return false ;
-
-    // test oscillation
-    if ( ! HepMCUtils::IsBAtProduction( part ) ) return false ;
-
-    // Test if the B has daughters (here we are sure it has not oscillated)
-    if ( 0 == part -> end_vertex() ) return true ;
-    
-    // Loop over daughters to check if they are B hadrons
-    HepMC::GenVertex::particles_out_const_iterator children ;
-    const HepMC::GenVertex * theEV = part -> end_vertex() ;
-    for ( children = theEV -> particles_out_const_begin() ;
-          children != theEV -> particles_out_const_end() ; ++children ) {
-      LHCb::ParticleID childID( (*children) -> pdg_id() ) ;
-      if ( childID.hasBottom() ) {
-        if ( (*children) -> pdg_id() == - part -> pdg_id() ) return true ;
-        return false ;
-      }
-    }
-
-    // If not, then it is a end B
-    return true ;
-  }
-};
-
-//=============================================================================
-// Function to test if a HepMC::GenParticle is a D hadron at end of decay tree
-//=============================================================================
-struct isEndD : std::unary_function< const HepMC::GenParticle * , bool > {
-
-  /// Test operator. Returns true if it is the last D
-  bool operator() ( const HepMC::GenParticle * part ) const {
-
-    // Do not look at special particles
-    if ( part -> status() == LHCb::HepMCEvent::DocumentationParticle ) 
-      return false ;
-
-    // Check if it has a c quark
-    LHCb::ParticleID thePid( part -> pdg_id() ) ;
-    if ( ! thePid.hasCharm() ) return false ;
-
-    // Check if it has daughters
-    if ( 0 == part -> end_vertex() ) return true ;
-
-    // Loop over the daughters to find a D hadron
-    HepMC::GenVertex::particles_out_const_iterator children ;
-    const HepMC::GenVertex * theEV = part -> end_vertex() ;
-    for ( children = theEV -> particles_out_const_begin() ;
-          children != theEV -> particles_out_const_end() ; ++children ) {
-      LHCb::ParticleID childID( (*children) -> pdg_id() ) ;
-      if ( childID.hasCharm() ) return false ;
-    }
-
-    // If not, then it is a End D
-    return true ;
-  }
-};
-
-//-----------------------------------------------------------------------------
-// Implementation file for namespace : GenCounters
-//
-// 2006-02-06 : Patrick Robbe
-//-----------------------------------------------------------------------------
-
-//=============================================================================
-// Setup names of B hadron counters
-//=============================================================================
-void GenCounters::setupBHadronCountersNames( BHadronCNames & BC , 
-                                             BHadronCNames & antiBC ) {
-    BC[ Bd ] = "B0" ;
-    BC[ Bu ] = "B+" ;
-    BC[ Bs ] = "Bs0" ;
-    BC[ Bc ] = "Bc+" ;
-    BC[ bBaryon ] = "b-Baryon" ;
-
-    antiBC[ Bd ] = "anti-B0" ;
-    antiBC[ Bu ] = "B-" ;
-    antiBC[ Bs ] = "anti-Bs0" ;
-    antiBC[ Bc ] = "Bc-" ;
-    antiBC[ bBaryon ] = "anti-b-Baryon" ;
-}
-
-//=============================================================================
-// Setup names of D hadron counters
-//=============================================================================
-void GenCounters::setupDHadronCountersNames( DHadronCNames & DC , 
-                                             DHadronCNames & antiDC ) {
-    DC[ D0 ] = "D0" ;
-    DC[ Dch ] = "D+" ;
-    DC[ Ds ] = "Ds+" ;
-    DC[ cBaryon ] = "c-Baryon" ;
-
-    antiDC[ D0 ] = "anti-D0" ;
-    antiDC[ Dch ] = "D-" ;
-    antiDC[ Ds ] = "Ds-" ;
-    antiDC[ cBaryon ] = "anti-c-Baryon" ;
-}
-
-//=============================================================================
-// Setup names of B excited states
-//=============================================================================
-void GenCounters::setupExcitedCountersNames( ExcitedCNames & B , 
-                                             const std::string & root ) {
-  B[ _0star ] = root + "(L=0,J=0)";
-    B[ _1star ] = root + "* (L=0, J=1)" ;
-    B[ _2star ] = root + "** (L=1, J=0,1,2)" ;
-}
-
-//=============================================================================
-// Count excited states counters
-//=============================================================================
-void GenCounters::updateExcitedStatesCounters
-( const HepMC::GenEvent * theEvent , ExcitedCounter & thebExcitedC ,
-  ExcitedCounter & thecExcitedC ) {
-  // Signal Vertex
-  HepMC::GenVertex * signalV = theEvent -> signal_process_vertex() ;
-
-  // Count B :
-  std::vector< HepMC::GenParticle * > rootB ;
-  HepMC::copy_if( theEvent -> particles_begin() , theEvent -> particles_end() ,
-                  std::back_inserter( rootB ) , isRootB() ) ;
-
-  std::vector< HepMC::GenParticle * >::const_iterator iter ;
-
-  for ( iter = rootB.begin() ; iter != rootB.end() ; ++iter ) {
-    if ( 0 != signalV ) {
-      if ( ! HepMCUtils::commonTrees( signalV ,
-                                      (*iter) -> end_vertex() ) ) 
-        continue ;
-    }
-    LHCb::ParticleID thePid( (*iter) -> pdg_id() ) ;
-
-    if ( thePid.isMeson() ) {
-      if ( 0 == thePid.lSpin() ) {
-        if ( 1 == thePid.jSpin() ) ++thebExcitedC[ _0star ] ;
-        else ++thebExcitedC[ _1star ] ;
-      } else ++thebExcitedC[ _2star ] ;
-    }
-  }
-
-  // Count D :
-  std::vector< HepMC::GenParticle * > rootD ;
-  HepMC::copy_if( theEvent -> particles_begin() , theEvent -> particles_end() ,
-                  std::back_inserter( rootD ) , isRootD() ) ;
-
-  for ( iter = rootD.begin() ; iter != rootD.end() ; ++iter ) {
-    if ( 0 != signalV ) {
-      if ( ! HepMCUtils::commonTrees( signalV , 
-                                      (*iter) -> end_vertex() ) ) 
-        continue ;
-    }
-    
-    LHCb::ParticleID thePid( (*iter) -> pdg_id() ) ;
-    if ( thePid.isMeson() ) {
-      if ( 0 == thePid.lSpin() ) {
-        if ( 1 == thePid.jSpin() ) ++thecExcitedC[ _0star ] ;
-        else ++thecExcitedC[ _1star ] ;
-        } else ++thecExcitedC[ _2star ] ;
-    }
-  }       
-}
-
-//=============================================================================
-// Update the counters of number of different hadrons in selected events
-//=============================================================================
-void GenCounters::updateHadronCounters( const HepMC::GenEvent * theEvent ,
-                                        BHadronCounter & thebHadC , 
-                                        BHadronCounter & theantibHadC ,
-                                        DHadronCounter & thecHadC ,
-                                        DHadronCounter & theanticHadC ,
-                                        unsigned int & thebbCounter ,
-                                        unsigned int & theccCounter ) {
-  // Signal vertex
-  HepMC::GenVertex * signalV = theEvent -> signal_process_vertex() ;
-
-  // Count B:
-  std::vector< HepMC::GenParticle * > endB ;
-  HepMC::copy_if( theEvent -> particles_begin() , theEvent -> particles_end() ,
-                  std::back_inserter( endB ) , isEndB() ) ;
-  std::vector< HepMC::GenParticle * >::const_iterator iter ;
-  
-  for ( iter = endB.begin() ; iter != endB.end() ; ++iter ) {
-    if ( 0 != signalV ) {
-      if ( HepMCUtils::commonTrees( signalV , 
-                                    (*iter) -> end_vertex() ) )
-        continue ;
-    }
-    
-    LHCb::ParticleID thePid( (*iter) -> pdg_id() ) ;
-    
-    if ( thePid.isMeson() ) {
-      if ( thePid.pid() > 0 ) {
-        if ( thePid.hasUp() ) ++thebHadC[ Bu ] ;
-        else if ( thePid.hasDown() ) ++thebHadC[ Bd ] ;
-        else if ( thePid.hasStrange() ) ++thebHadC[ Bs ] ;
-        else if ( thePid.hasCharm() ) ++thebHadC[ Bc ] ;
-        else ++thebbCounter ;
-      } else {
-        if ( thePid.hasUp() ) ++theantibHadC[ Bu ] ;
-        else if ( thePid.hasDown() ) ++theantibHadC[ Bd ] ;
-        else if ( thePid.hasStrange() ) ++theantibHadC[ Bs ] ;
-        else if ( thePid.hasCharm() ) ++theantibHadC[ Bc ] ;
-        else ++thebbCounter ;
-      }
-    } else if ( thePid.isBaryon() ) {
-      if ( thePid.pid() < 0 ) ++thebHadC[ bBaryon ] ;
-      else ++theantibHadC[ bBaryon ] ;
-    }
-  }
-  
-  std::vector< HepMC::GenParticle * > endD ;
-  HepMC::copy_if( theEvent -> particles_begin() , theEvent -> particles_end() ,
-                  std::back_inserter( endD ) , isEndD() ) ;
-  
-  for ( iter = endD.begin() ; iter != endD.end() ; ++iter ) {
-    if ( 0 != signalV ) {
-      if ( HepMCUtils::commonTrees( signalV ,
-                                    (*iter) -> end_vertex() ) ) 
-        continue ;
-    }
-    
-    LHCb::ParticleID thePid( (*iter) -> pdg_id() ) ;
-    
-    if ( thePid.isMeson() ) {
-      if ( thePid.pid() > 0 ) {
-        if ( thePid.hasUp() ) ++thecHadC[ D0 ] ;
-        else if ( thePid.hasDown() ) ++thecHadC[ Dch ] ;
-        else if ( thePid.hasStrange() ) ++thecHadC[ Ds ] ;
-        else ++theccCounter ;
-      } else {
-        if ( thePid.hasUp() ) ++theanticHadC[ D0 ] ;
-        else if ( thePid.hasDown() ) ++theanticHadC[ Dch ] ;
-        else if ( thePid.hasStrange() ) ++theanticHadC[ Ds ] ;
-        else ++theccCounter ;
-      }
-    } else if ( thePid.isBaryon() ) {
-      if ( thePid.pid() > 0 ) ++thecHadC[ cBaryon ] ;
-      else ++theanticHadC[ cBaryon ] ;
-    }
-  } 
-}
-
-
-//=============================================================================                    
-// Update the genFRS in selected events                                                            
-//=============================================================================                    
-void GenCounters::updateHadronFSR( const HepMC::GenEvent * theEvent ,
-                                   LHCb::GenFSR* genFSR,
-                                   const std::string option)
-{  
-  // Signal Vertex                                                                        
-  HepMC::GenVertex * signalV = theEvent -> signal_process_vertex() ;
-  int key = 0;
-  
-  // Count B :                                                                                    
-  std::vector< HepMC::GenParticle * > rootB ;
-  HepMC::copy_if( theEvent -> particles_begin() , theEvent -> particles_end() ,
-                  std::back_inserter( rootB ) , isRootB() ) ;
-
-  std::vector< HepMC::GenParticle * >::const_iterator iter ;
-
-  for ( iter = rootB.begin() ; iter != rootB.end() ; ++iter )
-  {
-    if ( 0 != signalV )
-    {  
-      if ( ! HepMCUtils::commonTrees( signalV ,
-                                      (*iter) -> end_vertex() ) )
-        continue ; 
-    }    
-    LHCb::ParticleID thePid( (*iter) -> pdg_id() ) ;
-
-    if (thePid.isMeson())
-    {
-      if (0 == thePid.lSpin())
-      {
-        if (1 == thePid.jSpin())
-        {
-          key = LHCb::GenCountersFSR::CounterKeyToType("B"+option);
-          genFSR->incrementGenCounter(key, 1); 
-        }
-        else
-        {
-          key = LHCb::GenCountersFSR::CounterKeyToType("Bstar"+option);
-          genFSR->incrementGenCounter(key, 1); 
-        } 
-      }
-      else
-      {
-        key = LHCb::GenCountersFSR::CounterKeyToType("B2star"+option);
-        genFSR->incrementGenCounter(key, 1);                                                                                        
-      } 
-    } 
-  }
-
-  // Count D :                                                                                     
-  std::vector< HepMC::GenParticle * > rootD ;  
-  HepMC::copy_if( theEvent -> particles_begin() , theEvent -> particles_end() ,
-                  std::back_inserter( rootD ) , isRootD() ) ;
-
-  for ( iter = rootD.begin() ; iter != rootD.end() ; ++iter )
-  {
-    if ( 0 != signalV )
-    {
-      if ( ! HepMCUtils::commonTrees( signalV ,
-                                      (*iter) -> end_vertex() ) )
-        continue ; 
-    }
-
-    LHCb::ParticleID thePid( (*iter) -> pdg_id() );
-
-    if (thePid.isMeson())
-    {
-      if (0 == thePid.lSpin())
-      {
-        if (1 == thePid.jSpin())
-        {
-          key = LHCb::GenCountersFSR::CounterKeyToType("D"+option);
-          genFSR->incrementGenCounter(key, 1); 
-        }
-        else
-        {
-          key = LHCb::GenCountersFSR::CounterKeyToType("Dstar"+option);
-          genFSR->incrementGenCounter(key, 1); 
-        } 
-      }
-      else
-      {
-        key = LHCb::GenCountersFSR::CounterKeyToType("D2star"+option);
-        genFSR->incrementGenCounter(key, 1); 
-      } 
-    } 
-  }
-
-  // Count B:                                                                                     
-  std::vector< HepMC::GenParticle * > endB ;
-  HepMC::copy_if( theEvent -> particles_begin() , theEvent -> particles_end() ,
-                  std::back_inserter( endB ) , isEndB() ) ;
-
-  for ( iter = endB.begin() ; iter != endB.end() ; ++iter )
-  {
-    if ( 0 != signalV )
-    {
-      if ( HepMCUtils::commonTrees( signalV ,
-                                    (*iter) -> end_vertex() ) )
-        continue ;      
-    }
-
-    LHCb::ParticleID thePid( (*iter) -> pdg_id() ) ;
-
-    if ( thePid.isMeson() )                                                                                                               
-    {                                                                                                                                  
-      if ( thePid.pid() > 0 )
-      {                                                                                                                              
-        if ( thePid.hasUp() )                                                                                                         
-        {                                                              
-          key = LHCb::GenCountersFSR::CounterKeyToType("Bplus"+option);
-          genFSR->incrementGenCounter(key, 1);                                                                                       
-        }                                                                                                                          
-        else if ( thePid.hasDown() )                                                                                                  
-        {                                                                 
-          key = LHCb::GenCountersFSR::CounterKeyToType("B0"+option);
-          genFSR->incrementGenCounter(key, 1);                                                                                       
-        }                                                                                                                          
-        else if ( thePid.hasStrange() )                                                                                               
-        {
-          key = LHCb::GenCountersFSR::CounterKeyToType("Bs0"+option); 
-          genFSR->incrementGenCounter(key, 1);
-        }
-        else if ( thePid.hasCharm() )
-        {
-          key = LHCb::GenCountersFSR::CounterKeyToType("Bcplus"+option);
-          genFSR->incrementGenCounter(key, 1); 
-        }
-        else
-        {
-          key = LHCb::GenCountersFSR::CounterKeyToType("bb"+option);
-          genFSR->incrementGenCounter(key, 1); 
-        } 
-      }
-      else
-      {
-        if ( thePid.hasUp() )
-        {
-          key = LHCb::GenCountersFSR::CounterKeyToType("Bminus"+option);
-          genFSR->incrementGenCounter(key, 1);
-        }
-        else if ( thePid.hasDown() )
-        {
-          key = LHCb::GenCountersFSR::CounterKeyToType("antiB0"+option);
-          genFSR->incrementGenCounter(key, 1); 
-        }
-        else if ( thePid.hasStrange() )
-        {
-          key = LHCb::GenCountersFSR::CounterKeyToType("antiBs0"+option);
-          genFSR->incrementGenCounter(key, 1); 
-        }
-        else if ( thePid.hasCharm() )
-        {
-          key = LHCb::GenCountersFSR::CounterKeyToType("Bcminus"+option);
-          genFSR->incrementGenCounter(key, 1); 
-        }
-        else
-        {
-          key = LHCb::GenCountersFSR::CounterKeyToType("bb"+option);
-          genFSR->incrementGenCounter(key, 1); 
-        } 
-      } 
-    }
-    else if ( thePid.isBaryon() )
-    {
-      if ( thePid.pid() < 0 )
-      {
-        key = LHCb::GenCountersFSR::CounterKeyToType("bBaryon"+option);
-        genFSR->incrementGenCounter(key, 1); 
-      }
-      else
-      {
-        key = LHCb::GenCountersFSR::CounterKeyToType("antibBaryon"+option);
-        genFSR->incrementGenCounter(key, 1); 
-      } 
-    } 
-  }
-
-  // Count D:                                                                                   
-  std::vector< HepMC::GenParticle * > endD ;
-  HepMC::copy_if( theEvent -> particles_begin() , theEvent -> particles_end() ,
-                  std::back_inserter( endD ) , isEndD() ) ;
-
-  for ( iter = endD.begin() ; iter != endD.end() ; ++iter )
-  {
-    if ( 0 != signalV )
-    {
-      if ( HepMCUtils::commonTrees( signalV ,
-                                    (*iter) -> end_vertex() ) )
-        continue ;      
-    }
-
-    LHCb::ParticleID thePid( (*iter) -> pdg_id() ) ;
-
-    if ( thePid.isMeson() )
-    {
-      if ( thePid.pid() > 0 )
-      {
-        if ( thePid.hasUp() )
-        {
-          key = LHCb::GenCountersFSR::CounterKeyToType("D0"+option);
-          genFSR->incrementGenCounter(key, 1); 
-        }
-        else if ( thePid.hasDown() )
-        {
-          key = LHCb::GenCountersFSR::CounterKeyToType("Dplus"+option);
-          genFSR->incrementGenCounter(key, 1); 
-        }
-        else if ( thePid.hasStrange() )
-        {
-          key = LHCb::GenCountersFSR::CounterKeyToType("Dsplus"+option);
-          genFSR->incrementGenCounter(key, 1);
-        }
-        else
-        {
-          key = LHCb::GenCountersFSR::CounterKeyToType("cc"+option);
-          genFSR->incrementGenCounter(key, 1); 
-        } 
-      }
-      else
-      {
-        if ( thePid.hasUp() )
-        {
-          key = LHCb::GenCountersFSR::CounterKeyToType("antiD0"+option);
-          genFSR->incrementGenCounter(key, 1); 
-        }
-        else if ( thePid.hasDown() )
-        {
-          key = LHCb::GenCountersFSR::CounterKeyToType("Dminus"+option);
-          genFSR->incrementGenCounter(key, 1); 
-        }
-        else if ( thePid.hasStrange() )
-        {
-          key = LHCb::GenCountersFSR::CounterKeyToType("Dsminus"+option);
-          genFSR->incrementGenCounter(key, 1); 
-        }
-        else
-        {
-          key = LHCb::GenCountersFSR::CounterKeyToType("cc"+option);
-          genFSR->incrementGenCounter(key, 1); 
-        } 
-      } 
-    }
-    else if ( thePid.isBaryon() )
-    {
-      if ( thePid.pid() > 0 )
-      {
-        key = LHCb::GenCountersFSR::CounterKeyToType("cBaryon"+option);
-        genFSR->incrementGenCounter(key, 1); 
-      }
-      else
-      {
-        key = LHCb::GenCountersFSR::CounterKeyToType("anticBaryon"+option);
-        genFSR->incrementGenCounter(key, 1); 
-      } 
-    } 
-  } 
-}
diff --git a/Gen/Generators/src/Lib/LBPHOTOS.F b/Gen/Generators/src/Lib/LBPHOTOS.F
deleted file mode 100644
index 0e441e60b..000000000
--- a/Gen/Generators/src/Lib/LBPHOTOS.F
+++ /dev/null
@@ -1,19 +0,0 @@
-C $Id: $
-      SUBROUTINE SetPhotosOutputUnit( OUTPUTUNIT ) 
-C-----------------------------------------------------------------------
-C  Purpose   : Change the default output unit of photos
-C  Arguments : 
-C
-C  Author    : Patrick Robbe
-C  Created   : 2013-05-31
-C-----------------------------------------------------------------------
-      IMPLICIT NONE
-C- Include Files
-C- Local Variables
-      INTEGER PHLUN
-      COMMON/PHOLUN/PHLUN
-      INTEGER OUTPUTUNIT
-C-----------------------------------------------------------------------
-      PHLUN = OUTPUTUNIT 
-  999 RETURN
-      END
diff --git a/Gen/Generators/src/Lib/LBTAULA.F b/Gen/Generators/src/Lib/LBTAULA.F
deleted file mode 100644
index b1309361e..000000000
--- a/Gen/Generators/src/Lib/LBTAULA.F
+++ /dev/null
@@ -1,19 +0,0 @@
-C $Id: $
-      SUBROUTINE SetTaulaOutputUnit( OUTPUTUNIT ) 
-C-----------------------------------------------------------------------
-C  Purpose   : Change the default output unit of taula
-C  Arguments : 
-C
-C  Author    : Patrick Robbe
-C  Created   : 2013-05-31
-C-----------------------------------------------------------------------
-      IMPLICIT NONE
-C- Include Files
-C- Local Variables
-      INTEGER OUTPUTUNIT
-      COMMON / INOUT / INUT,IOUT
-      INTEGER INUT, IOUT
-C-----------------------------------------------------------------------
-      IOUT = OUTPUTUNIT 
-  999 RETURN
-      END
diff --git a/Gen/Generators/src/Lib/LHAPDFCommonBlocks.cpp b/Gen/Generators/src/Lib/LHAPDFCommonBlocks.cpp
deleted file mode 100755
index 041c71987..000000000
--- a/Gen/Generators/src/Lib/LHAPDFCommonBlocks.cpp
+++ /dev/null
@@ -1,78 +0,0 @@
-// $Id: LHAPDFCommonBlocks.cpp,v 1.4 2009-10-22 16:43:05 robbep Exp $
-// access LHAPDF common LHASILENT
-#include "Generators/LHAPDFCommonBlocks.h"
-#include <cstring>
-
-extern "C" {
-#ifdef WIN32
-  void __stdcall GGETLHAPARM( int * , char * , int ) ;
-  void __stdcall GSETLHAPARM( int * , char * , int ) ;
-  void __stdcall GGETLHAVALUE( int * , double * ) ;
-  void __stdcall GSETLHAVALUE( int * , double * ) ;
-#else 
-  void ggetlhaparm_( int * , char * , int ) ;
-  void gsetlhaparm_( int * , char * , int ) ;
-  void ggetlhavalue_( int * , double * ) ;
-  void gsetlhavalue_( int * , double * ) ;
-#endif
-}
-
-// Constructor
-Lhacontrol::Lhacontrol(): m_dummystr( "" ) ,  m_dummy( -999. ) { }
-
-// Destructor
-Lhacontrol::~Lhacontrol() { }
-
-// access lhaparm in common
-void Lhacontrol::setlhaparm( int n , const std::string & value ) {
-  char * arg = new char[ 20 ] ; 
-  strncpy( arg , value.c_str() , value.size() ) ;
-  if ( n < 1 || n > lenlhaparm() ) { 
-    delete [] arg ;
-    return ; 
-  }
-#ifdef WIN32
-  GSETLHAPARM( & n , arg , strlen( arg ) ) ;
-#else
-  gsetlhaparm_( & n , arg , strlen( arg ) ) ;
-#endif
-  delete [] arg ;
-}
-
-void Lhacontrol::getlhaparm( int n , std::string & value ) {
-  if ( n < 1 || n > lenlhaparm() ) {
-    value = m_dummystr ;
-    return ;
-  }
-  char * arg = new char[ 20 ] ;
-#ifdef WIN32
-  GGETLHAPARM( &n , arg , strlen( arg ) ) ;
-#else
-  ggetlhaparm_( &n , arg , strlen( arg ) ) ;
-#endif
-  value = arg ;
-  delete [] arg ;
-}
-
-// access lhavalue in common
-void Lhacontrol::setlhavalue( int n , double value ) {
-  if ( n < 1 || n > lenlhaparm() ) return ;
-#ifdef WIN32
-  GSETLHAVALUE( &n , &value ) ;
-#else
-  gsetlhavalue_( &n , &value ) ;
-#endif
-}
-
-void Lhacontrol::getlhavalue( int n , double & value ) {
-  if ( n < 1 || n > lenlhaparm() ) {
-    value = m_dummy ;
-    return ;
-  }  
-#ifdef WIN32
-  GGETLHAVALUE( &n , &value ) ;
-#else
-  ggetlhavalue_( &n , &value ) ;
-#endif
-}
-
diff --git a/Gen/Generators/src/Lib/LHAPDFUtils.F b/Gen/Generators/src/Lib/LHAPDFUtils.F
deleted file mode 100755
index 7244f4803..000000000
--- a/Gen/Generators/src/Lib/LHAPDFUtils.F
+++ /dev/null
@@ -1,54 +0,0 @@
-C $Id: LHAPDFUtils.F,v 1.6 2008-05-23 11:56:18 robbep Exp $
-      SUBROUTINE GGETLHAPARM( INDEX , VALUE ) 
-      IMPLICIT NONE 
-      
-      INTEGER INDEX
-      CHARACTER*20 VALUE
-
-      CHARACTER*20 LHAPARM(20)
-      DOUBLE PRECISION LHAVALUE(20)
-      COMMON/LHACONTROL/LHAPARM,LHAVALUE
-
-      VALUE = LHAPARM( INDEX ) 
-      END
-
-
-      SUBROUTINE GSETLHAPARM( INDEX , VALUE ) 
-      IMPLICIT NONE 
-      
-      INTEGER INDEX
-      CHARACTER*(*) VALUE
-
-      CHARACTER*20 LHAPARM(20)
-      DOUBLE PRECISION LHAVALUE(20)
-      COMMON/LHACONTROL/LHAPARM,LHAVALUE
-
-      LHAPARM( INDEX ) = VALUE(1:LEN(VALUE))
-      END
-
-      SUBROUTINE GGETLHAVALUE( INDEX , VALUE ) 
-      IMPLICIT NONE 
-      
-      INTEGER INDEX
-      DOUBLE PRECISION VALUE
-
-      CHARACTER*20 LHAPARM(20)
-      DOUBLE PRECISION LHAVALUE(20)
-      COMMON/LHACONTROL/LHAPARM,LHAVALUE
-
-      VALUE = LHAVALUE( INDEX ) 
-      END
-
-
-      SUBROUTINE GSETLHAVALUE( INDEX , VALUE ) 
-      IMPLICIT NONE 
-      
-      INTEGER INDEX
-      DOUBLE PRECISION VALUE
-
-      CHARACTER*20 LHAPARM(20)
-      DOUBLE PRECISION LHAVALUE(20)
-      COMMON/LHACONTROL/LHAPARM,LHAVALUE
-
-      LHAVALUE( INDEX ) = VALUE
-      END
diff --git a/Gen/Generators/src/Lib/LbPhotos.cpp b/Gen/Generators/src/Lib/LbPhotos.cpp
deleted file mode 100644
index dd431b064..000000000
--- a/Gen/Generators/src/Lib/LbPhotos.cpp
+++ /dev/null
@@ -1,25 +0,0 @@
-// Include files
-// local
-#include "Generators/LbPhotos.h"
-
-//-----------------------------------------------------------------------------
-// Implementation file for class : LbPhotos
-//
-// 2013-05-31 : Patrick Robbe
-//-----------------------------------------------------------------------------
-
-extern "C" {
-#ifdef WIN32
-  void __stdcall SETPHOTOSOUTPUTUNIT( int * ) ;
-#else
-  void setphotosoutputunit_( int * ) ;
-#endif
-}
-
-void LbPhotos::setOutputUnit( int outputUnit ) {
-#ifdef WIN32
-  SETPHOTOSOUTPUTUNIT( &outputUnit ) ;
-#else
-  setphotosoutputunit_( &outputUnit ) ;
-#endif
-}
diff --git a/Gen/Generators/src/Lib/LbTaula.cpp b/Gen/Generators/src/Lib/LbTaula.cpp
deleted file mode 100644
index 2e41207d4..000000000
--- a/Gen/Generators/src/Lib/LbTaula.cpp
+++ /dev/null
@@ -1,25 +0,0 @@
-// Include files
-// local
-#include "Generators/LbTaula.h"
-
-//-----------------------------------------------------------------------------
-// Implementation file for class : LbTaula
-//
-// 2013-05-31 : Patrick Robbe
-//-----------------------------------------------------------------------------
-
-extern "C" {
-#ifdef WIN32
-  void __stdcall SETTAULAOUTPUTUNIT( int * ) ;
-#else
-  void settaulaoutputunit_( int * ) ;
-#endif
-}
-
-void LbTaula::setOutputUnit( int outputUnit ) {
-#ifdef WIN32
-  SETTAULAOUTPUTUNIT( &outputUnit ) ;
-#else
-  settaulaoutputunit_( &outputUnit ) ;
-#endif
-}
diff --git a/Gen/Generators/src/Lib/LhaPdf.cpp b/Gen/Generators/src/Lib/LhaPdf.cpp
deleted file mode 100755
index ceb6d125a..000000000
--- a/Gen/Generators/src/Lib/LhaPdf.cpp
+++ /dev/null
@@ -1,13 +0,0 @@
-// $Id: LhaPdf.cpp,v 1.1 2005-12-07 23:02:09 robbep Exp $
-// Include files
-
-// local
-#include "Generators/LhaPdf.h"
-
-//-----------------------------------------------------------------------------
-// Implementation file for class : LhaPdf
-//
-// 2005-12-07 : Patrick Robbe
-//-----------------------------------------------------------------------------
-
-Lhacontrol LhaPdf::s_lhacontrol ;
diff --git a/Gen/Generators/src/Lib/RandomForGenerator.cpp b/Gen/Generators/src/Lib/RandomForGenerator.cpp
deleted file mode 100755
index f04762b5b..000000000
--- a/Gen/Generators/src/Lib/RandomForGenerator.cpp
+++ /dev/null
@@ -1,16 +0,0 @@
-// $Id: RandomForGenerator.cpp,v 1.2 2007-10-11 13:23:26 robbep Exp $
-// Include files
-
-// local
-#include "Generators/RandomForGenerator.h"
-
-Rndm::Numbers RandomForGenerator::s_randgaudi ;
-
-Rndm::Numbers & RandomForGenerator::getNumbers() {
-  return s_randgaudi ;
-}
-
-double RandomForGenerator::flat( ) {
-  return s_randgaudi() ;
-}
-
diff --git a/Gen/Generators/src/Lib/Signal.cpp b/Gen/Generators/src/Lib/Signal.cpp
deleted file mode 100755
index 789278684..000000000
--- a/Gen/Generators/src/Lib/Signal.cpp
+++ /dev/null
@@ -1,387 +0,0 @@
-// Include files
-
-// local
-#include "Generators/Signal.h"
-
-// from Gaudi
-#include "Kernel/IParticlePropertySvc.h"
-#include "Kernel/ParticleProperty.h"
-#include "GaudiKernel/IRndmGenSvc.h"
-
-// from Generators
-#include "MCInterfaces/IDecayTool.h"
-#include "Generators/GenCounters.h"
-#include "GenEvent/HepMCUtils.h"
-
-// from Event
-#include "Event/GenFSR.h"
-#include "Event/GenCountersFSR.h"
-
-// Function to test if a HepMC::GenParticle is Particle (or antiParticle)
-struct isParticle : std::unary_function< const HepMC::GenParticle * , bool > {
-  bool operator() ( const HepMC::GenParticle * part ) const {
-    return ( part -> pdg_id() > 0 ) ;
-  }
-};
-
-// Functions to test if a HepMC::GenParticle goes forward
-struct isForwardParticle :
-  std::unary_function< const HepMC::GenParticle * , bool > {
-  bool operator() ( const HepMC::GenParticle * part ) const {
-    return ( ( part -> pdg_id() > 0 ) && ( part -> momentum().pz() > 0 ) ) ;
-  }
-};
-
-struct isForwardAntiParticle :
-  std::unary_function< const HepMC::GenParticle * , bool > {
-  bool operator() ( const HepMC::GenParticle * part ) const {
-    return ( ( part -> pdg_id() < 0 ) && ( part -> momentum().pz() > 0 ) ) ;
-  }
-};
-
-//-----------------------------------------------------------------------------
-// Implementation file for class : Signal
-//
-// 2005-08-18 : Patrick Robbe
-//-----------------------------------------------------------------------------
-
-//=============================================================================
-// Standard constructor, initializes variables
-//=============================================================================
-Signal::Signal( const std::string& type,
-                const std::string& name,
-                const IInterface* parent )
-  : ExternalGenerator( type, name , parent ) ,
-    m_nEventsBeforeCut   ( 0 ) , m_nEventsAfterCut        ( 0 ) ,
-    m_nParticlesBeforeCut( 0 ) , m_nAntiParticlesBeforeCut( 0 ) ,
-    m_nParticlesAfterCut ( 0 ) , m_nAntiParticlesAfterCut ( 0 ) ,
-    m_nInvertedEvents ( 0 ) ,
-    m_signalQuark     ( LHCb::ParticleID::down ) ,
-    m_signalPID       ( 0 ) ,
-    m_bbCounter       ( 0 ) ,
-    m_ccCounter       ( 0 ) ,
-    m_nSig            ( 0 ) ,
-    m_nSigBar         ( 0 ) ,
-    m_sigName        ( "" ) ,
-    m_sigBarName     ( "" ) ,
-    m_cpMixture       ( true ) ,
-    m_signalBr ( 0.0 ) {
-    declareProperty( "SignalPIDList" , m_pidVector ) ;
-    declareProperty( "Clean" , m_cleanEvents = false ) ;
-    declareProperty( "RevertWhenBackward" , m_revertWhenBackward = true ) ;
-
-    m_bHadC.assign( 0 ) ;  m_antibHadC.assign( 0 ) ;
-    m_cHadC.assign( 0 ) ;  m_anticHadC.assign( 0 ) ;
-
-    m_bExcitedC.assign( 0 ) ;
-    m_cExcitedC.assign( 0 ) ;
-
-    GenCounters::setupBHadronCountersNames( m_bHadCNames , m_antibHadCNames ) ;
-    GenCounters::setupDHadronCountersNames( m_cHadCNames , m_anticHadCNames ) ;
-
-    GenCounters::setupExcitedCountersNames( m_bExcitedCNames , "B" ) ;
-    GenCounters::setupExcitedCountersNames( m_cExcitedCNames , "D" ) ;
-  }
-
-//=============================================================================
-// Destructor
-//=============================================================================
-Signal::~Signal( ) { ; }
-
-//=============================================================================
-// Initialize method
-//=============================================================================
-StatusCode Signal::initialize( ) {
-  StatusCode sc = ExternalGenerator::initialize( ) ;
-  if ( sc.isFailure() ) return sc ;
-
-  if ( m_pidVector.empty() )
-    return Error( "SignalPIDList property is not set" ) ;
-
-  IRndmGenSvc * randSvc = svc< IRndmGenSvc >( "RndmGenSvc" , true ) ;
-
-  sc = m_flatGenerator.initialize( randSvc , Rndm::Flat( 0., 1. ) ) ;
-  if ( ! sc.isSuccess() )
-    return Error( "Could not initialize flat random number generator" ) ;
-
-  release( randSvc ) ;
-
-  // Transform vector into set
-  for ( std::vector<int>::iterator it = m_pidVector.begin() ;
-        it != m_pidVector.end() ; ++it ) m_pids.insert( *it ) ;
-
-  LHCb::IParticlePropertySvc * ppSvc =
-    svc< LHCb::IParticlePropertySvc >( "LHCb::ParticlePropertySvc" ) ;
-
-  info() << "Generating Signal events of " ;
-  PIDs::const_iterator it2 ;
-  for ( it2 = m_pids.begin() ; it2 != m_pids.end() ; ++it2 ) {
-    const LHCb::ParticleProperty * prop = ppSvc -> find( LHCb::ParticleID( *it2 ) ) ;
-    info() << prop -> particle() << " " ;
-
-    LHCb::ParticleID pid( prop -> pdgID() ) ;
-
-    m_signalPID  = pid.abspid() ;
-    if ( pid.hasCharm() ) m_signalQuark = LHCb::ParticleID::charm ;
-    else if ( pid.hasBottom()    ) m_signalQuark = LHCb::ParticleID::bottom ;
-
-    if ( pid.pid() > 0 ) { m_sigName = prop -> particle() ; }
-    else { m_sigBarName = prop -> particle() ; }
-
-  }
-
-  m_cpMixture = false ;
-
-  if ( 2 == m_pids.size() ) {
-    if ( *m_pids.begin() == - *(--m_pids.end()) ) m_cpMixture = true ;
-    else return Error( "Bad configuration in PID list" ) ;
-  } else if ( m_pids.size() > 2 ) return Error( "Too many PIDs in list" ) ;
-
-  if ( m_decayTool ) m_decayTool -> setSignal( *m_pids.begin() ) ;
-
-  if ( m_decayTool ) m_signalBr = m_decayTool -> getSignalBr( ) ;
-  else m_signalBr = 0. ;
-
-  info() << endmsg ;
-  release( ppSvc ) ;
-
-  if ( 0. == m_signalBr )
-    warning()
-      << "The signal decay mode is not defined in the main DECAY.DEC table"
-      << std::endl << "Please add it there !" << endmsg ;
-  else
-    info() << "The signal decay mode has visible branching fractions of :"
-           << m_signalBr << endmsg ;
-
-  return sc ;
-}
-
-//=============================================================================
-// Print the counters
-//=============================================================================
-void Signal::printCounters( ) const {
-  using namespace GenCounters ;
-  printEfficiency( m_xmlLogTool , "generator level cut" , m_nEventsAfterCut ,
-                   m_nEventsBeforeCut ) ;
-  printCounter( m_xmlLogTool , "z-inverted events" , m_nInvertedEvents ) ;
-
-  printEfficiency( m_xmlLogTool , "generator particle level cut" ,
-                   m_nParticlesAfterCut ,  m_nParticlesBeforeCut ) ;
-  printEfficiency( m_xmlLogTool , "generator anti-particle level cut" ,
-                   m_nAntiParticlesAfterCut , m_nAntiParticlesBeforeCut ) ;
-
-  if ( "" != m_sigName ) printFraction( m_xmlLogTool , "signal " + m_sigName +
-                                        " in sample" , m_nSig , m_nSig +
-                                        m_nSigBar ) ;
-  if ( "" != m_sigBarName ) printFraction( m_xmlLogTool , "signal " + m_sigBarName +
-                                           " in sample" , m_nSigBar , m_nSig +
-                                           m_nSigBar ) ;
-
-  printArray( m_xmlLogTool , m_bHadC , m_bHadCNames , "accepted" ) ;
-  printArray( m_xmlLogTool , m_antibHadC , m_antibHadCNames , "accepted" ) ;
-  printCounter( m_xmlLogTool , "accepted (bb)" , m_bbCounter ) ;
-
-  printArray( m_xmlLogTool , m_cHadC , m_cHadCNames , "accepted" ) ;
-  printArray( m_xmlLogTool , m_anticHadC , m_anticHadCNames , "accepted" ) ;
-  printCounter( m_xmlLogTool , "accepted (cc)" , m_ccCounter ) ;
-
-  printArray( m_xmlLogTool , m_bExcitedC , m_bExcitedCNames , "accepted" ) ;
-  printArray( m_xmlLogTool , m_cExcitedC , m_cExcitedCNames , "accepted" ) ;
-}
-
-//=============================================================================
-// Isolate signal to produce "clean" events
-//=============================================================================
-StatusCode Signal::isolateSignal( const HepMC::GenParticle * theSignal )
-  const {
-
-  StatusCode sc = StatusCode::SUCCESS ;
-  // Create a new event to contain isolated signal decay tree
-  LHCb::HepMCEvent * mcevt = new LHCb::HepMCEvent( ) ;
-  mcevt -> setGeneratorName( m_hepMCName + "_clean" ) ;
-
-  if ( 0 == theSignal -> production_vertex() )
-    return Error( "Signal particle has no production vertex." ) ;
-
-  // create a new vertex and a new HepMC Particle for the root particle
-  // (a copy of which will be associated to the new HepMC event)
-
-  HepMC::GenVertex * newVertex =
-    new HepMC::GenVertex( theSignal -> production_vertex() -> position() ) ;
-
-  HepMC::GenEvent * hepMCevt = mcevt -> pGenEvt() ;
-
-  hepMCevt -> add_vertex( newVertex ) ;
-
-  HepMC::GenParticle * theNewParticle =
-    new HepMC::GenParticle( theSignal -> momentum() , theSignal -> pdg_id() ,
-                            theSignal -> status() ) ;
-
-  newVertex -> add_particle_out( theNewParticle ) ;
-
-  // Associate the new particle to the HepMC event
-  // and copy all tree to the new HepMC event
-  sc = fillHepMCEvent( theNewParticle , theSignal ) ;
-  hepMCevt -> set_signal_process_vertex( theNewParticle -> production_vertex() ) ;
-
-  if ( ! sc.isSuccess( ) )
-    return Error( "Could not fill HepMC event for signal tree" , sc ) ;
-
-  // Check if container already exists
-  if ( exist< LHCb::HepMCEvents >( LHCb::HepMCEventLocation::Signal ) )
-    return Error( "SignalDecayTree container already exists !" ) ;
-
-  LHCb::HepMCEvents * hepVect = new LHCb::HepMCEvents ;
-  hepVect -> insert( mcevt ) ;
-
-  // Register new location and store HepMC event
-  put( hepVect , LHCb::HepMCEventLocation::Signal ) ;
-
-  return sc ;
-}
-
-//=============================================================================
-// Fill HepMC event from a HepMC tree
-//=============================================================================
-StatusCode Signal::fillHepMCEvent( HepMC::GenParticle * theNewParticle ,
-                                   const HepMC::GenParticle * theOldParticle )
-  const {
-  StatusCode sc = StatusCode::SUCCESS ;
-  //
-  // Copy theOldParticle to theNewParticle in theEvent
-  // theNewParticle already exist and is created outside this function
-  HepMC::GenVertex * oVertex = theOldParticle -> end_vertex() ;
-  if ( 0 != oVertex ) {
-    // Create decay vertex and associate it to theNewParticle
-    HepMC::GenVertex * newVertex =
-      new HepMC::GenVertex( oVertex -> position() ) ;
-    newVertex -> add_particle_in( theNewParticle ) ;
-    theNewParticle -> parent_event() -> add_vertex( newVertex ) ;
-
-    // loop over child particle of this vertex after sorting them
-    std::list< const HepMC::GenParticle * > outParticles ;
-    for ( HepMC::GenVertex::particles_out_const_iterator itP =
-            oVertex -> particles_out_const_begin() ;
-          itP != oVertex -> particles_out_const_end() ; ++itP )
-      outParticles.push_back( (*itP ) ) ;
-
-    outParticles.sort( HepMCUtils::compareHepMCParticles ) ;
-
-    std::list< const HepMC::GenParticle * >::const_iterator child ;
-    for ( child = outParticles.begin( ) ; child != outParticles.end( ) ;
-          ++child ) {
-
-      // Create a new particle for each daughter of theOldParticle
-      HepMC::GenParticle * newPart =
-        new HepMC::GenParticle ( (*child) -> momentum () ,
-                                 (*child) -> pdg_id ()   ,
-                                 (*child) -> status ()   ) ;
-      newVertex -> add_particle_out( newPart ) ;
-
-      const HepMC::GenParticle * theChild = (*child) ;
-      // Recursive call : fill the event with the daughters
-      sc = fillHepMCEvent( newPart , theChild ) ;
-
-      if ( ! sc.isSuccess() ) return sc ;
-    }
-  }
-  return sc ;
-}
-
-//=============================================================================
-// Choose one particle in acceptance
-//=============================================================================
-HepMC::GenParticle * Signal::chooseAndRevert( const ParticleVector &
-                                              theParticleList ,
-                                              bool & isInverted ,
-                                              bool & hasFlipped ,
-					      bool & hasFailed ) {
-  HepMC::GenParticle * theSignal ;
-  isInverted = false ;
-  hasFlipped = false ;
-  hasFailed = false ;
-
-  unsigned int nPart = theParticleList.size() ;
-  if ( nPart > 1 ) {
-    unsigned int iPart =
-      (unsigned int) floor( nPart * m_flatGenerator() ) ;
-    theSignal = theParticleList[ iPart ] ;
-
-    // Now erase daughters of the other particles in particle list
-    for ( unsigned int i = 0 ; i < nPart ; ++i ) {
-      if ( i != iPart )
-        HepMCUtils::RemoveDaughters( theParticleList[ i ] ) ;
-    }
-  } else if ( 1 == nPart ) theSignal = theParticleList.front() ;
-  else return 0 ;
-
-  if ( theSignal -> momentum().pz() < 0 && m_revertWhenBackward ) {
-    revertEvent( theSignal -> parent_event() ) ;
-    isInverted = true ;
-  }
-
-  // now force the particle to decay
-  if ( m_cpMixture )
-	if ( m_decayTool ) m_decayTool -> enableFlip() ;
-  if ( m_decayTool ) {
-    StatusCode sc = m_decayTool -> generateSignalDecay( theSignal , hasFlipped ) ;
-    if ( ! sc.isSuccess() ) hasFailed = true ;
-  }
-
-  return theSignal ;
-}
-
-//=============================================================================
-// Establish correct multiplicity of signal
-//=============================================================================
-bool Signal::ensureMultiplicity( const unsigned int nSignal ) {
-  if ( ! m_cpMixture ) return true ;
-  if ( nSignal > 1 ) return true ;
-  return ( m_flatGenerator() >= ( ( 1. - m_signalBr ) /
-                                  ( 2. - m_signalBr ) ) ) ;
-}
-
-//=============================================================================
-// update counters for efficiency calculations
-//=============================================================================
-void Signal::updateCounters( const ParticleVector & particleList ,
-                             unsigned int & particleCounter ,
-                             unsigned int & antiparticleCounter ,
-                             bool onlyForwardParticles ,
-                             bool isInverted ) const {
-  int nP( 0 ) , nAntiP( 0 ) ;
-  ParticleVector::const_iterator from = particleList.begin() ;
-  ParticleVector::const_iterator to = particleList.end() ;
-  LHCb::GenFSR* genFSR = nullptr;
-  if(m_FSRName != ""){
-    IDataProviderSvc* fileRecordSvc = svc<IDataProviderSvc>("FileRecordDataSvc", true);
-    genFSR = getIfExists<LHCb::GenFSR>(fileRecordSvc, m_FSRName, false);
-    if(!genFSR) warning() << "Could not find GenFSR at " << m_FSRName << endmsg;
-  }
-  int keyP = 0, keyAP = 0;
-
-  if ( onlyForwardParticles ) {
-    // if the particle has been inverted z -> -z, do not count it
-    if ( ! isInverted ) {
-      keyP = LHCb::GenCountersFSR::AfterPCut;
-      keyAP = LHCb::GenCountersFSR::AfterantiPCut;
-
-      nP = std::count_if( from , to , isForwardParticle() ) ;
-      nAntiP = std::count_if( from , to , isForwardAntiParticle() ) ;
-    }
-  } else {
-    keyP = LHCb::GenCountersFSR::BeforePCut;
-    keyAP = LHCb::GenCountersFSR::BeforeantiPCut;
-
-    nP = std::count_if( from , to , isParticle() ) ;
-    nAntiP = particleList.size() - nP ;
-  }
-
-  particleCounter += nP ;
-  antiparticleCounter += nAntiP ;
-
-  if(genFSR) genFSR->incrementGenCounter(keyP, nP);
-  if(genFSR) genFSR->incrementGenCounter(keyAP, nAntiP);
-
-}
-
diff --git a/Gen/Generators/src/Lib/StreamForGenerator.cpp b/Gen/Generators/src/Lib/StreamForGenerator.cpp
deleted file mode 100755
index 612bc1bc7..000000000
--- a/Gen/Generators/src/Lib/StreamForGenerator.cpp
+++ /dev/null
@@ -1,11 +0,0 @@
-// $Id: StreamForGenerator.cpp,v 1.2 2007-10-11 13:23:27 robbep Exp $
-// Include files
-
-// local
-#include "Generators/StreamForGenerator.h"
-
-MsgStream * StreamForGenerator::s_gaudiStream = 0 ;
-
-MsgStream *& StreamForGenerator::getStream() {
-  return s_gaudiStream ;
-}
diff --git a/Gen/Generators/src/Lib/StringParse.cpp b/Gen/Generators/src/Lib/StringParse.cpp
deleted file mode 100755
index bc8f19008..000000000
--- a/Gen/Generators/src/Lib/StringParse.cpp
+++ /dev/null
@@ -1,55 +0,0 @@
-// $Id: StringParse.cpp,v 1.3 2009-10-22 16:43:05 robbep Exp $
-// --------------------------------------------------
-// 
-// File:  GeneratorUtils/StringParse.cxx
-// Description:
-//    This code is used to parse a string .
-//    it breaks it into components which are seperated by spaces 
-//    in the original. The components can be accessed and converted to 
-//    doubles or ints
-// AuthorList:
-//         Ian Hinchliffe April 2000
-#include "Generators/StringParse.h"
-#include <string>
-#include <vector>
-#include <iostream>
-#include <cmath>
-#include <cstdlib>
-
-StringParse::StringParse( const std::string & input ) {
-  m_past_end="?!?";
-  m_lstring=input;
-  m_nword=0;
-  std::string::size_type pos=0;
-  std::string::size_type prev_pos=0;
-  while ( ( pos = input.find_first_of( ' ' , pos ) ) != std::string::npos ) {
-      m_lsubstring.push_back( input.substr( prev_pos , pos-prev_pos ) ) ;
-      prev_pos=++pos;
-    }
-  // special handling for last substring
-  m_lsubstring.push_back( input.substr( prev_pos , pos-prev_pos ) ) ;
-  m_nword=m_lsubstring.size();
-}
-
-std::string StringParse::piece( const int & num ) {
-  if ( num <= m_nword ) return m_lsubstring[ num-1 ] ;
-  else return m_past_end;
-}
-
-int StringParse::intpiece( const int & num ) {  
-  if ( num <= m_nword ) {
-    int i = atoi( m_lsubstring[ num-1 ].c_str() ) ;
-    return i;
-  }
-  else return -1;
-}
-
-double StringParse::numpiece( const int & num ) {  
-  if ( num <= m_nword ) {
-    double x = atof( m_lsubstring[ num-1 ].c_str() ) ;
-    return x;
-  }
-  else return -1.1;
-}
-
-StringParse::~StringParse(){ }
diff --git a/Gen/Generators/src/Lib/cpyr.cpp b/Gen/Generators/src/Lib/cpyr.cpp
deleted file mode 100755
index ebb23129c..000000000
--- a/Gen/Generators/src/Lib/cpyr.cpp
+++ /dev/null
@@ -1,23 +0,0 @@
-// $Id: cpyr.cpp,v 1.3 2007-10-10 20:07:24 robbep Exp $
-//-----------------------------------------------------------------------------
-// 06/05/2002 : Witold Pokorski
-//-----------------------------------------------------------------------------
-
-// plugs Gaudi RndmNumberSvc into Pythia
-
-//=============================================================================
-
-#include "GaudiKernel/RndmGenerators.h"
-#include "GaudiKernel/IRndmGenSvc.h"
-#include "GaudiKernel/IRndmGen.h"
-#include "Generators/RandomForGenerator.h"
-
-#ifdef WIN32
-extern "C"  double __stdcall CPYR(int*)
-#else
-extern "C" double cpyr_(int*)
-#endif
-{  
-  return (RandomForGenerator::getNumbers())() ;
-}
-//=============================================================================
diff --git a/Gen/Generators/src/Lib/f77units.F b/Gen/Generators/src/Lib/f77units.F
deleted file mode 100755
index 52b25205c..000000000
--- a/Gen/Generators/src/Lib/f77units.F
+++ /dev/null
@@ -1,221 +0,0 @@
-C $Id: f77units.F,v 1.2 2007-06-29 13:21:06 ibelyaev Exp $
-C ----------------------------------------------------------------------
-C CVS tag $Name: not supported by cvs2svn $, version $Revision: 1.2 $
-C ----------------------------------------------------------------------
-C $Log: not supported by cvs2svn $
-C Revision 1.1  2006/10/04 13:36:46  ibelyaev
-C  add utilities to open/close Fortran file
-C 
-C ----------------------------------------------------------------------
-      INTEGER FUNCTION f77clfile ( LUN )
-C-----------------------------------------------------------------------
-C  Purpose   : close the opened F77 file with logical unit LUN
-C  Arguments : LUN units to be close 
-C
-C  @author    : Vanya BELYAEV ibelyaev@physics.syr.edu
-C  @date      : 2006-10-03
-C-----------------------------------------------------------------------
-      IMPLICIT NONE
-C-----------------------------------------------------------------------
-C- Local Variables
-C-----------------------------------------------------------------------
-      INTEGER       lun
-C-----------------------------------------------------------------------
-      CLOSE ( LUN , ERR=100 ) 
-      F77CLFILE = LUN 
-      RETURN 
- 100  CONTINUE 
-      WRITE(*,*) 'ERROR in closing file LUN=',LUN
-      F77CLFILE = 0
-      RETURN
-      END
-C-----------------------------------------------------------------------
-      INTEGER FUNCTION f77onfile ( LUN , CHFILE ) 
-C-----------------------------------------------------------------------
-C  Purpose   : open "NEW" file with logical unit LUN and name CHFILE 
-C  Arguments : LUN units to be close 
-C
-C  @author    : Vanya BELYAEV ibelyaev@physics.syr.edu
-C  @date      : 2006-10-03
-C-----------------------------------------------------------------------
-      IMPLICIT NONE
-C-----------------------------------------------------------------------
-C- Local Variables
-C-----------------------------------------------------------------------
-      INTEGER       LUN
-      CHARACTER*(*) CHFILE 
-C-----------------------------------------------------------------------
-      OPEN( LUN , FILE = CHFILE, STATUS='new' , ERR=100 ) 
-      F77ONFILE = LUN 
-      RETURN 
- 100  CONTINUE
-      WRITE(*,*)'ERROR in open "new" file LUN=',LUN,',NAME="',CHFILE,'"'
-      F77ONFILE = 0
-      RETURN
-      END
-C-----------------------------------------------------------------------
-      INTEGER FUNCTION f77oofile ( LUN , CHFILE ) 
-C-----------------------------------------------------------------------
-C  Purpose   : open "OLD" file with logical unit LUN and name CHFILE 
-C  Arguments : LUN units to be close 
-C
-C  @author    : Vanya BELYAEV ibelyaev@physics.syr.edu
-C  @date      : 2006-10-03
-C-----------------------------------------------------------------------
-      IMPLICIT NONE
-C-----------------------------------------------------------------------
-C- Local Variables
-C-----------------------------------------------------------------------
-      INTEGER       LUN
-      CHARACTER*(*) CHFILE
-C-----------------------------------------------------------------------
-      OPEN( LUN , FILE = CHFILE, STATUS='old' , ERR=100 ) 
-      F77OOFILE = LUN
-      RETURN 
- 100  CONTINUE
-      WRITE(*,*)'ERROR in open "old" file LUN=',LUN,',NAME="',CHFILE,'"'
-      F77OOFILE = 0
-      RETURN
-      END
-C-----------------------------------------------------------------------
-      INTEGER FUNCTION f77oufile ( LUN , CHFILE ) 
-C-----------------------------------------------------------------------
-C  Purpose   : open "UNKNOWN" file with logical unit LUN and name CHFILE
-C 
-C  Arguments : LUN units to be close 
-C
-C  @author    : Vanya BELYAEV ibelyaev@physics.syr.edu
-C  @date      : 2006-10-03
-C-----------------------------------------------------------------------
-      IMPLICIT NONE
-C-----------------------------------------------------------------------
-C- Local Variables
-C-----------------------------------------------------------------------
-      INTEGER       LUN
-      CHARACTER*(*) CHFILE
-C-----------------------------------------------------------------------
-      OPEN( LUN , FILE = CHFILE, STATUS='unknown' , ERR=100 ) 
-      F77OUFILE= LUN 
-      RETURN 
- 100  CONTINUE
-      WRITE(*,*)'ERROR in open "unknown" file LUN=',LUN,',NAME="',CHFILE
-     &  ,'"'
-      F77OUFILE = 1 
-      RETURN
-      END      
-C-----------------------------------------------------------------------
-      INTEGER FUNCTION f77onffile ( LUN , CHFILE ) 
-C-----------------------------------------------------------------------
-C  Purpose   : open "NEW" FORMATTED file with logical unit LUN and name
-C              CHFILE 
-C  Arguments : LUN units to be close 
-C
-C  @author    : Vanya BELYAEV ibelyaev@physics.syr.edu
-C  @date      : 2006-10-03
-C-----------------------------------------------------------------------
-      IMPLICIT NONE
-C-----------------------------------------------------------------------
-C- Local Variables
-C-----------------------------------------------------------------------
-      INTEGER       LUN
-      CHARACTER*(*) CHFILE 
-C-----------------------------------------------------------------------
-      OPEN( LUN , 
-     &  FILE = CHFILE, STATUS='new' , FORM='formatted' , ERR =100 ) 
-      F77ONFFILE = LUN 
-      RETURN 
- 100  CONTINUE
-      WRITE(*,*)'ERROR in open "new"/"FORMATTED" file LUN=' , 
-     &  LUN,',NAME="',CHFILE,'"'
-      F77ONFFILE = 0
-      RETURN
-      END
-C-----------------------------------------------------------------------
-      INTEGER FUNCTION f77ooffile ( LUN , CHFILE ) 
-C-----------------------------------------------------------------------
-C  Purpose   : open "OLD" FORMATTED file with logical unit LUN and name
-C              CHFILE 
-C  Arguments : LUN units to be close 
-C
-C  @author    : Vanya BELYAEV ibelyaev@physics.syr.edu
-C  @date      : 2006-10-03
-C-----------------------------------------------------------------------
-      IMPLICIT NONE
-C-----------------------------------------------------------------------
-C- Local Variables
-C-----------------------------------------------------------------------
-      INTEGER       LUN
-      CHARACTER*(*) CHFILE 
-C-----------------------------------------------------------------------
-      OPEN( LUN , 
-     &  FILE = CHFILE, STATUS='old' , FORM='formatted' , ERR =100 ) 
-      F77OOFFILE = LUN 
-      RETURN 
- 100  CONTINUE
-      WRITE(*,*)'ERROR in open "old"/"FORMATTED" file LUN=' , 
-     &  LUN,',NAME="',CHFILE,'"'
-      F77OOFFILE = 0
-      RETURN
-      END
-C-----------------------------------------------------------------------
-      INTEGER FUNCTION f77ouffile ( LUN , CHFILE ) 
-C-----------------------------------------------------------------------
-C  Purpose   : open "UNKNOWN" "FORMATTED" file 
-C              with logical unit LUN and name CHFILE 
-C  Arguments : LUN units to be close 
-C
-C  @author    : Vanya BELYAEV ibelyaev@physics.syr.edu
-C  @date      : 2006-10-03
-C-----------------------------------------------------------------------
-      IMPLICIT NONE
-C-----------------------------------------------------------------------
-C- Local Variables
-C-----------------------------------------------------------------------
-      INTEGER       LUN
-      CHARACTER*(*) CHFILE 
-C-----------------------------------------------------------------------
-      OPEN( LUN , 
-     &  FILE = CHFILE, STATUS='unknown' , FORM='formatted' , ERR =100 ) 
-      F77OUFFILE = LUN 
-      RETURN 
- 100  CONTINUE
-      WRITE(*,*)'ERROR in open "unknown"/"FORMATTED" file LUN=' , 
-     &  LUN,',NAME="',CHFILE,'"'
-      F77OUFFILE = 0
-      RETURN
-      END
-C-----------------------------------------------------------------------
-      INTEGER FUNCTION f77GETUNIT ( N ) 
-C-----------------------------------------------------------------------
-C  Purpose   : search free fortran unit 
-C  Arguments : 
-C
-C  Author    : Vanya BELYAEV ibelyaev@physics.syr.edu
-C  Created   : 2007-06-28
-C-----------------------------------------------------------------------
-      IMPLICIT NONE
-C-----------------------------------------------------------------------
-      INTEGER N 
-C-----------------------------------------------------------------------
-      INTEGER i
-      LOGICAL yes 
-C-----------------------------------------------------------------------
-      N = 0 
-      DO i = 99,10,-1           ! scal all units 
-        INQUIRE(unit=i,opened=yes)
-        IF ( .not. yes ) THEN
-          N = i 
-          GO TO 100
-        ENDIF
-      ENDDO
-C-----------------------------------------------------------------------
- 100  CONTINUE 
-      f77getunit = N 
- 999  RETURN
-      END
-      
-
-
-C-----------------------------------------------------------------------
-C The END 
-C-----------------------------------------------------------------------
diff --git a/Gen/Generators/src/Lib/getaddr.cpp b/Gen/Generators/src/Lib/getaddr.cpp
deleted file mode 100755
index 0f2976274..000000000
--- a/Gen/Generators/src/Lib/getaddr.cpp
+++ /dev/null
@@ -1,22 +0,0 @@
-// $Id: getaddr.cpp,v 1.1.1.1 2005-06-20 21:42:17 robbep Exp $
-////////////////////////////////////////////////////////////////////////
-// Routine meant to be called from FORTRAN which simply returns the
-// address of the (FORTRAN) argument. This should be 64bit-safe.
-//
-// 1999/01/08 Chris Green (Purdue University)
-// 1999/04/29 CG * altered to use void* from long*
-////////////////////////////////////////////////////////////////////////
-
-#ifdef WIN32
-extern "C" void* __stdcall GETADDR(void* arg) {
-  return(arg);
-}
-#else
-extern "C" {
-  void* getaddr_(void* arg);
-}
-
-void* getaddr_(void* arg) {
-  return(arg);
-}
-#endif
diff --git a/Gen/Generators/src/Lib/pythiaoutput_utils.F b/Gen/Generators/src/Lib/pythiaoutput_utils.F
deleted file mode 100755
index 3ae209063..000000000
--- a/Gen/Generators/src/Lib/pythiaoutput_utils.F
+++ /dev/null
@@ -1,44 +0,0 @@
-C $Id: pythiaoutput_utils.F,v 1.5 2006-03-12 19:04:20 robbep Exp $
-      SUBROUTINE pythiaoutput_init( IVAL )
-C-----------------------------------------------------------------------
-C  Purpose   : Initialize Pythia output (suppress output)
-C  Arguments : IVAL : 0 -- Keep output   1 -- Suppress output
-C
-C  Author    : Patrick Robbe
-C  Created   : 2005-02-21
-C-----------------------------------------------------------------------
-      IMPLICIT NONE
-C- Include Files
-C- Local Variables
-C-----------------------------------------------------------------------
-      INTEGER IVAL
-      INTEGER MSTU, MSTJ
-      DOUBLE PRECISION PARU, PARJ
-      COMMON/PYDAT1/MSTU(200),PARU(200),MSTJ(200),PARJ(200)
-      INTEGER MSTP,MSTI
-      DOUBLE PRECISION PARP,PARI
-      COMMON/PYPARS/MSTP(200),PARP(200),MSTI(200),PARI(200)
-      EXTERNAL PYDATA
-
-      IF ( IVAL.EQ.0 ) THEN
-        IF (MSTU(12).NE.12345) MSTU( 12 ) = 1
-        MSTU( 13 ) = 1
-        MSTU( 25 ) = 1
-        MSTP( 122 ) = 1
-      ELSEIF ( IVAL.EQ.1 ) THEN
-        IF (MSTU(11).NE.49) THEN
-          MSTU( 12 ) = 12345
-          MSTU( 13 ) = 0
-          MSTU( 25 ) = 0
-          MSTP( 122 ) = 0
-        ELSE
-          MSTU( 12 ) = 1 
-          MSTU( 13 ) = 1
-          MSTU( 25 ) = 1
-          MSTP( 122 ) = 1
-        ENDIF
-      ENDIF
-      
-  999 RETURN
-      END
-
diff --git a/Gen/Generators/src/component/ApplyPhotos.cpp b/Gen/Generators/src/component/ApplyPhotos.cpp
deleted file mode 100644
index 3eabd15bb..000000000
--- a/Gen/Generators/src/component/ApplyPhotos.cpp
+++ /dev/null
@@ -1,140 +0,0 @@
-// $Id: $
-// Include files
-#include "Photos/Photos.h"
-#include "Photos/PhotosHepMCEvent.h"
-#include "Photos/PhotosHepMCParticle.h"
-#include "Photos/PhotosParticle.h"
-
-// Generators
-#include "Generators/RandomForGenerator.h"
-
-// from Gaudi
-
-// from Event
-#include "Event/HepMCEvent.h"
-
-// local
-#include "ApplyPhotos.h"
-
-//-----------------------------------------------------------------------------
-// Implementation file for class : ApplyPhotos
-//
-// 2011-05-27 : Patrick Robbe
-//-----------------------------------------------------------------------------
-
-// Declaration of the Algorithm Factory
-DECLARE_COMPONENT( ApplyPhotos )
-
-
-//=============================================================================
-// Standard constructor, initializes variables
-//=============================================================================
-ApplyPhotos::ApplyPhotos( const std::string& name,
-                          ISvcLocator* pSvcLocator)
-  : GaudiAlgorithm ( name , pSvcLocator ) {
-    // Location of the input from the generation
-    declareProperty ( "HepMCEventLocation" , m_hepMCEventLocation =
-                      LHCb::HepMCEventLocation::Default ) ;
-    declareProperty ( "PDGId" , m_pdgIdList ) ;
-}
-//=============================================================================
-// Destructor
-//=============================================================================
-ApplyPhotos::~ApplyPhotos() {}
-
-//=============================================================================
-// Initialization
-//=============================================================================
-StatusCode ApplyPhotos::initialize() {
-  StatusCode sc = GaudiAlgorithm::initialize(); // must be executed first
-  if ( sc.isFailure() ) return sc;  // error printed already by GaudiAlgorithm
-
-  if ( msgLevel( MSG::DEBUG ) ) debug() << "==> Initialize" << endmsg;
-
-  if ( m_pdgIdList.empty() ) 
-    return Error( "PDGId list property is not set" ) ;
-
-  for ( std::vector<int>::iterator it = m_pdgIdList.begin() ; 
-        it != m_pdgIdList.end() ; ++it ) m_pdgIds.insert( *it ) ;
-  
-  // Initialize PHOTOS
-  Photospp::Photos::initialize();
-  
-  // Give the Gauss random generator to Gauss 
-  // It is already initialized in Generation !
-  Photospp::Photos::setRandomGenerator( RandomForGenerator::flat );
-  // Set minimum photon energy (50keV at 1 GeV scale)
-  Photospp::Photos::setInfraredCutOff(1.e-7);
-  // Increase the maximum possible value of the interference weight
-  Photospp::Photos::maxWtInterference(64.0); // 2^n, where n = number of charges (+,-)
-  Photospp::Photos::setInterference( true ) ;
-  Photospp::Photos::setExponentiation( true ) ;
-
-  return StatusCode::SUCCESS;
-}
-
-//=============================================================================
-// Main execution
-//=============================================================================
-StatusCode ApplyPhotos::execute() {
-
-  if ( msgLevel(MSG::DEBUG) ) debug() << "==> Execute" << endmsg;
-
-  // Retrieve info from the TES
-  LHCb::HepMCEvents* theEvents =
-    get<LHCb::HepMCEvents>( m_hepMCEventLocation );
-
-  LHCb::HepMCEvents::iterator it ;
-
-  for ( it = theEvents -> begin() ; it != theEvents -> end() ; ++it ) {
-    HepMC::GenEvent * ev = (*it) -> pGenEvt() ;
-    for ( HepMC::GenEvent::particle_iterator itP = ev -> particles_begin() ;
-          itP != ev -> particles_end() ; ++itP ) {
-      if ( LHCb::HepMCEvent::DocumentationParticle != (*itP) -> status() ) {
-        if ( std::binary_search( m_pdgIds.begin() , m_pdgIds.end() , 
-                                 abs( (*itP) -> pdg_id() ) ) ) {
-          HepMC::GenVertex * EV = (*itP) -> end_vertex() ;
-          if ( 0 == EV ) continue ;
-
-          // Make one event with only the "signal" and its decay products
-          HepMC::GenEvent * newEvent = new HepMC::GenEvent( ) ;
-
-          // Fill the event
-          newEvent -> add_vertex( EV ) ;
-          HepMC::GenVertex::particle_iterator iterDes ;
-          for ( iterDes = EV -> particles_begin( HepMC::descendants ) ;
-                iterDes != EV -> particles_end( HepMC::descendants ) ; ++iterDes ) {
-            if ( 0 != (*iterDes) -> end_vertex() ) 
-              newEvent -> add_vertex( (*iterDes) -> end_vertex() ) ;
-          }
-
-         // Process the event in PHOTOS
-          Photospp::PhotosHepMCEvent photosEvent( newEvent );
-          photosEvent.process();
-
-          ev -> add_vertex( EV ) ;
-          for ( iterDes = EV -> particles_begin( HepMC::descendants ) ;
-                iterDes != EV -> particles_end( HepMC::descendants ) ; ++iterDes ) {
-            if ( 0 != (*iterDes) -> end_vertex() ) 
-              ev -> add_vertex( (*iterDes) -> end_vertex() ) ;
-          }
-        }
-      }
-    }
-  }
-  
-  return StatusCode::SUCCESS;
-}
-
-//=============================================================================
-//  Finalize
-//=============================================================================
-StatusCode ApplyPhotos::finalize() {
-
-  if ( msgLevel(MSG::DEBUG) ) debug() << "==> Finalize" << endmsg;
-
-  return GaudiAlgorithm::finalize();  // must be called after all other actions
-}
-
-//=============================================================================
-
diff --git a/Gen/Generators/src/component/ApplyPhotos.h b/Gen/Generators/src/component/ApplyPhotos.h
deleted file mode 100644
index 90d4dc1fc..000000000
--- a/Gen/Generators/src/component/ApplyPhotos.h
+++ /dev/null
@@ -1,35 +0,0 @@
-// $Id: $
-#ifndef GENERATORS_APPLYPHOTOS_H
-#define GENERATORS_APPLYPHOTOS_H 1
-
-// Include files
-// from Gaudi
-#include "GaudiAlg/GaudiAlgorithm.h"
-
-/** @class ApplyPhotos ApplyPhotos.h component/ApplyPhotos.h
- *  Class to apply photos on a given particle
- *
- *  @author Patrick Robbe
- *  @date   2011-05-27
- */
-class ApplyPhotos : public GaudiAlgorithm {
-public:
-  /// Standard constructor
-  ApplyPhotos( const std::string& name, ISvcLocator* pSvcLocator );
-
-  virtual ~ApplyPhotos( ); ///< Destructor
-
-  StatusCode initialize() override;    ///< Algorithm initialization
-  StatusCode execute   () override;    ///< Algorithm execution
-  StatusCode finalize  () override;    ///< Algorithm finalization
-
-protected:
-
-private:
-
-  std::string  m_hepMCEventLocation ;    ///< Input TES for HepMC events
-
-  std::vector< int > m_pdgIdList    ;    ///< list of the particle ID to study
-  std::set   < int > m_pdgIds       ;    ///< ordered list of PDG Ids
-};
-#endif // GENERATORS_APPLYPHOTOS_H
diff --git a/Gen/Generators/src/component/AsymmetricCollidingBeams.cpp b/Gen/Generators/src/component/AsymmetricCollidingBeams.cpp
deleted file mode 100755
index 9c5ceb8b6..000000000
--- a/Gen/Generators/src/component/AsymmetricCollidingBeams.cpp
+++ /dev/null
@@ -1,128 +0,0 @@
-// Include files 
-
-// local
-#include "AsymmetricCollidingBeams.h"
-
-// from Gaudi
-#include "GaudiKernel/IRndmGenSvc.h"
-
-// From Kernel
-#include "GaudiKernel/SystemOfUnits.h"
-
-// From Event
-#include "Event/BeamParameters.h"
-#include "GenEvent/BeamForInitialization.h"
-
-//-----------------------------------------------------------------------------
-// Implementation file for class : AsymmetricCollidingBeams
-//
-// 2016-10-27 : Patrick Robbe
-//-----------------------------------------------------------------------------
-
-// Declaration of the Tool Factory
-
-DECLARE_COMPONENT( AsymmetricCollidingBeams )
-
-
-//=============================================================================
-// Standard constructor, initializes variables
-//=============================================================================
-AsymmetricCollidingBeams::AsymmetricCollidingBeams( const std::string& type,
-                                                    const std::string& name,
-                                                    const IInterface* parent )
-  : GaudiTool ( type, name , parent ) {
-    declareInterface< IBeamTool >( this ) ;
-    declareProperty( "BeamParameters" , 
-                     m_beamParameters = LHCb::BeamParametersLocation::Default ) ;
-    declareProperty( "Beam2Momentum" , 
-                     m_beam2_zMomentum = 0. ) ;
-}
-
-//=============================================================================
-// Destructor 
-//=============================================================================
-AsymmetricCollidingBeams::~AsymmetricCollidingBeams( ) { ; }
-
-//=============================================================================
-// Initialize method
-//=============================================================================
-StatusCode AsymmetricCollidingBeams::initialize( ) {
-  StatusCode sc = GaudiTool::initialize( ) ;
-  if ( sc.isFailure() ) return sc ;
-
-  // Initialize the number generator
-  IRndmGenSvc * randSvc = svc< IRndmGenSvc >( "RndmGenSvc" , true ) ;
-  
-  sc = m_gaussianDist.initialize( randSvc , Rndm::Gauss( 0. , 1. ) )  ;
-  if ( ! sc.isSuccess() ) 
-    return Error( "Could not initialize Gaussian random generator" , sc ) ;
-  release( randSvc ) ;
-
-  return sc ;
-}
-
-//=============================================================================
-// Mean value of the beam momentum
-//=============================================================================
-void AsymmetricCollidingBeams::getMeanBeams( Gaudi::XYZVector & pBeam1 , 
-                                             Gaudi::XYZVector & pBeam2 )
-  const {
-  // Retrieve beam parameters from the static class
-  LHCb::BeamParameters * beam = 
-    BeamForInitialization::getInitialBeamParameters() ;
-  if ( 0 == beam ) 
-    Exception( "No beam parameters in initialization" ) ;
-
-  double p1x, p1y, p1z, p2x, p2y, p2z ;
-  
-  p1x = beam -> energy() * 
-    sin( beam -> horizontalCrossingAngle() +
-         beam -> horizontalBeamlineAngle() ) ;
-  p1y = beam -> energy() * 
-    sin( beam -> verticalCrossingAngle() + 
-         beam -> verticalBeamlineAngle() ) ;
-  p1z = beam -> energy() ;
-  pBeam1.SetXYZ( p1x, p1y, p1z ) ;
-
-  p2x = m_beam2_zMomentum * 
-    sin( beam -> horizontalCrossingAngle() - 
-         beam -> horizontalBeamlineAngle() ) ;
-  p2y = m_beam2_zMomentum * 
-    sin( beam -> verticalCrossingAngle() - 
-         beam -> verticalBeamlineAngle() ) ;
-  p2z = -m_beam2_zMomentum ;
-  pBeam2.SetXYZ( p2x, p2y, p2z ) ;
-}
-
-//=============================================================================
-// Current value of the smeared beams
-//=============================================================================
-void AsymmetricCollidingBeams::getBeams( Gaudi::XYZVector & pBeam1 , 
-                               Gaudi::XYZVector & pBeam2 ) {
-  // Retrieve beam parameters
-  LHCb::BeamParameters * beam = get< LHCb::BeamParameters >( m_beamParameters ) ;
-  if ( 0 == beam ) Exception( "No beam parameters in TES" ) ;
-
-  double p1x, p1y, p1z, p2x, p2y, p2z ;
-  p1x = beam -> energy() * 
-    sin( beam -> horizontalCrossingAngle() + 
-         beam -> horizontalBeamlineAngle() + 
-         m_gaussianDist() * beam -> angleSmear() ) ;
-  p1y = beam -> energy() * 
-    sin( beam -> verticalCrossingAngle() + 
-         beam -> verticalBeamlineAngle() +
-         m_gaussianDist() * beam -> angleSmear() ) ;
-  p1z = beam -> energy() ;
-  pBeam1.SetXYZ( p1x, p1y, p1z ) ;
-
-  p2x = m_beam2_zMomentum * 
-    sin( beam -> horizontalCrossingAngle() - 
-         beam -> horizontalBeamlineAngle() + 
-         m_gaussianDist() * beam -> angleSmear() ) ;
-  p2y = m_beam2_zMomentum  * 
-    sin( beam -> verticalCrossingAngle() - 
-         beam -> verticalBeamlineAngle() +
-         m_gaussianDist() * beam -> angleSmear() ) ;
-  p2z = -m_beam2_zMomentum ;
-  pBeam2.SetXYZ( p2x, p2y, p2z ) ;
-}
diff --git a/Gen/Generators/src/component/AsymmetricCollidingBeams.h b/Gen/Generators/src/component/AsymmetricCollidingBeams.h
deleted file mode 100755
index 4383fcafd..000000000
--- a/Gen/Generators/src/component/AsymmetricCollidingBeams.h
+++ /dev/null
@@ -1,53 +0,0 @@
-#ifndef GENERATORS_ASYMMETRICCOLLIDINGBEAMS_H
-#define GENERATORS_ASYMMETRICCOLLIDINGBEAMS_H 1
-
-// Include files
-// from Gaudi
-#include "GaudiAlg/GaudiTool.h"
-#include "GaudiKernel/RndmGenerators.h"
-
-#include "Generators/IBeamTool.h"
-
-// Forward declarations
-class IRndmGenSvc ;
-
-/** @class AsymmetricCollidingBeams AsymmetricCollidingBeams.h "AsymmetricCollidingBeams.h"
- *
- *  Tool to compute colliding beams values, with asymmetric beams.
- *  Concrete implementation
- *  of a beam tool.
- *
- *  @author Patrick Robbe
- *  @date   2016-10-27
- */
-class AsymmetricCollidingBeams : public GaudiTool, virtual public IBeamTool {
- public:
-  /// Standard constructor
-  AsymmetricCollidingBeams( const std::string& type, const std::string& name,
-                            const IInterface* parent ) ;
-
-  virtual ~AsymmetricCollidingBeams( ); ///< Destructor
-
-  /// Initialize method
-  StatusCode initialize( ) override;
-
-  /** Implements IBeamTool::getMeanBeams
-   */
-  void getMeanBeams( Gaudi::XYZVector & pBeam1 ,
-                     Gaudi::XYZVector & pBeam2 ) const override;
-
-  /** Implements IBeamTool::getBeams
-   *  Compute beam 3-momentum taking into account the horizontal and vertical
-   *  beam angles (given by job options). These angles are Gaussian-smeared
-   *  with an angular smearing equal to (emittance/beta*)^1/2.
-   */
-  void getBeams( Gaudi::XYZVector & pBeam1 ,
-                 Gaudi::XYZVector & pBeam2 ) override;
-
- private:
-  std::string m_beamParameters ; ///< Location of beam parameters (set by options)
-  double m_beam2_zMomentum ; ///< Energy of the second beam (beam 2)
-
-  Rndm::Numbers m_gaussianDist ; ///< Gaussian random number generator
-};
-#endif // GENERATORS_ASYMMETRICCOLLIDINGBEAMS_H
diff --git a/Gen/Generators/src/component/BeamSpotMarkovChainSampleVertex.cpp b/Gen/Generators/src/component/BeamSpotMarkovChainSampleVertex.cpp
deleted file mode 100644
index 163864596..000000000
--- a/Gen/Generators/src/component/BeamSpotMarkovChainSampleVertex.cpp
+++ /dev/null
@@ -1,219 +0,0 @@
-
-// local
-#include "BeamSpotMarkovChainSampleVertex.h"
-
-//-----------------------------------------------------------------------------
-// Implementation file for class : LHCbAcceptance
-//
-// 2016-10-10 : Floris Keizer
-//-----------------------------------------------------------------------------
-
-//=============================================================================
-// Standard constructor, initializes variables
-//=============================================================================
-BeamSpotMarkovChainSampleVertex::
-BeamSpotMarkovChainSampleVertex( const std::string& type,
-                                 const std::string& name,
-                                 const IInterface* parent )
-  : GaudiTool ( type, name , parent )
-{
-  declareInterface< IVertexSmearingTool >( this ) ;
-  declareProperty( "Xcut" , m_xcut = 4. ) ; // times SigmaX
-  declareProperty( "Ycut" , m_ycut = 4. ) ; // times SigmaY
-  declareProperty( "Zcut" , m_zcut = 4. ) ; // times SigmaZ
-  declareProperty( "BeamParameters" ,
-                   m_beamParameters = LHCb::BeamParametersLocation::Default ) ;
-  declareProperty( "NMarkovChainSamples", m_nMCSamples = 1000 );
-}
-
-//=============================================================================
-// Initialize
-//=============================================================================
-StatusCode BeamSpotMarkovChainSampleVertex::initialize( )
-{
-  StatusCode sc = GaudiTool::initialize( ) ;
-  if ( sc.isFailure() ) return sc ;
-
-  IRndmGenSvc * randSvc = svc< IRndmGenSvc >( "RndmGenSvc" , true ) ;
-
-  // Gaussians used to perturb the four-vector in the Markov chain
-  // The standard deviation of the pertubation should reflect (about 10%)
-  // the width of the function that is sampled from.
-  // However, it is not sensitive to the precise value... changing for example
-  // the sigma in m_gaussDistZ from 5. to 7. will not make a difference.
-
-  sc = StatusCode( sc
-         && m_gaussDistX.initialize( randSvc , Rndm::Gauss( 0. , 0.025  ) )
-         && m_gaussDistY.initialize( randSvc , Rndm::Gauss( 0. , 0.025  ) )
-         && m_gaussDistZ.initialize( randSvc , Rndm::Gauss( 0. , 5.     ) )
-         && m_gaussDistT.initialize( randSvc , Rndm::Gauss( 0. , 1.     ) )
-         && m_flatDist.initialize  ( randSvc , Rndm::Flat ( 0. , 1.     ) ) );
-  if ( sc.isFailure() )
-  { return Error( "Could not initialize random number generators" ); }
-
-  release( randSvc ) ;
-
-  return sc ;
-}
-
-//=============================================================================
-// Function representing the product of two 4D Gaussian PDFs (Floris)
-//=============================================================================
-double BeamSpotMarkovChainSampleVertex::gauss4D( LHCb::BeamParameters * beamp ,
-                                                 const HepMC::FourVector & vec ) const
-{
-  const auto emittance = beamp -> emittance();
-  const auto betastar  = beamp -> betaStar();
-  const auto aX        = beamp -> horizontalCrossingAngle();
-  const auto aY        = beamp -> verticalCrossingAngle();
-
-  const auto c  = Gaudi::Units::c_light ;
-  const auto Pi = Gaudi::Units::pi;
-
-  const auto sx = std::sqrt( emittance*betastar );
-  const auto sy = sx;
-  const auto sz = beamp -> sigmaS();// RMS bunch length in mm
-
-  const auto x = vec.x();
-  const auto y = vec.y();
-  const auto z = vec.z();
-  const auto t = vec.t();
-
-  const auto sX2 = std::pow( sx ,2 );
-  const auto sY2 = std::pow( sy ,2 );
-  const auto sZ2 = std::pow( sz ,2 );
-  const auto x2 = std::pow( x , 2 );
-  const auto y2 = std::pow( y , 2 );
-  const auto z2 = std::pow( z , 2 );
-  const auto t2 = std::pow( t , 2 );
-  const auto c2 = std::pow(c,2);
-
-  const auto c2m3 = std::cos(2*aX - 3*aY);
-  const auto c4m2 = std::cos(4*aX - 2*aY);
-  const auto c04 = std::cos(4*aY);
-  const auto c20 = std::cos(2*aX);
-  const auto c40 = std::cos(4*aX);
-  const auto c2m2 = std::cos(2*(aX - aY));
-  const auto c2m1 = std::cos(2*aX - aY);
-  const auto c4m1 = std::cos(4*aX - aY);
-  const auto c01 = std::cos(aY);
-  const auto c02 = std::cos(2*aY);
-  const auto c03 = std::cos(3*aY);
-  const auto c2p2 = std::cos(2*(aX + aY));
-  const auto c4p4 = std::cos(4*(aX + aY));
-  const auto c4p2 = std::cos(2*(2*aX + aY));
-  const auto c2p4 = std::cos(2*(aX + 2*aY));
-  const auto c2p3 = std::cos(2*aX + 3*aY);
-  const auto c4p3 = std::cos(4*aX + 3*aY);
-  const auto c2p1 = std::cos(2*aX + aY);
-  const auto s10 = std::sin(aX);
-  const auto s30 = std::sin(3*aX);
-  const auto s1m3 = std::sin(aX - 3*aY);
-  const auto s1m2 = std::sin(aX - 2*aY);
-  const auto s3m2 = std::sin(3*aX - 2*aY);
-  const auto s1m1 = std::sin(aX - aY);
-  const auto s3m1 = std::sin(3*aX - aY);
-  const auto s1p1 = std::sin(aX + aY);
-  const auto s3p3 = std::sin(3*(aX + aY));
-  const auto s3p1 = std::sin(3*aX + aY);
-  const auto s1p2 = std::sin(aX + 2*aY);
-  const auto s3p2 = std::sin(3*aX + 2*aY);
-  const auto s1p3 = std::sin(aX + 3*aY);
-
-  // finally, return the function...
-  // This is computed from the Mathematica notebook primaryVertexPDF.nb
-  return std::exp((-700 - (800*sZ2)/sX2 - (900*sZ2)/sY2 + (140*c*t)/sz + (160*c*sz*t)/sX2 + (180*c*sz*t)/sY2 - (8*c2*t2)/sX2 - (9*c2*t2)/sY2 - (7*c2*t2)/sZ2 - (16*x2)/sX2 - (8*x2)/sY2 - (8*x2)/sZ2 - (16*y2)/sY2 - (16*y2)/sZ2 - (16*z2)/sX2 - (8*z2)/sY2 - (8*z2)/sZ2 - (2*(-2*sY2*sZ2*std::pow(-10*sz + c*t,2) + sX2*(sZ2*(300*sZ2 - 60*c*sz*t + 3*c2*t2 - 4*(x2 - 2*y2 + z2)) + sY2*(300*sZ2 - 60*c*sz*t + 3*c2*t2 + 4*(x2 - 2*y2 + z2))))*c20)/(sX2*sY2*sZ2) + ((sY2 - sZ2)*std::pow(-10*sz + c*t,2)*c40)/(sY2*sZ2) + 200*c2m3 - (200*sZ2*c2m3)/sY2 - (40*c*t*c2m3)/sz + (40*c*sz*t*c2m3)/sY2 - (2*c2*t2*c2m3)/sY2 + (2*c2*t2*c2m3)/sZ2 - 100*c4m2 + (100*sZ2*c4m2)/sY2 + (20*c*t*c4m2)/sz - (20*c*sz*t*c4m2)/sY2 + (c2*t2*c4m2)/sY2 - (c2*t2*c4m2)/sZ2 - 200*c2m2 + (600*sZ2*c2m2)/sY2 + (40*c*t*c2m2)/sz - (120*c*sz*t*c2m2)/sY2 + (6*c2*t2*c2m2)/sY2 - (2*c2*t2*c2m2)/sZ2 - (4*x2*c2m2)/sY2 + (4*x2*c2m2)/sZ2 + (4*z2*c2m2)/sY2 - (4*z2*c2m2)/sZ2 + 200*c2m1 - (200*sZ2*c2m1)/sY2 - (40*c*t*c2m1)/sz + (40*c*sz*t*c2m1)/sY2 - (2*c2*t2*c2m1)/sY2 + (2*c2*t2*c2m1)/sZ2 + (16*x*y*c2m1)/sY2 - (16*x*y*c2m1)/sZ2 + 200*c4m1 - (200*sZ2*c4m1)/sY2 - (40*c*t*c4m1)/sz + (40*c*sz*t*c4m1)/sY2 - (2*c2*t2*c4m1)/sY2 + (2*c2*t2*c4m1)/sZ2 - 200*c01 + (200*sZ2*c01)/sY2 + (40*c*t*c01)/sz - (40*c*sz*t*c01)/sY2 + (2*c2*t2*c01)/sY2 - (2*c2*t2*c01)/sZ2 - 400*c02 - (800*sZ2*c02)/sX2 + (400*sZ2*c02)/sY2 + (80*c*t*c02)/sz + (160*c*sz*t*c02)/sX2 - (80*c*sz*t*c02)/sY2 - (8*c2*t2*c02)/sX2 + (4*c2*t2*c02)/sY2 - (4*c2*t2*c02)/sZ2 - (16*x2*c02)/sX2 + (8*x2*c02)/sY2 + (8*x2*c02)/sZ2 + (16*z2*c02)/sX2 - (8*z2*c02)/sY2 - (8*z2*c02)/sZ2 + 200*c03 - (200*sZ2*c03)/sY2 - (40*c*t*c03)/sz + (40*c*sz*t*c03)/sY2 - (2*c2*t2*c03)/sY2 + (2*c2*t2*c03)/sZ2 - 100*c04 + (100*sZ2*c04)/sY2 + (20*c*t*c04)/sz - (20*c*sz*t*c04)/sY2 + (c2*t2*c04)/sY2 - (c2*t2*c04)/sZ2 - 600*c2p2 + (800*sZ2*c2p2)/sX2 + (200*sZ2*c2p2)/sY2 + (120*c*t*c2p2)/sz - (160*c*sz*t*c2p2)/sX2 - (40*c*sz*t*c2p2)/sY2 + (8*c2*t2*c2p2)/sX2 + (2*c2*t2*c2p2)/sY2 - (6*c2*t2*c2p2)/sZ2 - (4*x2*c2p2)/sY2 + (4*x2*c2p2)/sZ2 + (4*z2*c2p2)/sY2 - (4*z2*c2p2)/sZ2 - 100*c4p4 + (100*sZ2*c4p4)/sY2 + (20*c*t*c4p4)/sz - (20*c*sz*t*c4p4)/sY2 + (c2*t2*c4p4)/sY2 - (c2*t2*c4p4)/sZ2 - 200*c2p1 + (200*sZ2*c2p1)/sY2 + (40*c*t*c2p1)/sz - (40*c*sz*t*c2p1)/sY2 + (2*c2*t2*c2p1)/sY2 - (2*c2*t2*c2p1)/sZ2 - (16*x*y*c2p1)/sY2 + (16*x*y*c2p1)/sZ2 - 300*c4p2 + (300*sZ2*c4p2)/sY2 + (60*c*t*c4p2)/sz - (60*c*sz*t*c4p2)/sY2 + (3*c2*t2*c4p2)/sY2 - (3*c2*t2*c4p2)/sZ2 - 200*c2p4 + (400*sZ2*c2p4)/sX2 - (200*sZ2*c2p4)/sY2 + (40*c*t*c2p4)/sz - (80*c*sz*t*c2p4)/sX2 + (40*c*sz*t*c2p4)/sY2 +  (4*c2*t2*c2p4)/sX2 - (2*c2*t2*c2p4)/sY2 - (2*c2*t2*c2p4)/sZ2 - 200*c2p3 + (200*sZ2*c2p3)/sY2 + (40*c*t*c2p3)/sz - (40*c*sz*t*c2p3)/sY2 + (2*c2*t2*c2p3)/sY2 - (2*c2*t2*c2p3)/sZ2 - 200*c4p3 +  (200*sZ2*c4p3)/sY2 + (40*c*t*c4p3)/sz - (40*c*sz*t*c4p3)/sY2 + (2*c2*t2*c4p3)/sY2 - (2*c2*t2*c4p3)/sZ2 + (80*x*s10)/sz - (80*sz*x*s10)/sY2 + (8*c*t*x*s10)/sY2 - (8*c*t*x*s10)/sZ2 - (80*y*s10)/sz + (80*sz*y*s10)/sY2 - (8*c*t*y*s10)/sY2 + (8*c*t*y*s10)/sZ2 + (80*x*s30)/sz - (80*sz*x*s30)/sY2 + (8*c*t*x*s30)/sY2 - (8*c*t*x*s30)/sZ2 - (80*y*s30)/sz + (80*sz*y*s30)/sY2 - (8*c*t*y*s30)/sY2 + (8*c*t*y*s30)/sZ2 + (40*x*s1m3)/sz - (40*sz*x*s1m3)/sY2 + (4*c*t*x*s1m3)/sY2 - (4*c*t*x*s1m3)/sZ2 - (40*x*s1m2)/sz + (40*sz*x*s1m2)/sY2 - (4*c*t*x*s1m2)/sY2 + (4*c*t*x*s1m2)/sZ2 - (80*y*s1m2)/sz +  (80*sz*y*s1m2)/sY2 - (8*c*t*y*s1m2)/sY2 + (8*c*t*y*s1m2)/sZ2 - (40*x*s3m2)/sz + (40*sz*x*s3m2)/sY2 - (4*c*t*x*s3m2)/sY2 + (4*c*t*x*s3m2)/sZ2 + (80*x*s1m1)/sz + (160*sz*x*s1m1)/sX2 + (80*sz*x*s1m1)/sY2 - (16*c*t*x*s1m1)/sX2 - (8*c*t*x*s1m1)/sY2 - (8*c*t*x*s1m1)/sZ2 - (80*y*s1m1)/sz - (240*sz*y*s1m1)/sY2 + (24*c*t*y*s1m1)/sY2 + (8*c*t*y*s1m1)/sZ2 + (40*x*s3m1)/sz - (40*sz*x*s3m1)/sY2 + (4*c*t*x*s3m1)/sY2 - (4*c*t*x*s3m1)/sZ2 + (80*y*s3m1)/sz - (80*sz*y*s3m1)/sY2 + (8*c*t*y*s3m1)/sY2 - (8*c*t*y*s3m1)/sZ2 - (40*x*s1p1)/sz + (320*sz*x*s1p1)/sX2 + (40*sz*x*s1p1)/sY2 - (32*c*t*x*s1p1)/sX2 - (4*c*t*x*s1p1)/sY2 + (4*c*t*x*s1p1)/sZ2 + (80*y*s1p1)/sz + (240*sz*y*s1p1)/sY2 - (24*c*t*y*s1p1)/sY2 - (8*c*t*y*s1p1)/sZ2 - (40*x*s3p3)/sz + (40*sz*x*s3p3)/sY2 - (4*c*t*x*s3p3)/sY2 + (4*c*t*x*s3p3)/sZ2 - (80*y*s3p1)/sz + (80*sz*y*s3p1)/sY2 - (8*c*t*y*s3p1)/sY2 + (8*c*t*y*s3p1)/sZ2 - (40*x*s1p2)/sz + (40*sz*x*s1p2)/sY2 - (4*c*t*x*s1p2)/sY2 + (4*c*t*x*s1p2)/sZ2 - (40*x*s3p2)/sz + (40*sz*x*s3p2)/sY2 - (4*c*t*x*s3p2)/sY2 + (4*c*t*x*s3p2)/sZ2 - (80*y*s3p2)/sz + (80*sz*y*s3p2)/sY2 - (8*c*t*y*s3p2)/sY2 + (8*c*t*y*s3p2)/sZ2 - (80*x*s1p3)/sz + (160*sz*x*s1p3)/sX2 - (80*sz*x*s1p3)/sY2 - (16*c*t*x*s1p3)/sX2 + (8*c*t*x*s1p3)/sY2 + (8*c*t*x*s1p3)/sZ2)/32.)/(8.*std::pow(Pi,3)*sX2*sY2*sZ2);
-}
-
-//=============================================================================
-// Markov chain sampler
-//=============================================================================
-StatusCode BeamSpotMarkovChainSampleVertex::smearVertex( LHCb::HepMCEvent * theEvent )
-{
-
-  LHCb::BeamParameters * beamp = get< LHCb::BeamParameters >( m_beamParameters ) ;
-  if ( ! beamp ) Exception( "No beam parameters registered" ) ;
-
-  // The sampled point. Always start at origin for reproducibility.
-  HepMC::FourVector x( 0 , 0 , 0 , 0 );
-
-  // Repeat until we get a sampled point within the defined (x,,y,z) limits
-  unsigned int iLoop = 0; // sanity check to prevent infinite loops...
-  bool OK = false;
-  while ( iLoop++ < m_nMCSamples && !OK )
-  {
-    for ( unsigned int repeat = 0; repeat < m_nMCSamples; ++repeat )
-    {
-      // Copute the PDF value for this point
-      const auto f = gauss4D( beamp , x );
-
-      // smear the point. random walk.
-      const HepMC::FourVector y( x.x() + m_gaussDistX(),
-                                 x.y() + m_gaussDistY(),
-                                 x.z() + m_gaussDistZ(),
-                                 x.t() + m_gaussDistT() );
-
-      // compute the prob for the new point
-      const auto g = gauss4D( beamp , y );
-
-      if ( f < g )
-      {
-        // new point is better, so always keep
-        x = y;
-      }
-      else
-      {
-        // randomly keep worse point a fraction depending on the prob values.
-        const auto ratio = ( fabs(f)>0 ? g/f : 0.0 );
-        const auto r = m_flatDist( );
-        if ( r < ratio ) { x = y; }
-      }
-    }
-
-    // Check final if the spatial part of x is within the defined limits.
-    OK = ( ( fabs(x.x()) < ( m_xcut * beamp->sigmaX() ) ) &&
-           ( fabs(x.y()) < ( m_ycut * beamp->sigmaY() ) ) &&
-           ( fabs(x.z()) < ( m_zcut * beamp->sigmaZ() ) ) );
-
-    // reset and repeat
-    if ( !OK ) { x = HepMC::FourVector(0,0,0,0); }
-
-  }
-  if ( UNLIKELY(!OK) )
-  {
-    Warning( "Markov Chain sampling for PV (x,y,z,t) failed" ).ignore();
-  }
-  else
-  {
-
-    // A shift to put the mean of the temporal distribution at t=0.// Factor 10 because the bunches
-    // start 10*sigmaZ away from the interaction point.
-    const auto timeDelay = 10*(beamp -> sigmaS())/Gaudi::Units::c_light;
-
-    // Shift the sampled point to average beam spot position and time offset
-    x.setT( x.t() - timeDelay );
-    x.setX( x.x() + beamp -> beamSpot().x() ); // Offset the centre of the beamspot
-    x.setY( x.y() + beamp -> beamSpot().y() );
-    x.setZ( x.z() + beamp -> beamSpot().z() );
-
-    // update the values for all vertices
-    auto * pEvt = theEvent -> pGenEvt() ;
-    if ( pEvt )
-    {
-      for ( auto vit = pEvt -> vertices_begin() ; vit != pEvt -> vertices_end() ; ++vit )
-      {
-        const auto pos = (*vit) -> position() ;
-        (*vit) -> set_position( HepMC::FourVector( pos.x() + x.x() ,
-                                                   pos.y() + x.y() ,
-                                                   pos.z() + x.z() ,
-                                                   pos.t() + x.t() ) ) ;
-      }
-    }
-
-  }
-
-  return StatusCode::SUCCESS;
-}
-
-// Declaration of the Tool Factory
-DECLARE_COMPONENT( BeamSpotMarkovChainSampleVertex )
diff --git a/Gen/Generators/src/component/BeamSpotMarkovChainSampleVertex.h b/Gen/Generators/src/component/BeamSpotMarkovChainSampleVertex.h
deleted file mode 100644
index ca2c62cb2..000000000
--- a/Gen/Generators/src/component/BeamSpotMarkovChainSampleVertex.h
+++ /dev/null
@@ -1,99 +0,0 @@
-#ifndef GENERATORS_BeamSpotMarkovChainSampleVertex_H
-#define GENERATORS_BeamSpotMarkovChainSampleVertex_H 1
-
-// Include files
-// from Gaudi
-#include "GaudiAlg/GaudiTool.h"
-#include "GaudiKernel/RndmGenerators.h"
-
-// from Gaudi
-#include "GaudiKernel/IRndmGenSvc.h"
-#include "GaudiKernel/PhysicalConstants.h"
-
-// from Event
-#include "Event/HepMCEvent.h"
-#include "Event/BeamParameters.h"
-
-#include "Generators/IVertexSmearingTool.h"
-
-/** @class BeamSpotMarkovChainSampleVertex BeamSpotMarkovChainSampleVertex.h
- *
- *  VertexSmearingTool to sample the (x,y,z,t) parameters from a 4D PDF
- *  that describes the intersection of two bunches.
- *
- *  @author Floris Keizer
- *  @author Chris Jones
- *  @date   2016-10-10
- */
-class BeamSpotMarkovChainSampleVertex final : public GaudiTool,
-                                              virtual public IVertexSmearingTool
-{
-
-public:
-
-  /// Standard constructor
-  BeamSpotMarkovChainSampleVertex( const std::string& type,
-                                   const std::string& name,
-                                   const IInterface* parent );
-
-
-  /// Initialize function
-  StatusCode initialize( ) override;
-
-  /** Implementation of IVertexSmearingTool::smearVertex.
-   *  Gaussian smearing of spatial position of primary event truncated
-   *  at a given number of sigma.
-   */
-  StatusCode smearVertex( LHCb::HepMCEvent * theEvent ) override;
-
- private:
-
-  //=============================================================================
-  // Test function to try Markov chain
-  //=============================================================================
-  // inline double tophat( const HepMC::FourVector& x ) const noexcept
-  // {
-  //   return ( (fabs(x.x())<2.0) &&
-  //            (fabs(x.y())<2.0) &&
-  //            (fabs(x.z())<2.0) &&
-  //            (fabs(x.t())<2.0) ? 2.0 : 0.000001 );
-  // }
-
-  //=============================================================================
-  // Test function to try Markov chain
-  //=============================================================================
-  // double triangle( const HepMC::FourVector& x ) const noexcept
-  // {
-  //   return ( x.t() < 0.0 ? 0.0 :
-  //            x.t() < 2.0 ? 2.0 - x.t() :
-  //            0.0 );
-  // }
-
-  /// Probability distribution in 4D
-  double gauss4D( LHCb::BeamParameters * beamp ,
-                  const HepMC::FourVector & vec ) const;
-
- private:
-
-  std::string m_beamParameters ; ///< Location of beam parameters (set by options)
-
-  /// Number of Markov Chain sampling iterations
-  unsigned int m_nMCSamples;
-
-  /// Number of sigma above which to cut for x-axis smearing (set by options)
-  double m_xcut;
-  /// Number of sigma above which to cut for y-axis smearing (set by options)
-  double m_ycut;
-  /// Number of sigma above which to cut for z-axis smearing (set by options)
-  double m_zcut;
-
-  //  Rndm::Numbers m_gaussDist ; ///< Gaussian random number generator
-  Rndm::Numbers m_gaussDistX ; ///< Gaussian random number generator for Markov chain pertubation in x
-  Rndm::Numbers m_gaussDistY ; ///< Gaussian random number generator for Markov chain pertubation in y
-  Rndm::Numbers m_gaussDistZ ; ///< Gaussian random number generator for Markov chain pertubation in z
-  Rndm::Numbers m_gaussDistT ; ///< Gaussian random number generator for Markov chain pertubation in t
-  Rndm::Numbers m_flatDist ; ///< Random number generator (between 0 and 1)
-
-};
-
-#endif // GENERATORS_BeamSpotMarkovChainSampleVertex_H
diff --git a/Gen/Generators/src/component/BeamSpotSmearVertex.cpp b/Gen/Generators/src/component/BeamSpotSmearVertex.cpp
deleted file mode 100755
index d129d6fbe..000000000
--- a/Gen/Generators/src/component/BeamSpotSmearVertex.cpp
+++ /dev/null
@@ -1,102 +0,0 @@
-// $Id: BeamSpotSmearVertex.cpp,v 1.12 2010-05-09 17:05:42 gcorti Exp $
-// Include files 
-
-// local
-#include "BeamSpotSmearVertex.h"
-
-// from Gaudi
-#include "GaudiKernel/IRndmGenSvc.h"
-#include "GaudiKernel/PhysicalConstants.h" 
-
-// from Event
-#include "Event/HepMCEvent.h"
-#include "Event/BeamParameters.h"
-
-//-----------------------------------------------------------------------------
-// Implementation file for class : LHCbAcceptance
-//
-// 2005-08-17 : Patrick Robbe
-//-----------------------------------------------------------------------------
-
-// Declaration of the Tool Factory
-
-DECLARE_COMPONENT( BeamSpotSmearVertex )
-
-
-//=============================================================================
-// Standard constructor, initializes variables
-//=============================================================================
-BeamSpotSmearVertex::BeamSpotSmearVertex( const std::string& type,
-                                          const std::string& name,
-                                          const IInterface* parent )
-  : GaudiTool ( type, name , parent ) {
-    declareInterface< IVertexSmearingTool >( this ) ;
-    declareProperty( "Xcut" , m_xcut = 4. ) ; // times SigmaX 
-    declareProperty( "Ycut" , m_ycut = 4. ) ; // times SigmaY
-    declareProperty( "Zcut" , m_zcut = 4. ) ; // times SigmaZ
-    declareProperty( "SignOfTimeVsT0", m_timeSignVsT0 = 0 ) ;
-    declareProperty( "BeamParameters" , 
-                     m_beamParameters = LHCb::BeamParametersLocation::Default ) ;
-}
-
-//=============================================================================
-// Destructor 
-//=============================================================================
-BeamSpotSmearVertex::~BeamSpotSmearVertex( ) { ; }
-
-//=============================================================================
-// Initialize 
-//=============================================================================
-StatusCode BeamSpotSmearVertex::initialize( ) {
-  StatusCode sc = GaudiTool::initialize( ) ;
-  if ( sc.isFailure() ) return sc ;
-  
-  IRndmGenSvc * randSvc = svc< IRndmGenSvc >( "RndmGenSvc" , true ) ;
-  sc = m_gaussDist.initialize( randSvc , Rndm::Gauss( 0. , 1. ) ) ;
-  if ( ! sc.isSuccess() ) 
-    return Error( "Could not initialize gaussian random number generator" ) ;
-
-    
-  info() << "Smearing of interaction point with Gaussian distribution "
-         << endmsg;
-
-  release( randSvc ) ;
- 
-  return sc ;
-}
-
-//=============================================================================
-// Smearing function
-//=============================================================================
-StatusCode BeamSpotSmearVertex::smearVertex( LHCb::HepMCEvent * theEvent ) {
-
-  LHCb::BeamParameters * beamp = get< LHCb::BeamParameters >( m_beamParameters ) ;
-  if ( 0 == beamp ) Exception( "No beam parameters registered" ) ;
-
-  double dx , dy , dz;
-  
-  do { dx = m_gaussDist( ) ; } while ( fabs( dx ) > m_xcut ) ;
-  dx = dx * beamp -> sigmaX() + beamp -> beamSpot().x() ;
-  do { dy = m_gaussDist( ) ; } while ( fabs( dy ) > m_ycut ) ;
-  dy = dy * beamp -> sigmaY() + beamp -> beamSpot().y() ;
-  do { dz = m_gaussDist( ) ; } while ( fabs( dz ) > m_zcut ) ;
-  dz = dz * beamp -> sigmaZ() + beamp -> beamSpot().z() ;
-
-  double meanT = m_timeSignVsT0 * beamp -> beamSpot().z() / Gaudi::Units::c_light ;
-
-  HepMC::FourVector dpos( dx , dy , dz , meanT ) ;
-  
-  HepMC::GenEvent::vertex_iterator vit ;
-  HepMC::GenEvent * pEvt = theEvent -> pGenEvt() ;
-  for ( vit = pEvt -> vertices_begin() ; vit != pEvt -> vertices_end() ; 
-        ++vit ) {
-     HepMC::FourVector pos = (*vit) -> position() ;
-    (*vit) -> set_position( HepMC::FourVector( pos.x() + dpos.x() , 
-                                               pos.y() + dpos.y() , 
-                                               pos.z() + dpos.z() , 
-                                               pos.t() + dpos.t() ) ) ;
-  }
-
-  return StatusCode::SUCCESS ;      
-}
-
diff --git a/Gen/Generators/src/component/BeamSpotSmearVertex.h b/Gen/Generators/src/component/BeamSpotSmearVertex.h
deleted file mode 100755
index d87b37ecd..000000000
--- a/Gen/Generators/src/component/BeamSpotSmearVertex.h
+++ /dev/null
@@ -1,57 +0,0 @@
-// $Id: BeamSpotSmearVertex.h,v 1.7 2010-05-09 17:05:43 gcorti Exp $
-#ifndef GENERATORS_BEAMSPOTSMEARVERTEX_H
-#define GENERATORS_BEAMSPOTSMEARVERTEX_H 1
-
-// Include files
-// from Gaudi
-#include "GaudiAlg/GaudiTool.h"
-#include "GaudiKernel/RndmGenerators.h"
-
-#include "Generators/IVertexSmearingTool.h"
-
-/** @class BeamSpotSmearVertex BeamSpotSmearVertex.h "BeamSpotSmearVertex.h"
- *
- *  VertexSmearingTool to smear vertex according to beam spot parameters.
- *  Concrete implementation of IVertexSmearingTool.
- *
- *  @author Patrick Robbe
- *  @date   2005-08-24
- */
-class BeamSpotSmearVertex : public GaudiTool,
-                            virtual public IVertexSmearingTool {
-public:
-  /// Standard constructor
-  BeamSpotSmearVertex( const std::string& type, const std::string& name,
-                       const IInterface* parent);
-
-  virtual ~BeamSpotSmearVertex( ); ///< Destructor
-
-  /// Initialize function
-  StatusCode initialize( ) override;
-
-  /** Implementation of IVertexSmearingTool::smearVertex.
-   *  Gaussian smearing of spatial position of primary event truncated
-   *  at a given number of sigma.
-   */
-  StatusCode smearVertex( LHCb::HepMCEvent * theEvent ) override;
-
- private:
-  /// Number of sigma above which to cut for x-axis smearing (set by options)
-  double m_xcut   ;
-
-  /// Number of sigma above which to cut for y-axis smearing (set by options)
-  double m_ycut   ;
-
-  /// Number of sigma above which to cut for z-axis smearing (set by options)
-  double m_zcut   ;
-
-  /// Sign of time of interaction as given from position with respect to
-  /// origin
-  int  m_timeSignVsT0 ;
-
-  std::string m_beamParameters ; ///< Location of beam parameters (set by options)
-
-  Rndm::Numbers m_gaussDist ; ///< Gaussian random number generator
-
-};
-#endif // GENERATORS_BEAMSPOTSMEARVERTEX_H
diff --git a/Gen/Generators/src/component/CollidingBeams.cpp b/Gen/Generators/src/component/CollidingBeams.cpp
deleted file mode 100755
index d7e758f61..000000000
--- a/Gen/Generators/src/component/CollidingBeams.cpp
+++ /dev/null
@@ -1,127 +0,0 @@
-// $Id: CollidingBeams.cpp,v 1.5 2007-02-08 17:46:06 gcorti Exp $
-// Include files 
-
-// local
-#include "CollidingBeams.h"
-
-// from Gaudi
-#include "GaudiKernel/IRndmGenSvc.h"
-
-// From Kernel
-#include "GaudiKernel/SystemOfUnits.h"
-
-// From Event
-#include "Event/BeamParameters.h"
-#include "GenEvent/BeamForInitialization.h"
-
-//-----------------------------------------------------------------------------
-// Implementation file for class : CollidingBeams
-//
-// 2005-08-17 : Patrick Robbe
-//-----------------------------------------------------------------------------
-
-// Declaration of the Tool Factory
-
-DECLARE_COMPONENT( CollidingBeams )
-
-
-//=============================================================================
-// Standard constructor, initializes variables
-//=============================================================================
-CollidingBeams::CollidingBeams( const std::string& type,
-                                const std::string& name,
-                                const IInterface* parent )
-  : GaudiTool ( type, name , parent ) {
-    declareInterface< IBeamTool >( this ) ;
-    declareProperty( "BeamParameters" , 
-                     m_beamParameters = LHCb::BeamParametersLocation::Default ) ;
-}
-
-//=============================================================================
-// Destructor 
-//=============================================================================
-CollidingBeams::~CollidingBeams( ) { ; }
-
-//=============================================================================
-// Initialize method
-//=============================================================================
-StatusCode CollidingBeams::initialize( ) {
-  StatusCode sc = GaudiTool::initialize( ) ;
-  if ( sc.isFailure() ) return sc ;
-
-  // Initialize the number generator
-  IRndmGenSvc * randSvc = svc< IRndmGenSvc >( "RndmGenSvc" , true ) ;
-  
-  sc = m_gaussianDist.initialize( randSvc , Rndm::Gauss( 0. , 1. ) )  ;
-  if ( ! sc.isSuccess() ) 
-    return Error( "Could not initialize Gaussian random generator" , sc ) ;
-  release( randSvc ) ;
-
-  return sc ;
-}
-
-//=============================================================================
-// Mean value of the beam momentum
-//=============================================================================
-void CollidingBeams::getMeanBeams( Gaudi::XYZVector & pBeam1 , 
-                                   Gaudi::XYZVector & pBeam2 )
-  const {
-  // Retrieve beam parameters from the static class
-  LHCb::BeamParameters * beam = 
-    BeamForInitialization::getInitialBeamParameters() ;
-  if ( 0 == beam ) 
-    Exception( "No beam parameters in initialization" ) ;
-
-  double p1x, p1y, p1z, p2x, p2y, p2z ;
-  
-  p1x = beam -> energy() * 
-    sin( beam -> horizontalCrossingAngle() +
-         beam -> horizontalBeamlineAngle() ) ;
-  p1y = beam -> energy() * 
-    sin( beam -> verticalCrossingAngle() + 
-         beam -> verticalBeamlineAngle() ) ;
-  p1z = beam -> energy() ;
-  pBeam1.SetXYZ( p1x, p1y, p1z ) ;
-
-  p2x = beam -> energy() * 
-    sin( beam -> horizontalCrossingAngle() - 
-         beam -> horizontalBeamlineAngle() ) ;
-  p2y = beam -> energy() * 
-    sin( beam -> verticalCrossingAngle() - 
-         beam -> verticalBeamlineAngle() ) ;
-  p2z = -beam -> energy() ;
-  pBeam2.SetXYZ( p2x, p2y, p2z ) ;
-}
-
-//=============================================================================
-// Current value of the smeared beams
-//=============================================================================
-void CollidingBeams::getBeams( Gaudi::XYZVector & pBeam1 , 
-                               Gaudi::XYZVector & pBeam2 ) {
-  // Retrieve beam parameters
-  LHCb::BeamParameters * beam = get< LHCb::BeamParameters >( m_beamParameters ) ;
-  if ( 0 == beam ) Exception( "No beam parameters in TES" ) ;
-
-  double p1x, p1y, p1z, p2x, p2y, p2z ;
-  p1x = beam -> energy() * 
-    sin( beam -> horizontalCrossingAngle() + 
-         beam -> horizontalBeamlineAngle() + 
-         m_gaussianDist() * beam -> angleSmear() ) ;
-  p1y = beam -> energy() * 
-    sin( beam -> verticalCrossingAngle() + 
-         beam -> verticalBeamlineAngle() +
-         m_gaussianDist() * beam -> angleSmear() ) ;
-  p1z = beam -> energy() ;
-  pBeam1.SetXYZ( p1x, p1y, p1z ) ;
-
-  p2x = beam -> energy() * 
-    sin( beam -> horizontalCrossingAngle() - 
-         beam -> horizontalBeamlineAngle() + 
-         m_gaussianDist() * beam -> angleSmear() ) ;
-  p2y = beam -> energy() * 
-    sin( beam -> verticalCrossingAngle() - 
-         beam -> verticalBeamlineAngle() +
-         m_gaussianDist() * beam -> angleSmear() ) ;
-  p2z = -beam -> energy() ;
-  pBeam2.SetXYZ( p2x, p2y, p2z ) ;
-}
diff --git a/Gen/Generators/src/component/CollidingBeams.h b/Gen/Generators/src/component/CollidingBeams.h
deleted file mode 100755
index 21e012143..000000000
--- a/Gen/Generators/src/component/CollidingBeams.h
+++ /dev/null
@@ -1,52 +0,0 @@
-// $Id: CollidingBeams.h,v 1.3 2005-12-31 17:32:01 robbep Exp $
-#ifndef GENERATORS_COLLIDINGBEAMS_H
-#define GENERATORS_COLLIDINGBEAMS_H 1
-
-// Include files
-// from Gaudi
-#include "GaudiAlg/GaudiTool.h"
-#include "GaudiKernel/RndmGenerators.h"
-
-#include "Generators/IBeamTool.h"
-
-// Forward declarations
-class IRndmGenSvc ;
-
-/** @class CollidingBeams CollidingBeams.h "CollidingBeams.h"
- *
- *  Tool to compute colliding beams values. Concrete implementation
- *  of a beam tool.
- *
- *  @author Patrick Robbe
- *  @date   2005-08-18
- */
-class CollidingBeams : public GaudiTool, virtual public IBeamTool {
- public:
-  /// Standard constructor
-  CollidingBeams( const std::string& type, const std::string& name,
-                  const IInterface* parent ) ;
-
-  virtual ~CollidingBeams( ); ///< Destructor
-
-  /// Initialize method
-  StatusCode initialize( ) override;
-
-  /** Implements IBeamTool::getMeanBeams
-   */
-  void getMeanBeams( Gaudi::XYZVector & pBeam1 ,
-                     Gaudi::XYZVector & pBeam2 ) const override;
-
-  /** Implements IBeamTool::getBeams
-   *  Compute beam 3-momentum taking into account the horizontal and vertical
-   *  beam angles (given by job options). These angles are Gaussian-smeared
-   *  with an angular smearing equal to (emittance/beta*)^1/2.
-   */
-  void getBeams( Gaudi::XYZVector & pBeam1 ,
-                 Gaudi::XYZVector & pBeam2 ) override;
-
- private:
-  std::string m_beamParameters ; ///< Location of beam parameters (set by options)
-
-  Rndm::Numbers m_gaussianDist ; ///< Gaussian random number generator
-};
-#endif // GENERATORS_COLLIDINGBEAMS_H
diff --git a/Gen/Generators/src/component/EvtGenTool.cpp b/Gen/Generators/src/component/EvtGenTool.cpp
deleted file mode 100755
index 22e39dcd2..000000000
--- a/Gen/Generators/src/component/EvtGenTool.cpp
+++ /dev/null
@@ -1,76 +0,0 @@
-// $Id: EvtGenTool.cpp,v 1.23 2010-05-05 19:38:36 robbep Exp $
-// Header file
-#include "EvtGenTool.h"
-
-
-#include<iostream>
-
-// from Gaudi
-#include "GaudiKernel/System.h"
-#include "GaudiKernel/GaudiException.h"
-
-// from EvtGen
-#include "EvtGen/EvtGen.hh"
-#include "EvtGenBase/EvtParticleFactory.hh"
-#include "EvtGenBase/EvtDecayTable.hh"
-#include "EvtGenBase/EvtDecayBase.hh"
-
-#include "Generators/StreamForGenerator.h"
-
-//-----------------------------------------------------------------------------
-// Implementation file for class : EvtGenTool
-//
-// 2003-10-15 : Alex Shires
-//-----------------------------------------------------------------------------
-// Declaration of the Tool Factory
-
-DECLARE_COMPONENT( EvtGenTool )
-
-//=============================================================================
-// Standard constructor, initializes variables
-//=============================================================================
-EvtGenTool::EvtGenTool( const std::string& type,
-                          const std::string& name,
-                          const IInterface* parent )
-  : GaudiTool ( type, name , parent ),
-    m_gen(0),
-    m_init(false) 
-{
-    declareInterface<IEvtGenTool>(this);
-}
-//=============================================================================
-// Destructor
-//=============================================================================
-EvtGenTool::~EvtGenTool( ) { ; }
-//=============================================================================
-// Initialize method
-//=============================================================================
-StatusCode EvtGenTool::initialize( ) {
-  StatusCode sc = GaudiTool::initialize( ) ;
-  if ( sc.isFailure() ) return sc ;
-
-  //MsgStream * msg = new MsgStream( msgSvc() , name() ) ;
-  //StreamForGenerator::getStream() = msg ;
-
-  debug() << "EvtGenTool initialized" << endmsg ;
-  
-  return StatusCode::SUCCESS ;
-}
-
-//=============================================================================
-// Finalize method
-//=============================================================================
-StatusCode EvtGenTool::finalize() {
-  if ( 0 != m_gen ) { 
-    delete m_gen ;
-    m_gen = 0 ;
-  }
-
-  m_init = false ;
-
-  if ( ! msgLevel( MSG::DEBUG ) ) {
-      debug() << "EvtGenTool finalized" << endmsg ;
-  }
-  
-  return GaudiTool::finalize( ) ;
-}
diff --git a/Gen/Generators/src/component/EvtGenTool.h b/Gen/Generators/src/component/EvtGenTool.h
deleted file mode 100755
index 185a1aef0..000000000
--- a/Gen/Generators/src/component/EvtGenTool.h
+++ /dev/null
@@ -1,77 +0,0 @@
-// $Id: EvtGenTool.h,v 1.9 2009-03-16 16:53:26 robbep Exp $
-#ifndef GENERATORS_EVTGENTOOL_H
-#define GENERATORS_EVTGENTOOL_H 1
-
-// Avoid contamination with WINDOWS symbols
-#ifdef WIN32
-#define NOATOM
-#define NOGDI
-#define NOGDICAPMASKS
-#define NOMETAFILE
-#define NOMINMAX
-#define NOMSG
-#define NOOPENFILE
-#define NORASTEROPS
-#define NOSCROLL
-#define NOSOUND
-#define NOSYSMETRICS
-#define NOTEXTMETRIC
-#define NOWH
-#define NOCOMM
-#define NOKANJI
-#define NOCRYPT
-#define NOMCX
-#endif
-
-// Include files
-
-// from Gaudi
-#include "GaudiAlg/GaudiTool.h"
-//interface
-#include "IEvtGenTool.h"
-
-// from EvtGen
-#include "EvtGen/EvtGen.hh"
-
-/** @class EvtGenTool EvtGenTool.h "EvtGenTool.h"
- *
- *  Tool to interface to EvtGen generator.
- *
- *  @author Alex Shires, Patrick Robbe
- *  @date   2011-10-28
- */
-class EvtGenTool : public GaudiTool, virtual public IEvtGenTool {
-public:
-  /// Standard constructor
-  EvtGenTool( const std::string& type, const std::string& name,
-              const IInterface* parent);
-
-  virtual ~EvtGenTool( ) ; ///< Destructor
-
-  /** Initialize method.
-   *  */
-  StatusCode initialize() override;
-
-  /// Finalize method
-  StatusCode finalize() override;
-
-  /// Get the pointer to the EvtGen instance
-  EvtGen* getEvtGen( ) override { return m_gen ; }
-
-  /// Get the pointer to the EvtGen instance
-  void setEvtGen( EvtGen * evtgenptr ) override {  m_gen = evtgenptr ; m_init = true ; }
-
-  /// return the initalised state of EvtGen
-  bool isInit() override { return m_init ; }
-
-private:
-
-    EvtGen * m_gen ; ///< EvtGen engine
-
-    bool m_init ; ///< Initialisation flag
-
-
-};
-
-
-#endif // GENERATORS_EVTGENTOOL_H
diff --git a/Gen/Generators/src/component/FixedLuminosity.cpp b/Gen/Generators/src/component/FixedLuminosity.cpp
deleted file mode 100755
index 735ab94a7..000000000
--- a/Gen/Generators/src/component/FixedLuminosity.cpp
+++ /dev/null
@@ -1,116 +0,0 @@
-// Include files
-
-// local
-#include "FixedLuminosity.h"
-
-// from Gaudi
-#include "GaudiKernel/IRndmGenSvc.h"
-#include "GaudiKernel/SystemOfUnits.h"
-
-// From Event
-#include "Event/BeamParameters.h"
-#include "Event/GenFSR.h"
-#include "Event/GenCountersFSR.h"
-
-// From Generators
-#include "Generators/GenCounters.h"
-#include "Generators/ICounterLogFile.h"
-
-//-----------------------------------------------------------------------------
-// Implementation file for class : FixedLuminosity
-//
-// 2005-08-17 : Patrick Robbe
-//-----------------------------------------------------------------------------
-
-// Declaration of the Tool Factory
-
-DECLARE_COMPONENT( FixedLuminosity )
-
-
-//=============================================================================
-// Standard constructor, initializes variables
-//=============================================================================
-FixedLuminosity::FixedLuminosity( const std::string& type,
-                                  const std::string& name,
-                                  const IInterface* parent )
-  : GaudiTool ( type, name , parent ) ,
-    m_xmlLogTool ( 0 ) ,
-    m_numberOfZeroInteraction( 0 ) ,
-    m_nEvents( 0 ) ,
-    m_randSvc( 0 ) {
-    declareInterface< IPileUpTool >( this ) ;
-    declareProperty( "BeamParameters" ,
-                     m_beamParameters = LHCb::BeamParametersLocation::Default ) ;
-    declareProperty ( "GenFSRLocation", m_FSRName =
-                      LHCb::GenFSRLocation::Default);
-}
-
-//=============================================================================
-// Destructor
-//=============================================================================
-FixedLuminosity::~FixedLuminosity( ) { ; }
-
-//=============================================================================
-// Initialize method
-//=============================================================================
-StatusCode FixedLuminosity::initialize( ) {
-  StatusCode sc = GaudiTool::initialize( ) ;
-  if ( sc.isFailure() ) return sc ;
-
-  // Initialize the number generator
-  m_randSvc = svc< IRndmGenSvc >( "RndmGenSvc" , true ) ;
-
-  //  XMl log file
-  m_xmlLogTool = tool< ICounterLogFile >( "XmlCounterLogFile" ) ;
-
-  return sc ;
-}
-
-//=============================================================================
-// Compute the number of pile up to generate according to beam parameters
-//=============================================================================
-unsigned int FixedLuminosity::numberOfPileUp( ) {
-  LHCb::BeamParameters * beam = get< LHCb::BeamParameters >( m_beamParameters ) ;
-  if ( 0 == beam ) Exception( "No beam parameters registered" ) ;
-
-  LHCb::GenFSR* genFSR = nullptr;
-  if(m_FSRName != ""){
-    IDataProviderSvc* fileRecordSvc = svc<IDataProviderSvc>("FileRecordDataSvc", true);
-    genFSR = getIfExists<LHCb::GenFSR>(fileRecordSvc, m_FSRName, false);
-    if(!genFSR) warning() << "Could not find GenFSR at " << m_FSRName << endmsg;
-  }
-  int key = 0;
-
-  unsigned int result = 0 ;
-  while ( 0 == result ) {
-    m_nEvents++ ;
-    key = LHCb::GenCountersFSR::AllEvt;
-    if(genFSR) genFSR->incrementGenCounter(key,1);
-    Rndm::Numbers poissonGenerator( m_randSvc , Rndm::Poisson( beam -> nu() ) ) ;
-    result = (unsigned int) poissonGenerator() ;
-    if ( 0 == result ) {
-      m_numberOfZeroInteraction++ ;
-      key =LHCb::GenCountersFSR::ZeroInt;
-      if(genFSR) genFSR->incrementGenCounter(key, 1);
-    }
-  }
-  return result ;
-}
-
-//=============================================================================
-// Print the specific pile up counters
-//=============================================================================
-void FixedLuminosity::printPileUpCounters( ) {
-  using namespace GenCounters ;
-  printCounter( m_xmlLogTool , "all events (including empty events)", m_nEvents ) ;
-  printCounter( m_xmlLogTool , "events with 0 interaction" ,
-                m_numberOfZeroInteraction ) ;
-}
-
-//=============================================================================
-// Finalize method
-//=============================================================================
-StatusCode FixedLuminosity::finalize( ) {
-  release( m_randSvc ) ;
-  return GaudiTool::finalize( ) ;
-}
diff --git a/Gen/Generators/src/component/FixedLuminosity.h b/Gen/Generators/src/component/FixedLuminosity.h
deleted file mode 100755
index 65f083d3b..000000000
--- a/Gen/Generators/src/component/FixedLuminosity.h
+++ /dev/null
@@ -1,65 +0,0 @@
-// $Id: FixedLuminosity.h,v 1.4 2009-04-07 16:11:21 gcorti Exp $
-#ifndef GENERATORS_FIXEDLUMINOSITY_H
-#define GENERATORS_FIXEDLUMINOSITY_H 1
-
-// Include files
-// from Gaudi
-#include "GaudiAlg/GaudiTool.h"
-#include "GaudiKernel/RndmGenerators.h"
-
-#include "Generators/IPileUpTool.h"
-
-// forward declaration
-class IRndmGenSvc ;
-class ICounterLogFile ;
-
-/** @class FixedLuminosity FixedLuminosity.h "FixedLuminosity.h"
- *
- *  Tool to compute variable number of pile up events
- *  depending on beam parameters
- *
- *  @author Patrick Robbe
- *  @date   2005-08-17
- */
-class FixedLuminosity : public GaudiTool, virtual public IPileUpTool {
-public:
-  /// Standard constructor
-  FixedLuminosity( const std::string& type, const std::string& name,
-                   const IInterface* parent) ;
-
-  virtual ~FixedLuminosity( ); ///< Destructor
-
-  /// Initialize method
-  StatusCode initialize( ) override;
-
-  /// Finalize method
-  StatusCode finalize( ) override;
-
-  /** Implements IPileUpTool::numberOfPileUp
-   *  Returns the number of pile-up interactions in one event. It follows
-   *  a Poisson distribution with
-   *  mean = Luminosity * cross_section / crossing_rate.
-   *  The fixed luminosity is returned in the GenHeader.
-   */
-  unsigned int numberOfPileUp( ) override;
-
-  /// Implements IPileUpTool::printPileUpCounters
-  void printPileUpCounters( ) override;
-
-protected:
-
-private:
-  /// Location where to store FSR counters (set by options)
-  std::string  m_FSRName;
-
-  ICounterLogFile * m_xmlLogTool ; ///< XML File for generator counters
-
-  std::string m_beamParameters ; ///< Location of beam parameters (set by options)
-
-  int    m_numberOfZeroInteraction ; ///< Counter of empty events
-
-  int    m_nEvents ; ///< Counter of events (including empty events)
-
-  IRndmGenSvc * m_randSvc ; ///< Pointer to random number generator service
-};
-#endif // GENERATORS_FIXEDLUMINOSITY_H
diff --git a/Gen/Generators/src/component/FixedLuminosityForRareProcess.cpp b/Gen/Generators/src/component/FixedLuminosityForRareProcess.cpp
deleted file mode 100755
index 01d8b009b..000000000
--- a/Gen/Generators/src/component/FixedLuminosityForRareProcess.cpp
+++ /dev/null
@@ -1,110 +0,0 @@
-// $Id: FixedLuminosityForRareProcess.cpp,v 1.3 2009-04-07 16:11:21 gcorti Exp $
-// Include files
-
-// local
-#include "FixedLuminosityForRareProcess.h"
-
-// from Gaudi
-#include "GaudiKernel/IRndmGenSvc.h"
-#include "GaudiKernel/SystemOfUnits.h"
-
-// From Event
-#include "Event/BeamParameters.h"
-#include "Event/GenFSR.h"
-#include "Event/GenCountersFSR.h"
-
-// From Generators
-#include "Generators/GenCounters.h"
-#include "Generators/ICounterLogFile.h"
-
-//-----------------------------------------------------------------------------
-// Implementation file for class : FixedLuminosityForRareProcess
-//
-// 2005-08-17 : Patrick Robbe
-//-----------------------------------------------------------------------------
-
-// Declaration of the Tool Factory
-
-DECLARE_COMPONENT( FixedLuminosityForRareProcess )
-
-
-//=============================================================================
-// Standard constructor, initializes variables
-//=============================================================================
-FixedLuminosityForRareProcess::FixedLuminosityForRareProcess( const std::string& type,
-                                  const std::string& name,
-                                  const IInterface* parent )
-  : GaudiTool ( type, name , parent ) ,
-    m_xmlLogTool( 0 ) ,
-    m_nEvents( 0 ) ,
-    m_randSvc( 0 ) {
-    declareInterface< IPileUpTool >( this ) ;
-    declareProperty( "BeamParameters" ,
-                     m_beamParameters = LHCb::BeamParametersLocation::Default ) ;
-    declareProperty ( "GenFSRLocation", m_FSRName =
-                      LHCb::GenFSRLocation::Default);
-}
-
-//=============================================================================
-// Destructor
-//=============================================================================
-FixedLuminosityForRareProcess::~FixedLuminosityForRareProcess( ) { ; }
-
-//=============================================================================
-// Initialize method
-//=============================================================================
-StatusCode FixedLuminosityForRareProcess::initialize( ) {
-  StatusCode sc = GaudiTool::initialize( ) ;
-  if ( sc.isFailure() ) return sc ;
-
-  // Initialize the number generator
-  m_randSvc = svc< IRndmGenSvc >( "RndmGenSvc" , true ) ;
-
-  // XML file for generator statistics
-  m_xmlLogTool = tool< ICounterLogFile >( "XmlCounterLogFile" ) ;
-
-  info() << "Poisson distribution with fixed luminosity. " << endmsg ;
-
-  return sc ;
-}
-
-//=============================================================================
-// Compute the number of pile up to generate according to beam parameters
-//=============================================================================
-unsigned int FixedLuminosityForRareProcess::numberOfPileUp( ) {
-  LHCb::BeamParameters * beam = get< LHCb::BeamParameters >( m_beamParameters ) ;
-  if ( 0 == beam ) Exception( "No beam parameters registered" ) ;
-
-  LHCb::GenFSR* genFSR = nullptr;
-  if(m_FSRName != ""){
-    IDataProviderSvc* fileRecordSvc = svc<IDataProviderSvc>("FileRecordDataSvc", true);
-    genFSR = getIfExists<LHCb::GenFSR>(fileRecordSvc, m_FSRName, false);
-    if(!genFSR) warning() << "Could not find GenFSR at " << m_FSRName << endmsg;
-  }
-  int key = 0;
-
-  unsigned int result = 0 ;
-  m_nEvents++ ;
-  key = LHCb::GenCountersFSR::AllEvt;
-  if(genFSR) genFSR->incrementGenCounter(key,1);
-
-  Rndm::Numbers poissonGenerator( m_randSvc , Rndm::Poisson( beam -> nu() ) ) ;
-  result = (unsigned int) ( poissonGenerator() + 1.0 ) ;
-  return result ;
-}
-
-//=============================================================================
-// Print the specific pile up counters
-//=============================================================================
-void FixedLuminosityForRareProcess::printPileUpCounters( ) {
-  using namespace GenCounters ;
-  printCounter( m_xmlLogTool , "all events (including empty events)", m_nEvents ) ;
-}
-
-//=============================================================================
-// Finalize method
-//=============================================================================
-StatusCode FixedLuminosityForRareProcess::finalize( ) {
-  release( m_randSvc ) ;
-  return GaudiTool::finalize( ) ;
-}
diff --git a/Gen/Generators/src/component/FixedLuminosityForRareProcess.h b/Gen/Generators/src/component/FixedLuminosityForRareProcess.h
deleted file mode 100755
index fa249247c..000000000
--- a/Gen/Generators/src/component/FixedLuminosityForRareProcess.h
+++ /dev/null
@@ -1,63 +0,0 @@
-// $Id: FixedLuminosityForRareProcess.h,v 1.2 2009-04-07 16:11:21 gcorti Exp $
-#ifndef GENERATORS_FIXEDLUMINOSITYFORRAREPROCESS_H
-#define GENERATORS_FIXEDLUMINOSITYFORRAREPROCESS_H 1
-
-// Include files
-// from Gaudi
-#include "GaudiAlg/GaudiTool.h"
-#include "GaudiKernel/RndmGenerators.h"
-
-#include "Generators/IPileUpTool.h"
-
-// forward declaration
-class IRndmGenSvc ;
-class ICounterLogFile ;
-
-/** @class FixedLuminosityForRareProcess FixedLuminosityForRareProcess.h "FixedLuminosityForRareProcess.h"
- *
- *  Tool to compute variable number of pile up events
- *  depending on beam parameters
- *
- *  @author Patrick Robbe
- *  @date   2005-08-17
- */
-class FixedLuminosityForRareProcess : public GaudiTool, virtual public IPileUpTool {
-public:
-  /// Standard constructor
-  FixedLuminosityForRareProcess( const std::string& type, const std::string& name,
-                   const IInterface* parent) ;
-
-  virtual ~FixedLuminosityForRareProcess( ); ///< Destructor
-
-  /// Initialize method
-  StatusCode initialize( ) override;
-
-  /// Finalize method
-  StatusCode finalize( ) override;
-
-  /** Implements IPileUpTool::numberOfPileUp
-   *  Returns the number of pile-up interactions in one event. It follows
-   *  a Poisson distribution with
-   *  mean = Luminosity * cross_section / crossing_rate.
-   *  The fixed luminosity is returned as the currentLuminosity.
-   */
-  unsigned int numberOfPileUp( ) override;
-
-  /// Implements IPileUpTool::printPileUpCounters
-  void printPileUpCounters( ) override;
-
-protected:
-
-private:
-  ICounterLogFile * m_xmlLogTool ; ///< XML File for generator statistics
-
-  std::string m_beamParameters ; ///< Location of beam parameters (set by options)
-
-  /// Location where to store FSR counters (set by options)
-  std::string  m_FSRName;
-
-  int    m_nEvents ; ///< Counter of events (including empty events)
-
-  IRndmGenSvc * m_randSvc ; ///< Pointer to random number generator service
-};
-#endif // GENERATORS_FIXEDLUMINOSITYFORRAREPROCESS_H
diff --git a/Gen/Generators/src/component/FixedLuminosityForSpillOver.cpp b/Gen/Generators/src/component/FixedLuminosityForSpillOver.cpp
deleted file mode 100644
index 34a0b2b70..000000000
--- a/Gen/Generators/src/component/FixedLuminosityForSpillOver.cpp
+++ /dev/null
@@ -1,119 +0,0 @@
-// $Id: FixedLuminosityForSpillOver.cpp,v 1.2 2009-04-07 16:11:21 gcorti Exp $
-// Include files
-
-// local
-#include "FixedLuminosityForSpillOver.h"
-
-// from Gaudi
-#include "GaudiKernel/IRndmGenSvc.h"
-#include "GaudiKernel/SystemOfUnits.h"
-
-// From Event
-#include "Event/BeamParameters.h"
-#include "Event/GenFSR.h"
-#include "Event/GenCountersFSR.h"
-
-// From Generators
-#include "Generators/GenCounters.h"
-#include "Generators/ICounterLogFile.h"
-
-//-----------------------------------------------------------------------------
-// Implementation file for class : FixedLuminosityForSpillOver
-//
-// 2005-08-17 : Patrick Robbe
-//-----------------------------------------------------------------------------
-
-// Declaration of the Tool Factory
-
-DECLARE_COMPONENT( FixedLuminosityForSpillOver )
-
-
-//=============================================================================
-// Standard constructor, initializes variables
-//=============================================================================
-FixedLuminosityForSpillOver::FixedLuminosityForSpillOver( const std::string& type,
-							  const std::string& name,
-							  const IInterface* parent )
-  : GaudiTool ( type, name , parent ) ,
-    m_xmlLogTool( 0 ) ,
-    m_numberOfZeroInteraction( 0 ) ,
-    m_nEvents( 0 ) ,
-    m_randSvc( 0 ) {
-    declareInterface< IPileUpTool >( this ) ;
-    declareProperty( "BeamParameters" ,
-                     m_beamParameters = LHCb::BeamParametersLocation::Default ) ;
-    declareProperty ( "GenFSRLocation", m_FSRName =
-                      LHCb::GenFSRLocation::Default);
-}
-
-//=============================================================================
-// Destructor
-//=============================================================================
-FixedLuminosityForSpillOver::~FixedLuminosityForSpillOver( ) { ; }
-
-//=============================================================================
-// Initialize method
-//=============================================================================
-StatusCode FixedLuminosityForSpillOver::initialize( ) {
-  StatusCode sc = GaudiTool::initialize( ) ;
-  if ( sc.isFailure() ) return sc ;
-
-  // Initialize the number generator
-  m_randSvc = svc< IRndmGenSvc >( "RndmGenSvc" , true ) ;
-
-  // Log file XML
-  m_xmlLogTool = tool< ICounterLogFile >( "XmlCounterLogFile" ) ;
-
-  info() << "Poisson distribution with fixed luminosity. " << endmsg ;
-
-  return sc ;
-}
-
-//=============================================================================
-// Compute the number of pile up to generate according to beam parameters
-//=============================================================================
-unsigned int FixedLuminosityForSpillOver::numberOfPileUp( ) {
-  LHCb::BeamParameters * beam = get< LHCb::BeamParameters >( m_beamParameters ) ;
-  if ( 0 == beam ) Exception( "No beam parameters registered" ) ;
-
-  LHCb::GenFSR* genFSR = nullptr;
-  if(m_FSRName != ""){
-    IDataProviderSvc* fileRecordSvc = svc<IDataProviderSvc>("FileRecordDataSvc", true);
-    genFSR = getIfExists<LHCb::GenFSR>(fileRecordSvc, m_FSRName, false);
-    if(!genFSR) warning() << "Could not find GenFSR at " << m_FSRName << endmsg;
-  }
-  int key = 0;
-
-  unsigned int result = 0 ;
-  m_nEvents++ ;
-  key = LHCb::GenCountersFSR::AllEvt;
-  if(genFSR) genFSR->incrementGenCounter(key,1);
-
-  Rndm::Numbers poissonGenerator( m_randSvc , Rndm::Poisson( beam -> nu() ) ) ;
-  result = (unsigned int) poissonGenerator() ;
-  if ( 0 == result ) {
-    m_numberOfZeroInteraction++ ;
-    key =LHCb::GenCountersFSR::ZeroInt;
-    if(genFSR) genFSR->incrementGenCounter(key, 1);
-  }
-
-  return result ;
-}
-
-//=============================================================================
-// Print the specific pile up counters
-//=============================================================================
-void FixedLuminosityForSpillOver::printPileUpCounters( ) {
-  using namespace GenCounters ;
-  printCounter( m_xmlLogTool , "all events (including empty events)", m_nEvents ) ;
-  printCounter( m_xmlLogTool , "events with 0 interaction" ,
-                m_numberOfZeroInteraction ) ;
-}
-
-//=============================================================================
-// Finalize method
-//=============================================================================
-StatusCode FixedLuminosityForSpillOver::finalize( ) {
-  release( m_randSvc ) ;
-  return GaudiTool::finalize( ) ;
-}
diff --git a/Gen/Generators/src/component/FixedLuminosityForSpillOver.h b/Gen/Generators/src/component/FixedLuminosityForSpillOver.h
deleted file mode 100644
index 06714ff13..000000000
--- a/Gen/Generators/src/component/FixedLuminosityForSpillOver.h
+++ /dev/null
@@ -1,67 +0,0 @@
-// $Id: FixedLuminosityForSpillOver.h,v 1.2 2009-04-07 16:11:21 gcorti Exp $
-#ifndef GENERATORS_FIXEDLUMINOSITYFORSPILLOVER_H
-#define GENERATORS_FIXEDLUMINOSITYFORSPILLOVER_H 1
-
-// Include files
-// from Gaudi
-#include "GaudiAlg/GaudiTool.h"
-#include "GaudiKernel/RndmGenerators.h"
-
-#include "Generators/IPileUpTool.h"
-
-// forward declaration
-class IRndmGenSvc ;
-class ICounterLogFile ;
-
-/** @class FixedLuminosityForSpillOver FixedLuminosityForSpillOver.h "FixedLuminosityForSpillOver.h"
- *
- *  Tool to compute variable number of pile up events
- *  depending on beam parameters.
- *  To be used for spill over generation because it accepts events
- *  with 0 interaction
- *
- *  @author Patrick Robbe
- *  @date   2009-03-30
- */
-class FixedLuminosityForSpillOver : public GaudiTool, virtual public IPileUpTool {
-public:
-  /// Standard constructor
-  FixedLuminosityForSpillOver( const std::string& type, const std::string& name,
-		               const IInterface* parent) ;
-
-  virtual ~FixedLuminosityForSpillOver( ); ///< Destructor
-
-  /// Initialize method
-  StatusCode initialize( ) override;
-
-  /// Finalize method
-  StatusCode finalize( ) override;
-
-  /** Implements IPileUpTool::numberOfPileUp
-   *  Returns the number of pile-up interactions in one event. It follows
-   *  a Poisson distribution with
-   *  mean = Luminosity * cross_section / crossing_rate.
-   *  The fixed luminosity is returned as the currentLuminosity.
-   */
-  unsigned int numberOfPileUp( ) override;
-
-  /// Implements IPileUpTool::printPileUpCounters
-  void printPileUpCounters( ) override;
-
-protected:
-
-private:
-  /// Location where to store FSR counters (set by options)
-  std::string  m_FSRName;
-
-  ICounterLogFile * m_xmlLogTool ; ///< Log file in XML
-
-  std::string m_beamParameters ; ///< Location of beam parameters (set by options)
-
-  int    m_numberOfZeroInteraction ; ///< Counter of empty events
-
-  int    m_nEvents ; ///< Counter of events (including empty events)
-
-  IRndmGenSvc * m_randSvc ; ///< Pointer to random number generator service
-};
-#endif // GENERATORS_FIXEDLUMINOSITYFORSPILLOVER_H
diff --git a/Gen/Generators/src/component/FixedNInteractions.cpp b/Gen/Generators/src/component/FixedNInteractions.cpp
deleted file mode 100755
index 14bc0b4e5..000000000
--- a/Gen/Generators/src/component/FixedNInteractions.cpp
+++ /dev/null
@@ -1,65 +0,0 @@
-// $Id: FixedNInteractions.cpp,v 1.5 2009-04-07 16:11:21 gcorti Exp $
-// Include files 
-
-// local
-#include "FixedNInteractions.h"
-
-// from Gaudi
-#include "GaudiKernel/SystemOfUnits.h"
-
-// from Event 
-#include "Event/GenHeader.h"
-
-//-----------------------------------------------------------------------------
-// Implementation file for class : FixedNInteractions
-//
-// 2005-08-17 : Patrick Robbe
-//-----------------------------------------------------------------------------
-
-// Declaration of the Tool Factory
-
-DECLARE_COMPONENT( FixedNInteractions )
-
-
-//=============================================================================
-// Standard constructor, initializes variables
-//=============================================================================
-FixedNInteractions::FixedNInteractions( const std::string& type,
-                                        const std::string& name,
-                                        const IInterface* parent )
-  : GaudiTool ( type, name , parent ) {
-    declareInterface< IPileUpTool >( this ) ;
-    declareProperty ( "NInteractions" , m_nInteractions = 1 ) ;
-}
-
-//=============================================================================
-// Destructor 
-//=============================================================================
-FixedNInteractions::~FixedNInteractions( ) { }
-
-//=============================================================================
-// Initialize method
-//=============================================================================
-StatusCode FixedNInteractions::initialize( ) {
-  StatusCode sc = GaudiTool::initialize( ) ;
-  if ( sc.isFailure() ) return sc ;
-
-  if ( 1 == m_nInteractions ) 
-    info() << "Single Interaction Mode" << endmsg ;
-  else info() << "Fixed Number of Interactions per Event = : "
-              << m_nInteractions << endmsg ;
-  return sc ;
-}
-
-//=============================================================================
-// Compute the number of pile up to generate according to beam parameters
-//=============================================================================
-unsigned int FixedNInteractions::numberOfPileUp( ) {
-  return m_nInteractions ;
-}
-
-//=============================================================================
-// Print the specific pile up counters
-//=============================================================================
-void FixedNInteractions::printPileUpCounters( ) { }
-
diff --git a/Gen/Generators/src/component/FixedNInteractions.h b/Gen/Generators/src/component/FixedNInteractions.h
deleted file mode 100755
index 20cf8aadb..000000000
--- a/Gen/Generators/src/component/FixedNInteractions.h
+++ /dev/null
@@ -1,44 +0,0 @@
-// $Id: FixedNInteractions.h,v 1.4 2009-04-07 16:11:21 gcorti Exp $
-#ifndef GENERATORS_FIXEDNINTERACTIONS_H
-#define GENERATORS_FIXEDNINTERACTIONS_H 1
-
-// Include files
-// from Gaudi
-#include "GaudiAlg/GaudiTool.h"
-
-#include "Generators/IPileUpTool.h"
-
-/** @class FixedNInteractions FixedNInteractions.h "FixedNInteractions.h"
- *
- *  Tool to generate fixed number of pile-up interactions. Concrete
- *  implementation of IPileUpTool.
- *
- *  @author Patrick Robbe
- *  @date   2005-08-17
- */
-class FixedNInteractions : public GaudiTool, virtual public IPileUpTool {
- public:
-  /// Standard constructor
-  FixedNInteractions( const std::string& type,
-                      const std::string& name,
-                      const IInterface* parent);
-
-  virtual ~FixedNInteractions( ); ///< Destructor
-
-  /// Initialize method
-  StatusCode initialize( ) override;
-
-  /** Returns a constant number of pile-up interactions.
-   *  Implementation of IPileUpTool::numberOfPileUp.
-   *  Returns a luminosity equal to 0.
-   */
-  unsigned int numberOfPileUp( ) override;
-
-  /// Implementation of IPileUpTool::printPileUpCounters
-  void printPileUpCounters( ) override;
-
- private:
-  /// Number of interactions to generate (set by job options)
-  int m_nInteractions ;
-};
-#endif // GENERATORS_FIXEDNINTERACTIONS_H
diff --git a/Gen/Generators/src/component/FixedTarget.cpp b/Gen/Generators/src/component/FixedTarget.cpp
deleted file mode 100755
index 1eec42990..000000000
--- a/Gen/Generators/src/component/FixedTarget.cpp
+++ /dev/null
@@ -1,101 +0,0 @@
-// $Id: FixedTarget.cpp,v 1.4 2007-02-08 17:46:06 gcorti Exp $
-// Include files 
-
-// local
-#include "FixedTarget.h"
-
-// from Gaudi
-#include "GaudiKernel/IRndmGenSvc.h"
-#include "GaudiKernel/SystemOfUnits.h"
-
-// from Event
-#include "Event/BeamParameters.h"
-#include "GenEvent/BeamForInitialization.h"
-
-//-----------------------------------------------------------------------------
-// Implementation file for class : FixedTarget
-//
-// 2005-08-17 : Patrick Robbe
-//-----------------------------------------------------------------------------
-
-// Declaration of the Tool Factory
-
-DECLARE_COMPONENT( FixedTarget )
-
-
-//=============================================================================
-// Standard constructor, initializes variables
-//=============================================================================
-FixedTarget::FixedTarget( const std::string& type, const std::string& name,
-                          const IInterface* parent )
-  : GaudiTool ( type, name , parent ) {
-    declareInterface< IBeamTool >( this ) ;
-    declareProperty( "BeamParameters" , 
-                     m_beamParameters = LHCb::BeamParametersLocation::Default ) ;
-}
-
-//=============================================================================
-// Destructor 
-//=============================================================================
-FixedTarget::~FixedTarget( ) { ; }
-
-//=============================================================================
-// Initialize method
-//=============================================================================
-StatusCode FixedTarget::initialize( ) {
-  StatusCode sc = GaudiTool::initialize( ) ;
-  if ( sc.isFailure() ) return sc ;
-
-  // Initialize the number generator
-  IRndmGenSvc * randSvc = svc< IRndmGenSvc >( "RndmGenSvc" , true ) ;
-  
-  sc = m_gaussianDist.initialize( randSvc , Rndm::Gauss( 0. , 1. ) )  ;
-  if ( ! sc.isSuccess() ) 
-    return Error( "Could not initialize Gaussian random generator" , sc ) ;
-  release( randSvc ) ;
-
-  info() << "Collision with fixed target" << endmsg ;
-
-  return sc ;
-}
-
-//=============================================================================
-// Mean value of the beam momentum
-//=============================================================================
-void FixedTarget::getMeanBeams( Gaudi::XYZVector & pBeam1 , 
-                                Gaudi::XYZVector & pBeam2 )
-  const {
-  // Retrieve beam parameters from the static class
-  LHCb::BeamParameters * beam = 
-    BeamForInitialization::getInitialBeamParameters() ;
-  if ( 0 == beam ) 
-    Exception( "No beam parameters for initialization" ) ;
-
-  double p1x, p1y, p1z ;
-  p1x = beam -> energy() * sin( beam -> horizontalCrossingAngle() ) ;
-  p1y = beam -> energy() * sin( beam -> verticalCrossingAngle()   ) ;
-  p1z = beam -> energy() ;
-  pBeam1.SetXYZ( p1x, p1y, p1z ) ;
-
-  pBeam2.SetXYZ( 0., 0., 0. ) ;
-}
-
-//=============================================================================
-// Current value of the smeared beams
-//=============================================================================
-void FixedTarget::getBeams( Gaudi::XYZVector & pBeam1 , 
-                            Gaudi::XYZVector & pBeam2 ) {
-  // Retrieve beam parameters
-  LHCb::BeamParameters * beam = get< LHCb::BeamParameters >( m_beamParameters ) ;
-  if ( 0 == beam ) Exception( "No beam parameters in TES" ) ;
-
-  double p1x, p1y, p1z ;
-  p1x = beam -> energy() * sin( beam -> horizontalCrossingAngle() + 
-                                m_gaussianDist() * beam -> angleSmear() ) ;
-  p1y = beam -> energy() * sin( beam -> verticalCrossingAngle() + 
-                                m_gaussianDist() * beam -> angleSmear() ) ;
-  p1z = beam -> energy() ;
-  pBeam1.SetXYZ( p1x, p1y, p1z ) ;
-  
-  pBeam2.SetXYZ( 0., 0., 0. ) ;
-}
diff --git a/Gen/Generators/src/component/FixedTarget.h b/Gen/Generators/src/component/FixedTarget.h
deleted file mode 100755
index aa92a7cfa..000000000
--- a/Gen/Generators/src/component/FixedTarget.h
+++ /dev/null
@@ -1,47 +0,0 @@
-// $Id: FixedTarget.h,v 1.3 2005-12-31 17:32:01 robbep Exp $
-#ifndef GENERATORS_COLLIDINGBEAMS_H
-#define GENERATORS_COLLIDINGBEAMS_H 1
-
-// Include files
-// from Gaudi
-#include "GaudiAlg/GaudiTool.h"
-#include "GaudiKernel/RndmGenerators.h"
-
-#include "Generators/IBeamTool.h"
-
-// Forward declarations
-class IRndmGenSvc ;
-
-/** @class FixedTarget FixedTarget.h "FixedTarget.h"
- *
- *  Tool to compute beam values with only one beam colliding to a fixed
- *  target. Concrete implementation of a IBeamTool.
- *
- *  @author Patrick Robbe
- *  @date   2005-08-18
- */
-class FixedTarget : public GaudiTool, virtual public IBeamTool {
- public:
-  /// Standard constructor
-  FixedTarget( const std::string& type , const std::string& name,
-               const IInterface* parent ) ;
-
-  virtual ~FixedTarget( ); ///< Destructor
-
-  /// Initialize method
-  StatusCode initialize( ) override;
-
-  /// Implements IBeamTool::getMeanBeams. See CollidingBeams::getMeanBeams
-  void getMeanBeams( Gaudi::XYZVector & pBeam1 ,
-                     Gaudi::XYZVector & pBeam2 ) const override;
-
-  /// Implements IBeamTool::getBeams. See CollidingBeams::getBeams
-  void getBeams( Gaudi::XYZVector & pBeam1 ,
-                 Gaudi::XYZVector & pBeam2 ) override;
-
- private:
-  std::string m_beamParameters ; ///< Location of beam parameters (set by options)
-
-  Rndm::Numbers m_gaussianDist ; ///< Gaussian random number generator
-};
-#endif // GENERATORS_FIXEDTARGET_H
diff --git a/Gen/Generators/src/component/FlatSmearVertex.cpp b/Gen/Generators/src/component/FlatSmearVertex.cpp
deleted file mode 100755
index 70d881c80..000000000
--- a/Gen/Generators/src/component/FlatSmearVertex.cpp
+++ /dev/null
@@ -1,127 +0,0 @@
-// $Id: FlatSmearVertex.cpp,v 1.1.1.1 2009-09-18 16:18:24 gcorti Exp $
-// Include files 
-
-// local
-#include "FlatSmearVertex.h"
-
-// from Gaudi
-#include "GaudiKernel/IRndmGenSvc.h" 
-#include "GaudiKernel/PhysicalConstants.h"
-#include "GaudiKernel/Vector4DTypes.h"
-#include "GaudiKernel/Transform3DTypes.h"
-
-// from Event
-#include "Event/HepMCEvent.h"
-
-//-----------------------------------------------------------------------------
-// Implementation file for class : FlatSmearVertex
-//
-// 2005-08-17 : Patrick Robbe
-//-----------------------------------------------------------------------------
-
-// Declaration of the Tool Factory
-DECLARE_COMPONENT( FlatSmearVertex )
-
-
-//=============================================================================
-// Standard constructor, initializes variables
-//=============================================================================
-FlatSmearVertex::FlatSmearVertex( const std::string& type,
-                                    const std::string& name,
-                                    const IInterface* parent )
-  : GaudiTool ( type, name , parent ) {
-    declareInterface< IVertexSmearingTool >( this ) ;
-    declareProperty( "xVertexMin" , m_xmin = 0.0 * Gaudi::Units::mm ) ;
-    declareProperty( "xVertexMax" , m_xmax = 0.0 * Gaudi::Units::mm ) ;
-    declareProperty( "yVertexMin" , m_ymin = 0.0 * Gaudi::Units::mm ) ;
-    declareProperty( "yVertexMax" , m_ymax = 0.0 * Gaudi::Units::mm ) ;
-    declareProperty( "zVertexMin" , m_zmin = 0.0 * Gaudi::Units::mm ) ;
-    declareProperty( "zVertexMax" , m_zmax = 0.0 * Gaudi::Units::mm ) ;
-    declareProperty( "BeamDirection", m_zDir = 0 );
-    declareProperty( "Tilt", m_tilt = false );
-    declareProperty( "TiltAngle", m_tiltAngle = -3.601e-3 );
-    
-}
-
-//=============================================================================
-// Destructor 
-//=============================================================================
-FlatSmearVertex::~FlatSmearVertex( ) { ; }
-
-//=============================================================================
-// Initialize 
-//=============================================================================
-StatusCode FlatSmearVertex::initialize( ) {
-  StatusCode sc = GaudiTool::initialize( ) ;
-  if ( sc.isFailure() ) return sc ;
-  
-  IRndmGenSvc * randSvc = svc< IRndmGenSvc >( "RndmGenSvc" , true ) ;
-  if ( m_xmin > m_xmax ) return Error( "xMin > xMax !" ) ;
-  if ( m_ymin > m_ymax ) return Error( "yMin > yMax !" ) ;  
-  if ( m_zmin > m_zmax ) return Error( "zMin > zMax !" ) ;
-  
-  sc = m_flatDist.initialize( randSvc , Rndm::Flat( 0. , 1. ) ) ;
-  
-  std::string infoMsg = " applying TOF of interaction with ";
-  if ( m_zDir == -1 ) {
-    infoMsg = infoMsg + "negative beam direction";
-  } else if ( m_zDir == 1 ) {
-    infoMsg = infoMsg + "positive beam direction";
-  } else if ( m_zDir == 0 ) {
-    infoMsg = " with TOF of interaction equal to zero ";
-  } else {
-    return Error("BeamDirection can only be set to -1 or 1, or 0 to switch off TOF");
-  }
-
-  info() << "Smearing of interaction point with flat distribution "
-         << " in x, y and z " << endmsg;
-  info() << infoMsg << endmsg;
-  info() << " with " << m_xmin / Gaudi::Units::mm 
-         << " mm <= x <= " << m_xmax / Gaudi::Units::mm << " mm, "
-         << m_ymin / Gaudi::Units::mm << " mm <= y <= " 
-         << m_ymax / Gaudi::Units::mm << " mm and "
-         << m_zmin / Gaudi::Units::mm << " mm <= z <= " 
-         << m_zmax / Gaudi::Units::mm << " mm." << endmsg;
-
-  if ( ! sc.isSuccess() ) 
-    return Error( "Could not initialize flat random number generator" ) ;
-
-  release( randSvc ) ;
-  return sc ;
-}
- 
-//=============================================================================
-// Smearing function
-//=============================================================================
-StatusCode FlatSmearVertex::smearVertex( LHCb::HepMCEvent * theEvent ) {
-  double dx , dy , dz , dt ;
-  
-  dx = m_xmin + m_flatDist( ) * ( m_xmax - m_xmin ) ;
-  dy = m_ymin + m_flatDist( ) * ( m_ymax - m_ymin ) ;
-  dz = m_zmin + m_flatDist( ) * ( m_zmax - m_zmin ) ;
-  dt = m_zDir * dz/Gaudi::Units::c_light ;
-
-  Gaudi::LorentzVector dpos( dx , dy , dz , dt ) ;
-  
-  HepMC::GenEvent::vertex_iterator vit ;
-  HepMC::GenEvent * pEvt = theEvent -> pGenEvt() ;
-  for ( vit = pEvt -> vertices_begin() ; vit != pEvt -> vertices_end() ; 
-        ++vit ) {
-    Gaudi::LorentzVector pos ( (*vit) -> position() ) ;
-    pos += dpos ;
-
-    if (m_tilt) {
-      Gaudi::LorentzVector negT( 0, 0, (fabs(m_zmax-m_zmin)<1e-3 ? -m_zmax : 0), 0 );
-      Gaudi::LorentzVector posT( 0, 0, (fabs(m_zmax-m_zmin)<1e-3 ? +m_zmax : 0), 0 );
-      Gaudi::RotationX rotX( m_zmax==m_zmin ? m_tiltAngle : 0 );
-      pos = pos + negT;
-      pos = rotX(pos);
-      pos = pos + posT;
-    }
-    (*vit) -> set_position( HepMC::FourVector( pos.x() , pos.y() , pos.z() ,
-                                               pos.t() ) ) ;
-  }
-
-  return StatusCode::SUCCESS ;      
-}
-
diff --git a/Gen/Generators/src/component/FlatSmearVertex.h b/Gen/Generators/src/component/FlatSmearVertex.h
deleted file mode 100755
index 09090201d..000000000
--- a/Gen/Generators/src/component/FlatSmearVertex.h
+++ /dev/null
@@ -1,64 +0,0 @@
-// $Id: FlatSmearVertex.h,v 1.1.1.1 2009-09-18 16:18:24 gcorti Exp $
-#ifndef PARTICLEGUNS_FLATSMEARVERTEX_H
-#define PARTICLEGUNS_FLATSMEARVERTEX_H 1
-
-// Include files
-// from Gaudi
-#include "GaudiAlg/GaudiTool.h"
-#include "GaudiKernel/RndmGenerators.h"
-
-#include "Generators/IVertexSmearingTool.h"
-
-/** @class FlatSmearVertex FlatSmearVertex.h "FlatSmearVertex.h"
- *
- *  Tool to smear vertex with flat smearing along the x- y- and z-axis.
- *  Concrete implementation of a IVertexSmearingTool.
- *
- *  @author Patrick Robbe
- *  @date   2008-05-18
- */
-class FlatSmearVertex : public GaudiTool, virtual public IVertexSmearingTool {
- public:
-  /// Standard constructor
-  FlatSmearVertex( const std::string& type , const std::string& name,
-                    const IInterface* parent ) ;
-
-  virtual ~FlatSmearVertex( ); ///< Destructor
-
-  /// Initialize method
-  StatusCode initialize( ) override;
-
-  /** Implements IVertexSmearingTool::smearVertex.
-   */
-  StatusCode smearVertex( LHCb::HepMCEvent * theEvent ) override;
-
- private:
-  /// Minimum value for the x coordinate of the vertex (set by options)
-  double m_xmin   ;
-
-  /// Minimum value for the y coordinate of the vertex (set by options)
-  double m_ymin   ;
-
-  /// Minimum value for the z coordinate of the vertex (set by options)
-  double m_zmin   ;
-
-  /// Maximum value for the x coordinate of the vertex (set by options)
-  double m_xmax   ;
-
-  /// Maximum value for the y coordinate of the vertex (set by options)
-  double m_ymax   ;
-
-  /// Maximum value for the z coordinate of the vertex (set by options)
-  double m_zmax   ;
-
-  /// Direction of the beam to take into account TOF vs nominal IP8, can have
-  /// only values -1 or 1, or 0 to switch off the TOF and set time of
-  /// interaction to zero (default = 1, as for beam 1)
-  int m_zDir;
-
-  bool m_tilt;
-  double m_tiltAngle;
-
-  Rndm::Numbers m_flatDist ; ///< Flat random number generator
-};
-#endif // PARTICLEGUNS_FLATSMEARVERTEX_H
diff --git a/Gen/Generators/src/component/FlatZSmearVertex.cpp b/Gen/Generators/src/component/FlatZSmearVertex.cpp
deleted file mode 100755
index c77853d56..000000000
--- a/Gen/Generators/src/component/FlatZSmearVertex.cpp
+++ /dev/null
@@ -1,127 +0,0 @@
-// $Id: FlatZSmearVertex.cpp,v 1.14 2010-05-09 17:05:24 gcorti Exp $
-// Include files 
-
-// local
-#include "FlatZSmearVertex.h"
-
-// from Gaudi
-#include "GaudiKernel/IRndmGenSvc.h" 
-#include "GaudiKernel/PhysicalConstants.h"
-#include "GaudiKernel/Vector4DTypes.h"
-
-// from Event
-#include "Event/HepMCEvent.h"
-#include "Event/BeamParameters.h"
-
-//-----------------------------------------------------------------------------
-// Implementation file for class : FlatZSmearVertex
-//
-// 2005-08-17 : Patrick Robbe
-//-----------------------------------------------------------------------------
-
-// Declaration of the Tool Factory
-DECLARE_COMPONENT( FlatZSmearVertex )
-
-
-//=============================================================================
-// Standard constructor, initializes variables
-//=============================================================================
-FlatZSmearVertex::FlatZSmearVertex( const std::string& type,
-                                    const std::string& name,
-                                    const IInterface* parent )
-  : GaudiTool ( type, name , parent ) {
-    declareInterface< IVertexSmearingTool >( this ) ;
-
-    declareProperty( "ZMin"   , m_zmin   = -1500. * Gaudi::Units::mm ) ;
-    declareProperty( "ZMax"   , m_zmax   =  1500. * Gaudi::Units::mm ) ;
-
-    declareProperty( "Xcut" , m_xcut = 4. ) ; // times SigmaX 
-    declareProperty( "Ycut" , m_ycut = 4. ) ; // times SigmaY
-
-    declareProperty( "BeamDirection", m_zDir = 1 );
-
-    declareProperty( "BeamParameters" ,
-                     m_beamParameters = LHCb::BeamParametersLocation::Default ) ;
-}
-
-//=============================================================================
-// Destructor 
-//=============================================================================
-FlatZSmearVertex::~FlatZSmearVertex( ) { ; }
-
-//=============================================================================
-// Initialize 
-//=============================================================================
-StatusCode FlatZSmearVertex::initialize( ) {
-  StatusCode sc = GaudiTool::initialize( ) ;
-  if ( sc.isFailure() ) return sc ;
-  
-  IRndmGenSvc * randSvc = svc< IRndmGenSvc >( "RndmGenSvc" , true ) ;
-  sc = m_gaussDist.initialize( randSvc , Rndm::Gauss( 0. , 1. ) ) ;
-  if ( ! sc.isSuccess() ) 
-    return Error( "Could not initialize gaussian random number generator" ) ;
-  if ( m_zmin > m_zmax ) return Error( "zMin > zMax !" ) ;
-  sc = m_flatDist.initialize( randSvc , Rndm::Flat( m_zmin , m_zmax ) ) ;
-  if ( ! sc.isSuccess() ) 
-    return Error( "Could not initialize flat random number generator" ) ;
-
-  std::string infoMsg = " applying TOF of interaction with ";
-  if ( m_zDir == -1 ) {
-    infoMsg = infoMsg + "negative beam direction";
-  } else if ( m_zDir == 1 ) {
-    infoMsg = infoMsg + "positive beam direction";
-  } else if ( m_zDir == 0 ) {
-    infoMsg = " with TOF of interaction equal to zero ";
-  } else {
-    return Error("BeamDirection can only be set to -1 or 1, or 0 to switch off TOF");
-  }
-
-  info() << "Smearing of interaction point with transverse Gaussian "
-         << " distribution " << endmsg;
-  info() << infoMsg << endmsg;
-  info() << "and flat longitudinal z distribution" << endmsg;
-
-  release( randSvc ) ;
- 
-  return sc ;
-}
- 
-//=============================================================================
-// Smearing function
-//=============================================================================
-StatusCode FlatZSmearVertex::smearVertex( LHCb::HepMCEvent * theEvent ) {
-
-  LHCb::BeamParameters * beam = get< LHCb::BeamParameters >( m_beamParameters ) ;
-  if ( 0 == beam ) Exception( "No beam parameters registered" ) ;
-
-  double dx , dy , dz , dt;
-  
-  dz = m_flatDist( ) ;
-  dt = m_zDir * dz/Gaudi::Units::c_light;
-
-  do { dx = m_gaussDist( ) ; } while ( fabs( dx ) > m_xcut ) ;
-  dx = dx * beam -> sigmaX() * sqrt( 2. ) ;
-  do { dy = m_gaussDist( ) ; } while ( fabs( dy ) > m_ycut ) ;
-  dy = dy * beam -> sigmaY() * sqrt( 2. ) ;
-
-  // take into account mean at z=0 and crossing angle
-  dx = dx/cos( beam -> horizontalCrossingAngle() ) + 
-    beam -> beamSpot().x() + dz*sin( beam -> horizontalCrossingAngle() )*m_zDir;
-  dy = dy/cos( beam -> verticalCrossingAngle() ) + 
-    beam -> beamSpot().y() + dz*sin( beam -> verticalCrossingAngle() )*m_zDir;
-
-  Gaudi::LorentzVector dpos( dx , dy , dz , dt ) ;
-  
-  HepMC::GenEvent::vertex_iterator vit ;
-  HepMC::GenEvent * pEvt = theEvent -> pGenEvt() ;
-  for ( vit = pEvt -> vertices_begin() ; vit != pEvt -> vertices_end() ; 
-        ++vit ) {
-    Gaudi::LorentzVector pos ( (*vit) -> position() ) ;
-    pos += dpos ;
-    (*vit) -> set_position( HepMC::FourVector( pos.x() , pos.y() , 
-                                               pos.z() , pos.t() ) ) ;
-  }
-
-  return StatusCode::SUCCESS ;      
-}
-
diff --git a/Gen/Generators/src/component/FlatZSmearVertex.h b/Gen/Generators/src/component/FlatZSmearVertex.h
deleted file mode 100755
index ba0e25d61..000000000
--- a/Gen/Generators/src/component/FlatZSmearVertex.h
+++ /dev/null
@@ -1,63 +0,0 @@
-// $Id: FlatZSmearVertex.h,v 1.5 2010-05-09 17:05:30 gcorti Exp $
-#ifndef GENERATORS_FLATZSMEARVERTEX_H
-#define GENERATORS_FLATZSMEARVERTEX_H 1
-
-// Include files
-// from Gaudi
-#include "GaudiAlg/GaudiTool.h"
-#include "GaudiKernel/RndmGenerators.h"
-
-#include "Generators/IVertexSmearingTool.h"
-
-/** @class FlatZSmearVertex FlatZSmearVertex.h "FlatZSmearVertex.h"
- *
- *  Tool to smear vertex with flat smearing along the z-axis and Gaussian
- *  smearing for the other axis (as in BeamSpotSmearVertex). Concrete
- *  implementation of a IVertexSmearingTool.
- *
- *  @author Patrick Robbe
- *  @date   2005-08-24
- */
-class FlatZSmearVertex : public GaudiTool, virtual public IVertexSmearingTool {
- public:
-  /// Standard constructor
-  FlatZSmearVertex( const std::string& type , const std::string& name,
-                    const IInterface* parent ) ;
-
-  virtual ~FlatZSmearVertex( ); ///< Destructor
-
-  /// Initialize method
-  StatusCode initialize( ) override;
-
-  /** Implements IVertexSmearingTool::smearVertex.
-   *  Does the same than BeamSpotSmearVertex::smearVertex for the x and y
-   *  direction but generates flat distribution for the z-coordinate of
-   *  the primary vertex.
-   */
-  StatusCode smearVertex( LHCb::HepMCEvent * theEvent ) override;
-
- private:
-  std::string m_beamParameters ; ///< Location of beam parameters (set by options)
-
-  /// Number of sigma above which to cut for x-axis smearing (set by options)
-  double m_xcut   ;
-
-  /// Number of sigma above which to cut for y-axis smearing (set by options)
-  double m_ycut   ;
-
-  /// Minimum value for the z coordinate of the vertex (set by options)
-  double m_zmin   ;
-
-  /// Maximum value for the z coordinate of the vertex (set by options)
-  double m_zmax   ;
-
-  /// Direction of the beam to take into account TOF vs nominal IP8, can have
-  /// only values -1 or 1, or 0 to switch off the TOF and set time of
-  /// interaction to zero (default = 1, as for beam 1)
-  int m_zDir;
-
-  Rndm::Numbers m_gaussDist ; ///< Gaussian random number generator
-
-  Rndm::Numbers m_flatDist ; ///< Flat random number generator
-};
-#endif // GENERATORS_FLATZSMEARVERTEX_H
diff --git a/Gen/Generators/src/component/Generation.cpp b/Gen/Generators/src/component/Generation.cpp
deleted file mode 100755
index 26d541d53..000000000
--- a/Gen/Generators/src/component/Generation.cpp
+++ /dev/null
@@ -1,670 +0,0 @@
-// $Id: Generation.cpp,v 1.33 2009-06-15 17:02:35 gcorti Exp $
-// Include files 
-
-// from Gaudi
-#include "GaudiKernel/RndmGenerators.h"
-#include "GaudiKernel/SystemOfUnits.h"
-
-// from Event
-#include "Event/GenHeader.h"
-#include "Event/GenCollision.h"
-#include "Event/GenFSR.h"
-#include "Event/GenCountersFSR.h"
-#include "Event/CrossSectionsFSR.h"
-
-// from LHCb
-#include "Kernel/ParticleID.h"
-#include "MCInterfaces/IFullGenEventCutTool.h"
-#include "MCInterfaces/IDecayTool.h" 
-
-// from Generators
-#include "Generators/ISampleGenerationTool.h"
-#include "Generators/IPileUpTool.h"
-#include "Generators/IVertexSmearingTool.h"
-#include "Generators/ICounterLogFile.h"
-#include "Generators/GenCounters.h"
-#include "GenEvent/HepMCUtils.h"
-
-// Gaudi Common Flat Random Number generator
-#include "Generators/RandomForGenerator.h"
-
-// local
-#include "Generation.h"
-
-#include <iostream>
-#include <stdlib.h>     /* getenv */
-#include "TSystem.h"
-#include "TUnixSystem.h"
-
-//-----------------------------------------------------------------------------
-// Implementation file for class : Generation
-//
-// 2005-08-11 : Patrick Robbe
-//-----------------------------------------------------------------------------
-
-// Declaration of the Algorithm Factory
-
-DECLARE_COMPONENT( Generation )
-
-//=============================================================================
-// Standard constructor, initializes variables
-//=============================================================================
-Generation::Generation( const std::string& name,
-                        ISvcLocator* pSvcLocator)
-  : GaudiAlgorithm ( name , pSvcLocator ) ,
-    m_fileRecordSvc        ( 0 ) ,
-    m_pileUpTool           ( 0 ) ,
-    m_decayTool            ( 0 ) ,
-    m_xmlLogTool           ( 0 ) ,
-    m_sampleGenerationTool ( 0 ) ,
-    m_vertexSmearingTool   ( 0 ) ,
-    m_fullGenEventCutTool  ( 0 ) ,
-    m_nEvents              ( 0 ) , 
-    m_nAcceptedEvents      ( 0 ) ,
-    m_nInteractions        ( 0 ) , 
-    m_nAcceptedInteractions( 0 ) ,
-    m_nBeforeFullEvent     ( 0 ) ,
-    m_nAfterFullEvent      ( 0 ) ,
-    m_genFSR               ( 0 ) {  
-
-    // Generation Method
-    declareProperty ( "SampleGenerationTool" , 
-                      m_sampleGenerationToolName = "MinimumBias" ) ;
-    declareProperty ( "EventType"          , m_eventType = 30000000 ) ;
-
-    // Location of the output of the generation
-    declareProperty ( "HepMCEventLocation" , m_hepMCEventLocation = 
-                      LHCb::HepMCEventLocation::Default ) ;
-    declareProperty ( "GenHeaderLocation"  , m_genHeaderLocation = 
-                      LHCb::GenHeaderLocation::Default ) ;
-    declareProperty ( "GenCollisionLocation" , m_genCollisionLocation = 
-                      LHCb::GenCollisionLocation::Default ) ;
-    declareProperty ( "GenFSRLocation", m_FSRName =
-                      LHCb::GenFSRLocation::Default);
-
-    // Tool name to generate the event
-    declareProperty( "PileUpTool" , m_pileUpToolName = "FixedLuminosity" ) ;
-    // Tool name to decay particles in the event
-    declareProperty( "DecayTool"  , m_decayToolName = "EvtGenDecay" ) ;
-    // Tool name to smear vertex
-    declareProperty( "VertexSmearingTool" , 
-                     m_vertexSmearingToolName = "BeamSpotSmearVertex" ) ;
-    // Tool name to cut on full event
-    declareProperty( "FullGenEventCutTool" , 
-                     m_fullGenEventCutToolName = "" ) ;
-    // Flag to attach all pile up events to the same PV
-    declareProperty( "CommonVertex" , m_commonVertex = false ) ;
-
-    // Reset counters
-    m_intC.assign( 0 ) ;
-    m_intCAccepted.assign( 0 ) ;
-    // setup counter names
-    m_intCName[ Oneb ] = "generated interactions with >= 1b" ;    
-    m_intCName[ Threeb ] = "generated interactions with >= 3b" ;
-    m_intCName[ PromptB ] = "generated interactions with 1 prompt B" ;
-    m_intCName[ Onec ] = "generated interactions with >= 1c" ;
-    m_intCName[ Threec ] = "generated interactions with >= 3c" ;
-    m_intCName[ PromptC ] = "generated interactions with >= prompt C" ;
-    m_intCName[ bAndc ] = "generated interactions with b and c" ;
-
-    m_intCAcceptedName[ Oneb ] = "accepted interactions with >= 1b" ;    
-    m_intCAcceptedName[ Threeb ] = "accepted interactions with >= 3b" ;
-    m_intCAcceptedName[ PromptB ] = "accepted interactions with 1 prompt B" ;
-    m_intCAcceptedName[ Onec ] = "accepted interactions with >= 1c" ;
-    m_intCAcceptedName[ Threec ] = "accepted interactions with >= 3c" ;
-    m_intCAcceptedName[ PromptC ] = "accepted interactions with >= prompt C" ;
-    m_intCAcceptedName[ bAndc ] = "accepted interactions with b and c" ;
-
-}
-
-//=============================================================================
-// Destructor
-//=============================================================================
-Generation::~Generation() {}
-
-//=============================================================================
-// Initialisation. Check parameters
-//=============================================================================
-StatusCode Generation::initialize() {
-  StatusCode sc = GaudiAlgorithm::initialize( ) ; // Initialize base class
-  if ( sc.isFailure() ) return sc ;
-  debug() << "==> Initialise" << endmsg ;
-
-  // Initialization of the Common Flat Random generator if not already done
-  // This generator must be used by all external MC Generator
-  if ( ! ( RandomForGenerator::getNumbers() ) ) {
-    sc = RandomForGenerator::getNumbers().initialize( randSvc( ) , 
-                                                      Rndm::Flat( 0 , 1 ) ) ;
-    if ( ! sc.isSuccess( ) )
-      return Error( "Could not initialize Rndm::Flat" , sc ) ;
-  }
-
-  // Retrieve pile up tool
-  if ( "" == m_pileUpToolName ) {
-    info() << "No Pile Up Tool is defined. Will generate no pile-up " 
-           << endmsg ;
-    info() << "and set luminosity in header to 2e32" << endmsg ;
-  } else m_pileUpTool = tool< IPileUpTool >( m_pileUpToolName , this ) ;
-
-  // Retrieve decay tool
-  if ( "" != m_decayToolName ) m_decayTool = 
-    tool< IDecayTool >( m_decayToolName ) ;
-
-  // Retrieve xml log file tool for generator statistics
-  m_xmlLogTool = tool< ICounterLogFile >( "XmlCounterLogFile" ) ;
-
-  // Retrieve generation method tool
-  if ( "" == m_sampleGenerationToolName ) 
-    return Error( "No Sample Generation Tool is defined. This is mandatory" ) ;
-  m_sampleGenerationTool = 
-    tool< ISampleGenerationTool >( m_sampleGenerationToolName , this ) ;
-  
-  // Retrieve vertex smearing tool
-  if ( "" == m_vertexSmearingToolName ) {
-    info() << "No vertex smearing tool is defined. Will not smear anything." 
-           << endmsg ;
-  } else {
-    m_vertexSmearingTool = 
-      tool< IVertexSmearingTool >( m_vertexSmearingToolName , this ) ;
-  }
-  
-  // Retrieve full gen event cut tool
-  if ( "" != m_fullGenEventCutToolName ) m_fullGenEventCutTool =
-    tool< IFullGenEventCutTool >( m_fullGenEventCutToolName , this ) ;
-
-  // Message relative to event type
-  always()
-    << "=================================================================="
-    << endmsg;
-  always()
-    << "Requested to generate EventType " << m_eventType << endmsg;
-  always()
-    << "=================================================================="
-    << endmsg;
-
-  if (m_FSRName != "") {
-    // get the File Records service
-    m_fileRecordSvc = svc<IDataProviderSvc>("FileRecordDataSvc", true);
-
-    // create a new FSR and append to TDS
-    m_genFSR = new LHCb::GenFSR();
-
-    // Now either create the info in the TES or add it to the existing one
-    put(m_fileRecordSvc, m_genFSR, m_FSRName, false);
-
-    m_genFSR->initializeInfos();
-  }
-
-  return StatusCode::SUCCESS;
-}
-
-//=============================================================================
-// Main execution
-//=============================================================================
-StatusCode Generation::execute() {
-
-  debug() << "Processing event type " << m_eventType << endmsg ;
-  StatusCode sc = StatusCode::SUCCESS ;
-  setFilterPassed( true ) ;
-
-  // Get the header and update the information
-  LHCb::GenHeader* theGenHeader = get<LHCb::GenHeader> ( m_genHeaderLocation );
-  if( !theGenHeader->evType() ){
-    theGenHeader -> setEvType( m_eventType );  
-  }
-
-  if(m_genFSR && m_genFSR->getSimulationInfo("evtType", 0) == 0)
-  {
-    std::string decFiles = "";
-    int evtType = 0;
-    std::string path = gSystem->Getenv("DECFILESROOT");
-    std::string decFiles_file = "";
-   
-    if(path!=NULL)
-    {
-      decFiles_file = path;
-    
-      for(int i=decFiles_file.length()-1; i>= 0; i--)
-      {
-        char stop_char = '/';
-        char ichar = decFiles_file[i];
-        if(ichar!=stop_char)
-          decFiles += ichar;
-        else
-          break; 
-      }
-
-      std::reverse(decFiles.begin(), decFiles.end());      
-    }
-
-    evtType = m_eventType;
-
-    m_genFSR->addSimulationInfo("evtType", evtType);
-    m_genFSR->addSimulationInfo("generationMethod",m_sampleGenerationTool->name());
-    m_genFSR->addSimulationInfo("decFiles", decFiles);
-    m_genFSR->incrementNJobs();
-  }
-
-  unsigned int  nPileUp( 0 ) ;
-  
-  LHCb::HepMCEvents::iterator itEvents ;
-
-  // Create temporary containers for this event
-  LHCb::HepMCEvents* theEvents = new LHCb::HepMCEvents( );
-  LHCb::GenCollisions* theCollisions = new LHCb::GenCollisions( );
-
-  interactionCounter theIntCounter ;
-
-  // variables to store counters in FSR                                                              
-  int key = 0;  
-  std::string name = " ";
-
-  // Generate a set of interaction until a good one is found
-  bool goodEvent = false ;
-  while ( ! goodEvent ) {
-    theEvents->clear() ;
-    theCollisions->clear() ;
-    
-    // Compute the number of pile-up interactions to generate 
-    if ( 0 != m_pileUpTool ) 
-      nPileUp = m_pileUpTool -> numberOfPileUp( ) ;
-    else 
-      // default set to 1 pile and 2.10^32 luminosity
-      nPileUp = 1 ;
-
-    // generate a set of Pile up interactions according to the requested type
-    // of event
-    if ( 0 < nPileUp ) 
-      goodEvent = m_sampleGenerationTool -> generate( nPileUp, theEvents, 
-                                                      theCollisions );
-    else { 
-      goodEvent = true ;
-      setFilterPassed( false ) ;
-    }
-    
-    // increase event and interactions counters
-    ++m_nEvents ;    m_nInteractions += nPileUp ;
-
-    // increase the generated events counter in the FSR                                                                                                          
-    name = "EvtGenerated";
-    key = LHCb::GenCountersFSR::CounterKeyToType(name);
-    if(m_genFSR) m_genFSR->incrementGenCounter(key,1);
-    // increase the generated interactions counter in the FSR                                                                                                    
-    name = "IntGenerated";
-    key = LHCb::GenCountersFSR::CounterKeyToType(name);    
-    if(m_genFSR) m_genFSR->incrementGenCounter(key,nPileUp);
-
-    // Update interaction counters
-    if ( 0 < nPileUp ) { 
-      theIntCounter.assign( 0 ) ;
-      for ( itEvents = theEvents->begin() ; itEvents != theEvents->end() ; 
-            ++itEvents ) updateInteractionCounters( theIntCounter , *itEvents ) ;
-    
-      // Increse the generated interactions counters in FSR                                                                                                      
-      if(m_genFSR) updateFSRCounters(theIntCounter, m_genFSR, "Gen");
-
-      GenCounters::AddTo( m_intC , theIntCounter ) ;
-
-      // Decay the event if it is a good event
-      if ( goodEvent ) {
-        unsigned short iPile( 0 ) ;
-        for ( itEvents = theEvents->begin() ; itEvents != theEvents->end() ;
-              ++itEvents ) {
-          if ( 0 != m_decayTool ) {
-            sc = decayEvent( *itEvents ) ;
-            if ( ! sc.isSuccess() ) goodEvent = false ;
-          }
-          (*itEvents) -> pGenEvt() -> set_event_number( ++iPile ) ;
-          if(m_vertexSmearingTool){
-            if ( ( ! ( m_commonVertex ) ) || ( 1 == iPile ) )
-                sc = m_vertexSmearingTool -> smearVertex( *itEvents ) ;
-            if ( ! sc.isSuccess() ) return sc ;
-          }
-        }
-      }
-
-      if ( ( m_commonVertex ) && ( 1 < nPileUp ) ) {
-        HepMC::FourVector commonV = 
-          ((*(theEvents->begin())) ->pGenEvt() -> beam_particles().first) -> end_vertex() -> position() ;
-        for ( itEvents = (theEvents->begin()+1) ; itEvents != theEvents -> end() ;
-              ++itEvents ) {
-          HepMC::GenEvent::vertex_iterator vit ;
-          HepMC::GenEvent * pEvt = (*itEvents) -> pGenEvt() ;
-          for ( vit = pEvt -> vertices_begin() ; vit != pEvt -> vertices_end() ; 
-                ++vit ) {
-            HepMC::FourVector pos = (*vit) -> position() ;
-            (*vit) -> set_position( HepMC::FourVector( pos.x() + commonV.x() , 
-                                                       pos.y() + commonV.y() , 
-                                                       pos.z() + commonV.z() , 
-                                                       pos.t() + commonV.t() ) ) ;
-          }
-        } 
-      }
-      
-
-      // Apply generator level cut on full event
-      if ( m_fullGenEventCutTool ) {
-        if ( goodEvent ) {
-          ++m_nBeforeFullEvent ;
-          // increase the counter of events before the full event generator level cut in the FSR                                                                 
-          name = "BeforeFullEvt";
-          key = LHCb::GenCountersFSR::CounterKeyToType(name);          
-          if(m_genFSR) m_genFSR->incrementGenCounter(key,1);
-
-          goodEvent = m_fullGenEventCutTool -> studyFullEvent( theEvents , 
-                                                             theCollisions );
-          if ( goodEvent ) {
-            ++m_nAfterFullEvent ;
-            // increase the counter of events after the full event generator level cut in the FSR                                                                
-            name = "AfterFullEvt";
-            key = LHCb::GenCountersFSR::CounterKeyToType(name);
-            if(m_genFSR) m_genFSR->incrementGenCounter(key,1);            
-          }
-        }
-      }
-    }
-  }  
-
-  ++m_nAcceptedEvents ;
-  m_nAcceptedInteractions += nPileUp ;
-  
-  // increase the generated events counter in the FSR                                                                                                            
-  name = "EvtAccepted";
-  key = LHCb::GenCountersFSR::CounterKeyToType(name);
-  if(m_genFSR) m_genFSR->incrementGenCounter(key,1);
-
-  // increase the generated interactions counter in the FSR                                                                                                      
-  name = "IntAccepted";
-  key = LHCb::GenCountersFSR::CounterKeyToType(name);  
-  if(m_genFSR) m_genFSR->incrementGenCounter(key,nPileUp);
-
-  LHCb::HepMCEvents* eventsInTES( 0 )  ;
-  LHCb::GenCollisions* collisionsInTES( 0 ) ;
-  if ( 0 < nPileUp ) {
-    GenCounters::AddTo( m_intCAccepted , theIntCounter ) ;
-
-    // Increse the accepted interactions counters in FSR                                                                                                         
-    if(m_genFSR) updateFSRCounters(theIntCounter, m_genFSR, "Acc");
-
-    // Now either create the info in the TES or add it to the existing one
-    eventsInTES = 
-      getOrCreate<LHCb::HepMCEvents,LHCb::HepMCEvents>( m_hepMCEventLocation );
-
-    collisionsInTES = 
-      getOrCreate<LHCb::GenCollisions,LHCb::GenCollisions>( m_genCollisionLocation );
-  }
-    
-  // Copy the HepMCevents and Collisions from the temporary containers to 
-  // those in TES and update the header information
-
-  // Check that number of temporary HepMCEvents is the same as GenCollisions
-  if( theEvents->size() != theCollisions->size() ) {
-    return Error("Number of HepMCEvents and GenCollisions do not match" );
-  }
-
-  itEvents = theEvents->begin();
-  if ( 0 < nPileUp ) {
-    for( LHCb::GenCollisions::const_iterator it = theCollisions->begin();
-         theCollisions->end() != it; ++it ) {
-
-      // GenFSR
-      if(m_genFSR && m_genFSR->getSimulationInfo("hardGenerator", "") == "")
-        m_genFSR->addSimulationInfo("hardGenerator",(*itEvents)->generatorName());
-
-      // HepMCEvent
-      LHCb::HepMCEvent* theHepMCEvent = new LHCb::HepMCEvent();
-      theHepMCEvent->setGeneratorName( (*itEvents)->generatorName() );
-      (*theHepMCEvent->pGenEvt()) = (*(*itEvents)->pGenEvt());
-      eventsInTES->insert( theHepMCEvent );
-      ++itEvents;
-      
-      // GenCollision
-      LHCb::GenCollision* theGenCollision = new LHCb::GenCollision();
-      theGenCollision->setIsSignal( (*it)->isSignal() );
-      theGenCollision->setProcessType( (*it)->processType() );
-      theGenCollision->setSHat( (*it)->sHat() );
-      theGenCollision->setTHat( (*it)->tHat() );
-      theGenCollision->setUHat( (*it)->uHat() );
-      theGenCollision->setPtHat( (*it)->ptHat() );
-      theGenCollision->setX1Bjorken( (*it)->x1Bjorken() );
-      theGenCollision->setX2Bjorken( (*it)->x2Bjorken() );
-      theGenCollision->setEvent( theHepMCEvent );
-      collisionsInTES->insert( theGenCollision );
-      
-      // GenHeader
-      theGenHeader->addToCollisions( theGenCollision );
-      
-    }
-  }
-
-  // Clear and delete the temporary containers
-  theEvents->clear();
-  theCollisions->clear();
-  delete(theEvents);
-  delete(theCollisions);
-
-  return sc ;
-}
-
-//=============================================================================
-//  Finalize
-//=============================================================================
-StatusCode Generation::finalize() {
-  using namespace GenCounters ;
-  debug( ) << "==> Finalize" << endmsg ;
-  // Add the event type number to the log file
-  m_xmlLogTool -> addEventType( m_eventType ) ;
-  
-  // Print the various counters
-  if ( 0 != m_pileUpTool ) { m_pileUpTool -> printPileUpCounters( ) ; }
-
-  printCounter( m_xmlLogTool , "generated events" , m_nEvents ) ;
-  printCounter( m_xmlLogTool , "generated interactions" , m_nInteractions ) ;
-  
-  for ( unsigned int i = 0 ; i < m_intC.size() ; ++i )
-    printCounter( m_xmlLogTool , m_intCName[ i ] , m_intC[ i ] ) ;
-  
-  printCounter( m_xmlLogTool , "accepted events" , m_nAcceptedEvents ) ;
-  printCounter( m_xmlLogTool , "interactions in accepted events" , 
-                m_nAcceptedInteractions ) ;
-  
-  for ( unsigned int j = 0 ; j < m_intCAccepted.size() ; ++j ) 
-    printCounter( m_xmlLogTool , m_intCAcceptedName[ j ] , 
-                  m_intCAccepted[ j ] ) ;
-
-  printEfficiency( m_xmlLogTool , "full event cut" , m_nAfterFullEvent , 
-                   m_nBeforeFullEvent ) ;
-
-  m_sampleGenerationTool -> printCounters() ;
-
-  // check if the FSR can be retrieved from the TS                                                                                                               
-  if(m_FSRName != ""){
-    LHCb::GenFSR* readFSR = getIfExists<LHCb::GenFSR>(m_fileRecordSvc, m_FSRName);
-    if(readFSR!=NULL)    // print the FSR just retrieved from TS
-      always() << "READ FSR: " << *readFSR << endmsg;
-  }
-
-  if ( 0 != m_pileUpTool ) release( m_pileUpTool ) ;
-  if ( 0 != m_decayTool ) release( m_decayTool ) ;
-  if ( 0 != m_sampleGenerationTool ) release( m_sampleGenerationTool ) ;
-  if ( 0 != m_vertexSmearingTool ) release( m_vertexSmearingTool ) ;
-  if ( 0 != m_fullGenEventCutTool ) release( m_fullGenEventCutTool ) ;
-  
-  return GaudiAlgorithm::finalize( ) ; // Finalize base class
-}
-
-//=============================================================================
-// Decay in the event all particles which have been left stable by the
-// production generator
-//=============================================================================
-StatusCode Generation::decayEvent( LHCb::HepMCEvent * theEvent ) {
-  using namespace LHCb;
-  m_decayTool -> disableFlip() ;
-  StatusCode sc ;
-  
-  HepMC::GenEvent * pEvt = theEvent -> pGenEvt() ;
-
-  // We must use particles_begin to obtain an ordered iterator of GenParticles
-  // according to the barcode: this allows to reproduce events !
-  HepMCUtils::ParticleSet pSet( pEvt -> particles_begin() , 
-                                pEvt -> particles_end() ) ;
-
-  HepMCUtils::ParticleSet::iterator itp ;
-
-  for ( itp = pSet.begin() ; itp != pSet.end() ; ++itp ) {
-    
-    HepMC::GenParticle * thePart = (*itp) ;
-    unsigned int status = thePart -> status() ;
-    
-    if ( ( HepMCEvent::StableInProdGen  == status ) || 
-         ( ( HepMCEvent::DecayedByDecayGenAndProducedByProdGen == status )
-           && ( 0 == thePart -> end_vertex() ) ) ) {
-      
-      if ( m_decayTool -> isKnownToDecayTool( thePart -> pdg_id() ) ) {
-        
-        if ( HepMCEvent::StableInProdGen == status ) 
-          thePart -> 
-            set_status( HepMCEvent::DecayedByDecayGenAndProducedByProdGen ) ;
-        else thePart -> set_status( HepMCEvent::DecayedByDecayGen ) ;
-        
-        sc = m_decayTool -> generateDecay( thePart ) ;
-        if ( ! sc.isSuccess() ) return sc ;
-      }
-    } 
-  }  
-  return StatusCode::SUCCESS ;
-}
-
-//=============================================================================
-// Interaction counters
-//=============================================================================
-void Generation::updateInteractionCounters( interactionCounter & theCounter ,
-                                            const LHCb::HepMCEvent * evt ) 
-{
-  const HepMC::GenEvent * theEvent = evt -> pGenEvt() ;
-  unsigned int bQuark( 0 ) , bHadron( 0 ) , cQuark( 0 ) , cHadron( 0 ) ;
-  int pdgId ;
-
-  HepMC::GenEvent::particle_const_iterator iter ;
-  for ( iter = theEvent -> particles_begin() ; 
-        theEvent -> particles_end() != iter ; ++iter ) {
-    if ( ( (*iter) -> status() == LHCb::HepMCEvent::DocumentationParticle ) ||
-         ( (*iter) -> status() == LHCb::HepMCEvent::DecayedByDecayGen ) ||
-         ( (*iter) -> status() == LHCb::HepMCEvent::StableInDecayGen ) ) 
-      continue ;
-    pdgId = abs( (*iter) -> pdg_id() ) ;
-    LHCb::ParticleID thePid( pdgId ) ;
-
-    if ( 5 == pdgId ) { 
-      if ( 0 != (*iter) -> production_vertex() ) {
-        if ( 1 != (*iter) -> production_vertex() -> particles_in_size() ) {
-           bool containB = false;
-           for (HepMC::GenVertex::particles_in_const_iterator par = (*iter) -> production_vertex() -> particles_in_const_begin();
-                par != (*iter) -> production_vertex() -> particles_in_const_end() ; par++) {
-             if (5==abs((*par)->pdg_id()))
-               containB = true;
-           }
-           if (!containB) ++bQuark ;
-        } else {
-          const HepMC::GenParticle * par = 
-            *( (*iter) -> production_vertex() -> particles_in_const_begin() ) ;
-          if ( ( par -> status() == 
-                 LHCb::HepMCEvent::DocumentationParticle ) ||
-               ( par -> pdg_id() != (*iter) -> pdg_id() ) ) { 
-            ++bQuark ;
-          }
-        }
-      }
-    }
-    else if( 4 == pdgId ) {
-      if ( 0 != (*iter) -> production_vertex() ) {
-        if ( 1 != (*iter) -> production_vertex() -> particles_in_size() ) {
-          bool containC = false;
-          for (HepMC::GenVertex::particles_in_const_iterator par = (*iter) -> production_vertex() -> particles_in_const_begin();
-               par != (*iter) -> production_vertex() -> particles_in_const_end() ; par++) {
-            if (4==abs((*par)->pdg_id()))
-              containC = true;
-          }
-          if (!containC) ++cQuark ;
-        } else {
-          const HepMC::GenParticle * par =
-            *( (*iter) -> production_vertex() -> particles_in_const_begin() ) ;
-          if ( ( par -> status() ==
-                 LHCb::HepMCEvent::DocumentationParticle ) ||
-               ( par -> pdg_id() != (*iter) -> pdg_id() ) ) {
-            ++cQuark ;
-          }
-        }
-      }
-    }
-    else {
-      if ( thePid.hasBottom() ) {
-        // Count B from initial proton as a quark
-        if ( 0 != (*iter) -> production_vertex() ) {
-          if ( 0 != (*iter) -> production_vertex() -> particles_in_size() ) {
-            const HepMC::GenParticle * par = 
-              *( (*iter)-> production_vertex()-> particles_in_const_begin() ) ;
-            if ( 0 != par -> production_vertex() ) {
-              if ( 0 == par -> production_vertex() -> particles_in_size() ) {
-                ++bQuark ;
-              }
-            } 
-            else {
-              ++bQuark ;
-            }
-          }
-        }
-        ++bHadron ;
-      } else if ( thePid.hasCharm() ) {
-        // Count D from initial proton as a quark
-        if ( 0 != (*iter) -> production_vertex() ) {
-          if ( 0 != (*iter) -> production_vertex() -> particles_in_size() ) {
-            const HepMC::GenParticle * par = 
-              *( (*iter)-> production_vertex()-> particles_in_const_begin() ) ;
-            if ( 0 != par -> production_vertex() ) {
-              if ( 0 == par -> production_vertex() -> particles_in_size() ) 
-                ++cQuark ;
-            } else ++cQuark ;
-          }
-        }
-        ++cHadron ;
-      }
-    }
-  }
-
-  if ( bQuark >= 1 ) { 
-    ++theCounter[ Oneb ] ;
-    if ( bQuark >= 3 ) ++theCounter[ Threeb ] ;
-  }
-  if ( cQuark >= 1 ) {
-    ++theCounter[ Onec ] ;
-    if ( cQuark >= 3 ) ++theCounter[ Threec ] ;
-    if ( bQuark >= 1 ) ++theCounter[ bAndc ] ;
-  }
-  if ( ( 0 == bQuark ) && ( bHadron > 0 ) ) ++theCounter[ PromptB ] ;
-  if ( ( 0 == cQuark ) && ( 0 == bHadron ) && ( cHadron > 0 ) ) 
-    ++theCounter[ PromptC ];
-}
-
-
-//=============================================================================
-// Interaction counters in FSR                                              
-//=============================================================================                   
-
-void Generation::updateFSRCounters( interactionCounter & theCounter,
-                                    LHCb::GenFSR* m_genFSR,
-                                    const std::string option)
-{
-  int key = 0; 
-  longlong count = 0;
-  std::string name[7]= {"Oneb","Threeb","PromptB","Onec","Threec","PromptC","bAndc"};  
-  std::string cname = "";
-
-  for(int i=0; i<7; i++)
-  {
-    cname = name[i]+option;
-    key = LHCb::GenCountersFSR::CounterKeyToType(cname);
-    count = theCounter[i];
-    m_genFSR->incrementGenCounter(key,count); 
-  } 
-}
diff --git a/Gen/Generators/src/component/Generation.h b/Gen/Generators/src/component/Generation.h
deleted file mode 100755
index 2a01c2e1b..000000000
--- a/Gen/Generators/src/component/Generation.h
+++ /dev/null
@@ -1,187 +0,0 @@
-// $Id: Generation.h,v 1.9 2007-07-03 16:31:36 gcorti Exp $
-#ifndef GENERATORS_GENERATION_H
-#define GENERATORS_GENERATION_H 1
-
-#include "GaudiAlg/GaudiAlgorithm.h"
-
-#include <boost/array.hpp>
-
-#include "Event/GenFSR.h"
-
-// Forward declarations
-class ISampleGenerationTool ;
-class IPileUpTool ;
-class IDecayTool ;
-class IVertexSmearingTool ;
-class IFullGenEventCutTool ;
-class ICounterLogFile ;
-
-namespace HepMC {
-  class GenParticle ;
-}
-
-namespace LHCb {
-  class HepMCEvent;
-}
-
-/** @class Generation Generation.h "Generation.h"
- *
- *  Main algorithm to generate Monte Carlo events.
- *
- *  @author Patrick Robbe
- *  @date   2005-08-11
- */
-class Generation : public GaudiAlgorithm {
- public:
-  /// Standard constructor
-  Generation( const std::string& name, ISvcLocator* pSvcLocator );
-
-  virtual ~Generation( ); ///< Destructor
-
-  /** Algorithm initialization.
-   *  -# Initializes the common Gaudi random number generator used in all
-   *     generators,
-   *  -# Retrieve Pile-up tool, sample generation tool, decay tool,
-   *     vertex smearing tool and full event cut tool used in the generation
-   *     of events.
-   */
-  StatusCode initialize() override;
-
-  /** Algorithm execution.
-   *  Repeat the following sequence until a good set of interactions is
-   *  generated.
-   *  -# Compute the number of interactions to generate in the event, using
-   *     the IPileUpTool.
-   *  -# Generate this number of interactions using the IProductionTool.
-   *     The IProductionTool indicates if a good event has been generated
-   *     (containing for example a B hadron).
-   *  -# Decay with the IDecayTool all particles in the event, if this is
-   *     a good event.
-   *  -# Apply the full event generator level cut (using IFullEventGenCutTool)
-   *     and accept or reject the event.
-   *  -# Store in event store the accepted event.
-   */
-  StatusCode execute   () override;
-
-  /** Algorithm finalization.
-   *  Print generation counters.
-   */
-  StatusCode finalize  () override;
-
-protected:
-  /// Decay the event with the IDecayTool.
-  StatusCode decayEvent( LHCb::HepMCEvent * theEvent ) ;
-
-private:
-  int          m_eventType ; ///< Event type (set by options)
-
-  /// Location where to store generator events (set by options)
-  std::string  m_hepMCEventLocation ;
-
-  /// Location where to store the Header of the events (set by options)
-  std::string  m_genHeaderLocation ;
-
-  /// Location where to store HardInfo (set by options)
-  std::string  m_genCollisionLocation ;
-
-  /// Location where to store FSR counters (set by options)
-  std::string  m_FSRName;
-
-  /// Reference to file records data service
-  IDataProviderSvc* m_fileRecordSvc;
-
-  IPileUpTool              * m_pileUpTool             ; ///< Pile-up tool
-
-  IDecayTool               * m_decayTool              ; ///< Decay tool
-
-  ICounterLogFile          * m_xmlLogTool             ; ///< Xml Log file tool
-
-  ISampleGenerationTool    * m_sampleGenerationTool   ; ///< Sample tool
-
-  IVertexSmearingTool      * m_vertexSmearingTool     ; ///< Smearing tool
-
-  IFullGenEventCutTool     * m_fullGenEventCutTool    ; ///< Cut tool
-
-  /// Name of the IPileUpTool (set by options).
-  std::string m_pileUpToolName           ;
-
-  /// Name of the ISampleGenerationTool - MinimumBias, ... (set by options)
-  std::string m_sampleGenerationToolName ;
-
-  /// Name of the IDecayTool (set by options)
-  std::string m_decayToolName            ;
-
-  /// Name of the IVertexSmearingTool (set by options)
-  std::string m_vertexSmearingToolName   ;
-
-  /// Name of the IFullGenEventCutTool (set by options)
-  std::string m_fullGenEventCutToolName  ;
-
-  /// Flag to generate all pile up events at the same PV (set by options)
-  bool m_commonVertex ;
-
-  unsigned int m_nEvents ; ///< Number of generated events
-
-  unsigned int m_nAcceptedEvents ; ///< Number of accepted events
-
-  unsigned int m_nInteractions ; ///< Number of generated interactions
-
-  /// Number of interactions in accepted events
-  unsigned int m_nAcceptedInteractions ;
-
-  /// Description of the counter index
-  enum interationCounterType{ Oneb = 0 , ///< interaction with >= 1 b quark
-                              Threeb , ///< interaction with >= 3 b quarks
-                              PromptB , ///< interaction with prompt B
-                              Onec , ///< interaction with >= 1 c quark
-                              Threec , ///< interaction with >= 3 c quarks
-                              PromptC , ///< interaction with prompt C
-                              bAndc ///< interaction with b and c
-  } ;
-
-  /// Type for interaction counter
-  typedef boost::array< unsigned int , 7 > interactionCounter ;
-  typedef boost::array< std::string  , 7 > interactionCNames  ;
-
-  /// Counter of content of generated interactions
-  interactionCounter m_intC ;
-
-  /// Array of counter names
-  interactionCNames  m_intCName ;
-
-  /// Counter of content of accepted interactions
-  interactionCounter m_intCAccepted ;
-
-  /// Array of accepted counter names
-  interactionCNames  m_intCAcceptedName ;
-
-  /// Counter of events before the full event generator level cut
-  unsigned int m_nBeforeFullEvent ;
-
-  /// Counter of events after the full event generator level cut
-  unsigned int m_nAfterFullEvent ;
-
-  /// TDS container
-  /// LHCb::GenFSRs* m_genFSRs;
-  /// FSR for current file
-  LHCb::GenFSR* m_genFSR;
-
-  /** Update the counters counting on interactions.
-   *  @param[in,out] theCounter Counter of events
-   *  @param[in]     theEvent  The interaction to study
-   */
-  void updateInteractionCounters( interactionCounter & theCounter ,
-                                  const LHCb::HepMCEvent * theEvent ) ;
-
-
-  /** Update the counters counting on interactions.
-   *  @param[in,out] m_genFSR     The counters in FSR
-   *  @param[in]     theCounter   The interaction counters
-   *  @param[in]     option       Separate generated and accepted counters
-   */
-  void updateFSRCounters( interactionCounter & theCounter ,
-                          LHCb::GenFSR * m_genFSR,
-                          const std::string option ) ;
-
-};
-#endif // GENERATORS_GENERATION_H
diff --git a/Gen/Generators/src/component/HistoSmearVertex.cpp b/Gen/Generators/src/component/HistoSmearVertex.cpp
deleted file mode 100755
index 6fcabe83b..000000000
--- a/Gen/Generators/src/component/HistoSmearVertex.cpp
+++ /dev/null
@@ -1,103 +0,0 @@
-// local
-#include "HistoSmearVertex.h"
-
-// from Gaudi
-#include "GaudiKernel/IRndmGenSvc.h"
-#include "GaudiKernel/PhysicalConstants.h"
-#include "GaudiKernel/Vector4DTypes.h"
-
-// from Event
-#include "Event/HepMCEvent.h"
-#include "TFile.h"
-#include "TH3.h"
-
-//-----------------------------------------------------------------------------
-// Implementation file for class : HistoSmearVertex
-//
-// 2014-08-02 : Dominik Mitzel
-//-----------------------------------------------------------------------------
-
-// Declaration of the Tool Factory
-DECLARE_COMPONENT( HistoSmearVertex )
-
-//=============================================================================
-// Standard constructor, initializes variables
-//=============================================================================
-HistoSmearVertex::HistoSmearVertex( const std::string& type,
-                                    const std::string& name,
-                                    const IInterface* parent )
-  : GaudiTool ( type, name , parent ) {
-    declareInterface< IVertexSmearingTool >( this ) ;
-    declareProperty("InputFileName", m_inputFileName = "");
-    declareProperty("HistogramPath", m_histoPath = "");
-    declareProperty("BeamDirection", m_zDir = 0 );
-}
-
-//=============================================================================
-// Destructor
-//=============================================================================
-HistoSmearVertex::~HistoSmearVertex( ) { ; }
-
-//=============================================================================
-// Initialize
-//=============================================================================
-StatusCode HistoSmearVertex::initialize( ) {
-  StatusCode sc = GaudiTool::initialize( ) ;
-  if ( sc.isFailure() ) return sc ;
-
-  // -- Open the file containing the VX distribution
-  TFile *file = TFile::Open( m_inputFileName.c_str() );
-  if( !file ){
-    error() << "Could not find vertex distribution template file!" << endmsg;
-    return StatusCode::FAILURE;
-  }
-
-  // -- Get the histogram template file for the particle momentum spectrum
-  m_hist = (TH3D*) file->Get( m_histoPath.c_str() );
-  if ( !m_hist ) {
-    error() << "Could not find vertex distribution template histogram!" << endmsg;
-    return StatusCode::FAILURE;
-  }
-
-  std::string infoMsg = " applying TOF of interaction with ";
-  if ( m_zDir == -1 ) {
-    infoMsg = infoMsg + "negative beam direction";
-  } else if ( m_zDir == 1 ) {
-    infoMsg = infoMsg + "positive beam direction";
-  } else if ( m_zDir == 0 ) {
-    infoMsg = " with TOF of interaction equal to zero ";
-  } else {
-    return Error("BeamDirection can only be set to -1 or 1, or 0 to switch off TOF");
-  }
-
-  info() << "Smearing of interaction point with external  distribution "
-         << " in x, y and z " << endmsg;
-  info() << infoMsg << endmsg;
-
-  return sc ;
-}
-
-//=============================================================================
-// Smearing function
-//=============================================================================
-StatusCode HistoSmearVertex::smearVertex( LHCb::HepMCEvent * theEvent ) {
-  double dx , dy , dz , dt ;
-  m_hist->GetRandom3(dx,dy,dz);
-
-  dt = m_zDir * dz/Gaudi::Units::c_light ;
-
-  Gaudi::LorentzVector dpos( dx , dy , dz , dt ) ;
-
-  HepMC::GenEvent::vertex_iterator vit ;
-  HepMC::GenEvent * pEvt = theEvent -> pGenEvt() ;
-  for ( vit = pEvt -> vertices_begin() ; vit != pEvt -> vertices_end() ;
-        ++vit ) {
-    Gaudi::LorentzVector pos ( (*vit) -> position() ) ;
-    pos += dpos ;
-    (*vit) -> set_position( HepMC::FourVector( pos.x() , pos.y() , pos.z() ,
-                                               pos.t() ) ) ;
-  }
-
-  return StatusCode::SUCCESS;
-}
-
diff --git a/Gen/Generators/src/component/HistoSmearVertex.h b/Gen/Generators/src/component/HistoSmearVertex.h
deleted file mode 100644
index 1a1731846..000000000
--- a/Gen/Generators/src/component/HistoSmearVertex.h
+++ /dev/null
@@ -1,40 +0,0 @@
-#ifndef HISTOSMEARVERTEX_H
-#define HISTOSMEARVERTEX_H 1
-
-// Include files
-#include "GaudiAlg/GaudiTool.h"
-#include "Generators/IVertexSmearingTool.h"
-#include "TH3.h"
-
-/** @class SmearVertex SmearVertex.h "SmearVertex.h"
- *
- *  Tool to smear vertex with external input distribution.
- *  Concrete implementation of a IVertexSmearingTool.
- *
- *  @author Dominik Mitzel
- *  @date   2014-08-02
- */
-class HistoSmearVertex : public GaudiTool, virtual public IVertexSmearingTool {
- public:
-  /// Standard constructor
-  HistoSmearVertex( const std::string& type , const std::string& name,
-                    const IInterface* parent ) ;
-  virtual ~HistoSmearVertex( ); ///< Destructor
-
-  /// Initialize method
-  StatusCode initialize( ) override;
-
-  /** Implements IVertexSmearingTool::smearVertex.
-   */
-  StatusCode smearVertex( LHCb::HepMCEvent * theEvent ) override;
-
- private:
-  /// Direction of the beam to take into account TOF vs nominal IP8, can have
-  /// only values -1 or 1, or 0 to switch off the TOF and set time of
-  /// interaction to zero (default = 1, as for beam 1)
-  int m_zDir;
-  TH3* m_hist;
-  std::string m_inputFileName;
-  std::string m_histoPath;
-};
-#endif // PARTICLEGUNS_SMEARVERTEX_H
diff --git a/Gen/Generators/src/component/IEvtGenTool.h b/Gen/Generators/src/component/IEvtGenTool.h
deleted file mode 100644
index f57eb2ccb..000000000
--- a/Gen/Generators/src/component/IEvtGenTool.h
+++ /dev/null
@@ -1,39 +0,0 @@
-#ifndef GENERATORS_IEVTGENTOOL_H
-#define GENERATORS_IEVTGENTOOL_H
-
-#include <string>
-//from Gaudi
-#include "GaudiKernel/IAlgTool.h"
-// from EvtGen
-#include "EvtGen/EvtGen.hh"
-
-/** @class IEvtGenTool IEvtGenTool.h "Generators/IEvtGenTool.h"
-  *
-  * Interface for containter tool for EvtGen
-  *
-  * @author Alex Shires
-  * @date 2011-10-28
-*/
-
-static const InterfaceID IID_IEvtGenTool( "IEvtGenTool", 1, 0 ) ;
-
-class IEvtGenTool : virtual public IAlgTool {
-  public:
-    static const InterfaceID& interfaceID() { return IID_IEvtGenTool ; }
-
-    /* return the pointer to EvtGen
-    */
-    virtual EvtGen * getEvtGen() = 0 ; 
-
-    /* set the EVtGen pointer
-    */
-    virtual void setEvtGen( EvtGen * ) = 0 ; 
-
-    /* return the initialisation status of
-     * EvtGen
-    */
-    virtual bool isInit() = 0 ;
-
-} ; 
-
-#endif // GENERATORS_IEVTGENTOOL_H
diff --git a/Gen/Generators/src/component/Inclusive.cpp b/Gen/Generators/src/component/Inclusive.cpp
deleted file mode 100755
index 36caa5477..000000000
--- a/Gen/Generators/src/component/Inclusive.cpp
+++ /dev/null
@@ -1,255 +0,0 @@
-// $Id: Inclusive.cpp,v 1.14 2008-07-04 08:51:29 robbep Exp $
-// Include files
-
-// local
-#include "Inclusive.h"
-
-// from Gaudi
-#include "Kernel/IParticlePropertySvc.h"
-#include "Kernel/ParticleProperty.h"
-
-// from Kernel
-#include "MCInterfaces/IGenCutTool.h"
-
-// from Generators
-#include "Generators/IProductionTool.h"
-#include "Generators/GenCounters.h"
-#include "Generators/ICounterLogFile.h"
-
-// from Event
-#include "Event/GenFSR.h"
-#include "Event/GenCountersFSR.h"
-
-//-----------------------------------------------------------------------------
-// Implementation file for class : Inclusive
-//
-// 2005-08-18 : Patrick Robbe
-//-----------------------------------------------------------------------------
-
-// Declaration of the Tool Factory
-
-DECLARE_COMPONENT( Inclusive )
-
-//=============================================================================
-// Standard constructor, initializes variables
-//=============================================================================
-Inclusive::Inclusive( const std::string& type, const std::string& name,
-                      const IInterface* parent )
-  : ExternalGenerator  ( type, name , parent ) ,
-    m_xmlLogTool( 0 ) ,
-    m_lightestQuark( LHCb::ParticleID::down ) ,
-    m_nEventsBeforeCut ( 0 ) , m_nEventsAfterCut ( 0 ) ,
-    m_nInvertedEvents  ( 0 ) ,
-    m_ccCounter        ( 0 ) , m_bbCounter( 0 ) ,
-    m_ccCounterAccepted( 0 ) , m_bbCounterAccepted( 0 ) {
-    declareProperty( "InclusivePIDList" , m_pidVector ) ;
-    m_bHadC.assign( 0 )     ;    m_bHadCAccepted.assign( 0 ) ;
-    m_antibHadC.assign( 0 ) ;    m_antibHadCAccepted.assign( 0 ) ;
-    m_cHadC.assign( 0 )     ;    m_cHadCAccepted.assign( 0 ) ;
-    m_anticHadC.assign( 0 ) ;    m_anticHadCAccepted.assign( 0 ) ;
-
-    m_bExcitedC.assign( 0 ) ;    m_bExcitedCAccepted.assign( 0 ) ;
-    m_cExcitedC.assign( 0 ) ;    m_cExcitedCAccepted.assign( 0 ) ;
-
-
-    GenCounters::setupBHadronCountersNames( m_bHadCNames , m_antibHadCNames ) ;
-    GenCounters::setupDHadronCountersNames( m_cHadCNames , m_anticHadCNames ) ;
-
-    GenCounters::setupExcitedCountersNames( m_bExcitedCNames , "B" ) ;
-    GenCounters::setupExcitedCountersNames( m_cExcitedCNames , "D" ) ;
-  }
-
-//=============================================================================
-// Destructor
-//=============================================================================
-Inclusive::~Inclusive( ) { ; }
-
-//=============================================================================
-// Initialize method
-//=============================================================================
-StatusCode Inclusive::initialize( ) {
-  StatusCode sc = ExternalGenerator::initialize( ) ;
-  if ( ! sc.isSuccess() ) return Error( "Cannot initialize base class !" ) ;
-
-  if ( m_pidVector.empty() )
-    return Error( "InclusivePIDList property is not set" ) ;
-
-  // Transform vector into set
-  for ( std::vector<int>::iterator it = m_pidVector.begin() ;
-        it != m_pidVector.end() ; ++it ) m_pids.insert( *it ) ;
-
-  LHCb::IParticlePropertySvc * ppSvc =
-    svc< LHCb::IParticlePropertySvc >( "LHCb::ParticlePropertySvc" ) ;
-
-  info() << "Generating Inclusive events of " ;
-  PIDs::const_iterator it ;
-  bool bottom( false ) , charm( false ) ;
-
-  for ( it = m_pids.begin() ; it != m_pids.end() ; ++it ) {
-    const LHCb::ParticleProperty * prop = ppSvc -> find( LHCb::ParticleID( *it ) ) ;
-    if ( 0 == prop )
-      warning() << "PDG Code " << (*it) << " does not exist." << endmsg ;
-    else {
-      info() << prop -> particle() << " " ;
-      if ( LHCb::ParticleID( prop -> pdgID() ).hasBottom() ) bottom = true ;
-      else if ( LHCb::ParticleID( prop -> pdgID() ).hasCharm()  ) charm  = true ;
-    }
-  }
-
-  if ( bottom && ! charm ) m_lightestQuark = LHCb::ParticleID::bottom ;
-  else if ( charm ) m_lightestQuark = LHCb::ParticleID::charm ;
-  else if (m_pids.size() > 2) return Error( "This case is not yet implemented" ) ;
-
-  info() << endmsg ;
-
-  // XML Log file
-  m_xmlLogTool = tool< ICounterLogFile >( "XmlCounterLogFile" ) ;
-
-  return sc ;
-}
-
-//=============================================================================
-// Generate Set of Event for Minimum Bias event type
-//=============================================================================
-bool Inclusive::generate( const unsigned int nPileUp ,
-                          LHCb::HepMCEvents * theEvents ,
-                          LHCb::GenCollisions * theCollisions ) {
-  StatusCode sc ;
-  bool result = false ;
-
-  LHCb::GenCollision * theGenCollision( 0 ) ;
-  HepMC::GenEvent * theGenEvent( 0 ) ;
-
-  GenCounters::BHadronCounter thebHadC , theantibHadC ;
-  GenCounters::DHadronCounter thecHadC , theanticHadC ;
-  GenCounters::ExcitedCounter thebExcitedC , thecExcitedC ;
-  unsigned int theccCounter , thebbCounter ;
-
-  LHCb::GenFSR* genFSR = nullptr;
-  if(m_FSRName != ""){
-    IDataProviderSvc* fileRecordSvc = svc<IDataProviderSvc>("FileRecordDataSvc", true);
-    genFSR = getIfExists<LHCb::GenFSR>(fileRecordSvc, m_FSRName, false);
-    if(!genFSR) warning() << "Could not find GenFSR at " << m_FSRName << endmsg;
-  }
-  int key = 0;
-
-  for ( unsigned int i = 0 ; i < nPileUp ; ++i ) {
-    prepareInteraction( theEvents , theCollisions , theGenEvent,
-                        theGenCollision ) ;
-
-    sc = m_productionTool -> generateEvent( theGenEvent , theGenCollision ) ;
-    if ( sc.isFailure() ) Exception( "Could not generate event" ) ;
-
-    if ( ! result ) {
-      // Decay particles heavier than the particles to look at
-      // If N hadrons <= 2, we assume it is (h,hbar)
-      // Passing m_pids[0] needed for incl. charmless bottomless hadron production
-      decayHeavyParticles( theGenEvent , m_lightestQuark , m_pids.size() > 2 ? 0 : *(m_pids.begin()) ) ;
-
-      // Check if one particle of the requested list is present in event
-      ParticleVector theParticleList ;
-      if ( checkPresence( m_pids , theGenEvent , theParticleList ) ) {
-        // Update counters
-        thebHadC.assign( 0 )     ;    theantibHadC.assign( 0 ) ;
-        thecHadC.assign( 0 )     ;    theanticHadC.assign( 0 ) ;
-        thebExcitedC.assign( 0 ) ;    thecExcitedC.assign( 0 ) ;
-
-        thebbCounter = 0         ;    theccCounter = 0 ;
-
-        GenCounters::updateHadronCounters( theGenEvent , thebHadC ,
-                                           theantibHadC , thecHadC ,
-                                           theanticHadC , thebbCounter ,
-                                           theccCounter ) ;
-        GenCounters::updateExcitedStatesCounters( theGenEvent , thebExcitedC ,
-                                                  thecExcitedC ) ;
-
-        // Accumulate counters
-        GenCounters::AddTo( m_bHadC , thebHadC ) ;
-        GenCounters::AddTo( m_antibHadC , theantibHadC ) ;
-        GenCounters::AddTo( m_cHadC , thecHadC ) ;
-        GenCounters::AddTo( m_anticHadC , theanticHadC ) ;
-
-        m_bbCounter += thebbCounter ;  m_ccCounter += theccCounter ;
-
-        GenCounters::AddTo( m_bExcitedC , thebExcitedC ) ;
-        GenCounters::AddTo( m_cExcitedC , thecExcitedC ) ;
-
-        if(genFSR) GenCounters::updateHadronFSR( theGenEvent, genFSR, "Gen");
-
-        ++m_nEventsBeforeCut ;
-        key = LHCb::GenCountersFSR::BeforeLevelCut;
-        if(genFSR) genFSR->incrementGenCounter(key, 1);
-        bool passCut = true ;
-        if ( 0 != m_cutTool )
-          passCut = m_cutTool -> applyCut( theParticleList , theGenEvent ,
-                                           theGenCollision ) ;
-
-        if ( passCut && ( ! theParticleList.empty() ) ) {
-          ++m_nEventsAfterCut ;
-          result = true ;
-
-          theGenCollision -> setIsSignal( true ) ;
-
-          if ( 0 == nPositivePz( theParticleList ) ) {
-            revertEvent( theGenEvent ) ;
-            ++m_nInvertedEvents ;
-            key = LHCb::GenCountersFSR::EvtInverted;
-            if(genFSR) genFSR->incrementGenCounter(key, 1);
-          }
-          else
-          {
-            key = LHCb::GenCountersFSR::AfterLevelCut;
-            if(genFSR) genFSR->incrementGenCounter(key, 1);
-          }
-
-          GenCounters::AddTo( m_bHadCAccepted , thebHadC ) ;
-          GenCounters::AddTo( m_antibHadCAccepted , theantibHadC ) ;
-          GenCounters::AddTo( m_cHadCAccepted , thecHadC ) ;
-          GenCounters::AddTo( m_anticHadCAccepted , theanticHadC ) ;
-
-          GenCounters::AddTo( m_bExcitedCAccepted , thebExcitedC ) ;
-          GenCounters::AddTo( m_cExcitedCAccepted , thecExcitedC ) ;
-
-          if(genFSR) GenCounters::updateHadronFSR( theGenEvent, genFSR, "Acc");
-        }
-      }
-    }
-  }
-
-  return result ;
-}
-
-//=============================================================================
-// Print the counters
-//=============================================================================
-void Inclusive::printCounters( ) const {
-  using namespace GenCounters ;
-
-  printEfficiency( m_xmlLogTool , "generator level cut" ,
-                   m_nEventsAfterCut - m_nInvertedEvents ,
-                   m_nEventsBeforeCut ) ;
-  printCounter( m_xmlLogTool , "z-inverted events" , m_nInvertedEvents ) ;
-
-  printArray( m_xmlLogTool , m_bHadC , m_bHadCNames , "generated" ) ;
-  printArray( m_xmlLogTool , m_antibHadC , m_antibHadCNames , "generated" ) ;
-  printCounter( m_xmlLogTool , "generated (bb)" , m_bbCounter ) ;
-
-  printArray( m_xmlLogTool , m_cHadC , m_cHadCNames , "generated" ) ;
-  printArray( m_xmlLogTool , m_anticHadC , m_anticHadCNames , "generated" ) ;
-  printCounter( m_xmlLogTool , "generated (cc)" , m_ccCounter ) ;
-
-  printArray( m_xmlLogTool , m_bHadCAccepted , m_bHadCNames , "accepted" ) ;
-  printArray( m_xmlLogTool , m_antibHadCAccepted , m_antibHadCNames , "accepted" ) ;
-  printCounter( m_xmlLogTool , "accepted (bb)" , m_bbCounterAccepted ) ;
-
-  printArray( m_xmlLogTool , m_cHadCAccepted , m_cHadCNames , "accepted" ) ;
-  printArray( m_xmlLogTool , m_anticHadCAccepted , m_anticHadCNames , "accepted" ) ;
-  printCounter( m_xmlLogTool , "accepted (cc)" , m_ccCounterAccepted ) ;
-
-  printArray( m_xmlLogTool , m_bExcitedC , m_bExcitedCNames , "generated" ) ;
-  printArray( m_xmlLogTool , m_bExcitedCAccepted , m_bExcitedCNames , "accepted" ) ;
-
-  printArray( m_xmlLogTool , m_cExcitedC , m_cExcitedCNames , "generated" ) ;
-  printArray( m_xmlLogTool , m_cExcitedCAccepted , m_cExcitedCNames , "accepted" ) ;
-}
-
diff --git a/Gen/Generators/src/component/Inclusive.h b/Gen/Generators/src/component/Inclusive.h
deleted file mode 100755
index 7bfc2c7c2..000000000
--- a/Gen/Generators/src/component/Inclusive.h
+++ /dev/null
@@ -1,148 +0,0 @@
-// $Id: Inclusive.h,v 1.7 2006-02-17 13:26:44 robbep Exp $
-#ifndef GENERATORS_INCLUSIVE_H
-#define GENERATORS_INCLUSIVE_H 1
-
-// Include files
-// from Gaudi
-#include "GaudiAlg/GaudiTool.h"
-
-#include "Generators/ExternalGenerator.h"
-
-#include "Generators/GenCounters.h"
-
-#include <boost/array.hpp>
-
-// forward declarations
-
-namespace HepMC {
-  class GenParticle ;
-}
-
-class ICounterLogFile ;
-
-/** @class Inclusive Inclusive.h "Inclusive.h"
- *
- *  Tool for inclusive samples generation. The particles to
- *  request are specified by their PDG Id in a list. Concrete
- *  implementation of a ISampleGenerationTool using the
- *  ExternalGenerator base class.
- *
- *  @author Patrick Robbe
- *  @date   2005-08-18
- */
-class Inclusive : public ExternalGenerator {
- public:
-  /// Standard constructor
-  Inclusive( const std::string& type, const std::string& name,
-             const IInterface* parent);
-
-  virtual ~Inclusive( ); ///< Destructor
-
-  /** Initialize method
-   *  Find the lightest particle among the requested particles.
-   *  When generating events, all particles heavier than this mass
-   *  will be decayed with the IDecayTool before the event is analyzed
-   *  to see if it contains particles of the inclusive list.
-   */
-  StatusCode initialize( ) override;
-
-  /** Generate a set of interactions.
-   *  Implements ISampleGenerationTool::generate.
-   *  -# Generate interactions using the IProductionTool
-   *  -# Check if the interaction has a particle specified in
-   *     the PID list
-   *  -# Apply the IGenCutTool on the interaction containing
-   *     a particle of the list.
-   *  -# Parity-flip the event (z -> -z, pz -> -pz) if all particles
-   *     of the inclusive list in the event have pz < 0.
-   */
-  bool generate( const unsigned int nPileUp ,
-                 LHCb::HepMCEvents * theEvents ,
-                 LHCb::GenCollisions * theCollisions ) override;
-
-  /** Print generation counters.
-   *  Implements ISampleGenerationTool::printCounters.
-   *  Prints (after generator level cuts):
-   *  -# Fractions of B0/B+/B0s/Bc/b-Baryons (and idem for D) in
-   *     selected events.
-   *  -# Fractions of B/Bstar/Bdoublestar in selected events.
-   */
-  void printCounters( ) const override;
-
- protected:
-
- private:
-  ICounterLogFile * m_xmlLogTool ; ///< XML log file for counters
-
-  /// Type of lightest quark in list of particles to produce
-  LHCb::ParticleID::Quark      m_lightestQuark     ;
-
-  /// Counter of events before applying generator level cut
-  unsigned int  m_nEventsBeforeCut ;
-
-  /// Counter of events after applying generator level cut
-  unsigned int  m_nEventsAfterCut  ;
-
-  /// Counter of parity-flipped events (z -> -z, pz -> -pz)
-  unsigned int  m_nInvertedEvents  ;
-
-  /// Ordered set of PDG Id of particles to produce (set by options)
-  PIDs          m_pids             ;
-
-  /// Vector to obtain list of PDG Ids from job options
-  std::vector< int > m_pidVector   ;
-
-  GenCounters::BHadronCounter m_bHadC ;  ///< Counter of B hadron (generated)
-
-  GenCounters::BHadronCounter m_antibHadC ; ///< Counter of Bbar hadron (gen)
-
-  /// Counter of B hadron (accepted)
-  GenCounters::BHadronCounter m_bHadCAccepted ;
-
-  /// Counter of anti-B hadron (accepted)
-  GenCounters::BHadronCounter m_antibHadCAccepted ;
-
-  GenCounters::BHadronCNames m_bHadCNames ; ///< Array of B counter names
-
-  /// Array of anti-B hadrons names
-  GenCounters::BHadronCNames m_antibHadCNames ;
-
-  GenCounters::DHadronCounter m_cHadC ; ///< Counter of D hadron (generated)
-
-  GenCounters::DHadronCounter m_anticHadC ; ///< Counter of Dbar hadron (gen)
-
-  /// Counter of D hadron (accepted)
-  GenCounters::DHadronCounter m_cHadCAccepted ;
-
-  /// Counter of D hadron (accepted)
-  GenCounters::DHadronCounter m_anticHadCAccepted ;
-
-  /// Array of D counter names
-  GenCounters::DHadronCNames m_cHadCNames ;
-
-  /// Array of anti-D counter names
-  GenCounters::DHadronCNames m_anticHadCNames ;
-
-  unsigned int m_ccCounter ; ///< Counter for cc quarkonium (generated)
-
-  unsigned int m_bbCounter ; ///< Counter for bb quarkonium (generated)
-
-  unsigned int m_ccCounterAccepted ; ///< Counter for cc (accepted)
-
-  unsigned int m_bbCounterAccepted ; ///<< Counter for bb (accepted)
-
-  GenCounters::ExcitedCounter m_bExcitedC ; ///< Counter of B(**) (generated)
-
-  GenCounters::ExcitedCounter m_cExcitedC ; ///< Counter of D(**) (generated)
-
-  /// Counter of B(**) (accepted)
-  GenCounters::ExcitedCounter m_bExcitedCAccepted ;
-
-  /// Counter of D(**) (accepted)
-  GenCounters::ExcitedCounter m_cExcitedCAccepted ;
-
-  GenCounters::ExcitedCNames m_bExcitedCNames ; ///< Names excited B counters
-
-  GenCounters::ExcitedCNames m_cExcitedCNames ; ///< Names excited D counters
-};
-#endif // GENERATORS_INCLUSIVE_H
diff --git a/Gen/Generators/src/component/MergedEventsFilter.cpp b/Gen/Generators/src/component/MergedEventsFilter.cpp
deleted file mode 100755
index f51421e37..000000000
--- a/Gen/Generators/src/component/MergedEventsFilter.cpp
+++ /dev/null
@@ -1,108 +0,0 @@
-// $Id: MergedEventsFilter.cpp,v 1.1 2008-05-06 08:27:55 gcorti Exp $
-// Include files 
-
-// from Gaudi
-
-// from LHCb
-#include "Event/GenHeader.h"
-#include "Event/GenCollision.h"
-
-// from Kernel
-#include "MCInterfaces/IFullGenEventCutTool.h"
-
-// local
-#include "MergedEventsFilter.h"
-
-//-----------------------------------------------------------------------------
-// Implementation file for class : MergedEventsFilter
-//
-// 2008-04-30 : Gloria CORTI
-//-----------------------------------------------------------------------------
-
-// Declaration of the Algorithm Factory
-DECLARE_COMPONENT( MergedEventsFilter )
-
-
-//=============================================================================
-// Standard constructor, initializes variables
-//=============================================================================
-MergedEventsFilter::MergedEventsFilter( const std::string& name,
-                                        ISvcLocator* pSvcLocator)
-  : GaudiAlgorithm ( name , pSvcLocator )
-  , m_fullGenEventCutTool  ( 0 )
-{
-  
-    // Tool name to cut on full event
-    declareProperty( "FullGenEventCutTool" , 
-                     m_fullGenEventCutToolName = "" ) ;
-    // Location of the input from the generation
-    declareProperty ( "HepMCEventLocation" , m_hepMCEventLocation = 
-                      LHCb::HepMCEventLocation::Default ) ;
-    declareProperty ( "GenCollisionLocation" , m_genCollisionLocation = 
-                      LHCb::GenCollisionLocation::Default ) ;
-    
-}
-//=============================================================================
-// Destructor
-//=============================================================================
-MergedEventsFilter::~MergedEventsFilter() {} 
-
-//=============================================================================
-// Initialization
-//=============================================================================
-StatusCode MergedEventsFilter::initialize() {
-  StatusCode sc = GaudiAlgorithm::initialize(); // must be executed first
-  if ( sc.isFailure() ) return sc;  // error printed already by GaudiAlgorithm
-
-  if ( msgLevel(MSG::DEBUG) ) debug() << "==> Initialize" << endmsg;
-
-  // Retrieve full gen event cut tool
-  if ( "" != m_fullGenEventCutToolName ) {
-    m_fullGenEventCutTool =
-      tool< IFullGenEventCutTool >( m_fullGenEventCutToolName , this ) ;
-  }
-  else {
-    info() << "Filter does not have a cut::: MUST be specified!!!" << endmsg;
-    return StatusCode::FAILURE;
-  }
-
-  return StatusCode::SUCCESS;
-}
-
-//=============================================================================
-// Main execution
-//=============================================================================
-StatusCode MergedEventsFilter::execute() {
-
-  if ( msgLevel(MSG::DEBUG) ) debug() << "==> Execute" << endmsg;
-
-  // Retrieve info from the TES
-  LHCb::HepMCEvents* theEvents = 
-    get<LHCb::HepMCEvents>( m_hepMCEventLocation );
-
-  LHCb::GenCollisions* theCollisions = 
-    get<LHCb::GenCollisions>( m_genCollisionLocation );
-  
-
-  // Apply generator level cut on full event
-  bool goodEvent = true;
-  
-  //  ++m_nBeforeFullEvent ;
-  goodEvent = m_fullGenEventCutTool->studyFullEvent( theEvents, theCollisions );
-  // put counters
-  setFilterPassed(goodEvent);
-  
-  return StatusCode::SUCCESS;
-}
-
-//=============================================================================
-//  Finalize
-//=============================================================================
-StatusCode MergedEventsFilter::finalize() {
-
-  if ( msgLevel(MSG::DEBUG) ) debug() << "==> Finalize" << endmsg;
-
-  return GaudiAlgorithm::finalize();  // must be called after all other actions
-}
-
-//=============================================================================
diff --git a/Gen/Generators/src/component/MergedEventsFilter.h b/Gen/Generators/src/component/MergedEventsFilter.h
deleted file mode 100755
index a17ad3ca7..000000000
--- a/Gen/Generators/src/component/MergedEventsFilter.h
+++ /dev/null
@@ -1,39 +0,0 @@
-// $Id: MergedEventsFilter.h,v 1.1 2008-05-06 08:27:55 gcorti Exp $
-#ifndef GENERATORS_MERGEDEVENTSFILTER_H
-#define GENERATORS_MERGEDEVENTSFILTER_H 1
-
-// Include files
-// from Gaudi
-#include "GaudiAlg/GaudiAlgorithm.h"
-
-class IFullGenEventCutTool;
-
-/** @class MergedEventsFilter MergedEventsFilter.h component/MergedEventsFilter.h
- *
- *
- *  @author Gloria CORTI
- *  @date   2008-04-30
- */
-class MergedEventsFilter : public GaudiAlgorithm {
-public:
-  /// Standard constructor
-  MergedEventsFilter( const std::string& name, ISvcLocator* pSvcLocator );
-
-  virtual ~MergedEventsFilter( ); ///< Destructor
-
-  StatusCode initialize() override;    ///< Algorithm initialization
-  StatusCode execute   () override;    ///< Algorithm execution
-  StatusCode finalize  () override;    ///< Algorithm finalization
-
-protected:
-
-private:
-
-  std::string  m_hepMCEventLocation ;    ///< Input TES for HepMC events
-  std::string  m_genCollisionLocation ;  ///< Input TES for GenCollisions
-
-  std::string           m_fullGenEventCutToolName; ///< Name of event cut tool
-  IFullGenEventCutTool* m_fullGenEventCutTool;     ///< Pointer to event cut tool
-
-};
-#endif // GENERATORS_MERGEDEVENTSFILTER_H
diff --git a/Gen/Generators/src/component/MinimumBias.cpp b/Gen/Generators/src/component/MinimumBias.cpp
deleted file mode 100755
index 122bb0977..000000000
--- a/Gen/Generators/src/component/MinimumBias.cpp
+++ /dev/null
@@ -1,63 +0,0 @@
-// $Id: MinimumBias.cpp,v 1.4 2007-01-12 15:17:38 ranjard Exp $
-// Include files 
-
-// local
-#include "MinimumBias.h"
-// from Gaudi
-
-#include "Generators/IProductionTool.h"
-
-// Event 
-#include "Event/HepMCEvent.h"
-#include "Event/GenCollision.h"
-
-//-----------------------------------------------------------------------------
-// Implementation file for class : MinimumBias
-//
-// 2005-08-18 : Patrick Robbe
-//-----------------------------------------------------------------------------
-
-// Declaration of the Tool Factory
-
-DECLARE_COMPONENT( MinimumBias )
-
-
-//=============================================================================
-// Standard constructor, initializes variables
-//=============================================================================
-MinimumBias::MinimumBias( const std::string & type , const std::string & name,
-                          const IInterface * parent )
-  : ExternalGenerator( type, name , parent ) { }
-
-//=============================================================================
-// Destructor
-//=============================================================================
-MinimumBias::~MinimumBias( ) { ; }
-
-//=============================================================================
-// Initialize method
-//=============================================================================
-StatusCode MinimumBias::initialize( ) {
-  info() << "Generating Minimum Bias events." << endmsg ;
-  return ExternalGenerator::initialize( ) ;
-}
-
-//=============================================================================
-// Generate Set of Event for Minimum Bias event type
-//=============================================================================
-bool MinimumBias::generate( const unsigned int nPileUp , 
-                            LHCb::HepMCEvents * theEvents , 
-                            LHCb::GenCollisions * theCollisions ) {
-  StatusCode sc ;
-  LHCb::GenCollision * theGenCollision( 0 ) ;
-  HepMC::GenEvent * theGenEvent( 0 ) ;
-  
-  for ( unsigned int i = 0 ; i < nPileUp ; ++i ) {
-    prepareInteraction( theEvents , theCollisions , theGenEvent , 
-                        theGenCollision ) ;
-    
-    sc = m_productionTool -> generateEvent( theGenEvent , theGenCollision ) ;
-    if ( sc.isFailure() ) Exception( "Could not generate event" ) ;
-  } 
-  return true ;
-}
diff --git a/Gen/Generators/src/component/MinimumBias.h b/Gen/Generators/src/component/MinimumBias.h
deleted file mode 100755
index 62f79c474..000000000
--- a/Gen/Generators/src/component/MinimumBias.h
+++ /dev/null
@@ -1,39 +0,0 @@
-// $Id: MinimumBias.h,v 1.3 2005-12-31 17:33:12 robbep Exp $
-#ifndef GENERATORS_MINIMUMBIAS_H
-#define GENERATORS_MINIMUMBIAS_H 1
-
-// Include files
-// from Gaudi
-#include "GaudiAlg/GaudiTool.h"
-#include "Generators/ExternalGenerator.h"
-
-/** @class MinimumBias MinimumBias.h "MinimumBias.h"
- *
- *  Tool for minimum bias generation. Concrete implementation
- *  of ISampleGenerationTool using the base class ExternalGenerator.
- *
- *  @author Patrick Robbe
- *  @date   2005-08-18
- */
-class MinimumBias : public ExternalGenerator {
- public:
-  /// Standard constructor
-  MinimumBias( const std::string & type , const std::string & name ,
-               const IInterface * parent ) ;
-
-  virtual ~MinimumBias( ); ///< Destructor
-
-  /// Initialize method
-  StatusCode initialize( ) override;
-
-  /** Generate minimum bias interactions without any cut.
-   *  Implements ISampleGeneratorTool::generate.
-   */
-  bool generate( const unsigned int nPileUp ,
-                 LHCb::HepMCEvents * theEvents ,
-                 LHCb::GenCollisions * theCollisions ) override;
-
-  /// Implements ISampleGeneratorTool::printCounters
-  void printCounters( ) const override { ; }
-};
-#endif // GENERATORS_MINIMUMBIAS_H
diff --git a/Gen/Generators/src/component/ReadHepMCAsciiFile.cpp b/Gen/Generators/src/component/ReadHepMCAsciiFile.cpp
deleted file mode 100755
index 3a8f4fe1c..000000000
--- a/Gen/Generators/src/component/ReadHepMCAsciiFile.cpp
+++ /dev/null
@@ -1,201 +0,0 @@
-// $Id: ReadHepMCAsciiFile.cpp,v 1.5 2009-03-02 12:12:35 robbep Exp $
-// ===========================================================================
-// Include files
-// ===========================================================================
-// GaudiKernel
-// ===========================================================================
-#include "GaudiKernel/SystemOfUnits.h"
-#include "GaudiKernel/PhysicalConstants.h"
-// ===========================================================================
-// GaudiAlg
-// ===========================================================================
-#include "GaudiAlg/GaudiTool.h"
-// ===========================================================================
-// Generators
-// ===========================================================================
-#include "Generators/IProductionTool.h"
-// ===========================================================================
-// HepMC
-// ===========================================================================
-#include "HepMC/IO_GenEvent.h"
-#include "HepMC/Units.h"
-// ===========================================================================
-/** @class ReadHepMCAsciiFile ReadHepMCAsciiFile.cpp
- *
- *  Simple "production tool", which actually reads HepMC events
- *  from  ascii input file. The tool could be useful to read
- *  information from external generators, if their integration
- *  into Gauss is impossible, difficult or not needed.
- *
- *  The tool has 2 properties:
- *
- *    - <c>Input</c>  : The name of input fiel in HepMC Ascii format
- *                    ( the default value is <c>""</c> (empty string))
- *    - <c>Rescale<c> : Boolean flag to rescal the input event from
- *                     Pythia units to LHCb units.
- *                     The default value is <c>true</c>.
- *
- *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
- *  @date 2005-10-05
- */
-class ReadHepMCAsciiFile
-  :         public       GaudiTool
-  , virtual public IProductionTool
-{
-public:
-  /// initialization of the tool
-  StatusCode initialize () override
-  {
-    StatusCode sc = GaudiTool::initialize () ;
-    if ( sc.isFailure() ) { return sc ; }
-    /// check the output file
-    if ( m_input.empty() )
-    { return Error ( "Input file name is not specified!" ) ; }
-    // open the file
-    m_file = new HepMC::IO_GenEvent ( m_input.c_str() , std::ios::in ) ;
-    //
-    if ( ( 0 == m_file ) || ( m_file->rdstate() == std::ios::failbit ) )
-    { return Error ( "Failure to input the file '"+m_input+"'" ) ; }
-    //
-    return StatusCode::SUCCESS ;
-  }
-  /// finalization of the tool
-  StatusCode finalize   () override
-  {
-    // delete the stream  (close the file!)
-    if ( 0 != m_file ) { delete m_file ; m_file = 0 ; }
-    // finalize the base class ;
-    return GaudiTool::finalize() ;
-  }
-public:
-  StatusCode initializeGenerator() override { return StatusCode::SUCCESS ; }
-
-  // ===================================================================
-  /** Generate a primary interaction.
-   *  The generated event contains all what happens up to the decay of
-   *  hadrons. Decay of hadrons will be performed in general by the decay
-   *  tool. Then all hadrons must be declared stable in the production
-   *  generator. This is done thanks to IProductionTool::setStable.
-   *  @param[out] theEvent  Event generated by the production generator.
-   *  @param[out] theInfo   Informations about the hard process of the
-   *                        generated interaction.
-   */
-  StatusCode generateEvent
-  ( HepMC::GenEvent    * theEvent ,
-    LHCb::GenCollision * theInfo  ) override;
-  // ===================================================================
-  /// Declare a particle stable to the production generator.
-  void setStable
-  ( const LHCb::ParticleProperty * /* thePP */ ) override { }
-  // ===================================================================
-  /** Update the properties of the particle in the production generator
-   *  with values from the particle property service.
-   */
-  // ===================================================================
-  void updateParticleProperties
-  ( const LHCb::ParticleProperty * /* thePP */ ) override {};
-  // ===================================================================
-  /// Turn off the fragmentation step in the generation.
-  void turnOffFragmentation  ( ) override {} ;
-  // ===================================================================
-  /// Turn on the fragmentation step in the generation.
-  void turnOnFragmentation   ( )  override {}  ;
-  // ===================================================================
-  /** Hadronize the event.
-   *  @param[in,out] theEvent  Unfragmented event to hadronize.
-   *  @param[out]    theInfo   Informations about the hard process of the
-   *                           generated interaction.
-   */
-  StatusCode hadronize
-  ( HepMC::GenEvent*     /* theEvent */ ,
-    LHCb::GenCollision * /* theInfo  */ ) override { return StatusCode::SUCCESS ; }
-  // ===================================================================
-  /// Save the parton level event (when the fragmentation is turned off)
-  void savePartonEvent
-  ( HepMC::GenEvent * /* theEvent */ ) override {} ;
-  // ===================================================================
-  /// Retrieve the previously saved parton event to re-hadronize it.
-  void retrievePartonEvent
-  ( HepMC::GenEvent* /* theEvent */ ) override {} ;
-  // ===================================================================
-  /// Print configuration of production generator
-  void printRunningConditions( ) override {} ;
-  // ===================================================================
-  /** Define special particles whose properties must not be updated from
-   *  the particle property service (like mass of top quark, ...)
-   */
-  bool isSpecialParticle
-  ( const LHCb::ParticleProperty* /* thePP */ ) const override { return true ; }
-  // ===================================================================
-  /// Prepare the generator to force fragmentationto in the thePdgId flavour.
-  StatusCode setupForcedFragmentation
-  ( const int /* thePdgId */ ) override { return StatusCode::SUCCESS ; };
-  // ===================================================================
-  /** standard constructor
-   *  @param type tool type(?)
-   *  @param name tool name
-   *  @param parent parent  component
-   */
-  ReadHepMCAsciiFile
-  ( const std::string& type,
-    const std::string& name,
-    const IInterface* parent )
-    : GaudiTool ( type , name , parent )
-    // no default
-    , m_input () ///< no default input file name
-    // the fiel itself
-    , m_file    ( 0    ) ///< the fiel itself
-  {
-    declareInterface<IProductionTool> ( this ) ;
-
-    declareProperty  ( "Input"   , m_input   ) ;
-  }
- virtual ~ReadHepMCAsciiFile()
-  {
-    // delete the stream  (close the file!)
-    if ( 0 != m_file ) { delete m_file ; m_file = 0 ; }
-  };
-private:
-  // the name of the input file
-  std::string      m_input ; ///< the name of the input file
-  // rescale event from Pythia to LHCb units ?
-  // the output file ;
-  HepMC::IO_GenEvent* m_file   ; ///< the input file ;
-} ;
-// =====================================================================
-/// Declaration of the Tool Factory
-// =====================================================================
-DECLARE_COMPONENT( ReadHepMCAsciiFile )
-// =====================================================================
-/** Generate a primary interaction.
- *  The generated event contains all what happens up to the decay of
- *  hadrons. Decay of hadrons will be performed in general by the decay
- *  tool. Then all hadrons must be declared stable in the production
- *  generator. This is done thanks to IProductionTool::setStable.
- *  @param[out] theEvent  Event generated by the production generator.
- *  @param[out] theInfo   Informations about the hard process of the
- *                        generated interaction.
- */
-
-// ===================================================================
-StatusCode ReadHepMCAsciiFile::generateEvent
-( HepMC::GenEvent    *    theEvent ,
-  LHCb::GenCollision * /* theInfo */ )
-{
-  Assert ( 0 != m_file , "Invalid input file!" ) ;
-  //
-  if ( !m_file->fill_next_event( theEvent ) )
-  { if ( m_file -> rdstate() != std::ios::eofbit )
-	return Error ( "Error in event reading!" ) ;
-    else return Error( "No more events in input file, set correct number of events in options" ) ;
-    ;
-  }
-  theEvent->use_units(HepMC::Units::MEV, HepMC::Units::MM);
-  //
-  return StatusCode::SUCCESS ;
-}
-
-
-// =====================================================================
-// The END
-// =====================================================================
diff --git a/Gen/Generators/src/component/RepeatDecay.cpp b/Gen/Generators/src/component/RepeatDecay.cpp
deleted file mode 100755
index 9d401496d..000000000
--- a/Gen/Generators/src/component/RepeatDecay.cpp
+++ /dev/null
@@ -1,164 +0,0 @@
-// $Id: RepeatDecay.cpp,v 1.1 2007-04-01 21:28:12 robbep Exp $
-// Include files 
-
-// local
-#include "RepeatDecay.h"
-
-// from Gaudi
-
-// from Generators
-#include "Generators/ISampleGenerationTool.h"
-#include "GenEvent/HepMCUtils.h"
-
-//-----------------------------------------------------------------------------
-// Implementation file for class : RepeatDecay
-//
-// 2005-08-18 : Patrick Robbe
-//-----------------------------------------------------------------------------
-
-// Declaration of the Tool Factory
-
-DECLARE_COMPONENT( RepeatDecay )
-
-//=======================================================
-// Standard constructor, initializes variables
-//=======================================================
-RepeatDecay::RepeatDecay( const std::string& type, 
-                          const std::string& name,
-                          const IInterface* parent )
-  : GaudiTool  ( type, name , parent )  ,
-    m_baseTool( 0 ) ,
-    m_nRedecay( 0 )  { 
-  declareInterface< ISampleGenerationTool >( this ) ;
-  declareProperty( "BaseTool" , m_baseToolName = "Inclusive" ) ;
-  declareProperty( "NRedecay" , m_nRedecayLimit = 50 ) ;
-}
-
-//=======================================================
-// Destructor
-//=======================================================
-RepeatDecay::~RepeatDecay( ) { ; }
-
-//=======================================================
-// Initialize method
-//=======================================================
-StatusCode RepeatDecay::initialize( ) {
-  StatusCode sc = GaudiTool::initialize( ) ;
-  if ( ! sc.isSuccess() ) return Error( "Cannot initialize base class !" ) ;
-
-  if ( "" == m_baseToolName ) 
-    return Error( "No name given for Base Tool" ) ;
-
-  info() << "Generating repeated events using base events of type "
-         << m_baseToolName << endmsg ;
-
-  m_baseTool = tool< ISampleGenerationTool >( m_baseToolName , this ) ;
-
-  m_theMemorizedEvents.clear() ;
-  m_theMemorizedCollisions.clear() ;
-
-  return sc ;
-}
-
-//===================================================
-// Generate Set of Event for Minimum Bias event type
-//===================================================
-bool RepeatDecay::generate( const unsigned int nPileUp , 
-                            LHCb::HepMCEvents * theEvents , 
-                            LHCb::GenCollisions * theCollisions ) {
-  bool result = false ;
-
-  if ( ( m_theMemorizedEvents.empty() ) || 
-       ( m_nRedecay > m_nRedecayLimit ) ) {
-    m_theMemorizedEvents.clear() ;
-    m_theMemorizedCollisions.clear() ;
-    m_nRedecay = 0 ;
-    
-    result = m_baseTool -> generate( nPileUp , theEvents , theCollisions ) ;  
-    if ( result ) {
-      // Erase decays before storing the event
-      LHCb::HepMCEvents::iterator it ;
-      std::vector< HepMC::GenParticle * > eraseList ;
-      
-      for ( it = theEvents -> begin() ; it != theEvents -> end() ; ++it ) {
-        HepMC::GenEvent * ev = (*it) -> pGenEvt() ;
-        for ( HepMC::GenEvent::particle_iterator itP = ev -> particles_begin()
-                ; itP != ev -> particles_end() ; ++itP ) {
-          if ( LHCb::HepMCEvent::DecayedByDecayGenAndProducedByProdGen ==
-               (*itP) -> status() )
-            eraseList.push_back( (*itP) ) ;
-        }
-      }
-      
-      for ( std::vector< HepMC::GenParticle * >::iterator part = 
-              eraseList.begin() ;
-            part != eraseList.end() ; ++part ) 
-        HepMCUtils::RemoveDaughters( (*part) ) ;
-
-      copyEvents( theEvents , &m_theMemorizedEvents ) ;
-      copyCollisions( theCollisions , &m_theMemorizedCollisions , theEvents ) ;
-    }
-  } else {
-    ++m_nRedecay ;
-    
-    copyEvents( &m_theMemorizedEvents , theEvents ) ;
-    copyCollisions( &m_theMemorizedCollisions , theCollisions , 
-                    &m_theMemorizedEvents ) ;
-    result = true ;
-  }
-  
-  return result ;
-}
-
-//===================================================
-// Print the counters
-//===================================================
-void RepeatDecay::printCounters( ) const {
-  m_baseTool -> printCounters() ;
-}
-
-//===================================================
-// Copy a HepMCEvent to another
-//===================================================
-void RepeatDecay::copyEvents( LHCb::HepMCEvents * from , 
-                              LHCb::HepMCEvents * to ) {
-  // Erase the event where to copy
-  to -> clear() ;
-
-  LHCb::HepMCEvents::iterator it ;
-  for ( it = from -> begin() ; it != from -> end() ; ++it ) {
-    LHCb::HepMCEvent * theHepMCEvent = new LHCb::HepMCEvent( ) ;
-    theHepMCEvent -> setGeneratorName( (*it) -> generatorName() ) ;
-    (*theHepMCEvent -> pGenEvt()) = (*(*it) -> pGenEvt()) ;
-    to -> insert( theHepMCEvent ) ;
-  } 
-}
-
-//===================================================
-// Copy a HepMCEvent to another
-//===================================================
-void RepeatDecay::copyCollisions( LHCb::GenCollisions * from , 
-                                  LHCb::GenCollisions * to ,
-                                  LHCb::HepMCEvents * theEvents ) {
-  // Erase the event where to copy
-  to -> clear() ;
-
-  LHCb::GenCollisions::iterator it ;
-  LHCb::HepMCEvents::iterator itEvents = theEvents -> begin() ;
-  
-  for ( it = from -> begin() ; it != from -> end() ; ++it ) {
-    LHCb::GenCollision * theGenCollision = new LHCb::GenCollision( ) ;
-    theGenCollision -> setIsSignal( (*it) -> isSignal() ) ;
-    theGenCollision -> setProcessType( (*it) -> processType() ) ;
-    theGenCollision -> setSHat( (*it) -> sHat() ) ;
-    theGenCollision -> setTHat( (*it) -> tHat() ) ;
-    theGenCollision -> setUHat( (*it) -> uHat() ) ;
-    theGenCollision -> setPtHat( (*it) -> ptHat() ) ;
-    theGenCollision -> setX1Bjorken( (*it) -> x1Bjorken() ) ;
-    theGenCollision -> setX2Bjorken( (*it) -> x2Bjorken() ) ;
-    theGenCollision -> setEvent( (*itEvents) ) ;
-    
-    to -> insert( theGenCollision ) ;
-    ++itEvents ;
-  } 
-}
diff --git a/Gen/Generators/src/component/RepeatDecay.h b/Gen/Generators/src/component/RepeatDecay.h
deleted file mode 100755
index f15906c41..000000000
--- a/Gen/Generators/src/component/RepeatDecay.h
+++ /dev/null
@@ -1,89 +0,0 @@
-// $Id: RepeatDecay.h,v 1.1 2007-04-01 21:28:12 robbep Exp $
-#ifndef GENERATORS_REPEATDECAY_H
-#define GENERATORS_REPEATDECAY_H 1
-
-// Include files
-// from Gaudi
-#include "GaudiAlg/GaudiTool.h"
-
-#include "Generators/ISampleGenerationTool.h"
-
-// forward declarations
-
-namespace HepMC {
-  class GenParticle ;
-}
-
-/** @class RepeatDecay RepeatDecay.h "RepeatDecay.h"
- *
- *  Tool for the generation of samples re-using the same event
- *  several times and re-decaying it only. When an event has been found
- *  passing the generator level cut, it is kept and re-decayed several times
- *  (applying again the same cut on it).
- *  Concrete implementation of a ISampleGenerationTool .
- *
- *  @author Patrick Robbe
- *  @date   2007-03-31
- */
-class RepeatDecay : public GaudiTool ,
-                    virtual public ISampleGenerationTool  {
- public:
-  /// Standard constructor
-  RepeatDecay( const std::string& type, const std::string& name,
-             const IInterface* parent);
-
-  virtual ~RepeatDecay( ); ///< Destructor
-
-  /** Initialize method
-   */
-  StatusCode initialize( ) override;
-
-  /** Generate a set of interactions.
-   *  Implements ISampleGenerationTool::generate.
-   *  -# Generate a set of interactions with the ISampleGenerationTool,
-   *       if there is no event in memory or the same event has been re-used
-   *       too many times.
-   *  -# If there is an event in memory, just erase the particles in it.
-   */
-  bool generate( const unsigned int nPileUp ,
-                 LHCb::HepMCEvents * theEvents ,
-                 LHCb::GenCollisions * theCollisions ) override;
-
-  /** Print generation counters.
-   *  Implements ISampleGenerationTool::printCounters.
-   */
-  void printCounters( ) const override;
-
- protected:
-
- private:
-
-  /// Name of the tool used to generate the events (set by option)
-  std::string m_baseToolName ;
-
-  /// Tool used to generate the base events which are re-decayed
-  ISampleGenerationTool * m_baseTool ;
-
-  /// Number of times to redecay the events (set by option)
-  unsigned int m_nRedecayLimit ;
-
-  /// counter of repetitions
-  unsigned int m_nRedecay ;
-
-  /// Memorized events
-  LHCb::HepMCEvents m_theMemorizedEvents ;
-
-  /// Memorized collisions
-  LHCb::GenCollisions m_theMemorizedCollisions ;
-
-  /// Copy a set of events into another
-  void copyEvents( LHCb::HepMCEvents * from ,
-                   LHCb::HepMCEvents * to )  ;
-
-  /* Copy a set of collisions into another, with the list of corresponding
-   * events
-   */
-  void copyCollisions( LHCb::GenCollisions * from , LHCb::GenCollisions * to ,
-                       LHCb::HepMCEvents * theEvents ) ;
-};
-#endif // GENERATORS_REPEATDECAY_H
diff --git a/Gen/Generators/src/component/SaveSignalBInformation.cpp b/Gen/Generators/src/component/SaveSignalBInformation.cpp
deleted file mode 100644
index 2343e67b7..000000000
--- a/Gen/Generators/src/component/SaveSignalBInformation.cpp
+++ /dev/null
@@ -1,179 +0,0 @@
-// Include files
-
-// from Gaudi
-
-// from Event
-#include "Event/HepMCEvent.h"
-
-// from Generators
-#include "GenEvent/HepMCUtils.h"
-
-// local
-#include "SaveSignalBInformation.h"
-
-//-----------------------------------------------------------------------------
-// Implementation file for class : SaveSignalBInformation
-//
-// 2013-06-26 : Patrick Robbe
-//-----------------------------------------------------------------------------
-
-// Declaration of the Algorithm Factory
-DECLARE_COMPONENT( SaveSignalBInformation )
-
-
-//=============================================================================
-// Standard constructor, initializes variables
-//=============================================================================
-SaveSignalBInformation::SaveSignalBInformation( const std::string& name,
-                                                ISvcLocator* pSvcLocator)
-  : GaudiAlgorithm ( name , pSvcLocator )
-{
-  declareProperty( "InputHepMCEvent" , m_inputHepMCEvent =
-                   LHCb::HepMCEventLocation::Default ) ;
-  declareProperty( "OutputHepMCEvent" , m_outputHepMCEvent = 
-                   "Gen/BInfo" ) ;
-}
-
-//=============================================================================
-// Main execution
-//=============================================================================
-StatusCode SaveSignalBInformation::execute() {
-  if ( msgLevel(MSG::DEBUG) ) debug() << "==> Execute" << endmsg;
-
-  // loop over input HepMC
-  SmartDataPtr< LHCb::HepMCEvents > hepMCptr( eventSvc() , 
-                                              m_inputHepMCEvent ) ;
-  
-  StatusCode sc = StatusCode::SUCCESS ;
-  
-  if ( 0 == hepMCptr ) {
-    info() << "No HepMCEvents at location " << m_inputHepMCEvent 
-           << endmsg ;
-  } else {
-    LHCb::HepMCEvents::iterator it ;
-    for ( it = hepMCptr -> begin() ; it != hepMCptr -> end() ; ++it ) {
-      // check if signal exists
-      if ( 0 != (*it) -> pGenEvt() -> signal_process_vertex() ) {
-        sc = extractSignal( (*it) -> pGenEvt() -> signal_process_vertex() ) ;
-        break ;
-      }
-    }
-  }
-
-  return sc ;
-}
-
-//=============================================================================
-// Extract B string and copy to a new location
-//=============================================================================
-StatusCode SaveSignalBInformation::extractSignal( const HepMC::GenVertex *
-                                                  theVertex ) const {
-  HepMC::GenParticle * HEPB0 = *( theVertex -> particles_in_const_begin() ) ;
-  HepMC::GenParticle * Bstring = 0 ;
-
-  // look for the string associated to the signal
-  for ( HepMC::GenVertex::particle_iterator iances = 
-          HEPB0->production_vertex()-> particles_begin(HepMC::ancestors);
-        iances != HEPB0->production_vertex()-> particles_end(HepMC::ancestors) ;
-        ++iances ) {
-    int genid = abs( (*iances) -> pdg_id() ) ;
-    if ( ( 91 == genid ) || ( 92 == genid ) ) { 
-      Bstring = (*iances) ; break ; 
-    }
-  }
-
-  if ( 0 != Bstring ) {
-    // copy the string in a new event
-    LHCb::HepMCEvent * mcevt = new LHCb::HepMCEvent( ) ;
-    mcevt -> setGeneratorName( "String" ) ;
-    
-    if ( 0 == Bstring -> production_vertex() ) 
-      return Error( "Bstring particle has no production vertex." ) ;
-  
-    // create a new vertex and a new HepMC Particle for the root particle
-    // (a copy of which will be associated to the new HepMC event) 
-    
-    HepMC::GenVertex * newVertex =
-      new HepMC::GenVertex( Bstring -> production_vertex() -> position() ) ;
-
-    HepMC::GenEvent * hepMCevt = mcevt -> pGenEvt() ;
-    
-    hepMCevt -> add_vertex( newVertex ) ;
-    
-    HepMC::GenParticle * theNewParticle =
-      new HepMC::GenParticle( Bstring -> momentum() , Bstring -> pdg_id() ,
-                              Bstring -> status() ) ;
-    
-    newVertex -> add_particle_out( theNewParticle ) ;
-    
-    // Associate the new particle to the HepMC event
-    StatusCode sc = fillHepMCEvent( theNewParticle , Bstring ) ;
-    hepMCevt -> set_signal_process_vertex( theNewParticle -> production_vertex() ) ;
-  
-    if ( ! sc.isSuccess( ) ) 
-      return Error( "Could not fill HepMC event for signal tree" , sc ) ;
-                            
-    // Check if container already exists
-    if ( exist< LHCb::HepMCEvents >( m_outputHepMCEvent ) ) 
-      return Error( "B string container already exists !" ) ;
-  
-    LHCb::HepMCEvents * hepVect = new LHCb::HepMCEvents ;
-    hepVect -> insert( mcevt ) ;
-    
-    // Register new location and store HepMC event
-    put( hepVect , m_outputHepMCEvent ) ;
-    
-    return sc ;
-  }
-  return StatusCode::SUCCESS ;
-}
-
-//=============================================================================
-// Fill HepMC event from a HepMC tree
-//=============================================================================
-StatusCode SaveSignalBInformation::fillHepMCEvent( HepMC::GenParticle * 
-                                                   theNewParticle ,
-                                                   const HepMC::GenParticle * 
-                                                   theOldParticle ) 
-  const {
-  StatusCode sc = StatusCode::SUCCESS ;
-  //
-  // Copy theOldParticle to theNewParticle in theEvent
-  // theNewParticle already exist and is created outside this function
-  HepMC::GenVertex * oVertex = theOldParticle -> end_vertex() ;
-  if ( 0 != oVertex ) {
-    // Create decay vertex and associate it to theNewParticle
-    HepMC::GenVertex * newVertex =
-      new HepMC::GenVertex( oVertex -> position() ) ;
-    newVertex -> add_particle_in( theNewParticle ) ;
-    theNewParticle -> parent_event() -> add_vertex( newVertex ) ;
-
-    // loop over child particle of this vertex after sorting them
-    std::list< const HepMC::GenParticle * > outParticles ;
-    for ( HepMC::GenVertex::particles_out_const_iterator itP = 
-            oVertex -> particles_out_const_begin() ; 
-          itP != oVertex -> particles_out_const_end() ; ++itP )
-      outParticles.push_back( (*itP ) ) ;
-
-    outParticles.sort( HepMCUtils::compareHepMCParticles ) ;
-
-    std::list< const HepMC::GenParticle * >::const_iterator child ;
-    for ( child = outParticles.begin( ) ; child != outParticles.end( ) ; 
-          ++child ) {
-      
-      // Create a new particle for each daughter of theOldParticle
-      HepMC::GenParticle * newPart =
-        new HepMC::GenParticle ( (*child) -> momentum () ,
-                                 (*child) -> pdg_id ()   ,
-                                 (*child) -> status ()   ) ;
-      newVertex -> add_particle_out( newPart ) ;
-      
-      const HepMC::GenParticle * theChild = (*child) ;
-      // Recursive call : fill the event with the daughters
-      sc = fillHepMCEvent( newPart , theChild ) ;
-      
-      if ( ! sc.isSuccess() ) return sc ;
-    }
-  }
-  return sc ;
-}
diff --git a/Gen/Generators/src/component/SaveSignalBInformation.h b/Gen/Generators/src/component/SaveSignalBInformation.h
deleted file mode 100644
index f17e259bf..000000000
--- a/Gen/Generators/src/component/SaveSignalBInformation.h
+++ /dev/null
@@ -1,45 +0,0 @@
-#ifndef COMPONENT_SAVESIGNALBINFORMATION_H
-#define COMPONENT_SAVESIGNALBINFORMATION_H 1
-
-// Include files
-// from Gaudi
-#include "GaudiAlg/GaudiAlgorithm.h"
-
-// forward declarations
-namespace HepMC {
-  class GenVertex ;
-  class GenParticle ;
-}
-
-/** @class SaveSignalBInformation SaveSignalBInformation.h
- *
- *  Algorithm that takes the b string information from HepMC
- *  and stores it at a specific location
- *
- *  @author Patrick Robbe
- *  @date   2013-06-26
- */
-class SaveSignalBInformation : public GaudiAlgorithm {
-public:
-  /// Standard constructor
-  SaveSignalBInformation( const std::string& name, ISvcLocator* pSvcLocator );
-
-  virtual ~SaveSignalBInformation( ) { } ; ///< Destructor
-
-  StatusCode execute   () override;    ///< Algorithm execution
-
-protected:
-
-private:
-  /// Extract B string from signal
-  StatusCode extractSignal( const HepMC::GenVertex * theVertex ) const ;
-
-  /// make a new HepMC event
-  StatusCode fillHepMCEvent( HepMC::GenParticle * theNewParticle,
-                             const HepMC::GenParticle * theOldParticle )
-    const ;
-
-  std::string m_inputHepMCEvent  ;
-  std::string m_outputHepMCEvent ;
-};
-#endif // COMPONENT_SAVESIGNALBINFORMATION_H
diff --git a/Gen/Generators/src/component/SignalForcedFragmentation.cpp b/Gen/Generators/src/component/SignalForcedFragmentation.cpp
deleted file mode 100755
index 91e84cd4f..000000000
--- a/Gen/Generators/src/component/SignalForcedFragmentation.cpp
+++ /dev/null
@@ -1,337 +0,0 @@
-// $Id: SignalForcedFragmentation.cpp,v 1.15 2008-07-24 22:05:38 robbep Exp $
-// Include files
-
-// from Gaudi
-#include "Kernel/IParticlePropertySvc.h"
-#include "Kernel/ParticleProperty.h"
-#include "GaudiKernel/SystemOfUnits.h"
-#include "GaudiKernel/PhysicalConstants.h"
-
-// from HepMC
-#include "HepMC/GenEvent.h"
-
-// from Kernel
-#include "MCInterfaces/IGenCutTool.h"
-#include "MCInterfaces/IDecayTool.h"
-
-// from Generators
-#include "Generators/IProductionTool.h"
-#include "GenEvent/HepMCUtils.h"
-
-// from Event
-#include "Event/GenFSR.h"
-#include "Event/GenCountersFSR.h"
-
-// local
-#include "SignalForcedFragmentation.h"
-
-//-----------------------------------------------------------------------------
-// Implementation file for class : SignalForcedFragmentation
-//
-// 2005-08-18 : Patrick Robbe
-//-----------------------------------------------------------------------------
-
-// Declaration of the Tool Factory
-
-DECLARE_COMPONENT( SignalForcedFragmentation )
-
-
-//=============================================================================
-// Standard constructor, initializes variables
-//=============================================================================
-SignalForcedFragmentation::SignalForcedFragmentation(
-  const std::string& type, const std::string& name, const IInterface* parent )
-  : Signal( type, name , parent ) , m_signalMass( 0. ) {
-  }
-
-//=============================================================================
-// Destructor
-//=============================================================================
-SignalForcedFragmentation::~SignalForcedFragmentation( ) { ; }
-
-//=============================================================================
-// Initialize method
-//=============================================================================
-StatusCode SignalForcedFragmentation::initialize( ) {
-  StatusCode sc = Signal::initialize( ) ;
-  if ( sc.isFailure() ) return sc ;
-
-  LHCb::IParticlePropertySvc * ppSvc =
-    svc< LHCb::IParticlePropertySvc >( "LHCb::ParticlePropertySvc" ) ;
-  const LHCb::ParticleProperty * prop = ppSvc -> find( LHCb::ParticleID( *m_pids.begin() ) ) ;
-  m_signalMass = prop -> mass() ;
-
-  release( ppSvc ) ;
-
-  return sc ;
-}
-
-//=============================================================================
-// Generate set of events with repeated hadronization
-//=============================================================================
-bool SignalForcedFragmentation::generate( const unsigned int nPileUp ,
-                                          LHCb::HepMCEvents * theEvents ,
-                                          LHCb::GenCollisions * theCollisions )
-{
-  StatusCode sc ;
-
-  // first decay signal particle
-  HepMC::GenEvent * theSignalHepMCEvent = new HepMC::GenEvent( ) ;
-  HepMC::GenParticle * theSignalAtRest = new HepMC::GenParticle( ) ;
-  theSignalAtRest ->
-    set_momentum( HepMC::FourVector( 0., 0., 0., m_signalMass ) ) ;
-
-  // Memorize if signal has been inverted (not used here)
-  bool isInverted = false ;
-  bool dummyHasFlipped = false ;
-  bool hasFailed = false ;
-
-  // Create an origin vertex at (0,0,0,0) for the signal particle at rest
-  HepMC::GenVertex * theVertex =
-    new HepMC::GenVertex( HepMC::FourVector( 0., 0., 0., 0. ) ) ;
-  theSignalHepMCEvent -> add_vertex( theVertex ) ;
-  theVertex -> add_particle_out( theSignalAtRest ) ;
-
-  bool flip ;
-  int theSignalPID = *m_pids.begin() ;
-
-  LHCb::GenFSR* genFSR = nullptr;
-  if(m_FSRName != ""){
-    IDataProviderSvc* fileRecordSvc = svc<IDataProviderSvc>("FileRecordDataSvc", true);
-    genFSR = getIfExists<LHCb::GenFSR>(fileRecordSvc, m_FSRName, false);
-    if(!genFSR) warning() << "Could not find GenFSR at " << m_FSRName << endmsg;
-  }
-  int key = 0;
-
-  if ( m_cpMixture ) {
-    // decide which flavour to generate :
-    // if flavour < 0.5, b flavour
-    // if flavour >= 0.5, bbar flavour
-    double flavour = m_flatGenerator() ;
-
-    m_decayTool -> enableFlip() ;
-
-    if ( flavour < 0.5 )
-      theSignalAtRest -> set_pdg_id( +abs( theSignalPID ) ) ;
-    else
-      theSignalAtRest -> set_pdg_id( -abs( theSignalPID ) ) ;
-  } else {
-    // generate only one flavour
-    m_decayTool -> disableFlip() ;
-    theSignalAtRest -> set_pdg_id( theSignalPID ) ;
-  }
-
-  sc = m_decayTool -> generateSignalDecay( theSignalAtRest , flip ) ;
-  if ( ! sc.isSuccess() ) return false ;
-
-  bool result = false ;
-
-  PIDs signalPid ;
-  signalPid.insert( theSignalAtRest -> pdg_id() ) ;
-
-  sc = m_productionTool ->
-    setupForcedFragmentation( theSignalAtRest -> pdg_id() ) ;
-  if ( sc.isFailure() ) error() << "Could not force fragmentation" << endmsg ;
-
-  LHCb::GenCollision * theGenCollision( 0 ) ;
-  HepMC::GenEvent * theGenEvent( 0 ) ;
-
-  // TODO: fix problem when 2 consecutive B events. The 2 B events both have
-  // signal in them !
-
-  // Then generate set of pile-up events
-  for ( unsigned int i = 0 ; i < nPileUp ; ++i ) {
-    prepareInteraction( theEvents , theCollisions , theGenEvent ,
-                        theGenCollision ) ;
-
-    sc = m_productionTool -> generateEvent( theGenEvent , theGenCollision ) ;
-    if ( sc.isFailure() ) Exception( "Could not generate event" ) ;
-
-    if ( ! result ) {
-      ParticleVector theParticleList ;
-      if ( checkPresence( signalPid , theGenEvent , theParticleList ) ) {
-        m_nEventsBeforeCut++ ;
-        key = LHCb::GenCountersFSR::BeforeLevelCut;
-        if(genFSR) genFSR->incrementGenCounter(key, 1);
-
-        updateCounters( theParticleList , m_nParticlesBeforeCut ,
-                        m_nAntiParticlesBeforeCut , false , false ) ;
-
-        HepMC::GenParticle * theSignal = chooseAndRevert( theParticleList ,
-                                                          isInverted ,
-                                                          dummyHasFlipped ,
-							  hasFailed ) ;
-
-        // Erase daughters of signal particle
-        HepMCUtils::RemoveDaughters( theSignal ) ;
-
-	if ( hasFailed ) {
-	  Error( "Skip event" ) ;
-	  return false  ;
-	}
-
-        theParticleList.clear() ;
-        theParticleList.push_back( theSignal ) ;
-
-        // Now boost signal at rest to frame of signal produced by
-        // production generator
-        Gaudi::LorentzVector mom( theSignal -> momentum() ) ;
-        ROOT::Math::Boost theBoost( -mom.BoostToCM() ) ;
-
-        // Give signal status
-        theSignal -> set_status( LHCb::HepMCEvent::SignalInLabFrame ) ;
-
-        sc = boostTree( theSignal , theSignalAtRest , theBoost ) ;
-        if ( ! sc.isSuccess() ) Exception( "Cannot boost signal tree" ) ;
-
-        bool passCut = true ;
-        if ( 0 != m_cutTool )
-          passCut = m_cutTool -> applyCut( theParticleList , theGenEvent ,
-                                           theGenCollision ) ;
-
-        if ( passCut && ( ! theParticleList.empty() ) ) {
-          m_nEventsAfterCut++ ;
-
-          updateCounters( theParticleList , m_nParticlesAfterCut ,
-                          m_nAntiParticlesAfterCut , true , false ) ;
-
-          if ( isInverted ) {
-            ++m_nInvertedEvents ;
-            key = LHCb::GenCountersFSR::EvtInverted;
-            if(genFSR) genFSR->incrementGenCounter(key, 1);
-          }
-          else
-          {
-            key = LHCb::GenCountersFSR::AfterLevelCut;
-            if(genFSR) genFSR->incrementGenCounter(key, 1);
-          }
-
-          if ( m_cleanEvents ) {
-            sc = isolateSignal( theSignal ) ;
-            if ( ! sc.isSuccess() ) Exception( "Cannot isolate signal" ) ;
-          }
-
-          theGenEvent ->
-            set_signal_process_vertex( theSignal -> end_vertex() ) ;
-          theGenCollision -> setIsSignal( true ) ;
-
-          // Count signal B and signal Bbar
-          if ( theSignal -> pdg_id() > 0 ) {
-            ++m_nSig ;
-            key = LHCb::GenCountersFSR::EvtSignal;
-            if(genFSR) genFSR->incrementGenCounter(key, 1);
-          }
-          else
-          {
-            ++m_nSigBar ;
-            key = LHCb::GenCountersFSR::EvtantiSignal;
-            if(genFSR) genFSR->incrementGenCounter(key, 1);
-          }
-
-          // Update counters
-          GenCounters::updateHadronCounters( theGenEvent , m_bHadC ,
-                                             m_antibHadC , m_cHadC ,
-                                             m_anticHadC , m_bbCounter ,
-                                             m_ccCounter ) ;
-          GenCounters::updateExcitedStatesCounters( theGenEvent ,
-                                                    m_bExcitedC ,
-                                                    m_cExcitedC ) ;
-
-          if(genFSR) GenCounters::updateHadronFSR( theGenEvent, genFSR, "Acc");
-
-          result = true ;
-        }
-      }
-    }
-  }
-
-  delete theSignalHepMCEvent ;
-  return result ;
-}
-
-//=============================================================================
-// Boost the Tree theSignal to theVector frame and attach it to theMother
-//=============================================================================
-StatusCode SignalForcedFragmentation::boostTree( HepMC::GenParticle *
-                                                 theSignal ,
-                                                 const HepMC::GenParticle *
-                                                 theSignalAtRest ,
-                                                 const ROOT::Math::Boost&
-                                                 theBoost )
-  const {
-  if ( 0 == theSignalAtRest -> end_vertex() ) return StatusCode::SUCCESS ;
-
-  if ( 0 != theSignal -> end_vertex() )
-    return Error( "The particle has already a decay vertex !" ) ;
-
-  if ( 0 == theSignalAtRest -> production_vertex() )
-    return Error( "The particle has no production vertex !" ) ;
-
-  // Displacement in original frame
-  Gaudi::LorentzVector positionEnd , positionBegin ;
-  positionEnd.SetXYZT( theSignalAtRest -> end_vertex() -> position() . x() ,
-                       theSignalAtRest -> end_vertex() -> position() . y() ,
-                       theSignalAtRest -> end_vertex() -> position() . z() ,
-                       theSignalAtRest -> end_vertex() -> position() . t() *
-                       Gaudi::Units::c_light ) ;
-
-  positionBegin.SetXYZT(theSignalAtRest->production_vertex()->position().x() ,
-                        theSignalAtRest->production_vertex()->position().y() ,
-                        theSignalAtRest->production_vertex()->position().z() ,
-                        theSignalAtRest->production_vertex()->position().t()
-                        * Gaudi::Units::c_light ) ;
-
-  Gaudi::LorentzVector position = positionEnd - positionBegin ;
-
-  // Displacement in new frame after boost.
-  Gaudi::LorentzVector newPosition = theBoost( position ) ;
-
-  // LHCb Units
-  Gaudi::LorentzVector newP ;
-  newP.SetXYZT( newPosition.X() , newPosition.Y() , newPosition.Z() ,
-                newPosition.T() / Gaudi::Units::c_light ) ;
-
-  // Add original position
-  Gaudi::LorentzVector
-    originalPosition( theSignal -> production_vertex() -> position() ) ;
-  newP += originalPosition ;
-
-  // Create new HepMC vertex after boost and add it to the current event
-  HepMC::GenVertex * newVertex =
-    new HepMC::GenVertex( HepMC::FourVector(newP.X(), newP.Y() , newP.Z() ,
-                                            newP.T()));
-
-  theSignal -> parent_event() -> add_vertex( newVertex ) ;
-  newVertex -> add_particle_in( theSignal ) ;
-
-  HepMC::GenVertex * sVertex = theSignalAtRest -> end_vertex() ;
-
-  HepMC::GenVertex::particles_out_const_iterator child ;
-
-  for ( child  = sVertex -> particles_out_const_begin( ) ;
-        child != sVertex -> particles_out_const_end( ) ; ++child ) {
-    // Boost all daughter particles and create a new HepMC particle
-    // for each daughter
-    Gaudi::LorentzVector momentum( (*child) -> momentum() ) ;
-    Gaudi::LorentzVector newMomentum = theBoost( momentum ) ;
-    int id                           = (*child) -> pdg_id() ;
-    int status                       = (*child) -> status() ;
-
-    HepMC::GenParticle * newPart =
-      new HepMC::GenParticle( HepMC::FourVector( newMomentum.Px() ,
-                                                 newMomentum.Py() ,
-                                                 newMomentum.Pz() ,
-                                                 newMomentum.E()   ) ,
-                              id , status ) ;
-
-    newVertex -> add_particle_out( newPart ) ;
-
-    HepMC::GenParticle * theNewSignal             = newPart ;
-    const HepMC::GenParticle * theNewSignalAtRest = (*child) ;
-
-    // Recursive call to boostTree for each daughter
-    boostTree( theNewSignal , theNewSignalAtRest , theBoost ) ;
-  }
-
-  return StatusCode::SUCCESS ;
-}
diff --git a/Gen/Generators/src/component/SignalForcedFragmentation.h b/Gen/Generators/src/component/SignalForcedFragmentation.h
deleted file mode 100755
index 6f160fdf1..000000000
--- a/Gen/Generators/src/component/SignalForcedFragmentation.h
+++ /dev/null
@@ -1,57 +0,0 @@
-// $Id: SignalForcedFragmentation.h,v 1.6 2008-05-29 14:22:00 gcorti Exp $
-#ifndef GENERATORS_SIGNALFORCEDFRAGMENTATION_H
-#define GENERATORS_SIGNALFORCEDFRAGMENTATION_H 1
-
-// Include files
-#include "Generators/Signal.h"
-#include "GaudiKernel/Transform4DTypes.h"
-#include "GaudiKernel/Vector4DTypes.h"
-
-/** @class SignalForcedFragmentation SignalForcedFragmentation.h "SignalForcedFragmentation.h"
- *
- *  Tool for signal generation with forced fragmentation.
- *  Concrete implementation of ISampleGenerationTool using
- *  the Signal base class.
- *
- *  @author Patrick Robbe
- *  @date   2005-08-18
- */
-class SignalForcedFragmentation : public Signal {
- public:
-  /// Standard constructor
-  SignalForcedFragmentation( const std::string & type ,
-                             const std::string & name ,
-                             const IInterface * parent ) ;
-
-  virtual ~SignalForcedFragmentation( ); ///< Destructor
-
-  StatusCode initialize( ) override; ///< Initialize
-
-  /** Generate set of interactions.
-   *  Implements ISampleGenerationTool::generate
-   *  -# Choose randomly a flavour to generate for each event
-   *  -# Generate with the IDecayTool the signal event (at rest)
-   *     of this flavour.
-   *  -# Force the fragmentation into this flavour when an
-   *     interaction contains a b quark, calling
-   *     IProductionTool::setupForcedFragmentation.
-   */
-  bool generate( const unsigned int nPileUp ,
-                 LHCb::HepMCEvents * theEvents ,
-                 LHCb::GenCollisions * theCollisions ) override;
- private:
-  /** Boost a particle at rest in the lab frame.
-   *  @param[in,out] theSignal       Particle in the lab. frame
-   *                                 to boost to
-   *  @param[in]     theSignalAtRest Decay tree at rest to boost
-   *  @param[in]     theVector       3-momentum boost vector
-   */
-  StatusCode boostTree( HepMC::GenParticle * theSignal ,
-                        const HepMC::GenParticle * theSignalAtRest ,
-                        const ROOT::Math::Boost & theBoost ) const ;
-
-  double m_signalMass ; ///< Mass of the signal particle
-};
-
-
-#endif // GENERATORS_SIGNALFORCEDFRAGMENTATION_H
diff --git a/Gen/Generators/src/component/SignalPlain.cpp b/Gen/Generators/src/component/SignalPlain.cpp
deleted file mode 100755
index 133b5c103..000000000
--- a/Gen/Generators/src/component/SignalPlain.cpp
+++ /dev/null
@@ -1,183 +0,0 @@
-// Include files
-
-// local
-#include "SignalPlain.h"
-
-// from Gaudi
-
-// Event
-#include "Event/HepMCEvent.h"
-#include "Event/GenCollision.h"
-#include "Event/GenFSR.h"
-#include "Event/GenCountersFSR.h"
-
-// Kernel
-#include "MCInterfaces/IGenCutTool.h"
-#include "MCInterfaces/IDecayTool.h"
-
-// from Generators
-#include "Generators/IProductionTool.h"
-#include "GenEvent/HepMCUtils.h"
-
-//-----------------------------------------------------------------------------
-// Implementation file for class : SignalPlain
-//
-// 2005-08-18 : Patrick Robbe
-//-----------------------------------------------------------------------------
-
-// Declaration of the Tool Factory
-
-DECLARE_COMPONENT( SignalPlain )
-
-
-//=============================================================================
-// Standard constructor, initializes variables
-//=============================================================================
-SignalPlain::SignalPlain( const std::string& type, const std::string& name,
-                          const IInterface* parent )
-  : Signal( type, name , parent ) { ; }
-
-//=============================================================================
-// Destructor
-//=============================================================================
-SignalPlain::~SignalPlain( ) { ; }
-
-//=============================================================================
-// Generate Set of Event for Minimum Bias event type
-//=============================================================================
-bool SignalPlain::generate( const unsigned int nPileUp ,
-                            LHCb::HepMCEvents * theEvents ,
-                            LHCb::GenCollisions * theCollisions ) {
-  StatusCode sc ;
-  bool result = false ;
-  // Memorize if the particle is inverted
-  bool isInverted = false ;
-  bool hasFlipped = false ;
-  bool hasFailed = false ;
-  LHCb::GenCollision * theGenCollision( 0 ) ;
-  HepMC::GenEvent * theGenEvent( 0 ) ;
-  LHCb::GenFSR* genFSR = nullptr;
-  if(m_FSRName != ""){
-    IDataProviderSvc* fileRecordSvc = svc<IDataProviderSvc>("FileRecordDataSvc", true);
-    genFSR = getIfExists<LHCb::GenFSR>(fileRecordSvc, m_FSRName);
-    if(!genFSR) warning() << "Could not find GenFSR at " << m_FSRName << endmsg;
-  }
-  int key = 0;
-
-  for ( unsigned int i = 0 ; i < nPileUp ; ++i ) {
-    prepareInteraction( theEvents , theCollisions , theGenEvent,
-                        theGenCollision ) ;
-
-    sc = m_productionTool -> generateEvent( theGenEvent , theGenCollision ) ;
-    if ( sc.isFailure() ) Exception( "Could not generate event" ) ;
-
-    if ( ! result ) {
-      // Decay particles heavier than the particles to look at
-      decayHeavyParticles( theGenEvent , m_signalQuark , m_signalPID ) ;
-
-      // Check if one particle of the requested list is present in event
-      ParticleVector theParticleList ;
-      if ( checkPresence( m_pids , theGenEvent , theParticleList ) ) {
-
-        // establish correct multiplicity of signal
-        if ( ensureMultiplicity( theParticleList.size() ) ) {
-
-          // choose randomly one particle and force the decay
-          hasFlipped = false ;
-          isInverted = false ;
-          hasFailed  = false ;
-          HepMC::GenParticle * theSignal =
-            chooseAndRevert( theParticleList , isInverted , hasFlipped , hasFailed ) ;
-          if ( hasFailed ) {
-            HepMCUtils::RemoveDaughters( theSignal ) ;
-            Error( "Skip event" ) ;
-            return false ;
-          }
-
-          theParticleList.clear() ;
-          theParticleList.push_back( theSignal ) ;
-
-          if ( ! hasFlipped ) {
-
-            m_nEventsBeforeCut++ ;
-            key = LHCb::GenCountersFSR::BeforeLevelCut;
-            if(genFSR) genFSR->incrementGenCounter(key, 1);
-
-            // count particles in 4pi
-            updateCounters( theParticleList , m_nParticlesBeforeCut ,
-                            m_nAntiParticlesBeforeCut , false , false ) ;
-
-            bool passCut = true ;
-            if ( 0 != m_cutTool )
-              passCut = m_cutTool -> applyCut( theParticleList , theGenEvent ,
-                                               theGenCollision ) ;
-
-            if ( passCut && ( ! theParticleList.empty() ) ) {
-              if ( ! isInverted ) {
-                m_nEventsAfterCut++ ;
-                key = LHCb::GenCountersFSR::AfterLevelCut;
-                if(genFSR) genFSR->incrementGenCounter(key, 1);
-              }
-
-              if ( isInverted ) {
-                ++m_nInvertedEvents ;
-                key = LHCb::GenCountersFSR::EvtInverted;
-                if(genFSR) genFSR->incrementGenCounter(key, 1);
-              }
-
-              // Count particles passing the generator level cut with pz > 0
-              updateCounters( theParticleList , m_nParticlesAfterCut ,
-                              m_nAntiParticlesAfterCut , true , isInverted ) ;
-
-              if ( m_cleanEvents ) {
-                sc = isolateSignal( theSignal ) ;
-                if ( ! sc.isSuccess() ) Exception( "Cannot isolate signal" ) ;
-              }
-              theGenEvent ->
-                set_signal_process_vertex( theSignal -> end_vertex() ) ;
-
-              theGenCollision -> setIsSignal( true ) ;
-
-              // Count signal B and signal Bbar
-              if ( theSignal -> pdg_id() > 0 ) {
-                ++m_nSig ;
-                key = LHCb::GenCountersFSR::EvtSignal;
-                if(genFSR) genFSR->incrementGenCounter(key, 1);
-              }
-              else {
-                ++m_nSigBar ;
-                key = LHCb::GenCountersFSR::EvtantiSignal;
-                if(genFSR) genFSR->incrementGenCounter(key, 1);
-              }
-
-
-              // Update counters
-              GenCounters::updateHadronCounters( theGenEvent , m_bHadC ,
-                                                 m_antibHadC , m_cHadC ,
-                                                 m_anticHadC , m_bbCounter ,
-                                                 m_ccCounter ) ;
-              GenCounters::updateExcitedStatesCounters( theGenEvent ,
-                                                        m_bExcitedC ,
-                                                        m_cExcitedC ) ;
-
-              if(genFSR) GenCounters::updateHadronFSR( theGenEvent, genFSR, "Acc");
-
-
-              result = true ;
-            } else {
-              // event does not pass cuts
-              HepMCUtils::RemoveDaughters( theSignal ) ;
-            }
-          } else {
-            // has flipped:
-            HepMCUtils::RemoveDaughters( theSignal ) ;
-            theSignal -> set_pdg_id( - ( theSignal -> pdg_id() ) ) ;
-          }
-        }
-      }
-    }
-  }
-
-  return result ;
-}
-
diff --git a/Gen/Generators/src/component/SignalPlain.h b/Gen/Generators/src/component/SignalPlain.h
deleted file mode 100755
index 76fab6097..000000000
--- a/Gen/Generators/src/component/SignalPlain.h
+++ /dev/null
@@ -1,39 +0,0 @@
-// $Id: SignalPlain.h,v 1.5 2006-10-01 22:43:40 robbep Exp $
-#ifndef GENERATORS_SIGNALPLAIN_H
-#define GENERATORS_SIGNALPLAIN_H 1
-
-// Include files
-// from Gaudi
-#include "GaudiAlg/GaudiTool.h"
-
-#include "Generators/Signal.h"
-
-/** @class SignalPlain SignalPlain.h
- *
- *  Tool for signal generation with plain method. Concrete
- *  implementation of ISampleGenerationTool using the Signal
- *  base class.
- *
- *  @author Patrick Robbe
- *  @date   2005-08-18
- */
-class SignalPlain : public Signal {
- public:
-  /// Standard constructor
-  SignalPlain( const std::string & type , const std::string & name ,
-               const IInterface * parent ) ;
-
-  virtual ~SignalPlain( ); ///< Destructor
-
-  /** Generates events containing a signal particle.
-   *  Implements ISampleProductionTool::generate.
-   *  Loop over events until it contains a signal particle
-   *  without using any trick (just like Inclusive).
-   */
-  bool generate( const unsigned int nPileUp ,
-                 LHCb::HepMCEvents * theEvents ,
-                 LHCb::GenCollisions * theCollisions ) override;
-
- private:
-};
-#endif // GENERATORS_SIGNALPLAIN_H
diff --git a/Gen/Generators/src/component/SignalRepeatedHadronization.cpp b/Gen/Generators/src/component/SignalRepeatedHadronization.cpp
deleted file mode 100755
index ddca95591..000000000
--- a/Gen/Generators/src/component/SignalRepeatedHadronization.cpp
+++ /dev/null
@@ -1,298 +0,0 @@
-// $Id: SignalRepeatedHadronization.cpp,v 1.14 2007-02-22 13:30:24 robbep Exp $
-// Include files
-
-// local
-#include "SignalRepeatedHadronization.h"
-
-// from Gaudi
-
-// from Kernel
-#include "Kernel/ParticleID.h"
-#include "MCInterfaces/IGenCutTool.h"
-#include "MCInterfaces/IDecayTool.h"
-
-// From HepMC
-#include "HepMC/GenParticle.h"
-#include "HepMC/GenEvent.h"
-
-// from Generators
-#include "Generators/IProductionTool.h"
-#include "GenEvent/HepMCUtils.h"
-
-// from Event
-#include "Event/GenFSR.h"
-#include "Event/GenCountersFSR.h"
-
-//-----------------------------------------------------------------------------
-// Implementation file for class : SignalRepeatedHadronization
-//
-// 2005-08-18 : Patrick Robbe
-//-----------------------------------------------------------------------------
-
-// Declaration of the Tool Factory
-
-DECLARE_COMPONENT( SignalRepeatedHadronization )
-
-
-//=============================================================================
-// Standard constructor, initializes variables
-//=============================================================================
-SignalRepeatedHadronization::SignalRepeatedHadronization(
-  const std::string& type, const std::string& name, const IInterface* parent )
-  : Signal( type, name , parent ) {
-    declareProperty( "MaxNumberOfRepetitions" ,
-                     m_maxNumberOfRepetitions = 500 ) ;
-  }
-
-//=============================================================================
-// Destructor
-//=============================================================================
-SignalRepeatedHadronization::~SignalRepeatedHadronization( ) { ; }
-
-//=============================================================================
-// Initialize Method
-//=============================================================================
-StatusCode SignalRepeatedHadronization::initialize( ) {
-  StatusCode sc = Signal::initialize( ) ;
-  if ( sc.isFailure() ) return sc ;
-
-  // Determine quark types
-  LHCb::ParticleID pid( *m_pids.begin() ) ;
-  if ( pid.hasBottom() ) {
-    m_pidQuarks.insert( -LHCb::ParticleID::bottom ) ;
-    m_pidQuarks.insert( LHCb::ParticleID::bottom ) ;
-  } else if ( pid.hasCharm() ) {
-    m_pidQuarks.insert( -LHCb::ParticleID::charm ) ;
-    m_pidQuarks.insert( LHCb::ParticleID::charm ) ;
-  }
-
-  return sc ;
-}
-
-//=============================================================================
-// Generate Set of Event for Minimum Bias event type
-//=============================================================================
-bool SignalRepeatedHadronization::generate( const unsigned int nPileUp ,
-                                            LHCb::HepMCEvents * theEvents ,
-                                            LHCb::GenCollisions *
-                                            theCollisions ) {
-  StatusCode sc ;
-  bool gotSignalInteraction = false ;
-
-  // Memorize the inversion of the event
-  bool isInverted = false ;
-
-  // Memorize the flip of the event
-  bool hasFlipped = false ;
-
-  // Check if problem in EvtGen
-  bool hasFailed = false ;
-
-  LHCb::GenCollision * theGenCollision( 0 ) ;
-  HepMC::GenEvent * theGenEvent( 0 ) ;
-  HepMC::GenParticle * theSignal ;
-
-  LHCb::GenFSR* genFSR = nullptr;
-  if(m_FSRName != ""){
-    IDataProviderSvc* fileRecordSvc = svc<IDataProviderSvc>("FileRecordDataSvc", true);
-    genFSR = getIfExists<LHCb::GenFSR>(fileRecordSvc, m_FSRName, false);
-    if(!genFSR) warning() << "Could not find GenFSR at " << m_FSRName << endmsg;
-  }
-  int key = 0;
-
-  for ( unsigned int i = 0 ; i < nPileUp ; ++i ) {
-    bool partonEventWithSignalQuarks = false ;
-    ParticleVector theQuarkList ;
-
-    prepareInteraction( theEvents , theCollisions , theGenEvent ,
-                        theGenCollision ) ;
-
-    if ( ! gotSignalInteraction ) m_productionTool -> turnOffFragmentation( ) ;
-
-    if (i==0 && ! gotSignalInteraction) theGenCollision -> setIsSignal( true ) ;
-
-    sc = m_productionTool -> generateEvent( theGenEvent , theGenCollision ) ;
-
-    if ( sc.isFailure() ) Exception( "Could not generate event" ) ;
-
-    if ( ! gotSignalInteraction ) {
-      if ( checkPresence( m_pidQuarks , theGenEvent , theQuarkList ) ) {
-        partonEventWithSignalQuarks = true ;
-        m_productionTool -> savePartonEvent( theGenEvent ) ;
-      }
-
-      m_productionTool -> turnOnFragmentation( ) ;
-      // Clear theGenEvent
-      Clear( theGenEvent ) ;
-      m_productionTool -> hadronize( theGenEvent , theGenCollision ) ;
-
-      // Check if one particle of the requested list is present in event
-      unsigned int nRepetitions = 0 ;
-
-      while ( nRepetitions < m_maxNumberOfRepetitions ) {
-        // Decay heavy particles
-        decayHeavyParticles( theGenEvent , m_signalQuark , m_signalPID ) ;
-
-        // Check if one particle of the requested list is present in event
-        ParticleVector theParticleList ;
-
-        if ( checkPresence( m_pids , theGenEvent , theParticleList ) ) {
-
-          // establish correct multiplicity of signal
-          if ( ensureMultiplicity( theParticleList.size() ) ) {
-
-            // If there are several particles passing the cuts, choose one
-            // and revert event if it has pz < 0
-            // memorize that the event is inverted in isInverted
-            // and force the decay at the same time
-            isInverted = false ;
-            hasFlipped = false ;
-	    hasFailed  = false ;
-            theSignal = chooseAndRevert( theParticleList , isInverted ,
-                                         hasFlipped , hasFailed ) ;
-
-	    if ( hasFailed ) {
-	      Error( "Skip Event" ) ;
-	      HepMCUtils::RemoveDaughters( theSignal ) ;
-	      return false ;
-	    }
-
-            theParticleList.clear() ;
-            theParticleList.push_back( theSignal ) ;
-
-            // Remove events with flip due to CP violation
-            if ( ! hasFlipped ) {
-
-              // Count particles and anti-particles of Signal type before
-              // the cut in all directions
-              m_nEventsBeforeCut++ ;
-              key = LHCb::GenCountersFSR::BeforeLevelCut;
-              if(genFSR) genFSR->incrementGenCounter(key, 1);
-
-              updateCounters( theParticleList , m_nParticlesBeforeCut ,
-                              m_nAntiParticlesBeforeCut , false , false ) ;
-
-              bool passCut = true ;
-
-              if ( 0 != m_cutTool )
-                passCut = m_cutTool -> applyCut( theParticleList , theGenEvent ,
-                                                 theGenCollision ) ;
-
-              if ( passCut && ( ! theParticleList.empty() ) ) {
-
-                if ( ! isInverted ) {
-                  m_nEventsAfterCut++ ;
-                  key = LHCb::GenCountersFSR::AfterLevelCut;
-                  if(genFSR) genFSR->incrementGenCounter(key, 1);
-                }
-
-                if ( isInverted ) {
-                  ++m_nInvertedEvents ;
-                  key = LHCb::GenCountersFSR::EvtInverted;
-                  if(genFSR) genFSR->incrementGenCounter(key, 1);
-                }
-
-                // Count particles and anti-particles of Signal type with
-                // pz>0, after generator level cut
-                updateCounters( theParticleList , m_nParticlesAfterCut ,
-                                m_nAntiParticlesAfterCut , true ,
-                                isInverted ) ;
-
-                gotSignalInteraction = true ;
-                if ( m_cleanEvents ) {
-                  sc = isolateSignal( theSignal ) ;
-                  if ( ! sc.isSuccess() )
-                    Exception( "Cannot isolate signal" ) ;
-                }
-
-                theGenEvent ->
-                  set_signal_process_vertex( theSignal -> end_vertex() ) ;
-
-                // theGenCollision -> setIsSignal( true ) ;
-
-                if ( theSignal -> pdg_id() > 0 ) {
-                  ++m_nSig ;
-                  key = LHCb::GenCountersFSR::EvtSignal;
-                  if(genFSR) genFSR->incrementGenCounter(key, 1);
-                }
-                else {
-                  ++m_nSigBar ;
-                  key = LHCb::GenCountersFSR::EvtantiSignal;
-                  if(genFSR) genFSR->incrementGenCounter(key, 1);
-                }
-
-                // Update counters
-                GenCounters::updateHadronCounters( theGenEvent , m_bHadC ,
-                                                   m_antibHadC , m_cHadC ,
-                                                   m_anticHadC , m_bbCounter,
-                                                   m_ccCounter ) ;
-                GenCounters::updateExcitedStatesCounters( theGenEvent ,
-                                                          m_bExcitedC ,
-                                                          m_cExcitedC ) ;
-                if(genFSR) GenCounters::updateHadronFSR( theGenEvent, genFSR, "Acc");
-              }
-              else {
-                // Signal does not pass cut: remove daughters
-                HepMCUtils::RemoveDaughters( theSignal ) ;
-              }
-            } else {
-              // event has flipped: remove daughters of signal and revert PID
-              HepMCUtils::RemoveDaughters( theSignal ) ;
-              theSignal -> set_pdg_id( - ( theSignal -> pdg_id() ) ) ;
-            }
-          }
-
-          // if the interaction is not kept, we must re-hadronize it
-          // once to have a fresh unbiased event
-          if ( ! gotSignalInteraction ) {
-            nRepetitions++ ;
-            m_productionTool -> retrievePartonEvent( theGenEvent ) ;
-            m_productionTool -> turnOnFragmentation( ) ;
-            m_productionTool -> savePartonEvent( theGenEvent ) ;
-            Clear( theGenEvent ) ;
-            m_productionTool -> hadronize( theGenEvent , theGenCollision ) ;
-          }
-          // Then we exit and do not re-hadronize this event
-          // not to bias things
-          break ;
-        }
-
-        if ( ! partonEventWithSignalQuarks ) break ;
-
-        nRepetitions++ ;
-        m_productionTool -> retrievePartonEvent( theGenEvent ) ;
-        m_productionTool -> turnOnFragmentation( ) ;
-        m_productionTool -> savePartonEvent( theGenEvent ) ;
-        // Clear HepMC event
-        Clear( theGenEvent ) ;
-        m_productionTool -> hadronize( theGenEvent , theGenCollision ) ;
-      }
-
-      if ( nRepetitions == m_maxNumberOfRepetitions )
-        info() << "Number of repetitions of hadronization exceeds the limit"
-               << endmsg ;
-    }
-    else if (m_hepMCName=="Pythia8") {
-      //hadronize the pile-up events for Pythia8 (already done above for pythia6)
-      m_productionTool -> hadronize( theGenEvent , theGenCollision ) ;
-    }
-  }
-
-  return gotSignalInteraction ;
-}
-
-//=============================================================================
-// Clear a complete HepMC event
-//=============================================================================
-void SignalRepeatedHadronization::Clear( HepMC::GenEvent * theEvent ) const {
-  if ( ! theEvent -> vertices_empty() ) {
-    std::vector< HepMC::GenVertex * > tempList( theEvent -> vertices_begin() ,
-                                                theEvent -> vertices_end() ) ;
-    std::vector< HepMC::GenVertex * >::iterator iter ;
-    for ( iter = tempList.begin() ; iter != tempList.end() ; ++iter ) {
-      if ( ! theEvent -> remove_vertex( *iter ) )
-        Exception( "Could not remove vertex !" ) ;
-      delete (*iter) ;
-    }
-  }
-}
diff --git a/Gen/Generators/src/component/SignalRepeatedHadronization.h b/Gen/Generators/src/component/SignalRepeatedHadronization.h
deleted file mode 100755
index 2cd618fc8..000000000
--- a/Gen/Generators/src/component/SignalRepeatedHadronization.h
+++ /dev/null
@@ -1,60 +0,0 @@
-// $Id: SignalRepeatedHadronization.h,v 1.6 2005-12-31 17:33:12 robbep Exp $
-#ifndef GENERATORS_SIGNALREPEATEDHADRONIZATION_H
-#define GENERATORS_SIGNALREPEATEDHADRONIZATION_H 1
-
-// Include files
-#include "Generators/Signal.h"
-
-/** @class SignalRepeatedHadronization SignalRepeatedHadronization.h "SignalRepeatedHadronization.h"
- *
- *  Tool for signal generation with repeated hadronization method.
- *  Concrete implementation of ISampleGenerationTool using the
- *  Signal base class.
- *
- *  @author Patrick Robbe
- *  @date   2005-08-18
- */
-class SignalRepeatedHadronization : public Signal {
-public:
-  /// Standard constructor
-  SignalRepeatedHadronization( const std::string& type,
-                               const std::string& name,
-                               const IInterface* parent);
-
-  virtual ~SignalRepeatedHadronization( ); ///< Destructor
-
-  StatusCode initialize( ) override; ///< Initialize
-
-  /** Generate events with at least one interaction containing the signal
-   *  Implements ISampleGenerationTool::generate.
-   *  -# Turn off hadronization process (using
-   *     IProductionTool::turnOffFragmentation)
-   *  -# Generate interaction with IProductionTool
-   *  -# If event has a b quark, save parton event (using
-   *     IProductionTool::savePartonEvent
-   *  -# In all cases, hadronize the event (using
-   *     IProductionTool::hadronize.
-   *  -# If interaction has b quark, recall (using
-   *     IProductionTool::retrievePartonEvent) and
-   *     hadronize this event (with IProductionTool:hadronize)
-   *     until it contains a signal B.
-   *  -# Apply generator level cut and keep or reject full
-   *     event (if rejected, the interaction is not hadronized
-   *     again and is not kept).
-   */
-  bool generate( const unsigned int nPileUp ,
-                 LHCb::HepMCEvents * theEvents ,
-                 LHCb::GenCollisions * theCollisions ) override;
-
-protected:
-  /// Delete full content of an event
-  void Clear( HepMC::GenEvent * theEvent ) const ;
-
-private:
-  /// Maximum number of allowed repetitions of hadronization (set by options)
-  unsigned int  m_maxNumberOfRepetitions ;
-
-  /// List of quarks of signal particles to generate
-  PIDs          m_pidQuarks        ;
-};
-#endif // GENERATORS_SIGNALREPEATEDHADRONIZATION_H
diff --git a/Gen/Generators/src/component/Special.cpp b/Gen/Generators/src/component/Special.cpp
deleted file mode 100755
index 9ed797f22..000000000
--- a/Gen/Generators/src/component/Special.cpp
+++ /dev/null
@@ -1,255 +0,0 @@
-// $Id: Special.cpp,v 1.13 2009-09-20 17:53:02 robbep Exp $
-// Include files
-
-// local
-#include "Special.h"
-// from Gaudi
-#include "Kernel/IParticlePropertySvc.h" 
-#include "Kernel/ParticleProperty.h"
-// from Kernel
-#include "MCInterfaces/IGenCutTool.h"
-#include "MCInterfaces/IDecayTool.h"
-
-// from Generators
-#include "Generators/IProductionTool.h"
-#include "Generators/GenCounters.h"
-#include "Generators/LhaPdf.h"
-#include "Generators/ICounterLogFile.h"
-
-// Event
-#include "Event/HepMCEvent.h"
-#include "Event/GenCollision.h"
-#include "Event/GenFSR.h"
-#include "Event/GenCountersFSR.h"
-
-//-----------------------------------------------------------------------------
-// Implementation file for class : Special
-//
-// 2005-08-18 : Patrick Robbe
-//-----------------------------------------------------------------------------
-
-// Declaration of the Tool Factory
-
-DECLARE_COMPONENT( Special )
-
-
-//=============================================================================
-// Standard constructor, initializes variables
-//=============================================================================
-Special::Special( const std::string & type , const std::string & name ,
-                  const IInterface * parent )
-  : ExternalGenerator( type, name , parent ) ,
-    m_xmlLogTool( 0 ) ,
-    m_nEventsBeforeCut    (  0 ) ,
-    m_nEventsAfterCut     (  0 ) ,
-    m_maxInteractions     ( 30 ) ,
-    m_pileUpProductionTool(  0 ) {
-  declareProperty( "PileUpProductionTool" ,
-                   m_pileUpProductionToolName =
-                   "Pythia8Production/MinimumBiasPythia8Production" ) ;
-  declareProperty( "ReinitializePileUpGenerator" ,
-                   m_reinitialize = true ) ;
-  declareProperty( "MaxInteractions" ,
-                   m_maxInteractions = 1000 ) ;
-}
-
-//=============================================================================
-// Destructor
-//=============================================================================
-Special::~Special( ) { ; }
-
-//=============================================================================
-// Initialize method
-//=============================================================================
-StatusCode Special::initialize( ) {
-  info() << "Generating Special events." << endmsg ;
-  StatusCode sc = ExternalGenerator::initialize( ) ;
-
-  // Update the particle properties of the pileup tool.
-  if ( "" != m_pileUpProductionToolName ) {
-    IProductionTool *pileup =
-      tool< IProductionTool >( m_pileUpProductionToolName , this ) ;
-    if ( 0 != pileup ) {
-      LHCb::IParticlePropertySvc::iterator iter ;
-      for ( iter = m_ppSvc -> begin() ; iter != m_ppSvc -> end() ; ++iter ) {
-	if ( ( ! pileup -> isSpecialParticle( *iter ) ) && 
-	     ( ! m_keepOriginalProperties ) ) 
-	  pileup -> updateParticleProperties( *iter ) ;
-	if ( 0 != m_decayTool )
-	  if ( m_decayTool -> isKnownToDecayTool( (*iter)->pdgID().pid() ) ) 
-	    pileup -> setStable( *iter ) ;    
-      }
-    }
-  }
-
-  // Initialize XML Log file
-  m_xmlLogTool = tool< ICounterLogFile >( "XmlCounterLogFile" ) ;
-
-  // Switch off LHA print out first
-  if ( msgLevel( MSG::DEBUG ) ) {
-    LhaPdf::lhacontrol().setlhaparm( 19 , "DEBUG" ) ;
-  }
-  else {
-    LhaPdf::lhacontrol().setlhaparm( 19 , "SILENT" ) ;
-  }
-
-  m_pileUpEventsVector.clear() ;
-  m_pileUpCollisionsVector.clear() ;
-
-  return sc ;
-}
-
-//=============================================================================
-// Finalize method
-//=============================================================================
-StatusCode Special::finalize( ) {
-  std::vector< HepMC::GenEvent * >::iterator iter ;
-  for ( iter = m_pileUpEventsVector.begin() ;
-        iter != m_pileUpEventsVector.end() ; ++iter )
-    delete (*iter) ;
-  m_pileUpEventsVector.clear() ;
-
-  std::vector< LHCb::GenCollision * >::iterator iterC ;
-  for ( iterC = m_pileUpCollisionsVector.begin() ;
-        iterC != m_pileUpCollisionsVector.end() ; ++iterC )
-    delete (*iterC) ;
-  m_pileUpCollisionsVector.clear() ;
-
-  if ( 0 != m_pileUpProductionTool ) release( m_pileUpProductionTool ) ;
-
-  return ExternalGenerator::finalize() ;
-}
-
-
-//=============================================================================
-// Generate Set of Event for Minimum Bias event type
-//=============================================================================
-bool Special::generate( const unsigned int nPileUp ,
-                        LHCb::HepMCEvents * theEvents ,
-                        LHCb::GenCollisions * theCollisions ) {
-  StatusCode sc ;
-  LHCb::GenCollision * theGenCollision( 0 ) ;
-  HepMC::GenEvent * theGenEvent( 0 ) ;
-
-  bool result = false ;
-
-  LHCb::GenFSR* genFSR = nullptr;
-  if(m_FSRName != ""){
-    IDataProviderSvc* fileRecordSvc = svc<IDataProviderSvc>("FileRecordDataSvc", true);
-    genFSR = getIfExists<LHCb::GenFSR>(fileRecordSvc, m_FSRName, false);
-    if(!genFSR) warning() << "Could not find GenFSR at " << m_FSRName << endmsg;
-  }
-  int key = 0;
-
-  // For the moment no pile-up for this type of event
-  for ( unsigned int i = 0 ; i < nPileUp ; ++i ) {
-    prepareInteraction( theEvents , theCollisions , theGenEvent,
-                        theGenCollision ) ;
-
-    // First interaction is always "signal"
-
-    if ( 0 == i ) {
-      sc = m_productionTool -> generateEvent( theGenEvent , theGenCollision ) ;
-      if ( sc.isFailure() ) Exception( "Could not generate event" ) ;
-
-      ParticleVector theParticleList ;
-      m_nEventsBeforeCut++ ;
-      key = LHCb::GenCountersFSR::BeforeLevelCut;
-      if(genFSR) genFSR->incrementGenCounter(key, 1);
-
-      bool passCut = true ;
-      if ( 0 != m_cutTool )
-        passCut = m_cutTool -> applyCut( theParticleList , theGenEvent ,
-                                         theGenCollision ) ;
-
-      if ( passCut ) {
-        m_nEventsAfterCut++ ;
-        key = LHCb::GenCountersFSR::AfterLevelCut;
-        if(genFSR) genFSR->incrementGenCounter(key, 1);
-        result = true ;
-        theGenCollision -> setIsSignal( true ) ;
-      } else return false ;
-    } else {
-      // if event passed generator level cut
-      // look if there are still enough pile-up events
-      if ( m_pileUpEventsVector.empty() ) generatePileUp() ;
-
-      // retrieve now pile-up events
-      HepMC::GenEvent * pileUpEvent = m_pileUpEventsVector.back() ;
-      (*theGenEvent) =  ( * pileUpEvent ) ;
-
-      m_pileUpEventsVector.pop_back() ;
-      delete pileUpEvent ;
-
-      // and collision
-      LHCb::GenCollision * pileUpCollision = m_pileUpCollisionsVector.back() ;
-      copyCollision( pileUpCollision , theGenCollision ) ;
-      m_pileUpCollisionsVector.pop_back() ;
-      delete pileUpCollision ;
-    }
-  }
-  return result ;
-}
-
-//=============================================================================
-// Print the counters
-//=============================================================================
-void Special::printCounters( ) const {
-  using namespace GenCounters ;
-  printEfficiency( m_xmlLogTool , "generator level cut" , m_nEventsAfterCut ,
-                   m_nEventsBeforeCut ) ;
-}
-
-//=============================================================================
-// Generate PileUp Minimum Bias interactions
-//=============================================================================
-void Special::generatePileUp() {
-
-  if ( 0 == m_pileUpProductionTool ) {
-    if ( "" != m_pileUpProductionToolName ) {
-      m_pileUpProductionTool =
-        tool< IProductionTool >( m_pileUpProductionToolName , this ) ;
-      m_pileUpProductionTool -> initializeGenerator() ;
-    }
-  }
-
-  if ( 0 == m_pileUpProductionTool ) {
-    fatal() << "No pile up production tool defined !" << endmsg ;
-    return ;
-  }
-
-  // initialize the production tool for pile up generation
-  if ( m_reinitialize )
-    m_pileUpProductionTool -> initializeGenerator() ;
-
-  // generate given number of events
-  for ( unsigned int i = 0 ; i < m_maxInteractions ; ++i ) {
-    HepMC::GenEvent * theEvent = new HepMC::GenEvent ;
-    LHCb::GenCollision * theCollision = new LHCb::GenCollision ;
-    m_pileUpProductionTool -> generateEvent( theEvent ,
-                                             theCollision ) ;
-
-    m_pileUpEventsVector.push_back( theEvent ) ;
-    m_pileUpCollisionsVector.push_back( theCollision ) ;
-  }
-
-  // now initialize the production tool for the "signal"
-  if ( m_reinitialize )
-    m_productionTool -> initializeGenerator() ;
-  //TODO : add finalize function to delete remaining events
-}
-
-//=============================================================================
-// Copy collisions
-//=============================================================================
-void Special::copyCollision( const LHCb::GenCollision * FROM ,
-                             LHCb::GenCollision * TO ) const {
-  TO -> setIsSignal( FROM -> isSignal() ) ;
-  TO -> setProcessType( FROM -> processType() ) ;
-  TO -> setSHat( FROM -> sHat() ) ;
-  TO -> setTHat( FROM -> tHat() ) ;
-  TO -> setUHat( FROM -> uHat() ) ;
-  TO -> setPtHat( FROM -> ptHat() ) ;
-  TO -> setX1Bjorken( FROM -> x1Bjorken() ) ;
-  TO -> setX2Bjorken( FROM -> x2Bjorken() ) ;
-}
diff --git a/Gen/Generators/src/component/Special.h b/Gen/Generators/src/component/Special.h
deleted file mode 100755
index 0e5754d21..000000000
--- a/Gen/Generators/src/component/Special.h
+++ /dev/null
@@ -1,84 +0,0 @@
-// $Id: Special.h,v 1.5 2007-03-08 13:42:17 robbep Exp $
-#ifndef GENERATORS_SPECIAL_H
-#define GENERATORS_SPECIAL_H 1
-
-// Include files
-// from Gaudi
-#include "GaudiAlg/GaudiTool.h"
-#include "Generators/ExternalGenerator.h"
-
-// forward declarations
-class ICounterLogFile ;
-
-/** @class Special Special.h
- *
- *  Tool for special samples (Higgs, W, Z, ...) generation.
- *  Concrete implementation of ISampleGenerationTool using
- *  the ExternalGenerator base class.
- *
- *  @author Patrick Robbe
- *  @date   2005-11-14
- */
-class Special : public ExternalGenerator {
- public:
-  /// Standard constructor
-  Special( const std::string& type, const std::string& name,
-           const IInterface* parent);
-
-  virtual ~Special( ); ///< Destructor
-
-  /// Initialize method
-  StatusCode initialize( ) override;
-
-  /// Finalize function
-  StatusCode finalize() override;
-
-  /** Generate a single interaction (No Pile-up for the moment.
-   *  Implements ISampleGenerationTool::generate.
-   *  Accepts all events generated with the IProductionTool
-   *  (usually configured with special options) and passing
-   *  the generator level cut.
-   */
-  bool generate( const unsigned int nPileUp ,
-                 LHCb::HepMCEvents * theEvents ,
-                 LHCb::GenCollisions * theCollisions ) override;
-
-  /// Implements ISampleGenerationTool::printCounters
-  void printCounters( ) const override;
-
-private:
-  /// XML Log file
-  ICounterLogFile * m_xmlLogTool ;
-
-  /// Counter of events before the generator level cut
-  unsigned int m_nEventsBeforeCut ;
-
-  /// Counter of events after the generator level cut
-  unsigned int m_nEventsAfterCut ;
-
-  /// Number of pile-up events to generate at once
-  unsigned int m_maxInteractions ;
-
-  /// Vector to contain pile-up events
-  std::vector< HepMC::GenEvent * > m_pileUpEventsVector ;
-
-  /// Vector to contain collision infos
-  std::vector< LHCb::GenCollision * > m_pileUpCollisionsVector ;
-
-  /// function to generate a set of pile up events
-  void generatePileUp() ;
-
-  /// production tool which generates pile-up interactions
-  IProductionTool * m_pileUpProductionTool ;
-
-  /// flag to reinitialize the pile up generator
-  bool m_reinitialize ;
-
-  /// Name of the production tool for pile-up
-  std::string m_pileUpProductionToolName ;
-
-  /// Copy collision FROM to TO
-  void copyCollision( const LHCb::GenCollision * FROM ,
-                      LHCb::GenCollision * TO ) const ;
-};
-#endif // GENERATORS_SPECIAL_H
diff --git a/Gen/Generators/src/component/StandAloneDecayTool.cpp b/Gen/Generators/src/component/StandAloneDecayTool.cpp
deleted file mode 100755
index 93f079766..000000000
--- a/Gen/Generators/src/component/StandAloneDecayTool.cpp
+++ /dev/null
@@ -1,114 +0,0 @@
-// $Id: StandAloneDecayTool.cpp,v 1.4 2008-07-24 22:06:07 robbep Exp $
-// Include files 
-#include "StandAloneDecayTool.h"
-
-// from Gaudi
-#include "Kernel/IParticlePropertySvc.h"
-#include "Kernel/ParticleProperty.h"
-
-// from Generators
-#include "MCInterfaces/IDecayTool.h"
-
-//-----------------------------------------------------------------------------
-// Implementation file for class : StandAloneDecayTool
-//
-// 2006-04-18 : Patrick Robbe
-//-----------------------------------------------------------------------------
-
-// Declaration of the tool factory
-
-DECLARE_COMPONENT( StandAloneDecayTool )
-
-//=============================================================================
-// const constructor, initializes variables
-//=============================================================================
-StandAloneDecayTool::StandAloneDecayTool( const std::string& type ,
-                                          const std::string& name ,
-                                          const IInterface * parent )
-  : Signal ( type , name , parent ) , m_signalMass( 0. ) {
-    declareProperty ( "Inclusive" , m_inclusive = false ) ;
-  } 
-//=============================================================================
-// Destructor
-//=============================================================================
-StandAloneDecayTool::~StandAloneDecayTool() {} 
-
-//=============================================================================
-// Initialization
-//=============================================================================
-StatusCode StandAloneDecayTool::initialize() {
-  StatusCode sc = Signal::initialize(); // must be executed first
-  if ( sc.isFailure() ) return sc;  // error printed already by GaudiAlgorithm
-
-  debug() << "==> Initialize" << endmsg;
-
-  LHCb::IParticlePropertySvc * ppSvc = 
-    svc< LHCb::IParticlePropertySvc >( "LHCb::ParticlePropertySvc" ) ;
-  const LHCb::ParticleProperty * prop = ppSvc -> find( LHCb::ParticleID( *m_pids.begin() ) ) ;
-  m_signalMass = prop -> mass() ;
-
-  release( ppSvc ) ;
-
-  return StatusCode::SUCCESS;
-}
-
-//=============================================================================
-// Main execution
-//=============================================================================
-bool StandAloneDecayTool::generate( const unsigned int nPileUp , 
-                                    LHCb::HepMCEvents * theEvents ,
-                                    LHCb::GenCollisions * theCollisions ) {
-  // prepare event
-  LHCb::GenCollision * theGenCollision( 0 ) ;
-  HepMC::GenEvent * theGenEvent( 0 ) ;
-
-  // generate the requested number of "pile-up" events
-  for ( unsigned int i = 0 ; i < nPileUp ; ++i ) {
-    prepareInteraction( theEvents , theCollisions , theGenEvent , 
-                        theGenCollision ) ;
-    
-    // Particle to decay
-    HepMC::GenParticle * theParticle = new HepMC::GenParticle( ) ;
-    theParticle -> 
-      set_momentum( HepMC::FourVector( 0. , 0. , 0., m_signalMass ) ) ;
-
-    // Decay the particle at (0,0,0,0)
-    HepMC::GenVertex * theVertex = 
-      new HepMC::GenVertex( HepMC::FourVector( 0., 0., 0., 0. ) ) ;
-    theGenEvent -> add_vertex( theVertex ) ;
-    theVertex -> add_particle_out( theParticle ) ;
-    
-    bool flip( false ) ;
-    
-    int thePID = *m_pids.begin() ;
-    if ( m_cpMixture ) {
-      // decide the PID to generate
-      double flavour = m_flatGenerator() ;
-      m_decayTool -> enableFlip() ;
-      
-      if ( flavour < 0.5 ) 
-        theParticle -> set_pdg_id( +abs( thePID ) ) ;
-      else
-        theParticle -> set_pdg_id( -abs( thePID ) ) ;
-    } else {
-      m_decayTool -> disableFlip() ;
-      theParticle -> set_pdg_id( thePID ) ;
-    }
-
-    if ( ! m_inclusive ) 
-      m_decayTool -> generateSignalDecay( theParticle , flip ) ;
-    else 
-      m_decayTool -> generateDecay( theParticle ) ;
-    
-    theParticle -> set_status( LHCb::HepMCEvent::SignalInLabFrame ) ;
-  
-    theGenEvent -> 
-      set_signal_process_vertex( theParticle -> end_vertex() ) ;
-    theGenCollision -> setIsSignal( true ) ;
-  }
-  
-  return true ;
-}
-
-//=============================================================================
-
diff --git a/Gen/Generators/src/component/StandAloneDecayTool.h b/Gen/Generators/src/component/StandAloneDecayTool.h
deleted file mode 100755
index 985a374d1..000000000
--- a/Gen/Generators/src/component/StandAloneDecayTool.h
+++ /dev/null
@@ -1,35 +0,0 @@
-// $Id: StandAloneDecayTool.h,v 1.3 2007-09-09 19:33:10 robbep Exp $
-#ifndef GENERATORS_STANDALONEDECAYTOOL_H
-#define GENERATORS_STANDALONEDECAYTOOL_H 1
-
-// Include files
-// from Gaudi
-#include "Generators/Signal.h"
-
-
-/** @class StandAloneDecayTool StandAloneDecayTool.h component/StandAloneDecayTool.h
- *  Class to generate decay with only the decay tool
- *
- *  @author Patrick Robbe
- *  @date   2006-04-18
- */
-class StandAloneDecayTool : public Signal {
-public:
-  /// Standard constructor
-  StandAloneDecayTool( const std::string & type , const std::string & name ,
-                       const IInterface * parent ) ;
-
-  virtual ~StandAloneDecayTool( ) ; ///< Destructor
-
-  StatusCode initialize( ) override;    ///< Tool initialization
-
-  bool generate( const unsigned int nPileUp ,
-                 LHCb::HepMCEvents * theEvents ,
-                 LHCb::GenCollisions * theCollisions ) override;
-
-private:
-  double m_signalMass ; ///< Mass of the particle to decay
-
-  bool m_inclusive ;  ///< Generate inclusive decay
-};
-#endif // GENERATORS_STANDALONEDECAYTOOL_H
diff --git a/Gen/Generators/src/component/UniformSmearVertex.cpp b/Gen/Generators/src/component/UniformSmearVertex.cpp
deleted file mode 100755
index 831949192..000000000
--- a/Gen/Generators/src/component/UniformSmearVertex.cpp
+++ /dev/null
@@ -1,124 +0,0 @@
-// $Id: UniformSmearVertex.cpp,v 1.5 2008-07-24 22:05:38 robbep Exp $
-// Include files 
-
-// local
-#include "UniformSmearVertex.h"
-
-// from Gaudi
-#include "GaudiKernel/IRndmGenSvc.h" 
-#include "GaudiKernel/PhysicalConstants.h"
-#include "GaudiKernel/Vector4DTypes.h"
-
-// from Event
-#include "Event/HepMCEvent.h"
-
-//-----------------------------------------------------------------------------
-// Implementation file for class : UniformSmearVertex
-//
-// 2007-09-07 : M.Ferro-Luzzi
-// 2007-09-27 : G.Corti, use twopi from PhysicalConstants.h instead of 
-//              hardcoded number
-//-----------------------------------------------------------------------------
-
-// Declaration of the Tool Factory
-DECLARE_COMPONENT( UniformSmearVertex )
-
-
-//=============================================================================
-// Standard constructor, initializes variables
-//=============================================================================
-UniformSmearVertex::UniformSmearVertex( const std::string& type,
-                                        const std::string& name,
-                                        const IInterface* parent )
-  : GaudiTool ( type, name , parent ) , 
-    m_rmaxsq( 0. ) , 
-    m_deltaz( 0. ) {
-    declareInterface< IVertexSmearingTool >( this ) ;
-    declareProperty( "RMax"   , m_rmax   =     1. * Gaudi::Units::mm ) ;
-    declareProperty( "ZMin"   , m_zmin   = -1500. * Gaudi::Units::mm ) ;
-    declareProperty( "ZMax"   , m_zmax   =  1500. * Gaudi::Units::mm ) ;
-    declareProperty( "BeamDirection", m_zDir = 1 );
-
-}
-
-//=============================================================================
-// Destructor 
-//=============================================================================
-UniformSmearVertex::~UniformSmearVertex( ) { ; }
-
-//=============================================================================
-// Initialize 
-//=============================================================================
-StatusCode UniformSmearVertex::initialize( ) {
-  StatusCode sc = GaudiTool::initialize( ) ;
-  if ( sc.isFailure() ) return sc ;
-  
-  if ( !(m_zmin < m_zmax) ) return Error( "zMin >= zMax !" ) ;
-  if ( !(m_rmax > 0.    ) ) return Error( "rMax <=  0  !" ) ;
-  m_deltaz =  m_zmax - m_zmin       ;
-  m_rmaxsq = m_rmax*m_rmax          ;
-
-  IRndmGenSvc* randSvc = svc< IRndmGenSvc >( "RndmGenSvc" , true ) ;
-  sc = m_flatDist.initialize( randSvc , Rndm::Flat( 0.0 , 1.0 ) ) ;
-  if ( ! sc.isSuccess() ) 
-    return Error( "Could not initialize flat random number generator" ) ;
-
-  std::string infoMsg = " applying TOF of interaction with ";
-  if ( m_zDir == -1 ) {
-    infoMsg = infoMsg + "negative beam direction";
-  } else if ( m_zDir == 1 ) {
-    infoMsg = infoMsg + "positive beam direction";
-  } else if ( m_zDir == 0 ) {
-    infoMsg = " with TOF of interaction equal to zero ";
-  } else {
-    return Error("BeamDirection can only be set to -1 or 1, or 0 to switch off TOF");
-  }
-
-  info() << "Smearing of interaction point with flat distribution "
-         << " in x, y and z " << endmsg;
-  info() << infoMsg << endmsg;
-  if( msgLevel(MSG::DEBUG) ) {
-    debug() << " with r less than " << m_rmax / Gaudi::Units::mm 
-            << " mm." << endmsg ;
-    debug() << " with z between " << m_zmin / Gaudi::Units::mm 
-            << " mm and " << m_zmax / Gaudi::Units::mm << " mm." << endmsg ;
-  } else {
-    info() << " with r <= " << m_rmax / Gaudi::Units::mm << " mm, "
-           << m_zmin / Gaudi::Units::mm << " mm <= z <= " 
-           << m_zmax / Gaudi::Units::mm << " mm." << endmsg;
-  }
-
-  release( randSvc ) ;
- 
-  return sc ;
-}
-
-//=============================================================================
-// Smearing function
-//=============================================================================
-StatusCode UniformSmearVertex::smearVertex( LHCb::HepMCEvent * theEvent ) {
-  double dx , dy , dz, dt, rsq, r, th ;
-  
-  // generate flat in z, r^2 and theta:
-  dz  = m_deltaz   * m_flatDist( ) + m_zmin ;
-  rsq = m_rmaxsq   * m_flatDist( )          ;
-  th  = Gaudi::Units::twopi * m_flatDist( ) ;
-  r   = sqrt(rsq) ;
-  dx  = r*cos(th) ;  
-  dy  = r*sin(th) ;
-  dt  = m_zDir * dz/Gaudi::Units::c_light ;
-  Gaudi::LorentzVector dpos( dx , dy , dz , dt ) ;
-  
-  HepMC::GenEvent::vertex_iterator vit ;
-  HepMC::GenEvent * pEvt = theEvent -> pGenEvt() ;
-  for ( vit = pEvt -> vertices_begin() ; vit != pEvt -> vertices_end() ; 
-        ++vit ) {
-    Gaudi::LorentzVector pos ( (*vit) -> position() ) ;
-    pos += dpos ;
-    (*vit) -> set_position( HepMC::FourVector( pos.x() , pos.y() , pos.z() ,
-                                               pos.t() ) ) ;
-  }
-
-  return StatusCode::SUCCESS ;      
-}
-
diff --git a/Gen/Generators/src/component/UniformSmearVertex.h b/Gen/Generators/src/component/UniformSmearVertex.h
deleted file mode 100755
index 34d3d37fa..000000000
--- a/Gen/Generators/src/component/UniformSmearVertex.h
+++ /dev/null
@@ -1,64 +0,0 @@
-// $Id: UniformSmearVertex.h,v 1.2 2008-05-06 08:21:00 gcorti Exp $
-#ifndef GENERATORS_UNIFORMSMEARVERTEX_H
-#define GENERATORS_UNIFORMSMEARVERTEX_H 1
-
-// Include files
-// from Gaudi
-#include "GaudiAlg/GaudiTool.h"
-#include "GaudiKernel/RndmGenerators.h"
-
-#include "Generators/IVertexSmearingTool.h"
-
-/** @class UniformSmearVertex UniformSmearVertex.h "UniformSmearVertex.h"
- *
- *  Tool to smear vertex with flat distribution along the z-axis and
- *  in the xy plane (within a radius). Simple modification of Patrick
- *  Robbe's FlatZSmearVertex.
- *  Concrete implementation of a IVertexSmearingTool.
- *
- *  @author Massi Ferro-Luzzi
- *  @date   2007-09-07
- */
-class UniformSmearVertex : public GaudiTool,
-                           virtual public IVertexSmearingTool {
- public:
-  /// Standard constructor
-  UniformSmearVertex( const std::string& type , const std::string& name,
-                      const IInterface* parent ) ;
-
-  virtual ~UniformSmearVertex( ); ///< Destructor
-
-  /// Initialize method
-  StatusCode initialize( ) override;
-
-  /** Implements IVertexSmearingTool::smearVertex.
-   *  Does the same than BeamSpotSmearVertex::smearVertex for the x and y
-   *  direction but generates flat distribution for the z-coordinate of
-   *  the primary vertex.
-   */
-  StatusCode smearVertex( LHCb::HepMCEvent * theEvent ) override;
-
- private:
-  /// Maximum value for the r coordinate of the vertex (set by options)
-  double m_rmax   ;
-
-  /// Minimum value for the z coordinate of the vertex (set by options)
-  double m_zmin   ;
-
-  /// Maximum value for the z coordinate of the vertex (set by options)
-  double m_zmax   ;
-
-  /// Square of m_rmax                     (set at initialisation)
-  double m_rmaxsq ;
-
-  /// Difference between m_zmax and m_zmin (set at initialisation)
-  double m_deltaz ;
-
-  /// Direction of the beam to take into account TOF vs nominal IP8, can have
-  /// only values -1 or 1, or 0 to switch off the TOF and set time of
-  /// interaction to zero (default = 1, as for beam 1)
-  int m_zDir;
-
-  Rndm::Numbers m_flatDist ; ///< Flat random number generator
-};
-#endif // GENERATORS_UNIFORMSMEARVERTEX_H
diff --git a/Gen/Generators/src/component/VariableLuminosity.cpp b/Gen/Generators/src/component/VariableLuminosity.cpp
deleted file mode 100755
index c58ef8056..000000000
--- a/Gen/Generators/src/component/VariableLuminosity.cpp
+++ /dev/null
@@ -1,139 +0,0 @@
-// $Id: VariableLuminosity.cpp,v 1.6 2009-04-07 16:11:21 gcorti Exp $
-// Include files
-
-// local
-#include "VariableLuminosity.h"
-
-// from Gaudi
-#include "GaudiKernel/IRndmGenSvc.h"
-
-// From CLHEP
-#include "CLHEP/Units/SystemOfUnits.h"
-
-// From Event
-#include "Event/BeamParameters.h"
-#include "Event/GenFSR.h"
-#include "Event/GenCountersFSR.h"
-
-// From Generators
-#include "Generators/GenCounters.h"
-#include "Generators/ICounterLogFile.h"
-
-//-----------------------------------------------------------------------------
-// Implementation file for class : VariableLuminosity
-//
-// 2005-08-17 : Patrick Robbe
-//-----------------------------------------------------------------------------
-
-// Declaration of the Tool Factory
-
-DECLARE_COMPONENT( VariableLuminosity )
-
-
-//=============================================================================
-// Standard constructor, initializes variables
-//=============================================================================
-VariableLuminosity::VariableLuminosity( const std::string& type,
-                                        const std::string& name,
-                                        const IInterface* parent )
-  : GaudiTool ( type, name , parent ) ,
-    m_xmlLogTool( 0 ) ,
-    m_numberOfZeroInteraction( 0 ) ,
-    m_nEvents( 0 ),
-    m_randSvc( 0 ) {
-
-    using CLHEP::s;
-    declareInterface< IPileUpTool >( this ) ;
-    declareProperty ( "GenFSRLocation", m_FSRName =
-                      LHCb::GenFSRLocation::Default);
-    declareProperty( "BeamParameters" ,
-                     m_beamParameters = LHCb::BeamParametersLocation::Default ) ;
-    declareProperty ( "FillDuration"  , m_fillDuration  = 7.0 * 3600 * s    ) ;
-    declareProperty ( "BeamDecayTime" , m_beamDecayTime = 10.0 * 3600 * s   ) ;
-}
-
-//=============================================================================
-// Destructor
-//=============================================================================
-VariableLuminosity::~VariableLuminosity( ) { ; }
-
-//=============================================================================
-// Initialize method
-//=============================================================================
-StatusCode VariableLuminosity::initialize( ) {
-  StatusCode sc = GaudiTool::initialize( ) ;
-  if ( sc.isFailure() ) return sc ;
-
-  // Initialize the number generator
-  m_randSvc = svc< IRndmGenSvc >( "RndmGenSvc" , true ) ;
-
-  // XML file
-  m_xmlLogTool = tool< ICounterLogFile >( "XmlCounterLogFile" ) ;
-
-  sc = m_flatGenerator.initialize( m_randSvc , Rndm::Flat( 0 , 1 ) ) ;
-  if ( ! sc.isSuccess() )
-    return Error( "Could not initialize flat random generator" ) ;
-
-  using CLHEP::s;
-  info() << "Poisson distribution with 'LHCb mean'. " << endmsg ;
-  info() << "Fill duration (hours): " << m_fillDuration / 3600 / s << endmsg ;
-  info() << "Beam decay time (hours): " << m_beamDecayTime / 3600 / s
-         << endmsg ;
-
-  return sc ;
-}
-
-//=============================================================================
-// Compute the number of pile up to generate according to beam parameters
-//=============================================================================
-unsigned int VariableLuminosity::numberOfPileUp( ) {
-  LHCb::BeamParameters * beam = get< LHCb::BeamParameters >( m_beamParameters ) ;
-  if ( 0 == beam ) Exception( "No beam parameters registered" ) ;
-
-  LHCb::GenFSR* genFSR = nullptr;
-  if(m_FSRName != ""){
-    IDataProviderSvc* fileRecordSvc = svc<IDataProviderSvc>("FileRecordDataSvc", true);
-    genFSR = getIfExists<LHCb::GenFSR>(fileRecordSvc, m_FSRName, false);
-    if(!genFSR) warning() << "Could not find GenFSR at " << m_FSRName << endmsg;
-  }
-  int key = 0;
-
-  unsigned int result = 0 ;
-  double mean , currentLuminosity;
-  while ( 0 == result ) {
-    m_nEvents++ ;
-    key = LHCb::GenCountersFSR::AllEvt;
-    if(genFSR) genFSR->incrementGenCounter(key,1);
-    currentLuminosity = beam -> luminosity() * m_fillDuration / m_beamDecayTime /
-      ( 1.0 - exp( -m_fillDuration / m_beamDecayTime ) ) ;
-
-    mean = currentLuminosity * beam -> totalXSec() / beam -> revolutionFrequency() ;
-    Rndm::Numbers poissonGenerator( m_randSvc , Rndm::Poisson( mean ) ) ;
-    result = (unsigned int) poissonGenerator() ;
-    if ( 0 == result ) {
-      m_numberOfZeroInteraction++ ;
-      key =LHCb::GenCountersFSR::ZeroInt;
-      if(genFSR) genFSR->incrementGenCounter(key, 1);
-    }
-  }
-
-  return result ;
-}
-
-//=============================================================================
-// Print the specific pile up counters
-//=============================================================================
-void VariableLuminosity::printPileUpCounters( ) {
-  using namespace GenCounters ;
-  printCounter( m_xmlLogTool , "all events (including empty events)" , m_nEvents ) ;
-  printCounter( m_xmlLogTool , "events with 0 interaction" ,
-                m_numberOfZeroInteraction ) ;
-}
-
-//=============================================================================
-// Finalize method
-//=============================================================================
-StatusCode VariableLuminosity::finalize( ) {
-  release( m_randSvc ) ;
-  return GaudiTool::finalize( ) ;
-}
diff --git a/Gen/Generators/src/component/VariableLuminosity.h b/Gen/Generators/src/component/VariableLuminosity.h
deleted file mode 100755
index 55ec9f29e..000000000
--- a/Gen/Generators/src/component/VariableLuminosity.h
+++ /dev/null
@@ -1,77 +0,0 @@
-// $Id: VariableLuminosity.h,v 1.3 2009-04-07 16:11:21 gcorti Exp $
-#ifndef GENERATORS_VARIABLELUMINOSITY_H
-#define GENERATORS_VARIABLELUMINOSITY_H 1
-
-// Include files
-// from Gaudi
-#include "GaudiAlg/GaudiTool.h"
-#include "GaudiKernel/RndmGenerators.h"
-
-#include "Generators/IPileUpTool.h"
-
-// Forward declarations
-class IRndmGenSvc ;
-class ICounterLogFile ;
-
-/** @class VariableLuminosity VariableLuminosity.h "VariableLuminosity.h"
- *
- *  Tool to compute variable number of pile up events depending on beam
- *  parameters, with time-dependant luminosity. Concrete implementation
- *  of a IPileUpTool.
- *
- *  @author Patrick Robbe
- *  @date   2005-08-17
- */
-class VariableLuminosity : public GaudiTool, virtual public IPileUpTool {
-public:
-  /// Standard constructor
-  VariableLuminosity( const std::string& type, const std::string& name,
-                      const IInterface* parent);
-
-  virtual ~VariableLuminosity( ); ///< Destructor
-
-  /// Initialize method
-  StatusCode initialize( ) override;
-
-  /// Finalize method
-  StatusCode finalize( ) override;
-
-  /** Compute number of interactions and returns luminosity
-   *  Implements IPileUpTool::numberOfPileUp.
-   *  The number of pileup interactions follows a Poisson law
-   *  with mean equal to Luminosity * cross_section / crossing_frequency
-   *  The Luminosity is exponentially decreasing with beam decay time.
-   *  The mean luminosity is given in options so the maximum luminosity
-   *  (at t=0) is computed using the fill duration.
-   */
-  unsigned int numberOfPileUp( ) override;
-
-  /// Implements IPileUpTool::printPileUpCounters
-  void printPileUpCounters( ) override;
-
-private:
-  /// Location where to store FSR counters (set by options)
-  std::string  m_FSRName;
-
-  std::string m_beamParameters ; ///< Location of beam parameters (set by options)
-
-  double m_fillDuration ; ///< Fill duration (set by options)
-
-  double m_beamDecayTime ; ///< Beam decay time (set by options)
-
-  /// XML Log tool
-  ICounterLogFile * m_xmlLogTool ;
-
-  /// Counter of empty interactions
-  int    m_numberOfZeroInteraction ;
-
-  /// Counter of events (including empty interactions)
-  int    m_nEvents ;
-
-  /// Random number generator service
-  IRndmGenSvc * m_randSvc ;
-
-  /// Flat random number generator
-  Rndm::Numbers m_flatGenerator ;
-};
-#endif // GENERATORS_VARIABLELUMINOSITY_H
diff --git a/Gen/Generators/src/component/WriteHepMCAsciiFile.cpp b/Gen/Generators/src/component/WriteHepMCAsciiFile.cpp
deleted file mode 100755
index e5cb53c57..000000000
--- a/Gen/Generators/src/component/WriteHepMCAsciiFile.cpp
+++ /dev/null
@@ -1,163 +0,0 @@
-// $Id: WriteHepMCAsciiFile.cpp,v 1.3 2008-07-09 14:39:08 robbep Exp $
-//
-// ============================================================================
-// Include files
-// ============================================================================
-// GaudiKernel
-// ============================================================================
-#include "GaudiKernel/SystemOfUnits.h"
-#include "GaudiKernel/PhysicalConstants.h"
-// ============================================================================
-// GaudiAlg
-// ============================================================================
-#include "GaudiAlg/GaudiAlgorithm.h"
-// ============================================================================
-// Event
-// ============================================================================
-#include "Event/HepMCEvent.h"
-// ============================================================================
-// HepMC
-// ============================================================================
-#include "HepMC/IO_GenEvent.h"
-// ============================================================================
-/** @class WriteHepMCAsciiFile WriteHepMCAsciiFile.cpp
- *
- *  Simple class to dump generators events in plain
- *  output file in HepMC Ascii format. It could be used for portable
- *  cross-transitions of events inbetween different generators
- *
- *   The algorithm has 3 properties:
- *
- *    - <c>Input</c>  : The TES location of LHCb::HepMCEvent::Container
- *              ( the default value is <c>LHCb::HepMCEventLocation::Default</c>)
- *    - <c>Ouput</c>  : The name of output HepMC Ascii file.
- *                     The file is opened in "new/overwrite" mode.
- *                     ( the default value is <c>""</c> (empty string)
- *
- *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
- *  @date 2005-10-05
- */
-class WriteHepMCAsciiFile : public GaudiAlgorithm
-{
-public:
-  /// initialize the algorithm
-  StatusCode initialize () override
-  {
-    StatusCode sc = GaudiAlgorithm::initialize() ;
-    if ( sc.isFailure() ) { return sc ; }
-    /// check the output file
-    if ( m_output.empty() )
-    { return Error ( "Output file name is not specified!" ) ; }
-    // open the file
-    m_file = new HepMC::IO_GenEvent
-      ( m_output.c_str() , std::ios::out | std::ios::trunc ) ;
-    //
-    if ( 0 == m_file || m_file->rdstate() == std::ios::failbit )
-    { return Error ( "Failure to open the file '"+m_output+"'" ) ; }
-    if(m_momentum_unit_name == "GeV"){
-      m_momentum_unit = HepMC::Units::GEV;
-    } else if (m_momentum_unit_name == "MeV") {
-      m_momentum_unit = HepMC::Units::MEV;
-    } else {
-      return Error("Invalid momentum unit");
-    }
-
-    if(m_length_unit_name == "CM"){
-      m_length_unit = HepMC::Units::CM;
-    } else if (m_length_unit_name == "MM") {
-      m_length_unit = HepMC::Units::MM;
-    } else {
-      return Error("Invalid length unit");
-    }
-    //
-    //m_file->write_comment( "Written by WriteHepMCAsciiFile/"+name() );
-    //
-    return StatusCode::SUCCESS ;
-  } ;
-  /// execute it!
-  StatusCode execute    () override;
-  /// finalize the algorithm
-  StatusCode finalize   () override
-  {
-    // delete the stream  (close the file!)
-    if ( 0 != m_file ) { delete m_file ; m_file = 0 ; }
-    // finalize the base class ;
-    return GaudiAlgorithm::finalize() ;
-  }
-  /** standard constructor
-   *  @param name algorithm instance name
-   *  @param pSvc ppinter to Service Locator
-   */
-  WriteHepMCAsciiFile
-  ( const std::string& name ,
-    ISvcLocator*       pSvc )
-    : GaudiAlgorithm ( name , pSvc )
-    // default location of HepMC events in TES
-    , m_input    ( LHCb::HepMCEventLocation::Default )
-    // no default value!
-    , m_output   (   )
-    // the file itself
-    , m_file     ( 0 )
-  {
-    declareProperty  ( "Input"   , m_input   ) ;
-    declareProperty  ( "Output"  , m_output  ) ;
-    declareProperty  ( "MomentumUnit" , m_momentum_unit_name = "", "Momentum unit [GeV, MeV]") ;
-    declareProperty  ( "LengthUnit" , m_length_unit_name = "MM", "Length unit [MM, CM]") ;
-  } ;
-  virtual ~WriteHepMCAsciiFile()
-  { if ( 0 != m_file ) { delete m_file ; m_file = 0  ; } }
-private:
-  // TES location of HepMC-events
-  std::string      m_input  ; ///< TES location of HepMC-events
-  // the name of the output file
-  std::string      m_output ; ///< the name of the output file
-  // rescale event from LHCb to Pythia units ?
-  std::string m_momentum_unit_name{};
-  std::string m_length_unit_name{}; ///< rescale event from LHCb units ?
-  HepMC::Units::MomentumUnit m_momentum_unit;
-  HepMC::Units::LengthUnit m_length_unit;
-  // the output file ;
-  HepMC::IO_GenEvent* m_file   ; ///< the output file ;
-} ;
-// ===========================================================================
-/// Declaration of the Algorithm Factory
-DECLARE_COMPONENT( WriteHepMCAsciiFile )
-// ===========================================================================
-/// Execut the algorithm
-StatusCode WriteHepMCAsciiFile::execute    ()
-{
-  /// get input events
-  LHCb::HepMCEvent::Container* events
-    = get<LHCb::HepMCEvent::Container>( m_input ) ;
-  if ( 0 == events ) { return StatusCode::FAILURE ; }
-  //
-  Assert ( 0 != m_file , "File is invalid!" ) ;
-  //
-  // loop over events and write them
-  for ( LHCb::HepMCEvent::Container::iterator
-          ievent = events->begin() ; events->end() != ievent  ; ++ievent )
-  {
-    LHCb::HepMCEvent* event = *ievent ;
-    if ( 0 == event ) { continue ; }
-    HepMC::GenEvent* evt = event->pGenEvt();
-    if ( 0 == evt   ) { continue ; }
-    auto old_mom_unit = evt->momentum_unit();
-    auto old_length_unit = evt->length_unit();
-
-    // rescale the event if needed
-    evt->use_units(m_momentum_unit, m_length_unit);
-
-    // write event to ascii file
-    m_file->write_event(evt); 	//also writes HeavyIon and PdfInfo!
-
-    // rescale back if needed (convert to LHCb units)
-    evt->use_units(old_mom_unit, old_length_unit);
-  }
-  //
-  return StatusCode::SUCCESS ;
-}
-// ===========================================================================
-
-// ===========================================================================
-// The END
-// ===========================================================================
diff --git a/Gen/Generators/src/component/XmlCounterLogFile.cpp b/Gen/Generators/src/component/XmlCounterLogFile.cpp
deleted file mode 100644
index 35fb3c2fd..000000000
--- a/Gen/Generators/src/component/XmlCounterLogFile.cpp
+++ /dev/null
@@ -1,154 +0,0 @@
-// Include files
-// local
-#include "XmlCounterLogFile.h"
-
-// from BOOST
-#include "boost/filesystem/path.hpp"
-#include "boost/filesystem.hpp"
-
-// from Gaudi
-
-
-//-----------------------------------------------------------------------------
-// Implementation file for class : XmlCounterLogFile
-//
-// 2013-01-15 : Patrick Robbe
-//-----------------------------------------------------------------------------
-
-// Declaration of the Tool Factory
-DECLARE_COMPONENT( XmlCounterLogFile )
-
-
-//=============================================================================
-// Standard constructor, initializes variables
-//=============================================================================
-XmlCounterLogFile::XmlCounterLogFile( const std::string& type,
-                                      const std::string& name,
-                                      const IInterface* parent )
-: GaudiTool ( type, name , parent ) , m_version( "1.1" ) 
-{
-  declareInterface<ICounterLogFile>(this);
-  declareProperty( "FileName" , m_fileName = "GeneratorLog.xml" ) ;
-}
-
-//=============================================================================
-// Destructor
-//=============================================================================
-XmlCounterLogFile::~XmlCounterLogFile() {} 
-
-//=============================================================================
-// Add efficiency in xml file
-//=============================================================================
-void XmlCounterLogFile::addEfficiency( const std::string & name , const unsigned int after , 
-                                       const unsigned int before , const double fraction , 
-                                       const double err_fraction )
-{
-  m_file << "  <efficiency name = \"" << name << "\">" << std::endl 
-         << "    <after> " << after << " </after>" << std::endl
-         << "    <before> " << before << " </before>" << std::endl 
-         << "    <value> " << format( "%.5g" , fraction ) << " </value>" << std::endl 
-         << "    <error> " << format( "%.5g" ,err_fraction ) << " </error>" << std::endl 
-         << "  </efficiency>" << std::endl ;
-}
-
-//=============================================================================
-// Add counter in xml file
-//=============================================================================
-void XmlCounterLogFile::addCounter( const std::string & name , const unsigned int value ) 
-{
-  m_file << "  <counter name = \"" << name << "\">" << std::endl
-         << "    <value> " << value << " </value>" << std::endl 
-         << "  </counter>" << std::endl ;
-}
-
-//=============================================================================
-// Add fraction in xml file
-//=============================================================================
-void XmlCounterLogFile::addFraction( const std::string & name , const unsigned int number , 
-                                     const double fraction , const double err_fraction ) 
-{
-  m_file << "  <fraction name = \"" << name << "\">" << std::endl 
-         << "    <number> " << number << " </number>" << std::endl
-         << "    <value> " << format( "%.5g" , fraction ) << " </value>" << std::endl 
-         << "    <error> " << format( "%.5g" , err_fraction ) << " </error>" << std::endl 
-         << "  </fraction>" << std::endl ;
-}
-
-//=============================================================================
-// Add cross section value
-//=============================================================================
-void XmlCounterLogFile::addCrossSection( const std::string & name , 
-                                         const unsigned int processId , 
-                                         const unsigned int number , 
-                                         const double value ) 
-{
-  m_file << "  <crosssection id = \"" << processId << "\">" << std::endl 
-         << "    <description> \""<< name << "\" </description>" << std::endl
-         << "    <generated> " << number << " </generated>" << std::endl 
-         << "    <value> " << format( "%.5g" , value ) << " </value>" << std::endl 
-         << "  </crosssection>" << std::endl ;
-}
-
-//=============================================================================
-// Add event type value
-//=============================================================================
-void XmlCounterLogFile::addEventType( const unsigned int evType )
-{
-  m_file << "  <eventType>" << evType << "</eventType>" << std::endl ;
-}
-
-//=============================================================================
-// Add version value
-//=============================================================================
-void XmlCounterLogFile::addGaussVersion( const std::string & version )
-{
-  m_file << "  <gaussVersion>" << version << "</gaussVersion>" << std::endl ;
-}
-
-//=============================================================================
-// Add version value
-//=============================================================================
-void XmlCounterLogFile::addMethod( const std::string & type )
-{
-  m_file << "  <method>" << type << "</method>" << std::endl ;
-}
-
-//=============================================================================
-// Add version value
-//=============================================================================
-void XmlCounterLogFile::addGenerator( const std::string & generator )
-{
-  m_file << "  <generator>" << generator << "</generator>" << std::endl ;
-}
-
-//=============================================================================
-// Initialize function
-//=============================================================================
-StatusCode XmlCounterLogFile::initialize( ) 
-{
-  StatusCode sc = GaudiTool::initialize( ) ;
-  if ( sc.isFailure() ) return sc ;
-
-  // Opens the file
-  if ( boost::filesystem::exists( m_fileName ) ) boost::filesystem::remove( m_fileName ) ;
-  
-  m_file.open( m_fileName.c_str() ) ;
-  if (  ! m_file.is_open() ) 
-    return Error( "Cannot open xml log file" ) ;
-  
-  m_file << "<?xml version=\"1.0\"?>" << std::endl 
-         << "<generatorCounters>" << std::endl 
-         << "  <version>" << m_version << "</version>" << std::endl ;
-
-  return StatusCode::SUCCESS ;
-}
-
-//=============================================================================
-// Finalize function
-//=============================================================================
-StatusCode XmlCounterLogFile::finalize( ) 
-{
-  m_file << "</generatorCounters>" << std::endl ;
-  m_file.close() ;
-  return GaudiTool::finalize( ) ;
-}
diff --git a/Gen/Generators/src/component/XmlCounterLogFile.h b/Gen/Generators/src/component/XmlCounterLogFile.h
deleted file mode 100644
index 0f515923a..000000000
--- a/Gen/Generators/src/component/XmlCounterLogFile.h
+++ /dev/null
@@ -1,67 +0,0 @@
-#ifndef GENERATORS_XMLCOUNTERLOGFILE_H
-#define GENERATORS_XMLCOUNTERLOGFILE_H 1
-
-// Include files
-// from STL
-#include <string>
-#include <fstream>
-
-// from Gaudi
-#include "GaudiAlg/GaudiTool.h"
-#include "Generators/ICounterLogFile.h"            // Interface
-
-/** @class XmlCounterLogFile XmlCounterLogFile.h component/XmlCounterLogFile.h
- *
- *  Tool to write counters in a xml file
- *
- *  @author Patrick Robbe
- *  @date   2013-01-15
- */
-class XmlCounterLogFile : public GaudiTool, virtual public ICounterLogFile {
-public:
-  /// Standard constructor
-  XmlCounterLogFile( const std::string& type,
-                     const std::string& name,
-                     const IInterface* parent);
-
-  virtual ~XmlCounterLogFile( ); ///< Destructor
-
-  /// Initialize method
-  StatusCode initialize( ) override;
-
-  /// Finalize method
-  StatusCode finalize( ) override;
-
-  /// Add efficiency number
-  void addEfficiency( const std::string & name , const unsigned int after ,
-                      const unsigned int before , const double fraction ,
-                      const double err_fraction ) override;
-
-  void addCounter( const std::string & name , const unsigned int value ) override;
-
-  void addFraction( const std::string & name , const unsigned int number ,
-                    const double fraction , const double err_fraction ) override;
-
-  void addCrossSection( const std::string & name ,
-                        const unsigned int processId ,
-                        const unsigned int number ,
-                        const double value ) override;
-
-  void addEventType( const unsigned int evType ) override;
-
-  /// Add the Gauss version
-  void addGaussVersion( const std::string & version ) override;
-
-  void addMethod( const std::string & type ) override;
-
-  void addGenerator( const std::string & generator ) override;
-
-protected:
-
-private:
-  std::string     m_version ;
-  std::string     m_fileName ;
-  std::ofstream   m_file ;
-
-};
-#endif // GENERATORS_XMLCOUNTERLOGFILE_H
diff --git a/Gen/Generators/CMakeLists.txt b/Gen/LbEvtGen/CMakeLists.txt
similarity index 50%
rename from Gen/Generators/CMakeLists.txt
rename to Gen/LbEvtGen/CMakeLists.txt
index 6d8f44f10..d22613c89 100644
--- a/Gen/Generators/CMakeLists.txt
+++ b/Gen/LbEvtGen/CMakeLists.txt
@@ -1,35 +1,27 @@
 ################################################################################
-# Package: Generators
+# Package: LbEvtGen
 ################################################################################
-gaudi_subdir(Generators v16r0)
+gaudi_subdir(LbEvtGen v1r0)
 
-gaudi_depends_on_subdirs(Event/GenEvent
-                         GaudiAlg
+gaudi_depends_on_subdirs(Gen/Generators
                          Gen/EvtGen
                          Gen/EvtGenExtras
-                         Kernel/MCInterfaces
-                         Kernel/LHCbKernel
-                         Kernel/PartProp)
+                         HepMCUser
+                         Utils)
+                         
 
 find_package(Boost COMPONENTS filesystem system)
 find_package(ROOT)
-find_package(HepMC)
 find_package(Photos++)
-include_directories(SYSTEM ${Boost_INCLUDE_DIRS} ${HEPMC_INCLUDE_DIRS} ${ROOT_INCLUDE_DIRS} ${PHOTOS++_INCLUDE_DIRS})
+AddHepMC3()
+include_directories(SYSTEM ${Boost_INCLUDE_DIRS} ${ROOT_INCLUDE_DIRS} ${PHOTOS++_INCLUDE_DIRS})
 
 string(REPLACE "-pedantic" "" CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS}")
 string(REPLACE "-Wall" "" CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS}")
 string(REPLACE "-Wextra" "" CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS}")
 string(REPLACE "-Werror=return-type" "" CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS}")
 
-gaudi_add_library(GeneratorsLib
-                  src/Lib/*.cpp src/Lib/*.F
-                  PUBLIC_HEADERS Generators
-                  INCLUDE_DIRS Kernel/MCInterfaces
-                  LINK_LIBRARIES GenEvent GaudiAlgLib EvtGen EvtGenExtras PartPropLib)
-
-gaudi_add_module(Generators
-                 src/component/*.cpp
+gaudi_add_module(LbEvtGen
+                 src/*.cpp
                  INCLUDE_DIRS Boost Kernel/MCInterfaces
-                 LINK_LIBRARIES Boost GenEvent GaudiAlgLib LHCbKernel EvtGen EvtGenExtras GeneratorsLib)
-
+                 LINK_LIBRARIES Boost GenEvent GaudiAlgLib LHCbKernel EvtGen EvtGenExtras GeneratorsLib HepMCUtils)
diff --git a/Gen/Generators/src/component/EvtGenDecay.cpp b/Gen/LbEvtGen/src/EvtGenDecay.cpp
similarity index 82%
rename from Gen/Generators/src/component/EvtGenDecay.cpp
rename to Gen/LbEvtGen/src/EvtGenDecay.cpp
index f3e91530f..899a72f22 100755
--- a/Gen/Generators/src/component/EvtGenDecay.cpp
+++ b/Gen/LbEvtGen/src/EvtGenDecay.cpp
@@ -22,13 +22,6 @@
 #include "Kernel/ParticleID.h"
 #include "GaudiKernel/SystemOfUnits.h"
 #include "GaudiKernel/PhysicalConstants.h"
-// from Event
-#include "Event/HepMCEvent.h"
-
-// from HepMC
-#include "HepMC/GenParticle.h"
-#include "HepMC/GenVertex.h"
-#include "HepMC/GenEvent.h"
  
 // from EvtGen
 #include "EvtGen/EvtGen.hh"
@@ -43,13 +36,13 @@
 #include "EvtGenModels/EvtModelRegExtras.hh"
 
 #include "Generators/StreamForGenerator.h"
-#include "Generators/IProductionTool.h"
+#include "GenInterfaces/IProductionTool.h"
 #include "Generators/F77Utils.h" 
 #include "Generators/LbTaula.h"
 #include "Generators/LbPhotos.h"
 
-//EvtGen holding tool
-#include "IEvtGenTool.h"
+#include "HepMCUser/Status.h"
+#include "HepMCUtils/PrintDecayTree.h"
 
 //-----------------------------------------------------------------------------
 // Implementation file for class : EvtGenDecay
@@ -60,55 +53,6 @@
 
 DECLARE_COMPONENT( EvtGenDecay )
 
-//=============================================================================
-// Standard constructor, initializes variables
-//=============================================================================
-EvtGenDecay::EvtGenDecay( const std::string& type,
-                          const std::string& name,
-                          const IInterface* parent )
-  : GaudiTool ( type, name , parent ),
-    m_gen(0),
-    m_randomEngine(0),
-    // Minimum value for ctau in particle property data.
-    // Below, it is set to 0
-    m_minctau( 1.e-4 * Gaudi::Units::mm ) ,
-    // Maximum value for ctau in particle property data.
-    // Above, it is set to 0
-    m_maxctau( 1.e+16 * Gaudi::Units::mm ) ,
-    // Minimum value for Gamma in particle property data.
-    // Below, it is set to 0
-    m_minwidth( 1.5e-6 * Gaudi::Units::GeV ) ,
-    // Unit for Taula output
-    m_taulaUnit( 6 ) ,
-    // Unit for PHOTOS output
-    m_photosUnit( 6 ) {
-    // Declare IEvtGenDecay interface
-    declareInterface<IDecayTool>( this ) ;
-    // Declare properties for EvtGen
-    // The generic decay file
-    declareProperty("DecayFile" , m_decayFile = "empty" ) ;
-    // The signal decay file
-    declareProperty("UserDecayFile" , m_userDecay = "empty" ) ;
-    // Keep temporary evt.pdl file
-    declareProperty("KeepTempEvtFile" , m_keepTempEvtFile = false ) ;
-    // Generate Polarized Lambda_b decays
-    declareProperty("PolarizedLambdad" , m_generatePolLambdab = false ) ;
-    declareProperty("TransverseLambdabPol", m_lambdabPol = 1.0 );
-    // Generate Polarized charmonium
-    declareProperty("PolarizedCharmonium" , m_generatePolCharmonium = false ) ;
-    // Parameters for charmonium polarization
-    declareProperty("RealHelOne"  , m_realHelOne  = 1. ) ;
-    declareProperty("ImHelOne"    , m_imHelOne    = 0. ) ;
-    declareProperty("RealHelZero" , m_realHelZero = 1. ) ;
-    declareProperty("ImHelZero"   , m_imHelZero   = 0. ) ;   
-    // Initialize signalId
-    m_signalId = EvtId( -1, -1 ) ;
-}
-
-//=============================================================================
-// Destructor
-//=============================================================================
-EvtGenDecay::~EvtGenDecay( ) { }
 
 //=============================================================================
 // Initialize method
@@ -120,10 +64,6 @@ StatusCode EvtGenDecay::initialize( ) {
   MsgStream * msg = new MsgStream( msgSvc() , name() ) ;
   StreamForGenerator::getStream() = msg ;
 
-  //EvtGenTool
-  debug() << "Getting EvtGenTool" << endmsg ;
-  m_evtgentool = tool<IEvtGenTool>("EvtGenTool") ;
-
   // Find Generic DECAY.DEC file
   // Default location (if not specified in job options is  $DECFILESROOT/dkfiles/DECAY.DEC
   if ( m_decayFile.empty() || "empty" == m_decayFile )
@@ -131,7 +71,7 @@ StatusCode EvtGenDecay::initialize( ) {
       m_decayFile  = System::getEnv( "DECFILESROOT" ) + "/dkfiles/DECAY.DEC" ;
   
   // Check if file exists:
-  if ( ! boost::filesystem::exists( m_decayFile ) ) 
+  if ( ! boost::filesystem::exists( m_decayFile.value() ) ) 
     return Error( "The specified generic decay table does not exist" ) ;
 
   // create temporary evt.pdl file filled with Gaudi ParticlePropertySvc
@@ -148,7 +88,7 @@ StatusCode EvtGenDecay::initialize( ) {
     Exception( "RndmGenSvc not found to initialize EvtGen random engine" ) ;
   }
 
-  m_randomEngine = new EvtGenGaudiRandomEngine( randSvc , sc ) ;
+  m_randomEngine = std::make_unique<RandomEngineWrapper>( );
   if ( ! sc.isSuccess() )
     return Error( "Cannot initialize EvtGenGaudiRandomService" , sc ) ;
   release( randSvc ) ;
@@ -183,11 +123,9 @@ StatusCode EvtGenDecay::initialize( ) {
   }
   
   // create EvtGen engine from decay file, evt.pdl file and random engine
-  if ( m_evtgentool -> isInit() )  m_gen = m_evtgentool->getEvtGen() ;
-  else { 
-    m_gen = new EvtGen ( m_decayFile.c_str() , evtPdlFile.string().c_str() ,
-                         m_randomEngine, isrEngine, models.get()) ;
-    m_evtgentool->setEvtGen( m_gen ) ;
+  if ( !m_gen ){
+    m_gen = std::make_unique<EvtGen>( m_decayFile.value().c_str() , evtPdlFile.string().c_str() ,
+                         m_randomEngine.get(), isrEngine, models.get()) ;
   }
   
   // Remove temporary file if not asked to keep it
@@ -195,9 +133,9 @@ StatusCode EvtGenDecay::initialize( ) {
 
   // Read the optional signal decay file
   if ( ! m_userDecay.empty() && "empty" != m_userDecay ) {
-    if ( ! boost::filesystem::exists( m_userDecay ) ) 
+    if ( ! boost::filesystem::exists( m_userDecay.value() ) ) 
       return Error( "The specified user decay file does not exist" ) ;
-    m_gen -> readUDecay( m_userDecay.c_str() ) ; 
+    m_gen -> readUDecay( m_userDecay.value().c_str() ) ; 
   }
 
   debug() << "EvtGenDecay initialized" << endmsg ;
@@ -209,11 +147,8 @@ StatusCode EvtGenDecay::initialize( ) {
 // Finalize method
 //=============================================================================
 StatusCode EvtGenDecay::finalize() {
-  delete m_randomEngine ;
   
   debug() << "EvtGenDecay finalized" << endmsg ;
- 
-  release( m_evtgentool ) ;
 	
   if ( ! ( msgLevel( MSG::DEBUG ) ) ) { 
     F77Utils::close( m_taulaUnit ) ;
@@ -229,7 +164,8 @@ StatusCode EvtGenDecay::finalize() {
 //=============================================================================
 // Generate a Decay tree from a particle theMother in the event theEvent
 //=============================================================================
-StatusCode EvtGenDecay::generateDecay( HepMC::GenParticle * theMother ) const {
+StatusCode EvtGenDecay::generateDecay( const HepMC3::GenParticlePtr & theMother ,
+                                       HepRandomEnginePtr & ) const {
   // Call EvtGen for the particle to generate
   checkParticle( theMother ) ;
 
@@ -248,7 +184,7 @@ StatusCode EvtGenDecay::generateDecay( HepMC::GenParticle * theMother ) const {
   // correct vertex for daughter particles of theMother
   // because EvtGen gives position with respect to the "root" particle
   // This reference position is production vertex of theMother
-  HepMC::GenVertex * V = theMother -> production_vertex() ;
+  auto V = theMother -> production_vertex() ;
   Gaudi::LorentzVector theOriginPosition( V -> position() ) ;
 
   // Fill HepMC event theEvent with EvtGen decay tree part
@@ -260,7 +196,7 @@ StatusCode EvtGenDecay::generateDecay( HepMC::GenParticle * theMother ) const {
 
   // Set status to "decayed by evtgen"
   theMother -> 
-    set_status( LHCb::HepMCEvent::DecayedByDecayGenAndProducedByProdGen ) ;
+    set_status( HepMC3::Status::DecayedByDecayGenAndProducedByProdGen ) ;
 
   return StatusCode::SUCCESS ;
 }
@@ -268,12 +204,12 @@ StatusCode EvtGenDecay::generateDecay( HepMC::GenParticle * theMother ) const {
 //=============================================================================
 // Generate a Decay tree from a particle theMother in the event theEvent
 //=============================================================================
-StatusCode EvtGenDecay::generateSignalDecay( HepMC::GenParticle * theMother ,
-                                             bool & flip) const {
+StatusCode EvtGenDecay::generateSignalDecay( const HepMC3::GenParticlePtr & theMother ,
+                                             bool & flip ,
+                                             HepRandomEnginePtr & ) const {
   // If particle already has daughters, return now
-  if ( 0 != theMother -> end_vertex() ) {
+  if ( theMother -> end_vertex() ) {
     flip = false ;
-    return StatusCode::SUCCESS ;
   }
   
   // Call EvtGen for the particle to generate
@@ -298,7 +234,7 @@ StatusCode EvtGenDecay::generateSignalDecay( HepMC::GenParticle * theMother ,
   // correct vertex for daughter particles of theMother
   // because EvtGen gives position with respect to the "root" particle
   // This reference position is production vertex of theMother
-  HepMC::GenVertex * PV = theMother -> production_vertex() ;
+  auto PV = theMother -> production_vertex() ;
   Gaudi::LorentzVector theOriginPosition( PV -> position() ) ;
   
   // Fill HepMC event theEvent with EvtGen decay tree part
@@ -309,7 +245,7 @@ StatusCode EvtGenDecay::generateSignalDecay( HepMC::GenParticle * theMother ,
   part -> deleteTree ( ) ;
 
   // Set status to "signal in lab frame"
-  theMother -> set_status( LHCb::HepMCEvent::SignalInLabFrame ) ;
+  theMother -> set_status( HepMC3::Status::SignalInLabFrame ) ;
 
   return StatusCode::SUCCESS ;
 }
@@ -319,8 +255,9 @@ StatusCode EvtGenDecay::generateSignalDecay( HepMC::GenParticle * theMother ,
 // It stops when the particle to decay has a mass larger than theMassLimit
 // or is of the type targetId
 //=============================================================================
-StatusCode EvtGenDecay::generateDecayWithLimit( HepMC::GenParticle * theMother ,
-                                                const int targetId ) const {
+StatusCode EvtGenDecay::generateDecayWithLimit( const HepMC3::GenParticlePtr & theMother ,
+                                                const int targetId ,
+                                                HepRandomEnginePtr & ) const {
   checkParticle( theMother ) ;
 
   EvtParticle * part( 0 ) ;
@@ -338,7 +275,7 @@ StatusCode EvtGenDecay::generateDecayWithLimit( HepMC::GenParticle * theMother ,
   // correct vertex for daughter particles of theMother
   // because EvtGen gives position with respect to the "root" particle
   // This reference position is production vertex of theMother  
-  HepMC::GenVertex * PV = theMother -> production_vertex() ;
+  auto PV = theMother -> production_vertex() ;
   Gaudi::LorentzVector theOriginPosition( PV -> position() ) ;
   
   // Fill HepMC event theEvent with EvtGen decay tree part
@@ -351,7 +288,7 @@ StatusCode EvtGenDecay::generateDecayWithLimit( HepMC::GenParticle * theMother ,
 
   // Set particle status to "decayed by evtgen"
   theMother ->
-    set_status( LHCb::HepMCEvent::DecayedByDecayGenAndProducedByProdGen ) ;
+    set_status( HepMC3::Status::DecayedByDecayGenAndProducedByProdGen ) ;
 
   return StatusCode::SUCCESS ;
 }
@@ -365,9 +302,10 @@ StatusCode EvtGenDecay::generateDecayWithLimit( HepMC::GenParticle * theMother ,
 // will be converted)
 //=============================================================================
 StatusCode EvtGenDecay::makeHepMC( EvtParticle * theEvtGenPart ,
-                                   HepMC::GenParticle * theMother ,
+                                   const HepMC3::GenParticlePtr & theMother ,
                                    const Gaudi::LorentzVector & theOrigin ,
                                    int targetId ) const {
+
   if ( 0 != theEvtGenPart->getNDaug() ) {
     // Find the vertex
     // In EvtGen all positions are defined with respect to the
@@ -381,8 +319,7 @@ StatusCode EvtGenDecay::makeHepMC( EvtParticle * theEvtGenPart ,
 
     // Create a new vertex corresponding to the decay vertex of
     // theMother and add it to theEvent
-    HepMC::GenVertex * end_vtx = 
-      new HepMC::GenVertex( HepMC::FourVector( x , y , z , t ) ) ;
+    auto end_vtx = std::make_shared<HepMC3::GenVertex>( HepMC3::FourVector( x , y , z , t ) ) ;
     theMother -> parent_event() -> add_vertex( end_vtx ) ;
     end_vtx->add_particle_in( theMother ) ;
     
@@ -396,10 +333,9 @@ StatusCode EvtGenDecay::makeHepMC( EvtParticle * theEvtGenPart ,
       double pz = momentum . get( 3 ) * Gaudi::Units::GeV ;
       
       int id = EvtPDL::getStdHep( theEvtGenPart->getDaug( it )->getId() ) ;
-      int status = LHCb::HepMCEvent::DecayedByDecayGen ;
+      int status = HepMC3::Status::DecayedByDecayGen ;
       
-      HepMC::GenParticle * prod_part = new
-        HepMC::GenParticle( HepMC::FourVector(px,py,pz,e) , id , status ) ;
+      auto prod_part = std::make_shared<HepMC3::GenParticle>( HepMC3::FourVector(px,py,pz,e) , id , status ) ;
       
       end_vtx->add_particle_out( prod_part ) ;
       
@@ -416,13 +352,13 @@ StatusCode EvtGenDecay::makeHepMC( EvtParticle * theEvtGenPart ,
           if ( theEvtGenPart->getDaug(it)->getNDaug() > 0 ) 
             prod_part -> 
               set_status
-              ( LHCb::HepMCEvent::DecayedByDecayGenAndProducedByProdGen ) ;
-          else prod_part -> set_status( LHCb::HepMCEvent::StableInDecayGen ) ;
+              ( HepMC3::Status::DecayedByDecayGenAndProducedByProdGen ) ;
+          else prod_part -> set_status( HepMC3::Status::StableInDecayGen ) ;
         }
     }
   }
   else {
-    theMother -> set_status( LHCb::HepMCEvent::StableInDecayGen ) ;
+    theMother -> set_status( HepMC3::Status::StableInDecayGen ) ;
   }
   
   return StatusCode::SUCCESS ;
@@ -669,7 +605,7 @@ bool EvtGenDecay::checkGeneric( const EvtId& id ) const {
 //=============================================================================
 // Check if the HepMC particle is a good candidate
 //=============================================================================
-void EvtGenDecay::checkParticle( const HepMC::GenParticle * thePart ) const {
+void EvtGenDecay::checkParticle( const HepMC3::GenParticlePtr & thePart ) const {
   if ( 0 == thePart -> production_vertex() ) 
     Exception( "Trying to decay a particle without production vertex" ) ;
   if ( 0 != thePart -> end_vertex ( ) ) 
@@ -681,9 +617,10 @@ void EvtGenDecay::checkParticle( const HepMC::GenParticle * thePart ) const {
 // Generate with EvtGen
 //=============================================================================
 StatusCode EvtGenDecay::callEvtGen( EvtParticle * &thePart , 
-                                   const HepMC::GenParticle * theHepMCPart ,
+                                   const HepMC3::GenParticlePtr & theHepMCPart ,
                                    const EvtId & eid ) 
 const {
+  std::lock_guard<std::recursive_mutex> locked{m_mutex};
   // Get parameters of particle to generate ( theHepMCPart )
   // Type of particle and 4-momentum
   // The mother is created outside EvtGenDecay
@@ -775,22 +712,5 @@ void EvtGenDecay::setSignal( const int pdgSignal )
   m_signalId = EvtPDL::getId( nameSignal ) ;
 }
 
-//=============================================================================
-// Implementation of class EvtGenGaudiRandomEngine
-//=============================================================================
-//=============================================================================
-// Constructor
-//=============================================================================
-EvtGenGaudiRandomEngine::EvtGenGaudiRandomEngine( IRndmGenSvc* i , 
-                                                  StatusCode & sc ) {
-  // Initialize Random Engine with flat generator
-  sc = m_randomgaudi.initialize( i , Rndm::Flat( 0 , 1 ) ) ;      
-}
-
-//=============================================================================
-// Destructor
-//=============================================================================
-EvtGenGaudiRandomEngine::~EvtGenGaudiRandomEngine( ) { 
-  m_randomgaudi.finalize( ) ;
-}
-
+/*static*/ std::unique_ptr<EvtGen> EvtGenDecay::m_gen{nullptr};
+/*static*/ std::recursive_mutex EvtGenDecay::m_mutex{};
diff --git a/Gen/Generators/src/component/EvtGenDecay.h b/Gen/LbEvtGen/src/EvtGenDecay.h
similarity index 67%
rename from Gen/Generators/src/component/EvtGenDecay.h
rename to Gen/LbEvtGen/src/EvtGenDecay.h
index c5b4b6491..7aab87f1b 100755
--- a/Gen/Generators/src/component/EvtGenDecay.h
+++ b/Gen/LbEvtGen/src/EvtGenDecay.h
@@ -1,6 +1,4 @@
-// $Id: EvtGenDecay.h,v 1.9 2009-03-16 16:53:26 robbep Exp $
-#ifndef GENERATORS_EVTGENDECAY_H
-#define GENERATORS_EVTGENDECAY_H 1
+#pragma once
 
 // Avoid contamination with WINDOWS symbols
 #ifdef WIN32
@@ -35,14 +33,35 @@
 #include "GaudiKernel/Vector4DTypes.h"
 
 // from MCInterfaces
-#include "MCInterfaces/IDecayTool.h"
+#include "GenInterfaces/IDecayTool.h"
 
 // from Generators
-#include "IEvtGenTool.h"
+#include "GaudiKernel/SystemOfUnits.h"
 
 // from EvtGen
 #include "EvtGenBase/EvtId.hh"
 
+// from HepMC
+#include "HepMC3/GenParticle.h"
+#include "HepMC3/GenVertex.h"
+#include "HepMC3/GenEvent.h"
+#include "HepMCUser/Status.h"
+
+// from EvtGen
+#include "EvtGenBase/EvtRandomEngine.hh"
+#include "TRandom.h"
+
+
+class RandomEngineWrapper : public EvtRandomEngine {
+public:
+  virtual ~RandomEngineWrapper() = default;
+  // return a random number using gRandom from ROOT.
+  // The Gaussino global random engine replaces gRandom
+  // to use the correct thread-local engine of the 
+  // respective algorithm call.
+  double random() override { return gRandom->Rndm();}
+};
+
 // forward declarations
 namespace LHCb {
   class ParticleID ;
@@ -50,7 +69,6 @@ namespace LHCb {
 
 class EvtGen ;
 class EvtParticle ;
-class EvtRandomEngine ;
 
 /** @class EvtGenDecay EvtGenDecay.h "EvtGenDecay.h"
  *
@@ -60,13 +78,12 @@ class EvtRandomEngine ;
  *  @author Patrick Robbe
  *  @date   2003-10-15
  */
-class EvtGenDecay : public GaudiTool, virtual public IDecayTool {
+class EvtGenDecay : public extends<GaudiTool, IDecayTool> {
 public:
-  /// Standard constructor
-  EvtGenDecay( const std::string& type, const std::string& name,
-              const IInterface* parent);
 
-  virtual ~EvtGenDecay( ) ; ///< Destructor
+  using extends::extends;
+
+  virtual ~EvtGenDecay( ) = default; ///< Destructor
 
   /** Initialize method.
    *  In initialization:
@@ -81,16 +98,16 @@ public:
   /// Finalize method
   StatusCode finalize() override;
 
-  /// Implements IDecayTool::generateDecay
-  StatusCode generateDecay( HepMC::GenParticle * theMother ) const override;
+  StatusCode generateDecay( const HepMC3::GenParticlePtr & theMother ,
+                                    HepRandomEnginePtr & engine ) const override;
 
-  /// Implements IDecayTool::generateSignalDecay
-  StatusCode generateSignalDecay( HepMC::GenParticle * theMother ,
-                                  bool & flip ) const override;
+  StatusCode generateSignalDecay( const HepMC3::GenParticlePtr& theMother ,
+                                  bool & flip ,
+                                  HepRandomEnginePtr & engine ) const override;
 
-  /// Implements IDecayTool::generateDecayWithLimit
-  StatusCode generateDecayWithLimit( HepMC::GenParticle * theMother,
-                                     const int targetId ) const override;
+  StatusCode generateDecayWithLimit( const HepMC3::GenParticlePtr & theMother ,
+                                     const int targetId ,
+                                     HepRandomEnginePtr & engine ) const override;
 
   /// Implements IDecayTool::enableFlip
   void enableFlip() const override;
@@ -122,7 +139,7 @@ public:
    *         negative)
    */
   StatusCode makeHepMC( EvtParticle * theParticle ,
-                        HepMC::GenParticle * theMother ,
+                        const HepMC3::GenParticlePtr & theMother ,
                         const Gaudi::LorentzVector & theOrigin ,
                         int targetId = -999 )  const ;
 
@@ -133,7 +150,7 @@ public:
    *  @return StatusCode::SUCCESS if no problem
    *  @return StatusCode::ERROR if particle has already an end vertex
    */
-  void checkParticle( const HepMC::GenParticle * theParticle ) const ;
+  void checkParticle( const HepMC3::GenParticlePtr & theParticle ) const ;
 
   /** Call EvtGen to decay a particle
    *  @param[out] thePart the EvtParticle to produce
@@ -144,17 +161,19 @@ public:
    *              example)
    */
   StatusCode callEvtGen( EvtParticle * &thePart ,
-                         const HepMC::GenParticle * theHepMCParticle ,
+                         const HepMC3::GenParticlePtr & theHepMCParticle ,
                          const EvtId & eid ) const ;
 
   /// Return the id of the alias corresponding to the pdg code pdgId
   virtual const EvtId getSignalAlias( int pdgId ) const ;
 
-  EvtGen * m_gen ; ///< EvtGen engine
+  static std::unique_ptr<EvtGen> m_gen; ///< EvtGen engine
 
-  EvtRandomEngine * m_randomEngine ; ///< Random Engine to use in EvtGeni
+  std::unique_ptr<EvtRandomEngine> m_randomEngine ; ///< Random Engine to use in EvtGeni
 
-  IEvtGenTool * m_evtgentool ;
+  // Recursive mutex to be called at the beginning of any of the three public functions for
+  // decaying
+  static std::recursive_mutex m_mutex;
 
 private:
 
@@ -179,50 +198,52 @@ private:
   /// check if id exists in generic decay table
   bool checkGeneric( const EvtId & id ) const ;
 
-  std::string m_decayFile ; ///< Generic decay file name (set by options)
+  ///< Generic decay file name (set by options)
+  Gaudi::Property<std::string> m_decayFile{this, "DecayFile" , "empty"};
 
-  std::string m_userDecay ; ///< User decay file name (set by options)
+  ///< User decay file name (set by options)
+  Gaudi::Property<std::string> m_userDecay{this, "UserDecayFile", "empty"};
 
-  EvtId m_signalId ; /// EvtGen Id of signal ID
+  EvtId m_signalId{-1,-1} ; /// EvtGen Id of signal ID
 
   /// Do not erase temporary evt.pdl particle property file (set by options)
-  bool  m_keepTempEvtFile ;
+  Gaudi::Property<bool> m_keepTempEvtFile{this, "KeepTempEvtFile", false};
 
   /// Minimum value for ctau. Below ctau is set to 0.
-  double m_minctau ;
+  double m_minctau{ 1.e-4 * Gaudi::Units::mm };
 
   /// Minimum value for ctau. Above ctau is set to 0.
-  double m_maxctau ;
+  double m_maxctau{ 1.e+16 * Gaudi::Units::mm };
 
   /// Minimum value for width. Below it is set to 0.
-  double m_minwidth ;
+  double m_minwidth{ 1.5e-6 * Gaudi::Units::GeV } ;
 
   /// Unit for TAULA output
-  int m_taulaUnit ;
+  int m_taulaUnit{6};
 
   /// Unit for PHOTOS output
-  int m_photosUnit ;
+  int m_photosUnit{6};
 
   /// Flag for polarized Lambda_b production (set by options)
-  bool m_generatePolLambdab ;
+  Gaudi::Property<bool> m_generatePolLambdab{this, "PolarizedLambdad", false};
 
   /// Lambda_b transverse polarisation
-  double m_lambdabPol; 
+  Gaudi::Property<double> m_lambdabPol{this, "TransverseLambdabPol", 1.0};
 
   /// Flag for polarized charmonium production (set by options)
-  bool m_generatePolCharmonium ;
+  Gaudi::Property<bool> m_generatePolCharmonium{this, "PolarizedCharmonium", false};
 
   /// Real part of spin matrix for helicity 0 for charmonium polarization
-  double m_realHelZero ;
+  Gaudi::Property<double> m_realHelZero{this, "RealHelZero", 1.};
 
   /// Imaginary part of spin matrix for helicity 0 for charmonium polarization
-  double m_imHelZero ;
+  Gaudi::Property<double> m_imHelZero{this, "ImHelZero", 0.};
 
   /// Real part of spin matrix for helicity 1 for charmonium polarization
-  double m_realHelOne ;
+  Gaudi::Property<double> m_realHelOne{this, "RealHelOne", 1.};
 
   /// Imaginary part of spin matrix for helicity 1 for charmonium polarization
-  double m_imHelOne ;
+  Gaudi::Property<double> m_imHelOne{this, "RealHelOne", 1.};
 };
 
 //#include "EvtGenBase/EvtIncoherentMixing.hh"
@@ -243,36 +264,3 @@ inline void EvtGenDecay::disableFlip() const {
 //  EvtIncoherentMixing::disableFlip() ;
 }
 
-#include "GaudiKernel/RndmGenerators.h"
-
-// from EvtGen
-#include "EvtGenBase/EvtRandomEngine.hh"
-
-// forward declaration
-class IRndmGenSvc ;
-/** @class EvtGenGaudiRandomEngine
- *  interface to GaudiRandomEngine random engine which will be used inside
- *  EvtGen.
- */
-class EvtGenGaudiRandomEngine : public EvtRandomEngine {
-public:
-  /// Constructor
-  EvtGenGaudiRandomEngine( IRndmGenSvc* i , StatusCode & sc ) ;
-
-  /// Destructor
-  ~EvtGenGaudiRandomEngine ( ) ;
-
-  /// return a random number from the Gaudi engine
-  double random() override;
-
-private:
-  /// Gaudi random engine common to all Gauss algorithms
-  Rndm::Numbers m_randomgaudi ;
-} ;
-
-//=============================================================================
-// Return random number
-//=============================================================================
-inline double EvtGenGaudiRandomEngine::random() { return m_randomgaudi() ; }
-
-#endif // GENERATORS_EVTGENDECAY_H
diff --git a/Gen/Generators/src/component/EvtGenDecayWithCutTool.cpp b/Gen/LbEvtGen/src/EvtGenDecayWithCutTool.cpp
similarity index 57%
rename from Gen/Generators/src/component/EvtGenDecayWithCutTool.cpp
rename to Gen/LbEvtGen/src/EvtGenDecayWithCutTool.cpp
index 412db4ff4..e34020f8e 100755
--- a/Gen/Generators/src/component/EvtGenDecayWithCutTool.cpp
+++ b/Gen/LbEvtGen/src/EvtGenDecayWithCutTool.cpp
@@ -6,15 +6,13 @@
 #include <iostream>
 
 // from LHCb
-#include "GenEvent/HepMCUtils.h"
+#include "HepMCUtils/HepMCUtils.h"
 
 // from HepMC
 #include "HepMC/GenEvent.h"
 #include "HepMC/GenParticle.h"
 #include "HepMC/GenVertex.h"
 
-#include "MCInterfaces/IGenCutTool.h"
-
 //-----------------------------------------------------------------------------
 // Implementation file for class : EvtGenDecayWithCutTool
 //
@@ -25,43 +23,20 @@
 
 DECLARE_COMPONENT( EvtGenDecayWithCutTool )
 
-//=============================================================================
-// Standard constructor, initializes variables
-//=============================================================================
-EvtGenDecayWithCutTool::EvtGenDecayWithCutTool( const std::string& type, const std::string& name,
-                                                const IInterface* parent )
-    : EvtGenDecay( type, name, parent )
-{
-  // Declare IEvtGenDecay interface
-  declareInterface<IDecayTool>( this );
-  // Name of the cut tool to be used
-  declareProperty( "CutTool", m_cutToolName = "" );
-}
-
-//=============================================================================
-// Initialize method
-//=============================================================================
-StatusCode EvtGenDecayWithCutTool::initialize()
-{
-  StatusCode sc = EvtGenDecay::initialize();
-  if ( sc.isFailure() ) return sc;
-
-  if ( m_cutToolName != "" ) m_cutTool = tool<IGenCutTool>( m_cutToolName, this );
-
-  return StatusCode::SUCCESS;
-}
 
 //=============================================================================
 // Generate a Decay tree from a particle theMother in the event theEvent
 // Repeat until it passes the the cut;
 //=============================================================================
-StatusCode EvtGenDecayWithCutTool::generateSignalDecay( HepMC::GenParticle* theMother, bool& flip ) const
-{
+StatusCode EvtGenDecayWithCutTool::generateSignalDecay( 
+    const HepMC3::GenParticlePtr& theMother ,
+    bool & flip ,
+    HepRandomEnginePtr & engine) const {
   int counter    = 0;
   bool found_one = false;
   while ( !found_one ) {
     HepMCUtils::RemoveDaughters( theMother );
-    StatusCode sc = EvtGenDecay::generateSignalDecay( theMother, flip );
+    StatusCode sc = EvtGenDecay::generateSignalDecay( theMother, flip, engine );
     if ( sc.isFailure() ) {
       return sc;
     }
diff --git a/Gen/Generators/src/component/EvtGenDecayWithCutTool.h b/Gen/LbEvtGen/src/EvtGenDecayWithCutTool.h
similarity index 68%
rename from Gen/Generators/src/component/EvtGenDecayWithCutTool.h
rename to Gen/LbEvtGen/src/EvtGenDecayWithCutTool.h
index 921270a70..b3af9dbe9 100755
--- a/Gen/Generators/src/component/EvtGenDecayWithCutTool.h
+++ b/Gen/LbEvtGen/src/EvtGenDecayWithCutTool.h
@@ -1,8 +1,7 @@
 #pragma once
 // from Generators
 #include "EvtGenDecay.h"
-
-class IGenCutTool;
+#include "GenInterfaces/IGenCutTool.h"
 
 /** @class EvtGenDecayWithCutTool EvtGenDecayWithCutTool.h "EvtGenDecayWithCutTool.h"
  *
@@ -27,20 +26,15 @@ class IGenCutTool;
 class EvtGenDecayWithCutTool : public EvtGenDecay
 {
 public:
-  /// Standard constructor
-  EvtGenDecayWithCutTool( const std::string& type, const std::string& name, const IInterface* parent );
+  using EvtGenDecay::EvtGenDecay;
 
-  /** Initialize method.
-   *  Runs the EvtGenDecay initialization and gets the cut tool.
-   */
-  StatusCode initialize() override;
 
   /// Implements IDecayTool::generateSignalDecay
   // Runs EvtGenDecay::generateSignalDecay until a decay passes the provided cut.
-  StatusCode generateSignalDecay( HepMC::GenParticle* theMother, bool& flip ) const override;
+  StatusCode generateSignalDecay( const HepMC3::GenParticlePtr& theMother ,
+                                  bool & flip ,
+                                  HepRandomEnginePtr & engine ) const override;
 
 private:
-  std::string m_cutToolName = ""; ///< Name of the cut tool to be applied at each decay attempt.
-
-  IGenCutTool* m_cutTool = nullptr;
+  ToolHandle<IGenCutTool> m_cutTool{this, "CutTool", ""};
 };
diff --git a/Gen/Generators/src/component/EvtGenInPhSpDecay.cpp b/Gen/LbEvtGen/src/EvtGenInPhSpDecay.cpp
similarity index 86%
rename from Gen/Generators/src/component/EvtGenInPhSpDecay.cpp
rename to Gen/LbEvtGen/src/EvtGenInPhSpDecay.cpp
index 41693c738..19bf740dd 100644
--- a/Gen/Generators/src/component/EvtGenInPhSpDecay.cpp
+++ b/Gen/LbEvtGen/src/EvtGenInPhSpDecay.cpp
@@ -37,7 +37,6 @@
 #include "EvtGenModels/EvtModelRegExtras.hh"
 
 #include "Generators/StreamForGenerator.h"
-#include "Generators/IProductionTool.h"
 
 //-----------------------------------------------------------------------------
 // Implementation file for class : EvtGenInPhSpDecay
@@ -48,32 +47,6 @@
 
 DECLARE_COMPONENT( EvtGenInPhSpDecay )
 
-//=============================================================================
-// Standard constructor, initializes variables
-//=============================================================================
-EvtGenInPhSpDecay::EvtGenInPhSpDecay( const std::string& type,
-                          const std::string& name,
-                          const IInterface* parent )
-  : EvtGenDecay ( type, name , parent ),
-    // name of q2 parameter file
-    m_q2mapfile ( "" )  ,
-    // statistics
-    m_tot_calls ( 0.0 ) ,
-    m_num_evts ( 0.0 ) ,
-    m_ave_eff ( 0.0 ) 
-{
-    // Declare IEvtGenInPhSpDecay interface
-    declareInterface<IDecayTool>( this ) ;
-    //number of bins for q2
-    declareProperty("NumQ2Bins" , m_q2nbins = 100 ) ;
-    declareProperty("MaxQ2Bins" , m_q2nmax  = 19 ) ;
-    declareProperty("MaxEvtGenCalls" , m_limit  = 1000 ) ;
-    declareProperty("ParamFile", m_prefix = "Q2Param" ) ;
-}
-//=============================================================================
-// Destructor
-//=============================================================================
-EvtGenInPhSpDecay::~EvtGenInPhSpDecay( ) { }
 //=============================================================================
 // Initialize method
 //=============================================================================
@@ -160,7 +133,7 @@ StatusCode EvtGenInPhSpDecay::loadMap( ) {
 // Generate with EvtGen until conditions are satisfied
 //=============================================================================
 StatusCode EvtGenInPhSpDecay::doEvtGenLoop( EvtParticle* & part , 
-                                            HepMC::GenParticle * &theMother ,
+                                            const HepMC3::GenParticlePtr &theMother ,
                                             const EvtId &pid ) const
 {
     //loop to re-decay particle until phase space conditions are satisfied
@@ -245,8 +218,9 @@ StatusCode EvtGenInPhSpDecay::doEvtGenLoop( EvtParticle* & part ,
 //=============================================================================
 // Generate a Decay tree from a particle theMother in the event theEvent
 //=============================================================================
-StatusCode EvtGenInPhSpDecay::generateSignalDecay( HepMC::GenParticle * theMother ,
-                                             bool & flip) const {
+StatusCode EvtGenInPhSpDecay::generateSignalDecay( const HepMC3::GenParticlePtr& theMother ,
+                                  bool & flip ,
+                                  HepRandomEnginePtr &) const {
   // If particle already has daughters, return now
   if ( 0 != theMother -> end_vertex() ) {
     flip = false ;
@@ -276,7 +250,7 @@ StatusCode EvtGenInPhSpDecay::generateSignalDecay( HepMC::GenParticle * theMothe
   // correct vertex for daughter particles of theMother
   // because EvtGen gives position with respect to the "root" particle
   // This reference position is production vertex of theMother
-  HepMC::GenVertex * PV = theMother -> production_vertex() ;
+  auto PV = theMother -> production_vertex() ;
   Gaudi::LorentzVector theOriginPosition( PV -> position() ) ;
   
   // Fill HepMC event theEvent with EvtGen decay tree part
diff --git a/Gen/Generators/src/component/EvtGenInPhSpDecay.h b/Gen/LbEvtGen/src/EvtGenInPhSpDecay.h
similarity index 56%
rename from Gen/Generators/src/component/EvtGenInPhSpDecay.h
rename to Gen/LbEvtGen/src/EvtGenInPhSpDecay.h
index a5a0a7535..6bbc7e5a7 100644
--- a/Gen/Generators/src/component/EvtGenInPhSpDecay.h
+++ b/Gen/LbEvtGen/src/EvtGenInPhSpDecay.h
@@ -12,13 +12,11 @@
  *  @author Alex Shires
  *  @date   2011-08-16
  */
-class EvtGenInPhSpDecay : public EvtGenDecay, virtual public IDecayTool {
+class EvtGenInPhSpDecay : public extends<EvtGenDecay, IDecayTool> {
 public:
-  /// Standard constructor
-  EvtGenInPhSpDecay( const std::string& type, const std::string& name,
-              const IInterface* parent);
+  using extends::extends;
 
-  virtual ~EvtGenInPhSpDecay( ) ; ///< Destructor
+  virtual ~EvtGenInPhSpDecay( ) = default; ///< Destructor
 
   /** Initialize method.
    *  In initialization:
@@ -31,37 +29,39 @@ public:
   StatusCode finalize() override;
 
   /// Implements IDecayTool::generateSignalDecay
-  StatusCode generateSignalDecay( HepMC::GenParticle * theMother ,
-                                  bool & flip ) const override;
+  StatusCode generateSignalDecay( const HepMC3::GenParticlePtr& theMother ,
+                                  bool & flip ,
+                                  HepRandomEnginePtr & engine ) const override;
+
 
  private:
 
   StatusCode doEvtGenLoop( EvtParticle* &thePart ,
-                           HepMC::GenParticle * &theHepMCParticle ,
+                           const HepMC3::GenParticlePtr &theHepMCParticle ,
                            const EvtId & eid ) const ;
 
   /// load qsquared map
   StatusCode loadMap(void ) ;
 
   /// File name of parameter file
-  boost::filesystem::path m_q2mapfile ;
+  boost::filesystem::path m_q2mapfile{""};
 
   std::string m_q2mapfilename ;
-  std::string m_prefix ;
+  Gaudi::Property<std::string> m_prefix{this, "ParamFile", "Q2Param"};
 
   // number of bins in q2
-  int m_q2nbins ;
-  int m_q2nmax ;
+  Gaudi::Property<int> m_q2nbins{this, "NumQ2Bins", 100};
+  Gaudi::Property<int> m_q2nmax{this, "MaxQ2Bins", 19};
 
   //vector for q2 values
   std::vector<double> m_q2mapvec ;
 
   //statistics
-  double m_tot_calls ;
-  double m_num_evts ;
-  double m_ave_eff ;
+  double m_tot_calls{0} ;
+  double m_num_evts{0} ;
+  double m_ave_eff{0} ;
 
-  int m_limit ;
+  Gaudi::Property<int> m_limit{this, "MaxEvtGenCalls", 1000};
 
 };
 
diff --git a/Sim/Gauss/python/Gauss/Configuration.py b/Sim/Gauss/python/Gauss/Configuration.py
index a0e84b979..7a6e78c53 100755
--- a/Sim/Gauss/python/Gauss/Configuration.py
+++ b/Sim/Gauss/python/Gauss/Configuration.py
@@ -220,4 +220,7 @@ class Gauss(LHCbConfigurableUser):
 
         crossingList = self.defineCrossingList()
 
+        from Configurables import EvtGenDecay
+        EvtGenDecay().DecayFile = "$DECFILESROOT/dkfiles/DECAY.DEC"
+
         self.defineOutput(crossingList)
-- 
GitLab


From 04d31bdfea1308604856e511c29da5d659d4a4d5 Mon Sep 17 00:00:00 2001
From: Dominik Muller <dominik.muller@cern.ch>
Date: Tue, 20 Aug 2019 12:42:55 +0200
Subject: [PATCH 22/90] Ported DaughtersInLHCb

---
 Gen/GenCuts/CMakeLists.txt                    |  12 +-
 Gen/GenCuts/src/DaughtersInLHCb.cpp           | 141 ------------------
 Gen/GenCuts/src_future/DaughtersInLHCb.cpp    | 107 +++++++++++++
 .../{src => src_future}/DaughtersInLHCb.h     |  32 ++--
 4 files changed, 128 insertions(+), 164 deletions(-)
 delete mode 100755 Gen/GenCuts/src/DaughtersInLHCb.cpp
 create mode 100755 Gen/GenCuts/src_future/DaughtersInLHCb.cpp
 rename Gen/GenCuts/{src => src_future}/DaughtersInLHCb.h (59%)

diff --git a/Gen/GenCuts/CMakeLists.txt b/Gen/GenCuts/CMakeLists.txt
index bae933c34..cc4b49555 100644
--- a/Gen/GenCuts/CMakeLists.txt
+++ b/Gen/GenCuts/CMakeLists.txt
@@ -1,19 +1,19 @@
 ################################################################################
 # Package: GenCuts
 ################################################################################
-gaudi_subdir(GenCuts v3r13)
+gaudi_subdir(GenCuts v4r0)
 
 gaudi_depends_on_subdirs(GaudiAlg
-                         Kernel/MCInterfaces
-                         Phys/LoKiGen)
+                         Gen/GenInterfaces)
 
 find_package(FastJet)
 find_package(Boost)
 find_package(ROOT)
 include_directories(SYSTEM ${Boost_INCLUDE_DIRS} ${ROOT_INCLUDE_DIRS} ${FASTJET_INCLUDE_DIRS})
+AddHepMC3()
 
 gaudi_add_module(GenCuts
-                 src/*.cpp
-                 INCLUDE_DIRS Kernel/MCInterfaces FastJet
-                 LINK_LIBRARIES GaudiAlgLib LoKiGenLib FastJet)
+                 src_future/*.cpp
+                 INCLUDE_DIRS GenInterfaces ${HEPMC3_INCLUDE_DIR}
+                 LINK_LIBRARIES GaudiAlgLib GeneratorsLib ${HEPMC3_LIBRARIES})
 
diff --git a/Gen/GenCuts/src/DaughtersInLHCb.cpp b/Gen/GenCuts/src/DaughtersInLHCb.cpp
deleted file mode 100755
index 801c266e3..000000000
--- a/Gen/GenCuts/src/DaughtersInLHCb.cpp
+++ /dev/null
@@ -1,141 +0,0 @@
-// $Id: DaughtersInLHCb.cpp,v 1.7 2008-07-09 14:33:47 robbep Exp $
-// Include files 
-
-// local
-#include "DaughtersInLHCb.h"
-
-// from Gaudi
-#include "GaudiKernel/SystemOfUnits.h"
-
-// from Kernel
-#include "Kernel/ParticleID.h"
-#include "GaudiKernel/Vector4DTypes.h"
-
-// from HepMC
-#include "HepMC/GenParticle.h"
-#include "HepMC/GenVertex.h"
-
-// from Generators
-#include "GenEvent/HepMCUtils.h"
-
-//-----------------------------------------------------------------------------
-// Implementation file for class : DaughtersInLHCb
-//
-// 2005-08-17 : Patrick Robbe
-//-----------------------------------------------------------------------------
-
-// Declaration of the Tool Factory
-
-DECLARE_COMPONENT( DaughtersInLHCb )
-
-
-//=============================================================================
-// Standard constructor, initializes variables
-//=============================================================================
-DaughtersInLHCb::DaughtersInLHCb( const std::string& type,
-                                  const std::string& name,
-                                  const IInterface* parent )
-  : GaudiTool ( type, name , parent ) {
-    declareInterface< IGenCutTool >( this ) ;
-    declareProperty( "ChargedThetaMin" , m_chargedThetaMin = 10 * Gaudi::Units::mrad ) ;
-    declareProperty( "ChargedThetaMax" , m_chargedThetaMax = 400 * Gaudi::Units::mrad ) ;
-    declareProperty( "NeutralThetaMin" , m_neutralThetaMin = 5 * Gaudi::Units::mrad ) ;
-    declareProperty( "NeutralThetaMax" , m_neutralThetaMax = 400 * Gaudi::Units::mrad ) ;
-}
-
-//=============================================================================
-// Destructor 
-//=============================================================================
-DaughtersInLHCb::~DaughtersInLHCb( ) { ; }
-
-//=============================================================================
-// Acceptance function
-//=============================================================================
-bool DaughtersInLHCb::applyCut( ParticleVector & theParticleVector ,
-                                const HepMC::GenEvent * /* theEvent */ ,
-                                const LHCb::GenCollision * /* theHardInfo */ )
-  const {
-  ParticleVector::iterator it ;
-  
-  for ( it = theParticleVector.begin() ; it != theParticleVector.end() ; ) {    
-    if ( ! passCuts( *it ) ) {
-      it = theParticleVector.erase( it ) ;
-    } else ++it ;
-  }
-
-  
-  return ( ! theParticleVector.empty() ) ;
-}
-
-//=============================================================================
-// Functions to test if all daughters are in acceptance
-//=============================================================================
-bool DaughtersInLHCb::passCuts( const HepMC::GenParticle * theSignal ) const {
-  HepMC::GenVertex * EV = theSignal -> end_vertex() ;
-  if ( 0 == EV ) return true ;
-
-  typedef std::vector< HepMC::GenParticle * > Particles ;
-  Particles stables ;
-  HepMC::GenVertex::particle_iterator iter ;
-
-  for ( iter = EV -> particles_begin( HepMC::descendants ) ; 
-        iter != EV -> particles_end( HepMC::descendants ) ; ++iter ) {
-    if ( 0 == (*iter) -> end_vertex() ) stables.push_back( *iter ) ;
-  }  
-
-  if ( stables.empty() )
-    Exception( "Signal has no stable daughters !" ) ;
-
-  double angle( 0. ) ;
-  double firstpz = stables.front() -> momentum().pz() ;
-
-  debug() << "New event" << endmsg ;
-
-  for ( Particles::const_iterator it = stables.begin() ; it != stables.end() ;
-        ++it ) {
-
-    debug() << "Check particle " << (*it) -> pdg_id() << " with angle " 
-            << (*it) -> momentum().theta() / Gaudi::Units::mrad 
-            << " mrad." << endmsg ;
-   
-    // Remove neutrinos
-    if ( ( 12 == abs( (*it) -> pdg_id() ) ) || 
-         ( 14 == abs( (*it) -> pdg_id() ) ) || 
-         ( 16 == abs( (*it) -> pdg_id() ) ) ) continue ;
- 
-    // Don't use daughters of Lambda and KS:
-    HepMC::GenParticle * theParent ;
-    theParent = 
-      *( (*it) -> production_vertex() -> particles_in_const_begin() ) ;
-    if ( 3122 == abs( theParent -> pdg_id() ) ) continue ;
-    if ( 310 == theParent -> pdg_id() ) continue ;
-
-    // Consider only gammas from pi0 and eta
-    if ( 22 == (*it) -> pdg_id() ) {
-      if ( ( 111 != theParent -> pdg_id() ) &&
-           ( 221 != theParent -> pdg_id() ) ) continue ;
-    }
-
-    // All particles in same direction
-    if ( 0 > ( firstpz * ( (*it) -> momentum().pz() ) ) ) return false ;
-      
-    angle = (*it) -> momentum().theta() ;
-    
-    LHCb::ParticleID pid( (*it) -> pdg_id() ) ;
-    if ( 0 == pid.threeCharge() ) {
-      if ( fabs( sin( angle ) ) > fabs( sin( m_neutralThetaMax ) ) ) 
-        return false ;
-      if ( fabs( sin( angle ) ) < fabs( sin( m_neutralThetaMin ) ) ) 
-        return false ;
-    } else {
-      if ( fabs( sin( angle ) ) > fabs( sin( m_chargedThetaMax ) ) ) 
-        return false ;
-      if ( fabs( sin( angle ) ) < fabs( sin( m_chargedThetaMin ) ) ) 
-        return false ;
-    }
-  }
-
-  debug() << "Event passed !" << endmsg ;
-  
-  return true ;
-}
diff --git a/Gen/GenCuts/src_future/DaughtersInLHCb.cpp b/Gen/GenCuts/src_future/DaughtersInLHCb.cpp
new file mode 100755
index 000000000..c2c4bd690
--- /dev/null
+++ b/Gen/GenCuts/src_future/DaughtersInLHCb.cpp
@@ -0,0 +1,107 @@
+// $Id: DaughtersInLHCb.cpp,v 1.7 2008-07-09 14:33:47 robbep Exp $
+// Include files
+
+// local
+#include "DaughtersInLHCb.h"
+
+// from Gaudi
+#include "GaudiKernel/SystemOfUnits.h"
+
+// from Kernel
+#include "GaudiKernel/Vector4DTypes.h"
+#include "HepMC3/Relatives.h"
+#include "Kernel/ParticleID.h"
+
+//-----------------------------------------------------------------------------
+// Implementation file for class : DaughtersInLHCb
+//
+// 2005-08-17 : Patrick Robbe
+//-----------------------------------------------------------------------------
+
+// Declaration of the Tool Factory
+
+DECLARE_COMPONENT(DaughtersInLHCb)
+
+//=============================================================================
+// Acceptance function
+//=============================================================================
+bool DaughtersInLHCb::applyCut(ParticleVector& theParticleVector,
+                               const HepMC3::GenEvent*,
+                               const LHCb::GenCollision*) const {
+  ParticleVector tmp;
+  for (auto p : theParticleVector) {
+
+    if (passCuts(p)) {
+      tmp.push_back(p);
+    }
+  }
+  theParticleVector = tmp;
+
+  return (!theParticleVector.empty());
+}
+
+//=============================================================================
+// Functions to test if all daughters are in acceptance
+//=============================================================================
+bool DaughtersInLHCb::passCuts(const HepMC3::GenParticlePtr theSignal) const {
+  auto EV = theSignal->end_vertex();
+  if (0 == EV) return true;
+
+  typedef std::vector<HepMC3::GenParticlePtr> Particles;
+  Particles stables;
+
+  for (auto desc : HepMC3::Relatives::DESCENDANTS(theSignal)) {
+    if (!desc->end_vertex()) {
+      stables.push_back(desc);
+    }
+  }
+
+  if (stables.empty()) Exception("Signal has no stable daughters !");
+
+  double angle(0.);
+  double firstpz = stables.front()->momentum().pz();
+
+  for (auto stable : stables) {
+    if (msgLevel(MSG::DEBUG)) {
+      debug() << "Check particle " << stable->pdg_id() << " with angle "
+              << stable->momentum().theta() / Gaudi::Units::mrad << " mrad."
+              << endmsg;
+    }
+
+    // Remove neutrinos
+    if ((12 == abs(stable->pdg_id())) || (14 == abs(stable->pdg_id())) ||
+        (16 == abs(stable->pdg_id())))
+      continue;
+
+    // Don't use daughters of Lambda and KS:
+    auto theParent = *std::begin(stable->parents());
+    if (3122 == abs(theParent->pdg_id())) continue;
+    if (310 == theParent->pdg_id()) continue;
+
+    // Consider only gammas from pi0 and eta
+    if (22 == stable->pdg_id()) {
+      if ((111 != theParent->pdg_id()) && (221 != theParent->pdg_id()))
+        continue;
+    }
+
+    // All particles in same direction
+    if (0 > (firstpz * (stable->momentum().pz()))) return false;
+
+    angle = stable->momentum().theta();
+
+    LHCb::ParticleID pid(stable->pdg_id());
+    if (0 == pid.threeCharge()) {
+      if (fabs(sin(angle)) > fabs(sin(m_neutralThetaMax))) return false;
+      if (fabs(sin(angle)) < fabs(sin(m_neutralThetaMin))) return false;
+    } else {
+      if (fabs(sin(angle)) > fabs(sin(m_chargedThetaMax))) return false;
+      if (fabs(sin(angle)) < fabs(sin(m_chargedThetaMin))) return false;
+    }
+  }
+
+  if (msgLevel(MSG::DEBUG)) {
+    debug() << "Event passed !" << endmsg;
+  }
+
+  return true;
+}
diff --git a/Gen/GenCuts/src/DaughtersInLHCb.h b/Gen/GenCuts/src_future/DaughtersInLHCb.h
similarity index 59%
rename from Gen/GenCuts/src/DaughtersInLHCb.h
rename to Gen/GenCuts/src_future/DaughtersInLHCb.h
index 249540f96..a7da36cb5 100755
--- a/Gen/GenCuts/src/DaughtersInLHCb.h
+++ b/Gen/GenCuts/src_future/DaughtersInLHCb.h
@@ -1,13 +1,15 @@
-// $Id: DaughtersInLHCb.h,v 1.4 2008-05-29 14:21:59 gcorti Exp $
-#ifndef GENCUTS_DAUGHTERSINLHCB_H
-#define GENCUTS_DAUGHTERSINLHCB_H 1
+#pragma once
 
 // Include files
 // from Gaudi
 #include "GaudiAlg/GaudiTool.h"
 
-#include "MCInterfaces/IGenCutTool.h"
+#include "GenInterfaces/IGenCutTool.h"
 #include "GaudiKernel/Transform4DTypes.h"
+#include "HepMC3/GenParticle.h"
+
+// from Gaudi
+#include "GaudiKernel/SystemOfUnits.h"
 
 /** @class DaughtersInLHCb DaughtersInLHCb.h
  *
@@ -18,47 +20,43 @@
  *  @author Patrick Robbe
  *  @date   2005-08-24
  */
-class DaughtersInLHCb : public GaudiTool, virtual public IGenCutTool {
+class DaughtersInLHCb : public extends<GaudiTool, IGenCutTool> {
  public:
   /// Standard constructor
-  DaughtersInLHCb( const std::string& type,
-                  const std::string& name,
-                  const IInterface* parent);
-
-  virtual ~DaughtersInLHCb( ); ///< Destructor
+  using extends::extends;
+  typedef std::vector< HepMC3::GenParticlePtr > ParticleVector ;
 
   /** Accept events with daughters in LHCb acceptance (defined by min and
    *  max angles, different values for charged and neutrals)
    *  Implements IGenCutTool::applyCut.
    */
   bool applyCut( ParticleVector & theParticleVector ,
-                 const HepMC::GenEvent * theEvent ,
+                 const HepMC3::GenEvent * theEvent ,
                  const LHCb::GenCollision * theCollision ) const override;
 
  private:
   /** Study a particle a returns true when all stable daughters
    *  are in LHCb acceptance
    */
-  bool passCuts( const HepMC::GenParticle * theSignal ) const ;
+  bool passCuts( const HepMC3::GenParticlePtr theSignal ) const ;
 
   /** Minimum value of angle around z-axis for charged daughters
    * (set by options)
    */
-  double m_chargedThetaMin ;
+  Gaudi::Property<double> m_chargedThetaMin{this, "ChargedThetaMin" , 10 * Gaudi::Units::mrad};
 
   /** Maximum value of angle around z-axis for charged daughters
    * (set by options)
    */
-  double m_chargedThetaMax ;
+  Gaudi::Property<double> m_chargedThetaMax{this, "ChargedThetaMax" , 400 * Gaudi::Units::mrad};
 
   /** Minimum value of angle around z-axis for neutral daughters
    * (set by options)
    */
-  double m_neutralThetaMin ;
+  Gaudi::Property<double> m_neutralThetaMin{this,"NeutralThetaMin" , 5 * Gaudi::Units::mrad};
 
   /** Maximum value of angle around z-axis for neutral daughters
    * (set by options)
    */
-  double m_neutralThetaMax ;
+  Gaudi::Property<double> m_neutralThetaMax{this,"NeutralThetaMax" , 400 * Gaudi::Units::mrad};
 };
-#endif // GENCUTS_DAUGHTERSINLHCB_H
-- 
GitLab


From 301da282c9642d477a1c4486a8cd10d96f44ccdf Mon Sep 17 00:00:00 2001
From: Dominik Muller <dominik.muller@cern.ch>
Date: Tue, 20 Aug 2019 12:43:31 +0200
Subject: [PATCH 23/90] Reverted to old Simulation.xml

---
 Gen/LbEvtGen/CMakeLists.txt     | 4 +---
 Sim/Gauss/xml/Simulation.xml    | 9 +--------
 Sim/GaussPhysics/CMakeLists.txt | 2 +-
 3 files changed, 3 insertions(+), 12 deletions(-)

diff --git a/Gen/LbEvtGen/CMakeLists.txt b/Gen/LbEvtGen/CMakeLists.txt
index d22613c89..4f2581c27 100644
--- a/Gen/LbEvtGen/CMakeLists.txt
+++ b/Gen/LbEvtGen/CMakeLists.txt
@@ -3,9 +3,7 @@
 ################################################################################
 gaudi_subdir(LbEvtGen v1r0)
 
-gaudi_depends_on_subdirs(Gen/Generators
-                         Gen/EvtGen
-                         Gen/EvtGenExtras
+gaudi_depends_on_subdirs(Gen/EvtGenExtras
                          HepMCUser
                          Utils)
                          
diff --git a/Sim/Gauss/xml/Simulation.xml b/Sim/Gauss/xml/Simulation.xml
index 9316bf51f..7a9eccb34 100755
--- a/Sim/Gauss/xml/Simulation.xml
+++ b/Sim/Gauss/xml/Simulation.xml
@@ -37,7 +37,7 @@
     <!-- This part is where simulation attributes are mapped to volumes -->
     <!-- ************************************************************** -->
 
-    &SimAttrRich;
+    <!--&SimAttrRich;-->
 
     <Item name="/dd/Geometry/DownstreamRegion/Muon/lvMuFilter1">
       <Cut particle="0" attr="SimAttrMuFilt"/>
@@ -56,13 +56,6 @@
       <Cut particle="13" attr="SimAttrMuon"/>
       <Cut particle="-13" attr="SimAttrMuon"/>
     </Item>
-
-   <Item name="/dd/Geometry/DownstreamRegion/Muon/lvMuFilter4">
-      <Cut particle="0" attr="SimAttrMuFilt"/>
-      <Cut particle="13" attr="SimAttrMuon"/>
-      <Cut particle="-13" attr="SimAttrMuon"/>
-    </Item>
-    
   </LogVols>
 
   <!-- Define cuts to be applied later in regions -->
diff --git a/Sim/GaussPhysics/CMakeLists.txt b/Sim/GaussPhysics/CMakeLists.txt
index a122716ee..bb21fad59 100644
--- a/Sim/GaussPhysics/CMakeLists.txt
+++ b/Sim/GaussPhysics/CMakeLists.txt
@@ -20,7 +20,7 @@ FindG4libs(digits_hits event geometry global graphics_reps materials
 
 gaudi_add_module(GaussParticlesPhysics
                  src/particles/*.cpp
-                 LINK_LIBRARIES GiGaMTCoreRunLib GaudiAlgLib GiGaMTLib G4LHCblists ${GEANT4_LIBS})
+                 LINK_LIBRARIES GiGaMTCoreRunLib GaudiAlgLib GiGaMTLib G4LHCblists ${GEANT4_LIBS} CLHEP)
 
 
 gaudi_add_module(GaussCutPhysics
-- 
GitLab


From 7e77afe3954ddd7023efcb53ff9bf590c4b8191a Mon Sep 17 00:00:00 2001
From: Dominik Muller <dominik.muller@cern.ch>
Date: Tue, 20 Aug 2019 16:00:49 +0200
Subject: [PATCH 24/90] Added all necessary Gaudi ignores

---
 Bcm/.gaudi_project_ignore                | 0
 Bls/.gaudi_project_ignore                | 0
 Gen/AmpGen/.gaudi_project_ignore         | 0
 Gen/BcVegPy/.gaudi_project_ignore        | 0
 Gen/GenTests/.gaudi_project_ignore       | 0
 Gen/GenTune/.gaudi_project_ignore        | 0
 Gen/GenXicc/.gaudi_project_ignore        | 0
 Gen/LPair/.gaudi_project_ignore          | 0
 Gen/LbAmpGen/.gaudi_project_ignore       | 0
 Gen/LbBcVegPy/.gaudi_project_ignore      | 0
 Gen/LbBound/.gaudi_project_ignore        | 0
 Gen/LbCRMC/.gaudi_project_ignore         | 0
 Gen/LbGenXicc/.gaudi_project_ignore      | 0
 Gen/LbHard/.gaudi_project_ignore         | 0
 Gen/LbHerwigpp/.gaudi_project_ignore     | 0
 Gen/LbHidValley/.gaudi_project_ignore    | 0
 Gen/LbHijing/.gaudi_project_ignore       | 0
 Gen/LbLPair/.gaudi_project_ignore        | 0
 Gen/LbMIB/.gaudi_project_ignore          | 0
 Gen/LbOniaPairs/.gaudi_project_ignore    | 0
 Gen/LbPGuns/.gaudi_project_ignore        | 0
 Gen/LbPowheg/.gaudi_project_ignore       | 0
 Gen/LbPythia/.gaudi_project_ignore       | 0
 Gen/LbPythia8/.gaudi_project_ignore      | 0
 Gen/LbStarLight/.gaudi_project_ignore    | 0
 Gen/LbSuperChic2/.gaudi_project_ignore   | 0
 Gen/SuperChic2/.gaudi_project_ignore     | 0
 HC/.gaudi_project_ignore                 | 0
 Sim/GaussAlgs/.gaudi_project_ignore      | 0
 Sim/GaussCherenkov/.gaudi_project_ignore | 0
 Sim/GaussCore/.gaudi_project_ignore      | 0
 Sim/GaussKine/.gaudi_project_ignore      | 0
 Sim/GaussMonitor/.gaudi_project_ignore   | 0
 Sim/GaussRICH/.gaudi_project_ignore      | 0
 Sim/GaussRedecay/.gaudi_project_ignore   | 0
 Sim/GaussTools/.gaudi_project_ignore     | 0
 Sim/GiGa/.gaudi_project_ignore           | 0
 Sim/GiGaCnv/.gaudi_project_ignore        | 0
 Sim/GiGaVisUI/.gaudi_project_ignore      | 0
 Sim/LbGDML/.gaudi_project_ignore         | 0
 Sim/SimChecks/.gaudi_project_ignore      | 0
 VP/.gaudi_project_ignore                 | 0
 Vis/.gaudi_project_ignore                | 0
 43 files changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 Bcm/.gaudi_project_ignore
 create mode 100644 Bls/.gaudi_project_ignore
 create mode 100644 Gen/AmpGen/.gaudi_project_ignore
 create mode 100644 Gen/BcVegPy/.gaudi_project_ignore
 create mode 100644 Gen/GenTests/.gaudi_project_ignore
 create mode 100644 Gen/GenTune/.gaudi_project_ignore
 create mode 100644 Gen/GenXicc/.gaudi_project_ignore
 create mode 100644 Gen/LPair/.gaudi_project_ignore
 create mode 100644 Gen/LbAmpGen/.gaudi_project_ignore
 create mode 100644 Gen/LbBcVegPy/.gaudi_project_ignore
 create mode 100644 Gen/LbBound/.gaudi_project_ignore
 create mode 100644 Gen/LbCRMC/.gaudi_project_ignore
 create mode 100644 Gen/LbGenXicc/.gaudi_project_ignore
 create mode 100644 Gen/LbHard/.gaudi_project_ignore
 create mode 100644 Gen/LbHerwigpp/.gaudi_project_ignore
 create mode 100644 Gen/LbHidValley/.gaudi_project_ignore
 create mode 100644 Gen/LbHijing/.gaudi_project_ignore
 create mode 100644 Gen/LbLPair/.gaudi_project_ignore
 create mode 100644 Gen/LbMIB/.gaudi_project_ignore
 create mode 100644 Gen/LbOniaPairs/.gaudi_project_ignore
 create mode 100644 Gen/LbPGuns/.gaudi_project_ignore
 create mode 100644 Gen/LbPowheg/.gaudi_project_ignore
 create mode 100644 Gen/LbPythia/.gaudi_project_ignore
 create mode 100644 Gen/LbPythia8/.gaudi_project_ignore
 create mode 100644 Gen/LbStarLight/.gaudi_project_ignore
 create mode 100644 Gen/LbSuperChic2/.gaudi_project_ignore
 create mode 100644 Gen/SuperChic2/.gaudi_project_ignore
 create mode 100644 HC/.gaudi_project_ignore
 create mode 100644 Sim/GaussAlgs/.gaudi_project_ignore
 create mode 100644 Sim/GaussCherenkov/.gaudi_project_ignore
 create mode 100644 Sim/GaussCore/.gaudi_project_ignore
 create mode 100644 Sim/GaussKine/.gaudi_project_ignore
 create mode 100644 Sim/GaussMonitor/.gaudi_project_ignore
 create mode 100644 Sim/GaussRICH/.gaudi_project_ignore
 create mode 100644 Sim/GaussRedecay/.gaudi_project_ignore
 create mode 100644 Sim/GaussTools/.gaudi_project_ignore
 create mode 100644 Sim/GiGa/.gaudi_project_ignore
 create mode 100644 Sim/GiGaCnv/.gaudi_project_ignore
 create mode 100644 Sim/GiGaVisUI/.gaudi_project_ignore
 create mode 100644 Sim/LbGDML/.gaudi_project_ignore
 create mode 100644 Sim/SimChecks/.gaudi_project_ignore
 create mode 100644 VP/.gaudi_project_ignore
 create mode 100644 Vis/.gaudi_project_ignore

diff --git a/Bcm/.gaudi_project_ignore b/Bcm/.gaudi_project_ignore
new file mode 100644
index 000000000..e69de29bb
diff --git a/Bls/.gaudi_project_ignore b/Bls/.gaudi_project_ignore
new file mode 100644
index 000000000..e69de29bb
diff --git a/Gen/AmpGen/.gaudi_project_ignore b/Gen/AmpGen/.gaudi_project_ignore
new file mode 100644
index 000000000..e69de29bb
diff --git a/Gen/BcVegPy/.gaudi_project_ignore b/Gen/BcVegPy/.gaudi_project_ignore
new file mode 100644
index 000000000..e69de29bb
diff --git a/Gen/GenTests/.gaudi_project_ignore b/Gen/GenTests/.gaudi_project_ignore
new file mode 100644
index 000000000..e69de29bb
diff --git a/Gen/GenTune/.gaudi_project_ignore b/Gen/GenTune/.gaudi_project_ignore
new file mode 100644
index 000000000..e69de29bb
diff --git a/Gen/GenXicc/.gaudi_project_ignore b/Gen/GenXicc/.gaudi_project_ignore
new file mode 100644
index 000000000..e69de29bb
diff --git a/Gen/LPair/.gaudi_project_ignore b/Gen/LPair/.gaudi_project_ignore
new file mode 100644
index 000000000..e69de29bb
diff --git a/Gen/LbAmpGen/.gaudi_project_ignore b/Gen/LbAmpGen/.gaudi_project_ignore
new file mode 100644
index 000000000..e69de29bb
diff --git a/Gen/LbBcVegPy/.gaudi_project_ignore b/Gen/LbBcVegPy/.gaudi_project_ignore
new file mode 100644
index 000000000..e69de29bb
diff --git a/Gen/LbBound/.gaudi_project_ignore b/Gen/LbBound/.gaudi_project_ignore
new file mode 100644
index 000000000..e69de29bb
diff --git a/Gen/LbCRMC/.gaudi_project_ignore b/Gen/LbCRMC/.gaudi_project_ignore
new file mode 100644
index 000000000..e69de29bb
diff --git a/Gen/LbGenXicc/.gaudi_project_ignore b/Gen/LbGenXicc/.gaudi_project_ignore
new file mode 100644
index 000000000..e69de29bb
diff --git a/Gen/LbHard/.gaudi_project_ignore b/Gen/LbHard/.gaudi_project_ignore
new file mode 100644
index 000000000..e69de29bb
diff --git a/Gen/LbHerwigpp/.gaudi_project_ignore b/Gen/LbHerwigpp/.gaudi_project_ignore
new file mode 100644
index 000000000..e69de29bb
diff --git a/Gen/LbHidValley/.gaudi_project_ignore b/Gen/LbHidValley/.gaudi_project_ignore
new file mode 100644
index 000000000..e69de29bb
diff --git a/Gen/LbHijing/.gaudi_project_ignore b/Gen/LbHijing/.gaudi_project_ignore
new file mode 100644
index 000000000..e69de29bb
diff --git a/Gen/LbLPair/.gaudi_project_ignore b/Gen/LbLPair/.gaudi_project_ignore
new file mode 100644
index 000000000..e69de29bb
diff --git a/Gen/LbMIB/.gaudi_project_ignore b/Gen/LbMIB/.gaudi_project_ignore
new file mode 100644
index 000000000..e69de29bb
diff --git a/Gen/LbOniaPairs/.gaudi_project_ignore b/Gen/LbOniaPairs/.gaudi_project_ignore
new file mode 100644
index 000000000..e69de29bb
diff --git a/Gen/LbPGuns/.gaudi_project_ignore b/Gen/LbPGuns/.gaudi_project_ignore
new file mode 100644
index 000000000..e69de29bb
diff --git a/Gen/LbPowheg/.gaudi_project_ignore b/Gen/LbPowheg/.gaudi_project_ignore
new file mode 100644
index 000000000..e69de29bb
diff --git a/Gen/LbPythia/.gaudi_project_ignore b/Gen/LbPythia/.gaudi_project_ignore
new file mode 100644
index 000000000..e69de29bb
diff --git a/Gen/LbPythia8/.gaudi_project_ignore b/Gen/LbPythia8/.gaudi_project_ignore
new file mode 100644
index 000000000..e69de29bb
diff --git a/Gen/LbStarLight/.gaudi_project_ignore b/Gen/LbStarLight/.gaudi_project_ignore
new file mode 100644
index 000000000..e69de29bb
diff --git a/Gen/LbSuperChic2/.gaudi_project_ignore b/Gen/LbSuperChic2/.gaudi_project_ignore
new file mode 100644
index 000000000..e69de29bb
diff --git a/Gen/SuperChic2/.gaudi_project_ignore b/Gen/SuperChic2/.gaudi_project_ignore
new file mode 100644
index 000000000..e69de29bb
diff --git a/HC/.gaudi_project_ignore b/HC/.gaudi_project_ignore
new file mode 100644
index 000000000..e69de29bb
diff --git a/Sim/GaussAlgs/.gaudi_project_ignore b/Sim/GaussAlgs/.gaudi_project_ignore
new file mode 100644
index 000000000..e69de29bb
diff --git a/Sim/GaussCherenkov/.gaudi_project_ignore b/Sim/GaussCherenkov/.gaudi_project_ignore
new file mode 100644
index 000000000..e69de29bb
diff --git a/Sim/GaussCore/.gaudi_project_ignore b/Sim/GaussCore/.gaudi_project_ignore
new file mode 100644
index 000000000..e69de29bb
diff --git a/Sim/GaussKine/.gaudi_project_ignore b/Sim/GaussKine/.gaudi_project_ignore
new file mode 100644
index 000000000..e69de29bb
diff --git a/Sim/GaussMonitor/.gaudi_project_ignore b/Sim/GaussMonitor/.gaudi_project_ignore
new file mode 100644
index 000000000..e69de29bb
diff --git a/Sim/GaussRICH/.gaudi_project_ignore b/Sim/GaussRICH/.gaudi_project_ignore
new file mode 100644
index 000000000..e69de29bb
diff --git a/Sim/GaussRedecay/.gaudi_project_ignore b/Sim/GaussRedecay/.gaudi_project_ignore
new file mode 100644
index 000000000..e69de29bb
diff --git a/Sim/GaussTools/.gaudi_project_ignore b/Sim/GaussTools/.gaudi_project_ignore
new file mode 100644
index 000000000..e69de29bb
diff --git a/Sim/GiGa/.gaudi_project_ignore b/Sim/GiGa/.gaudi_project_ignore
new file mode 100644
index 000000000..e69de29bb
diff --git a/Sim/GiGaCnv/.gaudi_project_ignore b/Sim/GiGaCnv/.gaudi_project_ignore
new file mode 100644
index 000000000..e69de29bb
diff --git a/Sim/GiGaVisUI/.gaudi_project_ignore b/Sim/GiGaVisUI/.gaudi_project_ignore
new file mode 100644
index 000000000..e69de29bb
diff --git a/Sim/LbGDML/.gaudi_project_ignore b/Sim/LbGDML/.gaudi_project_ignore
new file mode 100644
index 000000000..e69de29bb
diff --git a/Sim/SimChecks/.gaudi_project_ignore b/Sim/SimChecks/.gaudi_project_ignore
new file mode 100644
index 000000000..e69de29bb
diff --git a/VP/.gaudi_project_ignore b/VP/.gaudi_project_ignore
new file mode 100644
index 000000000..e69de29bb
diff --git a/Vis/.gaudi_project_ignore b/Vis/.gaudi_project_ignore
new file mode 100644
index 000000000..e69de29bb
-- 
GitLab


From 4c5b137f370e4a888768df077cd899e6c924918b Mon Sep 17 00:00:00 2001
From: Dominik Muller <dominik.muller@cern.ch>
Date: Tue, 20 Aug 2019 16:01:10 +0200
Subject: [PATCH 25/90] GaussTape now runs

---
 Sim/Gauss/python/Gauss/Configuration.py | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/Sim/Gauss/python/Gauss/Configuration.py b/Sim/Gauss/python/Gauss/Configuration.py
index 7a6e78c53..80a332c17 100755
--- a/Sim/Gauss/python/Gauss/Configuration.py
+++ b/Sim/Gauss/python/Gauss/Configuration.py
@@ -201,9 +201,14 @@ class Gauss(LHCbConfigurableUser):
 
         IOHelper().outStream(outputFile, simWriter, self.getProp("WriteFSR"))
 
+
         if not FileCatalog().isPropertySet("Catalogs"):
             FileCatalog().Catalogs = ["xmlcatalog_file:NewCatalog.xml"]
 
+        from Configurables import ApplicationMgr
+        ApplicationMgr().TopAlg += [simWriter]
+
+
     # Apply the configuration
     def __apply_configuration__(self):
 
-- 
GitLab


From f40a8cf723b36cb0a1bc3c59bfe8fdc8b9fde8f1 Mon Sep 17 00:00:00 2001
From: Dominik Muller <dominik.muller@cern.ch>
Date: Fri, 23 Aug 2019 16:54:43 +0200
Subject: [PATCH 26/90] Generator versions split by LCG

---
 ...s_versions.txt => generators_versions_LCG95.txt |  0
 generators_versions_LCG96.txt                      | 14 ++++++++++++++
 toolchain.cmake                                    | 12 ++++++------
 3 files changed, 20 insertions(+), 6 deletions(-)
 rename generators_versions.txt => generators_versions_LCG95.txt (100%)
 create mode 100644 generators_versions_LCG96.txt

diff --git a/generators_versions.txt b/generators_versions_LCG95.txt
similarity index 100%
rename from generators_versions.txt
rename to generators_versions_LCG95.txt
diff --git a/generators_versions_LCG96.txt b/generators_versions_LCG96.txt
new file mode 100644
index 000000000..be3003968
--- /dev/null
+++ b/generators_versions_LCG96.txt
@@ -0,0 +1,14 @@
+alpgen         2.1.4
+herwig++       2.7.1
+hijing         1.383bs.2
+lhapdf         6.2.3
+photos++       3.56
+powheg-box-v2  r3043.lhcb
+pythia6        427.2
+pythia8        240
+rivet          2.7.2b
+tauola++       1.1.6b.lhcb
+thepeg         2.1.5
+crmc           1.5.6
+yoda           1.7.5
+starlight      r300
diff --git a/toolchain.cmake b/toolchain.cmake
index c4021cdc1..6ab1c3e11 100644
--- a/toolchain.cmake
+++ b/toolchain.cmake
@@ -5,12 +5,6 @@ cmake_minimum_required(VERSION 3.6)
 
 find_file(inherit_heptools_module InheritHEPTools.cmake)
 
-if(EXISTS ${CMAKE_SOURCE_DIR}/generators_versions.txt)
-  file(READ ${CMAKE_SOURCE_DIR}/generators_versions.txt generators_versions)
-  string(REGEX REPLACE "[ \t\n]+" ";" generators_versions "${generators_versions}")
-  set(generators_versions ${generators_versions})
-endif()
-
 # Process the lines of LCG_generators_*.txt file to extract the
 # needed generators (variable generators_versions)
 macro(lcg_set_generator root name hash version dir)
@@ -75,6 +69,12 @@ if(inherit_heptools_module)
   include(${inherit_heptools_module})
   inherit_heptools()
 
+  if(EXISTS ${CMAKE_SOURCE_DIR}/generators_versions_LCG${heptools_version}.txt)
+    file(READ ${CMAKE_SOURCE_DIR}/generators_versions_LCG${heptools_version}.txt generators_versions)
+    string(REGEX REPLACE "[ \t\n]+" ";" generators_versions "${generators_versions}")
+    set(generators_versions ${generators_versions})
+  endif()
+
   if(LCG_TOOLCHAIN_INFO)
     # prepare list of toolchain info files for generators
     get_filename_component(_info_name ${LCG_TOOLCHAIN_INFO} NAME CACHE)
-- 
GitLab


From a7e6ac0d42af14c51d93cd075a3a738c3949a6b9 Mon Sep 17 00:00:00 2001
From: Dominik Muller <dominik.muller@cern.ch>
Date: Fri, 23 Aug 2019 16:55:30 +0200
Subject: [PATCH 27/90] Migration to split GiGaMTCore headers

---
 Sim/GaussCalo/src/CaloSensDet.h                           | 2 +-
 Sim/GaussCalo/src/CaloSensDet.icpp                        | 2 +-
 Sim/GaussCalo/src/CaloSubHit.h                            | 2 +-
 Sim/GaussCalo/src/GaussSensPlaneDet.cpp                   | 2 +-
 Sim/GaussCalo/src/GaussSensPlaneDet.h                     | 2 +-
 Sim/GaussCalo/src/GaussSensPlaneHit.h                     | 2 +-
 Sim/GaussCalo/src/GetCaloHitsAlg.cpp                      | 2 +-
 Sim/GaussCalo/src/GetCaloHitsAlg.h                        | 2 +-
 Sim/GaussCalo/src/SpdPrsSensDet.cpp                       | 2 +-
 Sim/GaussCore/GaussCore/GaussTrackInformation.h           | 2 +-
 Sim/GaussPhysics/src/cuts/TrCutsRunAction.h               | 2 +-
 Sim/GaussPhysics/src/particles/GiGaHiggsParticles.cpp     | 2 +-
 Sim/GaussPhysics/src/particles/GiGaPhysUnknownParticles.h | 2 +-
 Sim/GaussTracker/src/GetTrackerHitsAlg.h                  | 4 ++--
 Sim/GaussTracker/src/GiGaSensDetTracker.h                 | 4 ++--
 Sim/GaussTracker/src/TrackerHit.h                         | 2 +-
 16 files changed, 18 insertions(+), 18 deletions(-)

diff --git a/Sim/GaussCalo/src/CaloSensDet.h b/Sim/GaussCalo/src/CaloSensDet.h
index 859765f5d..243b073b6 100755
--- a/Sim/GaussCalo/src/CaloSensDet.h
+++ b/Sim/GaussCalo/src/CaloSensDet.h
@@ -9,7 +9,7 @@
 
 // GiGa
 #include "Geant4/G4VSensitiveDetector.hh"
-#include "GiGaMTCore/IGiGaMessage.h"
+#include "GiGaMTCoreMessage/IGiGaMessage.h"
 
 // AIDA
 #include "AIDA/IHistogram1D.h"
diff --git a/Sim/GaussCalo/src/CaloSensDet.icpp b/Sim/GaussCalo/src/CaloSensDet.icpp
index 2610f2338..5a00112da 100755
--- a/Sim/GaussCalo/src/CaloSensDet.icpp
+++ b/Sim/GaussCalo/src/CaloSensDet.icpp
@@ -18,7 +18,7 @@
 #include "GaudiKernel/Stat.h"
 
 // GaussTools
-#include "GiGaMTCore/Truth/GaussinoTrackInformation.h"
+#include "GiGaMTCoreTruth/GaussinoTrackInformation.h"
 
 // Geant4
 #include "Geant4/G4LogicalVolume.hh"
diff --git a/Sim/GaussCalo/src/CaloSubHit.h b/Sim/GaussCalo/src/CaloSubHit.h
index 877eafbf2..2f6430e89 100755
--- a/Sim/GaussCalo/src/CaloSubHit.h
+++ b/Sim/GaussCalo/src/CaloSubHit.h
@@ -5,7 +5,7 @@
 #include <unordered_map>
 // Include files
 #include "GaudiKernel/StatusCode.h"
-#include "GiGaMTCore/GaussHitBase.h"
+#include "GiGaMTCoreDet/GaussHitBase.h"
 // Local
 #include "CaloSimHash.h"
 #include "Geant4/G4Allocator.hh"
diff --git a/Sim/GaussCalo/src/GaussSensPlaneDet.cpp b/Sim/GaussCalo/src/GaussSensPlaneDet.cpp
index ac8fb73f8..3b6e14e00 100755
--- a/Sim/GaussCalo/src/GaussSensPlaneDet.cpp
+++ b/Sim/GaussCalo/src/GaussSensPlaneDet.cpp
@@ -13,7 +13,7 @@
 #include "GaudiKernel/SmartDataPtr.h"
 
 // GaussTools
-#include "GiGaMTCore/Truth/GaussinoTrackInformation.h"
+#include "GiGaMTCoreTruth/GaussinoTrackInformation.h"
 
 // Geant4
 #include "Geant4/G4Electron.hh"
diff --git a/Sim/GaussCalo/src/GaussSensPlaneDet.h b/Sim/GaussCalo/src/GaussSensPlaneDet.h
index 077cd4485..9c838bc59 100755
--- a/Sim/GaussCalo/src/GaussSensPlaneDet.h
+++ b/Sim/GaussCalo/src/GaussSensPlaneDet.h
@@ -10,7 +10,7 @@
 // local
 #include "CaloHit.h"
 #include "GaussSensPlaneHit.h"
-#include "GiGaMTCore/IGiGaMessage.h"
+#include "GiGaMTCoreMessage/IGiGaMessage.h"
 
 /** @class GaussSensPlaneDet GaussSensPlaneDet.h GaussSensPlaneDet.h
  *
diff --git a/Sim/GaussCalo/src/GaussSensPlaneHit.h b/Sim/GaussCalo/src/GaussSensPlaneHit.h
index 372a0aa53..2a3f7ff04 100755
--- a/Sim/GaussCalo/src/GaussSensPlaneHit.h
+++ b/Sim/GaussCalo/src/GaussSensPlaneHit.h
@@ -7,7 +7,7 @@
 // Event
 #include "Kernel/ParticleID.h"
 // GaussTools
-#include "GiGaMTCore/GaussHitBase.h"
+#include "GiGaMTCoreDet/GaussHitBase.h"
 // Geant4
 #include "Geant4/G4THitsCollection.hh"
 // ============================================================================
diff --git a/Sim/GaussCalo/src/GetCaloHitsAlg.cpp b/Sim/GaussCalo/src/GetCaloHitsAlg.cpp
index 07e95e198..b0960d8fc 100755
--- a/Sim/GaussCalo/src/GetCaloHitsAlg.cpp
+++ b/Sim/GaussCalo/src/GetCaloHitsAlg.cpp
@@ -10,7 +10,7 @@
 #include "CaloHit.h"
 #include "CaloSubHit.h"
 #include "GetCaloHitsAlg.h"
-#include "GiGaMTCore/Truth/MCTruthConverter.h"
+#include "GiGaMTCoreTruth/MCTruthConverter.h"
 
 //-----------------------------------------------------------------------------
 // Implementation file for class : GetCaloHitsAlg
diff --git a/Sim/GaussCalo/src/GetCaloHitsAlg.h b/Sim/GaussCalo/src/GetCaloHitsAlg.h
index 73a811bcc..f12e4a00a 100755
--- a/Sim/GaussCalo/src/GetCaloHitsAlg.h
+++ b/Sim/GaussCalo/src/GetCaloHitsAlg.h
@@ -4,7 +4,7 @@
 #include "Event/MCCaloHit.h"
 #include "GaudiAlg/GaudiAlgorithm.h"
 #include "GaudiAlg/Transformer.h"
-#include "GiGaMTCore/G4EventProxy.h"
+#include "GiGaMTCoreRun/G4EventProxy.h"
 #include "MCTruthToEDM/LinkedParticleMCParticleLink.h"
 
 /** @class GetCaloHitsAlg GetCaloHitsAlg.h
diff --git a/Sim/GaussCalo/src/SpdPrsSensDet.cpp b/Sim/GaussCalo/src/SpdPrsSensDet.cpp
index 14c35ebef..6c2dd3d78 100755
--- a/Sim/GaussCalo/src/SpdPrsSensDet.cpp
+++ b/Sim/GaussCalo/src/SpdPrsSensDet.cpp
@@ -15,7 +15,7 @@
 #include "GaudiKernel/IHistogramSvc.h"
 
 // GaussTools
-#include "GiGaMTCore/Truth/GaussinoTrackInformation.h"
+#include "GiGaMTCoreTruth/GaussinoTrackInformation.h"
 
 // Geant4
 #include "Geant4/G4Step.hh"
diff --git a/Sim/GaussCore/GaussCore/GaussTrackInformation.h b/Sim/GaussCore/GaussCore/GaussTrackInformation.h
index ee83477f0..d9d83920e 100755
--- a/Sim/GaussCore/GaussCore/GaussTrackInformation.h
+++ b/Sim/GaussCore/GaussCore/GaussTrackInformation.h
@@ -8,7 +8,7 @@
 /// GaussTools
 #include "DetTrackInfo.h"
 #include "Geant4/G4Allocator.hh"
-#include "GiGaMTCore/GaussHitBase.h"
+#include "GiGaMTCoreDet/GaussHitBase.h"
 
 /** @class GaussTrackInformation GaussTrackInformation.h
  *
diff --git a/Sim/GaussPhysics/src/cuts/TrCutsRunAction.h b/Sim/GaussPhysics/src/cuts/TrCutsRunAction.h
index f7e58756a..2ca7dfc64 100755
--- a/Sim/GaussPhysics/src/cuts/TrCutsRunAction.h
+++ b/Sim/GaussPhysics/src/cuts/TrCutsRunAction.h
@@ -1,7 +1,7 @@
 #pragma once
 #include "Geant4/G4VPhysicsConstructor.hh"
 #include "CLHEP/Units/SystemOfUnits.h"
-#include "GiGaMTCore/IGiGaMessage.h"
+#include "GiGaMTCoreMessage/IGiGaMessage.h"
 #include <vector>
 
 
diff --git a/Sim/GaussPhysics/src/particles/GiGaHiggsParticles.cpp b/Sim/GaussPhysics/src/particles/GiGaHiggsParticles.cpp
index fb8a6729a..6551fbb99 100755
--- a/Sim/GaussPhysics/src/particles/GiGaHiggsParticles.cpp
+++ b/Sim/GaussPhysics/src/particles/GiGaHiggsParticles.cpp
@@ -11,7 +11,7 @@
 #include "Geant4/G4VPhysicsConstructor.hh"
 // Local
 #include "G4Higgses.h"
-#include "GiGaMTCore/IGiGaMessage.h"
+#include "GiGaMTCoreMessage/IGiGaMessage.h"
 #include "GiGaMTFactories/GiGaMTG4PhysicsConstrFAC.h"
 
 class GiGaMTHiggsParticles : public G4VPhysicsConstructor, public GiGaMessage
diff --git a/Sim/GaussPhysics/src/particles/GiGaPhysUnknownParticles.h b/Sim/GaussPhysics/src/particles/GiGaPhysUnknownParticles.h
index 3b08c0a2b..c5e2bb7e5 100755
--- a/Sim/GaussPhysics/src/particles/GiGaPhysUnknownParticles.h
+++ b/Sim/GaussPhysics/src/particles/GiGaPhysUnknownParticles.h
@@ -3,7 +3,7 @@
 #include "Geant4/G4VPhysicsConstructor.hh"
 #include "Geant4/G4Decay.hh"
 #include "Geant4/G4UnknownDecay.hh"
-#include "GiGaMTCore/IGiGaMessage.h"
+#include "GiGaMTCoreMessage/IGiGaMessage.h"
 
 class GiGaMTPhysUnknownParticles :public GiGaMessage, public G4VPhysicsConstructor
 {
diff --git a/Sim/GaussTracker/src/GetTrackerHitsAlg.h b/Sim/GaussTracker/src/GetTrackerHitsAlg.h
index 00f58219f..39657950e 100755
--- a/Sim/GaussTracker/src/GetTrackerHitsAlg.h
+++ b/Sim/GaussTracker/src/GetTrackerHitsAlg.h
@@ -6,8 +6,8 @@
 #include "GaudiAlg/GaudiAlgorithm.h"
 #include "GaudiAlg/Transformer.h"
 #include "GaudiKernel/DataHandle.h"
-#include "GiGaMTCore/G4EventProxy.h"
-#include "GiGaMTCore/Truth/MCTruthConverter.h"
+#include "GiGaMTCoreRun/G4EventProxy.h"
+#include "GiGaMTCoreTruth/MCTruthConverter.h"
 #include "MCTruthToEDM/LinkedParticleMCParticleLink.h"
 
 #include "Defaults/Locations.h"
diff --git a/Sim/GaussTracker/src/GiGaSensDetTracker.h b/Sim/GaussTracker/src/GiGaSensDetTracker.h
index 7613de9b7..afabcfb8f 100755
--- a/Sim/GaussTracker/src/GiGaSensDetTracker.h
+++ b/Sim/GaussTracker/src/GiGaSensDetTracker.h
@@ -1,8 +1,8 @@
 #pragma once
 
 // Include files
-#include "GiGaMTCore/Truth/GaussinoTrackInformation.h"
-#include "GiGaMTCore/IGiGaMessage.h"
+#include "GiGaMTCoreTruth/GaussinoTrackInformation.h"
+#include "GiGaMTCoreMessage/IGiGaMessage.h"
 #include "Geant4/G4VSensitiveDetector.hh"
 #include "TrackerHit.h"
 
diff --git a/Sim/GaussTracker/src/TrackerHit.h b/Sim/GaussTracker/src/TrackerHit.h
index 65d588957..8db6d67e4 100755
--- a/Sim/GaussTracker/src/TrackerHit.h
+++ b/Sim/GaussTracker/src/TrackerHit.h
@@ -14,7 +14,7 @@
 #include "Geant4/G4Allocator.hh"
 #include "Geant4/G4THitsCollection.hh"
 #include "Geant4/G4ThreeVector.hh"
-#include "GiGaMTCore/GaussHitBase.h"
+#include "GiGaMTCoreDet/GaussHitBase.h"
 
 class TrackerHit : public Gaussino::HitBase {
   public:
-- 
GitLab


From 792bd8bb9f8cf6e2111d42f4bce221d5d8231478 Mon Sep 17 00:00:00 2001
From: Dominik Muller <dominik.muller@cern.ch>
Date: Wed, 28 Aug 2019 18:29:49 +0200
Subject: [PATCH 28/90] Config changes to allow Gauss() to be used in gen only

---
 Sim/Gauss/python/Gauss/Configuration.py       | 45 +++++++++++++++----
 .../python/Gauss/Geometry/Configuration.py    |  3 ++
 Sim/Gauss/python/Gauss/Physics.py             |  3 ++
 3 files changed, 42 insertions(+), 9 deletions(-)

diff --git a/Sim/Gauss/python/Gauss/Configuration.py b/Sim/Gauss/python/Gauss/Configuration.py
index 80a332c17..1ac90d06b 100755
--- a/Sim/Gauss/python/Gauss/Configuration.py
+++ b/Sim/Gauss/python/Gauss/Configuration.py
@@ -11,13 +11,13 @@ from Configurables import LHCbConfigurableUser, LHCbApp, SimConf
 from Configurables import Gaussino
 from Gauss.Geometry import LHCbGeo
 from Gauss import G4Physics
+from GaudiKernel import SystemOfUnits
 
 
 class Gauss(LHCbConfigurableUser):
 
     # Possible used Configurables
     __used_configurables__ = [LHCbApp, SimConf, Gaussino,
-                              LHCbGeo, G4Physics
                               # (GaussRICHConf,None),
                               # (GaussCherenkovConf,None)
                               ]
@@ -27,14 +27,27 @@ class Gauss(LHCbConfigurableUser):
         # The Gauss phases to include in the SIM file
         "Histograms": "DEFAULT",
         "DatasetName": "Gauss",
-        "Phases": ["Generator", "Simulation"],
         "DataType": "", "SpilloverPaths": [],
         "OutputType": 'SIM', "EnablePack": True,
         "DataPackingChecks": True,
         "WriteFSR": False,
         "MergeGenFSR": False,
         "Debug": False,
-        "ForceRandomEngine": 'NONE'
+        "ForceRandomEngine": 'NONE',
+        "Phases": ["Generator", "Simulation"],
+        "BeamMomentum": 3.5 * SystemOfUnits.TeV,  # NOQA
+        "BeamHCrossingAngle": -0.520 * SystemOfUnits.mrad,  # NOQA
+        "BeamVCrossingAngle": 0.0,  # NOQA
+        "BeamEmittance": 0.0037 * SystemOfUnits.mm,  # NOQA
+        "BeamBetaStar": 3.1 * SystemOfUnits.m,  # NOQA
+        "BeamLineAngles": [-0.075 * SystemOfUnits.mrad, 0.035 * SystemOfUnits.mrad],  # NOQA
+        "InteractionPosition" : [0.459 * SystemOfUnits.mm, -0.015 * SystemOfUnits.mm, 0.5 * SystemOfUnits.mm],  # NOQA
+        "BunchRMS": 82.03 * SystemOfUnits.mm,  # NOQA
+        "Luminosity": 0.247 * (10 ** 30) / (SystemOfUnits.cm2 * SystemOfUnits.s),  # NOQA
+        "TotalCrossSection": 91.1 * SystemOfUnits.millibarn,  # NOQA
+        "B2Momentum": 3.5 * SystemOfUnits.TeV,  # NOQA
+        "B1Particle": 'p',  # NOQA
+        "B2Particle": 'p',  # NOQA
         }
 
     _propertyDocDct = {
@@ -105,6 +118,9 @@ class Gauss(LHCbConfigurableUser):
         self.setOtherProps(
             SimConf(), [
                 "SpilloverPaths", "EnablePack", "Phases", "DataType"])
+        # Empty the list of detectors, it is later populated when configuring
+        # the subdetectors
+        SimConf().Detectors = []
         # if we have post-sim filters, we only want to write if the filter is
         # passed
         # if self.getProp("PostSimFilters"):
@@ -118,8 +134,11 @@ class Gauss(LHCbConfigurableUser):
                 self.Members = []
 
         packing = dummy()
-        for so in self.defineCrossingList():
-            SimConf().PackingSequencers[so] = packing
+        # Need this dummy sequence to later extract all the algorithm that
+        # need to be given to the scheduler.
+        if Gaussino().getProp('ConvertEDM') or "Simulation" in Gauss().getProp("Phases"):
+            for so in self.defineCrossingList():
+                SimConf().PackingSequencers[so] = packing
 
         from Gaudi.Configuration import appendPostConfigAction
 
@@ -201,27 +220,35 @@ class Gauss(LHCbConfigurableUser):
 
         IOHelper().outStream(outputFile, simWriter, self.getProp("WriteFSR"))
 
-
         if not FileCatalog().isPropertySet("Catalogs"):
             FileCatalog().Catalogs = ["xmlcatalog_file:NewCatalog.xml"]
 
         from Configurables import ApplicationMgr
         ApplicationMgr().TopAlg += [simWriter]
 
-
     # Apply the configuration
     def __apply_configuration__(self):
 
         self.setOtherProps(Gaussino(), [
             "Histograms", "DatasetName", "Phases", "SpilloverPaths"])
 
+        # Propagate beam settings for compatibility with existing option files
+        from Gaussino.Generation import GenPhase
+
+        self.setOtherProps(GenPhase(), [
+            "BeamMomentum", "BeamHCrossingAngle", "BeamVCrossingAngle",
+            "BeamEmittance", "BeamBetaStar", "BeamLineAngles",
+            "InteractionPosition", "BunchRMS", "Luminosity",
+            "TotalCrossSection", "B2Momentum", "B1Particle", "B2Particle"])
+
         LHCbApp(Simulation=True)  # in Boole? where?
         if Gaussino().getProp('EnableHive') is True:
             LHCbApp().EnableHive = True
 
         self.propagateSimConf()
-        G4Physics()
-        LHCbGeo()
+        if "Simulation" in Gaussino().getProp("Phases"):
+            G4Physics().apply()
+            LHCbGeo().apply()
 
         crossingList = self.defineCrossingList()
 
diff --git a/Sim/Gauss/python/Gauss/Geometry/Configuration.py b/Sim/Gauss/python/Gauss/Geometry/Configuration.py
index aafcf5d91..379fd8e62 100644
--- a/Sim/Gauss/python/Gauss/Geometry/Configuration.py
+++ b/Sim/Gauss/python/Gauss/Geometry/Configuration.py
@@ -84,6 +84,9 @@ class LHCbGeo(LHCbConfigurableUser):
                     self._listOfGeoObjects_.append(myStreamItem)
 
     def __apply_configuration__(self):
+        pass
+
+    def apply(self):
         from Configurables import GaussGeo
         if self.getProp('Debug'):
             GaussGeo.OutputLevel = -10
diff --git a/Sim/Gauss/python/Gauss/Physics.py b/Sim/Gauss/python/Gauss/Physics.py
index da407d11f..e01c4450d 100644
--- a/Sim/Gauss/python/Gauss/Physics.py
+++ b/Sim/Gauss/python/Gauss/Physics.py
@@ -43,6 +43,9 @@ class G4Physics(LHCbConfigurableUser):
     }
 
     def __apply_configuration__(self):
+        pass
+
+    def apply(self):
         from Configurables import GiGaMT
         giga = GiGaMT()
 
-- 
GitLab


From 6bb78071d60f9ee2b7493e3d9c08ce78321ca8af Mon Sep 17 00:00:00 2001
From: Dominik Muller <dominik.muller@cern.ch>
Date: Thu, 29 Aug 2019 13:54:02 +0200
Subject: [PATCH 29/90] Gauss configurable now manages most other configurables

---
 Sim/Gauss/python/Gauss/Configuration.py       | 43 ++++++++-----------
 .../python/Gauss/Geometry/Configuration.py    | 19 --------
 2 files changed, 19 insertions(+), 43 deletions(-)

diff --git a/Sim/Gauss/python/Gauss/Configuration.py b/Sim/Gauss/python/Gauss/Configuration.py
index 1ac90d06b..2fbc41945 100755
--- a/Sim/Gauss/python/Gauss/Configuration.py
+++ b/Sim/Gauss/python/Gauss/Configuration.py
@@ -9,8 +9,6 @@ from Gaudi.Configuration import log, GaudiSequencer, FileCatalog
 from Gaudi.Configuration import ApplicationMgr
 from Configurables import LHCbConfigurableUser, LHCbApp, SimConf
 from Configurables import Gaussino
-from Gauss.Geometry import LHCbGeo
-from Gauss import G4Physics
 from GaudiKernel import SystemOfUnits
 
 
@@ -48,6 +46,11 @@ class Gauss(LHCbConfigurableUser):
         "B2Momentum": 3.5 * SystemOfUnits.TeV,  # NOQA
         "B1Particle": 'p',  # NOQA
         "B2Particle": 'p',  # NOQA
+        "EvtMax": -1,  # NOQA
+        "EnableHive": False,  # NOQA
+        "ThreadPoolSize": 2,  # NOQA
+        "EventSlots" : 2,  # NOQA
+        "ConvertEDM" : False,  # NOQA
         }
 
     _propertyDocDct = {
@@ -89,9 +92,6 @@ class Gauss(LHCbConfigurableUser):
             return slot + '/'
         return slot
 
-    def evtMax(self):
-        return LHCbApp().evtMax()
-
     def eventType(self):
         from Configurables import Generation
         evtType = ''
@@ -99,19 +99,6 @@ class Gauss(LHCbConfigurableUser):
             evtType = str(Generation("Generation").EventType)
         return evtType
 
-    def setLHCbAppDetectors(self):
-        from Configurables import LHCbApp
-        # If detectors set in LHCbApp then use those
-        if hasattr(LHCbApp(), "Detectors"):
-            if not LHCbApp().Detectors:
-                LHCbApp().Detectors = self.getProp("DetectorGeo")["Detectors"]
-            else:
-                log.warning(
-                    "Value of 'LHCbApp().Detectors' already"
-                    "set, using that value: %s" %
-                    (LHCbApp().Detectors))
-        return
-
     def propagateSimConf(self):
         # Propagate properties to SimConf
         SimConf().setProp("Writer", "GaussTape")
@@ -230,24 +217,32 @@ class Gauss(LHCbConfigurableUser):
     def __apply_configuration__(self):
 
         self.setOtherProps(Gaussino(), [
-            "Histograms", "DatasetName", "Phases", "SpilloverPaths"])
+            "Histograms", "DatasetName", "Phases", "SpilloverPaths", "EvtMax",
+            "EnableHive", "ThreadPoolSize", "EventSlots", "ConvertEDM"])
+
+        LHCbApp().Simulation = True
+        self.setOtherProps(LHCbApp(), [
+            "EvtMax", "EnableHive", "ThreadPoolSize"])
 
         # Propagate beam settings for compatibility with existing option files
         from Gaussino.Generation import GenPhase
-
         self.setOtherProps(GenPhase(), [
             "BeamMomentum", "BeamHCrossingAngle", "BeamVCrossingAngle",
             "BeamEmittance", "BeamBetaStar", "BeamLineAngles",
             "InteractionPosition", "BunchRMS", "Luminosity",
             "TotalCrossSection", "B2Momentum", "B1Particle", "B2Particle"])
 
-        LHCbApp(Simulation=True)  # in Boole? where?
-        if Gaussino().getProp('EnableHive') is True:
-            LHCbApp().EnableHive = True
-
+        # Propagates and sets up SimConf to be able to configure the
+        # OutputStream during its apply_configuration
         self.propagateSimConf()
+
+        # Trigger the simulation related configuration if simulation is in
+        # phases
         if "Simulation" in Gaussino().getProp("Phases"):
+            from Gauss import G4Physics
             G4Physics().apply()
+            from Gauss.Geometry import LHCbGeo
+            LHCbGeo().setOtherProps(LHCbApp(), ['DetectorGeo'])
             LHCbGeo().apply()
 
         crossingList = self.defineCrossingList()
diff --git a/Sim/Gauss/python/Gauss/Geometry/Configuration.py b/Sim/Gauss/python/Gauss/Geometry/Configuration.py
index 379fd8e62..be82a13ba 100644
--- a/Sim/Gauss/python/Gauss/Geometry/Configuration.py
+++ b/Sim/Gauss/python/Gauss/Geometry/Configuration.py
@@ -1,9 +1,7 @@
-from Gaudi.Configuration import log
 from Configurables import LHCbConfigurableUser
 from Gaudi.Configuration import Configurable
 from Gauss.Geometry.Helpers import checkIncompatibleDetectors
 from Gauss.Geometry.Helpers import defineGeoBasePieces
-from Configurables import LHCbApp, SimConf
 
 
 class LHCbGeo(LHCbConfigurableUser):
@@ -11,8 +9,6 @@ class LHCbGeo(LHCbConfigurableUser):
     """Main configurable to set up the LHCb geometry using the GaussGeo
     service for Run1 or Run2"""
 
-    __used_configurables__ = [LHCbApp, SimConf]
-
     __knownDetectors__ = [
         'velo', 'puveto', 'vp', 'tt', 'ut',
         'it', 'sl', 'ot', 'ft', 'ft-noshield',
@@ -55,18 +51,6 @@ class LHCbGeo(LHCbConfigurableUser):
     # GaussGeo or in GiGaInputStream if GiGaGeo is used for conversion
     _listOfGeoObjects_ = []
 
-    def setLHCbAppDetectors(self):
-        from Configurables import LHCbApp
-        # If detectors set in LHCbApp then use those
-        if hasattr(LHCbApp(), "Detectors"):
-            if not LHCbApp().Detectors:
-                LHCbApp().Detectors = self.getProp("DetectorGeo")["Detectors"]
-            else:
-                log.warning(
-                    "Value of 'LHCbApp().Detectors' already set"
-                    ", using that value: %s" % LHCbApp().Detectors)
-        return
-
     def __init__(self, name=Configurable.DefaultName, **kwargs):
         kwargs["name"] = name
         super(LHCbConfigurableUser, self).__init__(*(), **kwargs)
@@ -100,7 +84,6 @@ class LHCbGeo(LHCbConfigurableUser):
                      'AfterDownstreamRegion': []}
         basePieces = {}
 
-        self.setLHCbAppDetectors()
         checkIncompatibleDetectors()
         defineGeoBasePieces(basePieces)
 
@@ -166,8 +149,6 @@ class LHCbGeo(LHCbConfigurableUser):
         self.MakeItTalkToGaussino()
 
         # Setup read-out algorithms
-        # but first reset the SimConf detector list
-        SimConf().setProp('Detectors', [])
         for det in detectors_geo:
             getsubdetector(det).SetupExtraction()
 
-- 
GitLab


From dff4e136383d4d531130263f6e5a9ce9201c9521 Mon Sep 17 00:00:00 2001
From: Dominik Muller <dominik.muller@cern.ch>
Date: Wed, 4 Sep 2019 17:33:16 +0200
Subject: [PATCH 30/90] Working upgrade configuration

---
 Sim/Gauss/python/Gauss/Configuration.py        |  2 +-
 Sim/Gauss/python/Gauss/Geometry/BeamPipe.py    |  8 ++++----
 .../python/Gauss/Geometry/Configuration.py     | 11 ++++++++---
 Sim/Gauss/python/Gauss/Geometry/FT.py          | 15 +++++++++++++++
 Sim/Gauss/python/Gauss/Geometry/UT.py          | 14 ++++++++++++++
 Sim/Gauss/python/Gauss/Geometry/VP.py          | 18 ++++++++++++++++++
 Sim/Gauss/python/Gauss/Physics.py              |  5 +++--
 7 files changed, 63 insertions(+), 10 deletions(-)

diff --git a/Sim/Gauss/python/Gauss/Configuration.py b/Sim/Gauss/python/Gauss/Configuration.py
index 2fbc41945..bacd09f1e 100755
--- a/Sim/Gauss/python/Gauss/Configuration.py
+++ b/Sim/Gauss/python/Gauss/Configuration.py
@@ -222,7 +222,7 @@ class Gauss(LHCbConfigurableUser):
 
         LHCbApp().Simulation = True
         self.setOtherProps(LHCbApp(), [
-            "EvtMax", "EnableHive", "ThreadPoolSize"])
+            "EvtMax", "EnableHive", "ThreadPoolSize", "DataType"])
 
         # Propagate beam settings for compatibility with existing option files
         from Gaussino.Generation import GenPhase
diff --git a/Sim/Gauss/python/Gauss/Geometry/BeamPipe.py b/Sim/Gauss/python/Gauss/Geometry/BeamPipe.py
index 00e6e95ea..1a9d2b04f 100644
--- a/Sim/Gauss/python/Gauss/Geometry/BeamPipe.py
+++ b/Sim/Gauss/python/Gauss/Geometry/BeamPipe.py
@@ -103,8 +103,8 @@ class BeamPipe(det_base):
         if "UT" not in all_dets and "TT" not in all_dets:
             from Configurables import LHCbApp
             if LHCbApp().getProp("DataType") not in ["Upgrade"]:
-                for element in BeamPipe._beamPipeElements["tt"]:
-                    BeamPipe._listOfGeoObjects_.append(element)
+                for element in self._beamPipeElements["tt"]:
+                    LHCbGeo._listOfGeoObjects_.append(element)
             else:
-                for element in BeamPipe._beamPipeElements["ut"]:
-                    BeamPipe._listOfGeoObjects_.append(element)
+                for element in self._beamPipeElements["ut"]:
+                    LHCbGeo._listOfGeoObjects_.append(element)
diff --git a/Sim/Gauss/python/Gauss/Geometry/Configuration.py b/Sim/Gauss/python/Gauss/Geometry/Configuration.py
index be82a13ba..1e1399672 100644
--- a/Sim/Gauss/python/Gauss/Geometry/Configuration.py
+++ b/Sim/Gauss/python/Gauss/Geometry/Configuration.py
@@ -28,7 +28,9 @@ class LHCbGeo(LHCbConfigurableUser):
         "DetectorMoni": {
             "Detectors": ['PuVeto', 'Velo', 'TT', 'IT', 'OT', 'Rich1', 'Rich2',
                           'Spd', 'Prs', 'Ecal', 'Hcal', 'Muon']},
-        "Debug": False
+        "Debug": False,
+        "SensDetMap":{},
+        "ExtraGeoTools":[]
         }
 
     _detectorsDefaults = {
@@ -149,7 +151,7 @@ class LHCbGeo(LHCbConfigurableUser):
         self.MakeItTalkToGaussino()
 
         # Setup read-out algorithms
-        for det in detectors_geo:
+        for det in detectors_sim:
             getsubdetector(det).SetupExtraction()
 
         for det in detectors_moni:
@@ -163,10 +165,13 @@ class LHCbGeo(LHCbConfigurableUser):
         dettool = giga.addTool(GiGaMTProxyDetectorConstructionFAC,
                                "GiGaMTProxyDetectorConstructionFAC")
         dettool.GiGaMTGeoSvc = "GaussGeo"
+        dettool.SensDetVolumeMap = self.getProp('SensDetMap')
+
+        dettool.AfterGeoConstructionTools = self.getProp('ExtraGeoTools')
 
         # Now add the tools automatically set up after the construction
         # of the geometry to configure the regions
-        dettool.AfterGeoConstructionTools = [
+        dettool.AfterGeoConstructionTools += [
             'GiGaSetSimAttributes',
             'GiGaRegionsTool']
         from Configurables import GiGaSetSimAttributes
diff --git a/Sim/Gauss/python/Gauss/Geometry/FT.py b/Sim/Gauss/python/Gauss/Geometry/FT.py
index 38713ec43..c59eb9a7f 100644
--- a/Sim/Gauss/python/Gauss/Geometry/FT.py
+++ b/Sim/Gauss/python/Gauss/Geometry/FT.py
@@ -18,6 +18,21 @@ class FT(det_base):
         region = "DownstreamRegion"
         detPieces[region] += ['NeutronShielding']
 
+
+    def SetupExtractionImpl(self, slot=''):
+        from Configurables import GetTrackerHitsAlg
+        self.simconf_name = 'FT'
+        region   = "AfterMagnetRegion/T"
+        det = "FT"
+        alg = GetTrackerHitsAlg(
+            'Get'+det+'Hits'+slot,
+            MCHitsLocation='MC/'+det+'/Hits',
+            CollectionName=det + 'SDet/Hits',
+            Detectors=['/dd/Structure/LHCb/' + region + '/' + det]
+        )
+        from Configurables import ApplicationMgr
+        ApplicationMgr().TopAlg += [alg]
+
     def SetupMonitor(self, slot=''):
         from Configurables import MCHitMonitor
         from GaudiKernel import SystemOfUnits
diff --git a/Sim/Gauss/python/Gauss/Geometry/UT.py b/Sim/Gauss/python/Gauss/Geometry/UT.py
index b38cd5b73..229edd8af 100644
--- a/Sim/Gauss/python/Gauss/Geometry/UT.py
+++ b/Sim/Gauss/python/Gauss/Geometry/UT.py
@@ -11,6 +11,20 @@ class UT(det_base):
         if 'UT' not in detPieces['BeforeMagnetRegion']:
             detPieces['BeforeMagnetRegion'] += ['UT']
 
+    def SetupExtractionImpl(self, slot=''):
+        from Configurables import GetTrackerHitsAlg
+        self.simconf_name = 'UT'
+        region = "BeforeMagnetRegion"
+        det = "UT"
+        alg = GetTrackerHitsAlg(
+            'Get'+det+'Hits'+slot,
+            MCHitsLocation='MC/'+det+'/Hits',
+            CollectionName=det + 'SDet/Hits',
+            Detectors=['/dd/Structure/LHCb/' + region + '/' + det]
+        )
+        from Configurables import ApplicationMgr
+        ApplicationMgr().TopAlg += [alg]
+
     def SetupMonitor(self, slot=''):
         from Configurables import MCHitMonitor
         from GaudiKernel import SystemOfUnits
diff --git a/Sim/Gauss/python/Gauss/Geometry/VP.py b/Sim/Gauss/python/Gauss/Geometry/VP.py
index be44b1dcb..e9689d68b 100644
--- a/Sim/Gauss/python/Gauss/Geometry/VP.py
+++ b/Sim/Gauss/python/Gauss/Geometry/VP.py
@@ -12,3 +12,21 @@ class VP(det_base):
         BeamPipe.removeBeamPipeElements("velo")
         if 'BeforeMagnetRegion' in detPieces:
             detPieces['BeforeMagnetRegion'] += ['VP']
+
+    def SetupExtractionImpl(self, slot=''):
+        from Configurables import GetTrackerHitsAlg
+        self.simconf_name = 'VP'
+        region = "BeforeMagnetRegion"
+        det = "VP"
+        alg = GetTrackerHitsAlg(
+            'Get'+det+'Hits'+slot,
+            MCHitsLocation='MC/'+det+'/Hits',
+            CollectionName=det + 'SDet/Hits',
+            Detectors=['/dd/Structure/LHCb/' + region + '/' + det]
+        )
+        from Configurables import ApplicationMgr
+        ApplicationMgr().TopAlg += [alg]
+
+    def SetupMonitor(self, slot=''):
+        from Gaudi.Configuration import log
+        log.warning("Monitoring for VP not available yet")
diff --git a/Sim/Gauss/python/Gauss/Physics.py b/Sim/Gauss/python/Gauss/Physics.py
index e01c4450d..2b425796b 100644
--- a/Sim/Gauss/python/Gauss/Physics.py
+++ b/Sim/Gauss/python/Gauss/Physics.py
@@ -22,7 +22,8 @@ class G4Physics(LHCbConfigurableUser):
         "LHCbPhys": False,
         "Other": '',
         "DeltaRays": True,
-        "RichUpgradeConfig": False
+        "RichUpgradeConfig": False,
+        "AddPhysConstr": [],
     }
 
     _propertyDocDct = {
@@ -54,7 +55,7 @@ class G4Physics(LHCbConfigurableUser):
                             name="ModularPL")
         giga.PhysicsListFactory = "GiGaMTModularPhysListFAC/ModularPL"
         gmpl = giga.ModularPL
-        gmpl.PhysicsConstructors = []
+        gmpl.PhysicsConstructors = self.getProp('AddPhysConstr')
 
         # set production cuts
         ecut = 5.0 * SystemOfUnits.mm
-- 
GitLab


From ee08b53c10537236850b1436347b4ad72e03df0b Mon Sep 17 00:00:00 2001
From: Dominik Muller <dominik.muller@cern.ch>
Date: Mon, 9 Sep 2019 11:24:40 +0200
Subject: [PATCH 31/90] Example package for Run3 Lumi studies

---
 Example/LHCbLumi/CMakeLists.txt               |  25 +
 Example/LHCbLumi/options/setup.py             |  87 +++
 Example/LHCbLumi/src/AddLumiDetectorTool.cpp  | 518 ++++++++++++++++++
 Example/LHCbLumi/src/AddLumiDetectorTool.h    |  60 ++
 Example/LHCbLumi/src/HitDataStructure.hh      |  23 +
 Example/LHCbLumi/src/LConst.hh                | 135 +++++
 Example/LHCbLumi/src/LumiHit.cpp              |  40 ++
 Example/LHCbLumi/src/LumiHit.h                |  50 ++
 .../LHCbLumi/src/LumiSensitiveDetector.cpp    | 112 ++++
 Example/LHCbLumi/src/LumiSensitiveDetector.h  |  25 +
 Example/LHCbLumi/src/LumiSteppingAction.cpp   | 193 +++++++
 Example/LHCbLumi/src/LumiSteppingAction.h     |  23 +
 Example/LHCbLumi/src/LumiVolumeStructures.h   | 115 ++++
 Example/LHCbLumi/src/MakeLumiHitsTuple.cpp    |  89 +++
 Example/LHCbLumi/src/MakeLumiHitsTuple.h      |  65 +++
 Example/LHCbLumi/src/Physics.cpp              |   6 +
 16 files changed, 1566 insertions(+)
 create mode 100644 Example/LHCbLumi/CMakeLists.txt
 create mode 100644 Example/LHCbLumi/options/setup.py
 create mode 100644 Example/LHCbLumi/src/AddLumiDetectorTool.cpp
 create mode 100644 Example/LHCbLumi/src/AddLumiDetectorTool.h
 create mode 100644 Example/LHCbLumi/src/HitDataStructure.hh
 create mode 100644 Example/LHCbLumi/src/LConst.hh
 create mode 100644 Example/LHCbLumi/src/LumiHit.cpp
 create mode 100644 Example/LHCbLumi/src/LumiHit.h
 create mode 100644 Example/LHCbLumi/src/LumiSensitiveDetector.cpp
 create mode 100644 Example/LHCbLumi/src/LumiSensitiveDetector.h
 create mode 100644 Example/LHCbLumi/src/LumiSteppingAction.cpp
 create mode 100644 Example/LHCbLumi/src/LumiSteppingAction.h
 create mode 100644 Example/LHCbLumi/src/LumiVolumeStructures.h
 create mode 100755 Example/LHCbLumi/src/MakeLumiHitsTuple.cpp
 create mode 100755 Example/LHCbLumi/src/MakeLumiHitsTuple.h
 create mode 100644 Example/LHCbLumi/src/Physics.cpp

diff --git a/Example/LHCbLumi/CMakeLists.txt b/Example/LHCbLumi/CMakeLists.txt
new file mode 100644
index 000000000..969959df4
--- /dev/null
+++ b/Example/LHCbLumi/CMakeLists.txt
@@ -0,0 +1,25 @@
+################################################################################
+# Package: LHCbLumi
+################################################################################
+gaudi_subdir(LHCbLumi v1r0)
+
+gaudi_depends_on_subdirs(GaudiAlg
+                         Sim/GiGaMTCore
+                         Det/DetDesc
+                         HepMC3
+                         Sim/GiGaMTFactories)
+
+find_package(Boost)
+find_package(ROOT COMPONENTS Tree TreePlayer RIO REQUIRED)
+find_package(CLHEP)
+AddHepMC3()
+include_directories(SYSTEM ${Boost_INCLUDE_DIRS} ${ROOT_INCLUDE_DIRS} ${CLHEP_INCLUDE_DIRS} ${Geant4_INCLUDE_DIRS} ${HEPMC3_INCLUDE_DIR})
+
+add_definitions(-DG4MULTITHREADED)
+add_definitions(-DG4USE_STD11)
+
+gaudi_add_module(LHCbLumi
+                 src/*.cpp
+                 LINK_LIBRARIES DetDescLib Geant4 GiGaMTCoreTruthLib GaudiAlgLib ROOT)
+
+gaudi_env(SET LHCBLUMIOPTS \${LHCBLUMIROOT}/options)
diff --git a/Example/LHCbLumi/options/setup.py b/Example/LHCbLumi/options/setup.py
new file mode 100644
index 000000000..7990d4b8d
--- /dev/null
+++ b/Example/LHCbLumi/options/setup.py
@@ -0,0 +1,87 @@
+from Gaudi.Configuration import importOptions
+from Gaussino.Generation import GenPhase
+
+from Configurables import Gauss, CondDB, LHCbApp
+importOptions("$APPCONFIGOPTS/Gauss/Beam7000GeV-md100-nu7.6-HorExtAngle.py")
+
+CondDB().Upgrade = True
+LHCbApp().DDDBtag = "dddb-20171010"
+LHCbApp().CondDBtag = "sim-20170301-vc-md100"
+
+CondDB().Upgrade = True
+Gauss().DataType = "Upgrade"
+
+from Gauss.Geometry import LHCbGeo
+LHCbGeo().DetectorGeo = {"Detectors": ['VP', 'Magnet']}
+LHCbGeo().DetectorSim = {"Detectors": []}
+LHCbGeo().DetectorMoni = {"Detectors": []}
+
+LHCbGeo().ExtraGeoTools = ['AddLumiDetectorTool']
+LHCbGeo().SensDetMap = {'LumiSensitiveDetector/LSD':
+                        ["sector out {}".format(j + 1) for j in range(100)]
+                        }
+
+from Configurables import GiGaMTProxyDetectorConstructionFAC
+from Configurables import GiGaMT
+giga = GiGaMT()
+dettool = giga.addTool(GiGaMTProxyDetectorConstructionFAC,
+                       "GiGaMTProxyDetectorConstructionFAC")
+from Configurables import LumiSensitiveDetector
+lsd = dettool.addTool(LumiSensitiveDetector,
+                       "LSD")
+# giga.OutputLevel = 1
+
+from Configurables import ApplicationMgr, MakeLumiHitsTuple
+# ApplicationMgr().ExtSvc += ["NTupleSvc"];
+# from Gaudi.Configuration import NTupleSvc
+# NTupleSvc().Output = ["FILE1 DATAFILE='LumiHits.root' OPT='NEW'"];
+ApplicationMgr().TopAlg += [MakeLumiHitsTuple(
+    CollectionName='LSD/Hits')]
+
+from Gauss import G4Physics
+G4Physics().AddPhysConstr = ["GiGaMT_G4OpticalPhysics"]
+
+from Configurables import Generation
+Generation().EventType = 30000000
+
+GenPhase().ProductionTool = "Pythia8Production"
+GenPhase().SampleGenerationTool = "MinimumBias"
+GenPhase().DecayTool = "EvtGenDecay"
+GenPhase().CutTool = ""
+
+from Configurables import ToolSvc
+from Configurables import EvtGenDecay
+ToolSvc().addTool(EvtGenDecay)
+ToolSvc().EvtGenDecay.UserDecayFile = "$DECFILESROOT/dkfiles/minbias.dec"
+
+
+from Configurables import Gauss
+nthreads = 3
+
+# GenPhase().Production = 'P8MB'
+GenPhase().GenMonitor = True
+Gauss().EvtMax = 100
+Gauss().EnableHive = True
+
+Gauss().ThreadPoolSize = nthreads
+Gauss().EventSlots = nthreads
+Gauss().ConvertEDM = True
+
+from Configurables import GenRndInit
+GenRndInit().FirstEventNumber = 10042
+GenRndInit().TimingSkipAtStart = 10
+
+from Configurables import GiGaMT
+giga = GiGaMT()
+giga.NumberOfWorkerThreads = nthreads
+
+from Gaudi.Configuration import appendPostConfigAction
+
+def force_engine():
+    from Gaussino.Utilities import get_set_configurable
+    from Configurables import GiGaMT
+    giga = GiGaMT()
+    actioninit = get_set_configurable(giga, 'ActionInitializer')
+    actioninit.TrackingActions += ["DebugTrackAction"]
+
+# appendPostConfigAction(force_engine)
diff --git a/Example/LHCbLumi/src/AddLumiDetectorTool.cpp b/Example/LHCbLumi/src/AddLumiDetectorTool.cpp
new file mode 100644
index 000000000..030ddabc7
--- /dev/null
+++ b/Example/LHCbLumi/src/AddLumiDetectorTool.cpp
@@ -0,0 +1,518 @@
+/*
+ * AddLumiDetectorTool.cpp
+ *
+ *  Created on: Oct 2, 2018
+ *      Author: vsevolod
+ */
+
+#include "AddLumiDetectorTool.h"
+#include "Geant4/G4LogicalVolumeStore.hh"
+#include "Geant4/G4Trap.hh"
+
+#include "LumiVolumeStructures.h"
+
+DECLARE_COMPONENT(AddLumiDetectorTool)
+
+StatusCode AddLumiDetectorTool::initialize() {
+  auto sc = extends::initialize();
+  G4String symbol;
+  G4double a, z, density;
+  G4int ncomponents, natoms;
+  G4double fractionmass;
+
+  G4NistManager *man = G4NistManager::Instance();
+
+  G4Element *N =
+      new G4Element("Nitrogen", symbol = "N", z = 7., a = 14.01 * g / mole);
+  G4Element *O =
+      new G4Element("Oxygen", symbol = "O", z = 8., a = 16.00 * g / mole);
+  G4Element *Si =
+      new G4Element("Silicon", symbol = "Si", z = 14., a = 28.09 * g / mole);
+  Air = new G4Material("Air", density = 0.000290 * mg / cm3, ncomponents = 2);
+  Air->AddElement(N, fractionmass = 0.7);
+  Air->AddElement(O, fractionmass = 0.3);
+  worldMaterial = Air;
+
+  G4Material *Scint = man->FindOrBuildMaterial("G4_PLASTIC_SC_VINYLTOLUENE");
+  ScintMaterial = Scint;
+
+  INOX = man->FindOrBuildMaterial("G4_STAINLESS-STEEL");
+
+  Beryllium = man->FindOrBuildMaterial("G4_Be");
+  Copper = man->FindOrBuildMaterial("G4_Cu");
+
+  BPMaterial = Copper;
+  BPMaterial = Beryllium;
+
+  Vacuum = new G4Material("Galactic", z = 1., a = 1.01 * g / mole,
+                          density = universe_mean_density, kStateGas,
+                          2.73 * kelvin, 3.e-18 * pascal);
+
+  // Quartz Material (SiO2)
+  SiO2 = new G4Material("quartz", density = 2.200 * g / cm3, ncomponents = 2);
+  SiO2->AddElement(Si, natoms = 1);
+  SiO2->AddElement(O, natoms = 2);
+
+  //
+  // Generate and Add Material Properties Table
+  //
+  const G4int num = 36;
+  G4double WaveLength[num];
+  G4double AirAbsorption[num];
+  G4double AirRefractiveIndex[num];
+  G4double PhotonEnergy[num];
+
+  // Absorption of quartz per 1m
+  G4double QuartzAbsorption[num] = {
+      0.999572036, 0.999544661, 0.999515062, 0.999483019, 0.999448285,
+      0.999410586, 0.999369611, 0.999325013, 0.999276402, 0.999223336,
+      0.999165317, 0.999101778, 0.999032079, 0.998955488, 0.998871172,
+      0.998778177, 0.99867541,  0.998561611, 0.998435332, 0.998294892,
+      0.998138345, 0.997963425, 0.997767484, 0.997547418, 0.99729958,
+      0.99701966,  0.99670255,  0.996342167, 0.995931242, 0.995461041,
+      0.994921022, 0.994298396, 0.993577567, 0.992739402, 0.991760297,
+      0.990610945};
+
+  for (int i = 0; i < num; i++) {
+    WaveLength[i] = (300 + i * 10) * nanometer;
+    AirAbsorption[i] = 10. * cm;  // If photon hits air, kill it
+    AirRefractiveIndex[i] = 1.;   // Rough air refraction
+    PhotonEnergy[num - (i + 1)] = twopi * hbarc / WaveLength[i];
+    /* Absorption is given per length and G4 needs mean free path
+     length, calculate it here
+     mean free path length - taken as probablility equal 1/e
+     that the photon will be absorbed */
+    QuartzAbsorption[i] = (-1) / log(QuartzAbsorption[i]) * 100 * cm;
+    // EpotekAbsorption[i] = (-1)/log(EpotekAbsorption[i])*
+    // epotekBarJoint.thickness;
+  }
+
+  G4double QuartzRefractiveIndex[num] = {
+      1.456535, 1.456812, 1.4571,   1.457399, 1.457712, 1.458038,
+      1.458378, 1.458735, 1.459108, 1.4595,   1.459911, 1.460344,
+      1.460799, 1.46128,  1.461789, 1.462326, 1.462897, 1.463502,
+      1.464146, 1.464833, 1.465566, 1.46635,  1.46719,  1.468094,
+      1.469066, 1.470116, 1.471252, 1.472485, 1.473826, 1.475289,
+      1.476891, 1.478651, 1.480592, 1.482739, 1.485127, 1.487793};
+
+  // Assign absorption and refraction to materials
+
+  // Quartz
+  G4MaterialPropertiesTable *QuartzMPT = new G4MaterialPropertiesTable();
+  QuartzMPT->AddProperty("RINDEX", PhotonEnergy, QuartzRefractiveIndex, num);
+  QuartzMPT->AddProperty("ABSLENGTH", PhotonEnergy, QuartzAbsorption, num);
+
+  SiO2->SetMaterialPropertiesTable(QuartzMPT);
+
+  // Air
+  G4MaterialPropertiesTable *AirMPT = new G4MaterialPropertiesTable();
+  AirMPT->AddProperty("RINDEX", PhotonEnergy, AirRefractiveIndex, num);
+  AirMPT->AddProperty("ABSLENGTH", PhotonEnergy, AirAbsorption, num);
+
+  // Assign these properties to the world volume
+  Air->SetMaterialPropertiesTable(AirMPT);
+  // In our rough assumption
+  Vacuum->SetMaterialPropertiesTable(AirMPT);
+  return sc;
+}
+
+StatusCode AddLumiDetectorTool::process(const std::string &) const {
+  G4LogicalVolume *worldLogical =
+      G4LogicalVolumeStore::GetInstance()->GetVolume(m_worldName.value());
+
+  ///////////////////////////////////////////////////////////
+
+  // The solid to be extracted from VELO vessel upstream cap
+  // in order to avoid overlap with beampipe
+  G4VSolid *ExtSolid = new G4Tubs("ExtTube",                // name
+                                  0.,                       // inner radius
+                                  LConst::BPOuterRadius,    // outer radius
+                                  LConst::worldSizeZ / 2.,  // dZ/2
+                                  0,                        // theta start
+                                  twopi);                   // theta of sector
+
+  ////////////////////// Beampipe ////////////////////////////
+  // G4VSolid *BPSolid = new G4Tubs("BeamPipe",			// name
+  // LConst::BPInnerRadius,						// inner
+  // radius
+  // LConst::BPOuterRadius,						// outer
+  // radius (LConst::worldSizeZ/2. + LConst::BeamStart)/2.,  // dZ/2 0,
+  // // theta start
+  // twopi);										// theta of
+  // sector
+  // G4LogicalVolume *BPLogical = new G4LogicalVolume(BPSolid,
+  // BPMaterial,
+  //"BeamPipe");
+  // G4VPhysicalVolume *BPPhysical =  new G4PVPlacement(
+  // new G4RotationMatrix(),
+  // G4ThreeVector(0.,0., (- LConst::worldSizeZ/2. + LConst::BeamStart)/2.),
+  // BPLogical,
+  //"BeamPipe",
+  // worldLogical,
+  // false,
+  // 0);
+  ////////////////////////////////////////////////////////////
+
+  ////////////////////// VELO cap ////////////////////////////
+  // G4VSolid *VELOsphere = new G4Sphere("VELOsphere",
+  // LConst::sphereInnerR,
+  // LConst::sphereOuterR,
+  // 0,
+  // twopi, //LConst::sphereTheta*2.,
+  // 0,
+  // LConst::sphereTheta);
+  // G4SubtractionSolid *VELOsphereSolid = new G4SubtractionSolid("VELOsphere",
+  // VELOsphere, ExtSolid); G4LogicalVolume *VELOsphereLog = new
+  // G4LogicalVolume(VELOsphereSolid, INOX, "VELOsphere");
+  // G4RotationMatrix *Rm = new G4RotationMatrix();
+  // Rm->rotateX(pi);
+  // G4VPhysicalVolume *VELOspherePhys =  new G4PVPlacement(
+  // Rm,
+  // G4ThreeVector(0.,0., (LConst::sphereCenter)),
+  // VELOsphereLog,
+  //"VELOsphere",
+  // worldLogical,
+  // false,
+  // 0);
+  ////////////////////////////////////////////////////////////
+
+  //    G4VSolid *BPVSolid = new G4Tubs("BeamPipeVacuum",               // name
+  //            0.,                                                     // inner
+  //            radius
+  //            LConst::BPInnerRadius,                              	// outer
+  //            radius (LConst::worldSizeZ/2. + LConst::BeamStart)/2., // dZ/2
+  //            0,                                                      // theta
+  //            start twopi);                                                 //
+  //            theta of sector
+
+  //    G4LogicalVolume *BPVLogical = new G4LogicalVolume(BPVSolid,
+  //            Vacuum,
+  //            "BeamPipeVacuum");
+  //    G4VPhysicalVolume *BPVPhysical =  new G4PVPlacement(
+  //            new G4RotationMatrix(),
+  //            G4ThreeVector(0.,0.,(LConst::worldSizeZ/2. +
+  //            LConst::BeamStart)/2.), BPVLogical, "BeamPipe", worldLogical,
+  //            false,
+  //            0);
+
+  ////////////////////// OLD CONFIGURATION ////////////////////////////
+
+  ///////////////////////////////////////////////////////
+  G4VSolid *L1SolidPlane = new G4Box("L1Plane", 100 * cm, 100 * cm, 1 * mm);
+  G4SubtractionSolid *L1Solid =
+      new G4SubtractionSolid("L1Plane", L1SolidPlane, ExtSolid);
+  new G4LogicalVolume(L1Solid, Vacuum, "L1PlaneOuter");
+  //    G4VPhysicalVolume *L1PlanePhysOuter =  new G4PVPlacement(
+  //                new G4RotationMatrix(),
+  //                G4ThreeVector(0.,0.,LConst::L1pozZ),
+  //                L1PlaneLogOuter,
+  //                "L1PlaneOuter",
+  //                worldLogical,
+  //                false,
+  //                0);
+  ///////////////////////////////////////////////////////
+
+  ///////////////////////////////////////////////////////
+  G4VSolid *L1SolidIn =
+      new G4Tubs("L1Plane", 0., LConst::BPOuterRadius, 1 * mm, 0, twopi);
+  new G4LogicalVolume(L1SolidIn, Vacuum, "L1PlaneInner");
+  //        G4VPhysicalVolume *L1PlanePhysInner =  new G4PVPlacement(
+  //                    new G4RotationMatrix(),
+  //                    G4ThreeVector(0.,0.,LConst::L1pozZ),
+  //                    L1PlaneLogInner,
+  //                    "L1PlaneInner",
+  //                    worldLogical,
+  //                    false,
+  //                    0);
+  ////////////////////////////////////////////////////////
+
+  ////////////////////////////////////////////////////////
+  G4VSolid *L2SolidPlane = new G4Box("L2Plane", 100 * cm, 100 * cm, 1 * mm);
+  G4SubtractionSolid *L2Solid =
+      new G4SubtractionSolid("L2Plane", L2SolidPlane, ExtSolid);
+  new G4LogicalVolume(L2Solid, Vacuum, "L2PlaneOuter");
+  //            G4VPhysicalVolume *L2PlanePhysOuter =  new G4PVPlacement(
+  //                        new G4RotationMatrix(),
+  //                        G4ThreeVector(0.,0.,LConst::L2pozZ),
+  //                        L2PlaneLogOuter,
+  //                        "L2PlaneOuter",
+  //                        worldLogical,
+  //                        false,
+  //                        0);
+  ////////////////////////////////////////////////////////
+
+  ///////////////////////////////////////////////////////
+  G4VSolid *L2SolidIn =
+      new G4Tubs("L2Plane", 0., LConst::BPOuterRadius, 1 * mm, 0, twopi);
+  new G4LogicalVolume(L2SolidIn, Vacuum, "L2PlaneInner");
+  //        G4VPhysicalVolume *L2PlanePhysInner =  new G4PVPlacement(
+  //                    new G4RotationMatrix(),
+  //                    G4ThreeVector(0.,0.,LConst::L2pozZ),
+  //                    L2PlaneLogInner,
+  //                    "L2PlaneInner",
+  //                    worldLogical,
+  //                    false,
+  //                    0);
+  ////////////////////////////////////////////////////////
+
+  /////////////////// END OF OLD CONFIGURATION ///////////////////////
+
+  G4ThreeVector *Ta = new G4ThreeVector(0., 0., 0.);
+  G4RotationMatrix *Ra = new G4RotationMatrix();
+
+  ////////////// Trapeze sectors and absorbers ///////////////
+  G4Trd *secIn = new G4Trd("sectorIn", sectorIn.shortSide / 2.,
+                           sectorIn.longSide / 2., sectorIn.thickness / 2.,
+                           sectorIn.thickness / 2., sectorIn.height / 2.);
+
+  G4Trd *secOut = new G4Trd("sectorOut", sectorOut.shortSide / 2.,
+                            sectorOut.longSide / 2., sectorOut.thickness / 2.,
+                            sectorOut.thickness / 2., sectorOut.height / 2.);
+
+  //G4Trd *absIn = new G4Trd("absIn", absorberIn.shortSide / 2.,
+                           //absorberIn.longSide / 2., absorberIn.thickness / 2.,
+                           //absorberIn.thickness / 2., absorberIn.height / 2.);
+
+  G4Trd *absOut =
+      new G4Trd("absOut", absorberOut.shortSide / 2. * 1.3,
+                absorberOut.longSide / 2. * 1.3, absorberOut.thickness / 2.,
+                absorberOut.thickness / 2., absorberOut.height / 2.);
+  ////////////////////////////////////////////////////////////
+
+  ///////////// Photon detector at the surface ///////////////
+  G4VSolid *detectorOut = new G4Box("detector", sectorOut.longSide / 2.,
+                                    sectorOut.thickness / 2., 1 * mm);
+  ////////////////////////////////////////////////////////////
+
+  // Loop for sectors in order to place them with detectors and absorbers
+  // IN THE OLD CONFIGURATION (placing is commented)
+  G4LogicalVolume *LSectorIn[LConst::nSecIn];
+  for (int j = 0; j < LConst::nSecIn; ++j) {
+    /////////// sector /////////////
+    G4String name = "sector in ";
+    name += std::to_string(j + 1);
+    LSectorIn[j] = new G4LogicalVolume(secIn,
+                                       /*Vacuum*/ SiO2, name);
+    // FIXME: ADD SENSDET ! LSectorIn[j]->SetSensitiveDetector(LSD);
+    Ta = new G4ThreeVector(0., 0., 0.);
+    Ra = new G4RotationMatrix();
+
+    Ra->rotateX(-90. * deg);
+    Ra->rotateY(-360. / LConst::nSecIn * j * deg - 90. * deg);
+    Ta->setX(LConst::centerRadIn * TMath::Cos(360. / LConst::nSecIn * j * deg));
+    Ta->setZ(LConst::L1pozZ);
+    Ta->setY(LConst::centerRadIn * TMath::Sin(360. / LConst::nSecIn * j * deg));
+
+    //        G4VPhysicalVolume *PSecIn =  new G4PVPlacement(
+    //                    Ra,
+    //                    *Ta,
+    //                    LSectorIn[j],
+    //                    name,
+    //                    worldLogical,
+    //                    false,
+    //                    0);
+  }
+
+  G4RotationMatrix RTilt = G4RotationMatrix();
+  RTilt.rotateX(LConst::angleOut);
+
+  G4Transform3D Tr;
+
+  // Assembly
+  G4AssemblyVolume *assembly = new G4AssemblyVolume();
+  G4String name;
+  G4LogicalVolume *LSectorOut[LConst::nSecOut];
+
+  G4LogicalVolume *LAbsOut[LConst::nSecOut];
+  G4LogicalVolume *LDetectorOut[LConst::nSecOut];
+
+  // Loop for sectors in order to place them with detectors and absorbers
+  for (int j = 0; j < LConst::nSecOut; ++j) {
+    /////////// sector /////////////
+    name = "sector out ";
+    name += std::to_string(j + 1);
+    LSectorOut[j] = new G4LogicalVolume(secOut,
+                                        /*Vacuum*/ SiO2, name);
+    // FIXME: ADD SENSDET ! LSectorOut[j]->SetSensitiveDetector(LSD);
+    Ta = new G4ThreeVector(0., 0., 0.);
+    Ra = new G4RotationMatrix();
+
+    //        Ra->rotateX(-90.*deg);
+    Ra->rotateY(-360. / LConst::nSecOut * j * deg + 90 * deg);
+    *Ra = *Ra * RTilt;
+
+    //        Ta = G4ThreeVector(0.,0.,0.);
+    //        Ra = G4RotationMatrix();
+
+    //        Ra.rotateY(- 360./fTOFConst::nSec*i *deg + 90.*deg);
+
+    //        Ra = Ra * RTilt;
+
+    //        Ta.setX(fTOFConst::centerRad * TMath::Cos(360./fTOFConst::nSec*i
+    //        *deg)); Ta.setY(dist); Ta.setZ(fTOFConst::centerRad *
+    //        TMath::Sin(360./fTOFConst::nSec*i *deg));
+
+    //        Tr = G4Transform3D(Ra,Ta);
+    //        secAssembly->AddPlacedVolume(fullBarLog,Tr);
+
+    Ta->setX(LConst::centerRadOut *
+             TMath::Cos(360. / LConst::nSecOut * j * deg));
+    Ta->setY(LConst::L1pozZ);
+    Ta->setZ(LConst::centerRadOut *
+             TMath::Sin(360. / LConst::nSecOut * j * deg));
+
+    Tr = G4Transform3D(*Ra, *Ta);
+    //        if (j == 0)
+    assembly->AddPlacedVolume(LSectorOut[j], Tr);
+
+    //        G4VPhysicalVolume *PSecOut =  new G4PVPlacement(
+    //                    Ra,
+    //                    *Ta,
+    //                    LSectorOut[j],
+    //                    name,
+    //                    worldLogical,
+    //                    false,
+    //                    0);
+
+    ////////// absorber /////////////
+
+    name = "absorber out ";
+    name += std::to_string(j + 1);
+
+    Ta = new G4ThreeVector(0., 0., 0.);
+    Ra = new G4RotationMatrix();
+
+    Ra->rotateY(-360. / LConst::nSecOut * (j + 0.5) * deg + 90. * deg);
+
+    *Ra = *Ra * RTilt;
+    Ta->setX(LConst::centerRadOut *
+             TMath::Cos(360. / LConst::nSecOut * (j + 0.5) * deg));
+    Ta->setY(LConst::L1pozZ);
+    Ta->setZ(LConst::centerRadOut *
+             TMath::Sin(360. / LConst::nSecOut * (j + 0.5) * deg));
+
+    *Ta -= G4ThreeVector(
+        LConst::centerRadOut * TMath::Cos(360. / LConst::nSecOut * j * deg),
+        LConst::L1pozZ,
+        LConst::centerRadOut * TMath::Sin(360. / LConst::nSecOut * j * deg));
+
+    *Ta = (*Ra * (RTilt * (Ra->inverse() * (*Ta))));
+
+    *Ta += G4ThreeVector(
+        LConst::centerRadOut * TMath::Cos(360. / LConst::nSecOut * j * deg),
+        LConst::L1pozZ,
+        LConst::centerRadOut * TMath::Sin(360. / LConst::nSecOut * j * deg));
+
+    Tr = G4Transform3D(*Ra, *Ta);
+
+    LAbsOut[j] = new G4LogicalVolume(absOut,
+                                     /*Vacuum*/ SiO2, name);
+
+    //        if (j == 0 || j == LConst::nSecOut - 1)
+    assembly->AddPlacedVolume(LAbsOut[j], Tr);
+
+    /////////// outer detector ///////
+
+    name = "detector out ";
+    name += std::to_string(j + 1);
+
+    Ta = new G4ThreeVector(0., 0., 0.);
+    Ra = new G4RotationMatrix();
+
+    Ra->rotateY(-360. / LConst::nSecOut * j * deg + 90. * deg);
+
+    Ta->setX(
+        (LConst::detectorRadOut * TMath::Cos(TMath::Pi() / LConst::nSecOut) +
+         1 * mm) *
+        TMath::Cos(360. / LConst::nSecOut * j * deg));
+    Ta->setY(LConst::L1pozZ);
+    Ta->setZ(
+        (LConst::detectorRadOut * TMath::Cos(TMath::Pi() / LConst::nSecOut) +
+         1 * mm) *
+        TMath::Sin(360. / LConst::nSecOut * j * deg));
+
+    *Ta -= G4ThreeVector(
+        LConst::centerRadOut * TMath::Cos(360. / LConst::nSecOut * j * deg),
+        LConst::L1pozZ,
+        LConst::centerRadOut * TMath::Sin(360. / LConst::nSecOut * j * deg));
+
+    *Ta = (*Ra * (RTilt * (Ra->inverse() * (*Ta))));
+
+    *Ta += G4ThreeVector(
+        LConst::centerRadOut * TMath::Cos(360. / LConst::nSecOut * j * deg),
+        LConst::L1pozZ,
+        LConst::centerRadOut * TMath::Sin(360. / LConst::nSecOut * j * deg));
+
+    *Ra = *Ra * RTilt;
+    Tr = G4Transform3D(*Ra, *Ta);
+
+    LDetectorOut[j] = new G4LogicalVolume(detectorOut,
+                                          /*Vacuum*/ SiO2, name);
+    //        if (j == 0)
+    assembly->AddPlacedVolume(LDetectorOut[j], Tr);
+  }
+
+  Ra = new G4RotationMatrix();
+  Ta = new G4ThreeVector();
+
+  // Managing the final position of the assembly
+
+  Ra->rotateY(270.0 * deg);
+  Ra->rotateX(90.0 * deg);
+
+  Ta->setX(0.);
+  Ta->setY(0.);
+  Ta->setZ(0.);
+
+  //    Ta += G4ThreeVector(fTOFConst::centerRad *
+  //    TMath::Cos(360./fTOFConst::nSec*i *deg),
+  //                        0,
+  //                        fTOFConst::centerRad *
+  //                        TMath::Sin(360./fTOFConst::nSec*i *deg));
+
+  Ta->rotateZ(270 * deg);
+
+  Tr = G4Transform3D(*Ra, *Ta);
+
+  assembly->MakeImprint(worldLogical, Tr, 0, true);
+
+  const G4int num1 = 2;
+  G4double Ephoton[num1] = {1.5 * eV, 5.8 * eV};
+
+  G4OpticalSurface *OpVolumeKillSurface =
+      new G4OpticalSurface("VolumeKillSurface");
+  OpVolumeKillSurface->SetType(dielectric_metal);
+  OpVolumeKillSurface->SetFinish(polished);
+  OpVolumeKillSurface->SetModel(glisur);
+
+  G4double ReflectivityKill[num1] = {0., 0.};
+  G4double EfficiencyKill[num1] = {1., 1.};
+  G4MaterialPropertiesTable *VolumeKill = new G4MaterialPropertiesTable();
+  VolumeKill->AddProperty("REFLECTIVITY", Ephoton, ReflectivityKill, num1);
+  VolumeKill->AddProperty("EFFICIENCY", Ephoton, EfficiencyKill, num1);
+  OpVolumeKillSurface->SetMaterialPropertiesTable(VolumeKill);
+
+  G4OpticalSurface *quartzSurface = new G4OpticalSurface("quartzBorder");
+  quartzSurface->SetType(dielectric_dielectric);
+
+  for (int j = 0; j < LConst::nSecOut; ++j) {
+    new G4LogicalSkinSurface("AbsTrdSurface", LAbsOut[j], OpVolumeKillSurface);
+    new G4LogicalSkinSurface("DetectorAbsSurface", LDetectorOut[j],
+                             OpVolumeKillSurface);
+    new G4LogicalSkinSurface("sectorSurface", LSectorOut[j], quartzSurface);
+  }
+
+  G4Color green = G4Color(0., 1., 0.);
+
+  G4VisAttributes *sectorVisAtt = new G4VisAttributes;
+  sectorVisAtt->SetColor(green);
+  sectorVisAtt->SetVisibility(true);
+  for (int j = 0; j < LConst::nSecOut; ++j) {
+    LSectorOut[j]->SetVisAttributes(sectorVisAtt);
+  }
+  for (int j = 0; j < LConst::nSecIn; ++j) {
+    LSectorIn[j]->SetVisAttributes(sectorVisAtt);
+  }
+
+  return StatusCode::SUCCESS;
+}
diff --git a/Example/LHCbLumi/src/AddLumiDetectorTool.h b/Example/LHCbLumi/src/AddLumiDetectorTool.h
new file mode 100644
index 000000000..1c80bf9da
--- /dev/null
+++ b/Example/LHCbLumi/src/AddLumiDetectorTool.h
@@ -0,0 +1,60 @@
+#pragma once
+
+#include "GaudiAlg/GaudiTool.h"
+#include "Geant4/G4AssemblyVolume.hh"
+#include "Geant4/G4Box.hh"
+#include "Geant4/G4Color.hh"
+#include "Geant4/G4ExtrudedSolid.hh"
+#include "Geant4/G4LogicalSkinSurface.hh"
+#include "Geant4/G4LogicalVolume.hh"
+#include "Geant4/G4Material.hh"
+#include "Geant4/G4MultiUnion.hh"
+#include "Geant4/G4NistManager.hh"
+#include "Geant4/G4OpticalSurface.hh"
+#include "Geant4/G4PVPlacement.hh"
+#include "Geant4/G4RotationMatrix.hh"
+#include "Geant4/G4SDManager.hh"
+#include "Geant4/G4Sphere.hh"
+#include "Geant4/G4SubtractionSolid.hh"
+#include "Geant4/G4ThreeVector.hh"
+#include "Geant4/G4Transform3D.hh"
+#include "Geant4/G4Trap.hh"
+#include "Geant4/G4Trd.hh"
+#include "Geant4/G4Tubs.hh"
+#include "Geant4/G4TwoVector.hh"
+#include "Geant4/G4UnionSolid.hh"
+#include "Geant4/G4VSolid.hh"
+#include "Geant4/G4VisAttributes.hh"
+#include "Geant4/globals.hh"
+#include "SimInterfaces/IGaussinoTool.h"
+
+#include "LConst.hh"
+
+#include "LumiVolumeStructures.h"
+
+class AddLumiDetectorTool : public extends<GaudiTool, IGaussinoTool> {
+  public:
+  using extends::extends;
+
+  public:
+  StatusCode initialize() override;
+  StatusCode process(const std::string &parameter = "") const override;
+
+  private:
+  Gaudi::Property<std::string> m_worldName{this, "WorldName", "World"};
+  G4Material *worldMaterial;
+  G4Material *ScintMaterial;
+  G4Material *Vacuum;
+  G4Material *BPMaterial;
+  G4Material *INOX;
+  G4Material *SiO2;
+  G4Material *Copper;
+  G4Material *Beryllium;
+
+  G4Material *Air;
+
+  TrapezeSectorStructIn sectorIn;
+  TrapezeSectorStructOut sectorOut;
+  TrapezeAbsStructIn absorberIn;
+  TrapezeAbsStructOut absorberOut;
+};
diff --git a/Example/LHCbLumi/src/HitDataStructure.hh b/Example/LHCbLumi/src/HitDataStructure.hh
new file mode 100644
index 000000000..02df93759
--- /dev/null
+++ b/Example/LHCbLumi/src/HitDataStructure.hh
@@ -0,0 +1,23 @@
+#ifndef HitDataStructure_h
+#define HitDataStructure_h 1
+
+#include "Geant4/globals.hh"
+
+struct HitData
+{
+  G4int TrackID;
+  G4int ParentID;
+  G4int PdgID;
+  G4int StationID;
+  G4double Energy;
+  G4double Time;
+  G4double X;
+  G4double Y;
+  G4double Z;
+  G4double Px;
+  G4double Py;
+  G4double Pz;
+  G4double Momentum;
+};
+
+#endif
diff --git a/Example/LHCbLumi/src/LConst.hh b/Example/LHCbLumi/src/LConst.hh
new file mode 100644
index 000000000..599cbfe54
--- /dev/null
+++ b/Example/LHCbLumi/src/LConst.hh
@@ -0,0 +1,135 @@
+/*
+ * LConst.hh
+ *
+ *  Created on: Oct 2, 2018
+ *      Author: vsevolod
+ */
+
+#pragma once
+
+#include "TMath.h"
+#include "Geant4/G4SystemOfUnits.hh"
+#include "Geant4/G4PhysicalConstants.hh"
+#include "Geant4/globals.hh"
+
+namespace LConst{
+
+// World size
+const G4double worldSizeX = 1*m;
+const G4double worldSizeY = 1*m;
+const G4double worldSizeZ = 4.6*m;
+
+
+// Outer and inner radius of the beampipe
+//const G4double BPOuterRadius = 31*mm;
+//const G4double BPInnerRadius = 30*mm;
+const G4double BPOuterRadius = 41*mm;
+const G4double BPInnerRadius = 40*mm;
+
+
+// Detector pozition along Z-axis
+
+const G4double L1pozZ = - 2172.*mm;           // The closest option
+//const G4double L1pozZ = - 2172.*mm + 400*mm;  // An intermediate option
+//const G4double L1pozZ = - 2172.*mm + 800*mm;    // The farthest option
+
+// The same for the second detector
+//const G4double L2pozZ = - 2172.*mm + 800*mm;
+
+
+// VELO Sphere
+const G4double capHeight = 280.*mm;
+const G4double capBaseR = 1000./2. *mm;
+const G4double sphereStart = - 500.*mm;
+const G4double sphereThickness = 5.*mm;
+
+const G4double sphereR = (capHeight*capHeight + capBaseR*capBaseR)/2. / capHeight;
+const G4double sphereTheta = TMath::ATan(capBaseR/2. / (sphereR - capHeight));
+const G4double sphereOuterR = sphereR;
+const G4double sphereInnerR = sphereR - sphereThickness;
+const G4double sphereCenter = sphereStart - capHeight + sphereR;
+
+const G4double BeamStart = sphereStart - capHeight + 32.*mm;
+
+const G4double VeloLeft = -175*mm;
+const G4double VeloRight = 350*mm;
+
+
+
+///////////////////////// Detector inside beampipe ///////////////////////////////////////////////////
+// The old configuration
+
+const G4double sectorThicknessIn = 1*cm;
+
+const G4double innerRadIn = 10*mm;
+const G4double outerRadIn = BPInnerRadius;
+const G4int nSecIn = 12;
+
+const G4double centerRadIn = (innerRadIn * TMath::Cos(TMath::Pi() / nSecIn) +
+                              outerRadIn * TMath::Cos(TMath::Pi() / nSecIn)) / 2.;
+const G4double absInnerSideIn = 0.1*mm;
+const G4double absOuterSideIn = absInnerSideIn * outerRadIn / innerRadIn;
+const G4double VertHeightIn = outerRadIn - innerRadIn;
+const G4double innerSideIn = 2. * innerRadIn * TMath::Sin(TMath::Pi() / nSecIn) - absInnerSideIn;
+const G4double outerSideIn = 2. * outerRadIn * TMath::Sin(TMath::Pi() / nSecIn) - absOuterSideIn;
+/////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+/////////////////////////// Detoctor outside beampipe ///////////////////////////////////////////////
+const G4double sectorThicknessOut = 1*cm;
+
+const G4double innerRadOut = BPOuterRadius + 1.*cm;
+
+const G4double lengthOut = 60*mm;
+//const G4double outerRadOut = 10*cm;
+
+const G4int nSecOut = 100;
+
+/*
+ * Saturated track angles in quartz:    46.64 - 47.77
+ * Green light saturated track angle:   46.95
+ *
+ * Lower angle is the angle of the detector inner radius
+*/
+
+const G4double saturatedAngle = 46.95*deg;
+const G4double lowerAngle = atan( - (innerRadOut + lengthOut / sqrt(2) * 0.1) / L1pozZ);
+
+const G4double angleOut = saturatedAngle + lowerAngle;
+
+const G4double centerRadOut = innerRadOut + lengthOut * cos(angleOut) / 2.;
+const G4double outerRadOut = innerRadOut + lengthOut;
+
+const G4double detectorRadOut = centerRadOut + lengthOut / 2.;
+
+//const G4double centerRadOut = (innerRadOut * TMath::Cos(TMath::Pi() / nSecOut) +
+//                               outerRadOut * TMath::Cos(TMath::Pi() / nSecOut)) / 2.;
+
+const G4double absInnerSideOut = 0.01*mm;
+const G4double absOuterSideOut = absInnerSideOut * outerRadOut / innerRadOut * 0.8;
+const G4double VertHeightOut = outerRadOut - innerRadOut;
+
+const G4double innerSideOut = 2. * (centerRadOut - VertHeightOut * TMath::Cos(angleOut)/2.) * TMath::Sin(TMath::Pi() / nSecOut) - absInnerSideOut*40;
+const G4double outerSideOut = 2. * (centerRadOut + VertHeightOut * TMath::Cos(angleOut)/2.) * TMath::Sin(TMath::Pi() / nSecOut) - absOuterSideOut*20;
+
+//const G4double outerSideOut = innerSideOut;
+//////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+
+///////////////////////////////////////// Vertex /////////////////////////////////////////////////////////
+const G4double VertexX = 0.;
+const G4double VertexY = 0.;
+const G4double VertexZ = 0.;
+
+
+const G4double VertexSigmaX = 0.;
+const G4double VertexSigmaY = 0.;
+const G4double VertexSigmaZ = 1.*cm;
+//////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+
+
+}
+
diff --git a/Example/LHCbLumi/src/LumiHit.cpp b/Example/LHCbLumi/src/LumiHit.cpp
new file mode 100644
index 000000000..1a79fb9df
--- /dev/null
+++ b/Example/LHCbLumi/src/LumiHit.cpp
@@ -0,0 +1,40 @@
+/*
+ * LumiHit.cpp
+ *
+ *  Created on: Oct 3, 2018
+ *      Author: vsevolod
+ */
+
+#include "LumiHit.h"
+
+#include "Geant4/G4Circle.hh"
+#include "Geant4/G4Color.hh"
+#include "Geant4/G4Square.hh"
+#include "Geant4/G4UnitsTable.hh"
+#include "Geant4/G4VVisManager.hh"
+#include "Geant4/G4VisAttributes.hh"
+
+G4ThreadLocal G4Allocator<LumiHit>* aLumiHitAllocator = nullptr;
+
+LumiHit::LumiHit()  {
+  for (G4int i = 0; i < LConst::nSecOut; ++i) {
+    _nPhot[i] = 0;
+  }
+}
+
+LumiHit::LumiHit(const LumiHit& right) {
+  for (G4int i = 0; i < LConst::nSecOut; ++i) {
+    _nPhot[i] = right._nPhot[i];
+  }
+}
+
+const LumiHit& LumiHit::operator=(const LumiHit& right) {
+  for (G4int i = 0; i < LConst::nSecOut; ++i) {
+    _nPhot[i] = right._nPhot[i];
+  }
+  return *this;
+}
+
+G4int LumiHit::operator==(const LumiHit& right) const {
+  return (this == &right) ? 1 : 0;
+}
diff --git a/Example/LHCbLumi/src/LumiHit.h b/Example/LHCbLumi/src/LumiHit.h
new file mode 100644
index 000000000..88745225f
--- /dev/null
+++ b/Example/LHCbLumi/src/LumiHit.h
@@ -0,0 +1,50 @@
+/*
+ * LumiHit.h
+ *
+ *  Created on: Oct 3, 2018
+ *      Author: vsevolod
+ */
+
+#pragma once
+
+#include "Geant4/G4VHit.hh"
+// G4
+#include "Geant4/G4Allocator.hh"
+#include "Geant4/G4THitsCollection.hh"
+#include "Geant4/G4ThreeVector.hh"
+#include "LConst.hh"
+
+// my
+#include "HitDataStructure.hh"
+
+class LumiHit : public G4VHit {
+  public:
+    LumiHit();
+
+  LumiHit(const LumiHit&);
+  const LumiHit& operator=(const LumiHit&);
+  G4int operator==(const LumiHit&) const;
+
+  inline void* operator new(size_t);
+  inline void operator delete(void*);
+  inline void InsertPhoton(G4int secID){ _nPhot[secID - 1] ++; }
+  inline G4int GetNPhotons(G4int secID) const { return _nPhot[secID - 1]; }
+
+  private:
+    G4int _nPhot[LConst::nSecOut];
+};
+
+typedef G4THitsCollection<LumiHit> LumiHitsCollection;
+
+extern G4ThreadLocal G4Allocator<LumiHit>* aLumiHitAllocator;
+
+inline void* LumiHit::operator new(size_t) {
+  if (!aLumiHitAllocator) {
+    aLumiHitAllocator = new G4Allocator<LumiHit>;
+  }
+  return (void*)aLumiHitAllocator->MallocSingle();
+}
+
+inline void LumiHit::operator delete(void* aHit) {
+  aLumiHitAllocator->FreeSingle((LumiHit*)aHit);
+}
diff --git a/Example/LHCbLumi/src/LumiSensitiveDetector.cpp b/Example/LHCbLumi/src/LumiSensitiveDetector.cpp
new file mode 100644
index 000000000..c660b5ac5
--- /dev/null
+++ b/Example/LHCbLumi/src/LumiSensitiveDetector.cpp
@@ -0,0 +1,112 @@
+/*
+ * LumiSensitiveDetector.cpp
+ *
+ *  Created on: Oct 3, 2018
+ *      Author: vsevolod
+ */
+
+#include "LumiSensitiveDetector.h"
+
+#include "Geant4/G4HCofThisEvent.hh"
+#include "Geant4/G4PhysicalConstants.hh"
+#include "Geant4/G4RunManager.hh"
+#include "Geant4/G4SDManager.hh"
+#include "Geant4/G4SystemOfUnits.hh"
+
+#include <iterator>
+
+LumiSensitiveDetector::LumiSensitiveDetector(G4String name)
+    :  // @suppress("Class members should be properly initialized")
+      G4VSensitiveDetector(name) {
+  //  G4RunManager* runManager = G4RunManager::GetRunManager();
+  collectionName.insert("Hits");
+}
+
+LumiSensitiveDetector::~LumiSensitiveDetector() {}
+
+void LumiSensitiveDetector::Initialize(G4HCofThisEvent* HCE) {
+  _Collection =
+      new LumiHitsCollection(SensitiveDetectorName, collectionName[0]);
+
+  std::string hit_location = SensitiveDetectorName + "/" + collectionName[0];
+
+  debug("Registering location at " + hit_location);
+  int HCID = G4SDManager::GetSDMpointer()->GetCollectionID(hit_location);
+
+  HCE->AddHitsCollection(HCID, _Collection);
+
+  _theHit = new LumiHit();
+  _Collection->insert(_theHit);
+}
+
+G4bool LumiSensitiveDetector::ProcessHitsL(G4Step* aStep,
+                                           G4TouchableHistory* hist) {
+  return ProcessHits(aStep, hist);
+}
+
+G4bool LumiSensitiveDetector::ProcessHits(G4Step* aStep, G4TouchableHistory*) {
+  G4Track* aTrack = aStep->GetTrack();
+  G4ThreeVector globalPosition = aStep->GetPostStepPoint()->GetPosition();
+  //	newHit->myData;
+
+  G4StepPoint* aPostPoint = aStep->GetPostStepPoint();
+  G4StepPoint* aPrevPoint = aStep->GetPreStepPoint();
+  if (!aPostPoint->GetPhysicalVolume()) return false;
+
+  G4LogicalVolume* PostVolume =
+      aPostPoint->GetPhysicalVolume()->GetLogicalVolume();
+  G4LogicalVolume* PrevVolume =
+      aPrevPoint->GetPhysicalVolume()->GetLogicalVolume();
+
+  G4String PreName = PrevVolume->GetName();
+  G4String PostName = PostVolume->GetName();
+
+  const G4DynamicParticle* aParticle = aTrack->GetDynamicParticle();
+  if (printDebug()) {
+    std::stringstream sstr;
+    sstr << "SD hit by " << aParticle->GetDefinition()->GetParticleName();
+    debug(sstr.str());
+  }
+
+  // Handling only optical photons
+  if (aParticle->GetDefinition()->GetParticleName() != "opticalphoton")
+    return false;
+
+  // Vectors of sector's and detector's names splitted into words
+  std::vector<G4String> sectorWords;
+  std::vector<G4String> detectorWords;
+
+  auto splitName = [](auto& str, auto& cont) {
+    std::istringstream iss(str);
+    std::copy(std::istream_iterator<std::string>(iss),
+              std::istream_iterator<std::string>(), std::back_inserter(cont));
+  };
+
+  // Splitting a string into words
+  splitName(PreName, sectorWords);
+  splitName(PostName, detectorWords);
+  if (printDebug()) {
+    std::stringstream sstr;
+    sstr << "sectorWords " << sectorWords[0];
+    debug(sstr.str());
+    sstr.clear();
+    sstr << "detectorWords " << detectorWords[0] << " -> " << detectorWords[0];
+    debug(sstr.str());
+  }
+
+  // Sector ID discrimination for the hit
+  if (sectorWords[0] == "sector" && detectorWords[0] == "detector") {
+    G4int stationID = atoi(detectorWords[2]);
+    _theHit->InsertPhoton(stationID);
+  } else
+    return false;
+
+  return true;
+}
+
+#include "GiGaMTFactories/GiGaMTG4SensDetFactory.h"
+
+// As long we do not have any additional
+typedef GiGaMTG4SensDetFactory<LumiSensitiveDetector> LumiSensitiveDetectorFAC;
+
+DECLARE_COMPONENT_WITH_ID(LumiSensitiveDetectorFAC, "LumiSensitiveDetector")
diff --git a/Example/LHCbLumi/src/LumiSensitiveDetector.h b/Example/LHCbLumi/src/LumiSensitiveDetector.h
new file mode 100644
index 000000000..0e8f17b44
--- /dev/null
+++ b/Example/LHCbLumi/src/LumiSensitiveDetector.h
@@ -0,0 +1,25 @@
+#pragma once
+#include "Geant4/G4VSensitiveDetector.hh"
+#include "GiGaMTCoreMessage/IGiGaMessage.h"
+#include "HitDataStructure.hh"
+#include "LumiHit.h"
+
+class G4HCofThisEvent;
+class G4Step;
+class G4TouchableHistory;
+
+class LumiSensitiveDetector : public G4VSensitiveDetector, public virtual GiGaMessage {
+  public:
+  LumiSensitiveDetector(G4String name);
+  virtual ~LumiSensitiveDetector();
+
+  void Initialize(G4HCofThisEvent*) override;
+
+  G4bool ProcessHits(G4Step*, G4TouchableHistory*) override;
+
+  G4bool ProcessHitsL(G4Step*, G4TouchableHistory*);
+
+  private:
+  LumiHitsCollection* _Collection{nullptr};
+  LumiHit* _theHit{nullptr};
+};
diff --git a/Example/LHCbLumi/src/LumiSteppingAction.cpp b/Example/LHCbLumi/src/LumiSteppingAction.cpp
new file mode 100644
index 000000000..528495270
--- /dev/null
+++ b/Example/LHCbLumi/src/LumiSteppingAction.cpp
@@ -0,0 +1,193 @@
+/*
+ * LumiSteppingAction.cpp
+ *
+ *  Created on: Oct 2, 2018
+ *      Author: vsevolod
+ */
+
+#include "LumiSteppingAction.h"
+#include "LumiSensitiveDetector.h"
+#include "Geant4/G4Track.hh"
+#include "Geant4/G4ParticleTypes.hh"
+#include "Geant4/G4ParticleDefinition.hh"
+#include "Geant4/G4OpBoundaryProcess.hh"
+#include "Geant4/G4SDManager.hh"
+#include "Geant4/G4ProcessManager.hh"
+#include "Geant4/G4SystemOfUnits.hh"
+#include "Geant4/G4PhysicalConstants.hh"
+#include "Geant4/G4EventManager.hh"
+#include "Geant4/G4Event.hh"
+
+
+void LumiSteppingAction::UserSteppingAction(const G4Step* aStep) {
+    //	G4cout << "_____________________________ step" << G4endl;
+    G4Track* aTrack = aStep->GetTrack();
+    // G4Track *aTrack = aStep->GetTrack();
+    G4int trackID = aTrack->GetTrackID();
+    //G4cout<<"trackID = "<<trackID<<G4endl;
+
+
+    // Pre step point and physical volume
+    G4StepPoint* aPrePoint = aStep->GetPreStepPoint();
+    //G4VPhysicalVolume* aPrePV = aPrePoint->GetPhysicalVolume();
+
+    // Post step point and physical volume
+    G4StepPoint* aPostPoint = aStep->GetPostStepPoint();
+    G4VPhysicalVolume* aPostPV = aPostPoint->GetPhysicalVolume();
+
+
+    // Further operations are only for optical photons
+    G4ParticleDefinition* particleType = aTrack->GetDefinition();
+    if (particleType != G4OpticalPhoton::OpticalPhotonDefinition())
+        return;
+
+    // Check if particle trying to escape the World
+    if (!aPostPV) return;
+
+    // TO BE REVIEWED, GONNA BE A MISTAKE HERE///////////////////////////////
+//    if(!aPostPV->GetLogicalVolume()->GetSensitiveDetector()) return;
+    ////////////////////////////////////////////////////////////////////////
+
+    // Killing downstream particles
+    if (aPrePoint->GetPosition().z() > 50.*cm) {
+        aTrack->SetTrackStatus(fStopAndKill);
+        return;
+    }
+
+    // Killing charged particles bellow 20 MeV
+    if (aPrePoint->GetCharge() != 0. && aPrePoint->GetMomentum().mag() < 20.*MeV ) {
+        aTrack->SetTrackStatus(fStopAndKill);
+        return;
+    }
+
+    static thread_local double _probOfReflection = 1.;
+    static thread_local int _particleID = 0;
+    static thread_local int _eventID = 0;
+    int currentid = G4EventManager::GetEventManager()->GetConstCurrentEvent()->GetEventID();
+
+    // Getting probability of internal reflection
+    if (_particleID != trackID || currentid != _eventID) {
+        _probOfReflection = 1.;
+        _particleID = trackID;
+        _eventID = currentid;
+        InternalReflectionProbability(aTrack->GetTotalEnergy()/eV,
+                                      _probOfReflection);
+    }
+
+    // Declaring boundary
+    G4OpBoundaryProcessStatus boundaryStatus = Undefined;
+    static G4OpBoundaryProcess* boundary = NULL;
+
+    // Find boundary process
+    if (!boundary) {
+        G4ProcessManager* pm =
+                aStep->GetTrack()->GetDefinition()->GetProcessManager();
+        G4int nprocesses = pm->GetProcessListLength();
+        G4ProcessVector* pv = pm->GetProcessList();
+        for (G4int i = 0; i < nprocesses; i++) {
+            if ((*pv)[i]->GetProcessName() == "OpBoundary") {
+                boundary = (G4OpBoundaryProcess*)(*pv)[i];
+                break;
+            }
+        }
+    }
+
+    // Only boundary processes are handling further
+    if (!boundary) return;
+
+    boundaryStatus = boundary->GetStatus();
+
+    if (aPostPoint->GetStepStatus() == fGeomBoundary) {
+        G4double flat = G4UniformRand();
+        switch(boundaryStatus) {
+        case Absorption:
+            break;
+        case FresnelReflection:
+            // Reflections of surfaces of different media
+            break;
+        case TotalInternalReflection:
+            // Actually check if particle is reflected
+            if (flat > _probOfReflection) {
+                G4Track* aNonConstTrack = const_cast<G4Track*>(aTrack);
+                aNonConstTrack->SetTrackStatus(fStopAndKill);
+//                G4cout << "KILL THAT BASTARD \n";
+            }
+//            G4cout << "TOTAL INTERNAL REFLECTION"<< G4endl;
+            break;
+        case SpikeReflection:
+            break;
+        default:
+            break;
+
+        }
+
+    }
+
+
+    return;
+}
+
+// This metod is stolen from Leonid's code
+void LumiSteppingAction::InternalReflectionProbability(G4double energy,
+                                                     G4double& probability)
+{
+    probability = 1.0;
+
+    /* this function simulate the internal reflection probability per one
+     bounce - each time photon bounced this function is called
+     and the reflection is tested if photon reflects or disappear -
+     this function estimates loss of photons during imperfections
+     of bar */
+
+    static G4double opticalPhotonEnergy[36] = {
+        1.90744901082931,1.93725290162352,1.96800294768103,1.99974493070815,
+        2.03252763449025,2.06640309506508,2.10142687633737,2.13765837420526,
+        2.17516115270009,2.21400331614116,2.25425792188918,2.29600343896121,
+        2.33932425856425,2.38431126353664,2.43106246478245,2.4796837140781,
+        2.53028950416133,2.58300386883136,2.63796139795543,2.6953083848675,
+        2.75520412675345,2.81782240236148,2.88335315590477,2.95200442152155,
+        3.02400452936354,3.09960464259763,3.17908168471551,3.26274172905013,
+        3.35092393794338,3.44400515844181,3.54240530582586,3.64659369717368,
+        3.75709653648197,3.87450580324703,3.99948986141629,4.13280619013017};
+
+    static G4double internalReflectivity[36] = {
+        0.999895281,0.999891334,0.999885743,0.999878696,0.999870426,
+        0.9998612,0.999851309,0.999841055,0.999830735,0.999820635,0.999811012,
+        0.999802084,0.999794018,0.999786917,0.999780807,0.999775625,
+        0.999771209,0.999767282,0.999763441,0.999759146,0.999753706,
+        0.999746266,0.999735798,0.999721084,0.999700708,0.99967304,
+        0.999636227,0.999588178,0.999526552,0.999448747,0.999351887,
+        0.999232808,0.99908805,0.998913839,0.998706078,0.998460335};
+
+    G4int i;
+    for(i = 0; i < 36;i++) {
+        if(energy < opticalPhotonEnergy[i]) break;
+    }
+
+
+    probability = ((energy-opticalPhotonEnergy[i-1])/
+            (opticalPhotonEnergy[i]-opticalPhotonEnergy[i-1]))*
+            (internalReflectivity[i]-internalReflectivity[i-1]) +
+            internalReflectivity[i-1];
+
+    /* because the ratio between peak1 and peak2 did not correspond,
+     the reflection probability was change to get the same
+     ration 2.1:1 => the original probability is multiplied by .9992 */
+    probability = probability*.9992;
+
+
+    // probability = 0;
+}
+
+#include "GaudiAlg/GaudiTool.h"
+#include "GiGaMTFactories/GiGaFactoryBase.h"
+
+class LumiSteppingActionFAC : public extends<GaudiTool, GiGaFactoryBase<G4UserSteppingAction>>
+{
+  using extends::extends;
+  virtual G4UserSteppingAction* construct() const override {
+    return new LumiSteppingAction{};
+  }
+};
+
+DECLARE_COMPONENT_WITH_ID( LumiSteppingActionFAC, "LumiSteppingAction" )
diff --git a/Example/LHCbLumi/src/LumiSteppingAction.h b/Example/LHCbLumi/src/LumiSteppingAction.h
new file mode 100644
index 000000000..1399f95ad
--- /dev/null
+++ b/Example/LHCbLumi/src/LumiSteppingAction.h
@@ -0,0 +1,23 @@
+/*
+ * LumiSteppingAction.h
+ *
+ *  Created on: Oct 2, 2018
+ *      Author: vsevolod
+ */
+
+#pragma once
+
+#include "Geant4/G4UserSteppingAction.hh"
+#include "Geant4/globals.hh"
+
+class LumiSteppingAction: public G4UserSteppingAction {
+public:
+  LumiSteppingAction() = default;
+  virtual ~LumiSteppingAction() = default;
+	void UserSteppingAction(const G4Step*) override;
+
+private:
+
+    void InternalReflectionProbability(G4double energy,
+                                       G4double& probability);
+};
diff --git a/Example/LHCbLumi/src/LumiVolumeStructures.h b/Example/LHCbLumi/src/LumiVolumeStructures.h
new file mode 100644
index 000000000..d338b38d1
--- /dev/null
+++ b/Example/LHCbLumi/src/LumiVolumeStructures.h
@@ -0,0 +1,115 @@
+#pragma once
+
+//G4
+#include "Geant4/G4Material.hh"
+#include "Geant4/G4VSolid.hh"
+#include "Geant4/G4LogicalVolume.hh"
+#include "Geant4/G4VPhysicalVolume.hh"
+#include "Geant4/G4Point3D.hh"
+#include "Geant4/G4TwoVector.hh"
+#include "Geant4/globals.hh"
+
+#include "TMath.h"
+
+//My
+#include "LConst.hh"
+
+// Base structure
+struct VolumeStruct {
+    G4Material*        material;
+    G4VSolid*          solid;
+    G4LogicalVolume*   logical;
+    G4VPhysicalVolume* physical;
+    VolumeStruct() :
+        material(0),
+        solid(0),
+        logical(0),
+        physical(0)
+    {;}
+    ~VolumeStruct() {;}
+};
+
+// Sector structure (inside beampipe)
+struct TrapezeSectorStructIn: VolumeStruct {
+    const G4double thickness;
+    const G4double height;
+    const G4double shortSide;
+    const G4double longSide;
+    const G4double angle;
+    const G4double sides;
+    const G4double middleLine;
+    TrapezeSectorStructIn():
+        thickness(LConst::sectorThicknessIn),
+        height(LConst::outerRadIn * TMath::Cos(TMath::Pi() / LConst::nSecIn) -
+               LConst::innerRadIn * TMath::Cos(TMath::Pi() / LConst::nSecIn)),
+        shortSide(LConst::innerSideIn),
+        longSide(LConst::outerSideIn),
+        angle(atan((longSide-shortSide)/2./height)),
+        sides(sqrt(height*height + (longSide-shortSide)*(longSide-shortSide)/4.)),
+        middleLine((longSide+shortSide)/2.)
+    {;}
+};
+
+// Sector structure (outside beampipe)
+struct TrapezeSectorStructOut: VolumeStruct {
+    const G4double thickness;
+    const G4double height;
+    const G4double shortSide;
+    const G4double longSide;
+    const G4double angle;
+    const G4double sides;
+    const G4double middleLine;
+    TrapezeSectorStructOut():
+        thickness(LConst::sectorThicknessOut),
+        height(LConst::lengthOut),
+        shortSide(LConst::innerSideOut),
+        longSide(LConst::outerSideOut),
+        angle(atan((longSide-shortSide)/2./height)),
+        sides(sqrt(height*height + (longSide-shortSide)*(longSide-shortSide)/4.)),
+        middleLine((longSide+shortSide)/2.)
+    {
+    }
+};
+
+// Optical insulation between sectors (inside beampipe)
+struct TrapezeAbsStructIn: VolumeStruct {
+    const G4double shortSide;
+    const G4double longSide;
+    const G4double thickness;
+    const G4double height;
+    const G4double angle;
+    const G4double sides;
+    const G4double middleLine;
+    TrapezeAbsStructIn():
+        shortSide(LConst::absInnerSideIn),
+        longSide(LConst::absOuterSideIn),
+        thickness(LConst::sectorThicknessIn),
+        height(LConst::outerRadIn -
+               LConst::innerRadIn),
+        angle(atan((longSide-shortSide)/2./height)),
+        sides(sqrt(height*height + (longSide-shortSide)*(longSide-shortSide)/4.)),
+        middleLine((longSide+shortSide)/2.)
+    {;}
+};
+
+// Optical insulation between sectors (outside beampipe)
+struct TrapezeAbsStructOut: VolumeStruct {
+    const G4double shortSide;
+    const G4double longSide;
+    const G4double thickness;
+    const G4double height;
+    const G4double angle;
+    const G4double sides;
+    const G4double middleLine;
+    TrapezeAbsStructOut():
+        shortSide(LConst::absInnerSideOut),
+        longSide(LConst::absOuterSideOut),
+        thickness(LConst::sectorThicknessOut * 1.2),
+        height(LConst::lengthOut),
+        angle(atan((longSide-shortSide)/2./height)),
+        sides(sqrt(height*height + (longSide-shortSide)*(longSide-shortSide)/4.)),
+        middleLine((longSide+shortSide)/2.)
+    {;}
+};
+
+
diff --git a/Example/LHCbLumi/src/MakeLumiHitsTuple.cpp b/Example/LHCbLumi/src/MakeLumiHitsTuple.cpp
new file mode 100755
index 000000000..15e47e2f1
--- /dev/null
+++ b/Example/LHCbLumi/src/MakeLumiHitsTuple.cpp
@@ -0,0 +1,89 @@
+// from Geant4
+#include "Geant4/G4HCofThisEvent.hh"
+#include "Geant4/G4SDManager.hh"
+
+// local
+#include "MakeLumiHitsTuple.h"
+#include "LumiHit.h"
+
+//-----------------------------------------------------------------------------
+// Implementation file for class : MakeLumiHitsTuple
+//
+// 2018-04-05 : Dominik Muller
+//-----------------------------------------------------------------------------
+
+// Declaration of the Algorithm Factory
+DECLARE_COMPONENT(MakeLumiHitsTuple)
+
+//=============================================================================
+// Initialization
+//=============================================================================
+StatusCode MakeLumiHitsTuple::initialize() {
+    StatusCode sc = Consumer::initialize();  // must be executed first
+    if (sc.isFailure()) return sc;  // error printed already by GaudiAlgorithm
+
+    debug() << "==> Initialize" << endmsg;
+
+    if ("" == m_colName) {
+        fatal() << "Property CollectionName need to be set! " << endmsg;
+        return StatusCode::FAILURE;
+    }
+    m_file = new TFile("LumiHits.root", "RECREATE");
+    m_tree = new TTree("Tree", "Tree");
+    _nSec = LConst::nSecOut;
+    m_tree->Branch("nSec", &_nSec, "nSec/I");
+    m_tree->Branch("nPhot", _nPhot, "nPhot[nSec]/I");
+    m_tree->SetDirectory(m_file);
+    m_tree->Write();
+
+    return StatusCode::SUCCESS;
+}
+
+StatusCode MakeLumiHitsTuple::finalize() {
+    m_file->cd();
+    m_tree->SetDirectory(m_file);
+    m_tree->Write();
+    m_file->Close();
+
+    return Consumer::finalize();  // must be executed first
+}
+
+//=============================================================================
+// Main execution
+//=============================================================================
+void MakeLumiHitsTuple::operator()(
+    const G4EventProxies& eventproxies,
+    const LinkedParticleMCParticleLinks& ) const {
+    debug() << "==> Execute" << endmsg;
+    std::lock_guard locked{m_lazy_lock};
+    m_tree->SetDirectory(m_file);
+
+    for(int idx=0;idx < LConst::nSecOut; idx++){
+      // FIXME: + 1 here necessary?
+      _nPhot[idx] = 0;
+    }
+    for (auto& ep : eventproxies) {
+        auto hitCollection =
+            ep.GetHitCollection<LumiHitsCollection>(m_colName);
+        if (!hitCollection) {
+            warning() << "The hit collection='" + m_colName + "' is not found!"
+                      << endmsg;
+            continue;
+        }
+        // reserve elements on output container
+        int numOfHits = hitCollection->entries();
+        if (numOfHits != 1) {
+            error() << "Number of LumiHits for G4Event is not exactly one!"
+                      << endmsg;
+            continue;
+        }
+        auto hit = (*hitCollection)[0];
+        for(int idx=0;idx < LConst::nSecOut; idx++){
+          // FIXME: + 1 here necessary?
+          _nPhot[idx] += hit->GetNPhotons(idx + 1);
+        }
+    }
+    m_file->cd();
+    m_tree->SetDirectory(m_file);
+    m_tree->Fill();
+}
diff --git a/Example/LHCbLumi/src/MakeLumiHitsTuple.h b/Example/LHCbLumi/src/MakeLumiHitsTuple.h
new file mode 100755
index 000000000..657417270
--- /dev/null
+++ b/Example/LHCbLumi/src/MakeLumiHitsTuple.h
@@ -0,0 +1,65 @@
+#pragma once
+#include <vector>
+
+// Include files
+// from Gaudi
+#include "GaudiAlg/GaudiAlgorithm.h"
+#include "GaudiAlg/Consumer.h"
+#include "GiGaMTCoreRun/G4EventProxy.h"
+#include "GiGaMTCoreTruth/MCTruthConverter.h"
+#include "MCTruthToEDM/LinkedParticleMCParticleLink.h"
+
+#include "Defaults/Locations.h"
+
+#include "LConst.hh"
+#include "TTree.h"
+#include "TFile.h"
+
+// Forward declarations
+class IGiGaSvc;
+class IGiGaKineCnvSvc;
+class DetectorElement;
+class TrackerHit;
+
+/** @class MakeLumiHitsTuple MakeLumiHitsTuple.h
+ *
+ *
+ *  @author Gloria CORTI
+ *  @date   2005-10-02
+ */
+class MakeLumiHitsTuple
+    : public Gaudi::Functional::Consumer<void(
+          const G4EventProxies&, const LinkedParticleMCParticleLinks&)> {
+  public:
+  /// Standard constructor
+  MakeLumiHitsTuple(const std::string& name, ISvcLocator* pSvcLocator)
+      : Consumer(
+            name, pSvcLocator,
+            {{KeyValue{"Input", Gaussino::G4EventsLocation::Default},
+              KeyValue{
+                  "LinkedParticleMCParticleLinks",
+                  Gaussino::LinkedParticleMCParticleLinksLocation::Default}}}) {}
+  virtual ~MakeLumiHitsTuple() = default;
+
+  virtual void operator()(const G4EventProxies&, const LinkedParticleMCParticleLinks&) const override;
+
+  virtual StatusCode initialize() override;  ///< Algorithm initialization
+  virtual StatusCode finalize() override;  ///< Algorithm initialization
+
+  private:
+
+  Gaudi::Property<std::string> m_colName{
+      this, "CollectionName", "",
+      "Name of Geant4 collection where to retrieve hits"};
+  Gaudi::Property<std::vector<std::string>> m_detName{
+      this,
+      "Detectors",
+      {},
+      "List of detector paths in TDS for which to retrieve the hits (most of "
+      "the time one"};
+  mutable std::mutex m_lazy_lock; 
+  G4int _nSec;
+  mutable G4int _nPhot[LConst::nSecOut];
+  mutable TTree* m_tree;
+  mutable TFile* m_file;
+};
diff --git a/Example/LHCbLumi/src/Physics.cpp b/Example/LHCbLumi/src/Physics.cpp
new file mode 100644
index 000000000..42fe9cc4b
--- /dev/null
+++ b/Example/LHCbLumi/src/Physics.cpp
@@ -0,0 +1,6 @@
+#include "GiGaMTFactories/GiGaMTG4PhysicsConstrFAC.h"
+
+#include "Geant4/G4OpticalPhysics.hh"
+
+typedef GiGaMTG4PhysicsConstrFAC<G4OpticalPhysics> GiGaMT_G4OpticalPhysics;
+DECLARE_COMPONENT_WITH_ID( GiGaMT_G4OpticalPhysics, "GiGaMT_G4OpticalPhysics" )
-- 
GitLab


From bdc318e146a3677f4d05fe810dd12d748619cb78 Mon Sep 17 00:00:00 2001
From: Dominik Muller <dominik.muller@cern.ch>
Date: Tue, 17 Sep 2019 14:08:52 +0200
Subject: [PATCH 32/90] Adaptation for renamed detector construction

---
 Example/LHCbLumi/options/setup.py                | 6 +++---
 Sim/Gauss/python/Gauss/Geometry/Configuration.py | 8 ++++----
 2 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/Example/LHCbLumi/options/setup.py b/Example/LHCbLumi/options/setup.py
index 7990d4b8d..8e31afacc 100644
--- a/Example/LHCbLumi/options/setup.py
+++ b/Example/LHCbLumi/options/setup.py
@@ -21,11 +21,11 @@ LHCbGeo().SensDetMap = {'LumiSensitiveDetector/LSD':
                         ["sector out {}".format(j + 1) for j in range(100)]
                         }
 
-from Configurables import GiGaMTProxyDetectorConstructionFAC
+from Configurables import GiGaMTDetectorConstructionFAC
 from Configurables import GiGaMT
 giga = GiGaMT()
-dettool = giga.addTool(GiGaMTProxyDetectorConstructionFAC,
-                       "GiGaMTProxyDetectorConstructionFAC")
+dettool = giga.addTool(GiGaMTDetectorConstructionFAC,
+                       "GiGaMTDetectorConstructionFAC")
 from Configurables import LumiSensitiveDetector
 lsd = dettool.addTool(LumiSensitiveDetector,
                        "LSD")
diff --git a/Sim/Gauss/python/Gauss/Geometry/Configuration.py b/Sim/Gauss/python/Gauss/Geometry/Configuration.py
index 1e1399672..a4d46fae4 100644
--- a/Sim/Gauss/python/Gauss/Geometry/Configuration.py
+++ b/Sim/Gauss/python/Gauss/Geometry/Configuration.py
@@ -158,12 +158,12 @@ class LHCbGeo(LHCbConfigurableUser):
             getsubdetector(det).SetupMonitor()
 
     def MakeItTalkToGaussino(self):
-        from Configurables import GiGaMTProxyDetectorConstructionFAC
+        from Configurables import GiGaMTDetectorConstructionFAC
         from Configurables import GiGaMT
         giga = GiGaMT()
-        giga.DetectorConstruction = "GiGaMTProxyDetectorConstructionFAC"
-        dettool = giga.addTool(GiGaMTProxyDetectorConstructionFAC,
-                               "GiGaMTProxyDetectorConstructionFAC")
+        giga.DetectorConstruction = "GiGaMTDetectorConstructionFAC"
+        dettool = giga.addTool(GiGaMTDetectorConstructionFAC,
+                               "GiGaMTDetectorConstructionFAC")
         dettool.GiGaMTGeoSvc = "GaussGeo"
         dettool.SensDetVolumeMap = self.getProp('SensDetMap')
 
-- 
GitLab


From eb69beac8bcf8699f9bb9e6ca613e469bcd652d9 Mon Sep 17 00:00:00 2001
From: Dominik Muller <dominik.muller@cern.ch>
Date: Tue, 17 Sep 2019 16:51:09 +0200
Subject: [PATCH 33/90] By default dump GDML in Lumi study setup

---
 Example/LHCbLumi/options/setup.py | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/Example/LHCbLumi/options/setup.py b/Example/LHCbLumi/options/setup.py
index 8e31afacc..162c26624 100644
--- a/Example/LHCbLumi/options/setup.py
+++ b/Example/LHCbLumi/options/setup.py
@@ -26,6 +26,8 @@ from Configurables import GiGaMT
 giga = GiGaMT()
 dettool = giga.addTool(GiGaMTDetectorConstructionFAC,
                        "GiGaMTDetectorConstructionFAC")
+dettool.Output = "Dump.gdml"
+
 from Configurables import LumiSensitiveDetector
 lsd = dettool.addTool(LumiSensitiveDetector,
                        "LSD")
-- 
GitLab


From 37de6e2ab1cc570ff066863ed449ce6c4b02db63 Mon Sep 17 00:00:00 2001
From: Dominik Muller <dominik.muller@cern.ch>
Date: Mon, 9 Dec 2019 17:19:28 +0100
Subject: [PATCH 34/90] Generator versions for LCG96b

---
 generators_versions_LCG96b.txt | 14 ++++++++++++++
 1 file changed, 14 insertions(+)
 create mode 100644 generators_versions_LCG96b.txt

diff --git a/generators_versions_LCG96b.txt b/generators_versions_LCG96b.txt
new file mode 100644
index 000000000..9b6459b47
--- /dev/null
+++ b/generators_versions_LCG96b.txt
@@ -0,0 +1,14 @@
+alpgen         2.1.4
+herwig++       2.7.1
+hijing         1.383bs.2
+lhapdf         6.2.3
+photos++       3.56
+powheg-box-v2  r3043.lhcb
+pythia6        427.2
+pythia8        240
+rivet          2.7.2b
+tauola++       1.1.6b.lhcb
+thepeg         2.1.5
+crmc           1.5.6
+yoda           1.7.7
+starlight      r300
-- 
GitLab


From 8b16db97ce9b81c3c8efbe1bcaf7441d6328c872 Mon Sep 17 00:00:00 2001
From: Dominik Muller <dominik.muller@cern.ch>
Date: Thu, 19 Dec 2019 16:16:09 +0100
Subject: [PATCH 35/90] WIP SimCutTool

---
 Sim/GaussSimCutTools/CMakeLists.txt           |  16 ++
 Sim/GaussSimCutTools/src/ConversionFilter.cpp | 162 ++++++++++++++++++
 Sim/GaussSimCutTools/src/ConversionFilter.h   |  61 +++++++
 3 files changed, 239 insertions(+)
 create mode 100644 Sim/GaussSimCutTools/CMakeLists.txt
 create mode 100644 Sim/GaussSimCutTools/src/ConversionFilter.cpp
 create mode 100644 Sim/GaussSimCutTools/src/ConversionFilter.h

diff --git a/Sim/GaussSimCutTools/CMakeLists.txt b/Sim/GaussSimCutTools/CMakeLists.txt
new file mode 100644
index 000000000..148ac79de
--- /dev/null
+++ b/Sim/GaussSimCutTools/CMakeLists.txt
@@ -0,0 +1,16 @@
+################################################################################
+# Package: GaussSimCutTools 
+# Package to contain simulation based cut tools
+#################################################################################
+gaudi_subdir(GaussSimCutTools v1r0)
+
+gaudi_depends_on_subdirs(Sim/GiGaMT
+                         Gen/GenInterfaces)
+
+add_definitions(-DG4MULTITHREADED)
+add_definitions(-DG4USE_STD11)
+find_package(ROOT COMPONENTS MathCore GenVector)
+
+gaudi_add_module(GaussSimCutTools
+        src/*.cpp
+        LINK_LIBRARIES GiGaMTLib ROOT)
diff --git a/Sim/GaussSimCutTools/src/ConversionFilter.cpp b/Sim/GaussSimCutTools/src/ConversionFilter.cpp
new file mode 100644
index 000000000..ded70a0db
--- /dev/null
+++ b/Sim/GaussSimCutTools/src/ConversionFilter.cpp
@@ -0,0 +1,162 @@
+// Include files 
+
+// from Event/Event
+#include "Event/MCParticle.h"
+#include "Event/MCVertex.h"
+
+#include "Kernel/IParticlePropertySvc.h"
+#include "Kernel/ParticleProperty.h"
+
+// local
+#include "ConversionFilter.h"
+#include "Kernel/IParticlePropertySvc.h"
+
+#include "Defaults/HepMCAttributes.h"
+#include "HepMCUser/VertexAttribute.h"
+
+//-----------------------------------------------------------------------------
+// Implementation file for class : ConversionFilter
+//
+// 2017-10-26 : Michel De Cian
+//-----------------------------------------------------------------------------
+
+// Declaration of the Algorithm Factory
+DECLARE_COMPONENT( ConversionCutTool )
+
+//=============================================================================
+// Initialisation. Check parameters
+//=============================================================================
+StatusCode ConversionCutTool::initialize() {
+
+  StatusCode sc = extends::initialize(); // must be executed first
+  if ( sc.isFailure() ) return sc;  // error printed already by GaudiAlgorithm
+  
+  if( m_mother == "" ){
+    m_motherID = -1;
+    m_maxSearchDepth = 1;
+    return StatusCode::SUCCESS;
+  }
+
+  m_ppSvc.retrieve();
+  if( !m_ppSvc ) {
+    error() << "Could not retrieve ParticlePropertySvc" << endmsg;
+    m_motherID = -1;
+    m_maxSearchDepth = 1;
+    return StatusCode::SUCCESS;
+  }
+  
+  const LHCb::ParticleProperty* prop = m_ppSvc->find( m_mother );
+  if( !prop ) {
+    error() << "Could not retrieve ParticleProperty" << endmsg;
+    m_motherID = -1;
+    m_maxSearchDepth = 1;
+    return StatusCode::SUCCESS;
+  }
+
+  // -- Get the ID of the mother (particle and antiparticle)
+  m_motherID = prop->pdgID().abspid();
+  
+  info() << "Filtering on gamma conversion with " << m_mother << " in the decay chain" << endmsg; 
+
+  return StatusCode::SUCCESS;
+}
+
+//=============================================================================
+// Main execution
+//=============================================================================
+bool ConversionCutTool::studyFullEvent( const HepMC3::GenEventPtrs & theEvents ,
+                       const LHCb::GenCollisions & ) const {
+
+  if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) debug() << "Calling tool" << endmsg;
+
+  // First loop over events and find the signal event
+  HepMC3::GenVertexPtr signal_vertex{nullptr};
+  for(auto & evt : theEvents){
+    auto bla= evt->attribute<HepMC3::VertexAttribute>(Gaussino::HepMC::Attributes::SignalProcessVertex)->value();
+  }
+
+  LHCb::MCParticles* mcParts =
+    get<LHCb::MCParticles>( LHCb::MCParticleLocation::Default );
+  
+  const std::string filterString = "event with gamma conversion from "+m_mother;
+
+  bool filter = false;
+  int nConv = 0;
+  // -- Loop over all MCParticles
+  // -- First check that they are gammas
+  // -- do pair production at their endvertex and have the right z-position.
+  for( auto mcPart : *mcParts){
+    if( mcPart->particleID().pid() != 22 ) continue;
+    bool goodPhoton = false;
+    for( const auto endVtx : mcPart->endVertices()){
+      if( !endVtx ) continue;
+      if( endVtx->type() == LHCb::MCVertex::PairProduction && std::abs(endVtx->position().z()) < m_maxZ ){
+        goodPhoton = true;
+        break;
+      }
+    }
+    if( !goodPhoton ) continue;
+    nConv++;
+
+    unsigned int searchDepth = 0;
+    const LHCb::MCParticle* momPart = mcPart->mother();
+    
+    // -- Search up the decay tree to see if this gamma is coming from the mother we care for
+    // -- If we don't care about the mother, we just check if it fullfills the p,pt and theta requirements
+    while( momPart && searchDepth < m_maxSearchDepth){
+
+      // -- If we only want to search for a given depth, and not for a maximum
+      // -- loop until we have reach that depth.
+      if( m_matchSearchDepth && searchDepth < m_maxSearchDepth - 1 ){
+        searchDepth++;
+        momPart = momPart->mother();
+        continue;
+      }
+      
+
+      if( (std::abs(momPart->particleID().pid()) == m_motherID) || (m_motherID == -1) ){
+        if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) debug() << "Found gamma conversion from mother: " << m_motherID << endmsg;
+        // -- we found the right mother
+        // -- let's see if the daughters (=electrons) have enough momentum, pt and are within the acceptance.
+        for( const LHCb::MCVertex* endVtx : mcPart->endVertices()){
+          if( !endVtx ) continue;
+          if( endVtx->products().size() != 2 ) continue; // want pair production
+          
+          // -- We ask that all of the daughters have enough p and pt, and are within the LHCb acceptance. In case there is more than 1 end vertex
+          // -- we take the "or" of them.
+          filter |= std::all_of( std::begin(endVtx->products()), std::end(endVtx->products()), [&](const LHCb::MCParticle* dau){
+              return (dau->p() > m_minP) && (dau->pt() > m_minPT) && (dau->momentum().theta() > m_minTheta) && (dau->momentum().theta() < m_maxTheta);
+            });
+          
+          // --
+          if( UNLIKELY( msgLevel(MSG::DEBUG) ) ){
+            for( const LHCb::MCParticle* dau : endVtx->products()){
+              debug() << "particle: " << dau->particleID().pid() << " p: " << dau->p() << " pt: " 
+                      << dau->pt() << " theta: " << dau->momentum().theta() << endmsg;
+            }
+            if( filter ){
+              debug() << "accepted" << endmsg;
+            }else{
+              debug() << "rejected" << endmsg;
+            }
+            
+          }
+          // --
+        }
+        // -- We have found the right mother, no need to loop deeper
+        break;
+      }
+      searchDepth++;
+      momPart = momPart->mother();
+    }
+  }
+
+  if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) debug() << "Found " <<  nConv << " gamma conversions in total" << endmsg;
+
+  if( filter ) counter(filterString)++;
+  
+  setFilterPassed( filter );
+  return StatusCode::SUCCESS;
+  
+}
+
diff --git a/Sim/GaussSimCutTools/src/ConversionFilter.h b/Sim/GaussSimCutTools/src/ConversionFilter.h
new file mode 100644
index 000000000..054247a6e
--- /dev/null
+++ b/Sim/GaussSimCutTools/src/ConversionFilter.h
@@ -0,0 +1,61 @@
+#pragma once
+
+// Include files
+// from STL
+#include <string>
+
+// from Gaudi
+#include "GaudiAlg/GaudiAlgorithm.h"
+#include "GenInterfaces/IFullGenEventCutTool.h"
+#include "GaudiAlg/GaudiTool.h"
+
+#include "GiGaMT/IGiGaMTSvc.h"
+
+class IHepMC3ToMCTruthConverter;
+namespace LHCb
+{
+  class IParticlePropertySvc;
+}
+/** @class ConversionFilter ConversionFilter.h
+ *  Filter on gamma conversions. Applied as a cut tool in the generation, only the signal is simulated first and the presence of gamma conversion is checked. If not present in the simulated output, the event is rejected.
+ * 
+ *  Parameters:
+ *  - Mother: Mother up the decay tree the gamma conversion has to originate from. Use DecayDescriptor symbols, like B+, D*(2007)0, etc. An empty string accepts all mothers.
+ *  - MaxSearchDepth: Maximum "distance" in decay tree between gamma and mother.
+ *  - MatchSearchDepth: Does the search depth need to match, or is it only a maximum?
+ *  - MaxZ: Maximum z value the gamma conversion has to occur.
+ *  - MinP: Minimum momentum of the products of the gamma conversion.
+ *  - MinPT: Minimum transverse momentum of the products of the gamma conversion.
+ *  - MinTheta: Minimum value of angle theta for conversion products
+ *  - MaxTheta: Maximum value of angle theta for conversion products
+ *
+ *  @author Michel De Cian, adapted to SimCutTool by Dominik Muller
+ *  @date   2017-10-26
+ */
+
+class ConversionCutTool : public extends<GaudiTool, IFullGenEventCutTool>{
+
+ public: 
+  /// Standard constructor
+  using extends::extends;
+  bool studyFullEvent( const HepMC3::GenEventPtrs & theEvents ,
+                       const LHCb::GenCollisions & theCollisions ) const override;
+  StatusCode initialize() override;
+
+  
+
+ private:
+  Gaudi::Property<std::string> m_mother{this, "Mother", ""};
+  Gaudi::Property<unsigned int> m_maxSearchDepth{this, "MaxSearchDepth", 20};
+  Gaudi::Property<bool> m_matchSearchDepth{this, "MatchSearchDepth", false};
+  Gaudi::Property<double> m_maxZ{this, "MaxZ", 500.0};
+  Gaudi::Property<double> m_minP{this, "MinP", 1500.0};
+  Gaudi::Property<double> m_minPT{this, "MinPT", 50.0};
+  Gaudi::Property<double> m_minTheta{this, "MinTheta", 0.010};
+  Gaudi::Property<double> m_maxTheta{this, "MaxTheta", 0.400};
+
+  int           m_motherID = -1;
+
+  ServiceHandle<IGiGaMTSvc> m_gigaSvc{this, "GiGaMTSvc", "GiGaMT"};
+  ServiceHandle<LHCb::IParticlePropertySvc> m_ppSvc{this, "PropertyService", "LHCb::ParticlePropertySvc"};
+};
-- 
GitLab


From f365eb2d2bb0cd6c37e462454a5624c969eb8820 Mon Sep 17 00:00:00 2001
From: Dominik Muller <dominik.muller@cern.ch>
Date: Mon, 13 Jan 2020 13:30:27 +0100
Subject: [PATCH 36/90] Compiling prototype for gamma conversion cut tool

---
 Example/LHCbLumi/src/MakeLumiHitsTuple.cpp    |  2 +-
 Sim/GaussCalo/src/GetCaloHitsAlg.cpp          |  6 +-
 Sim/GaussSimCutTools/CMakeLists.txt           | 10 ++-
 Sim/GaussSimCutTools/src/ConversionFilter.cpp | 81 +++++++++++++------
 Sim/GaussTracker/src/GetTrackerHitsAlg.cpp    |  6 +-
 5 files changed, 73 insertions(+), 32 deletions(-)

diff --git a/Example/LHCbLumi/src/MakeLumiHitsTuple.cpp b/Example/LHCbLumi/src/MakeLumiHitsTuple.cpp
index 15e47e2f1..d67058b05 100755
--- a/Example/LHCbLumi/src/MakeLumiHitsTuple.cpp
+++ b/Example/LHCbLumi/src/MakeLumiHitsTuple.cpp
@@ -64,7 +64,7 @@ void MakeLumiHitsTuple::operator()(
     }
     for (auto& ep : eventproxies) {
         auto hitCollection =
-            ep.GetHitCollection<LumiHitsCollection>(m_colName);
+            ep->GetHitCollection<LumiHitsCollection>(m_colName);
         if (!hitCollection) {
             warning() << "The hit collection='" + m_colName + "' is not found!"
                       << endmsg;
diff --git a/Sim/GaussCalo/src/GetCaloHitsAlg.cpp b/Sim/GaussCalo/src/GetCaloHitsAlg.cpp
index b0960d8fc..3965674ed 100755
--- a/Sim/GaussCalo/src/GetCaloHitsAlg.cpp
+++ b/Sim/GaussCalo/src/GetCaloHitsAlg.cpp
@@ -34,7 +34,7 @@ LHCb::MCCaloHits GetCaloHitsAlg::operator()(
     size_t total_numHits{0};
 
     for (auto& ep : eventproxies) {
-        auto hitCollection = ep.GetHitCollection<CaloHitsCollection>(m_colName);
+        auto hitCollection = ep->GetHitCollection<CaloHitsCollection>(m_colName);
         if (hitCollection) {
             total_numHits += hitCollection->entries();
         }
@@ -44,7 +44,7 @@ LHCb::MCCaloHits GetCaloHitsAlg::operator()(
     }
 
     for (auto& ep : eventproxies) {
-        auto hitCollection = ep.GetHitCollection<CaloHitsCollection>(m_colName);
+        auto hitCollection = ep->GetHitCollection<CaloHitsCollection>(m_colName);
         if (!hitCollection) {
             warning() << "The hit collection='" + m_colName + "' is not found!"
                       << endmsg;
@@ -80,7 +80,7 @@ LHCb::MCCaloHits GetCaloHitsAlg::operator()(
                     mchit->setActiveE(entry->second);
                     //   - Pointer to the LHCb::MCParticle giving the hit
                     int trackID = subhit->GetTrackID();
-                    if (auto lp = ep.truth()->GetParticleFromTrackID(trackID);
+                    if (auto lp = ep->truth()->GetParticleFromTrackID(trackID);
                         lp) {
                         if (auto it = mcplinks.find(lp);
                             it != std::end(mcplinks)) {
diff --git a/Sim/GaussSimCutTools/CMakeLists.txt b/Sim/GaussSimCutTools/CMakeLists.txt
index 148ac79de..008cebf47 100644
--- a/Sim/GaussSimCutTools/CMakeLists.txt
+++ b/Sim/GaussSimCutTools/CMakeLists.txt
@@ -5,12 +5,20 @@
 gaudi_subdir(GaussSimCutTools v1r0)
 
 gaudi_depends_on_subdirs(Sim/GiGaMT
+                         EDMdev/MCTruthToEDM
                          Gen/GenInterfaces)
 
 add_definitions(-DG4MULTITHREADED)
 add_definitions(-DG4USE_STD11)
+
+include_directories(SYSTEM ${Boost_INCLUDE_DIRS} ${ROOT_INCLUDE_DIRS} ${Geant4_INCLUDE_DIRS})
+
+FindG4libs(digits_hits event geometry global graphics_reps materials persistency
+           particles processes run tracking track intercoms physicslists)
+AddHepMC3()
+
 find_package(ROOT COMPONENTS MathCore GenVector)
 
 gaudi_add_module(GaussSimCutTools
         src/*.cpp
-        LINK_LIBRARIES GiGaMTLib ROOT)
+        LINK_LIBRARIES GiGaMTLib ROOT MCTruthToEDMLib)
diff --git a/Sim/GaussSimCutTools/src/ConversionFilter.cpp b/Sim/GaussSimCutTools/src/ConversionFilter.cpp
index ded70a0db..f398a644e 100644
--- a/Sim/GaussSimCutTools/src/ConversionFilter.cpp
+++ b/Sim/GaussSimCutTools/src/ConversionFilter.cpp
@@ -10,9 +10,13 @@
 // local
 #include "ConversionFilter.h"
 #include "Kernel/IParticlePropertySvc.h"
+#include "NewRnd/RndGlobal.h"
+#include "GiGaMTCoreRun/SimResults.h"
+#include "GiGaMTCoreRun/SimResultsProxyAttribute.h"
 
 #include "Defaults/HepMCAttributes.h"
 #include "HepMCUser/VertexAttribute.h"
+#include "MCTruthToEDM/VertexType.h"
 
 //-----------------------------------------------------------------------------
 // Implementation file for class : ConversionFilter
@@ -72,12 +76,27 @@ bool ConversionCutTool::studyFullEvent( const HepMC3::GenEventPtrs & theEvents ,
   // First loop over events and find the signal event
   HepMC3::GenVertexPtr signal_vertex{nullptr};
   for(auto & evt : theEvents){
-    auto bla= evt->attribute<HepMC3::VertexAttribute>(Gaussino::HepMC::Attributes::SignalProcessVertex)->value();
+
+    auto sig_attr = evt->attribute<HepMC3::VertexAttribute>(Gaussino::HepMC::Attributes::SignalProcessVertex);
+    if(sig_attr->value().get()){
+      signal_vertex = sig_attr->value();
+    }
+  }
+  if(!signal_vertex){
+    warning() << "No signal vertex found, returning FALSE" << endmsg;
+    return false;
   }
 
-  LHCb::MCParticles* mcParts =
-    get<LHCb::MCParticles>( LHCb::MCParticleLocation::Default );
-  
+  // Simulating the signal decay, first make sure that the signal vertex has only one outgoing particle
+  if(signal_vertex->particles_in().size() != 1){
+    warning() << "Signal vertex does not have exactly one child, returning FALSE" << endmsg;
+    return false;
+  }
+  auto sig_part = *std::begin(signal_vertex->particles_in());
+  Gaussino::GiGaSimReturn simresult = m_gigaSvc->simulateDecay(sig_part, ThreadLocalEngine::GetPtr());
+  // Now, we can search for the presence of the whatever we need in the simulated result.
+  auto & [g4event, mctruth ] = simresult;
+
   const std::string filterString = "event with gamma conversion from "+m_mother;
 
   bool filter = false;
@@ -85,12 +104,14 @@ bool ConversionCutTool::studyFullEvent( const HepMC3::GenEventPtrs & theEvents ,
   // -- Loop over all MCParticles
   // -- First check that they are gammas
   // -- do pair production at their endvertex and have the right z-position.
-  for( auto mcPart : *mcParts){
-    if( mcPart->particleID().pid() != 22 ) continue;
+  for( auto linkedPart : mctruth->GetParticles()){
+    if( linkedPart->GetPDG() != 22 ) continue;
     bool goodPhoton = false;
-    for( const auto endVtx : mcPart->endVertices()){
+    for( auto & endVtx : linkedPart->GetEndVtxs()){
       if( !endVtx ) continue;
-      if( endVtx->type() == LHCb::MCVertex::PairProduction && std::abs(endVtx->position().z()) < m_maxZ ){
+      msgStream();
+      auto vertex_type = Gaussino::GetLinkedVertexType(endVtx.get(), &msgStream());
+      if( vertex_type == LHCb::MCVertex::PairProduction && std::abs(endVtx->GetPosition().z()) < m_maxZ ){
         goodPhoton = true;
         break;
       }
@@ -99,7 +120,15 @@ bool ConversionCutTool::studyFullEvent( const HepMC3::GenEventPtrs & theEvents ,
     nConv++;
 
     unsigned int searchDepth = 0;
-    const LHCb::MCParticle* momPart = mcPart->mother();
+    auto getmother = [&] (LinkedParticle * part) -> LinkedParticle*{
+      auto parents = part->GetParents();
+      if(parents.size() > 0){
+        return *std::begin(parents);
+      } else {
+        return nullptr;
+      }
+    };
+    auto momPart = getmother(linkedPart);
     
     // -- Search up the decay tree to see if this gamma is coming from the mother we care for
     // -- If we don't care about the mother, we just check if it fullfills the p,pt and theta requirements
@@ -109,30 +138,31 @@ bool ConversionCutTool::studyFullEvent( const HepMC3::GenEventPtrs & theEvents ,
       // -- loop until we have reach that depth.
       if( m_matchSearchDepth && searchDepth < m_maxSearchDepth - 1 ){
         searchDepth++;
-        momPart = momPart->mother();
+        momPart = getmother(momPart);
         continue;
       }
       
+      // FIXME: Does not support nested MCTruth structures yet but probably not needed
 
-      if( (std::abs(momPart->particleID().pid()) == m_motherID) || (m_motherID == -1) ){
+      if( (std::abs(momPart->GetPDG()) == m_motherID) || (m_motherID == -1) ){
         if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) debug() << "Found gamma conversion from mother: " << m_motherID << endmsg;
         // -- we found the right mother
         // -- let's see if the daughters (=electrons) have enough momentum, pt and are within the acceptance.
-        for( const LHCb::MCVertex* endVtx : mcPart->endVertices()){
+        for( auto & endVtx : linkedPart->GetEndVtxs()){
           if( !endVtx ) continue;
-          if( endVtx->products().size() != 2 ) continue; // want pair production
+          if( endVtx->outgoing_particles.size() != 2 ) continue; // want pair production
           
           // -- We ask that all of the daughters have enough p and pt, and are within the LHCb acceptance. In case there is more than 1 end vertex
           // -- we take the "or" of them.
-          filter |= std::all_of( std::begin(endVtx->products()), std::end(endVtx->products()), [&](const LHCb::MCParticle* dau){
-              return (dau->p() > m_minP) && (dau->pt() > m_minPT) && (dau->momentum().theta() > m_minTheta) && (dau->momentum().theta() < m_maxTheta);
+          filter |= std::all_of( std::begin(endVtx->outgoing_particles), std::end(endVtx->outgoing_particles), [&](LinkedParticle* dau){
+              return (dau->GetMomentum().p3mod() > m_minP) && (dau->GetMomentum().pt() > m_minPT) && (dau->GetMomentum().theta() > m_minTheta) && (dau->GetMomentum().theta() < m_maxTheta);
             });
           
           // --
           if( UNLIKELY( msgLevel(MSG::DEBUG) ) ){
-            for( const LHCb::MCParticle* dau : endVtx->products()){
-              debug() << "particle: " << dau->particleID().pid() << " p: " << dau->p() << " pt: " 
-                      << dau->pt() << " theta: " << dau->momentum().theta() << endmsg;
+            for( auto dau : endVtx->outgoing_particles){
+              debug() << "particle: " << dau->GetPDG() << " p: " << dau->GetMomentum().p3mod() << " pt: " 
+                      << dau->GetMomentum().pt() << " theta: " << dau->GetMomentum().theta() << endmsg;
             }
             if( filter ){
               debug() << "accepted" << endmsg;
@@ -147,16 +177,19 @@ bool ConversionCutTool::studyFullEvent( const HepMC3::GenEventPtrs & theEvents ,
         break;
       }
       searchDepth++;
-      momPart = momPart->mother();
+      momPart = getmother(momPart);
     }
   }
 
   if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) debug() << "Found " <<  nConv << " gamma conversions in total" << endmsg;
 
-  if( filter ) counter(filterString)++;
-  
-  setFilterPassed( filter );
-  return StatusCode::SUCCESS;
+  // Lastly, if the filter has been successful, we attach the simulation result to the
+  // particle via an hepmc attribute. If not, the results will automatically be 
+  // destroyed at the end of this function.
+  if( filter ){
+    counter(filterString)++;
+    sig_part->add_attribute(Gaussino::HepMC::Attributes::SimResults, std::make_shared<HepMC3::SimResultsAttribute>(simresult));
+  }
   
+  return filter;
 }
-
diff --git a/Sim/GaussTracker/src/GetTrackerHitsAlg.cpp b/Sim/GaussTracker/src/GetTrackerHitsAlg.cpp
index 2b6c0a15d..b33eefebc 100755
--- a/Sim/GaussTracker/src/GetTrackerHitsAlg.cpp
+++ b/Sim/GaussTracker/src/GetTrackerHitsAlg.cpp
@@ -67,7 +67,7 @@ LHCb::MCHits GetTrackerHitsAlg::operator()(
 
     for (auto& ep : eventproxies) {
         auto hitCollection =
-            ep.GetHitCollection<TrackerHitsCollection>(m_colName);
+            ep->GetHitCollection<TrackerHitsCollection>(m_colName);
         if (!hitCollection) {
             warning() << "The hit collection='" + m_colName + "' is not found!"
                       << endmsg;
@@ -80,14 +80,14 @@ LHCb::MCHits GetTrackerHitsAlg::operator()(
             // create hit or extended hit depending on choice
             if (m_extendedInfo) {
                 LHCb::MCExtendedHit* newHit = new LHCb::MCExtendedHit();
-                fillHit((*hitCollection)[iG4Hit], newHit, ep.truth(),
+                fillHit((*hitCollection)[iG4Hit], newHit, ep->truth(),
                         mcp_links);
                 Gaudi::XYZVector mom((*hitCollection)[iG4Hit]->GetMomentum());
                 newHit->setMomentum(mom);
                 hits.add(newHit);
             } else {
                 LHCb::MCHit* newHit = new LHCb::MCHit();
-                fillHit((*hitCollection)[iG4Hit], newHit, ep.truth(),
+                fillHit((*hitCollection)[iG4Hit], newHit, ep->truth(),
                         mcp_links);
                 hits.add(newHit);
             }
-- 
GitLab


From b5b1233ce7c8929aa57fef72de99eba758d12ed1 Mon Sep 17 00:00:00 2001
From: Dominik Muller <dominik.muller@cern.ch>
Date: Fri, 31 Jan 2020 15:40:39 +0100
Subject: [PATCH 37/90] gamma conversion fixed invalid attribute crash. Added
 Debug statements.

---
 Sim/GaussSimCutTools/src/ConversionFilter.cpp | 22 ++++++++++++++++++-
 1 file changed, 21 insertions(+), 1 deletion(-)

diff --git a/Sim/GaussSimCutTools/src/ConversionFilter.cpp b/Sim/GaussSimCutTools/src/ConversionFilter.cpp
index f398a644e..3480b7607 100644
--- a/Sim/GaussSimCutTools/src/ConversionFilter.cpp
+++ b/Sim/GaussSimCutTools/src/ConversionFilter.cpp
@@ -16,6 +16,7 @@
 
 #include "Defaults/HepMCAttributes.h"
 #include "HepMCUser/VertexAttribute.h"
+#include "HepMCUtils/PrintDecayTree.h"
 #include "MCTruthToEDM/VertexType.h"
 
 //-----------------------------------------------------------------------------
@@ -78,7 +79,7 @@ bool ConversionCutTool::studyFullEvent( const HepMC3::GenEventPtrs & theEvents ,
   for(auto & evt : theEvents){
 
     auto sig_attr = evt->attribute<HepMC3::VertexAttribute>(Gaussino::HepMC::Attributes::SignalProcessVertex);
-    if(sig_attr->value().get()){
+    if(sig_attr.get() && sig_attr->value().get()){
       signal_vertex = sig_attr->value();
     }
   }
@@ -93,9 +94,16 @@ bool ConversionCutTool::studyFullEvent( const HepMC3::GenEventPtrs & theEvents ,
     return false;
   }
   auto sig_part = *std::begin(signal_vertex->particles_in());
+  if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) {
+      debug() << "Simulating Decay:" << endmsg;
+      debug() << PrintDecay(sig_part, 0, m_ppSvc.get()) << endmsg;
+  }
   Gaussino::GiGaSimReturn simresult = m_gigaSvc->simulateDecay(sig_part, ThreadLocalEngine::GetPtr());
   // Now, we can search for the presence of the whatever we need in the simulated result.
   auto & [g4event, mctruth ] = simresult;
+  if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) {
+    mctruth->DumpToStream(debug());
+  }
 
   const std::string filterString = "event with gamma conversion from "+m_mother;
 
@@ -117,6 +125,9 @@ bool ConversionCutTool::studyFullEvent( const HepMC3::GenEventPtrs & theEvents ,
       }
     }
     if( !goodPhoton ) continue;
+    if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) {
+        debug() << "Found a good photon with PairProduction endvertex" << endmsg;
+    }
     nConv++;
 
     unsigned int searchDepth = 0;
@@ -132,7 +143,16 @@ bool ConversionCutTool::studyFullEvent( const HepMC3::GenEventPtrs & theEvents ,
     
     // -- Search up the decay tree to see if this gamma is coming from the mother we care for
     // -- If we don't care about the mother, we just check if it fullfills the p,pt and theta requirements
+    if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) {
+        debug() << "Mother particle: " << momPart << (momPart?momPart->GetPDG():-1) << endmsg;
+    }
     while( momPart && searchDepth < m_maxSearchDepth){
+      if (UNLIKELY(msgLevel(MSG::DEBUG))) {
+        debug() << "Search Depth: " << searchDepth << " < " << m_maxSearchDepth
+                << endmsg;
+        debug() << "Mother particle: " << momPart
+                << (momPart ? momPart->GetPDG() : -1) << endmsg;
+      }
 
       // -- If we only want to search for a given depth, and not for a maximum
       // -- loop until we have reach that depth.
-- 
GitLab


From 86b2eeb58bd81ad4d7a8672df8857d0f21c6a4ed Mon Sep 17 00:00:00 2001
From: Dominik Muller <dominik.muller@cern.ch>
Date: Wed, 25 Mar 2020 15:01:25 +0100
Subject: [PATCH 38/90] StatusCode ignore fixes

---
 Gen/LbEvtGen/src/EvtGenDecay.cpp              | 16 +++---
 Gen/LbEvtGen/src/EvtGenInPhSpDecay.cpp        |  4 +-
 Muon/MuonMoniSim/src/MuonHitChecker.cpp       | 50 +++++++++----------
 Sim/GaussCalo/src/CaloSensDetFAC.h            |  2 +-
 Sim/GaussCalo/src/EcalSensDet.cpp             |  2 +-
 Sim/GaussCalo/src/HcalSensDet.cpp             |  2 +-
 Sim/GaussCalo/src/SpdPrsSensDet.cpp           |  2 +-
 Sim/GaussGeo/src/component/GaussGeo.cpp       | 10 ++--
 .../src/component/GaussGeoAssembly.cpp        |  6 +--
 .../src/component/GaussGeoAssemblyStore.cpp   |  2 +-
 Velo/VeloGauss/src/VeloGaussMoni.cpp          |  6 +--
 11 files changed, 51 insertions(+), 51 deletions(-)

diff --git a/Gen/LbEvtGen/src/EvtGenDecay.cpp b/Gen/LbEvtGen/src/EvtGenDecay.cpp
index 899a72f22..0467d9e52 100755
--- a/Gen/LbEvtGen/src/EvtGenDecay.cpp
+++ b/Gen/LbEvtGen/src/EvtGenDecay.cpp
@@ -91,7 +91,7 @@ StatusCode EvtGenDecay::initialize( ) {
   m_randomEngine = std::make_unique<RandomEngineWrapper>( );
   if ( ! sc.isSuccess() )
     return Error( "Cannot initialize EvtGenGaudiRandomService" , sc ) ;
-  release( randSvc ) ;
+  release( randSvc ).ignore() ;
 
   //this list will be deleted after use
   //the actual models will be deleted by the singleton EvtModel
@@ -151,8 +151,8 @@ StatusCode EvtGenDecay::finalize() {
   debug() << "EvtGenDecay finalized" << endmsg ;
 	
   if ( ! ( msgLevel( MSG::DEBUG ) ) ) { 
-    F77Utils::close( m_taulaUnit ) ;
-    F77Utils::close( m_photosUnit ) ;
+    F77Utils::close( m_taulaUnit ).ignore() ;
+    F77Utils::close( m_photosUnit ).ignore() ;
   }
   
   delete StreamForGenerator::getStream() ;
@@ -189,7 +189,7 @@ StatusCode EvtGenDecay::generateDecay( const HepMC3::GenParticlePtr & theMother
 
   // Fill HepMC event theEvent with EvtGen decay tree part
   // starting from theMother
-  makeHepMC( part , theMother , theOriginPosition , -999 ) ;
+  makeHepMC( part , theMother , theOriginPosition , -999 ).ignore() ;
 
   // delete EvtGen particle and all its daughters
   part -> deleteTree ( ) ;
@@ -239,7 +239,7 @@ StatusCode EvtGenDecay::generateSignalDecay( const HepMC3::GenParticlePtr & theM
   
   // Fill HepMC event theEvent with EvtGen decay tree part
   // starting from theMother
-  makeHepMC( part , theMother , theOriginPosition , -999 ) ;
+  makeHepMC( part , theMother , theOriginPosition , -999 ).ignore() ;
 
   // delete EvtGen particle and all its daughters
   part -> deleteTree ( ) ;
@@ -281,7 +281,7 @@ StatusCode EvtGenDecay::generateDecayWithLimit( const HepMC3::GenParticlePtr & t
   // Fill HepMC event theEvent with EvtGen decay tree part
   // starting from theMother and stopping at particle with pdgId
   // equals to targetId
-  makeHepMC( part , theMother , theOriginPosition , targetId ) ;
+  makeHepMC( part , theMother , theOriginPosition , targetId ).ignore() ;
   
   // delete EvtGen particle and all its daughters
   part -> deleteTree ( ) ;
@@ -343,7 +343,7 @@ StatusCode EvtGenDecay::makeHepMC( EvtParticle * theEvtGenPart ,
       // if the particle is not of requested type
       if ( abs( id ) != targetId )
           makeHepMC( theEvtGenPart->getDaug(it) , prod_part , theOrigin , 
-                     targetId ) ;
+                     targetId ).ignore() ;
       // otherwise (particle has targetId pdg ID) it can be decayed further
       // by EvtGen (it is the signal particle in pratice) so give it 
       // status 888 unless it is a stable particle and then give it status 999
@@ -466,7 +466,7 @@ StatusCode EvtGenDecay::createTemporaryEvtFile( const boost::filesystem::path &
   // File must en with key word "end"
   g << "end" << std::endl ;
   g.close() ;
-  release( ppSvc ) ;
+  release( ppSvc ).ignore() ;
 
   return StatusCode::SUCCESS ;
 }
diff --git a/Gen/LbEvtGen/src/EvtGenInPhSpDecay.cpp b/Gen/LbEvtGen/src/EvtGenInPhSpDecay.cpp
index 19bf740dd..e19d0bb07 100644
--- a/Gen/LbEvtGen/src/EvtGenInPhSpDecay.cpp
+++ b/Gen/LbEvtGen/src/EvtGenInPhSpDecay.cpp
@@ -71,7 +71,7 @@ StatusCode EvtGenInPhSpDecay::initialize( ) {
 
   m_q2mapvec.reserve( m_q2nbins ) ;
   //load map
-  loadMap();
+  loadMap().ignore();
   
   if ( msgLevel ( MSG::DEBUG ) )  debug() << "EvtGenInPhSpDecay initialized" << endmsg ;
   
@@ -255,7 +255,7 @@ StatusCode EvtGenInPhSpDecay::generateSignalDecay( const HepMC3::GenParticlePtr&
   
   // Fill HepMC event theEvent with EvtGen decay tree part
   // starting from theMother
-  makeHepMC( part , theMother , theOriginPosition , -999 ) ;
+  makeHepMC( part , theMother , theOriginPosition , -999 ).ignore() ;
 
   // delete EvtGen particle and all its daughters
   part -> deleteTree ( ) ;
diff --git a/Muon/MuonMoniSim/src/MuonHitChecker.cpp b/Muon/MuonMoniSim/src/MuonHitChecker.cpp
index 27c01c6c8..1afda6a46 100755
--- a/Muon/MuonMoniSim/src/MuonHitChecker.cpp
+++ b/Muon/MuonMoniSim/src/MuonHitChecker.cpp
@@ -179,31 +179,31 @@ void MuonHitChecker::operator()(const LHCb::MCHits& hits,
     info() << "Doing ntuple stuff" << endmsg;
     //    nt1->column("Run", m_run,0,1000000);
     int pippo = m_evt;
-    nt1->column("Event", pippo, 0, 10000);
-
-    nt1->farray("is", m_sta, "Nhits", 1000);
-    nt1->farray("ir", m_reg, "Nhits", 1000);
-    nt1->farray("ic", m_con, "Nhits", 1000);
-    nt1->farray("x", m_x, "Nhits", 1000);
-    nt1->farray("y", m_y, "Nhits", 1000);
-    nt1->farray("z", m_z, "Nhits", 1000);
-    nt1->farray("t", m_time, "Nhits", 1000);
-    nt1->farray("id", m_id, "Nhits", 1000);
-    nt1->farray("px", m_px, "Nhits", 1000);
-    nt1->farray("py", m_py, "Nhits", 1000);
-    nt1->farray("pz", m_pz, "Nhits", 1000);
-    nt1->farray("E", m_E, "Nhits", 1000);
-    nt1->farray("xv", m_xv, "Nhits", 1000);
-    nt1->farray("yv", m_yv, "Nhits", 1000);
-    nt1->farray("zv", m_zv, "Nhits", 1000);
-    nt1->farray("tv", m_tv, "Nhits", 1000);
-    nt1->farray("idm", m_mom, "Nhits", 1000);
-    nt1->farray("pl", m_ple, "Nhits", 1000);
-    nt1->farray("he", m_hen, "Nhits", 1000);
-    nt1->farray("dx", m_dix, "Nhits", 1000);
-    nt1->farray("xz", m_dxz, "Nhits", 1000);
-    nt1->farray("yz", m_dyz, "Nhits", 1000);
-    nt1->write();
+    nt1->column("Event", pippo, 0, 10000).ignore();
+
+    nt1->farray("is", m_sta, "Nhits", 1000).ignore();
+    nt1->farray("ir", m_reg, "Nhits", 1000).ignore();
+    nt1->farray("ic", m_con, "Nhits", 1000).ignore();
+    nt1->farray("x", m_x, "Nhits", 1000).ignore();
+    nt1->farray("y", m_y, "Nhits", 1000).ignore();
+    nt1->farray("z", m_z, "Nhits", 1000).ignore();
+    nt1->farray("t", m_time, "Nhits", 1000).ignore();
+    nt1->farray("id", m_id, "Nhits", 1000).ignore();
+    nt1->farray("px", m_px, "Nhits", 1000).ignore();
+    nt1->farray("py", m_py, "Nhits", 1000).ignore();
+    nt1->farray("pz", m_pz, "Nhits", 1000).ignore();
+    nt1->farray("E", m_E, "Nhits", 1000).ignore();
+    nt1->farray("xv", m_xv, "Nhits", 1000).ignore();
+    nt1->farray("yv", m_yv, "Nhits", 1000).ignore();
+    nt1->farray("zv", m_zv, "Nhits", 1000).ignore();
+    nt1->farray("tv", m_tv, "Nhits", 1000).ignore();
+    nt1->farray("idm", m_mom, "Nhits", 1000).ignore();
+    nt1->farray("pl", m_ple, "Nhits", 1000).ignore();
+    nt1->farray("he", m_hen, "Nhits", 1000).ignore();
+    nt1->farray("dx", m_dix, "Nhits", 1000).ignore();
+    nt1->farray("xz", m_dxz, "Nhits", 1000).ignore();
+    nt1->farray("yz", m_dyz, "Nhits", 1000).ignore();
+    nt1->write().ignore();
   }
 }
 //=============================================================================
diff --git a/Sim/GaussCalo/src/CaloSensDetFAC.h b/Sim/GaussCalo/src/CaloSensDetFAC.h
index 0c3ff731a..5171b1872 100755
--- a/Sim/GaussCalo/src/CaloSensDetFAC.h
+++ b/Sim/GaussCalo/src/CaloSensDetFAC.h
@@ -67,7 +67,7 @@ class CaloSensDetBaseFAC : public GiGaMTG4SensDetFactory<CALO> {
   StatusCode initialize() override {
     auto sc = gaussino_base_class::initialize();
 
-    m_histoSvc.retrieve();
+    m_histoSvc.retrieve().ignore();
     {  // load all input histos
       for (auto& histo : m_histoNames) {
         SmartDataPtr<IHistogram1D> pHist(m_histoSvc.get(), histo);
diff --git a/Sim/GaussCalo/src/EcalSensDet.cpp b/Sim/GaussCalo/src/EcalSensDet.cpp
index 926d8048a..d1ff75b8d 100755
--- a/Sim/GaussCalo/src/EcalSensDet.cpp
+++ b/Sim/GaussCalo/src/EcalSensDet.cpp
@@ -102,7 +102,7 @@ bool EcalSensDet<CELLGETTER>::fillHitInfo(
   }
 
   for (double fr : fractions) {
-    if (fr > 1.e-5) hit->add(slot, ecorrected * fr);
+    if (fr > 1.e-5) hit->add(slot, ecorrected * fr).ignore();
     slot++;
   }
 
diff --git a/Sim/GaussCalo/src/HcalSensDet.cpp b/Sim/GaussCalo/src/HcalSensDet.cpp
index 81f349294..f4e883208 100755
--- a/Sim/GaussCalo/src/HcalSensDet.cpp
+++ b/Sim/GaussCalo/src/HcalSensDet.cpp
@@ -91,7 +91,7 @@ bool HcalSensDet<CELLGETTER>::fillHitInfo(
 
   for (auto fr : fractions) {
     if (fr > 1.e-5) {
-      hit->add(slot, energy * fr);
+      hit->add(slot, energy * fr).ignore();
     }
   }
 
diff --git a/Sim/GaussCalo/src/SpdPrsSensDet.cpp b/Sim/GaussCalo/src/SpdPrsSensDet.cpp
index 6c2dd3d78..77933f7cb 100755
--- a/Sim/GaussCalo/src/SpdPrsSensDet.cpp
+++ b/Sim/GaussCalo/src/SpdPrsSensDet.cpp
@@ -106,7 +106,7 @@ bool SpdPrsSensDet<CELLGETTER>::fillHitInfo
   { this->error ( "Could not smear Edep!" ) ; }
 
   for( unsigned int i = 0; i < frac.size(); i++, slot += 1 )
-  { if ( frac[i] > m_fracMin ) { hit->add( slot, edep*frac[i] ) ; } }
+  { if ( frac[i] > m_fracMin ) { hit->add( slot, edep*frac[i] ).ignore() ; } }
 
   return true;
 }
diff --git a/Sim/GaussGeo/src/component/GaussGeo.cpp b/Sim/GaussGeo/src/component/GaussGeo.cpp
index 2ec47a08f..a290af2b9 100644
--- a/Sim/GaussGeo/src/component/GaussGeo.cpp
+++ b/Sim/GaussGeo/src/component/GaussGeo.cpp
@@ -291,7 +291,7 @@ StatusCode GaussGeo::finalize() {
   //m_mag_field_managers.clear();
 
   // Clear assembly store
-  GaussGeoAssemblyStore::store()->clear();
+  GaussGeoAssemblyStore::store()->clear().ignore();
 
   // Delete volumes
   if (m_clear_stores) {
@@ -485,7 +485,7 @@ StatusCode GaussGeo::convertDetectorElementObject(DataObject* object) {
         return reportError("Failed to cast daughter object while looping over "
                            + det_element->name() + "'s children: " + bc_msg.what());
       }
-      convertGeoObject(child_object);
+      convertGeoObject(child_object).ignore();
     }
   }
 
@@ -554,7 +554,7 @@ StatusCode GaussGeo::convertLAssemblyObject(DataObject* object) {
     if (!gg_volume.isValid()) {
       return reportError("GaussGeoVolume is invalid!");
     }
-    gg_assembly->addVolume(GaussGeoVolumePair(gg_volume, pvolume->matrix()), pvolume->name());
+    gg_assembly->addVolume(GaussGeoVolumePair(gg_volume, pvolume->matrix()), pvolume->name()).ignore();
   }
 
   if (outputLevel() == MSG::VERBOSE) {
@@ -1477,7 +1477,7 @@ G4VPhysicalVolume* GaussGeo::constructWorld() {
 
   //FIXME Field stuff
   if (!m_mag_field_mgr.empty()) {
-    register_mag_field(m_mag_field_mgr, nullptr);
+    register_mag_field(m_mag_field_mgr, nullptr).ignore();
 
   } else {
     warning() << "Magnetic Field was not requested to be loaded" << endmsg;
@@ -1514,7 +1514,7 @@ G4LogicalVolume* GaussGeo::createG4LVolume(G4VSolid* g4_solid, G4Material* g4_ma
 
   // Look for global material budget counter
   if (!m_budget.empty()) {
-    register_sensitive(m_budget, g4_lvolume);
+    register_sensitive(m_budget, g4_lvolume).ignore();
   }
 
   if (outputLevel() == MSG::VERBOSE) {
diff --git a/Sim/GaussGeo/src/component/GaussGeoAssembly.cpp b/Sim/GaussGeo/src/component/GaussGeoAssembly.cpp
index e9342e9de..9b119fbd2 100644
--- a/Sim/GaussGeo/src/component/GaussGeoAssembly.cpp
+++ b/Sim/GaussGeo/src/component/GaussGeoAssembly.cpp
@@ -3,19 +3,19 @@
 #include "GaussGeoAssemblyStore.h"
 
 GaussGeoAssembly::GaussGeoAssembly(const std::string& Name) : m_name(Name), m_volumes() {
-  GaussGeoAssemblyStore::store()->addAssembly(this);
+  GaussGeoAssemblyStore::store()->addAssembly(this).ignore();
 }
 
 GaussGeoAssembly::GaussGeoAssembly(const GaussGeoAssembly& right)
   : m_name(right.m_name),
     m_volumes(right.m_volumes)
 {
-  GaussGeoAssemblyStore::store()->addAssembly(this);
+  GaussGeoAssemblyStore::store()->addAssembly(this).ignore();
 }
 
 GaussGeoAssembly::~GaussGeoAssembly() {
   m_volumes.clear();
-  GaussGeoAssemblyStore::store()->removeAssembly(this);
+  GaussGeoAssemblyStore::store()->removeAssembly(this).ignore();
 }
 
 StatusCode GaussGeoAssembly::addVolume(const GaussGeoVolumePair& volume_pair, const std::string& name) {
diff --git a/Sim/GaussGeo/src/component/GaussGeoAssemblyStore.cpp b/Sim/GaussGeo/src/component/GaussGeoAssemblyStore.cpp
index e1c749309..45809da2a 100644
--- a/Sim/GaussGeo/src/component/GaussGeoAssemblyStore.cpp
+++ b/Sim/GaussGeo/src/component/GaussGeoAssemblyStore.cpp
@@ -14,7 +14,7 @@ GaussGeoAssemblyStore* GaussGeoAssemblyStore::store()
 GaussGeoAssemblyStore::GaussGeoAssemblyStore() : m_assemblies() {}
 
 GaussGeoAssemblyStore::~GaussGeoAssemblyStore() {
-  clear();
+  clear().ignore();
 }
 
 GaussGeoAssembly* GaussGeoAssemblyStore::assembly(const std::string& name) {  
diff --git a/Velo/VeloGauss/src/VeloGaussMoni.cpp b/Velo/VeloGauss/src/VeloGaussMoni.cpp
index 90e568dd7..a61442969 100755
--- a/Velo/VeloGauss/src/VeloGaussMoni.cpp
+++ b/Velo/VeloGauss/src/VeloGaussMoni.cpp
@@ -31,7 +31,7 @@ StatusCode VeloGaussMoni::initialize() {
   m_veloDet=( getDet<DeVelo>(m_veloDetLocation ) );
   setHistoTopDir("Velo/");
   bookHistograms();
-  checkTests();
+  checkTests().ignore();
   //
   return StatusCode::SUCCESS;
 }
@@ -45,8 +45,8 @@ void VeloGaussMoni::operator()(const LHCb::MCHits& m_veloMCHits, const LHCb::MCH
   //so instead of doing something smart we just lock this for now ...
   std::lock_guard<std::mutex> guard_lock(m_lazy_lock);
   m_nEvent++;
-  if(m_testMCHit) veloMCHitMonitor(&m_veloMCHits);
-  if(m_testPileUpMCHit) veloPileUpMCHitMonitor(&m_veloPileUpMCHits);
+  if(m_testMCHit) veloMCHitMonitor(&m_veloMCHits).ignore();
+  if(m_testPileUpMCHit) veloPileUpMCHitMonitor(&m_veloPileUpMCHits).ignore();
 }
 
 //=============================================================================
-- 
GitLab


From 5ba748988118503d1e311b64dd9778dd08775ad6 Mon Sep 17 00:00:00 2001
From: Dominik Muller <dominik.muller@cern.ch>
Date: Thu, 26 Mar 2020 16:41:27 +0100
Subject: [PATCH 39/90] Compatibility patches for Gaussino ReDecay branch

---
 Sim/Gauss/python/Gauss/Configuration.py       | 7 ++++---
 Sim/GaussSimCutTools/src/ConversionFilter.cpp | 2 +-
 2 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/Sim/Gauss/python/Gauss/Configuration.py b/Sim/Gauss/python/Gauss/Configuration.py
index bacd09f1e..c0b8d103f 100755
--- a/Sim/Gauss/python/Gauss/Configuration.py
+++ b/Sim/Gauss/python/Gauss/Configuration.py
@@ -31,6 +31,7 @@ class Gauss(LHCbConfigurableUser):
         "WriteFSR": False,
         "MergeGenFSR": False,
         "Debug": False,
+        "ReDecay": False,
         "ForceRandomEngine": 'NONE',
         "Phases": ["Generator", "Simulation"],
         "BeamMomentum": 3.5 * SystemOfUnits.TeV,  # NOQA
@@ -50,7 +51,6 @@ class Gauss(LHCbConfigurableUser):
         "EnableHive": False,  # NOQA
         "ThreadPoolSize": 2,  # NOQA
         "EventSlots" : 2,  # NOQA
-        "ConvertEDM" : False,  # NOQA
         }
 
     _propertyDocDct = {
@@ -123,7 +123,7 @@ class Gauss(LHCbConfigurableUser):
         packing = dummy()
         # Need this dummy sequence to later extract all the algorithm that
         # need to be given to the scheduler.
-        if Gaussino().getProp('ConvertEDM') or "Simulation" in Gauss().getProp("Phases"):
+        if "GenToMCTree" in Gaussino().getProp('Phases') or "Simulation" in Gauss().getProp("Phases"):
             for so in self.defineCrossingList():
                 SimConf().PackingSequencers[so] = packing
 
@@ -218,7 +218,8 @@ class Gauss(LHCbConfigurableUser):
 
         self.setOtherProps(Gaussino(), [
             "Histograms", "DatasetName", "Phases", "SpilloverPaths", "EvtMax",
-            "EnableHive", "ThreadPoolSize", "EventSlots", "ConvertEDM"])
+            "EnableHive", "ThreadPoolSize", "EventSlots", 
+            "ReDecay"])
 
         LHCbApp().Simulation = True
         self.setOtherProps(LHCbApp(), [
diff --git a/Sim/GaussSimCutTools/src/ConversionFilter.cpp b/Sim/GaussSimCutTools/src/ConversionFilter.cpp
index 3480b7607..afe7a6e44 100644
--- a/Sim/GaussSimCutTools/src/ConversionFilter.cpp
+++ b/Sim/GaussSimCutTools/src/ConversionFilter.cpp
@@ -42,7 +42,7 @@ StatusCode ConversionCutTool::initialize() {
     return StatusCode::SUCCESS;
   }
 
-  m_ppSvc.retrieve();
+  sc &= m_ppSvc.retrieve();
   if( !m_ppSvc ) {
     error() << "Could not retrieve ParticlePropertySvc" << endmsg;
     m_motherID = -1;
-- 
GitLab


From 56a4f808d6d119fe5f24aa5f7ec136ad21d144c9 Mon Sep 17 00:00:00 2001
From: Dominik Muller <dominik.muller@cern.ch>
Date: Thu, 26 Mar 2020 16:43:56 +0100
Subject: [PATCH 40/90] Compatibility changes for phys constr changes in
 Gaussino

---
 Sim/Gauss/python/Gauss/Physics.py             |  2 +-
 .../src/particles/GiGaHiggsParticles.cpp      | 20 +++++++-----------
 .../particles/GiGaPhysUnknownParticles.cpp    | 21 +++++++++++++++++--
 .../src/particles/GiGaPhysUnknownParticles.h  | 20 ------------------
 4 files changed, 27 insertions(+), 36 deletions(-)
 delete mode 100755 Sim/GaussPhysics/src/particles/GiGaPhysUnknownParticles.h

diff --git a/Sim/Gauss/python/Gauss/Physics.py b/Sim/Gauss/python/Gauss/Physics.py
index 2b425796b..da653039a 100644
--- a/Sim/Gauss/python/Gauss/Physics.py
+++ b/Sim/Gauss/python/Gauss/Physics.py
@@ -170,13 +170,13 @@ class G4Physics(LHCbConfigurableUser):
     def AddLHCbPhysics(self, pl):
         lhcbPhys = self.getProp('LHCbPhys')
         richUpgradeConfig = self.getProp('RichUpgradeConfig')
+        pl.PhysicsConstructors.append("GiGaPhysUnknownParticles")
         if lhcbPhys:
             log.info("Applying LHCb specific physics.")
             if richUpgradeConfig:
                 self.defineRichMaPmtPhys(pl)
             else:
                 self.defineRichPhys(pl)
-            pl.PhysicsConstructors.append("GiGaMTPhysUnknownParticles")
         else:
             log.warning("The lhcb-related physics (RICH processed,"
                         "UnknownParticles) is disabled")
diff --git a/Sim/GaussPhysics/src/particles/GiGaHiggsParticles.cpp b/Sim/GaussPhysics/src/particles/GiGaHiggsParticles.cpp
index 6551fbb99..d00e17115 100755
--- a/Sim/GaussPhysics/src/particles/GiGaHiggsParticles.cpp
+++ b/Sim/GaussPhysics/src/particles/GiGaHiggsParticles.cpp
@@ -96,22 +96,17 @@ void GiGaMTHiggsParticles::ConstructParticle () // construct the particles
 }
 
 
-template <typename PhysConstr>
-class GiGaMTG4PhysicsConstrFAC<
-    PhysConstr,
-    typename std::enable_if<
-        std::is_same<PhysConstr, GiGaMTHiggsParticles>::value,
-        PhysConstr>::type>
-    : public extends<GiGaMTPhysConstr, GiGaFactoryBase<G4VPhysicsConstructor>> {
+class GiGaMTHiggsParticlesFAC : public extends<GiGaMTPhysConstr, GiGaFactoryBase<G4VPhysicsConstructor>>
+{
+public:
   Gaudi::Property<std::vector<std::string>> m_higgses{
       this, "Higgses", {},
       "The List of Higgsed to be instantiated"};
   ServiceHandle<LHCb::IParticlePropertySvc> m_ppSvc{this, "PropertyService", "LHCb::ParticlePropertySvc"};
-
-  public:
   using extends::extends;
-  PhysConstr* construct() const override {
-    auto tmp = new PhysConstr{m_ppSvc.get(), m_higgses};
+  GiGaMTHiggsParticles* construct() const override
+  {
+    auto tmp = new GiGaMTHiggsParticles{m_ppSvc.get(), m_higgses};
     tmp->SetMessageInterface(message_interface());
     tmp->SetVerboseLevel(verbosity());
     tmp->SetPhysicsName(name());
@@ -119,5 +114,4 @@ class GiGaMTG4PhysicsConstrFAC<
   }
 };
 
-typedef GiGaMTG4PhysicsConstrFAC<GiGaMTHiggsParticles> GiGaMT_GiGaMTHiggsParticles;
-DECLARE_COMPONENT_WITH_ID(GiGaMT_GiGaMTHiggsParticles, "GiGaMTHiggsParticles")
+DECLARE_COMPONENT_WITH_ID(GiGaMTHiggsParticlesFAC, "GiGaMTHiggsParticles")
diff --git a/Sim/GaussPhysics/src/particles/GiGaPhysUnknownParticles.cpp b/Sim/GaussPhysics/src/particles/GiGaPhysUnknownParticles.cpp
index 87b322c5f..a226e7bba 100755
--- a/Sim/GaussPhysics/src/particles/GiGaPhysUnknownParticles.cpp
+++ b/Sim/GaussPhysics/src/particles/GiGaPhysUnknownParticles.cpp
@@ -37,8 +37,25 @@
 #include "G4XiccPlusPlus.h"
 #include "G4XiccStarPlus.h"
 
-//
-#include "GiGaPhysUnknownParticles.h"
+#include "Geant4/G4VPhysicsConstructor.hh"
+#include "Geant4/G4Decay.hh"
+#include "Geant4/G4UnknownDecay.hh"
+#include "GiGaMTCoreMessage/IGiGaMessage.h"
+
+class GiGaMTPhysUnknownParticles :public GiGaMessage, public G4VPhysicsConstructor
+{
+
+public:
+  void ConstructParticle () override;
+  void ConstructProcess  () override;
+
+private:
+
+  G4Decay m_decayProcess ;
+  G4UnknownDecay m_unknownDecay ;
+
+};
+
 
 void GiGaMTPhysUnknownParticles::ConstructParticle() {
   G4BcMesonMinus::BcMesonMinusDefinition();
diff --git a/Sim/GaussPhysics/src/particles/GiGaPhysUnknownParticles.h b/Sim/GaussPhysics/src/particles/GiGaPhysUnknownParticles.h
deleted file mode 100755
index c5e2bb7e5..000000000
--- a/Sim/GaussPhysics/src/particles/GiGaPhysUnknownParticles.h
+++ /dev/null
@@ -1,20 +0,0 @@
-#pragma once
-
-#include "Geant4/G4VPhysicsConstructor.hh"
-#include "Geant4/G4Decay.hh"
-#include "Geant4/G4UnknownDecay.hh"
-#include "GiGaMTCoreMessage/IGiGaMessage.h"
-
-class GiGaMTPhysUnknownParticles :public GiGaMessage, public G4VPhysicsConstructor
-{
-
-public:
-  void ConstructParticle () override;
-  void ConstructProcess  () override;
-
-private:
-
-  G4Decay m_decayProcess ;
-  G4UnknownDecay m_unknownDecay ;
-
-};
-- 
GitLab


From 0397e3cc17e06765a2e38ef04cdb1d8e22b303c1 Mon Sep 17 00:00:00 2001
From: Dominik Muller <dominik.muller@cern.ch>
Date: Fri, 27 Sep 2019 10:12:42 +0200
Subject: [PATCH 41/90] Ported most DaughtersInLHCb gencut tools

---
 .../src/DaughtersInLHCbAndCutsForDACP.h       | 106 -----------------
 .../DaughtersInLHCbAndCutsForDinSLBdecays.h   | 102 ----------------
 .../DaughtersInLHCbAndCutsForDstarFromB.cpp   |  62 ----------
 .../src/DaughtersInLHCbAndCutsForDstarFromB.h |  36 ------
 .../src/DaughtersInLHCbAndCutsForLambdacD.h   |  75 ------------
 .../src/DaughtersInLHCbAndCutsForLc3pi.h      |  72 ------------
 Gen/GenCuts/src/DaughtersInLHCbAndFromB.cpp   |  63 ----------
 Gen/GenCuts/src/DaughtersInLHCbAndFromB.h     |  50 --------
 Gen/GenCuts/src/DaughtersInLHCbAndMassCut.h   |  75 ------------
 .../src/DaughtersInLHCbAndWithDaughAndBCuts.h | 100 ----------------
 Gen/GenCuts/src/DaughtersInLHCbAndWithMinP.h  |  65 -----------
 Gen/GenCuts/src_future/DaughtersInLHCb.h      |   1 +
 .../DaughtersInLHCbAndCutsForDACP.cpp         | 109 +++++-------------
 .../DaughtersInLHCbAndCutsForDACP.h           |  73 ++++++++++++
 .../DaughtersInLHCbAndCutsForDinSLBdecays.cpp |  85 +++++---------
 .../DaughtersInLHCbAndCutsForDinSLBdecays.h   |  65 +++++++++++
 .../DaughtersInLHCbAndCutsForDstar.cpp        |  82 +++++--------
 .../DaughtersInLHCbAndCutsForDstar.h          |  33 ++----
 .../DaughtersInLHCbAndCutsForDstarFromB.cpp   |  37 ++++++
 .../DaughtersInLHCbAndCutsForDstarFromB.h     |  30 +++++
 .../DaughtersInLHCbAndCutsForLambdacD.cpp     |  85 +++++---------
 .../DaughtersInLHCbAndCutsForLambdacD.h       |  55 +++++++++
 .../DaughtersInLHCbAndCutsForLc3pi.cpp        |  92 +++++----------
 .../DaughtersInLHCbAndCutsForLc3pi.h          |  55 +++++++++
 .../src_future/DaughtersInLHCbAndFromB.cpp    |  35 ++++++
 .../src_future/DaughtersInLHCbAndFromB.h      |  36 ++++++
 .../DaughtersInLHCbAndMassCut.cpp             |  57 +++------
 .../src_future/DaughtersInLHCbAndMassCut.h    |  56 +++++++++
 .../DaughtersInLHCbAndWithDaughAndBCuts.cpp   |  79 ++++---------
 .../DaughtersInLHCbAndWithDaughAndBCuts.h     |  76 ++++++++++++
 .../DaughtersInLHCbAndWithMinP.cpp            |  47 ++------
 .../src_future/DaughtersInLHCbAndWithMinP.h   |  52 +++++++++
 32 files changed, 780 insertions(+), 1266 deletions(-)
 delete mode 100644 Gen/GenCuts/src/DaughtersInLHCbAndCutsForDACP.h
 delete mode 100644 Gen/GenCuts/src/DaughtersInLHCbAndCutsForDinSLBdecays.h
 delete mode 100644 Gen/GenCuts/src/DaughtersInLHCbAndCutsForDstarFromB.cpp
 delete mode 100644 Gen/GenCuts/src/DaughtersInLHCbAndCutsForDstarFromB.h
 delete mode 100644 Gen/GenCuts/src/DaughtersInLHCbAndCutsForLambdacD.h
 delete mode 100644 Gen/GenCuts/src/DaughtersInLHCbAndCutsForLc3pi.h
 delete mode 100755 Gen/GenCuts/src/DaughtersInLHCbAndFromB.cpp
 delete mode 100755 Gen/GenCuts/src/DaughtersInLHCbAndFromB.h
 delete mode 100755 Gen/GenCuts/src/DaughtersInLHCbAndMassCut.h
 delete mode 100644 Gen/GenCuts/src/DaughtersInLHCbAndWithDaughAndBCuts.h
 delete mode 100644 Gen/GenCuts/src/DaughtersInLHCbAndWithMinP.h
 rename Gen/GenCuts/{src => src_future}/DaughtersInLHCbAndCutsForDACP.cpp (66%)
 create mode 100644 Gen/GenCuts/src_future/DaughtersInLHCbAndCutsForDACP.h
 rename Gen/GenCuts/{src => src_future}/DaughtersInLHCbAndCutsForDinSLBdecays.cpp (68%)
 create mode 100644 Gen/GenCuts/src_future/DaughtersInLHCbAndCutsForDinSLBdecays.h
 rename Gen/GenCuts/{src => src_future}/DaughtersInLHCbAndCutsForDstar.cpp (56%)
 rename Gen/GenCuts/{src => src_future}/DaughtersInLHCbAndCutsForDstar.h (54%)
 create mode 100644 Gen/GenCuts/src_future/DaughtersInLHCbAndCutsForDstarFromB.cpp
 create mode 100644 Gen/GenCuts/src_future/DaughtersInLHCbAndCutsForDstarFromB.h
 rename Gen/GenCuts/{src => src_future}/DaughtersInLHCbAndCutsForLambdacD.cpp (67%)
 create mode 100644 Gen/GenCuts/src_future/DaughtersInLHCbAndCutsForLambdacD.h
 rename Gen/GenCuts/{src => src_future}/DaughtersInLHCbAndCutsForLc3pi.cpp (64%)
 create mode 100644 Gen/GenCuts/src_future/DaughtersInLHCbAndCutsForLc3pi.h
 create mode 100755 Gen/GenCuts/src_future/DaughtersInLHCbAndFromB.cpp
 create mode 100755 Gen/GenCuts/src_future/DaughtersInLHCbAndFromB.h
 rename Gen/GenCuts/{src => src_future}/DaughtersInLHCbAndMassCut.cpp (73%)
 create mode 100755 Gen/GenCuts/src_future/DaughtersInLHCbAndMassCut.h
 rename Gen/GenCuts/{src => src_future}/DaughtersInLHCbAndWithDaughAndBCuts.cpp (66%)
 create mode 100644 Gen/GenCuts/src_future/DaughtersInLHCbAndWithDaughAndBCuts.h
 rename Gen/GenCuts/{src => src_future}/DaughtersInLHCbAndWithMinP.cpp (65%)
 create mode 100644 Gen/GenCuts/src_future/DaughtersInLHCbAndWithMinP.h

diff --git a/Gen/GenCuts/src/DaughtersInLHCbAndCutsForDACP.h b/Gen/GenCuts/src/DaughtersInLHCbAndCutsForDACP.h
deleted file mode 100644
index 3c91a5d4e..000000000
--- a/Gen/GenCuts/src/DaughtersInLHCbAndCutsForDACP.h
+++ /dev/null
@@ -1,106 +0,0 @@
-#ifndef GENCUTS_DAUGHTERSINLHCBANDCUTSFORDACP_H
-#define GENCUTS_DAUGHTERSINLHCBANDCUTSFORDACP_H 1
-
-// Include files
-// from Gaudi
-#include "GaudiAlg/GaudiTool.h"
-
-#include "MCInterfaces/IGenCutTool.h"
-
-/** @class DaughtersInLHCbAndCutsForDACP DaughtersInLHCbAndCutsForDACP.h
- *
- *  Tool to keep events with daughters from signal particles in LHCb
- *  and with cuts on:
- *     (Dst p, D0 pT) plane
- *     (Dst p - D0 p, Dst pT - D0 pT) plane
- *     D0 tau
- *     D0 flight distance from origin vertex
- *     D0 daughter p and pT
- *  Concrete implementation of IGenCutTool.
- *
- *  @author Chris Thomas, based on DaughtersInLHCbAndCutsForDstar
- *  @date   2012-05-14
- */
-class DaughtersInLHCbAndCutsForDACP : public GaudiTool, virtual public IGenCutTool {
- public:
-  /// Standard constructor
-  DaughtersInLHCbAndCutsForDACP( const std::string& type,
-                                 const std::string& name,
-                                 const IInterface* parent);
-
-  virtual ~DaughtersInLHCbAndCutsForDACP( ); ///< Destructor
-
-  /** Accept events with daughters in LHCb and cuts outlined above
-   *  Implements IGenCutTool::applyCut.
-   */
-  bool applyCut( ParticleVector & theParticleVector ,
-                 const HepMC::GenEvent * theEvent ,
-                 const LHCb::GenCollision * theCollision ) const override;
-
- private:
-  /** Study a particle a returns true when all stable daughters
-   *  are in LHCb AndCutsForDACP
-   */
-  bool passCuts( const HepMC::GenParticle * theSignal ) const ;
-
-  /** Momentum Cut function
-   *
-   */
-  bool momentumCut( const HepMC::GenParticle *, double ) const ;
-
-  // Minimum value of angle around z-axis for charged daughters
-  double m_chargedThetaMin ;
-
-  // Maximum value of angle around z-axis for charged daughters
-  double m_chargedThetaMax ;
-
-  // Minimum value of angle around z-axis for neutral daughters
-  double m_neutralThetaMin ;
-
-  // Maximum value of angle around z-axis for neutral daughters
-  double m_neutralThetaMax ;
-
-  //
-  //Cuts on (D* p, D* pT) plane
-  //
-
-  double m_scaleDst ;
-  double m_uDst ;
-  double m_vDst ;
-  double m_sinthetaDst ;
-  double m_costhetaDst ;
-  double m_kDst ;
-
-  //
-  //Cuts on (D* p - D0 p, D* pT - D0 pT) plane
-  //
-
-  double m_scaleDiff ;
-  double m_uDiff ;
-  double m_vDiff ;
-  double m_sinthetaDiff ;
-  double m_costhetaDiff ;
-  double m_kDiff ;
-
-  //
-  //Cut on D0 tau
-  //
-
-  double m_D0_TAU ;
-
-  //
-  //Cut on D0 flight distance from origin vertex
-  //
-
-  double m_D0_FD_ORIVX ;
-
-  //
-  //Cuts on D0 daughter minimum pT, maximum pT and minimum p
-  //
-
-  double m_D0_daugHiPT ;
-  double m_D0_daugLoPT ;
-  double m_D0_daugLoP ;
-
-};
-#endif // GENCUTS_DAUGHTERSINLHCDANDCUTSFORDACP_H
diff --git a/Gen/GenCuts/src/DaughtersInLHCbAndCutsForDinSLBdecays.h b/Gen/GenCuts/src/DaughtersInLHCbAndCutsForDinSLBdecays.h
deleted file mode 100644
index 70dc0725b..000000000
--- a/Gen/GenCuts/src/DaughtersInLHCbAndCutsForDinSLBdecays.h
+++ /dev/null
@@ -1,102 +0,0 @@
-#ifndef GENCUTS_DAUGHTERSINLHCBANDCUTSFORDINSLBDECAYS_H
-#define GENCUTS_DAUGHTERSINLHCBANDCUTSFORDINSLBDECAYS_H 1
-
-// Include files
-// from Gaudi
-#include "GaudiAlg/GaudiTool.h"
-
-#include "MCInterfaces/IGenCutTool.h"
-
-/** @class DaughtersInLHCbAndCutsForDinSLBdecays DaughtersInLHCbAndCutsForDinSLBdecays.h
- *
- *  Tool to keep events with daughters from signal particles
- *  in LHCb and with p and pt cuts on D0 daughters and muon.
- *  Concrete implementation of IGenCutTool.
- *
- *  @author Maurizio Martinelli
- *  @date   2013-08-19
- */
-class DaughtersInLHCbAndCutsForDinSLBdecays : public GaudiTool, virtual public IGenCutTool {
- public:
-  /// Standard constructor
-  DaughtersInLHCbAndCutsForDinSLBdecays( const std::string& type,
-					 const std::string& name,
-					 const IInterface* parent);
-
-  virtual ~DaughtersInLHCbAndCutsForDinSLBdecays( ); ///< Destructor
-
-  /** Accept events with daughters in LHCb and p/pt cuts on D0 daughters
-   *  (defined by min and max angles, different values for charged and neutrals)
-   *  Implements IGenCutTool::applyCut.
-   */
-  bool applyCut( ParticleVector & theParticleVector ,
-                 const HepMC::GenEvent * theEvent ,
-                 const LHCb::GenCollision * theCollision ) const override;
-
- private:
-  /** Study a particle a returns true when all stable daughters
-   *  are in LHCb AndWithMinP
-   */
-  bool passCuts( const HepMC::GenParticle * theSignal ) const ;
-
-  /** Check particle is in LHCb acceptance
-   */
-  bool InLHCbAcceptance( const HepMC::GenParticle * stable, const double firstpz ) const ;
-
-  /** Momentum Cut function
-   */
-  bool momentumCut( const HepMC::GenParticle *, double ) const ;
-
-  /** Calculate proper time
-   */
-  double ProperTime( const HepMC::GenParticle * resonance ) const;
-
-  /**  Minimum value of angle around z-axis for charged daughters
-   */
-  double m_chargedThetaMin ;
-
-  /** Maximum value of angle around z-axis for charged daughters
-   */
-  double m_chargedThetaMax ;
-
-  /** Minimum value of angle around z-axis for neutral daughters
-   */
-  double m_neutralThetaMin ;
-
-  /** Maximum value of angle around z-axis for neutral daughters
-   */
-  double m_neutralThetaMax ;
-
-  /** cut value of minimum (D0mu) invariant mass
-   */
-  double m_md0muMin;
-
-  /** cut value of D0 pt
-   */
-  double m_d0PtMin ;
-
-  /** cut on D0 ctau
-   */
-  double m_d0ctauMin ;
-
-  /** cut value on daughters min pt
-   */
-  double m_daughtersPtMin ;
-
-  /** cut value on daughters max pt
-   */
-  //  double m_daughtersPtMaxCut ;
-
-  /** cut value on daughters min p
-   */
-  double m_daughtersPMin ;
-
-  /** cut value on minimum muon p
-   */
-  double m_muonPMin ;
-
-  /** cut value on minimum muon pt
-   */
-  double m_muonPtMin ;
-};
-#endif // GENCUTS_DAUGHTERSINLHCDANDCUTSFORDINSLBDECAYS_H
diff --git a/Gen/GenCuts/src/DaughtersInLHCbAndCutsForDstarFromB.cpp b/Gen/GenCuts/src/DaughtersInLHCbAndCutsForDstarFromB.cpp
deleted file mode 100644
index 5953ec9f9..000000000
--- a/Gen/GenCuts/src/DaughtersInLHCbAndCutsForDstarFromB.cpp
+++ /dev/null
@@ -1,62 +0,0 @@
-// Include files
-
-// local
-#include "DaughtersInLHCbAndCutsForDstarFromB.h"
-
-// from Kernel
-#include "Kernel/ParticleID.h"
-
-// from Generators
-#include "GenEvent/HepMCUtils.h"
-#include "MCInterfaces/IDecayTool.h"
-
-// from STL
-#include <algorithm>
-
-//-----------------------------------------------------------------------------
-// Implementation file for class : DaughtersInLHCbAndCutsForDstarFromB
-//
-// 2018-03-30 Adam Morris
-//-----------------------------------------------------------------------------
-
-// Declaration of the Tool Factory
-
-DECLARE_COMPONENT( DaughtersInLHCbAndCutsForDstarFromB )
-
-//=============================================================================
-// Standard constructor, initializes variables
-//=============================================================================
-DaughtersInLHCbAndCutsForDstarFromB::DaughtersInLHCbAndCutsForDstarFromB( const std::string& type,
-                                                                          const std::string& name,
-                                                                          const IInterface* parent )
-  : DaughtersInLHCbAndCutsForDstar( type, name, parent ) {
-  declareInterface< IGenCutTool >( this ) ;
-}
-
-
-//=============================================================================
-// initialize
-//=============================================================================
-StatusCode DaughtersInLHCbAndCutsForDstarFromB::initialize()
-{
-  const StatusCode sc = DaughtersInLHCb::initialize();
-  if ( sc.isFailure() ) return sc;
-
-  // load the tool to check if the signal is ultimately from a b
-  m_fromBcuts = tool<IGenCutTool>( "SignalIsFromBDecay", this );
-
-  return sc;
-}
-
-//=============================================================================
-// Acceptance function
-//=============================================================================
-bool DaughtersInLHCbAndCutsForDstarFromB::applyCut( ParticleVector & theParticleVector ,
-                                                    const HepMC::GenEvent * theEvent ,
-                                                    const LHCb::GenCollision * theHardInfo )
-  const
-{
-  return ( m_fromBcuts->applyCut(theParticleVector,theEvent,theHardInfo) &&
-           DaughtersInLHCbAndCutsForDstar::applyCut(theParticleVector,theEvent,theHardInfo) );
-}
-
diff --git a/Gen/GenCuts/src/DaughtersInLHCbAndCutsForDstarFromB.h b/Gen/GenCuts/src/DaughtersInLHCbAndCutsForDstarFromB.h
deleted file mode 100644
index 46c057858..000000000
--- a/Gen/GenCuts/src/DaughtersInLHCbAndCutsForDstarFromB.h
+++ /dev/null
@@ -1,36 +0,0 @@
-#ifndef GENCUTS_DAUGHTERSINLHCBANDCUTSFORDSTARFROMB_H
-#define GENCUTS_DAUGHTERSINLHCBANDCUTSFORDSTARFROMB_H 1
-
-// Include files
-#include "DaughtersInLHCbAndCutsForDstar.h"
-
-/** @class DaughtersInLHCbAndCutsForDstarFromB DaughtersInLHCbAndCutsForDstarFromB.h
- *
- *  Tool to select D* particles from a b-hadron with pT cuts
- *
- *  @author Adam Morris
- *  @date   2018-03-30
- */
-class DaughtersInLHCbAndCutsForDstarFromB : public DaughtersInLHCbAndCutsForDstar, virtual public IGenCutTool {
-public:
-  /// Standard constructor
-  DaughtersInLHCbAndCutsForDstarFromB( const std::string & type,
-                                     const std::string & name,
-                                     const IInterface * parent ) ;
-
-  /// Initialization
-  StatusCode initialize() override;
-
-  /** Check that the signal D* satisfies the cuts in
-   *  SignalIsFromBDecay and DaughtersInLHCbAndCutsForDstar.
-   *  Implements IGenCutTool::applyCut.
-   */
-  bool applyCut( ParticleVector & theParticleVector,
-                 const HepMC::GenEvent * theEvent,
-                 const LHCb::GenCollision * theCollision ) const override;
-
-private:
-  /// From a b cut tool
-  const IGenCutTool * m_fromBcuts = nullptr;
-} ;
-#endif // GENCUTS_DAUGHTERSINLHCBANDCUTSFORDSTARFROMB_H
diff --git a/Gen/GenCuts/src/DaughtersInLHCbAndCutsForLambdacD.h b/Gen/GenCuts/src/DaughtersInLHCbAndCutsForLambdacD.h
deleted file mode 100644
index a5ff53fce..000000000
--- a/Gen/GenCuts/src/DaughtersInLHCbAndCutsForLambdacD.h
+++ /dev/null
@@ -1,75 +0,0 @@
-#ifndef GENCUTS_DAUGHTERSINLHCBANDCUTSFORLCD_H
-#define GENCUTS_DAUGHTERSINLHCBANDCUTSFORLCD_H 1
-
-// Include files
-// from Gaudi
-#include "GaudiAlg/GaudiTool.h"
-
-#include "MCInterfaces/IGenCutTool.h"
-
-/** @class DaughtersInLHCbAndCutsForLambdac DaughtersInLHCbAndCutsForLambdacD.h
- *
- *  Tool to keep events with daughters from signal particles
- *  in LHCb and with p and pt cuts on Lambda_c daughters.
- *  Concrete implementation of IGenCutTool.
- *
- *  @author Patrick Robbe
- *  @date   2012-02-07
- */
-class DaughtersInLHCbAndCutsForLambdacD : public GaudiTool, virtual public IGenCutTool {
-public:
-  /// Standard constructor
-  DaughtersInLHCbAndCutsForLambdacD( const std::string& type,
-                                     const std::string& name,
-                                     const IInterface* parent);
-
-  virtual ~DaughtersInLHCbAndCutsForLambdacD( ); ///< Destructor
-
-  /** Accept events with daughters in LHCb and p/pt cuts on Lambda_c daughters
-   *  (defined by min and max angles, different values for charged and neutrals)
-   *  Implements IGenCutTool::applyCut.
-   */
-  bool applyCut( ParticleVector & theParticleVector ,
-                 const HepMC::GenEvent * theEvent ,
-                 const LHCb::GenCollision * theCollision ) const override;
-
-private:
-  /** Study a particle a returns true when all stable daughters
-   *  are in LHCb AndWithMinP
-   */
-  bool passCuts( const HepMC::GenParticle * theSignal ) const ;
-
-  /** Momentum Cut function
-   *
-   */
-  bool momentumCut( const HepMC::GenParticle *, double ) const ;
-
-  // Minimum value of angle around z-axis for charged daughters
-  double m_chargedThetaMin ;
-
-  // Maximum value of angle around z-axis for charged daughters
-  double m_chargedThetaMax ;
-
-  // Minimum value of angle around z-axis for neutral daughters
-  double m_neutralThetaMin ;
-
-  // Maximum value of angle around z-axis for neutral daughters
-  double m_neutralThetaMax ;
-
-  // cut value of Lambda_c pt
-  double m_lcptCut ;
-
-  // cut value on daughters min pt
-  double m_daughtersptminCut ;
-
-  // cut value on daughters max pt
-  double m_daughtersptmaxCut ;
-
-  // cut value on daughters min p
-  double m_daughterspminCut ;
-
-
-  // cut on Lambda_c ctau
-  double m_lcctauCut ;
-};
-#endif // GENCUTS_DAUGHTERSINLHCDANDCUTSFORDSTARD_H
diff --git a/Gen/GenCuts/src/DaughtersInLHCbAndCutsForLc3pi.h b/Gen/GenCuts/src/DaughtersInLHCbAndCutsForLc3pi.h
deleted file mode 100644
index c81a1b239..000000000
--- a/Gen/GenCuts/src/DaughtersInLHCbAndCutsForLc3pi.h
+++ /dev/null
@@ -1,72 +0,0 @@
-#ifndef GENCUTS_DAUGHTERSINLHCBANDCUTSFORLC3PI_H
-#define GENCUTS_DAUGHTERSINLHCBANDCUTSFORLC3PI_H 1
-
-// Include files
-// from Gaudi
-#include "GaudiAlg/GaudiTool.h"
-
-#include "MCInterfaces/IGenCutTool.h"
-
-/** @class DaughtersInLHCbAndCutsForLc DaughtersInLHCbAndCutsForLc3pi.h
- *
- *  Tool to keep events with daughters from signal particles
- *  in LHCb and with p and pt cuts on Lc daughters.
- *  Concrete implementation of IGenCutTool.
- *
- *  @author Patrick Robbe
- *  @date   2012-02-07
- */
-class DaughtersInLHCbAndCutsForLc3pi : public GaudiTool, virtual public IGenCutTool {
-public:
-  /// Standard constructor
-  DaughtersInLHCbAndCutsForLc3pi( const std::string& type,
-                                     const std::string& name,
-                                     const IInterface* parent);
-
-  virtual ~DaughtersInLHCbAndCutsForLc3pi( ); ///< Destructor
-
-  /** Accept events with daughters in LHCb and p/pt cuts on Lc daughters
-   *  (defined by min and max angles, different values for charged and neutrals)
-   *  Implements IGenCutTool::applyCut.
-   */
-  bool applyCut( ParticleVector & theParticleVector ,
-                 const HepMC::GenEvent * theEvent ,
-                 const LHCb::GenCollision * theCollision ) const override;
-
-private:
-  /** Study a particle a returns true when all stable daughters
-   *  are in LHCb AndWithMinP
-   */
-  bool passCuts( const HepMC::GenParticle * theSignal ) const ;
-
-  /** Momentum Cut function
-   *
-   */
-  bool momentumCut( const HepMC::GenParticle *, double ) const ;
-
-  // Minimum value of angle around z-axis for charged daughters
-  double m_chargedThetaMin ;
-
-  // Maximum value of angle around z-axis for charged daughters
-  double m_chargedThetaMax ;
-
-  // Minimum value of angle around z-axis for neutral daughters
-  double m_neutralThetaMin ;
-
-  // Maximum value of angle around z-axis for neutral daughters
-  double m_neutralThetaMax ;
-
-  // cut value of Lc pt
-  double m_lcptCut ;
-
-  // cut value on daughters min pt
-  double m_daughtersptminCut ;
-
-  // cut value on daughters max pt
-  double m_daughtersptmaxCut ;
-
-  // cut value on daughters min p
-  double m_daughterspminCut ;
-
- };
-#endif // GENCUTS_DAUGHTERSINLHCDANDCUTSFORLC3PI_H
diff --git a/Gen/GenCuts/src/DaughtersInLHCbAndFromB.cpp b/Gen/GenCuts/src/DaughtersInLHCbAndFromB.cpp
deleted file mode 100755
index d2c433405..000000000
--- a/Gen/GenCuts/src/DaughtersInLHCbAndFromB.cpp
+++ /dev/null
@@ -1,63 +0,0 @@
-// $Id: DaughtersInLHCbAndFromB.cpp,v 1.1 2007-11-26 13:44:34 jonrob Exp $
-// Include files
-
-// local
-#include "DaughtersInLHCbAndFromB.h"
-
-// from Gaudi
-
-// from HepMC
-#include "HepMC/GenParticle.h"
-#include "HepMC/GenVertex.h"
-
-// Kernel
-#include "Kernel/ParticleID.h"
-
-//-----------------------------------------------------------------------------
-// Implementation file for class : DaughtersInLHCbAndFromB
-//
-// 22/11/2007 : Chris Jones
-//-----------------------------------------------------------------------------
-
-// Declaration of the Tool Factory
-DECLARE_COMPONENT( DaughtersInLHCbAndFromB )
-
-//=============================================================================
-// Standard constructor, initializes variables
-//=============================================================================
-DaughtersInLHCbAndFromB::DaughtersInLHCbAndFromB( const std::string& type,
-                                                  const std::string& name,
-                                                  const IInterface* parent )
-  : DaughtersInLHCb ( type, name , parent ),
-    m_fromBcuts     ( NULL                ) { }
-
-//=============================================================================
-// Destructor
-//=============================================================================
-DaughtersInLHCbAndFromB::~DaughtersInLHCbAndFromB( ) { }
-
-//=============================================================================
-// initialize
-//=============================================================================
-StatusCode DaughtersInLHCbAndFromB::initialize()
-{
-  const StatusCode sc = DaughtersInLHCb::initialize();
-  if ( sc.isFailure() ) return sc;
-  
-  // load the tool to check if the signal is ultimately from a b
-  m_fromBcuts = tool<IGenCutTool>( "SignalIsFromBDecay", this );
-
-  return sc;
-}
-
-//=============================================================================
-// Acceptance function
-//=============================================================================
-bool DaughtersInLHCbAndFromB::applyCut( ParticleVector & theParticleVector ,
-                                        const HepMC::GenEvent * theEvent ,
-                                        const LHCb::GenCollision * theHardInfo )
-  const
-{
-  return ( m_fromBcuts->applyCut(theParticleVector,theEvent,theHardInfo) && 
-           DaughtersInLHCb::applyCut(theParticleVector,theEvent,theHardInfo) );
-}
diff --git a/Gen/GenCuts/src/DaughtersInLHCbAndFromB.h b/Gen/GenCuts/src/DaughtersInLHCbAndFromB.h
deleted file mode 100755
index 7b76b94f0..000000000
--- a/Gen/GenCuts/src/DaughtersInLHCbAndFromB.h
+++ /dev/null
@@ -1,50 +0,0 @@
-// $Id: DaughtersInLHCbAndFromB.h,v 1.1 2007-11-26 13:44:34 jonrob Exp $
-#ifndef GENCUTS_DAUGHTERSINLHCBANDFROMB_H
-#define GENCUTS_DAUGHTERSINLHCBANDFROMB_H 1
-
-// Include files
-#include "DaughtersInLHCb.h"
-
-/** @class DaughtersInLHCbAndFromB DaughtersInLHCbAndFromB.h
- *
- *  Inherits from DaughtersInLHCb adding the additional requirement that
- *  the signal be from a b decay.
- *
- *  Concrete implementation of IGenCutTool.
- *
- *  @author Chris Jones
- *  @date   22/11/2007
- */
-
-class DaughtersInLHCbAndFromB : public DaughtersInLHCb,
-                                virtual public IGenCutTool
-{
-
-public:
-
-  /// Standard constructor
-  DaughtersInLHCbAndFromB( const std::string& type,
-                           const std::string& name,
-                           const IInterface* parent);
-
-  virtual ~DaughtersInLHCbAndFromB( ); ///< Destructor
-
-  /// Initialization
-  StatusCode initialize() override;
-
-  /** Accept events with daughters in LHCb acceptance (defined by min and
-   *  max angles, different values for charged and neutrals)
-   *  Implements IGenCutTool::applyCut.
-   */
-  bool applyCut( ParticleVector & theParticleVector ,
-                 const HepMC::GenEvent * theEvent ,
-                 const LHCb::GenCollision * theCollision ) const override;
-
-private: // data
-
-  /// From a b cut tool
-  const IGenCutTool * m_fromBcuts;
-
-};
-
-#endif // GENCUTS_DAUGHTERSINLHCBANDFROMB_H
diff --git a/Gen/GenCuts/src/DaughtersInLHCbAndMassCut.h b/Gen/GenCuts/src/DaughtersInLHCbAndMassCut.h
deleted file mode 100755
index 4971551cc..000000000
--- a/Gen/GenCuts/src/DaughtersInLHCbAndMassCut.h
+++ /dev/null
@@ -1,75 +0,0 @@
-// $Id: DaughtersInLHCbAndMassCut.h,v 1.4 2008-05-29 14:21:59 gcorti Exp $
-#ifndef GENCUTS_DAUGHTERSINLHCBANDMASSCUT_H
-#define GENCUTS_DAUGHTERSINLHCBANDMASSCUT_H 1
-
-// Include files
-// from Gaudi
-#include "GaudiAlg/GaudiTool.h"
-
-#include "MCInterfaces/IGenCutTool.h"
-#include "GaudiKernel/Transform4DTypes.h"
-
-/** @class DaughtersInLHCbAndMassCut DaughtersInLHCbAndMassCut.h
- *
- *  Tool to keep events with daughters from signal particles
- *  in LHCb acceptance.
- *  Concrete implementation of IGenCutTool.
- *
- *  @author Patrick Robbe
- *  @date   2005-08-24
- */
-class DaughtersInLHCbAndMassCut : public GaudiTool, virtual public IGenCutTool {
-public:
-  /// Standard constructor
-  DaughtersInLHCbAndMassCut( const std::string& type,
-                             const std::string& name,
-                             const IInterface* parent);
-
-  virtual ~DaughtersInLHCbAndMassCut( ); ///< Destructor
-
-  /** Accept events with daughters in LHCb acceptance (defined by min and
-   *  max angles, different values for charged and neutrals)
-   *  Implements IGenCutTool::applyCut.
-   */
-  bool applyCut( ParticleVector & theParticleVector ,
-                 const HepMC::GenEvent * theEvent ,
-                 const LHCb::GenCollision * theCollision ) const override;
-
- private:
-  /** Study a particle a returns true when all stable daughters
-   *  are in LHCb acceptance
-   */
-  bool passCuts( const HepMC::GenParticle * theSignal ) const ;
-
-  /** Minimum value of angle around z-axis for charged daughters
-   * (set by options)
-   */
-  double m_chargedThetaMin ;
-
-  /** Maximum value of angle around z-axis for charged daughters
-   * (set by options)
-   */
-  double m_chargedThetaMax ;
-
-  /** Minimum value of angle around z-axis for neutral daughters
-   * (set by options)
-   */
-  double m_neutralThetaMin ;
-
-  /** Maximum value of angle around z-axis for neutral daughters
-   * (set by options)
-   */
-  double m_neutralThetaMax ;
-
-  int m_LeptonOneID;
-  int m_LeptonTwoID;
-  int m_HadronOneABSID;
-  int m_HadronTwoABSID;
-
-  double m_DausPTMin;
-  double m_eeMassMax;
-  double m_eeKstarMassMin;
-
-
-};
-#endif // GENCUTS_DAUGHTERSINLHCB_H
diff --git a/Gen/GenCuts/src/DaughtersInLHCbAndWithDaughAndBCuts.h b/Gen/GenCuts/src/DaughtersInLHCbAndWithDaughAndBCuts.h
deleted file mode 100644
index a953ffd94..000000000
--- a/Gen/GenCuts/src/DaughtersInLHCbAndWithDaughAndBCuts.h
+++ /dev/null
@@ -1,100 +0,0 @@
-// $Id: DaughtersInLHCbAndWithKSCutsAndWithMinPAndPT.h,v 1.4 2008-05-29 14:21:59 gcorti Exp $
-#ifndef GENCUTS_DAUGHTERSINLHCBAndWithDaughAndBCuts_H
-#define GENCUTS_DAUGHTERSINLHCBAndWithDaughAndBCuts_H 1
-
-// Include files
-// from Gaudi
-#include "GaudiAlg/GaudiTool.h"
-
-#include "MCInterfaces/IGenCutTool.h"
-#include "GaudiKernel/Transform4DTypes.h"
-
-/** @class DaughtersInLHCbAndWithDaughAndBCuts DaughtersInLHCbAndWithDaughAndBCuts.h
- *
- *  Tool to keep events with daughters from signal particles
- *  in LHCb AndWithMinP.
- *  Concrete implementation of IGenCutTool.
- *
- *  @author Alex Shires
- *  @date   2011-03-02
- */
-class DaughtersInLHCbAndWithDaughAndBCuts : public GaudiTool, virtual public IGenCutTool {
- public:
-  /// Standard constructor
-  DaughtersInLHCbAndWithDaughAndBCuts( const std::string& type,
-                  const std::string& name,
-                  const IInterface* parent);
-
-  virtual ~DaughtersInLHCbAndWithDaughAndBCuts( ); ///< Destructor
-
-  /** Accept events with daughters in LHCb AndWithMinP (defined by min and
-   *  max angles, different values for charged and neutrals)
-   *  Implements IGenCutTool::applyCut.
-   */
-  bool applyCut( ParticleVector & theParticleVector ,
-                 const HepMC::GenEvent * theEvent ,
-                 const LHCb::GenCollision * theCollision ) const override;
-
- private:
-  /** Study a particle a returns true when all stable daughters
-   *  are in LHCb AndWithMinP
-   */
-  bool passCuts( const HepMC::GenParticle * theSignal ) const ;
-
-  /** Flight Distance Cut function
-   *
-   */
-  bool flightCut( const HepMC::GenParticle * , double ) const ;
-
-  /** Momentum Cut function
-   *
-   */
-  bool momentumCut( const HepMC::GenParticle *p, const double pMin, double& sumP) const ;
-
-  /** Transverse Momentum Cut function
-   *
-   */
-  bool transverseMomentumCut( const HepMC::GenParticle *p, const double pTMin, double& sumPt) const ;
-
-  // Minimum value of angle around z-axis for charged daughters
-  double m_chargedThetaMin ;
-
-  // Maximum value of angle around z-axis for charged daughters
-  double m_chargedThetaMax ;
-
-  // Minimum value of angle around z-axis for neutral daughters
-  double m_neutralThetaMin ;
-
-  // Maximum value of angle around z-axis for neutral daughters
-  double m_neutralThetaMax ;
-
-  // Minimum value of angle around z-axis for a KS/Lambda
-  double m_llThetaMin ;
-
-  // Maximum value of angle around z-axis for a KS/Lambda
-  double m_llThetaMax ;
-
-  //min value of momentum
-  double m_minMuonP;
-  double m_minTrackP;
-  double m_minLongLivedP;
-	double m_minLongLivedDaughP;
-  double m_minBP;
-
-  //min value of trnasverse momentum
-  double m_minMuonPT;
-  double m_minTrackPT;
-  double m_minLongLivedPT;
-double m_minLongLivedDaughPT;
-  double m_minBPT;
-
-  //flight distance
-  double m_minBFD;
-
-	// sum of Pt and P
-	double m_minSumP;
-  double m_minSumPT;
-
-
-};
-#endif // GENCUTS_DAUGHTERSINLHCBAndWithDaughAndBCuts_H
diff --git a/Gen/GenCuts/src/DaughtersInLHCbAndWithMinP.h b/Gen/GenCuts/src/DaughtersInLHCbAndWithMinP.h
deleted file mode 100644
index 712462e8e..000000000
--- a/Gen/GenCuts/src/DaughtersInLHCbAndWithMinP.h
+++ /dev/null
@@ -1,65 +0,0 @@
-// $Id: DaughtersInLHCbAndWithMinP.h,v 1.4 2008-05-29 14:21:59 gcorti Exp $
-#ifndef GENCUTS_DAUGHTERSINLHCBAndWithMinP_H
-#define GENCUTS_DAUGHTERSINLHCBAndWithMinP_H 1
-
-// Include files
-// from Gaudi
-#include "GaudiAlg/GaudiTool.h"
-
-#include "MCInterfaces/IGenCutTool.h"
-#include "GaudiKernel/Transform4DTypes.h"
-
-/** @class DaughtersInLHCbAndWithMinP DaughtersInLHCbAndWithMinP.h
- *
- *  Tool to keep events with daughters from signal particles
- *  in LHCb AndWithMinP.
- *  Concrete implementation of IGenCutTool.
- *
- *  @author Alex Shires
- *  @date   2011-03-02
- */
-class DaughtersInLHCbAndWithMinP : public GaudiTool, virtual public IGenCutTool {
- public:
-  /// Standard constructor
-  DaughtersInLHCbAndWithMinP( const std::string& type,
-                  const std::string& name,
-                  const IInterface* parent);
-
-  virtual ~DaughtersInLHCbAndWithMinP( ); ///< Destructor
-
-  /** Accept events with daughters in LHCb AndWithMinP (defined by min and
-   *  max angles, different values for charged and neutrals)
-   *  Implements IGenCutTool::applyCut.
-   */
-  bool applyCut( ParticleVector & theParticleVector ,
-                 const HepMC::GenEvent * theEvent ,
-                 const LHCb::GenCollision * theCollision ) const override;
-
- private:
-  /** Study a particle a returns true when all stable daughters
-   *  are in LHCb AndWithMinP
-   */
-  bool passCuts( const HepMC::GenParticle * theSignal ) const ;
-
-  /** Momentum Cut function
-   *
-   */
-  bool momentumCut( const HepMC::GenParticle *, double ) const ;
-
-  // Minimum value of angle around z-axis for charged daughters
-  double m_chargedThetaMin ;
-
-  // Maximum value of angle around z-axis for charged daughters
-  double m_chargedThetaMax ;
-
-  // Minimum value of angle around z-axis for neutral daughters
-  double m_neutralThetaMin ;
-
-  // Maximum value of angle around z-axis for neutral daughters
-  double m_neutralThetaMax ;
-
-    //min value of momentum
-    double m_minMuonP;
-    double m_minTrackP;
-};
-#endif // GENCUTS_DAUGHTERSINLHCBAndWithMinP_H
diff --git a/Gen/GenCuts/src_future/DaughtersInLHCb.h b/Gen/GenCuts/src_future/DaughtersInLHCb.h
index a7da36cb5..fe28ce8e5 100755
--- a/Gen/GenCuts/src_future/DaughtersInLHCb.h
+++ b/Gen/GenCuts/src_future/DaughtersInLHCb.h
@@ -25,6 +25,7 @@ class DaughtersInLHCb : public extends<GaudiTool, IGenCutTool> {
   /// Standard constructor
   using extends::extends;
   typedef std::vector< HepMC3::GenParticlePtr > ParticleVector ;
+  virtual ~DaughtersInLHCb() = default;
 
   /** Accept events with daughters in LHCb acceptance (defined by min and
    *  max angles, different values for charged and neutrals)
diff --git a/Gen/GenCuts/src/DaughtersInLHCbAndCutsForDACP.cpp b/Gen/GenCuts/src_future/DaughtersInLHCbAndCutsForDACP.cpp
similarity index 66%
rename from Gen/GenCuts/src/DaughtersInLHCbAndCutsForDACP.cpp
rename to Gen/GenCuts/src_future/DaughtersInLHCbAndCutsForDACP.cpp
index b5ce9bf84..ba701c35e 100644
--- a/Gen/GenCuts/src/DaughtersInLHCbAndCutsForDACP.cpp
+++ b/Gen/GenCuts/src_future/DaughtersInLHCbAndCutsForDACP.cpp
@@ -13,8 +13,9 @@
 #include "GaudiKernel/Vector4DTypes.h"
 
 // from HepMC
-#include "HepMC/GenParticle.h"
-#include "HepMC/GenVertex.h"
+#include "HepMC3/GenParticle.h"
+#include "HepMC3/GenVertex.h"
+#include "HepMC3/Relatives.h"
 
 // from Generators
 #include "GenEvent/HepMCUtils.h"
@@ -29,53 +30,11 @@
 
 DECLARE_COMPONENT( DaughtersInLHCbAndCutsForDACP )
 
-
-//=============================================================================
-// Standard constructor, initializes variables
-//=============================================================================
-DaughtersInLHCbAndCutsForDACP::DaughtersInLHCbAndCutsForDACP( const std::string& type,
-                                                              const std::string& name,
-                                                              const IInterface* parent )
-  : GaudiTool ( type, name , parent ) {
-  declareInterface< IGenCutTool >( this ) ;
-  declareProperty( "ChargedThetaMin"   , m_chargedThetaMin   = 10 * Gaudi::Units::mrad ) ;
-  declareProperty( "ChargedThetaMax"   , m_chargedThetaMax   = 400 * Gaudi::Units::mrad ) ;
-  declareProperty( "NeutralThetaMin"   , m_neutralThetaMin   = 5 * Gaudi::Units::mrad ) ;
-  declareProperty( "NeutralThetaMax"   , m_neutralThetaMax   = 400 * Gaudi::Units::mrad ) ;
-  //
-  declareProperty( "ScaleDst"          , m_scaleDst          = 0.1 ) ; //scaling between p and pT ranges
-  declareProperty( "uDst"              , m_uDst              = 6000.0 * Gaudi::Units::MeV ) ; //x-coordinate of parabola base
-  declareProperty( "vDst"              , m_vDst              = 60000.0 * Gaudi::Units::MeV ) ; //y-coordinate of parabola base
-  //angle of rotation of parabola from vertical = thetaDst = 37.0 degrees
-  declareProperty( "costhetaDst"       , m_costhetaDst       = 0.798636 ) ;
-  declareProperty( "sinthetaDst"       , m_sinthetaDst       = 0.601815 ) ;
-  declareProperty( "kDst"              , m_kDst              = 0.00009 ) ; //roughly proportional to inverse width of parabbola
-  //
-  declareProperty( "ScaleDiff"         , m_scaleDiff         = 0.1 ) ; //scaling between x and y axes
-  declareProperty( "uDiff"             , m_uDiff             = 400.0 * Gaudi::Units::MeV ) ; //x-coordinate of parabola base
-  declareProperty( "vDiff"             , m_vDiff             = 4500.0 * Gaudi::Units::MeV ) ; //y-coordinate of parabola base
-  //angle of rotation of parabola from vertical = thetaDiff = 38.0 degrees
-  declareProperty( "costhetaDiff"      , m_costhetaDiff      = 0.788011 ) ;
-  declareProperty( "sinthetaDiff"      , m_sinthetaDiff      = 0.615661 ) ;
-  declareProperty( "kDiff"             , m_kDiff             = 0.0014 ) ; //roughly proportional to inverse width of parabola
-  //  
-  declareProperty( "D0_TAU"            , m_D0_TAU            = 0.0005 * Gaudi::Units::ns ) ;
-  declareProperty( "D0_FD_ORIVX"       , m_D0_FD_ORIVX       = 5.0 * Gaudi::Units::mm ) ;
-  declareProperty( "D0_daug_HiPT"      , m_D0_daugHiPT       = 3000.0 * Gaudi::Units::MeV ) ;
-  declareProperty( "D0_daug_LoPT"      , m_D0_daugLoPT       = 1000.0 * Gaudi::Units::MeV ) ;
-  declareProperty( "D0_daug_LoP"       , m_D0_daugLoP        = 5000.0 * Gaudi::Units::MeV ) ;
-}
-
-//=============================================================================
-// Destructor 
-//=============================================================================
-DaughtersInLHCbAndCutsForDACP::~DaughtersInLHCbAndCutsForDACP( ) { ; }
-
 //=============================================================================
 // AndWithMinP function
 //=============================================================================
 bool DaughtersInLHCbAndCutsForDACP::applyCut( ParticleVector & theParticleVector ,
-                                              const HepMC::GenEvent * /* theEvent */ ,
+                                              const HepMC3::GenEvent * /* theEvent */ ,
                                               const LHCb::GenCollision * /* theHardInfo */ )
   const {
   ParticleVector::iterator it ;
@@ -96,32 +55,29 @@ bool DaughtersInLHCbAndCutsForDACP::applyCut( ParticleVector & theParticleVector
 //=============================================================================
 // Functions to test if all daughters are in acceptance
 //=============================================================================
-bool DaughtersInLHCbAndCutsForDACP::passCuts( const HepMC::GenParticle * theSignal ) const {
-  HepMC::GenVertex * EV = theSignal -> end_vertex() ;
+bool DaughtersInLHCbAndCutsForDACP::passCuts( const HepMC3::GenParticlePtr theSignal ) const {
+  auto EV = theSignal -> end_vertex() ;
   if ( 0 == EV ) return true ;
 
-  typedef std::vector< HepMC::GenParticle * > Particles ;
+  typedef std::vector< HepMC3::GenParticlePtr > Particles ;
   Particles stables ;
-  HepMC::GenParticle * theSoftPion( 0 ) ;
-  HepMC::GenParticle * theD0( 0 ) ;
-  HepMC::GenParticle * theDst( 0 ) ; //specifically want a Dst instead of just a "parent"
-  HepMC::GenParticle * theParent( 0 );
+  HepMC3::GenParticlePtr theSoftPion{nullptr} ;
+  HepMC3::GenParticlePtr theD0{nullptr} ;
+  HepMC3::GenParticlePtr theDst{nullptr} ; //specifically want a Dst instead of just a "parent"
+  HepMC3::GenParticlePtr theParent{nullptr};
   Particles d0daughters ;
   
-  HepMC::GenVertex::particle_iterator iter ;
-
-  for ( iter = EV -> particles_begin( HepMC::descendants ) ; 
-        iter != EV -> particles_end( HepMC::descendants ) ; ++iter ) {
+  for (auto desc : HepMC3::Relatives::DESCENDANTS(theSignal)) {
     // Fill all daughters
-    if ( 0 == (*iter) -> end_vertex() ) stables.push_back( *iter ) ;
+    if ( !desc -> end_vertex() ) stables.push_back( desc ) ;
 
     // The D0
-    if ( abs( (*iter) -> pdg_id() ) == 421 ) theD0 = (*iter) ;
+    if ( abs( desc -> pdg_id() ) == 421 ) theD0 = desc ;
 
     // The soft pion
-    theParent = *( (*iter) -> production_vertex() -> particles_in_const_begin() ) ;
-    if ( ( 413 == abs( theParent -> pdg_id() ) ) && ( 211 == abs( (*iter) -> pdg_id() ) ) )
-      theSoftPion = (*iter) ;
+    theParent = *std::cbegin( desc -> production_vertex() -> particles_in() ) ;
+    if ( ( 413 == abs( theParent -> pdg_id() ) ) && ( 211 == abs( desc -> pdg_id() ) ) )
+      theSoftPion = desc ;
 
     // The Dst
     if ( 413 == abs( theParent -> pdg_id() ) )
@@ -129,29 +85,28 @@ bool DaughtersInLHCbAndCutsForDACP::passCuts( const HepMC::GenParticle * theSign
     
   }
 
-  if ( 0 == theDst )
+  if ( !theDst )
     Exception( "No Dst in the signal decay chain !" ) ;
 
-  if ( 0 == theD0 )
+  if ( !theD0 )
     Exception( "No D0 in the signal decay chain !" ) ;
 
   if ( stables.empty() )
     Exception( "Signal has no stable daughters !" ) ;
 
-  if ( 0 == theSoftPion ) 
+  if ( !theSoftPion ) 
     Exception( "No soft pion in the decay chain !" ) ;  
 
   // daughters of D0
   EV = theD0 -> end_vertex() ;
-  if ( 0 == EV ) 
+  if ( !EV ) 
     Exception( "The D0 has no daughters" ) ;
   
-  for ( iter = EV -> particles_begin( HepMC::descendants ) ; 
-        iter != EV -> particles_end( HepMC::descendants ) ; ++iter ) {
+  for (auto desc : HepMC3::Relatives::DESCENDANTS(EV)) {
     // Fill all daughters but exclude photons (can be radiative photons)
-    if ( 0 == (*iter) -> end_vertex() )
-      if ( 22 != (*iter) -> pdg_id() ) 
-        d0daughters.push_back( *iter ) ;
+    if ( !desc -> end_vertex() )
+      if ( 22 != desc -> pdg_id() ) 
+        d0daughters.push_back( desc ) ;
   }
 
   if ( d0daughters.empty() )
@@ -175,9 +130,9 @@ bool DaughtersInLHCbAndCutsForDACP::passCuts( const HepMC::GenParticle * theSign
          ( 16 == abs( (*it) -> pdg_id() ) ) ) continue ;
  
     // Don't use daughters of Lambda and KS:
-    HepMC::GenParticle * theParent ;
+    HepMC3::GenParticlePtr theParent ;
     theParent = 
-      *( (*it) -> production_vertex() -> particles_in_const_begin() ) ;
+      *std::cbegin( (*it) -> production_vertex() -> particles_in() ) ;
     if ( 3122 == abs( theParent -> pdg_id() ) ) continue ;
     if ( 310 == theParent -> pdg_id() ) continue ;
 
@@ -240,13 +195,13 @@ bool DaughtersInLHCbAndCutsForDACP::passCuts( const HepMC::GenParticle * theSign
   for ( Particles::const_iterator it = d0daughters.begin() ; it != d0daughters.end() ;
         ++it ) {  
     debug() << "Daughter pT = " << (*it) -> momentum().perp() 
-            << " p = " << (*it) -> momentum().rho() << endmsg ;
+            << " p = " << (*it) -> momentum().p3mod() << endmsg ;
     if ( (*it) -> momentum().perp() > maxpt ) 
       maxpt = (*it) -> momentum().perp() ;
     if ( (*it) -> momentum().perp() < minpt ) 
       minpt = (*it) -> momentum().perp() ;
-    if ( (*it) -> momentum().rho() < minp ) 
-      minp = (*it) -> momentum().rho() ;
+    if ( (*it) -> momentum().p3mod() < minp ) 
+      minp = (*it) -> momentum().p3mod() ;
   }
 
   debug() << "Min Pt = "  << minpt
@@ -261,7 +216,7 @@ bool DaughtersInLHCbAndCutsForDACP::passCuts( const HepMC::GenParticle * theSign
   //Cut on (Dst p, Dst pT) plane
   //
 
-  double Dstp = theDst -> momentum().rho() ;
+  double Dstp = theDst -> momentum().p3mod() ;
   double DstpT = theDst -> momentum().perp() ;
   
   debug() << "Dst p = " << Dstp << endmsg ;
@@ -282,7 +237,7 @@ bool DaughtersInLHCbAndCutsForDACP::passCuts( const HepMC::GenParticle * theSign
   //Cut on (Dst p - D0 p, Dst pT - D0 pT) plane
   //
 
-  double D0p = theD0 -> momentum().rho() ;
+  double D0p = theD0 -> momentum().p3mod() ;
   double D0pT = theD0 -> momentum().perp() ;
 
   debug() << "D0 p = " << D0p << endmsg ;
diff --git a/Gen/GenCuts/src_future/DaughtersInLHCbAndCutsForDACP.h b/Gen/GenCuts/src_future/DaughtersInLHCbAndCutsForDACP.h
new file mode 100644
index 000000000..e72c3a684
--- /dev/null
+++ b/Gen/GenCuts/src_future/DaughtersInLHCbAndCutsForDACP.h
@@ -0,0 +1,73 @@
+#pragma once
+
+// Include files
+// from Gaudi
+#include "GaudiAlg/GaudiTool.h"
+
+#include "GenInterfaces/IGenCutTool.h"
+#include "GaudiKernel/Transform4DTypes.h"
+#include "HepMC3/GenParticle.h"
+
+// from Gaudi
+#include "GaudiKernel/SystemOfUnits.h"
+
+/** @class DaughtersInLHCbAndCutsForDACP DaughtersInLHCbAndCutsForDACP.h
+ *
+ *  Tool to keep events with daughters from signal particles in LHCb
+ *  and with cuts on:
+ *     (Dst p, D0 pT) plane
+ *     (Dst p - D0 p, Dst pT - D0 pT) plane
+ *     D0 tau
+ *     D0 flight distance from origin vertex
+ *     D0 daughter p and pT
+ *  Concrete implementation of IGenCutTool.
+ *
+ *  @author Chris Thomas, based on DaughtersInLHCbAndCutsForDstar
+ *  @date   2012-05-14
+ */
+class DaughtersInLHCbAndCutsForDACP : public extends<GaudiTool, IGenCutTool> {
+ public:
+  /// Standard constructor
+  using extends::extends;
+
+  /** Accept events with daughters in LHCb and cuts outlined above
+   *  Implements IGenCutTool::applyCut.
+   */
+  bool applyCut( ParticleVector & theParticleVector ,
+                 const HepMC3::GenEvent * theEvent ,
+                 const LHCb::GenCollision * theCollision ) const override;
+
+ private:
+  /** Study a particle a returns true when all stable daughters
+   *  are in LHCb AndCutsForDACP
+   */
+  bool passCuts( const HepMC3::GenParticlePtr theSignal ) const ;
+
+  /** Momentum Cut function
+   *
+   */
+  bool momentumCut( const HepMC3::GenParticlePtr, double ) const ;
+
+  Gaudi::Property<double> m_chargedThetaMin{this, "ChargedThetaMin", 10 * Gaudi::Units::mrad};
+  Gaudi::Property<double> m_chargedThetaMax{this, "ChargedThetaMax", 400 * Gaudi::Units::mrad};
+  Gaudi::Property<double> m_neutralThetaMin{this, "NeutralThetaMin", 5 * Gaudi::Units::mrad};
+  Gaudi::Property<double> m_neutralThetaMax{this, "NeutralThetaMax", 400 * Gaudi::Units::mrad};
+  Gaudi::Property<double> m_scaleDst       {this, "ScaleDst"       , 0.1};
+  Gaudi::Property<double> m_uDst           {this, "uDst"           , 6000.0 * Gaudi::Units::MeV};
+  Gaudi::Property<double> m_vDst           {this, "vDst"           , 60000.0 * Gaudi::Units::MeV};
+  Gaudi::Property<double> m_costhetaDst    {this, "costhetaDst"    , 0.798636};
+  Gaudi::Property<double> m_sinthetaDst    {this, "sinthetaDst"    , 0.601815};
+  Gaudi::Property<double> m_kDst           {this, "kDst"           , 0.00009};
+  Gaudi::Property<double> m_scaleDiff      {this, "ScaleDiff"      , 0.1};
+  Gaudi::Property<double> m_uDiff          {this, "uDiff"          , 400.0 * Gaudi::Units::MeV};
+  Gaudi::Property<double> m_vDiff          {this, "vDiff"          , 4500.0 * Gaudi::Units::MeV};
+  Gaudi::Property<double> m_costhetaDiff   {this, "costhetaDiff"   , 0.788011};
+  Gaudi::Property<double> m_sinthetaDiff   {this, "sinthetaDiff"   , 0.615661};
+  Gaudi::Property<double> m_kDiff          {this, "kDiff"          , 0.0014};
+  Gaudi::Property<double> m_D0_TAU         {this, "D0_TAU"         , 0.0005 * Gaudi::Units::ns};
+  Gaudi::Property<double> m_D0_FD_ORIVX    {this, "D0_FD_ORIVX"    , 5.0 * Gaudi::Units::mm};
+  Gaudi::Property<double> m_D0_daugHiPT    {this, "D0_daug_HiPT"   , 3000.0 * Gaudi::Units::MeV};
+  Gaudi::Property<double> m_D0_daugLoPT    {this, "D0_daug_LoPT"   , 1000.0 * Gaudi::Units::MeV};
+  Gaudi::Property<double> m_D0_daugLoP     {this, "D0_daug_LoP"    , 5000.0 * Gaudi::Units::MeV};
+
+};
diff --git a/Gen/GenCuts/src/DaughtersInLHCbAndCutsForDinSLBdecays.cpp b/Gen/GenCuts/src_future/DaughtersInLHCbAndCutsForDinSLBdecays.cpp
similarity index 68%
rename from Gen/GenCuts/src/DaughtersInLHCbAndCutsForDinSLBdecays.cpp
rename to Gen/GenCuts/src_future/DaughtersInLHCbAndCutsForDinSLBdecays.cpp
index 8eddb0197..4a5e634c7 100644
--- a/Gen/GenCuts/src/DaughtersInLHCbAndCutsForDinSLBdecays.cpp
+++ b/Gen/GenCuts/src_future/DaughtersInLHCbAndCutsForDinSLBdecays.cpp
@@ -17,6 +17,7 @@
 
 // from Generators
 #include "GenEvent/HepMCUtils.h"
+#include "HepMC3/Relatives.h"
 
 //-----------------------------------------------------------------------------
 // Implementation file for class : DaughtersInLHCbAndCutsForDinSLBdecays
@@ -29,37 +30,11 @@
 DECLARE_COMPONENT( DaughtersInLHCbAndCutsForDinSLBdecays )
 
 
-//=============================================================================
-// Standard constructor, initializes variables
-//=============================================================================
-DaughtersInLHCbAndCutsForDinSLBdecays::DaughtersInLHCbAndCutsForDinSLBdecays( const std::string& type,
-                                  const std::string& name,
-                                  const IInterface* parent )
-  : GaudiTool ( type, name , parent ) {
-    declareInterface< IGenCutTool >( this ) ;
-    declareProperty( "ChargedThetaMin" , m_chargedThetaMin = 10 * Gaudi::Units::mrad ) ;
-    declareProperty( "ChargedThetaMax" , m_chargedThetaMax = 400 * Gaudi::Units::mrad ) ;
-    declareProperty( "NeutralThetaMin" , m_neutralThetaMin = 5 * Gaudi::Units::mrad ) ;
-    declareProperty( "NeutralThetaMax" , m_neutralThetaMax = 400 * Gaudi::Units::mrad ) ;
-    declareProperty( "MassMin" , m_md0muMin = 0*Gaudi::Units::MeV ) ;
-    declareProperty( "D0DaughtersPMin", m_daughtersPMin = 0 * Gaudi::Units::MeV );
-    declareProperty( "D0DaughtersPtMin", m_daughtersPtMin = 0 * Gaudi::Units::MeV );
-    declareProperty( "MuonPMin", m_muonPMin = 0 * Gaudi::Units::MeV );
-    declareProperty( "MuonPtMin", m_muonPtMin = 0 * Gaudi::Units::MeV );
-    declareProperty( "D0PtMin", m_d0PtMin = 0 * Gaudi::Units::MeV );
-    declareProperty( "D0PropTimeMin", m_d0ctauMin = 0 * Gaudi::Units::mm );
-}
-
-//=============================================================================
-// Destructor 
-//=============================================================================
-DaughtersInLHCbAndCutsForDinSLBdecays::~DaughtersInLHCbAndCutsForDinSLBdecays( ) { ; }
-
 //=============================================================================
 // Cut function
 //=============================================================================
 bool DaughtersInLHCbAndCutsForDinSLBdecays::applyCut( ParticleVector & theParticleVector ,
-						      const HepMC::GenEvent * /* theEvent */ ,
+						      const HepMC3::GenEvent * /* theEvent */ ,
 						      const LHCb::GenCollision * /* theHardInfo */ )
   const {
   ParticleVector::iterator it ;
@@ -82,60 +57,56 @@ bool DaughtersInLHCbAndCutsForDinSLBdecays::applyCut( ParticleVector & thePartic
 //=============================================================================
 // Apply cuts Function
 //=============================================================================
-bool DaughtersInLHCbAndCutsForDinSLBdecays::passCuts( const HepMC::GenParticle * theSignal ) const {
+bool DaughtersInLHCbAndCutsForDinSLBdecays::passCuts( const HepMC3::GenParticlePtr theSignal ) const {
 
-  HepMC::GenVertex * EV = theSignal -> end_vertex() ;
+  auto EV = theSignal -> end_vertex() ;
   if ( 0 == EV ) return true ;
 
-  typedef std::vector< HepMC::GenParticle * > Particles ;
+  typedef std::vector< HepMC3::GenParticlePtr > Particles ;
   Particles stables ;
-  HepMC::GenParticle * theMuon( 0 ) ;
-  HepMC::GenParticle * theD0( 0 ) ;
-  HepMC::GenParticle * theNeutrino( 0 ) ;
+  HepMC3::GenParticlePtr theMuon{nullptr} ;
+  HepMC3::GenParticlePtr theD0{nullptr} ;
+  HepMC3::GenParticlePtr theNeutrino{nullptr} ;
   Particles d0daughters ;
 
-  HepMC::GenVertex::particle_iterator iter ;
-
-  for ( iter = EV -> particles_begin( HepMC::descendants ) ; 
-        iter != EV -> particles_end( HepMC::descendants ) ; ++iter ) {
+  for (auto desc : HepMC3::Relatives::DESCENDANTS(theSignal)) {
     // Fill all daughters
-    if ( 0 == (*iter) -> end_vertex() ) stables.push_back( *iter ) ;
+    if ( !desc -> end_vertex() ) stables.push_back( desc ) ;
 
     // The D0
-    if ( abs( (*iter) -> pdg_id() ) == 421 ) theD0 = (*iter) ;
+    if ( abs( desc -> pdg_id() ) == 421 ) theD0 = desc ;
 
     // The muon
-    if ( abs( (*iter) -> pdg_id() ) == 13 ) theMuon = (*iter) ;
+    if ( abs( desc -> pdg_id() ) == 13 ) theMuon = desc ;
 
     // The neutrino
-    if ( abs( (*iter) -> pdg_id() ) == 14 ) theNeutrino = (*iter) ;
+    if ( abs( desc -> pdg_id() ) == 14 ) theNeutrino = desc ;
   }
 
   // check D0, mu, and nu are found
-  if ( 0 == theD0 )
+  if ( !theD0 )
     Exception( "No D0 in the signal decay chain !" ) ;
 
   if ( stables.empty() )
     Exception( "Signal has no stable daughters !" ) ;
 
-  if ( 0 == theMuon ) 
+  if ( !theMuon ) 
     Exception( "No muon in the decay chain !" ) ;  
 
-  if ( 0 == theNeutrino ) 
+  if ( !theNeutrino ) 
     Exception( "No neutrino in the decay chain !" ) ;
   if( !(theD0 && theMuon && theNeutrino)) return false;
 
   // daughters of D0
   EV = theD0 -> end_vertex() ;
-  if ( 0 == EV ) 
+  if ( !EV ) 
     Exception( "The D0 has no daughters" ) ;
   
-  for ( iter = EV -> particles_begin( HepMC::descendants ) ; 
-        iter != EV -> particles_end( HepMC::descendants ) ; ++iter ) {
+  for (auto desc : HepMC3::Relatives::DESCENDANTS(EV)) {
     // Fill all daughters but exclude photons (can be radiative photons)
-    if ( 0 == (*iter) -> end_vertex() )
-      if ( 22 != (*iter) -> pdg_id() ) 
-        d0daughters.push_back( *iter ) ;
+    if ( !desc -> end_vertex() )
+      if ( 22 != desc -> pdg_id() ) 
+        d0daughters.push_back( desc ) ;
   }
 
   if ( d0daughters.empty() )
@@ -176,8 +147,8 @@ bool DaughtersInLHCbAndCutsForDinSLBdecays::passCuts( const HepMC::GenParticle *
   // ---------------------------------------------------------
   // check muon momentum
   //
-  debug() << "Muon p = " << theMuon -> momentum().rho() << endmsg ;
-  if ( theMuon -> momentum().rho() < m_muonPMin ) return false ;
+  debug() << "Muon p = " << theMuon -> momentum().p3mod() << endmsg ;
+  if ( theMuon -> momentum().p3mod() < m_muonPMin ) return false ;
 
   // ---------------------------------------------------------
   // check muon transverse momentum
@@ -191,9 +162,9 @@ bool DaughtersInLHCbAndCutsForDinSLBdecays::passCuts( const HepMC::GenParticle *
   for ( Particles::const_iterator it = d0daughters.begin() ; it != d0daughters.end() ;
         ++it ) {  
     debug() << "Daughter pT = " << (*it) -> momentum().perp() 
-            << " p = " << (*it) -> momentum().rho() << endmsg ;
+            << " p = " << (*it) -> momentum().p3mod() << endmsg ;
     if ( (*it) -> momentum().perp() < m_daughtersPtMin ) return false;
-    if ( (*it) -> momentum().rho() < m_daughtersPMin ) return false;
+    if ( (*it) -> momentum().p3mod() < m_daughtersPMin ) return false;
   }
 
   return true;
@@ -201,7 +172,7 @@ bool DaughtersInLHCbAndCutsForDinSLBdecays::passCuts( const HepMC::GenParticle *
 }
 
 bool 
-DaughtersInLHCbAndCutsForDinSLBdecays::InLHCbAcceptance( const HepMC::GenParticle * stable, const double firstpz ) const
+DaughtersInLHCbAndCutsForDinSLBdecays::InLHCbAcceptance( const HepMC3::GenParticlePtr stable, const double firstpz ) const
 {
   
   debug() << "Check particle " << stable -> pdg_id() << " with angle " 
@@ -214,7 +185,7 @@ DaughtersInLHCbAndCutsForDinSLBdecays::InLHCbAcceptance( const HepMC::GenParticl
        ( 16 == abs( stable -> pdg_id() ) ) ) return true ;
  
   // Don't use daughters of Lambda and KS:
-  HepMC::GenParticle * theParent = *( stable -> production_vertex() -> particles_in_const_begin() ) ;
+  auto theParent = *std::cbegin( stable -> production_vertex() -> particles_in() ) ;
   if ( 3122 == abs( theParent -> pdg_id() ) ||
        310 == theParent -> pdg_id() ) return true ;
 
@@ -247,7 +218,7 @@ DaughtersInLHCbAndCutsForDinSLBdecays::InLHCbAcceptance( const HepMC::GenParticl
 }
 
 double 
-DaughtersInLHCbAndCutsForDinSLBdecays::ProperTime( const HepMC::GenParticle * resonance ) const
+DaughtersInLHCbAndCutsForDinSLBdecays::ProperTime( const HepMC3::GenParticlePtr resonance ) const
 {
   Gaudi::LorentzVector pEnd , pBegin ;
   pEnd.SetXYZT( resonance -> end_vertex() -> position() . x() ,
diff --git a/Gen/GenCuts/src_future/DaughtersInLHCbAndCutsForDinSLBdecays.h b/Gen/GenCuts/src_future/DaughtersInLHCbAndCutsForDinSLBdecays.h
new file mode 100644
index 000000000..e52c75651
--- /dev/null
+++ b/Gen/GenCuts/src_future/DaughtersInLHCbAndCutsForDinSLBdecays.h
@@ -0,0 +1,65 @@
+#pragma once
+
+// Include files
+// from Gaudi
+#include "GaudiAlg/GaudiTool.h"
+
+#include "GenInterfaces/IGenCutTool.h"
+#include "GaudiKernel/Transform4DTypes.h"
+#include "HepMC3/GenParticle.h"
+
+// from Gaudi
+#include "GaudiKernel/SystemOfUnits.h"
+
+/** @class DaughtersInLHCbAndCutsForDinSLBdecays DaughtersInLHCbAndCutsForDinSLBdecays.h
+ *
+ *  Tool to keep events with daughters from signal particles
+ *  in LHCb and with p and pt cuts on D0 daughters and muon.
+ *  Concrete implementation of IGenCutTool.
+ *
+ *  @author Maurizio Martinelli
+ *  @date   2013-08-19
+ */
+class DaughtersInLHCbAndCutsForDinSLBdecays : public extends<GaudiTool, IGenCutTool> {
+ public:
+  /// Standard constructor
+  using extends::extends;
+
+  /** Accept events with daughters in LHCb and p/pt cuts on D0 daughters
+   *  (defined by min and max angles, different values for charged and neutrals)
+   *  Implements IGenCutTool::applyCut.
+   */
+  bool applyCut( ParticleVector & theParticleVector ,
+                 const HepMC3::GenEvent * theEvent ,
+                 const LHCb::GenCollision * theCollision ) const override;
+
+ private:
+  /** Study a particle a returns true when all stable daughters
+   *  are in LHCb AndWithMinP
+   */
+  bool passCuts( const HepMC3::GenParticlePtr theSignal ) const ;
+
+  /** Check particle is in LHCb acceptance
+   */
+  bool InLHCbAcceptance( const HepMC3::GenParticlePtr stable, const double firstpz ) const ;
+
+  /** Momentum Cut function
+   */
+  bool momentumCut( const HepMC3::GenParticlePtr, double ) const ;
+
+  /** Calculate proper time
+   */
+  double ProperTime( const HepMC3::GenParticlePtr resonance ) const;
+
+  Gaudi::Property<double> m_chargedThetaMin {this, "ChargedThetaMin"  , 10 * Gaudi::Units::mrad };
+  Gaudi::Property<double> m_chargedThetaMax {this, "ChargedThetaMax"  , 400 * Gaudi::Units::mrad };
+  Gaudi::Property<double> m_neutralThetaMin {this, "NeutralThetaMin"  , 5 * Gaudi::Units::mrad };
+  Gaudi::Property<double> m_neutralThetaMax {this, "NeutralThetaMax"  , 400 * Gaudi::Units::mrad };
+  Gaudi::Property<double> m_md0muMin        {this, "MassMin"          , 0*Gaudi::Units::MeV };
+  Gaudi::Property<double> m_daughtersPMin   {this, "D0DaughtersPMin"  , 0 * Gaudi::Units::MeV };
+  Gaudi::Property<double> m_daughtersPtMin  {this, "D0DaughtersPtMin" , 0 * Gaudi::Units::MeV };
+  Gaudi::Property<double> m_muonPMin        {this, "MuonPMin"         , 0 * Gaudi::Units::MeV };
+  Gaudi::Property<double> m_muonPtMin       {this, "MuonPtMin"        , 0 * Gaudi::Units::MeV };
+  Gaudi::Property<double> m_d0PtMin         {this, "D0PtMin"          , 0 * Gaudi::Units::MeV };
+  Gaudi::Property<double> m_d0ctauMin       {this, "D0PropTimeMin"    , 0 * Gaudi::Units::mm };
+};
diff --git a/Gen/GenCuts/src/DaughtersInLHCbAndCutsForDstar.cpp b/Gen/GenCuts/src_future/DaughtersInLHCbAndCutsForDstar.cpp
similarity index 56%
rename from Gen/GenCuts/src/DaughtersInLHCbAndCutsForDstar.cpp
rename to Gen/GenCuts/src_future/DaughtersInLHCbAndCutsForDstar.cpp
index c2fc6168c..6fcff732a 100644
--- a/Gen/GenCuts/src/DaughtersInLHCbAndCutsForDstar.cpp
+++ b/Gen/GenCuts/src_future/DaughtersInLHCbAndCutsForDstar.cpp
@@ -13,8 +13,9 @@
 #include "GaudiKernel/Vector4DTypes.h"
 
 // from HepMC
-#include "HepMC/GenParticle.h"
-#include "HepMC/GenVertex.h"
+#include "HepMC3/GenParticle.h"
+#include "HepMC3/GenVertex.h"
+#include "HepMC3/Relatives.h"
 
 // from Generators
 #include "GenEvent/HepMCUtils.h"
@@ -30,32 +31,12 @@
 DECLARE_COMPONENT( DaughtersInLHCbAndCutsForDstar )
 
 
-//=============================================================================
-// Standard constructor, initializes variables
-//=============================================================================
-DaughtersInLHCbAndCutsForDstar::DaughtersInLHCbAndCutsForDstar( const std::string& type,
-                                                                const std::string& name,
-                                                                const IInterface* parent )
-  : DaughtersInLHCb ( type, name , parent ) {
-  declareInterface< IGenCutTool >( this ) ;
-  declareProperty( "D0PtCuts"          , m_d0ptCut           = 1700 * Gaudi::Units::MeV ) ;
-  declareProperty( "DaughtersPtMinCut" , m_daughtersptminCut = 700 * Gaudi::Units::MeV ) ;
-  declareProperty( "DaughtersPtMaxCut" , m_daughtersptmaxCut = 1050 * Gaudi::Units::MeV ) ;
-  declareProperty( "DaughtersPMinCut"  , m_daughterspminCut  = 4500 * Gaudi::Units::MeV ) ;
-  declareProperty( "SoftPiPtCut"       , m_softpiptCut       = 100 * Gaudi::Units::MeV ) ;
-  declareProperty( "D0CTauCut"         , m_d0ctauCut         = -1. ) ;
-}
-
-//=============================================================================
-// Destructor
-//=============================================================================
-DaughtersInLHCbAndCutsForDstar::~DaughtersInLHCbAndCutsForDstar( ) { ; }
 
 //=============================================================================
 // AndWithMinP function
 //=============================================================================
 bool DaughtersInLHCbAndCutsForDstar::applyCut( ParticleVector & theParticleVector ,
-                                               const HepMC::GenEvent * theEvent ,
+                                               const HepMC3::GenEvent * theEvent ,
                                                const LHCb::GenCollision * theHardInfo )
   const {
   if( ! DaughtersInLHCb::applyCut( theParticleVector, theEvent, theHardInfo ) ) {
@@ -79,28 +60,25 @@ bool DaughtersInLHCbAndCutsForDstar::applyCut( ParticleVector & theParticleVecto
 //=============================================================================
 // Functions to test if all daughters are in acceptance
 //=============================================================================
-bool DaughtersInLHCbAndCutsForDstar::passCuts( const HepMC::GenParticle * theSignal ) const {
-  HepMC::GenVertex * EV = theSignal -> end_vertex() ;
+bool DaughtersInLHCbAndCutsForDstar::passCuts( const HepMC3::GenParticlePtr theSignal ) const {
+  auto EV = theSignal -> end_vertex() ;
   if ( 0 == EV ) return true ;
 
-  typedef std::vector< HepMC::GenParticle * > Particles ;
-  HepMC::GenParticle * theSoftPion( 0 ) ;
-  HepMC::GenParticle * theD0( 0 ) ;
-  HepMC::GenParticle * theParent( 0 );
+  typedef std::vector< HepMC3::GenParticlePtr > Particles ;
+  HepMC3::GenParticlePtr theSoftPion{nullptr} ;
+  HepMC3::GenParticlePtr theD0{nullptr} ;
+  HepMC3::GenParticlePtr theParent{nullptr};
   Particles d0daughters ;
 
-  HepMC::GenVertex::particle_iterator iter ;
-
-  for ( iter = EV -> particles_begin( HepMC::descendants ) ;
-        iter != EV -> particles_end( HepMC::descendants ) ; ++iter ) {
+  for (auto desc : HepMC3::Relatives::DESCENDANTS(theSignal)) {
 
     // The D0
-    if ( abs( (*iter) -> pdg_id() ) == 421 ) theD0 = (*iter) ;
+    if ( abs( desc -> pdg_id() ) == 421 ) theD0 = desc ;
 
     // The soft pion
-    theParent = *( (*iter) -> production_vertex() -> particles_in_const_begin() ) ;
-    if ( ( 413 == abs( theParent -> pdg_id() ) ) && ( 211 == abs( (*iter) -> pdg_id() ) ) )
-      theSoftPion = (*iter) ;
+    theParent = *std::cbegin(( desc -> production_vertex()->particles_in() )) ;
+    if ( ( 413 == abs( theParent -> pdg_id() ) ) && ( 211 == abs( desc -> pdg_id() ) ) )
+      theSoftPion = desc ;
   }
 
   if ( 0 == theD0 )
@@ -114,12 +92,11 @@ bool DaughtersInLHCbAndCutsForDstar::passCuts( const HepMC::GenParticle * theSig
   if ( 0 == EV )
     Exception( "The D0 has no daughters" ) ;
 
-  for ( iter = EV -> particles_begin( HepMC::descendants ) ;
-        iter != EV -> particles_end( HepMC::descendants ) ; ++iter ) {
+  for (auto desc : HepMC3::Relatives::DESCENDANTS(EV)) {
     // Fill all daughters but exclude photons (can be radiative photons)
-    if ( 0 == (*iter) -> end_vertex() )
-      if ( 22 != (*iter) -> pdg_id() )
-        d0daughters.push_back( *iter ) ;
+    if ( 0 == desc -> end_vertex() )
+      if ( 22 != desc -> pdg_id() )
+        d0daughters.push_back( desc ) ;
   }
 
   if ( d0daughters.empty() )
@@ -136,7 +113,7 @@ bool DaughtersInLHCbAndCutsForDstar::passCuts( const HepMC::GenParticle * theSig
 
   if ( m_d0ctauCut > 0. ) {
     // Apply ctau cut
-    const HepMC::FourVector& D0fourmomentum = theD0 -> momentum();
+    const HepMC3::FourVector& D0fourmomentum = theD0 -> momentum();
     double gamma = D0fourmomentum . e() / D0fourmomentum . m() ;
     double delta_t = theD0 -> end_vertex() -> position() . t() - theD0 -> production_vertex() -> position() . t() ;
     double ctau = Gaudi::Units::c_light * delta_t / gamma ;
@@ -151,18 +128,17 @@ bool DaughtersInLHCbAndCutsForDstar::passCuts( const HepMC::GenParticle * theSig
   double maxpt = 0. ;
   double minp  = 14.*Gaudi::Units::TeV ;
 
-  for ( Particles::const_iterator it = d0daughters.begin() ; it != d0daughters.end() ;
-        ++it ) {
+  for ( auto & d0daug : d0daughters ) {
     if ( msgLevel( MSG::DEBUG ) ) {
-      debug() << "Daughter pT = " << (*it) -> momentum().perp()
-              << " p = " << (*it) -> momentum().rho() << endmsg ;
+      debug() << "Daughter pT = " << d0daug -> momentum().perp()
+              << " p = " << d0daug -> momentum().p3mod() << endmsg ;
     }
-    if ( (*it) -> momentum().perp() > maxpt )
-      maxpt = (*it) -> momentum().perp() ;
-    if ( (*it) -> momentum().perp() < minpt )
-      minpt = (*it) -> momentum().perp() ;
-    if ( (*it) -> momentum().rho() < minp )
-      minp = (*it) -> momentum().rho() ;
+    if ( d0daug -> momentum().perp() > maxpt )
+      maxpt = d0daug -> momentum().perp() ;
+    if ( d0daug -> momentum().perp() < minpt )
+      minpt = d0daug -> momentum().perp() ;
+    if ( d0daug -> momentum().p3mod() < minp )
+      minp = d0daug -> momentum().p3mod() ;
   }
 
   if ( msgLevel( MSG::DEBUG ) ) {
diff --git a/Gen/GenCuts/src/DaughtersInLHCbAndCutsForDstar.h b/Gen/GenCuts/src_future/DaughtersInLHCbAndCutsForDstar.h
similarity index 54%
rename from Gen/GenCuts/src/DaughtersInLHCbAndCutsForDstar.h
rename to Gen/GenCuts/src_future/DaughtersInLHCbAndCutsForDstar.h
index b61a79293..a222ce6c5 100644
--- a/Gen/GenCuts/src/DaughtersInLHCbAndCutsForDstar.h
+++ b/Gen/GenCuts/src_future/DaughtersInLHCbAndCutsForDstar.h
@@ -1,5 +1,4 @@
-#ifndef GENCUTS_DAUGHTERSINLHCBANDCUTSFORDSTAR_H
-#define GENCUTS_DAUGHTERSINLHCBANDCUTSFORDSTAR_H 1
+#pragma once
 
 // Include files
 #include "DaughtersInLHCb.h"
@@ -13,45 +12,35 @@
  *  @author Patrick Robbe
  *  @date   2012-02-07
  */
-class DaughtersInLHCbAndCutsForDstar : public DaughtersInLHCb, virtual public IGenCutTool {
+class DaughtersInLHCbAndCutsForDstar : public extends<DaughtersInLHCb, IGenCutTool> {
  public:
   /// Standard constructor
-  DaughtersInLHCbAndCutsForDstar( const std::string& type,
-                                  const std::string& name,
-                                  const IInterface* parent);
-
-  virtual ~DaughtersInLHCbAndCutsForDstar( ); ///< Destructor
+   using extends::extends;
 
   /** Accept events with daughters in LHCb and p/pt cuts on Dstar daughters
    *  (defined by min and max angles, different values for charged and neutrals)
    *  Implements IGenCutTool::applyCut.
    */
   bool applyCut( ParticleVector & theParticleVector ,
-                 const HepMC::GenEvent * theEvent ,
+                 const HepMC3::GenEvent * theEvent ,
                  const LHCb::GenCollision * theCollision ) const override;
 
  private:
   /** Study a particle a returns true when all stable daughters
    *  are in LHCb AndWithMinP
    */
-  bool passCuts( const HepMC::GenParticle * theSignal ) const ;
+  bool passCuts( const HepMC3::GenParticlePtr theSignal ) const ;
 
   // cut value of D0 pt
-  double m_d0ptCut ;
-
+  Gaudi::Property<double> m_d0ptCut           {this,"D0PtCuts"          , 1700 * Gaudi::Units::MeV };
   // cut value on daughters min pt
-  double m_daughtersptminCut ;
-
+  Gaudi::Property<double> m_daughtersptminCut {this,"DaughtersPtMinCut" , 700 * Gaudi::Units::MeV };
   // cut value on daughters max pt
-  double m_daughtersptmaxCut ;
-
+  Gaudi::Property<double> m_daughtersptmaxCut {this,"DaughtersPtMaxCut" , 1050 * Gaudi::Units::MeV };
   // cut value on daughters min p
-  double m_daughterspminCut ;
-
+  Gaudi::Property<double> m_daughterspminCut  {this,"DaughtersPMinCut"  , 4500 * Gaudi::Units::MeV };
   // soft pion pt cut
-  double m_softpiptCut ;
-
+  Gaudi::Property<double> m_softpiptCut       {this,"SoftPiPtCut"       , 100 * Gaudi::Units::MeV };
   // cut on D0 ctau
-  double m_d0ctauCut ;
+  Gaudi::Property<double> m_d0ctauCut         {this,"D0CTauCut"         , -1. };
 };
-#endif // GENCUTS_DAUGHTERSINLHCDANDCUTSFORDSTAR_H
diff --git a/Gen/GenCuts/src_future/DaughtersInLHCbAndCutsForDstarFromB.cpp b/Gen/GenCuts/src_future/DaughtersInLHCbAndCutsForDstarFromB.cpp
new file mode 100644
index 000000000..723824681
--- /dev/null
+++ b/Gen/GenCuts/src_future/DaughtersInLHCbAndCutsForDstarFromB.cpp
@@ -0,0 +1,37 @@
+// Include files
+
+// local
+#include "DaughtersInLHCbAndCutsForDstarFromB.h"
+
+// from Kernel
+#include "Kernel/ParticleID.h"
+
+// from Generators
+#include "GenEvent/HepMCUtils.h"
+
+// from STL
+#include <algorithm>
+
+//-----------------------------------------------------------------------------
+// Implementation file for class : DaughtersInLHCbAndCutsForDstarFromB
+//
+// 2018-03-30 Adam Morris
+//-----------------------------------------------------------------------------
+
+// Declaration of the Tool Factory
+
+DECLARE_COMPONENT( DaughtersInLHCbAndCutsForDstarFromB )
+
+
+//=============================================================================
+// Acceptance function
+//=============================================================================
+bool DaughtersInLHCbAndCutsForDstarFromB::applyCut( ParticleVector & theParticleVector ,
+                                                    const HepMC3::GenEvent * theEvent ,
+                                                    const LHCb::GenCollision * theHardInfo )
+  const
+{
+  return ( m_fromBcuts->applyCut(theParticleVector,theEvent,theHardInfo) &&
+           DaughtersInLHCbAndCutsForDstar::applyCut(theParticleVector,theEvent,theHardInfo) );
+}
+
diff --git a/Gen/GenCuts/src_future/DaughtersInLHCbAndCutsForDstarFromB.h b/Gen/GenCuts/src_future/DaughtersInLHCbAndCutsForDstarFromB.h
new file mode 100644
index 000000000..c630d4669
--- /dev/null
+++ b/Gen/GenCuts/src_future/DaughtersInLHCbAndCutsForDstarFromB.h
@@ -0,0 +1,30 @@
+#pragma once
+
+// Include files
+#include "DaughtersInLHCbAndCutsForDstar.h"
+#include "GaudiKernel/ToolHandle.h"
+
+/** @class DaughtersInLHCbAndCutsForDstarFromB DaughtersInLHCbAndCutsForDstarFromB.h
+ *
+ *  Tool to select D* particles from a b-hadron with pT cuts
+ *
+ *  @author Adam Morris
+ *  @date   2018-03-30
+ */
+class DaughtersInLHCbAndCutsForDstarFromB : public extends<DaughtersInLHCbAndCutsForDstar, IGenCutTool> {
+public:
+    using extends::extends;
+
+
+  /** Check that the signal D* satisfies the cuts in
+   *  SignalIsFromBDecay and DaughtersInLHCbAndCutsForDstar.
+   *  Implements IGenCutTool::applyCut.
+   */
+  bool applyCut( ParticleVector & theParticleVector,
+                 const HepMC3::GenEvent * theEvent,
+                 const LHCb::GenCollision * theCollision ) const override;
+
+private:
+  /// From a b cut tool
+  ToolHandle<IGenCutTool> m_fromBcuts{"SignalIsFromBDecay", this};
+} ;
diff --git a/Gen/GenCuts/src/DaughtersInLHCbAndCutsForLambdacD.cpp b/Gen/GenCuts/src_future/DaughtersInLHCbAndCutsForLambdacD.cpp
similarity index 67%
rename from Gen/GenCuts/src/DaughtersInLHCbAndCutsForLambdacD.cpp
rename to Gen/GenCuts/src_future/DaughtersInLHCbAndCutsForLambdacD.cpp
index 1aa52f13b..ca74b8ba6 100644
--- a/Gen/GenCuts/src/DaughtersInLHCbAndCutsForLambdacD.cpp
+++ b/Gen/GenCuts/src_future/DaughtersInLHCbAndCutsForLambdacD.cpp
@@ -13,11 +13,12 @@
 #include "GaudiKernel/Vector4DTypes.h"
 
 // from HepMC
-#include "HepMC/GenParticle.h"
-#include "HepMC/GenVertex.h"
+#include "HepMC3/GenParticle.h"
+#include "HepMC3/GenVertex.h"
 
 // from Generators
 #include "GenEvent/HepMCUtils.h"
+#include "HepMC3/Relatives.h"
 
 //-----------------------------------------------------------------------------
 // Implementation file for class : DaughtersInLHCbAndCutsForLambdacD
@@ -30,35 +31,11 @@
 DECLARE_COMPONENT( DaughtersInLHCbAndCutsForLambdacD )
 
 
-//=============================================================================
-// Standard constructor, initializes variables
-//=============================================================================
-DaughtersInLHCbAndCutsForLambdacD::DaughtersInLHCbAndCutsForLambdacD( const std::string& type,
-                                                                const std::string& name,
-                                                                const IInterface* parent )
-  : GaudiTool ( type, name , parent ) {
-  declareInterface< IGenCutTool >( this ) ;
-  declareProperty( "ChargedThetaMin"   , m_chargedThetaMin   = 10 * Gaudi::Units::mrad ) ;
-  declareProperty( "ChargedThetaMax"   , m_chargedThetaMax   = 400 * Gaudi::Units::mrad ) ;
-  declareProperty( "NeutralThetaMin"   , m_neutralThetaMin   = 5 * Gaudi::Units::mrad ) ;
-  declareProperty( "NeutralThetaMax"   , m_neutralThetaMax   = 400 * Gaudi::Units::mrad ) ;
-  declareProperty( "LambdacPtCuts"     , m_lcptCut           = 1500 * Gaudi::Units::MeV ) ;
-  declareProperty( "DaughtersPtMinCut" , m_daughtersptminCut = 150 * Gaudi::Units::MeV ) ;
-  declareProperty( "DaughtersPtMaxCut" , m_daughtersptmaxCut = 150 * Gaudi::Units::MeV ) ;
-  declareProperty( "DaughtersPMinCut"  , m_daughterspminCut  = 1000 * Gaudi::Units::MeV ) ;
-  declareProperty( "LambdacCTauCut"    , m_lcctauCut         = -1. ) ;
-}
-
-//=============================================================================
-// Destructor
-//=============================================================================
-DaughtersInLHCbAndCutsForLambdacD::~DaughtersInLHCbAndCutsForLambdacD( ) { ; }
-
 //=============================================================================
 // AndWithMinP function
 //=============================================================================
 bool DaughtersInLHCbAndCutsForLambdacD::applyCut( ParticleVector & theParticleVector ,
-                                               const HepMC::GenEvent * /* theEvent */ ,
+                                               const HepMC3::GenEvent * /* theEvent */ ,
                                                const LHCb::GenCollision * /* theHardInfo */ )
   const {
   ParticleVector::iterator it ;
@@ -80,29 +57,27 @@ bool DaughtersInLHCbAndCutsForLambdacD::applyCut( ParticleVector & theParticleVe
 //=============================================================================
 // Functions to test if the Lambda_c and 3 pi from the daughters are in acceptance
 //=============================================================================
-bool DaughtersInLHCbAndCutsForLambdacD::passCuts( const HepMC::GenParticle * theSignal ) const {
+bool DaughtersInLHCbAndCutsForLambdacD::passCuts( const HepMC3::GenParticlePtr theSignal ) const {
     //theSignal = Lambda_c
-    HepMC::GenVertex * EV = theSignal -> end_vertex() ;
+    auto EV = theSignal -> end_vertex() ;
     if ( 0 == EV ) return true ;
 
-    typedef std::vector< HepMC::GenParticle * > Particles ;
+    typedef std::vector< HepMC3::GenParticlePtr > Particles ;
     Particles unstables, stables ;
     Particles lcparents , lcdaughters ;
 
     // first check on the Lambda_c origin : it should come from a B decay
-    HepMC::GenVertex::particle_iterator iter ;
     int bOK=0 ;
     double zB=-999. ;
     double zB2=-999. ;
 
     if( msgLevel (MSG::DEBUG))debug() << "Check the Lambda_c ancestor " <<endmsg;
-    for ( iter = EV -> particles_begin( HepMC::ancestors ) ;
-            iter != EV -> particles_end( HepMC::ancestors ) ; ++iter ) {
-        lcparents.push_back( *iter );
+    for (auto anc : HepMC3::Relatives::ANCESTORS(EV)) {
+        lcparents.push_back( anc );
 
         // is there a B
-        if ( int(abs( (*iter) -> pdg_id() )) % 10000 > 500 && int(abs( (*iter) -> pdg_id() )) % 10000 < 600 )bOK++;
-        if ( int(abs( (*iter) -> pdg_id() )) % 10000 > 5000 && int(abs( (*iter) -> pdg_id() )) % 10000 < 6000 )bOK++;
+        if ( int(abs( (anc) -> pdg_id() )) % 10000 > 500 && int(abs( (anc) -> pdg_id() )) % 10000 < 600 )bOK++;
+        if ( int(abs( (anc) -> pdg_id() )) % 10000 > 5000 && int(abs( (anc) -> pdg_id() )) % 10000 < 6000 )bOK++;
     }
 
     if( msgLevel (MSG::DEBUG))debug() <<"start of Lambda_c parent loop with "<<bOK<<" B ancestors"<<endmsg;
@@ -133,17 +108,16 @@ bool DaughtersInLHCbAndCutsForLambdacD::passCuts( const HepMC::GenParticle * the
     int npiLc=0;
 
     //ask all Lambda_c daughters in acceptance
-    for ( iter = EV -> particles_begin( HepMC::descendants ) ;
-            iter != EV -> particles_end( HepMC::descendants ) ; ++iter ) {
+    for (auto desc : HepMC3::Relatives::DESCENDANTS(EV)) {
 
         // Fill all daughters
-        if ( 0 == (*iter) -> end_vertex() ) stables.push_back( *iter ) ;
+        if ( 0 == (desc) -> end_vertex() ) stables.push_back( desc ) ;
 
-        if ( 0 == (*iter) -> end_vertex() )
-        if ( 22 != (*iter) -> pdg_id() ) lcdaughters.push_back( *iter ) ;
-        if ( 2212 == abs(int((*iter) -> pdg_id())) )npLc++;
-        if ( 321 == abs(int((*iter) -> pdg_id() )))nKLc++;
-        if ( 211 == abs(int((*iter) -> pdg_id() )))npiLc++;
+        if ( 0 == (desc) -> end_vertex() )
+        if ( 22 != (desc) -> pdg_id() ) lcdaughters.push_back( desc ) ;
+        if ( 2212 == abs(int((desc) -> pdg_id())) )npLc++;
+        if ( 321 == abs(int((desc) -> pdg_id() )))nKLc++;
+        if ( 211 == abs(int((desc) -> pdg_id() )))npiLc++;
     }
 
     if ( stables.empty() )
@@ -193,14 +167,14 @@ bool DaughtersInLHCbAndCutsForLambdacD::passCuts( const HepMC::GenParticle * the
     for ( Particles::const_iterator it = lcdaughters.begin() ; it != lcdaughters.end() ;
             ++it ) {
         if( msgLevel (MSG::DEBUG))debug() << "Daughter pT = " << (*it) -> momentum().perp()
-            << " p = " << (*it) -> momentum().rho() << endmsg ;
+            << " p = " << (*it) -> momentum().p3mod() << endmsg ;
 
         if ( (*it) -> momentum().perp() > maxpt )
             maxpt = (*it) -> momentum().perp() ;
         if ( (*it) -> momentum().perp() < minpt )
             minpt = (*it) -> momentum().perp() ;
-        if ( (*it) -> momentum().rho() < minp )
-            minp = (*it) -> momentum().rho() ;
+        if ( (*it) -> momentum().p3mod() < minp )
+            minp = (*it) -> momentum().p3mod() ;
     }
 
     if( msgLevel (MSG::DEBUG))debug() << "Min Pt = " << minpt
@@ -215,18 +189,19 @@ bool DaughtersInLHCbAndCutsForLambdacD::passCuts( const HepMC::GenParticle * the
     if( msgLevel (MSG::DEBUG))debug() << "Check for 3 pions in addition to Lambda_c " <<zB<<endmsg;
     int Npions_inacc=0;
 
-    for ( iter = EV -> particles_begin( HepMC::relatives) ;
-            iter != EV -> particles_end( HepMC::relatives ) ; ++iter ) {
+    // TODO: Verify that HepMC2 relatives are now simply all particles as they are connected via
+    // the ROOT vertex
+    for (auto part : theSignal->parent_event()->particles()) {
 
-        if ( 0 == (*iter) -> end_vertex() ) stables.push_back( *iter ) ;
-        if ( 0 != (*iter) -> end_vertex() ) unstables.push_back( *iter ) ;
+        if ( 0 == (part) -> end_vertex() ) stables.push_back( part ) ;
+        if ( 0 != (part) -> end_vertex() ) unstables.push_back( part ) ;
 
         // identify z of second B
-        if ( int(abs( (*iter) -> pdg_id() ))%10000> 500&& int(abs( (*iter) -> pdg_id() ))%10000<600 ){
-            if ( zB2<= (*iter)->end_vertex()->position().z() && zB != (*iter)->end_vertex()->position().z() ) zB2 = (*iter)->end_vertex()->position().z();
+        if ( int(abs( (part) -> pdg_id() ))%10000> 500&& int(abs( (part) -> pdg_id() ))%10000<600 ){
+            if ( zB2<= (part)->end_vertex()->position().z() && zB != (part)->end_vertex()->position().z() ) zB2 = (part)->end_vertex()->position().z();
         }
-        if ( int(abs( (*iter) -> pdg_id() ))%10000> 5000&& int(abs( (*iter) -> pdg_id() ))%10000<6000 ){
-            if ( zB2<= (*iter)->end_vertex()->position().z() && zB != (*iter)->end_vertex()->position().z() ) zB2 = (*iter)->end_vertex()->position().z();
+        if ( int(abs( (part) -> pdg_id() ))%10000> 5000&& int(abs( (part) -> pdg_id() ))%10000<6000 ){
+            if ( zB2<= (part)->end_vertex()->position().z() && zB != (part)->end_vertex()->position().z() ) zB2 = (part)->end_vertex()->position().z();
         }
     }
     //now loop on the unstable particles
diff --git a/Gen/GenCuts/src_future/DaughtersInLHCbAndCutsForLambdacD.h b/Gen/GenCuts/src_future/DaughtersInLHCbAndCutsForLambdacD.h
new file mode 100644
index 000000000..96c328343
--- /dev/null
+++ b/Gen/GenCuts/src_future/DaughtersInLHCbAndCutsForLambdacD.h
@@ -0,0 +1,55 @@
+#pragma once
+
+// Include files
+// from Gaudi
+#include "GaudiAlg/GaudiTool.h"
+
+#include "GenInterfaces/IGenCutTool.h"
+#include "GaudiKernel/Transform4DTypes.h"
+#include "HepMC3/GenParticle.h"
+
+// from Gaudi
+#include "GaudiKernel/SystemOfUnits.h"
+
+/** @class DaughtersInLHCbAndCutsForLambdac DaughtersInLHCbAndCutsForLambdacD.h
+ *
+ *  Tool to keep events with daughters from signal particles
+ *  in LHCb and with p and pt cuts on Lambda_c daughters.
+ *  Concrete implementation of IGenCutTool.
+ *
+ *  @author Patrick Robbe
+ *  @date   2012-02-07
+ */
+class DaughtersInLHCbAndCutsForLambdacD : public extends<GaudiTool, IGenCutTool> {
+public:
+  using extends::extends;
+
+  /** Accept events with daughters in LHCb and p/pt cuts on Lambda_c daughters
+   *  (defined by min and max angles, different values for charged and neutrals)
+   *  Implements IGenCutTool::applyCut.
+   */
+  bool applyCut( ParticleVector & theParticleVector ,
+                 const HepMC3::GenEvent * theEvent ,
+                 const LHCb::GenCollision * theCollision ) const override;
+
+private:
+  /** Study a particle a returns true when all stable daughters
+   *  are in LHCb AndWithMinP
+   */
+  bool passCuts( const HepMC3::GenParticlePtr theSignal ) const ;
+
+  /** Momentum Cut function
+   *
+   */
+  bool momentumCut( const HepMC3::GenParticlePtr, double ) const ;
+
+  Gaudi::Property<double> m_chargedThetaMin  {this, "ChargedThetaMin"   , 10 * Gaudi::Units::mrad};
+  Gaudi::Property<double> m_chargedThetaMax  {this, "ChargedThetaMax"   , 400 * Gaudi::Units::mrad};
+  Gaudi::Property<double> m_neutralThetaMin  {this, "NeutralThetaMin"   , 5 * Gaudi::Units::mrad};
+  Gaudi::Property<double> m_neutralThetaMax  {this, "NeutralThetaMax"   , 400 * Gaudi::Units::mrad};
+  Gaudi::Property<double> m_lcptCut          {this, "LambdacPtCuts"     , 1500 * Gaudi::Units::MeV};
+  Gaudi::Property<double> m_daughtersptminCut{this, "DaughtersPtMinCut" , 150 * Gaudi::Units::MeV};
+  Gaudi::Property<double> m_daughtersptmaxCut{this, "DaughtersPtMaxCut" , 150 * Gaudi::Units::MeV};
+  Gaudi::Property<double> m_daughterspminCut {this, "DaughtersPMinCut"  , 1000 * Gaudi::Units::MeV};
+  Gaudi::Property<double> m_lcctauCut        {this, "LambdacCTauCut"    , -1.};
+};
diff --git a/Gen/GenCuts/src/DaughtersInLHCbAndCutsForLc3pi.cpp b/Gen/GenCuts/src_future/DaughtersInLHCbAndCutsForLc3pi.cpp
similarity index 64%
rename from Gen/GenCuts/src/DaughtersInLHCbAndCutsForLc3pi.cpp
rename to Gen/GenCuts/src_future/DaughtersInLHCbAndCutsForLc3pi.cpp
index 9f06315d9..0c71c261e 100644
--- a/Gen/GenCuts/src/DaughtersInLHCbAndCutsForLc3pi.cpp
+++ b/Gen/GenCuts/src_future/DaughtersInLHCbAndCutsForLc3pi.cpp
@@ -13,11 +13,12 @@
 #include "GaudiKernel/Vector4DTypes.h"
 
 // from HepMC
-#include "HepMC/GenParticle.h"
-#include "HepMC/GenVertex.h"
+#include "HepMC3/GenParticle.h"
+#include "HepMC3/GenVertex.h"
 
 // from Generators
-#include "GenEvent/HepMCUtils.h"
+#include "HepMCUtils/HepMCUtils.h"
+#include "HepMC3/Relatives.h"
 
 //-----------------------------------------------------------------------------
 // Implementation file for class : DaughtersInLHCbAndCutsForLc3pi
@@ -30,34 +31,11 @@
 DECLARE_COMPONENT( DaughtersInLHCbAndCutsForLc3pi )
 
 
-//=============================================================================
-// Standard constructor, initializes variables
-//=============================================================================
-DaughtersInLHCbAndCutsForLc3pi::DaughtersInLHCbAndCutsForLc3pi( const std::string& type,
-                                                                const std::string& name,
-                                                                const IInterface* parent )
-  : GaudiTool ( type, name , parent ) {
-  declareInterface< IGenCutTool >( this ) ;
-  declareProperty( "ChargedThetaMin"   , m_chargedThetaMin   = 10 * Gaudi::Units::mrad ) ;
-  declareProperty( "ChargedThetaMax"   , m_chargedThetaMax   = 400 * Gaudi::Units::mrad ) ;
-  declareProperty( "NeutralThetaMin"   , m_neutralThetaMin   = 5 * Gaudi::Units::mrad ) ;
-  declareProperty( "NeutralThetaMax"   , m_neutralThetaMax   = 400 * Gaudi::Units::mrad ) ;
-  declareProperty( "LcPtCuts"          , m_lcptCut           = 1500 * Gaudi::Units::MeV ) ;
-  declareProperty( "DaughtersPtMinCut" , m_daughtersptminCut = 150 * Gaudi::Units::MeV ) ;
-  declareProperty( "DaughtersPtMaxCut" , m_daughtersptmaxCut = 150 * Gaudi::Units::MeV ) ;
-  declareProperty( "DaughtersPMinCut"  , m_daughterspminCut  = 1000 * Gaudi::Units::MeV ) ;
-  }
-
-//=============================================================================
-// Destructor
-//=============================================================================
-DaughtersInLHCbAndCutsForLc3pi::~DaughtersInLHCbAndCutsForLc3pi( ) { ; }
-
 //=============================================================================
 // AndWithMinP function
 //=============================================================================
 bool DaughtersInLHCbAndCutsForLc3pi::applyCut( ParticleVector & theParticleVector ,
-                                               const HepMC::GenEvent * /* theEvent */ ,
+                                               const HepMC3::GenEvent * /* theEvent */ ,
                                                const LHCb::GenCollision * /* theHardInfo */ )
   const {
   ParticleVector::iterator it ;
@@ -78,16 +56,15 @@ bool DaughtersInLHCbAndCutsForLc3pi::applyCut( ParticleVector & theParticleVecto
 //=============================================================================
 // Functions to test if the Lc and 3 pi from the daughters are in acceptance
 //=============================================================================
-bool DaughtersInLHCbAndCutsForLc3pi::passCuts( const HepMC::GenParticle * theSignal ) const {
-  HepMC::GenVertex * EV = theSignal -> end_vertex() ;
+bool DaughtersInLHCbAndCutsForLc3pi::passCuts( const HepMC3::GenParticlePtr theSignal ) const {
+  auto EV = theSignal -> end_vertex() ;
   if ( 0 == EV ) return true ;
 
-  typedef std::vector< HepMC::GenParticle * > Particles ;
+  typedef std::vector< HepMC3::GenParticlePtr > Particles ;
   Particles stables ;
   Particles Lc_parents ;
   Particles lcdaughters ;
 
-  HepMC::GenVertex::particle_iterator iter ;
   // first check on the Lc origin : it should come from a B decay
   int bOK=0;
   debug() << "Check the Lc ancestor " <<endmsg;
@@ -96,18 +73,17 @@ bool DaughtersInLHCbAndCutsForLc3pi::passCuts( const HepMC::GenParticle * theSig
   goodzB=-999.;
   bool firstB = true;
 
- for ( iter = EV -> particles_begin( HepMC::ancestors ) ;
-        iter != EV -> particles_end( HepMC::ancestors ) ; ++iter ) {
+ for (auto anc : HepMC3::Relatives::ANCESTORS(EV)) {
 
-   Lc_parents.push_back( *iter );
+   Lc_parents.push_back( anc );
     // is there a B
-   if ( int(abs( (*iter) -> pdg_id() ))%10000> 500&& int(abs( (*iter) -> pdg_id() ))%10000<600 )bOK++;
-   if ( int(abs( (*iter) -> pdg_id() ))%10000> 5000&& int(abs( (*iter) -> pdg_id() ))%10000<6000 )bOK++;
+   if ( int(abs( (anc) -> pdg_id() ))%10000> 500&& int(abs( (anc) -> pdg_id() ))%10000<600 )bOK++;
+   if ( int(abs( (anc) -> pdg_id() ))%10000> 5000&& int(abs( (anc) -> pdg_id() ))%10000<6000 )bOK++;
 
    // will be used to be sure that the B of a relative is the same B as the Lc one
-   if ( ( int(abs( (*iter) -> pdg_id() ))%10000> 500&& int(abs( (*iter) -> pdg_id() ))%10000<600 && firstB == true) ||
-   ( int(abs( (*iter) -> pdg_id() ))%10000> 5000&& int(abs( (*iter) -> pdg_id() ))%10000<6000 && firstB == true) ){
-       goodzB = (*iter)->end_vertex()->position().z();
+   if ( ( int(abs( (anc) -> pdg_id() ))%10000> 500&& int(abs( (anc) -> pdg_id() ))%10000<600 && firstB == true) ||
+   ( int(abs( (anc) -> pdg_id() ))%10000> 5000&& int(abs( (anc) -> pdg_id() ))%10000<6000 && firstB == true) ){
+       goodzB = (anc)->end_vertex()->position().z();
        firstB = false;
    }
  }
@@ -127,10 +103,9 @@ break;
  debug() << "N beauty in Lc ancestors "<<bOK<<" vertex position "<<zB<<endmsg;
 
         //ask all Lc daughters in acceptance
-  for ( iter = EV -> particles_begin( HepMC::descendants ) ;
-        iter != EV -> particles_end( HepMC::descendants ) ; ++iter ) {
+    for (auto desc : HepMC3::Relatives::DESCENDANTS(EV)) {
     // Fill all daughters
-    if ( 0 == (*iter) -> end_vertex() ) stables.push_back( *iter ) ;
+    if ( 0 == (desc) -> end_vertex() ) stables.push_back( desc ) ;
 
   }
 
@@ -141,14 +116,13 @@ break;
   int npiLc=0;
   int npLc=0;
 
-  for ( iter = EV -> particles_begin( HepMC::descendants ) ;
-        iter != EV -> particles_end( HepMC::descendants ) ; ++iter ) {
+  for (auto desc : HepMC3::Relatives::DESCENDANTS(EV)) {
     // Fill all daughters but exclude photons (can be radiative photons)
-    if ( 0 == (*iter) -> end_vertex() )
-      if ( 22 != (*iter) -> pdg_id() )lcdaughters.push_back( *iter ) ;
-    if ( 211 == abs(int((*iter) -> pdg_id() )))npiLc++;
-    if ( 321 == abs(int((*iter) -> pdg_id())) )nKLc++;
-    if ( 2212 == abs(int((*iter) -> pdg_id())) )npLc++;
+    if ( 0 == (desc) -> end_vertex() )
+      if ( 22 != (desc) -> pdg_id() )lcdaughters.push_back( desc ) ;
+    if ( 211 == abs(int((desc) -> pdg_id() )))npiLc++;
+    if ( 321 == abs(int((desc) -> pdg_id())) )nKLc++;
+    if ( 2212 == abs(int((desc) -> pdg_id())) )npLc++;
 
   }
 
@@ -197,14 +171,14 @@ break;
   for ( Particles::const_iterator it = lcdaughters.begin() ; it != lcdaughters.end() ;
         ++it ) {
     debug() << "Daughter pT = " << (*it) -> momentum().perp()
-            << " p = " << (*it) -> momentum().rho() << endmsg ;
+            << " p = " << (*it) -> momentum().p3mod() << endmsg ;
 
   if ( (*it) -> momentum().perp() > maxpt )
       maxpt = (*it) -> momentum().perp() ;
     if ( (*it) -> momentum().perp() < minpt )
       minpt = (*it) -> momentum().perp() ;
-    if ( (*it) -> momentum().rho() < minp )
-      minp = (*it) -> momentum().rho() ;
+    if ( (*it) -> momentum().p3mod() < minp )
+      minp = (*it) -> momentum().p3mod() ;
   }
 
   debug() << "Min Pt = " << minpt
@@ -218,11 +192,9 @@ break;
   debug() << "Check for 3 pions in addition to Lc " <<zB<<endmsg;
         int Npions_inacc=0;
 
-  for ( iter = EV -> particles_begin( HepMC::relatives) ;
-        iter != EV -> particles_end( HepMC::relatives ) ; ++iter ) {
-
- if ( 0 == (*iter) -> end_vertex() ) stables.push_back( *iter ) ;
-  }
+    for (auto rel : theSignal->parent_event()->particles()) {
+      if (0 == (rel)->end_vertex()) stables.push_back(rel);
+    }
 
     //now loop on the stable particles
     //we  look at all the children of the B ancestor by requiring z>ZB
@@ -233,14 +205,14 @@ for ( Particles::const_iterator it = stables.begin() ; it != stables.end() ;
     double zB_B_parent_stables;
     zB_B_parent_stables=-999.;
     // bool firstB_stables = true;
-    HepMC::GenVertex * EV_parent_stables = (*it) -> production_vertex() ;
+    auto EV_parent_stables = (*it) -> production_vertex() ;
 
-    HepMC::GenVertex::particle_iterator parent = EV_parent_stables -> particles_begin( HepMC::ancestors );
+    auto parent = std::begin(HepMC3::Relatives::ANCESTORS(EV_parent_stables));
 
     //We want to be sure that the stables come from the same B as the Lc
     while( ( (int(abs( (*parent) -> pdg_id() ))%10000> 500 && int(abs( (*parent) -> pdg_id() ))%10000<600) ||
      (int(abs( (*parent) -> pdg_id() ))%10000> 5000 && int(abs( (*parent) -> pdg_id() ))%10000<6000) ) && ( (*parent) -> status() != 4 || (*parent) -> status() != 1 ) ){
-         parent = (*parent) -> production_vertex() -> particles_begin( HepMC::ancestors );
+         parent = std::begin(HepMC3::Relatives::ANCESTORS((*parent)->production_vertex()));
     }
 
     if ( (int(abs( (*parent) -> pdg_id() ))%10000> 500 && int(abs( (*parent) -> pdg_id() ))%10000<600) ||
diff --git a/Gen/GenCuts/src_future/DaughtersInLHCbAndCutsForLc3pi.h b/Gen/GenCuts/src_future/DaughtersInLHCbAndCutsForLc3pi.h
new file mode 100644
index 000000000..ffcca46bd
--- /dev/null
+++ b/Gen/GenCuts/src_future/DaughtersInLHCbAndCutsForLc3pi.h
@@ -0,0 +1,55 @@
+#pragma once
+
+// Include files
+// from Gaudi
+#include "GaudiAlg/GaudiTool.h"
+
+#include "GenInterfaces/IGenCutTool.h"
+#include "GaudiKernel/Transform4DTypes.h"
+#include "HepMC3/GenParticle.h"
+
+// from Gaudi
+#include "GaudiKernel/SystemOfUnits.h"
+
+/** @class DaughtersInLHCbAndCutsForLc DaughtersInLHCbAndCutsForLc3pi.h
+ *
+ *  Tool to keep events with daughters from signal particles
+ *  in LHCb and with p and pt cuts on Lc daughters.
+ *  Concrete implementation of IGenCutTool.
+ *
+ *  @author Patrick Robbe
+ *  @date   2012-02-07
+ */
+class DaughtersInLHCbAndCutsForLc3pi : public extends<GaudiTool, IGenCutTool> {
+public:
+  using extends::extends;
+
+  /** Accept events with daughters in LHCb and p/pt cuts on Lc daughters
+   *  (defined by min and max angles, different values for charged and neutrals)
+   *  Implements IGenCutTool::applyCut.
+   */
+  bool applyCut( ParticleVector & theParticleVector ,
+                 const HepMC3::GenEvent * theEvent ,
+                 const LHCb::GenCollision * theCollision ) const override;
+
+private:
+  /** Study a particle a returns true when all stable daughters
+   *  are in LHCb AndWithMinP
+   */
+  bool passCuts( const HepMC3::GenParticlePtr theSignal ) const ;
+
+  /** Momentum Cut function
+   *
+   */
+  bool momentumCut( const HepMC3::GenParticlePtr, double ) const ;
+
+  Gaudi::Property<double> m_chargedThetaMin  {this, "ChargedThetaMin"   ,  10 * Gaudi::Units::mrad};
+  Gaudi::Property<double> m_chargedThetaMax  {this, "ChargedThetaMax"   ,  400 * Gaudi::Units::mrad};
+  Gaudi::Property<double> m_neutralThetaMin  {this, "NeutralThetaMin"   ,  5 * Gaudi::Units::mrad};
+  Gaudi::Property<double> m_neutralThetaMax  {this, "NeutralThetaMax"   ,  400 * Gaudi::Units::mrad};
+  Gaudi::Property<double> m_lcptCut          {this, "LcPtCuts"          ,  1500 * Gaudi::Units::MeV};
+  Gaudi::Property<double> m_daughtersptminCut{this, "DaughtersPtMinCut" ,  150 * Gaudi::Units::MeV};
+  Gaudi::Property<double> m_daughtersptmaxCut{this, "DaughtersPtMaxCut" ,  150 * Gaudi::Units::MeV};
+  Gaudi::Property<double> m_daughterspminCut {this, "DaughtersPMinCut"  ,  1000 * Gaudi::Units::MeV};
+
+ };
diff --git a/Gen/GenCuts/src_future/DaughtersInLHCbAndFromB.cpp b/Gen/GenCuts/src_future/DaughtersInLHCbAndFromB.cpp
new file mode 100755
index 000000000..31a650175
--- /dev/null
+++ b/Gen/GenCuts/src_future/DaughtersInLHCbAndFromB.cpp
@@ -0,0 +1,35 @@
+// $Id: DaughtersInLHCbAndFromB.cpp,v 1.1 2007-11-26 13:44:34 jonrob Exp $
+// Include files
+
+// local
+#include "DaughtersInLHCbAndFromB.h"
+
+// from Gaudi
+
+// from HepMC
+#include "HepMC/GenParticle.h"
+#include "HepMC/GenVertex.h"
+
+// Kernel
+#include "Kernel/ParticleID.h"
+
+//-----------------------------------------------------------------------------
+// Implementation file for class : DaughtersInLHCbAndFromB
+//
+// 22/11/2007 : Chris Jones
+//-----------------------------------------------------------------------------
+
+// Declaration of the Tool Factory
+DECLARE_COMPONENT( DaughtersInLHCbAndFromB )
+
+//=============================================================================
+// Acceptance function
+//=============================================================================
+bool DaughtersInLHCbAndFromB::applyCut( ParticleVector & theParticleVector ,
+                                        const HepMC3::GenEvent * theEvent ,
+                                        const LHCb::GenCollision * theHardInfo )
+  const
+{
+  return ( m_fromBcuts->applyCut(theParticleVector,theEvent,theHardInfo) && 
+           DaughtersInLHCb::applyCut(theParticleVector,theEvent,theHardInfo) );
+}
diff --git a/Gen/GenCuts/src_future/DaughtersInLHCbAndFromB.h b/Gen/GenCuts/src_future/DaughtersInLHCbAndFromB.h
new file mode 100755
index 000000000..1b4a3c8fe
--- /dev/null
+++ b/Gen/GenCuts/src_future/DaughtersInLHCbAndFromB.h
@@ -0,0 +1,36 @@
+#pragma once
+
+// Include files
+#include "DaughtersInLHCb.h"
+
+/** @class DaughtersInLHCbAndFromB DaughtersInLHCbAndFromB.h
+ *
+ *  Inherits from DaughtersInLHCb adding the additional requirement that
+ *  the signal be from a b decay.
+ *
+ *  Concrete implementation of IGenCutTool.
+ *
+ *  @author Chris Jones
+ *  @date   22/11/2007
+ */
+
+class DaughtersInLHCbAndFromB : public extends<DaughtersInLHCb, IGenCutTool>
+{
+
+public:
+  using extends::extends;
+
+  /** Accept events with daughters in LHCb acceptance (defined by min and
+   *  max angles, different values for charged and neutrals)
+   *  Implements IGenCutTool::applyCut.
+   */
+  bool applyCut( ParticleVector & theParticleVector ,
+                 const HepMC3::GenEvent * theEvent ,
+                 const LHCb::GenCollision * theCollision ) const override;
+
+private: // data
+
+  /// From a b cut tool
+  ToolHandle<IGenCutTool> m_fromBcuts{"SignalIsFromBDecay", this};
+
+};
diff --git a/Gen/GenCuts/src/DaughtersInLHCbAndMassCut.cpp b/Gen/GenCuts/src_future/DaughtersInLHCbAndMassCut.cpp
similarity index 73%
rename from Gen/GenCuts/src/DaughtersInLHCbAndMassCut.cpp
rename to Gen/GenCuts/src_future/DaughtersInLHCbAndMassCut.cpp
index ed16b5b77..f6f1223c4 100755
--- a/Gen/GenCuts/src/DaughtersInLHCbAndMassCut.cpp
+++ b/Gen/GenCuts/src_future/DaughtersInLHCbAndMassCut.cpp
@@ -12,8 +12,9 @@
 #include "GaudiKernel/Vector4DTypes.h"
 
 // from HepMC
-#include "HepMC/GenParticle.h"
-#include "HepMC/GenVertex.h"
+#include "HepMC3/GenParticle.h"
+#include "HepMC3/GenVertex.h"
+#include "HepMC3/Relatives.h"
 
 // from Generators
 #include "GenEvent/HepMCUtils.h"
@@ -29,39 +30,11 @@
 DECLARE_COMPONENT( DaughtersInLHCbAndMassCut )
 
 
-//=============================================================================
-// Standard constructor, initializes variables
-//=============================================================================
-DaughtersInLHCbAndMassCut::DaughtersInLHCbAndMassCut( const std::string& type,
-                                  const std::string& name,
-                                  const IInterface* parent )
-  : GaudiTool ( type, name , parent ) {
-    declareInterface< IGenCutTool >( this ) ;
-    declareProperty( "ChargedThetaMin" , m_chargedThetaMin = 10 * Gaudi::Units::mrad ) ;
-    declareProperty( "ChargedThetaMax" , m_chargedThetaMax = 400 * Gaudi::Units::mrad ) ;
-    declareProperty( "NeutralThetaMin" , m_neutralThetaMin = 5 * Gaudi::Units::mrad ) ;
-    declareProperty( "NeutralThetaMax" , m_neutralThetaMax = 400 * Gaudi::Units::mrad ) ;
-    declareProperty( "LeptonOneID"     , m_LeptonOneID = -11 );
-    declareProperty( "LeptonTwoID"     , m_LeptonTwoID =  11 );
-    declareProperty( "HadronOneABSID"  , m_HadronOneABSID = 321 );
-    declareProperty( "HadronTwoABSID"  , m_HadronTwoABSID = 211 );
-    declareProperty( "DausPTMin"       , m_DausPTMin = 0.2 * Gaudi::Units::GeV );  
-    declareProperty( "eeMassMax"       , m_eeMassMax = 1.5 * Gaudi::Units::GeV );
-    declareProperty( "eeKstarMassMin"  , m_eeKstarMassMin = 4.0 * Gaudi::Units::GeV );
-    
-
-}
-
-//=============================================================================
-// Destructor 
-//=============================================================================
-DaughtersInLHCbAndMassCut::~DaughtersInLHCbAndMassCut( ) { ; }
-
 //=============================================================================
 // Acceptance function
 //=============================================================================
 bool DaughtersInLHCbAndMassCut::applyCut( ParticleVector & theParticleVector ,
-                                          const HepMC::GenEvent * /* theEvent */ ,
+                                          const HepMC3::GenEvent * /* theEvent */ ,
                                           const LHCb::GenCollision * /* theHardInfo */ )
   const {
   ParticleVector::iterator it ;
@@ -78,11 +51,11 @@ bool DaughtersInLHCbAndMassCut::applyCut( ParticleVector & theParticleVector ,
 //=============================================================================
 // Functions to test if all daughters are in acceptance
 //=============================================================================
-bool DaughtersInLHCbAndMassCut::passCuts( const HepMC::GenParticle * theSignal ) const {
-  HepMC::GenVertex * EV = theSignal -> end_vertex() ;
+bool DaughtersInLHCbAndMassCut::passCuts( const HepMC3::GenParticlePtr theSignal ) const {
+  auto EV = theSignal -> end_vertex() ;
   if ( 0 == EV ) return true ;
 
-  typedef std::vector< HepMC::GenParticle * > Particles ;
+  typedef std::vector< HepMC3::GenParticlePtr > Particles ;
   Particles stables ;
   
   Particles ePlusList ;
@@ -90,11 +63,8 @@ bool DaughtersInLHCbAndMassCut::passCuts( const HepMC::GenParticle * theSignal )
   Particles KaonList ;
   Particles PionList ;  
 
-  HepMC::GenVertex::particle_iterator iter ;
-
-  for ( iter = EV -> particles_begin( HepMC::descendants ) ; 
-        iter != EV -> particles_end( HepMC::descendants ) ; ++iter ) {
-    if ( 0 == (*iter) -> end_vertex() ) stables.push_back( *iter ) ;
+  for (auto desc : HepMC3::Relatives::DESCENDANTS(theSignal)) {
+    if ( 0 == (desc) -> end_vertex() ) stables.push_back( desc ) ;
   }  
 
   if ( stables.empty() )
@@ -125,9 +95,8 @@ bool DaughtersInLHCbAndMassCut::passCuts( const HepMC::GenParticle * theSignal )
          ( 16 == abs( (*it) -> pdg_id() ) ) ) continue ;
  
     // Don't use daughters of Lambda and KS:
-    HepMC::GenParticle * theParent ;
-    theParent = 
-      *( (*it) -> production_vertex() -> particles_in_const_begin() ) ;
+    auto theParent = 
+      *std::cbegin( (*it) -> production_vertex() -> particles_in() ) ;
     if ( 3122 == abs( theParent -> pdg_id() ) ) continue ;
     if ( 310 == theParent -> pdg_id() ) continue ;
 
@@ -172,8 +141,8 @@ bool DaughtersInLHCbAndMassCut::passCuts( const HepMC::GenParticle * theSignal )
   //====================================================================
   // Check mass 
   //====================================================================
-  HepMC::FourVector eeVect;
-  HepMC::FourVector eeKstarVect;
+  HepMC3::FourVector eeVect;
+  HepMC3::FourVector eeKstarVect;
   
   for ( Particles::const_iterator itePlus = ePlusList.begin() ; itePlus != ePlusList.end() ;
         ++itePlus ) {
diff --git a/Gen/GenCuts/src_future/DaughtersInLHCbAndMassCut.h b/Gen/GenCuts/src_future/DaughtersInLHCbAndMassCut.h
new file mode 100755
index 000000000..8a4d99a4c
--- /dev/null
+++ b/Gen/GenCuts/src_future/DaughtersInLHCbAndMassCut.h
@@ -0,0 +1,56 @@
+// $Id: DaughtersInLHCbAndMassCut.h,v 1.4 2008-05-29 14:21:59 gcorti Exp $
+#ifndef GENCUTS_DAUGHTERSINLHCBANDMASSCUT_H
+#define GENCUTS_DAUGHTERSINLHCBANDMASSCUT_H 1
+
+// Include files
+// from Gaudi
+#include "GaudiAlg/GaudiTool.h"
+
+#include "GenInterfaces/IGenCutTool.h"
+#include "GaudiKernel/Transform4DTypes.h"
+#include "HepMC3/GenParticle.h"
+
+// from Gaudi
+#include "GaudiKernel/SystemOfUnits.h"
+
+/** @class DaughtersInLHCbAndMassCut DaughtersInLHCbAndMassCut.h
+ *
+ *  Tool to keep events with daughters from signal particles
+ *  in LHCb acceptance.
+ *  Concrete implementation of IGenCutTool.
+ *
+ *  @author Patrick Robbe
+ *  @date   2005-08-24
+ */
+class DaughtersInLHCbAndMassCut : public extends<GaudiTool, IGenCutTool> {
+public:
+  using extends::extends;
+  /** Accept events with daughters in LHCb acceptance (defined by min and
+   *  max angles, different values for charged and neutrals)
+   *  Implements IGenCutTool::applyCut.
+   */
+  bool applyCut( ParticleVector & theParticleVector ,
+                 const HepMC3::GenEvent * theEvent ,
+                 const LHCb::GenCollision * theCollision ) const override;
+
+ private:
+  /** Study a particle a returns true when all stable daughters
+   *  are in LHCb acceptance
+   */
+  bool passCuts( const HepMC3::GenParticlePtr theSignal ) const ;
+
+  Gaudi::Property<double> m_chargedThetaMin {this, "ChargedThetaMin" , 10 * Gaudi::Units::mrad};
+  Gaudi::Property<double> m_chargedThetaMax {this, "ChargedThetaMax" , 400 * Gaudi::Units::mrad};
+  Gaudi::Property<double> m_neutralThetaMin {this, "NeutralThetaMin" , 5 * Gaudi::Units::mrad};
+  Gaudi::Property<double> m_neutralThetaMax {this, "NeutralThetaMax" , 400 * Gaudi::Units::mrad};
+  Gaudi::Property<double> m_DausPTMin       {this, "DausPTMin"       , 0.2 * Gaudi::Units::GeV };
+  Gaudi::Property<double> m_eeMassMax       {this, "eeMassMax"       , 1.5 * Gaudi::Units::GeV };
+  Gaudi::Property<double> m_eeKstarMassMin  {this, "eeKstarMassMin"  , 4.0 * Gaudi::Units::GeV };
+  Gaudi::Property<int>    m_LeptonOneID     {this, "LeptonOneID"     , -11 };
+  Gaudi::Property<int>    m_LeptonTwoID     {this, "LeptonTwoID"     , 11 };
+  Gaudi::Property<int>    m_HadronOneABSID  {this, "HadronOneABSID"  , 321 };
+  Gaudi::Property<int>    m_HadronTwoABSID  {this, "HadronTwoABSID"  , 211 };
+
+
+};
+#endif // GENCUTS_DAUGHTERSINLHCB_H
diff --git a/Gen/GenCuts/src/DaughtersInLHCbAndWithDaughAndBCuts.cpp b/Gen/GenCuts/src_future/DaughtersInLHCbAndWithDaughAndBCuts.cpp
similarity index 66%
rename from Gen/GenCuts/src/DaughtersInLHCbAndWithDaughAndBCuts.cpp
rename to Gen/GenCuts/src_future/DaughtersInLHCbAndWithDaughAndBCuts.cpp
index f73353583..d5268aa09 100644
--- a/Gen/GenCuts/src/DaughtersInLHCbAndWithDaughAndBCuts.cpp
+++ b/Gen/GenCuts/src_future/DaughtersInLHCbAndWithDaughAndBCuts.cpp
@@ -12,12 +12,14 @@
 #include "GaudiKernel/Vector4DTypes.h"
 
 // from HepMC
-#include "HepMC/GenParticle.h"
-#include "HepMC/GenVertex.h"
+#include "HepMC3/GenParticle.h"
+#include "HepMC3/GenVertex.h"
 
 // from Generators
 #include "GenEvent/HepMCUtils.h"
 
+#include "HepMC3/Relatives.h"
+
 //-----------------------------------------------------------------------------
 // Implementation file for class : DaughtersInLHCbAndWithDaughAndBCuts
 //
@@ -29,45 +31,11 @@
 DECLARE_COMPONENT( DaughtersInLHCbAndWithDaughAndBCuts )
 
 
-//=============================================================================
-// Standard constructor, initializes variables
-//=============================================================================
-DaughtersInLHCbAndWithDaughAndBCuts::DaughtersInLHCbAndWithDaughAndBCuts( const std::string& type,
-                                                                          const std::string& name,
-                                                                          const IInterface* parent )
-  : GaudiTool ( type, name , parent ) {
-  declareInterface< IGenCutTool >( this ) ;
-  declareProperty( "ChargedThetaMin" , m_chargedThetaMin = 10 * Gaudi::Units::mrad ) ;
-  declareProperty( "ChargedThetaMax" , m_chargedThetaMax = 400 * Gaudi::Units::mrad ) ;
-  declareProperty( "NeutralThetaMin" , m_neutralThetaMin = 5 * Gaudi::Units::mrad ) ;
-  declareProperty( "NeutralThetaMax" , m_neutralThetaMax = 400 * Gaudi::Units::mrad ) ;
-  declareProperty( "LongLivedThetaMin" , m_llThetaMin = 0 * Gaudi::Units::mrad ) ;
-  declareProperty( "LongLivedThetaMax" , m_llThetaMax = 400 * Gaudi::Units::mrad ) ;
-  declareProperty( "MinMuonP" ,        m_minMuonP = 0 * Gaudi::Units::MeV ) ;
-  declareProperty( "MinTrackP" ,       m_minTrackP = 0 * Gaudi::Units::MeV ) ;
-  declareProperty( "MinLongLivedP" ,        m_minLongLivedP = 0 * Gaudi::Units::MeV ) ;
-  declareProperty( "MinLongLivedDaughP" ,        m_minLongLivedDaughP = 0 * Gaudi::Units::MeV ) ;
-  declareProperty( "MinSumP" ,        m_minSumP = 0* Gaudi::Units::MeV ) ;
-  declareProperty( "MinBP" ,        m_minBP = 0 * Gaudi::Units::MeV ) ;
-  declareProperty( "MinMuonPT" ,        m_minMuonPT = 0 * Gaudi::Units::MeV ) ;
-  declareProperty( "MinTrackPT" ,       m_minTrackPT = 0 * Gaudi::Units::MeV ) ;
-  declareProperty( "MinLongLivedPT" ,      m_minLongLivedPT = 0 * Gaudi::Units::MeV ) ;
-  declareProperty( "MinLongLivedDaughPT" ,      m_minLongLivedDaughPT = 0 * Gaudi::Units::MeV ) ;
-  declareProperty( "MinBPT" ,        m_minBPT = 0 * Gaudi::Units::MeV ) ;
-  declareProperty( "MinSumPT" ,        m_minSumPT = 0* Gaudi::Units::MeV ) ;
-  declareProperty( "MinBFD" ,        m_minBFD = 0 * Gaudi::Units::mm ) ;
-}
-
-//=============================================================================
-// Destructor 
-//=============================================================================
-DaughtersInLHCbAndWithDaughAndBCuts::~DaughtersInLHCbAndWithDaughAndBCuts( ) { ; }
-
 //=============================================================================
 // AndWithMinP function
 //=============================================================================
 bool DaughtersInLHCbAndWithDaughAndBCuts::applyCut( ParticleVector & theParticleVector ,
-							const HepMC::GenEvent * /* theEvent */ ,
+							const HepMC3::GenEvent * /* theEvent */ ,
 							const LHCb::GenCollision * /* theHardInfo */ )
   const {
   ParticleVector::iterator it ;
@@ -85,8 +53,8 @@ bool DaughtersInLHCbAndWithDaughAndBCuts::applyCut( ParticleVector & theParticle
 //=============================================================================
 // Functions to test if all daughters are in AndWithMinP
 //=============================================================================
-bool DaughtersInLHCbAndWithDaughAndBCuts::passCuts( const HepMC::GenParticle * theSignal ) const {
-  HepMC::GenVertex * EV = theSignal -> end_vertex() ;
+bool DaughtersInLHCbAndWithDaughAndBCuts::passCuts( const HepMC3::GenParticlePtr theSignal ) const {
+  auto EV = theSignal -> end_vertex() ;
   if ( 0 == EV ) return true ;
 
   double fakeSum(0.);
@@ -102,15 +70,13 @@ bool DaughtersInLHCbAndWithDaughAndBCuts::passCuts( const HepMC::GenParticle * t
   pass = transverseMomentumCut(theSignal, m_minBPT,fakeSum );
   if (!pass) return false;
   
-  typedef std::vector< HepMC::GenParticle * > Particles ;
+  typedef std::vector< HepMC3::GenParticlePtr > Particles ;
   Particles stables ;
   Particles unstables;
-  HepMC::GenVertex::particle_iterator iter ;
 
-  for ( iter = EV -> particles_begin( HepMC::descendants ) ; 
-        iter != EV -> particles_end( HepMC::descendants ) ; ++iter ) {
-    if ( 0 == (*iter) -> end_vertex() ) stables.push_back( *iter ) ;
-    else unstables.push_back( *iter ) ;
+  for (auto desc : HepMC3::Relatives::DESCENDANTS(EV)) {
+    if ( 0 == desc -> end_vertex() ) stables.push_back( desc ) ;
+    else unstables.push_back( desc ) ;
   }  
 
   if ( stables.empty() )
@@ -159,9 +125,8 @@ bool DaughtersInLHCbAndWithDaughAndBCuts::passCuts( const HepMC::GenParticle * t
          ( 14 == abs( (*it) -> pdg_id() ) ) || 
          ( 16 == abs( (*it) -> pdg_id() ) ) ) continue ;
  
-    HepMC::GenParticle * theParent ;
-    theParent =
-      *( (*it) -> production_vertex() -> particles_in_const_begin() ) ;
+    auto theParent =
+      *std::cbegin( (*it) -> production_vertex() -> particles_in() ) ;
 
    // Consider only gammas from pi0 and eta
     if ( 22 == (*it) -> pdg_id() ) {
@@ -225,7 +190,7 @@ bool DaughtersInLHCbAndWithDaughAndBCuts::passCuts( const HepMC::GenParticle * t
   return true ;
 }
 
-bool DaughtersInLHCbAndWithDaughAndBCuts::transverseMomentumCut( const HepMC::GenParticle *p,
+bool DaughtersInLHCbAndWithDaughAndBCuts::transverseMomentumCut( const HepMC3::GenParticlePtr p,
                                                                  const double pTmin,
                                                                  double& sumPt ) const
 {
@@ -249,7 +214,7 @@ bool DaughtersInLHCbAndWithDaughAndBCuts::transverseMomentumCut( const HepMC::Ge
 }
 
 
-bool DaughtersInLHCbAndWithDaughAndBCuts::momentumCut( const HepMC::GenParticle *p, 
+bool DaughtersInLHCbAndWithDaughAndBCuts::momentumCut( const HepMC3::GenParticlePtr p, 
                                                        const double pmin,
                                                        double& sumP ) const 
 {
@@ -276,7 +241,7 @@ bool DaughtersInLHCbAndWithDaughAndBCuts::momentumCut( const HepMC::GenParticle
    return pass;
 }
 
-bool DaughtersInLHCbAndWithDaughAndBCuts::flightCut( const HepMC::GenParticle *p,
+bool DaughtersInLHCbAndWithDaughAndBCuts::flightCut( const HepMC3::GenParticlePtr p,
 								const double fdmin ) const
 {
   bool pass(true);
@@ -286,13 +251,13 @@ bool DaughtersInLHCbAndWithDaughAndBCuts::flightCut( const HepMC::GenParticle *p
   if (p->production_vertex()==0 || p->end_vertex()==0)
     return false;
 
-  px = p->production_vertex()->point3d().x();
-  py = p->production_vertex()->point3d().y();
-  pz = p->production_vertex()->point3d().z();
+  px = p->production_vertex()->position().x();
+  py = p->production_vertex()->position().y();
+  pz = p->production_vertex()->position().z();
 
-  dx = p->end_vertex()->point3d().x();
-  dy = p->end_vertex()->point3d().y();
-  dz = p->end_vertex()->point3d().z();
+  dx = p->end_vertex()->position().x();
+  dy = p->end_vertex()->position().y();
+  dz = p->end_vertex()->position().z();
   
   double FD = sqrt(pow(dx-px,2)+pow(dy-py,2)+pow(dz-pz,2));
   if (FD<fdmin)
diff --git a/Gen/GenCuts/src_future/DaughtersInLHCbAndWithDaughAndBCuts.h b/Gen/GenCuts/src_future/DaughtersInLHCbAndWithDaughAndBCuts.h
new file mode 100644
index 000000000..7f1a24c55
--- /dev/null
+++ b/Gen/GenCuts/src_future/DaughtersInLHCbAndWithDaughAndBCuts.h
@@ -0,0 +1,76 @@
+#pragma once
+
+// Include files
+// from Gaudi
+#include "GaudiAlg/GaudiTool.h"
+
+#include "GenInterfaces/IGenCutTool.h"
+#include "GaudiKernel/Transform4DTypes.h"
+#include "HepMC3/GenParticle.h"
+
+// from Gaudi
+#include "GaudiKernel/SystemOfUnits.h"
+
+/** @class DaughtersInLHCbAndWithDaughAndBCuts DaughtersInLHCbAndWithDaughAndBCuts.h
+ *
+ *  Tool to keep events with daughters from signal particles
+ *  in LHCb AndWithMinP.
+ *  Concrete implementation of IGenCutTool.
+ *
+ *  @author Alex Shires
+ *  @date   2011-03-02
+ */
+class DaughtersInLHCbAndWithDaughAndBCuts : public extends<GaudiTool, IGenCutTool> {
+ public:
+   using extends::extends;
+  /** Accept events with daughters in LHCb AndWithMinP (defined by min and
+   *  max angles, different values for charged and neutrals)
+   *  Implements IGenCutTool::applyCut.
+   */
+  bool applyCut( ParticleVector & theParticleVector ,
+                 const HepMC3::GenEvent * theEvent ,
+                 const LHCb::GenCollision * theCollision ) const override;
+
+ private:
+  /** Study a particle a returns true when all stable daughters
+   *  are in LHCb AndWithMinP
+   */
+  bool passCuts( const HepMC3::GenParticlePtr theSignal ) const ;
+
+  /** Flight Distance Cut function
+   *
+   */
+  bool flightCut( const HepMC3::GenParticlePtr , double ) const ;
+
+  /** Momentum Cut function
+   *
+   */
+  bool momentumCut( const HepMC3::GenParticlePtr p, const double pMin, double& sumP) const ;
+
+  /** Transverse Momentum Cut function
+   *
+   */
+  bool transverseMomentumCut( const HepMC3::GenParticlePtr p, const double pTMin, double& sumPt) const ;
+
+
+  Gaudi::Property<double> m_chargedThetaMin      {this, "ChargedThetaMin"     ,10 * Gaudi::Units::mrad};
+  Gaudi::Property<double> m_chargedThetaMax      {this, "ChargedThetaMax"     ,400 * Gaudi::Units::mrad};
+  Gaudi::Property<double> m_neutralThetaMin      {this, "NeutralThetaMin"     ,5 * Gaudi::Units::mrad};
+  Gaudi::Property<double> m_neutralThetaMax      {this, "NeutralThetaMax"     ,400 * Gaudi::Units::mrad};
+  Gaudi::Property<double> m_llThetaMin           {this, "LongLivedThetaMin"   ,0 * Gaudi::Units::mrad};
+  Gaudi::Property<double> m_llThetaMax           {this, "LongLivedThetaMax"   ,400 * Gaudi::Units::mrad};
+  Gaudi::Property<double> m_minMuonP             {this, "MinMuonP"            ,0 * Gaudi::Units::MeV};
+  Gaudi::Property<double> m_minTrackP            {this, "MinTrackP"           ,0 * Gaudi::Units::MeV};
+  Gaudi::Property<double> m_minLongLivedP        {this, "MinLongLivedP"       ,0 * Gaudi::Units::MeV};
+  Gaudi::Property<double> m_minLongLivedDaughP   {this, "MinLongLivedDaughP"  ,0 * Gaudi::Units::MeV};
+  Gaudi::Property<double> m_minSumP              {this, "MinSumP"             ,0* Gaudi::Units::MeV};
+  Gaudi::Property<double> m_minBP                {this, "MinBP"               ,0 * Gaudi::Units::MeV};
+  Gaudi::Property<double> m_minMuonPT            {this, "MinMuonPT"           ,0 * Gaudi::Units::MeV};
+  Gaudi::Property<double> m_minTrackPT           {this, "MinTrackPT"          ,0 * Gaudi::Units::MeV};
+  Gaudi::Property<double> m_minLongLivedPT       {this, "MinLongLivedPT"      ,0 * Gaudi::Units::MeV};
+  Gaudi::Property<double> m_minLongLivedDaughPT  {this, "MinLongLivedDaughPT" ,0 * Gaudi::Units::MeV};
+  Gaudi::Property<double> m_minBPT               {this, "MinBPT"              ,0 * Gaudi::Units::MeV};
+  Gaudi::Property<double> m_minSumPT             {this, "MinSumPT"            ,0* Gaudi::Units::MeV};
+  Gaudi::Property<double> m_minBFD               {this, "MinBFD"              ,0 * Gaudi::Units::mm};
+
+};
diff --git a/Gen/GenCuts/src/DaughtersInLHCbAndWithMinP.cpp b/Gen/GenCuts/src_future/DaughtersInLHCbAndWithMinP.cpp
similarity index 65%
rename from Gen/GenCuts/src/DaughtersInLHCbAndWithMinP.cpp
rename to Gen/GenCuts/src_future/DaughtersInLHCbAndWithMinP.cpp
index ccc7e6def..9a3ec6fa3 100644
--- a/Gen/GenCuts/src/DaughtersInLHCbAndWithMinP.cpp
+++ b/Gen/GenCuts/src_future/DaughtersInLHCbAndWithMinP.cpp
@@ -12,11 +12,12 @@
 #include "GaudiKernel/Vector4DTypes.h"
 
 // from HepMC
-#include "HepMC/GenParticle.h"
-#include "HepMC/GenVertex.h"
+#include "HepMC3/GenParticle.h"
+#include "HepMC3/GenVertex.h"
 
 // from Generators
 #include "GenEvent/HepMCUtils.h"
+#include "HepMC3/Relatives.h"
 
 //-----------------------------------------------------------------------------
 // Implementation file for class : DaughtersInLHCbAndWithMinP
@@ -29,32 +30,11 @@
 DECLARE_COMPONENT( DaughtersInLHCbAndWithMinP )
 
 
-//=============================================================================
-// Standard constructor, initializes variables
-//=============================================================================
-DaughtersInLHCbAndWithMinP::DaughtersInLHCbAndWithMinP( const std::string& type,
-                                  const std::string& name,
-                                  const IInterface* parent )
-  : GaudiTool ( type, name , parent ) {
-    declareInterface< IGenCutTool >( this ) ;
-    declareProperty( "ChargedThetaMin" , m_chargedThetaMin = 10 * Gaudi::Units::mrad ) ;
-    declareProperty( "ChargedThetaMax" , m_chargedThetaMax = 400 * Gaudi::Units::mrad ) ;
-    declareProperty( "NeutralThetaMin" , m_neutralThetaMin = 5 * Gaudi::Units::mrad ) ;
-    declareProperty( "NeutralThetaMax" , m_neutralThetaMax = 400 * Gaudi::Units::mrad ) ;
-    declareProperty( "MinMuonP" ,        m_minMuonP = 3000 * Gaudi::Units::MeV ) ;
-    declareProperty( "MinTrackP" ,       m_minTrackP = 1000 * Gaudi::Units::MeV ) ;
-}
-
-//=============================================================================
-// Destructor 
-//=============================================================================
-DaughtersInLHCbAndWithMinP::~DaughtersInLHCbAndWithMinP( ) { ; }
-
 //=============================================================================
 // AndWithMinP function
 //=============================================================================
 bool DaughtersInLHCbAndWithMinP::applyCut( ParticleVector & theParticleVector ,
-                                const HepMC::GenEvent * /* theEvent */ ,
+                                const HepMC3::GenEvent * /* theEvent */ ,
                                 const LHCb::GenCollision * /* theHardInfo */ )
   const {
   ParticleVector::iterator it ;
@@ -72,17 +52,15 @@ bool DaughtersInLHCbAndWithMinP::applyCut( ParticleVector & theParticleVector ,
 //=============================================================================
 // Functions to test if all daughters are in AndWithMinP
 //=============================================================================
-bool DaughtersInLHCbAndWithMinP::passCuts( const HepMC::GenParticle * theSignal ) const {
-  HepMC::GenVertex * EV = theSignal -> end_vertex() ;
+bool DaughtersInLHCbAndWithMinP::passCuts( const HepMC3::GenParticlePtr theSignal ) const {
+  auto EV = theSignal -> end_vertex() ;
   if ( 0 == EV ) return true ;
 
-  typedef std::vector< HepMC::GenParticle * > Particles ;
+  typedef std::vector< HepMC3::GenParticlePtr > Particles ;
   Particles stables ;
-  HepMC::GenVertex::particle_iterator iter ;
 
-  for ( iter = EV -> particles_begin( HepMC::descendants ) ; 
-        iter != EV -> particles_end( HepMC::descendants ) ; ++iter ) {
-    if ( 0 == (*iter) -> end_vertex() ) stables.push_back( *iter ) ;
+  for (auto desc : HepMC3::Relatives::DESCENDANTS(theSignal)) {
+    if ( 0 == (desc) -> end_vertex() ) stables.push_back( desc ) ;
   }  
 
   if ( stables.empty() )
@@ -106,9 +84,8 @@ bool DaughtersInLHCbAndWithMinP::passCuts( const HepMC::GenParticle * theSignal
          ( 16 == abs( (*it) -> pdg_id() ) ) ) continue ;
  
     // Don't use daughters of Lambda and KS:
-    HepMC::GenParticle * theParent ;
-    theParent = 
-      *( (*it) -> production_vertex() -> particles_in_const_begin() ) ;
+    auto theParent = 
+      *std::cbegin( (*it) -> production_vertex() -> particles_in() ) ;
     if ( 3122 == abs( theParent -> pdg_id() ) ) continue ;
     if ( 310 == theParent -> pdg_id() ) continue ;
 
@@ -149,7 +126,7 @@ bool DaughtersInLHCbAndWithMinP::passCuts( const HepMC::GenParticle * theSignal
 }
 
 
-bool DaughtersInLHCbAndWithMinP::momentumCut( const HepMC::GenParticle *p, 
+bool DaughtersInLHCbAndWithMinP::momentumCut( const HepMC3::GenParticlePtr p, 
                                            const double pmin ) const 
 {
    bool pass(true);  
diff --git a/Gen/GenCuts/src_future/DaughtersInLHCbAndWithMinP.h b/Gen/GenCuts/src_future/DaughtersInLHCbAndWithMinP.h
new file mode 100644
index 000000000..409d7f3bd
--- /dev/null
+++ b/Gen/GenCuts/src_future/DaughtersInLHCbAndWithMinP.h
@@ -0,0 +1,52 @@
+#pragma once
+
+// Include files
+// from Gaudi
+#include "GaudiAlg/GaudiTool.h"
+
+#include "GenInterfaces/IGenCutTool.h"
+#include "GaudiKernel/Transform4DTypes.h"
+#include "HepMC3/GenParticle.h"
+
+// from Gaudi
+#include "GaudiKernel/SystemOfUnits.h"
+
+/** @class DaughtersInLHCbAndWithMinP DaughtersInLHCbAndWithMinP.h
+ *
+ *  Tool to keep events with daughters from signal particles
+ *  in LHCb AndWithMinP.
+ *  Concrete implementation of IGenCutTool.
+ *
+ *  @author Alex Shires
+ *  @date   2011-03-02
+ */
+class DaughtersInLHCbAndWithMinP : public extends<GaudiTool, IGenCutTool> {
+ public:
+   using extends::extends;
+
+  /** Accept events with daughters in LHCb AndWithMinP (defined by min and
+   *  max angles, different values for charged and neutrals)
+   *  Implements IGenCutTool::applyCut.
+   */
+  bool applyCut( ParticleVector & theParticleVector ,
+                 const HepMC3::GenEvent * theEvent ,
+                 const LHCb::GenCollision * theCollision ) const override;
+
+ private:
+  /** Study a particle a returns true when all stable daughters
+   *  are in LHCb AndWithMinP
+   */
+  bool passCuts( const HepMC3::GenParticlePtr theSignal ) const ;
+
+  /** Momentum Cut function
+   *
+   */
+  bool momentumCut( const HepMC3::GenParticlePtr, double ) const ;
+
+  Gaudi::Property<double> m_chargedThetaMin {this, "ChargedThetaMin" ,10 * Gaudi::Units::mrad};
+  Gaudi::Property<double> m_chargedThetaMax {this, "ChargedThetaMax" ,400 * Gaudi::Units::mrad};
+  Gaudi::Property<double> m_neutralThetaMin {this, "NeutralThetaMin" ,5 * Gaudi::Units::mrad};
+  Gaudi::Property<double> m_neutralThetaMax {this, "NeutralThetaMax" ,400 * Gaudi::Units::mrad};
+  Gaudi::Property<double> m_minMuonP        {this, "MinMuonP" ,       3000 * Gaudi::Units::MeV};
+  Gaudi::Property<double> m_minTrackP       {this, "MinTrackP" ,      1000 * Gaudi::Units::MeV};
+};
-- 
GitLab


From 720e37dfa6ca5e24bfe137170af2e9a856cd50c2 Mon Sep 17 00:00:00 2001
From: Dominik Muller <dominik.muller@cern.ch>
Date: Tue, 26 Nov 2019 09:56:05 +0100
Subject: [PATCH 42/90] Basic modifications to LoKi based cut tools for future
 framework

---
 Calo/CaloMoniSim/src/MCCaloMonitor.cpp        | 23 ++++----
 Gen/GenCuts/CMakeLists.txt                    |  5 +-
 .../GenericFullEventCutTool.cpp               | 32 +++--------
 .../{src => src_future}/GenericGenCutTool.cpp | 25 ++++-----
 .../{src => src_future}/GenericGenCutTool.h   |  7 ++-
 .../GenericGenCutToolWithDecay.cpp            | 56 ++++++++++++-------
 6 files changed, 76 insertions(+), 72 deletions(-)
 rename Gen/GenCuts/{src => src_future}/GenericFullEventCutTool.cpp (88%)
 rename Gen/GenCuts/{src => src_future}/GenericGenCutTool.cpp (96%)
 rename Gen/GenCuts/{src => src_future}/GenericGenCutTool.h (98%)
 rename Gen/GenCuts/{src => src_future}/GenericGenCutToolWithDecay.cpp (90%)

diff --git a/Calo/CaloMoniSim/src/MCCaloMonitor.cpp b/Calo/CaloMoniSim/src/MCCaloMonitor.cpp
index 9ec2b7d71..ab6ae55e4 100755
--- a/Calo/CaloMoniSim/src/MCCaloMonitor.cpp
+++ b/Calo/CaloMoniSim/src/MCCaloMonitor.cpp
@@ -108,7 +108,7 @@ void MCCaloMonitor::operator()(const LHCb::MCCaloHits& CaloHits) const {
     m_hName1->fill(hit->activeE(), 1.);
     m_hName2->fill(hit->activeE(), hit->activeE());
     m_hName3->fill(binTime, hit->activeE());
-    if (m_DivMonitor) {
+    if (m_DivMonitor.value()) {
       if ((2 == zone && m_DetectorName != "Hcal") ||
           (1 == zone && m_DetectorName == "Hcal")) {
         if (m_detector->valid(ID)) {
@@ -206,17 +206,20 @@ void MCCaloMonitor::bookHistograms() {
   std::string tmp_hName45 =
       "Number of Subhits in the " + m_DetectorName + " ( BC = 4  )";
   m_hName1 = book1D(11, tmp_hName1, m_MinE, m_MaxE, 100);
-  m_hName1a = book1D(111, tmp_hName1a, m_MinE, m_MaxE, 100);
-  m_hName1b = book1D(112, tmp_hName1b, m_MinE, m_MaxE, 100);
-  m_hName1c = book1D(113, tmp_hName1c, m_MinE, m_MaxE, 100);
   m_hName2 = book1D(12, tmp_hName2, m_MinE, m_MaxE, 100);
-  m_hName2a = book1D(121, tmp_hName2a, m_MinE, m_MaxE, 100);
-  m_hName2b = book1D(122, tmp_hName2b, m_MinE, m_MaxE, 100);
-  m_hName2c = book1D(123, tmp_hName2c, m_MinE, m_MaxE, 100);
   m_hName3 = book1D(13, tmp_hName3, MinT, MaxT, m_Bin);
-  m_hName3a = book1D(131, tmp_hName3a, MinT, MaxT, m_Bin);
-  m_hName3b = book1D(132, tmp_hName3b, MinT, MaxT, m_Bin);
-  m_hName3c = book1D(133, tmp_hName3c, MinT, MaxT, m_Bin);
+
+  if(m_DivMonitor.value()){
+    m_hName1a = book1D(111, tmp_hName1a, m_MinE, m_MaxE, 100);
+    m_hName1b = book1D(112, tmp_hName1b, m_MinE, m_MaxE, 100);
+    m_hName1c = book1D(113, tmp_hName1c, m_MinE, m_MaxE, 100);
+    m_hName2a = book1D(121, tmp_hName2a, m_MinE, m_MaxE, 100);
+    m_hName2b = book1D(122, tmp_hName2b, m_MinE, m_MaxE, 100);
+    m_hName2c = book1D(123, tmp_hName2c, m_MinE, m_MaxE, 100);
+    m_hName3a = book1D(131, tmp_hName3a, MinT, MaxT, m_Bin);
+    m_hName3b = book1D(132, tmp_hName3b, MinT, MaxT, m_Bin);
+    m_hName3c = book1D(133, tmp_hName3c, MinT, MaxT, m_Bin);
+  }
   m_hName4 = book1D(14, tmp_hName4, 0, 1000, 100);
   m_hName40 = book1D(140, tmp_hName40, 0, 1000, 100);
   m_hName41 = book1D(141, tmp_hName41, 0, 1000, 100);
diff --git a/Gen/GenCuts/CMakeLists.txt b/Gen/GenCuts/CMakeLists.txt
index cc4b49555..c2c047e97 100644
--- a/Gen/GenCuts/CMakeLists.txt
+++ b/Gen/GenCuts/CMakeLists.txt
@@ -4,7 +4,8 @@
 gaudi_subdir(GenCuts v4r0)
 
 gaudi_depends_on_subdirs(GaudiAlg
-                         Gen/GenInterfaces)
+                         Gen/GenInterfaces
+                         Gen/LoKiGen)
 
 find_package(FastJet)
 find_package(Boost)
@@ -15,5 +16,5 @@ AddHepMC3()
 gaudi_add_module(GenCuts
                  src_future/*.cpp
                  INCLUDE_DIRS GenInterfaces ${HEPMC3_INCLUDE_DIR}
-                 LINK_LIBRARIES GaudiAlgLib GeneratorsLib ${HEPMC3_LIBRARIES})
+                 LINK_LIBRARIES GaudiAlgLib GeneratorsLib ${HEPMC3_LIBRARIES} LoKiGenLib)
 
diff --git a/Gen/GenCuts/src/GenericFullEventCutTool.cpp b/Gen/GenCuts/src_future/GenericFullEventCutTool.cpp
similarity index 88%
rename from Gen/GenCuts/src/GenericFullEventCutTool.cpp
rename to Gen/GenCuts/src_future/GenericFullEventCutTool.cpp
index 7483e4bc9..63c8f2741 100644
--- a/Gen/GenCuts/src/GenericFullEventCutTool.cpp
+++ b/Gen/GenCuts/src_future/GenericFullEventCutTool.cpp
@@ -11,11 +11,11 @@
 // =============================================================================
 // GenEvent
 // =============================================================================
-#include "Event/HepMCEvent.h"
+#include "HepMC3/GenEvent.h"
 // =============================================================================
 // Generators
 // =============================================================================
-#include "MCInterfaces/IFullGenEventCutTool.h"
+#include "GenInterfaces/IFullGenEventCutTool.h"
 // =============================================================================
 // LoKi
 // =============================================================================
@@ -62,8 +62,8 @@ namespace LoKi
      *  @see IFullGEnEventrCutTool
      */
     bool studyFullEvent
-    ( LHCb::HepMCEvents*       theEvents        ,
-      LHCb::GenCollisions*  /* theCollisions */ ) const override;
+    ( const std::vector<HepMC3::GenEvent> & theEvents ,
+      const LHCb::GenCollisions & /* theCollisions */ ) const override;
     // =========================================================================
   public:
     // =========================================================================
@@ -160,34 +160,20 @@ StatusCode LoKi::FullGenEventCut::decode()
  */
 // ============================================================================
 bool LoKi::FullGenEventCut::studyFullEvent
-( LHCb::HepMCEvents*       theEvents        ,
-  LHCb::GenCollisions*  /* theCollisions */ ) const
+( const std::vector<HepMC3::GenEvent> & theEvents ,
+  const LHCb::GenCollisions & /* theCollisions */ ) const
 {
-  //
-  if ( 0 == theEvents )
-  {
-    Error ( "LHCb::HepMCEvents* points to NULL, reject event") ;
-    return false ;                                             // RETURN
-  }
   //
   Assert ( !updateRequired () , "Update is required!" ) ;
   //
   // copy all particles into one constainer
   LoKi::GenTypes::GenContainer particles ;
   //
-  for ( LHCb::HepMCEvents::const_iterator ievent = theEvents->begin() ;
-        theEvents -> end() != ievent ;  ++ievent )
+  for ( auto & evt: theEvents)
   {
-    //
-    const LHCb::HepMCEvent* event = *ievent ;
-    if ( 0 == event )                   { continue ; }         // CONTINUE
-    //
-    const HepMC::GenEvent*  evt   = event -> pGenEvt () ;
-    if ( 0 == evt   )                   { continue ; }         // CONTINUE
-    //
     particles.insert ( particles.end ()          ,
-                       evt -> particles_begin () ,
-                       evt -> particles_end   () ) ;
+                       std::begin(evt.particles()) ,
+                       std::end(evt.particles()) ) ;
   }
   //
   // evaluate the functor:
diff --git a/Gen/GenCuts/src/GenericGenCutTool.cpp b/Gen/GenCuts/src_future/GenericGenCutTool.cpp
similarity index 96%
rename from Gen/GenCuts/src/GenericGenCutTool.cpp
rename to Gen/GenCuts/src_future/GenericGenCutTool.cpp
index 434969262..07524fda2 100644
--- a/Gen/GenCuts/src/GenericGenCutTool.cpp
+++ b/Gen/GenCuts/src_future/GenericGenCutTool.cpp
@@ -21,10 +21,6 @@
 // =============================================================================
 #include "AIDA/IHistogram2D.h"
 // =============================================================================
-// Generators 
-// =============================================================================
-#include "MCInterfaces/IGenCutTool.h"
-// =============================================================================
 // PartProp
 // =============================================================================
 #include "Kernel/iNode.h"
@@ -40,7 +36,6 @@
 #include "LoKi/Primitives.h"
 #include "LoKi/GenTypes.h"
 #include "LoKi/GenParticles.h"
-#include "LoKi/IGenDecay.h"
 #include "LoKi/IGenHybridFactory.h"
 #include "LoKi/Trees.h"
 #include "LoKi/PrintHepMCDecay.h"
@@ -49,6 +44,10 @@
 #include "LoKi/PrintHepMCDecay.h"
 #include "LoKi/GenDecayChain.h"
 #include "LoKi/ParticleProperties.h"
+#include "HepMC3/GenEvent.h"
+#include "HepMC3/GenParticle.h"
+#include "HepMC3/GenVertex.h"
+#include "HepMC3/Relatives.h"
 // =============================================================================
 // ROOT
 // =============================================================================
@@ -68,15 +67,15 @@ namespace
   // ===========================================================================
   /// the invalid tree 
   const Decays::IGenDecay::Tree s_TREE = 
-    Decays::Trees::Invalid_<const HepMC::GenParticle*>() ;
+    Decays::Trees::Invalid_<HepMC3::ConstGenParticlePtr>() ;
   /// the invalid node 
   const Decays::Node            s_NODE = Decays::Nodes::Invalid() ;
   /// the invalid function 
   const LoKi::GenTypes::GFun    s_FUNC = 
-    LoKi::BasicFunctors<const HepMC::GenParticle*>::Constant ( -1 )  ;
+    LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::Constant ( -1 )  ;
   /// the invalid predicate 
   const LoKi::GenTypes::GCut    s_PRED = 
-    LoKi::BasicFunctors<const HepMC::GenParticle*>::BooleanConstant ( false )  ;
+    LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::BooleanConstant ( false )  ;
   // ===========================================================================
 } //                                                  end of anonymous namespace 
 // =============================================================================
@@ -415,7 +414,7 @@ StatusCode LoKi::GenCutTool::finalize ()
 // =============================================================================
 // accept the particle 
 // =============================================================================
-bool LoKi::GenCutTool::accept ( const HepMC::GenParticle* particle ) const 
+bool LoKi::GenCutTool::accept ( const HepMC3::ConstGenParticlePtr & particle ) const 
 {
   /// check the argument 
   if ( 0 == particle ) { return false ; }                    // RETURN
@@ -474,7 +473,7 @@ bool LoKi::GenCutTool::accept ( const HepMC::GenParticle* particle ) const
   // ===========================================================================
   // loop over the selected particles 
   // ===========================================================================
-  for ( const HepMC::GenParticle* p : particles ) 
+  for ( auto p : particles ) 
   {
     if ( 0 == p    ) { continue ; }               // CONTINUE 
     if ( !accepted ) { break    ; }               // BREAK 
@@ -510,7 +509,7 @@ bool LoKi::GenCutTool::accept ( const HepMC::GenParticle* particle ) const
             error ()     , 
             endmsg       ,
             LoKi::Objects::_VALID_                         , // show  
-            LoKi::TheSame<const HepMC::GenParticle*> { p } , // mark
+            LoKi::TheSame<HepMC3::ConstGenParticlePtr> { p } , // mark
               " " ,  0 )   <<  endmsg    ;
       }
     }
@@ -632,7 +631,7 @@ StatusCode LoKi::GenCutTool::getEfficiency()
 // ============================================================================
 bool LoKi::GenCutTool::applyCut
 ( ParticleVector&              particles       , 
-  const HepMC::GenEvent*    /* theEvent     */ , 
+  const HepMC3::GenEvent*    /* theEvent     */ , 
   const LHCb::GenCollision* /* theCollision */ ) const 
 {
   //
@@ -642,7 +641,7 @@ bool LoKi::GenCutTool::applyCut
   ParticleVector good ;
   good.reserve ( particles.size() ) ;
   //
-  for ( HepMC::GenParticle* p : particles ) 
+  for ( auto & p : particles ) 
   {
     if ( 0 == p ) { continue ; }
     //
diff --git a/Gen/GenCuts/src/GenericGenCutTool.h b/Gen/GenCuts/src_future/GenericGenCutTool.h
similarity index 98%
rename from Gen/GenCuts/src/GenericGenCutTool.h
rename to Gen/GenCuts/src_future/GenericGenCutTool.h
index 7060ae864..c65379e37 100644
--- a/Gen/GenCuts/src/GenericGenCutTool.h
+++ b/Gen/GenCuts/src_future/GenericGenCutTool.h
@@ -18,7 +18,7 @@
 // =============================================================================
 // Generators 
 // =============================================================================
-#include "MCInterfaces/IGenCutTool.h"
+#include "GenInterfaces/IGenCutTool.h"
 // =============================================================================
 // PartProp
 // =============================================================================
@@ -27,6 +27,7 @@
 // LoKi
 // =============================================================================
 #include "LoKi/GenTypes.h"
+#include "LoKi/IGenDecay.h"
 // =============================================================================
 namespace LoKi 
 {
@@ -104,7 +105,7 @@ namespace LoKi
      */
     virtual bool applyCut
     ( ParticleVector&              particles       , 
-      const HepMC::GenEvent*    /* theEvent     */ , 
+      const HepMC3::GenEvent*    /* theEvent     */ , 
       const LHCb::GenCollision* /* theCollision */ ) const override ;
     // =========================================================================
   public:
@@ -124,7 +125,7 @@ namespace LoKi
   protected:
     // =========================================================================
     /// accept the particle 
-    bool accept ( const HepMC::GenParticle* particle ) const ;
+    bool accept ( const HepMC3::ConstGenParticlePtr & particle ) const ;
     // =========================================================================
   protected:
     // =========================================================================
diff --git a/Gen/GenCuts/src/GenericGenCutToolWithDecay.cpp b/Gen/GenCuts/src_future/GenericGenCutToolWithDecay.cpp
similarity index 90%
rename from Gen/GenCuts/src/GenericGenCutToolWithDecay.cpp
rename to Gen/GenCuts/src_future/GenericGenCutToolWithDecay.cpp
index c83d54726..bccedaafb 100644
--- a/Gen/GenCuts/src/GenericGenCutToolWithDecay.cpp
+++ b/Gen/GenCuts/src_future/GenericGenCutToolWithDecay.cpp
@@ -11,11 +11,12 @@
 // ============================================================================
 // MCI-nterfaces 
 // ============================================================================
-#include "MCInterfaces/IDecayTool.h"
+#include "GenInterfaces/IDecayTool.h"
 // ============================================================================
 // GenEvent
 // ============================================================================
-#include "GenEvent/HepMCUtils.h"
+#include "HepMCUtils/HepMCUtils.h"
+#include "HepMCUser/Status.h"
 // ============================================================================
 // LoKi
 // ============================================================================
@@ -33,6 +34,12 @@
 // Local
 // ============================================================================
 #include "GenericGenCutTool.h"
+
+#include "HepMC3/GenEvent.h"
+#include "HepMC3/GenParticle.h"
+#include "HepMC3/GenVertex.h"
+#include "HepMC3/Relatives.h"
+#include "NewRnd/RndGlobal.h"
 //=============================================================================
 namespace LoKi 
 {
@@ -99,7 +106,7 @@ namespace LoKi
      */
     bool applyCut
     ( ParticleVector&           particles    , 
-      const HepMC::GenEvent*    theEvent     , 
+      const HepMC3::GenEvent*    theEvent     , 
       const LHCb::GenCollision* theCollision ) const override ;
     // ========================================================================
   public:
@@ -288,33 +295,32 @@ StatusCode LoKi::GenCutToolWithDecay::finalize ()
 // ============================================================================
 bool LoKi::GenCutToolWithDecay::applyCut
 ( ParticleVector&              particles    , 
-  const HepMC::GenEvent*       theEvent     , 
+  const HepMC3::GenEvent*       theEvent     , 
   const LHCb::GenCollision*    theCollision ) const 
 {
   m_decayTool -> disableFlip() ;
+  Assert(false,  "Not supported yet due to thread-safety of m_particle");
   // ==========================================================================
   // 1) First pre-decay all non-signal particles (heavier than the signal)
   // ==========================================================================
   if ( m_predecay ) 
   {
-    HepMCUtils::ParticleSet for_decays ;  
-    for ( HepMC::GenEvent::particle_const_iterator it = theEvent -> particles_begin() ; 
-          theEvent -> particles_end() != it ; ++it )
+    HepMCUtils::ConstParticleSet for_decays ;  
+    for ( auto & part: theEvent->particles() )
     {
-      HepMC::GenParticle* h = *it ;
-      if ( 0 == h ) { continue ; } 
-      if ( LHCb::HepMCEvent::DocumentationParticle == h->status() ) { continue ; }
-      if ( LHCb::HepMCEvent::StableInProdGen       != h->status() ) { continue ; }    
-      if ( m_particle.pid() == std::abs ( h->pdg_id()  )          ) { continue ; }
-      if ( m_heavy2 < h->momentum().m2() && m_decayTool ->isKnownToDecayTool ( h->pdg_id() ) ) 
-      { for_decays.insert ( h ) ; }
+      if ( 0 == part ) { continue ; } 
+      if ( HepMC3::Status::DocumentationParticle == part->status() ) { continue ; }
+      if ( HepMC3::Status::StableInProdGen       != part->status() ) { continue ; }    
+      if ( m_particle.pid() == std::abs ( part->pdg_id()  )          ) { continue ; }
+      if ( m_heavy2 < part->momentum().m2() && m_decayTool ->isKnownToDecayTool ( part->pdg_id() ) ) 
+      { for_decays.insert (part) ; }
     }
     // decay them
-    for ( HepMC::GenParticle*  p : for_decays ) 
+    for ( auto &  p : for_decays ) 
     { 
       if ( nullptr == p )  { continue ; }
       const LHCb::ParticleID pid{ p->pdg_id() } ; 
-      m_decayTool -> generateDecayWithLimit ( p , m_particle.pid() ) ; 
+      m_decayTool -> generateDecayWithLimit ( std::const_pointer_cast<HepMC3::GenParticle>(p) , m_particle.pid(), ThreadLocalEngine::GetPtr() ) ; 
       if ( UNLIKELY ( msgLevel ( MSG::DEBUG ) ) )
       { ++m_decays[ LoKi::Particles::nameFromPID ( pid )  ] ; }
     }
@@ -322,14 +328,21 @@ bool LoKi::GenCutToolWithDecay::applyCut
   // =================================================================================
   // 2) select all signal decays 
   // =================================================================================
+  // FIXME: Ugly hack to get around const limitation here.
+  // Consider reorganising the interface instead or ban cut tools
+  // in generatur cuts
+  ConstParticleVector tmp_particles;
   particles.clear() ; 
   using namespace LoKi::Cuts ;
   LoKi::Extract::getGenParticles 
     ( theEvent                        , 
-      std::back_inserter( particles ) , 
+      std::back_inserter( tmp_particles ) , 
       ( m_particle.pid()                  == GABSID  ) && 
-      ( LHCb::HepMCEvent::StableInProdGen == GSTATUS ) ) ;
+      ( HepMC3::Status::StableInProdGen == GSTATUS ) ) ;
   //
+  for(auto & p:tmp_particles){
+    particles.push_back(std::const_pointer_cast<HepMC3::GenParticle>(p));
+  }
   if      ( 1 < particles.size() )   // too many signals ? 
   { 
     Warning ( "Too many signals are found, skip extra").ignore() ; 
@@ -341,15 +354,16 @@ bool LoKi::GenCutToolWithDecay::applyCut
     return false ;                                                // RETURN
   }
   // choose the signal as the first particle 
-  HepMC::GenParticle* signal = particles.front() ;
+  auto signal = particles.front() ;
   // ==========================================================================
   // make decay of signal particle 
   // ==========================================================================
   bool hasFlipped = false ;
-  StatusCode sc = m_decayTool -> generateSignalDecay ( signal , hasFlipped ) ;
+  StatusCode sc = m_decayTool -> generateSignalDecay ( signal , hasFlipped , ThreadLocalEngine::GetPtr()) ;
   auto EV = signal->end_vertex();
+  auto mcevt = signal->parent_event();
   if(EV){
-    signal->parent_event()->set_signal_process_vertex(EV);
+    mcevt->add_attribute(Gaussino::HepMC::Attributes::SignalProcessVertex, std::make_shared<HepMC3::VertexAttribute>(EV));
   }
   if ( sc.isFailure() ) 
   {
-- 
GitLab


From 873dc0703bc9fc68dc3c02b6be604a010dd8a4e2 Mon Sep 17 00:00:00 2001
From: Dominik Muller <dominik.muller@cern.ch>
Date: Tue, 26 Nov 2019 09:56:40 +0100
Subject: [PATCH 43/90] Moved LoKiGen to Gauss + ported to HepMC3

---
 Gen/LoKiGen/CMakeLists.txt                    |   53 +
 Gen/LoKiGen/LoKi/BuildGenTrees.h              |   90 +
 Gen/LoKiGen/LoKi/CmpBarCode.h                 |   85 +
 Gen/LoKiGen/LoKi/GenAlgs.h                    |  637 +++++++
 Gen/LoKiGen/LoKi/GenAlgsDicts.h               |  119 ++
 Gen/LoKiGen/LoKi/GenChild.h                   |  381 +++++
 Gen/LoKiGen/LoKi/GenChildSelector.h           |  175 ++
 Gen/LoKiGen/LoKi/GenDecayChain.h              |  272 +++
 Gen/LoKiGen/LoKi/GenDecays.h                  | 1063 ++++++++++++
 Gen/LoKiGen/LoKi/GenDump.h                    |   73 +
 Gen/LoKiGen/LoKi/GenExtract.h                 |  268 +++
 Gen/LoKiGen/LoKi/GenExtractDicts.h            |   48 +
 Gen/LoKiGen/LoKi/GenHybridEngine.h            |  129 ++
 Gen/LoKiGen/LoKi/GenHybridEngineActor.h       |  165 ++
 Gen/LoKiGen/LoKi/GenHybridLock.h              |   73 +
 Gen/LoKiGen/LoKi/GenKinematics.h              |  128 ++
 Gen/LoKiGen/LoKi/GenMoniDicts.h               |   32 +
 Gen/LoKiGen/LoKi/GenOscillated.h              |   68 +
 Gen/LoKiGen/LoKi/GenPIDOperators.h            |  452 +++++
 Gen/LoKiGen/LoKi/GenParticleCuts.h            | 1261 ++++++++++++++
 Gen/LoKiGen/LoKi/GenParticles.h               | 1282 ++++++++++++++
 Gen/LoKiGen/LoKi/GenParticles2.h              |  891 ++++++++++
 Gen/LoKiGen/LoKi/GenParticles3.h              |  177 ++
 Gen/LoKiGen/LoKi/GenParticles4.h              |  903 ++++++++++
 Gen/LoKiGen/LoKi/GenParticles5.h              |  121 ++
 Gen/LoKiGen/LoKi/GenSections.h                |   89 +
 Gen/LoKiGen/LoKi/GenSources.h                 |  195 +++
 Gen/LoKiGen/LoKi/GenToCpp.h                   |   32 +
 Gen/LoKiGen/LoKi/GenTreesFactory.h            |   97 ++
 Gen/LoKiGen/LoKi/GenTypes.h                   |  260 +++
 Gen/LoKiGen/LoKi/GenVertexCuts.h              |  274 +++
 Gen/LoKiGen/LoKi/GenVertices.h                |  294 ++++
 Gen/LoKiGen/LoKi/IGenDecay.h                  |   72 +
 Gen/LoKiGen/LoKi/IGenHybridFactory.h          |  181 ++
 Gen/LoKiGen/LoKi/IGenHybridTool.h             |  104 ++
 Gen/LoKiGen/LoKi/LoKiGen.h                    |   50 +
 Gen/LoKiGen/LoKi/LoKiGen_dct.h                |  422 +++++
 Gen/LoKiGen/LoKi/PrintHepMCDecay.h            |  178 ++
 Gen/LoKiGen/dict/LoKiGen.xml                  |  176 ++
 Gen/LoKiGen/dict/LoKiGenDict.h                |   36 +
 Gen/LoKiGen/doc/release.notes                 |  730 ++++++++
 Gen/LoKiGen/python/LoKiGen/HepMC.py           |  659 ++++++++
 Gen/LoKiGen/python/LoKiGen/__init__.py        |   46 +
 Gen/LoKiGen/python/LoKiGen/decorators.py      |  207 +++
 Gen/LoKiGen/python/LoKiGen/functions.py       |  410 +++++
 Gen/LoKiGen/python/LoKiGen/graph.py           |  226 +++
 Gen/LoKiGen/python/LoKiGen/tests.py           |  118 ++
 Gen/LoKiGen/python/LoKiGen/trees.py           |   81 +
 Gen/LoKiGen/src/Components/DumpHepMC.cpp      |  145 ++
 Gen/LoKiGen/src/Components/GenDecay.cpp       |  127 ++
 Gen/LoKiGen/src/Components/GenFilter.cpp      |  167 ++
 Gen/LoKiGen/src/Components/GenHybridTool.cpp  |  405 +++++
 Gen/LoKiGen/src/GenAlgsDicts.cpp              |  181 ++
 Gen/LoKiGen/src/GenChild.cpp                  |  273 +++
 Gen/LoKiGen/src/GenChildSelector.cpp          |  360 ++++
 Gen/LoKiGen/src/GenDecayChain.cpp             |  102 ++
 Gen/LoKiGen/src/GenDecays.cpp                 |  976 +++++++++++
 Gen/LoKiGen/src/GenDump.cpp                   |  126 ++
 Gen/LoKiGen/src/GenExtractDicts.cpp           |   76 +
 Gen/LoKiGen/src/GenHybridEngine.cpp           |  138 ++
 Gen/LoKiGen/src/GenHybridEngineActor.cpp      |  200 +++
 Gen/LoKiGen/src/GenHybridLock.cpp             |   45 +
 Gen/LoKiGen/src/GenKinematics.cpp             |  141 ++
 Gen/LoKiGen/src/GenMoniDicts.cpp              |   24 +
 Gen/LoKiGen/src/GenPIDOperators.cpp           |  266 +++
 Gen/LoKiGen/src/GenParticles.cpp              | 1486 +++++++++++++++++
 Gen/LoKiGen/src/GenParticles2.cpp             |  756 +++++++++
 Gen/LoKiGen/src/GenParticles3.cpp             |  143 ++
 Gen/LoKiGen/src/GenParticles4.cpp             |  691 ++++++++
 Gen/LoKiGen/src/GenParticles5.cpp             |  111 ++
 Gen/LoKiGen/src/GenSections.cpp               |   74 +
 Gen/LoKiGen/src/GenSources.cpp                |  155 ++
 Gen/LoKiGen/src/GenStreamers.cpp              |   88 +
 Gen/LoKiGen/src/GenTreesFactory.cpp           |  144 ++
 Gen/LoKiGen/src/GenVertices.cpp               |  278 +++
 Gen/LoKiGen/src/IGenDecay.cpp                 |   27 +
 Gen/LoKiGen/src/IGenHybridFactory.cpp         |   37 +
 Gen/LoKiGen/src/IGenHybridTool.cpp            |   41 +
 Gen/LoKiGen/src/LoKiGen.cpp                   |   38 +
 Gen/LoKiGen/src/Oscillated.cpp                |   79 +
 Gen/LoKiGen/src/PrintHepMCDecay.cpp           |  176 ++
 Gen/LoKiGen/src/tests/GenDecayGrammarTest.cpp |   87 +
 Gen/LoKiGen/tests/GenDecayGrammarTest.txt     |   12 +
 Gen/LoKiGen/tests/qmtest/jira_461.qmt         |   15 +
 Gen/LoKiGen/tests/qmtest/lokigen0.qmt         |   15 +
 Gen/LoKiGen/tests/tst_JIRA_LBCORE461.py       |   40 +
 86 files changed, 22128 insertions(+)
 create mode 100644 Gen/LoKiGen/CMakeLists.txt
 create mode 100644 Gen/LoKiGen/LoKi/BuildGenTrees.h
 create mode 100644 Gen/LoKiGen/LoKi/CmpBarCode.h
 create mode 100644 Gen/LoKiGen/LoKi/GenAlgs.h
 create mode 100644 Gen/LoKiGen/LoKi/GenAlgsDicts.h
 create mode 100644 Gen/LoKiGen/LoKi/GenChild.h
 create mode 100644 Gen/LoKiGen/LoKi/GenChildSelector.h
 create mode 100644 Gen/LoKiGen/LoKi/GenDecayChain.h
 create mode 100644 Gen/LoKiGen/LoKi/GenDecays.h
 create mode 100644 Gen/LoKiGen/LoKi/GenDump.h
 create mode 100644 Gen/LoKiGen/LoKi/GenExtract.h
 create mode 100644 Gen/LoKiGen/LoKi/GenExtractDicts.h
 create mode 100644 Gen/LoKiGen/LoKi/GenHybridEngine.h
 create mode 100644 Gen/LoKiGen/LoKi/GenHybridEngineActor.h
 create mode 100644 Gen/LoKiGen/LoKi/GenHybridLock.h
 create mode 100644 Gen/LoKiGen/LoKi/GenKinematics.h
 create mode 100644 Gen/LoKiGen/LoKi/GenMoniDicts.h
 create mode 100644 Gen/LoKiGen/LoKi/GenOscillated.h
 create mode 100644 Gen/LoKiGen/LoKi/GenPIDOperators.h
 create mode 100644 Gen/LoKiGen/LoKi/GenParticleCuts.h
 create mode 100644 Gen/LoKiGen/LoKi/GenParticles.h
 create mode 100644 Gen/LoKiGen/LoKi/GenParticles2.h
 create mode 100644 Gen/LoKiGen/LoKi/GenParticles3.h
 create mode 100644 Gen/LoKiGen/LoKi/GenParticles4.h
 create mode 100644 Gen/LoKiGen/LoKi/GenParticles5.h
 create mode 100644 Gen/LoKiGen/LoKi/GenSections.h
 create mode 100644 Gen/LoKiGen/LoKi/GenSources.h
 create mode 100644 Gen/LoKiGen/LoKi/GenToCpp.h
 create mode 100644 Gen/LoKiGen/LoKi/GenTreesFactory.h
 create mode 100644 Gen/LoKiGen/LoKi/GenTypes.h
 create mode 100644 Gen/LoKiGen/LoKi/GenVertexCuts.h
 create mode 100644 Gen/LoKiGen/LoKi/GenVertices.h
 create mode 100644 Gen/LoKiGen/LoKi/IGenDecay.h
 create mode 100644 Gen/LoKiGen/LoKi/IGenHybridFactory.h
 create mode 100644 Gen/LoKiGen/LoKi/IGenHybridTool.h
 create mode 100644 Gen/LoKiGen/LoKi/LoKiGen.h
 create mode 100644 Gen/LoKiGen/LoKi/LoKiGen_dct.h
 create mode 100644 Gen/LoKiGen/LoKi/PrintHepMCDecay.h
 create mode 100644 Gen/LoKiGen/dict/LoKiGen.xml
 create mode 100644 Gen/LoKiGen/dict/LoKiGenDict.h
 create mode 100644 Gen/LoKiGen/doc/release.notes
 create mode 100755 Gen/LoKiGen/python/LoKiGen/HepMC.py
 create mode 100755 Gen/LoKiGen/python/LoKiGen/__init__.py
 create mode 100755 Gen/LoKiGen/python/LoKiGen/decorators.py
 create mode 100755 Gen/LoKiGen/python/LoKiGen/functions.py
 create mode 100644 Gen/LoKiGen/python/LoKiGen/graph.py
 create mode 100755 Gen/LoKiGen/python/LoKiGen/tests.py
 create mode 100755 Gen/LoKiGen/python/LoKiGen/trees.py
 create mode 100644 Gen/LoKiGen/src/Components/DumpHepMC.cpp
 create mode 100644 Gen/LoKiGen/src/Components/GenDecay.cpp
 create mode 100644 Gen/LoKiGen/src/Components/GenFilter.cpp
 create mode 100644 Gen/LoKiGen/src/Components/GenHybridTool.cpp
 create mode 100644 Gen/LoKiGen/src/GenAlgsDicts.cpp
 create mode 100644 Gen/LoKiGen/src/GenChild.cpp
 create mode 100644 Gen/LoKiGen/src/GenChildSelector.cpp
 create mode 100644 Gen/LoKiGen/src/GenDecayChain.cpp
 create mode 100644 Gen/LoKiGen/src/GenDecays.cpp
 create mode 100644 Gen/LoKiGen/src/GenDump.cpp
 create mode 100644 Gen/LoKiGen/src/GenExtractDicts.cpp
 create mode 100644 Gen/LoKiGen/src/GenHybridEngine.cpp
 create mode 100644 Gen/LoKiGen/src/GenHybridEngineActor.cpp
 create mode 100644 Gen/LoKiGen/src/GenHybridLock.cpp
 create mode 100644 Gen/LoKiGen/src/GenKinematics.cpp
 create mode 100644 Gen/LoKiGen/src/GenMoniDicts.cpp
 create mode 100644 Gen/LoKiGen/src/GenPIDOperators.cpp
 create mode 100644 Gen/LoKiGen/src/GenParticles.cpp
 create mode 100644 Gen/LoKiGen/src/GenParticles2.cpp
 create mode 100644 Gen/LoKiGen/src/GenParticles3.cpp
 create mode 100644 Gen/LoKiGen/src/GenParticles4.cpp
 create mode 100644 Gen/LoKiGen/src/GenParticles5.cpp
 create mode 100644 Gen/LoKiGen/src/GenSections.cpp
 create mode 100644 Gen/LoKiGen/src/GenSources.cpp
 create mode 100644 Gen/LoKiGen/src/GenStreamers.cpp
 create mode 100644 Gen/LoKiGen/src/GenTreesFactory.cpp
 create mode 100644 Gen/LoKiGen/src/GenVertices.cpp
 create mode 100644 Gen/LoKiGen/src/IGenDecay.cpp
 create mode 100644 Gen/LoKiGen/src/IGenHybridFactory.cpp
 create mode 100644 Gen/LoKiGen/src/IGenHybridTool.cpp
 create mode 100644 Gen/LoKiGen/src/LoKiGen.cpp
 create mode 100644 Gen/LoKiGen/src/Oscillated.cpp
 create mode 100644 Gen/LoKiGen/src/PrintHepMCDecay.cpp
 create mode 100644 Gen/LoKiGen/src/tests/GenDecayGrammarTest.cpp
 create mode 100644 Gen/LoKiGen/tests/GenDecayGrammarTest.txt
 create mode 100644 Gen/LoKiGen/tests/qmtest/jira_461.qmt
 create mode 100644 Gen/LoKiGen/tests/qmtest/lokigen0.qmt
 create mode 100755 Gen/LoKiGen/tests/tst_JIRA_LBCORE461.py

diff --git a/Gen/LoKiGen/CMakeLists.txt b/Gen/LoKiGen/CMakeLists.txt
new file mode 100644
index 000000000..579632fcf
--- /dev/null
+++ b/Gen/LoKiGen/CMakeLists.txt
@@ -0,0 +1,53 @@
+###############################################################################
+# (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration      #
+#                                                                             #
+# This software is distributed under the terms of the GNU General Public      #
+# Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   #
+#                                                                             #
+# In applying this licence, CERN does not waive the privileges and immunities #
+# granted to it by virtue of its status as an Intergovernmental Organization  #
+# or submit itself to any jurisdiction.                                       #
+###############################################################################
+################################################################################
+# Package: LoKiGen
+################################################################################
+gaudi_subdir(LoKiGen v10r24)
+
+find_package(Graphviz) 
+gaudi_depends_on_subdirs(Phys/LoKiCore
+                         Phys/LoKiNumbers
+                         Gen/Generators)
+
+include_directories(SYSTEM ${Boost_INCLUDE_DIRS} ${ROOT_INCLUDE_DIRS})
+
+AddHepMC3()
+
+gaudi_add_library(LoKiGenLib
+                  src/*.cpp
+                  PUBLIC_HEADERS LoKi
+                  INCLUDE_DIRS ${HEPMC3_INCLUDE_DIR}
+                  LINK_LIBRARIES GeneratorsLib LoKiCoreLib ${HEPMC3_LIBRARIES})
+
+gaudi_add_module(LoKiGen
+                 src/Components/*.cpp
+                 INCLUDE_DIRS ${HEPMC3_INCLUDE_DIR}
+                 LINK_LIBRARIES ${HEPMC3_LIBRARIES} LoKiCoreLib LoKiGenLib)
+
+gaudi_add_dictionary(LoKiGen
+                     dict/LoKiGenDict.h
+                     dict/LoKiGen.xml
+                     INCLUDE_DIRS ${HEPMC3_INCLUDE_DIR}
+                     LINK_LIBRARIES ${HEPMC3_LIBRARIES} LoKiCoreLib LoKiGenLib
+                     OPTIONS " -U__MINGW32__ ")
+
+if(GAUDI_BUILD_TESTS)
+  gaudi_add_executable(GenDecayGrammarTest
+                       src/tests/GenDecayGrammarTest.cpp
+                       INCLUDE_DIRS ${HEPMC3_INCLUDE_DIR}
+                       LINK_LIBRARIES ${HEPMC3_LIBRARIES} LoKiCoreLib LoKiGenLib)
+endif()
+
+gaudi_install_python_modules()
+
+
+gaudi_add_test(QMTest QMTEST)
diff --git a/Gen/LoKiGen/LoKi/BuildGenTrees.h b/Gen/LoKiGen/LoKi/BuildGenTrees.h
new file mode 100644
index 000000000..b63149251
--- /dev/null
+++ b/Gen/LoKiGen/LoKi/BuildGenTrees.h
@@ -0,0 +1,90 @@
+/*****************************************************************************\
+* (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration      *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                             *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+// ============================================================================
+#ifndef LOKI_BUILDGENTREES_H
+#define LOKI_BUILDGENTREES_H 1
+// ============================================================================
+// Include files
+// ============================================================================
+// LoKi
+// ============================================================================
+#include "LoKi/GenParticles.h"
+// ============================================================================
+/** @file
+ *
+ *  This file is a part of LoKi project -
+ *    "C++ ToolKit  for Smart and Friendly Physics Analysis"
+ *
+ *  The package has been designed with the kind help from
+ *  Galina PAKHLOVA and Sergey BARSUK.  Many bright ideas,
+ *  contributions and advices from G.Raven, J.van Tilburg,
+ *  A.Golutvin, P.Koppenburg have been used in the design.
+ *
+ *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+ *  @date 2006-01-23
+ */
+// ============================================================================
+namespace LoKi {
+  /** @namespace LoKi::GenTrees
+   *  useful namespace with utility to build HepMC3-trees from flat lists
+   *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+   *  @date 2005-01-20
+   */
+  namespace GenTrees {
+    // ========================================================================
+    /** Simple function which 'builds' the trees from flat list
+     *
+     *  @code
+     *
+     *  typedef ....  INSEQ  ;
+     *  typedef ....  OUTSEQ ;
+     *
+     *  // input container of (HepMC3)particles (flat list)
+     *  INSEQ  input = ... ;
+     *  // output container of (HepMC3) particles (only independent trees)
+     *  OUTSEQ trees ;
+     *
+     *  LoKi::GenTrees::buldTrees
+     *    ( input.begin() , input.end() , std::back_inserter ( trees ) ) ;
+     *
+     *
+     *  @endcode
+     *
+     *  @param first begin of flat sequence of HepMC3::GenParticles
+     *  @param last   end    of flat sequence  of HepMC3::GenParticles
+     *  @param output output iterator
+     *  @return iterator for  sequence of trees
+     *  @attention  it could be a bit slow
+     */
+    template <class PARTICLE, class OUTPUT>
+    inline OUTPUT buildTrees( PARTICLE first, PARTICLE last, OUTPUT output ) {
+      if ( first != last ) {
+        // helper function
+        LoKi::GenParticles::FromHepMCTree fromDecay( first, last );
+        using arg_t = decltype( *first );
+        std::copy_if( first, last, output, [&]( arg_t p ) {
+          fromDecay.remove( p ); // remove 'self'
+          // use the helper function
+          const bool result = fromDecay( p );
+          fromDecay.add( p ); // add    'self'
+          return !result;     // return true if head of decay tree
+        } );
+      }
+      return output;
+    }
+    // ========================================================================
+  } // namespace GenTrees
+  // ==========================================================================
+} //                                                      end of namespace LoKi
+// ============================================================================
+// The END
+// ============================================================================
+#endif // LOKI_BUILDGENTREES_H
diff --git a/Gen/LoKiGen/LoKi/CmpBarCode.h b/Gen/LoKiGen/LoKi/CmpBarCode.h
new file mode 100644
index 000000000..9afbe7fbf
--- /dev/null
+++ b/Gen/LoKiGen/LoKi/CmpBarCode.h
@@ -0,0 +1,85 @@
+/*****************************************************************************\
+* (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration      *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                             *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+// ============================================================================
+#ifndef LOKI_CMPBARCODE_H
+#define LOKI_CMPBARCODE_H 1
+// ============================================================================
+// Include files
+// ============================================================================
+// STD & STL
+// ============================================================================
+#include <set>
+// ============================================================================
+// GaudiKernel
+// ============================================================================
+#include "GaudiKernel/Kernel.h"
+// ============================================================================
+// HepMC3
+// ============================================================================
+#include "HepMC3/GenParticle.h"
+// ============================================================================
+/** @file
+ *  This file is a part of LoKi project -
+ *    "C++ ToolKit  for Smart and Friendly Physics Analysis"
+ *
+ *  The package has been designed with the kind help from
+ *  Galina PAKHLOVA and Sergey BARSUK.  Many bright ideas,
+ *  contributions and advices from G.Raven, J.van Tilburg,
+ *  A.Golutvin, P.Koppenburg have been used in the design.
+ *
+ *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+ *
+ */
+// ============================================================================
+namespace LoKi {
+  // ==========================================================================
+  namespace GenParticles {
+    // ========================================================================
+    /** @struct CmpBarCode CmpBarCode.h LoKi/CmpBarCode.h
+     *  "srickt-less" comparisons of HepMC3::GenParticle pointers
+     *  @author Vanya BELYAEV Ivan.Belyaev@nikhef.nl
+     *  @date   2008-06-24
+     */
+    struct CmpBarCode {
+      // ======================================================================
+      /// the only one essential method: compare two particles
+      inline bool operator()( const HepMC3::ConstGenParticlePtr & a, const HepMC3::ConstGenParticlePtr & b ) const {
+        return a == b ? false :                         // they are equal, not "less"
+                   0 == a ? true :                      // NULL is always less
+                       0 == b ? false :                 // NULL is always less
+                           a->id() < b->id(); // compare by barcode
+      }
+      // ======================================================================
+    };
+    // ========================================================================
+    /** get unique string for HepMC3::Particle
+     */
+    GAUDI_API
+    std::string hex_id( const HepMC3::ConstGenParticlePtr & particle );
+    /// get hash function for HepMC3::Particle
+    GAUDI_API std::size_t hash( const HepMC3::ConstGenParticlePtr & particle );
+    /// get hash function for HepMC3::Particle
+    GAUDI_API std::size_t hash( const HepMC3::ConstGenVertexPtr & particle );
+    // ========================================================================
+  } // namespace GenParticles
+  // ==========================================================================
+  namespace GenTypes {
+    // ========================================================================
+    /// the type of ordered set generator particles
+    typedef std::set<HepMC3::ConstGenParticlePtr, LoKi::GenParticles::CmpBarCode> GenSet;
+    // ========================================================================
+  } // namespace GenTypes
+  // ==========================================================================
+} //                                                      end of namespace LoKi
+// ============================================================================
+//                                                                      The END
+// ============================================================================
+#endif // LOKI_CMPBARCODE_H
diff --git a/Gen/LoKiGen/LoKi/GenAlgs.h b/Gen/LoKiGen/LoKi/GenAlgs.h
new file mode 100644
index 000000000..aa4b41125
--- /dev/null
+++ b/Gen/LoKiGen/LoKi/GenAlgs.h
@@ -0,0 +1,637 @@
+/*****************************************************************************\
+* (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration      *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                             *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+// ============================================================================
+#ifndef LOKI_GENALGS_H
+#define LOKI_GENALGS_H 1
+// ============================================================================
+// Include files
+// ============================================================================
+// STD & STL
+// ============================================================================
+#include <algorithm>
+#include <numeric>
+// ============================================================================
+// LoKiCore
+// ============================================================================
+#include "LoKi/Algs.h"
+// ============================================================================
+#include "HepMC3/GenEvent.h"
+#include "HepMC3/GenParticle.h"
+#include "HepMC3/GenVertex.h"
+#include "HepMC3/Relatives.h"
+/** @file
+ *
+ *  This file is a part of LoKi project -
+ *    "C++ ToolKit  for Smart and Friendly Physics Analysis"
+ *
+ *  The package has been designed with the kind help from
+ *  Galina PAKHLOVA and Sergey BARSUK.  Many bright ideas,
+ *  contributions and advices from G.Raven, J.van Tilburg,
+ *  A.Golutvin, P.Koppenburg have been used in the design.
+ *
+ *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+ *  @date 2006-01-23
+ *
+ */
+// ============================================================================
+namespace LoKi {
+  /** @namespace  LoKi::GenAlgs  LoKi/GenAlgs.h
+   *
+   *  Collection of  few helper functions/algoritgms  "a'la STL"
+   *  to simplify the operations with HepMC3 graphs
+   *
+   *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+   *  @date   2006-01-23
+   */
+  namespace GenAlgs {
+    template <class OBJECT, class PREDICATE>
+    inline size_t count_if( OBJECT first, OBJECT last, const PREDICATE& cut );
+    // ========================================================================
+    /** useful helper function (a'la STL) to count a number of
+     *  (HepMC3) particles, which satisfies the certain criteria,
+     *  e.e. count number of leptons in LHCb acceptance :
+     *
+     *  @code
+     *
+     *  using namespace LoKi::GenAlgs
+     *  using namespace LoKi::Cuts
+     *
+     *  const HepMC3::GenEvent* event = ... ;
+     *
+     *  const size_t nLeptons =
+     *    count_if ( event , GLEPTON && GTHETA < 400 * mrad ) ;
+     *
+     *  @endcode
+     *
+     *  @see LoKi::Cuts::GLEPTON
+     *  @see LoKi::Cuts::GTHETA
+     *
+     *  @param event pointer to HepMC3 event
+     *  @param cut   the condidion/predicate/criterion
+     *  @return number of elements which satisfy the criterion
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date   2006-01-23
+     */
+    template <class PREDICATE>
+    inline size_t count_if( const HepMC3::GenEvent* event, const PREDICATE& cut ) {
+      return ( 0 == event ) ? 0 : LoKi::Algs::count_if( std::begin(event->particles()), std::end(event->particles()), cut );
+    }
+    // ========================================================================
+    /** simple function to count number of "good" paricles in the HepMC3-graph
+     *  @param vertex pointer to the vertex
+     *  @param cut    predicate which defines "good" particle
+     *  @param range  range of HepMC3-graph
+     *  @see const HepMC3::Relatives &
+     *  @see HepMC3::GenParticle
+     *  @see HepMC3::GenVertex
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date 2007-06-03
+     */
+    template <class PREDICATE>
+    inline size_t count_if( const HepMC3::ConstGenVertexPtr & vertex, const PREDICATE& cut, const HepMC3::Relatives & range ) {
+      if ( 0 == vertex ) { return 0; } // RETURN
+      auto particles = range(vertex);
+      return LoKi::Algs::count_if( std::begin(particles), std::end(particles), cut ); // RETURN
+    }
+    // ========================================================================
+    /** simple function to count number of "good" paricles in the decay tree
+     *  of th egiven particlee
+     *  @param particle pointer to the mother particle
+     *  @param cut    predicate which defines "good" particle
+     *  @see HepMC3::GenParticle
+     *  @see HepMC3::GenVertex
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date 2007-06-03
+     */
+    template <class PREDICATE>
+    inline size_t count_if( const HepMC3::ConstGenParticlePtr & particle, const PREDICATE& cut ) {
+      size_t result = 0;
+      if ( 0 != particle ) { result = LoKi::GenAlgs::count_if( particle->end_vertex(), cut, HepMC3::Relatives::DESCENDANTS ); }
+      if ( cut( particle ) ) { ++result; }
+      // check the particle itself
+      return result;
+    }
+    // ========================================================================
+    /** useful helper function (a'la STL) to count a number of
+     *  (HepMC3) particles, which satisfy certain criteria,
+     *  e.e. count number of beauty particles
+     *
+     *  @code
+     *
+     *  using namespace LoKi::GenAlgs
+     *  using namespace LoKi::Cuts
+     *
+     *  // any sequence of objects, convertible to
+     *  // const LHCb::HepMC3Events*, const LHCb::HepMC3Event*
+     *  // or const HepMC3::GenEvent*
+     *  SEQUENCE objects = ... ;
+     *
+     *  const size_t nBeauty  =
+     *    count_if ( objects.begin() , objects.end() , BEAUTY ) ;
+     *
+     *  @endcode
+     *
+     *  @see LoKi::Cuts::BEAUTY
+     *
+     *  @param  first begin of the sequence
+     *  @param  last  end of the sequence
+     *  @param  cut   the predicate
+     *  @return number of elements which satisfy the criterion
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date   2006-01-23
+     */
+    template <class OBJECT, class PREDICATE>
+    inline size_t count_if( OBJECT first, OBJECT last, const PREDICATE& cut ) {
+      using arg_t = decltype( *first );
+      return std::accumulate( first, last, size_t( 0 ),
+                              [&]( size_t n, arg_t arg ) { return n + LoKi::GenAlgs::count_if( arg, cut ); } );
+    }
+    // ========================================================================
+    /** usefull helper function (a'la STL) to efficiently check the
+     *  presence of at least one (HepMC3) particle, which satisfies the
+     *  certain criteria, e.g. b-buarks from Higgs decays:
+     *
+     *  @code
+     *
+     *  using namespace LoKi::GenAlgs
+     *  using namespace LoKi::Cuts
+     *
+     *  const HepMC3::GenEvent* event = ... ;
+     *
+     *  const bool good =
+     *    found ( event , ( "b" == GABSID ) &&
+     *       0 < GNINTREE ( "H_10" == GABSID , HepMC3::parents ) ) ;
+     *
+     *  @endcode
+     *
+     *  @see LoKi::Cuts::GABSID
+     *  @see LoKi::Cuts::GNINTREE
+     *
+     *  @param event pointer to HepMC3 event
+     *  @param cut   the condidion/predicate/criterion
+     *  @return true if the particle, which satisfies the criterion is found
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date   2006-01-23
+     */
+    template <class PREDICATE>
+    inline bool found( const HepMC3::GenEvent* event, const PREDICATE& cut ) {
+      return event &&
+             ( std::end(event->particles()) != LoKi::Algs::find_if( std::begin(event->particles()), std::end(event->particles()), cut ) );
+    }
+    // ========================================================================
+    /** simple function to check the presence of "good" particle in HepMC3-graph
+     *  @param vertex pointer to the vertex
+     *  @param cut defintion of "good" particle
+     *  @param range HepMC3-graph
+     *  @return true if at least one "good" particle is in a graph.
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     */
+    template <class PREDICATE>
+    inline bool found( const HepMC3::ConstGenVertexPtr & vertex, const PREDICATE& cut, const HepMC3::Relatives & range ) {
+      if(!vertex){
+        return false;
+      }
+      auto particles = range(vertex);
+      return LoKi::Algs::found( std::begin(particles), std::end(particles), cut );
+    }
+    // ========================================================================
+    /** simple function to check the presence of "good" particle in the decay
+     *  tree of the mother particle
+     *  @param particle pointer to mother particle
+     *  @param cut defintion of "good" particle
+     *  @return true if at least one "good" particle is in a decay tree
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     */
+    template <class PREDICATE>
+    inline bool found( const HepMC3::ConstGenParticlePtr & particle, const PREDICATE& cut ) {
+      return cut( particle ) || ( particle && LoKi::GenAlgs::found( particle->end_vertex(), cut, HepMC3::Relatives::DESCENDANTS ) );
+    }
+    // =====================================================================
+    template <class PREDICATE>
+    inline const HepMC3::ConstGenParticlePtr foundFirst( const HepMC3::ConstGenVertexPtr & vertex, const PREDICATE& cut );
+    // ======================================================================
+    template <class PREDICATE>
+    inline const HepMC3::ConstGenParticlePtr foundFirst( const HepMC3::ConstGenParticlePtr & particle, const PREDICATE& cut );
+    // ======================================================================
+    template <class PARTICLE, class PREDICATE>
+    inline const HepMC3::ConstGenParticlePtr foundFirst( PARTICLE begin, PARTICLE end, const PREDICATE& cut ) {
+      //
+      HepMC3::ConstGenParticlePtr result = nullptr;
+      //
+      for ( ; !result && begin != end; ++begin ) { result = foundFirst( *begin, cut ); }
+      //
+      return result;
+    }
+    // ======================================================================
+    /** simple function to get the first matched element in tree
+     *  tree of the mother particle
+     *  @param particle pointer to mother particle
+     *  @param cut defintion of "good" particle
+     *  @return good particle
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     */
+    template <class PREDICATE>
+    inline const HepMC3::ConstGenParticlePtr foundFirst( const HepMC3::ConstGenParticlePtr & particle, const PREDICATE& cut ) {
+      if ( 0 == particle ) { return nullptr; }    // RETURN
+      if ( cut( particle ) ) { return particle; } // RETURN
+      //
+      if ( 0 == particle->end_vertex() ) { return nullptr; } // RETURN
+      //
+      return foundFirst( particle->end_vertex(), cut );
+    }
+    // ========================================================================
+    template <class PREDICATE>
+    inline const HepMC3::ConstGenParticlePtr foundFirst( const HepMC3::ConstGenVertexPtr & vertex, const PREDICATE& cut ) {
+      //
+      if ( !vertex ) { return nullptr; } // RETURN
+      //
+      auto particles = HepMC3::Relatives::CHILDREN(vertex);
+      return foundFirst( std::begin(particles), std::end(particles), cut );
+    }
+    // ========================================================================
+    /** useful helper function (a'la STL) to efficiently check the
+     *  presence of at least one (HepMC3) particle, which satisfies the
+     *  certain criteria, e.g. for beauty particles
+     *
+     *  @code
+     *
+     *  using namespace LoKi::GenAlgs
+     *  using namespace LoKi::Cuts
+     *
+     *  // any sequence of objects, convertible to
+     *  // const LHCb::HepMC3Events*, const LHCb::HepMC3Event*
+     *  // or const HepMC3::GenEvent*
+     *  SEQUENCE objects = ... ;
+     *
+     *  const bool good =
+     *    found ( objects.begin() , objects.end() , BEAUTY ) ;
+     *
+     *  @endcode
+     *
+     *  @see LoKi::Cuts::BEAUTY
+     *
+     *  @param  first begin of the sequence
+     *  @param  last  end of the sequence
+     *  @param  cut   the predicate
+     *  @return number of elements which satisfy the criterion
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date   2006-01-23
+     */
+    template <class OBJECT, class PREDICATE>
+    inline bool found( OBJECT first, OBJECT last, const PREDICATE& cut ) {
+      using arg_t = decltype( *first );
+      return std::any_of( first, last, [&]( arg_t arg ) { return found( arg, cut ); } );
+    }
+    // ========================================================================
+    /** Simple algorithm for accumulation of
+     *  the function value through the  HepMC3 graph
+     *
+     *  E.g. one can 'accumulate' the total
+     *  4-momentum of all daughter muons:
+     *
+     *  @code
+     *
+     *  const HepMC3::GenEvent* event = ... ;
+     *
+     *  LoKi::LorentzVector result = LoKi::GenAlgs::accumulate
+     *   ( event                            ,   // the event
+     *     LoKi::Kinematics::Gen4Momentum() ,   // get 4-mometumm
+     *     "mu+" == GABSID                  ,   // consider only muons
+     *     LoKi::LorentzVector()            ,   // the initial value
+     *     std::plus<LoKi::LorentzVector>() ) ; // operation
+     *
+     *  @endcode
+     *
+     *  @see HepMC3::GenEvent
+     *  @see LoKi::Cuts::GABSID
+     *  @see LoKi::LorentzVector
+     *  @see LoKi::Kinematics::Gen4Momentum
+     *
+     *  @param  event     pointer to HepMC3::GenEvent
+     *  @param  functor   function to be evaluated
+     *  @param  predicate selection criteria
+     *  @param  result    the initial-value for the result
+     *  @return the result of accumulation
+     *
+     *  @author Vanya BELYAEV ibelyaev@physucs.syr.edu
+     *  @date 2006-02-09
+     */
+    template <class RESULT, class FUNCTOR, class PREDICATE, class OPERATION>
+    inline RESULT accumulate( const HepMC3::GenEvent* event, const FUNCTOR& functor, const PREDICATE& predicate,
+                              RESULT result, OPERATION binop ) {
+      return event ? LoKi::Algs::accumulate( std::begin(event->particles()), std::end(event->particles()), functor, predicate,
+                                             result, binop )
+                   : result;
+    }
+    // ========================================================================
+    template <class RESULT, class FUNCTOR, class PREDICATE>
+    inline RESULT accumulate( const HepMC3::GenEvent* event, const FUNCTOR& functor, const PREDICATE& predicate,
+                              RESULT result ) {
+      return accumulate( event, functor, predicate, result, std::plus<RESULT>() );
+    }
+    // ========================================================================
+    /** simple function for accumulatio throught the HepMC3-graph
+     *  @param vertex pointer to HepMC3-graph
+     *  @param functor    function to be accumulated
+     *  @param predicate  restriction/selector for particles
+     *  @param result     the initial value for accumulation
+     *  @param range      the type of HepMC3-graph
+     *  @param binop      the operation used for accumulation
+     *  @return updated accumulation result
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     */
+    template <class RESULT, class FUNCTOR, class PREDICATE, class OPERATION>
+    inline RESULT accumulate( const HepMC3::ConstGenVertexPtr & vertex, const FUNCTOR& functor, const PREDICATE& predicate,
+                              RESULT result, const HepMC3::Relatives & range, OPERATION binop ) {
+      if ( !vertex ) { return result; }
+      auto particles = range(vertex);
+      return LoKi::Algs::accumulate( std::begin(particles), std::end(particles), functor, predicate,
+                                     result, binop );
+    }
+    // ========================================================================
+    template <class RESULT, class FUNCTOR, class PREDICATE>
+    inline RESULT accumulate( const HepMC3::ConstGenVertexPtr & vertex, const FUNCTOR& functor, const PREDICATE& predicate,
+                              RESULT result, const HepMC3::Relatives & range ) {
+      return accumulate( vertex, functor, predicate, result, range, std::plus<RESULT>() );
+    }
+    // ========================================================================
+    /** simple function for accumulatio throught the decay tree of the particle
+     *  @param particle the pointer to mother particle
+     *  @param functor    function to be accumulated
+     *  @param predicate  restriction/selector for particles
+     *  @param result     the initial value for accumulation
+     *  @param binop      the operation used for accumulation
+     *  @return updated accumulation result
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     */
+    template <class RESULT, class FUNCTOR, class PREDICATE, class OPERATION>
+    inline RESULT accumulate( const HepMC3::ConstGenParticlePtr & particle, const FUNCTOR& functor, const PREDICATE& predicate,
+                              RESULT result, OPERATION binop ) {
+      if ( particle ) {
+        result =
+            LoKi::GenAlgs::accumulate( particle->end_vertex(), functor, predicate, result, HepMC3::Relatives::DESCENDANTS, binop );
+      }
+      if ( predicate( particle ) ) { result = binop( result, functor( particle ) ); }
+      return result;
+    }
+    // ========================================================================
+    template <class RESULT, class FUNCTOR, class PREDICATE>
+    inline RESULT accumulate( const HepMC3::ConstGenParticlePtr & particle, const FUNCTOR& functor, const PREDICATE& predicate,
+                              RESULT result ) {
+      return accumulate( particle, functor, predicate, result, std::plus<RESULT>() );
+    }
+    // ========================================================================
+    /** simple function to extract the minimum value of certain function
+     *  form HepMC3-graph
+     *  @param vertex     pointer to HepMC3-graph
+     *  @param functor    function to be evaluated
+     *  @param predicate  restriction/selector for particles
+     *  @param range      the type of HepMC3-graph
+     *  @param minval     the initial value
+     *  @return updated accumulation result
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     */
+    template <class FUNCTION, class PREDICATE, class RESULT>
+    inline RESULT min_value( const HepMC3::ConstGenVertexPtr & vertex, const FUNCTION& fun, const PREDICATE& cut,
+                             const HepMC3::Relatives & range, RESULT minval ) {
+      if ( !vertex ) { return minval; } // RETURN
+      // investigate the vertex
+      auto particles = range(vertex);
+      auto ifound = LoKi::Algs::select_min( std::begin(particles), std::end(particles), fun, cut );
+      if ( std::end(particles) == ifound ) { return minval; } // RETURN
+      // check the minimum:
+      minval = std::min( minval, fun( *ifound ) );
+      return minval; // RETURN
+    }
+    // ========================================================================
+    /** The trivial algorithm which scans the decay
+     *  tree of the particle and searches for the the
+     *  minimal value for some functions for
+     *  particles which satisfy the certain criteria
+     *
+     *  @param particle the particle
+     *  @param fun      function to be evaluated
+     *  @param cut      the criteria
+     *  @param minval   minimal value
+     *  @return updated minimal value
+     *
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date   2007-02-20
+     */
+    template <class FUNCTION, class PREDICATE, class RESULT>
+    inline RESULT min_value( const HepMC3::ConstGenParticlePtr & particle, const FUNCTION& fun, const PREDICATE& cut,
+                             RESULT minval ) {
+      // (1) traverse the tree if possible
+      if ( particle ) {
+        // check all end-vertices :
+        minval = LoKi::GenAlgs::min_value( particle->end_vertex(), fun, cut, HepMC3::Relatives::DESCENDANTS, minval ); // RECURSION!
+      }
+      // (2) check itself
+      if ( cut( particle ) ) { minval = std::min( minval, fun( particle ) ); }
+      //
+      return minval; // RETURN
+    }
+    // ========================================================================
+    /** simple function to extract the maximum value of certain function
+     *  form HepMC3-graph
+     *  @param vertex     pointer to HepMC3-graph
+     *  @param functor    function to be evaluated
+     *  @param predicate  restriction/selector for particles
+     *  @param range      the type of HepMC3-graph
+     *  @param minval     the initial value
+     *  @return updated maximum
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     */
+    template <class FUNCTION, class PREDICATE, class RESULT>
+    inline RESULT max_value( const HepMC3::ConstGenVertexPtr & vertex, const FUNCTION& fun, const PREDICATE& cut,
+                             const HepMC3::Relatives & range, RESULT maxval ) {
+      if ( !vertex ) { return maxval; } // RETURN
+      // investigate the vertex
+      auto particles = range(vertex);
+      auto ifound = LoKi::Algs::select_max( std::begin(particles), std::end(particles), fun, cut );
+      // check the maximum
+      return ( std::end(particles) != ifound ) ? std::max( maxval, fun( *ifound ) ) : maxval;
+    }
+    // ========================================================================
+    /** The trivial algorithm which scans the decay
+     *  tree of the particle and searches for the the
+     *  maximal value for some functions for
+     *  particles which satisfy the certain criteria
+     *
+     *  @param particle the particle
+     *  @param fun      function to be evaluated
+     *  @param cut      the criteria
+     *  @param minval   minimal value
+     *  @return updated minimal value
+     *
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date   2007-02-20
+     */
+    template <class FUNCTION, class PREDICATE, class RESULT>
+    inline RESULT max_value( const HepMC3::ConstGenParticlePtr & particle, const FUNCTION& fun, const PREDICATE& cut,
+                             RESULT maxval ) {
+      // (1) traverse the tree if possible
+      if ( particle ) {
+        // check for endvertices
+        maxval = LoKi::GenAlgs::max_value( particle->end_vertex(), fun, cut, HepMC3::Relatives::DESCENDANTS, maxval ); // RECURSION!
+      }
+      // (2) check itself
+      return cut( particle ) ? std::max( maxval, fun( particle ) ) : maxval;
+    }
+    // ========================================================================
+    /** simple function to extract the mminimul value of certain function
+     *  for whole HepMC3-event
+     *  @param event      pointer to event
+     *  @param fun        function to be evaluated
+     *  @param cut        restriction/selector for particles
+     *  @param minval     the initial value
+     *  @return updated minimum
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     */
+    template <class FUNCTION, class PREDICATE, class RESULT>
+    inline RESULT min_value( const HepMC3::GenEvent* event, const FUNCTION& fun, const PREDICATE& cut, RESULT minval ) {
+      if ( !event ) { return minval; } // RETURN
+      //
+      auto ifound = LoKi::Algs::select_min( std::begin(event->particles()), std::end(event->particles()), fun, cut );
+      return ifound != std::end(event->particles()) ? std::min( minval, fun( *ifound ) ) : minval;
+    }
+    // ========================================================================
+    /** simple function to extract the maximum value of certain function
+     *  for whole HepMC3 event
+     *  @param event      pointer to event
+     *  @param fun        function to be evaluated
+     *  @param cut        restriction/selector for particles
+     *  @param maxval     the initial value of maximum
+     *  @return updated maximum
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     */
+    template <class FUNCTION, class PREDICATE, class RESULT>
+    inline RESULT max_value( const HepMC3::GenEvent* event, const FUNCTION& fun, const PREDICATE& cut, RESULT maxval ) {
+      if ( event ) { return maxval; } // RETURN
+      //
+      auto ifound = LoKi::Algs::select_max( std::begin(event->particles()), std::end(event->particles()), fun, cut );
+      return ifound != std::end(event->particles()) ? std::max( maxval, fun( *ifound ) ) : maxval;
+    }
+    // ========================================================================
+    /** simple function to extract the particle, which minimizes a
+     *  certain function
+     *  @param event      pointer to event
+     *  @param fun        function to be evaluated
+     *  @param cut        restriction/selector for particles
+     *  @return particle which mimimizes the function
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     */
+    template <class FUNCTION, class PREDICATE>
+    inline const HepMC3::ConstGenParticlePtr min_element( const HepMC3::GenEvent* event, const FUNCTION& fun,
+                                                          const PREDICATE& cut ) {
+      if ( !event ) { return nullptr; } // RETURN
+      auto ifound = LoKi::Algs::select_min( std::begin(event->particles()), std::end(event->particles()), fun, cut );
+      return ifound != std::end(event->particles()) ? *ifound : nullptr;
+    }
+    // ========================================================================
+    /** simple function to extract the particle, which minimizes a
+     *  certain function
+     *  @param vertex     pointer to HepMC3-graph
+     *  @param fun        function to be evaluated
+     *  @param cut        restriction/selector for particles
+     *  @param range      type of HepMC3-graph
+     *  @return particle which mimimizes the function
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     */
+    template <class FUNCTION, class PREDICATE>
+    inline const HepMC3::ConstGenParticlePtr min_element( const HepMC3::ConstGenVertexPtr & vertex, const FUNCTION& fun,
+                                                          const PREDICATE& cut, const HepMC3::Relatives & range ) {
+      if ( !vertex ) { return nullptr; } // RETURN
+      auto particles = range(vertex);
+      auto ifound = LoKi::Algs::select_min( std::begin(particles), std::end(particles), fun, cut );
+      return ifound != std::end(particles) ? *ifound : nullptr; // RETURN
+    }
+    // ========================================================================
+    /** simple function to extract the particle, which minimizes a
+     *  certain function
+     *  @param particle pointer to mother particle
+     *  @param fun      function to be evaluated
+     *  @param cut      restriction/selector for particles
+     *  @return particle which mimimizes the function
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     */
+    template <class FUNCTION, class PREDICATE>
+    inline const HepMC3::ConstGenParticlePtr min_element( const HepMC3::ConstGenParticlePtr & particle, const FUNCTION& fun,
+                                                  const PREDICATE& cut ) {
+      if ( !particle ) { return nullptr; } // RETURN
+      const HepMC3::ConstGenParticlePtr & tmp =
+          LoKi::GenAlgs::min_element( particle->end_vertex(), fun, cut, HepMC3::Relatives::DESCENDANTS);
+      if ( !tmp && cut( particle ) ) { return particle; } // RETURN
+      if ( !tmp ) { return nullptr; }                     // RETURN
+      return fun( tmp ) < fun( particle ) ? tmp : particle;
+    }
+    // ========================================================================
+    /** simple function to extract the particle, which maximizes a
+     *  certain function
+     *  @param event pointer to the event
+     *  @param fun   function to be evaluated
+     *  @param cut   restriction/selector for particles
+     *  @return particle which maximizes the function
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     */
+    template <class FUNCTION, class PREDICATE>
+    inline const HepMC3::ConstGenParticlePtr max_element( const HepMC3::GenEvent* event, const FUNCTION& fun,
+                                                  const PREDICATE& cut ) {
+      if ( !event ) { return nullptr; } // RETURN
+      auto ifound = LoKi::Algs::select_max( std::begin(event->particles()), std::end(event->particles()), fun, cut );
+      return ifound != std::end(event->particles())? *ifound : nullptr; // RETURN
+    }
+    // ========================================================================
+    /** simple function to extract the particle, which maximizes a
+     *  certain function
+     *  @param vertex pointer to HepMC3-graph
+     *  @param fun    function to be evaluated
+     *  @param cut    restriction/selector for particles
+     *  @param range      type of HepMC3-graph
+     *  @return particle which maximizes the function
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     */
+    template <class FUNCTION, class PREDICATE>
+    inline const HepMC3::ConstGenParticlePtr max_element( const HepMC3::ConstGenVertexPtr & vertex, const FUNCTION& fun,
+                                                  const PREDICATE& cut, const HepMC3::Relatives & range ) {
+      if ( 0 == vertex ) { return 0; } // RETURN
+      auto particles = range(vertex);
+      auto ifound =
+          LoKi::Algs::select_max( std::begin(particles), std::end(particles), fun, cut );
+      if ( std::end(particles) == ifound ) { return 0; } // RETURN
+      return *ifound;                                           // RETURN
+    }
+    // ========================================================================
+    /** simple function to extract the particle, which maximizes a
+     *  certain function
+     *  @param particle pointer to the mother particle
+     *  @param fun      function to be evaluated
+     *  @param cut      restriction/selector for particles
+     *  @return particle which maximizes the function
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     */
+    template <class FUNCTION, class PREDICATE>
+    inline const HepMC3::ConstGenParticlePtr max_element( const HepMC3::ConstGenParticlePtr & particle, const FUNCTION& fun,
+                                                  const PREDICATE& cut ) {
+      if ( 0 == particle ) { return 0; } // RETURN
+      auto tmp = LoKi::GenAlgs::max_element( particle->end_vertex(), fun, cut, HepMC3::Relatives::DESCENDANTS );
+      if ( 0 == tmp && cut( particle ) ) { return particle; } // RETURN
+      if ( 0 == tmp ) { return 0; }                           // RETURN
+      return fun( tmp ) < fun( particle ) ? tmp : particle;
+    }
+    // ========================================================================
+  } // namespace GenAlgs
+  // ==========================================================================
+} // namespace LoKi
+// ============================================================================
+//                                                                      The END
+// ============================================================================
+#endif // LOKI_GENALGS_H
diff --git a/Gen/LoKiGen/LoKi/GenAlgsDicts.h b/Gen/LoKiGen/LoKi/GenAlgsDicts.h
new file mode 100644
index 000000000..6d57e76a2
--- /dev/null
+++ b/Gen/LoKiGen/LoKi/GenAlgsDicts.h
@@ -0,0 +1,119 @@
+/*****************************************************************************\
+* (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration      *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                             *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+// ============================================================================
+#ifndef LOKI_GENALGSDICTS_H
+#define LOKI_GENALGSDICTS_H
+// ============================================================================
+// Include files
+// ============================================================================
+// LoKi
+// ============================================================================
+#include "HepMC3/GenEvent.h"
+#include "HepMC3/Relatives.h"
+
+#include "LoKi/Constants.h"
+#include "LoKi/GenTypes.h"
+// ============================================================================
+namespace LoKi {
+  namespace Dicts {
+    namespace GenAlgs {
+      // ======================================================================
+      /// count the particles in the event
+      std::size_t count_if( const HepMC3::GenEvent* event, const LoKi::GenTypes::GCuts& cuts );
+      // ======================================================================
+      /// count the particles in the tree
+      std::size_t count_if( const HepMC3::ConstGenParticlePtr & particle, const LoKi::GenTypes::GCuts& cuts );
+      // ======================================================================
+      /// count the particles in the tree
+      std::size_t count_if( const HepMC3::ConstGenVertexPtr & vertex, const LoKi::GenTypes::GCuts& cuts,
+                            const HepMC3::Relatives & range = HepMC3::Relatives::DESCENDANTS);
+      // ======================================================================
+      /// check the presence in the event
+      bool found( const HepMC3::GenEvent* event, const LoKi::GenTypes::GCuts& cuts );
+      // ======================================================================
+      /// check the presence in the tree
+      bool found( const HepMC3::ConstGenParticlePtr & particle, const LoKi::GenTypes::GCuts& cuts );
+      // ======================================================================
+      /// check the presence in the tree
+      bool found( const HepMC3::ConstGenVertexPtr & vertex, const LoKi::GenTypes::GCuts& cuts,
+                  const HepMC3::Relatives & range = HepMC3::Relatives::DESCENDANTS);
+      // ======================================================================
+      /// accumulate through the addition
+      double accumulate( const HepMC3::GenEvent* event, const LoKi::GenTypes::GFunc& fun,
+                         const LoKi::GenTypes::GCuts& cut, double res = 0.0 );
+      // ======================================================================
+      /// accumulate through the addition
+      double accumulate( const HepMC3::ConstGenVertexPtr & vertex, const LoKi::GenTypes::GFunc& fun,
+                         const LoKi::GenTypes::GCuts& cut, const HepMC3::Relatives & range = HepMC3::Relatives::DESCENDANTS,
+                         double res = 0.0 );
+      // ======================================================================
+      /// accumulate through the addition
+      double accumulate( const HepMC3::ConstGenParticlePtr & particle, const LoKi::GenTypes::GFunc& fun,
+                         const LoKi::GenTypes::GCuts& cut, double res = 0.0 );
+      // ======================================================================
+      /// find minimal value over the event
+      double min_value( const HepMC3::GenEvent* event, const LoKi::GenTypes::GFunc& fun,
+                        const LoKi::GenTypes::GCuts& cut, double res = LoKi::Constants::PositiveInfinity );
+      // ======================================================================
+      /// find minimal value over the tree:
+      double min_value( const HepMC3::ConstGenParticlePtr & particle, const LoKi::GenTypes::GFunc& fun,
+                        const LoKi::GenTypes::GCuts& cut, double res = LoKi::Constants::PositiveInfinity );
+      // ======================================================================
+      /// find minimal value over the tree:
+      double min_value( const HepMC3::ConstGenVertexPtr & veretx, const LoKi::GenTypes::GFunc& fun,
+                        const LoKi::GenTypes::GCuts& cut, const HepMC3::Relatives & range = HepMC3::Relatives::DESCENDANTS,
+                        double res = LoKi::Constants::PositiveInfinity );
+      // ======================================================================
+      /// find maximum value over the event
+      double max_value( const HepMC3::GenEvent* event, const LoKi::GenTypes::GFunc& fun,
+                        const LoKi::GenTypes::GCuts& cut, double res = LoKi::Constants::NegativeInfinity );
+      // ======================================================================
+      /// find maximum value over the tree
+      double max_value( const HepMC3::ConstGenParticlePtr & particle, const LoKi::GenTypes::GFunc& fun,
+                        const LoKi::GenTypes::GCuts& cut, double res = LoKi::Constants::NegativeInfinity );
+      // ======================================================================
+      /// find maximum value over the tree
+      double max_value( const HepMC3::ConstGenVertexPtr & vertex, const LoKi::GenTypes::GFunc& fun,
+                        const LoKi::GenTypes::GCuts& cut, const HepMC3::Relatives & range = HepMC3::Relatives::DESCENDANTS,
+                        double res = LoKi::Constants::NegativeInfinity );
+      // ======================================================================
+      /// find the minimum element through the event
+      HepMC3::ConstGenParticlePtr min_element( const HepMC3::GenEvent* event, const LoKi::GenTypes::GFunc& fun,
+                                             const LoKi::GenTypes::GCuts& cut );
+      /// find the minimum element through the tree
+      HepMC3::ConstGenParticlePtr min_element( const HepMC3::ConstGenParticlePtr & particle, const LoKi::GenTypes::GFunc& fun,
+                                             const LoKi::GenTypes::GCuts& cut );
+      // ======================================================================
+      /// find the minimum element through the tree
+      HepMC3::ConstGenParticlePtr min_element( const HepMC3::ConstGenVertexPtr & veretx, const LoKi::GenTypes::GFunc& fun,
+                                             const LoKi::GenTypes::GCuts& cut,
+                                             const HepMC3::Relatives &         range = HepMC3::Relatives::DESCENDANTS );
+      // ======================================================================
+      /// find the maximal element through the event
+      HepMC3::ConstGenParticlePtr max_element( const HepMC3::GenEvent* event, const LoKi::GenTypes::GFunc& fun,
+                                             const LoKi::GenTypes::GCuts& cut );
+      // ======================================================================
+      /// find the minimum element through the tree
+      HepMC3::ConstGenParticlePtr max_element( const HepMC3::ConstGenParticlePtr & particle, const LoKi::GenTypes::GFunc& fun,
+                                             const LoKi::GenTypes::GCuts& cut );
+      // ======================================================================
+      /// find the minimum element through the tree
+      HepMC3::ConstGenParticlePtr max_element( const HepMC3::ConstGenVertexPtr & veretx, const LoKi::GenTypes::GFunc& fun,
+                                             const LoKi::GenTypes::GCuts& cut,
+                                             const HepMC3::Relatives &         range = HepMC3::Relatives::DESCENDANTS );
+      // ======================================================================
+    } // namespace GenAlgs
+  }   // namespace Dicts
+} // end of namespace LoKi
+// ============================================================================
+// The END
+// ============================================================================
+#endif // LOKI_GENALGSDICTS_H
diff --git a/Gen/LoKiGen/LoKi/GenChild.h b/Gen/LoKiGen/LoKi/GenChild.h
new file mode 100644
index 000000000..d0c945e3e
--- /dev/null
+++ b/Gen/LoKiGen/LoKi/GenChild.h
@@ -0,0 +1,381 @@
+/*****************************************************************************\
+* (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration      *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                             *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+// ============================================================================
+#ifndef LOKI_GENCHILD_H
+#define LOKI_GENCHILD_H 1
+// ============================================================================
+// Include files
+// ============================================================================
+// HepMC3
+// ============================================================================
+#ifdef __INTEL_COMPILER
+// floating-point equality and inequality comparisons are unreliable
+#  pragma warning( disable : 1572 )
+#  pragma warning( push )
+#endif
+#include "HepMC3/GenEvent.h"
+#include "HepMC3/GenParticle.h"
+#include "HepMC3/GenVertex.h"
+#include "HepMC3/Relatives.h"
+#ifdef __INTEL_COMPILER
+#  pragma warning( pop )
+#endif
+// ============================================================================
+// GaudiKernel
+// ============================================================================
+#include "GaudiKernel/Kernel.h"
+// ============================================================================
+// LoKi
+// ============================================================================
+#include "LoKi/CmpBarCode.h"
+#include "LoKi/GenTypes.h"
+// ============================================================================
+/** @file
+ *  Set of functions to access daughtr particles
+ *
+ *  This file is a part of LoKi project -
+ *    "C++ ToolKit  for Smart and Friendly Physics Analysis"
+ *
+ *  The package has been designed with the kind help from
+ *  Galina PAKHLOVA and Sergey BARSUK.  Many bright ideas,
+ *  contributions and advices from G.Raven, J.van Tilburg,
+ *  A.Golutvin, P.Koppenburg have been used in the design.
+ *
+ *  @author Vanya BELYAEV Ivan.Belyaev@cern.ch
+ */
+// ============================================================================
+namespace LoKi {
+  // ==========================================================================
+  namespace GenChild {
+    // ========================================================================
+    /** get the number of children for the given HepMC3-particle
+     *  @see HepMC3::GenParticle
+     *  @param  mother pointer to HepMC3-particle
+     *  @return number of chilren
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date 2007-06-02
+     */
+    GAUDI_API
+    std::size_t nChildren( const HepMC3::ConstGenParticlePtr & mother );
+    // ========================================================================
+    /** Trivial accessor to the daughter "decay" particles for
+     *  the given HepMC3-particle
+     *
+     *  @attention index starts with 1 , null index corresponds
+     *             to the original particle
+     *
+     *  @param  mother   (const) pointer to mother particle
+     *  @param  index            index of the child particle
+     *  @return daughter particle with given index
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date 2007-06-02
+     */
+    GAUDI_API
+    HepMC3::ConstGenParticlePtr child( const HepMC3::ConstGenParticlePtr & mother, const size_t index );
+    // ========================================================================
+    /** Trivial accessor to the daughter "decay" particles for
+     *  the given HepMC3-particle
+     *
+     *  @attention index starts with 1 , null index corresponds
+     *             to the original particle
+     *
+     *  @param  particle (const) pointer to mother particle
+     *  @param  index1   index   index of the child particle
+     *  @param  index2   index   index of the child particle
+     *  @return daughter particle with given index
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date 2007-06-02
+     */
+    inline HepMC3::ConstGenParticlePtr child( const HepMC3::ConstGenParticlePtr & particle, const size_t index1,
+                                            const size_t index2 ) {
+      return child( child( particle, index1 ), index2 );
+    }
+    // ========================================================================
+    /** Trivial accessor to the daughter "decay" particles for
+     *  the given HepMC3-particle
+     *
+     *  @attention index starts with 1 , null index corresponds
+     *             to the original particle
+     *
+     *  @param  particle (const) pointer to mother particle
+     *  @param  index1   index   index of the child particle
+     *  @param  index2   index   index of the child particle
+     *  @param  index3   index   index of the child particle
+     *  @return daughter particle with given index
+     *  @author Vanya BELYAEV ibelyaev@phsycis.syr.edu
+     *  @date 2007-06-02
+     */
+    inline HepMC3::ConstGenParticlePtr child( const HepMC3::ConstGenParticlePtr & particle, const size_t index1,
+                                            const size_t index2, const size_t index3 ) {
+      return child( child( particle, index1 ), index2, index3 );
+    }
+    // ========================================================================
+    /** Trivial accessor to the daughter "decay" particles for
+     *  the given HepMC3-particle
+     *
+     *  @attention index starts with 1 , null index corresponds
+     *             to the original particle
+     *
+     *  @param  particle (const) pointer to mother particle
+     *  @param  index1   index   index of the child particle
+     *  @param  index2   index   index of the child particle
+     *  @param  index3   index   index of the child particle
+     *  @param  index4   index   index of the child particle
+     *  @return daughter particle with given index
+     *  @author Vanya BELYAEV ibelyaev@phsycis.syr.edu
+     *  @date 2007-06-02
+     */
+    inline HepMC3::ConstGenParticlePtr child( const HepMC3::ConstGenParticlePtr & particle, const size_t index1,
+                                            const size_t index2, const size_t index3, const size_t index4 ) {
+      return child( child( particle, index1 ), index2, index3, index4 );
+    }
+    // ========================================================================
+    GAUDI_API
+    HepMC3::ConstGenParticlePtr child( const HepMC3::ConstGenParticlePtr & particle, const std::vector<unsigned int>& indices );
+    // ========================================================================
+    /*  get all "in"-particles for the given vertex
+     *  @see HepMC3::GenVertex::particles_in_const_begin()
+     *  @see HepMC3::GenVertex::particles_in_const_end()
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date   2007-05-26
+     */
+    GAUDI_API
+    std::vector<HepMC3::ConstGenParticlePtr> particles_in( const HepMC3::ConstGenVertexPtr & vertex );
+    // ========================================================================
+    /*  get all "out"-particles for the given vertex
+     *  @see HepMC3::GenVertex::particles_in_const_begin()
+     *  @see HepMC3::GenVertex::particles_in_const_end()
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date   2007-05-26
+     */
+    GAUDI_API
+    std::vector<HepMC3::ConstGenParticlePtr> particles_out( const HepMC3::ConstGenVertexPtr & vertex );
+    // ========================================================================
+    /*  get all particles form the given event
+     *  @see HepMC3::GenEvent::particles_begin
+     *  @see HepMC3::GenEvent::particles_end
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date   2007-05-26
+     */
+    GAUDI_API
+    std::vector<HepMC3::ConstGenParticlePtr> particles_all( const HepMC3::GenEvent* event );
+    // ========================================================================
+    /** get all vertices form the given event
+     *  @see HepMC3::GenEvent::vertices_begin
+     *  @see HepMC3::GenEvent::vertices_end
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date   2007-05-26
+     */
+    GAUDI_API
+    std::vector<HepMC3::ConstGenVertexPtr> vertices_all( const HepMC3::GenEvent* event );
+    // ========================================================================
+    /** get all particles from the given vertex from the given range
+     *  @see HepMC3::GenVertex::particles_begin
+     *  @see HepMC3::GenVertex::particles_end
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date   2007-05-26
+     */
+    GAUDI_API
+    size_t particles( const HepMC3::ConstGenVertexPtr & vertex, const HepMC3::Relatives & range,
+                      std::vector<HepMC3::ConstGenParticlePtr>& output );
+    // ========================================================================
+    /** get all particles from the given vertex from the given range
+     *  @see HepMC3::GenVertex::particles_begin
+     *  @see HepMC3::GenVertex::particles_end
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date   2007-05-26
+     */
+    GAUDI_API
+    size_t particles( const HepMC3::ConstGenVertexPtr & vertex, const HepMC3::Relatives & range,
+                      LoKi::GenTypes::GenSet& output );
+    // ========================================================================
+    /** get all particles form the given vertex form the given range
+     *  @see HepMC3::GenVertex::particles_begin
+     *  @see HepMC3::GenVertex::particles_end
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date   2007-05-26
+     */
+    inline std::vector<HepMC3::ConstGenParticlePtr> particles( const HepMC3::ConstGenVertexPtr & vertex,
+                                                             const HepMC3::Relatives & range ) {
+      LoKi::GenTypes::GenSet result;
+      particles( vertex, range, result );
+      return std::vector<HepMC3::ConstGenParticlePtr>( result.begin(), result.end() );
+    }
+    // ========================================================================
+    /** get all "parents" particles form the given vertxex
+     *  @see LoKi::Child::particles
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date   2007-05-26
+     */
+    inline std::vector<HepMC3::ConstGenParticlePtr> parents( const HepMC3::ConstGenVertexPtr & vertex ) {
+      return particles( vertex, HepMC3::Relatives::PARENTS );
+    }
+    // ========================================================================
+    /** get all "daughter" particles form the given vertex
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date   2007-05-26
+     */
+    inline size_t daughters( const HepMC3::ConstGenVertexPtr & vertex, std::vector<HepMC3::ConstGenParticlePtr>& output ) {
+      return particles( vertex, HepMC3::Relatives::CHILDREN, output );
+    }
+    // ========================================================================
+    /** get all "daughter" particles form the given vertex
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date   2007-05-26
+     */
+    inline size_t daughters( const HepMC3::ConstGenVertexPtr & vertex, LoKi::GenTypes::GenSet& output ) {
+      return particles( vertex, HepMC3::Relatives::CHILDREN, output );
+    }
+    // ========================================================================
+    /** get all "daughter" particles form the given particle
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date   2007-05-26
+     */
+    GAUDI_API
+    size_t daughters( const HepMC3::ConstGenParticlePtr & particle, std::vector<HepMC3::ConstGenParticlePtr>& output );
+    // ========================================================================
+    /** get all "daughter" particles form the given particle
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date   2007-05-26
+     */
+    GAUDI_API
+    size_t daughters( const HepMC3::ConstGenParticlePtr & particle, LoKi::GenTypes::GenSet& output );
+    // ========================================================================
+    /** get all "children" particles form the given vertex
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date   2007-05-26
+     */
+    inline std::vector<HepMC3::ConstGenParticlePtr> children( const HepMC3::ConstGenVertexPtr & vertex ) {
+      return particles( vertex, HepMC3::Relatives::CHILDREN);
+    }
+    // ========================================================================
+    /** get all "children" particles form the given particle
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date   2007-05-26
+     */
+    inline std::vector<HepMC3::ConstGenParticlePtr> children( const HepMC3::ConstGenParticlePtr & particle ) {
+      std::vector<HepMC3::ConstGenParticlePtr> result;
+      daughters( particle, result );
+      return result;
+    }
+    // ========================================================================
+    /** get all "ancestors" particles form the given vertex
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date   2007-05-26
+     */
+    inline std::vector<HepMC3::ConstGenParticlePtr> ancestors( const HepMC3::ConstGenVertexPtr & vertex ) {
+      return particles( vertex, HepMC3::Relatives::ANCESTORS);
+    }
+    // ========================================================================
+    /** get all "ancestors" particles form the givel particlle
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date   2007-05-26
+     */
+    std::vector<HepMC3::ConstGenParticlePtr> ancestors( const HepMC3::ConstGenParticlePtr & particle );
+    // ========================================================================
+    /** get all "descendants" particles form the given vertex
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date   2007-05-26
+     */
+    inline std::vector<HepMC3::ConstGenParticlePtr> descendants( const HepMC3::ConstGenVertexPtr & vertex ) {
+      return particles( vertex, HepMC3::Relatives::DESCENDANTS);
+    }
+    // ========================================================================
+    /** get all "descendant" particles form the given particle
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date   2007-05-26
+     */
+    GAUDI_API
+    std::vector<HepMC3::ConstGenParticlePtr> descendants( const HepMC3::ConstGenParticlePtr & particle );
+    // ========================================================================
+    /** get all "relatives" particles from the given vertex
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date   2007-05-26
+     */
+    //inline std::vector<HepMC3::ConstGenParticlePtr> relatives( const HepMC3::ConstGenVertexPtr & vertex ) {
+      //return particles( vertex, HepMC3::relatives );
+    //}
+    // ========================================================================
+    /// forward declaration
+    class Selector; // forward declaration
+    // ========================================================================
+    /** Trivial accessor to the daughter particles for the given particle.
+     *  @param  particle (const) pointer to mother particle
+     *  @param  selector the selector
+     *  @author Vanya BELYAEV Ivan.Belyaev@itep.ru
+     *  @date   2012-01-26
+     */
+    GAUDI_API
+    HepMC3::ConstGenParticlePtr child( const HepMC3::ConstGenParticlePtr & particle, const LoKi::GenChild::Selector& selector );
+    // ========================================================================
+    /** accessor to certain children particles for the given particle
+     *  @param  particle (INPUT) pointer to mother particle
+     *  @param  selector (INPUT) the selector
+     *  @param  result   (OUTPUT) the container of found particles
+     *  @return number of found particles
+     *  @author Vanya BELYAEV Ivan.Belyaev@itep.ru
+     *  @date   2012-01-26
+     */
+    GAUDI_API
+    unsigned int children( const HepMC3::ConstGenParticlePtr & particle, const LoKi::GenChild::Selector& selector,
+                           LoKi::GenTypes::ConstVector& daughters );
+    // ========================================================================
+    /** accessor to certain children particles for the given particle
+     *  @param  particle (INPUT) pointer to mother particle
+     *  @param  selector (INPUT) the selector
+     *  @return the container of found particles
+     *  @author Vanya BELYAEV Ivan.Belyaev@itep.ru
+     *  @date   2010-05-29
+     */
+    GAUDI_API
+    LoKi::GenTypes::ConstVector children( const HepMC3::ConstGenParticlePtr & particle,
+                                          const LoKi::GenChild::Selector& selector );
+    // ========================================================================
+    /** get all independent decay trees from HepMC3::GenEvent
+     *  @see LoKi::GenTrees::buildTrees
+     *  @author Vanya BELYAEV Ivan.Belyaev@itep.ru
+     *  @date   2016-01-17
+     *  @attention  it could be a bit slow
+     */
+    GAUDI_API
+    LoKi::GenTypes::ConstVector trees( const HepMC3::GenEvent* event );
+    // ========================================================================
+    /** get all independent decay trees from container of particles
+     *  @see LoKi::GenTrees::buildTrees
+     *  @author Vanya BELYAEV Ivan.Belyaev@itep.ru
+     *  @date   2016-01-17
+     *  @attention  it could be a bit slow
+     */
+    GAUDI_API
+    LoKi::GenTypes::ConstVector trees( const LoKi::GenTypes::ConstVector& particles );
+    // ========================================================================
+    /** get all independent decay trees from container of particles
+     *  @see LoKi::GenTrees::buildTrees
+     *  @author Vanya BELYAEV Ivan.Belyaev@itep.ru
+     *  @date   2016-01-17
+     *  @attention  it could be a bit slow
+     */
+    GAUDI_API
+    LoKi::GenTypes::ConstVector trees( const LoKi::GenTypes::GRange& particles );
+    // ========================================================================
+  } // namespace GenChild
+  // ==========================================================================
+  namespace Child {
+    // ========================================================================
+    using namespace LoKi::GenChild;
+    // ========================================================================
+  } // namespace Child
+  // ==========================================================================
+} //                                                      end of namespace LoKi
+// ============================================================================
+//                                                                      The END
+// ============================================================================
+#endif // LOKI_GENCHILD_H
diff --git a/Gen/LoKiGen/LoKi/GenChildSelector.h b/Gen/LoKiGen/LoKi/GenChildSelector.h
new file mode 100644
index 000000000..21f6e0f57
--- /dev/null
+++ b/Gen/LoKiGen/LoKi/GenChildSelector.h
@@ -0,0 +1,175 @@
+/*****************************************************************************\
+* (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration      *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                             *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+// ============================================================================
+#ifndef LOKI_GENCHILDSELECTOR_H
+#define LOKI_GENCHILDSELECTOR_H 1
+// ============================================================================
+// Include files
+// ============================================================================
+// GaudiKernel
+// ============================================================================
+#include "GaudiKernel/Kernel.h"
+// ============================================================================
+// Kernel/PartProp
+// ============================================================================
+#include "Kernel/iNode.h"
+// ============================================================================
+// LoKi
+// ============================================================================
+#include "LoKi/AuxFunBase.h"
+#include "LoKi/GenTypes.h"
+#include "LoKi/IGenDecay.h"
+#include "LoKi/iTree.h"
+// ============================================================================
+/** @file LoKi/GenChildSelector.h
+ *
+ *  This file is a part of LoKi project -
+ *    "C++ ToolKit  for Smart and Friendly Physics Analysis"
+ *
+ *  The package has been designed with the kind help from
+ *  Galina PAKHLOVA and Sergey BARSUK.  Many bright ideas,
+ *  contributions and advices from G.Raven, J.van Tilburg,
+ *  A.Golutvin, P.Koppenburg have been used in the design.
+ *
+ *  @author Vanya Belyaev  Ivan.Belyaev@cern.ch
+ *  @date 2011-12-11
+ *
+ */
+// ============================================================================
+namespace LoKi {
+  // ==========================================================================
+  namespace GenChild {
+    // ========================================================================
+    /** @class Selector LoKi/GenChildSelector.h
+     *
+     *  "Child-selector" for HepMC3-particles
+     *
+     *  This file is a part of LoKi project -
+     *    "C++ ToolKit  for Smart and Friendly Physics Analysis"
+     *
+     *  The package has been designed with the kind help from
+     *  Galina PAKHLOVA and Sergey BARSUK.  Many bright ideas,
+     *  contributions and advices from G.Raven, J.van Tilburg,
+     *  A.Golutvin, P.Koppenburg have been used in the design.
+     *
+     *  @author Vanya Belyaev  Ivan.Belyaev@cern.ch
+     *  @date   2011-12-13
+     */
+    // ========================================================================
+    class GAUDI_API Selector final : public LoKi::AuxFunBase {
+    public:
+      // ======================================================================
+      /// the vector of selectors
+      typedef std::vector<LoKi::GenChild::Selector> Vector;
+      // ======================================================================
+    public:
+      // ======================================================================
+      /// constructor from the indices
+      Selector( const std::vector<unsigned int>& indices );
+      /// constructor from decay node
+      Selector( const Decays::iNode& node );
+      /// constructor from decay tree
+      Selector( const Decays::IGenDecay::iTree& child );
+      /// constructor from decay tree
+      Selector( const Decays::IGenDecay::Finder& child );
+      /// constructor from decay desctriptor
+      Selector( const std::string& child );
+      /// constructor from decay desctriptor & factory
+      Selector( const std::string& child, const std::string& factory );
+      /// constructor from the cut
+      Selector( const LoKi::Types::GCuts& cut );
+      /// OPTIONAL: nice printout
+      std::ostream& fillStream( std::ostream& s ) const override;
+      // ======================================================================
+    public:
+      // ======================================================================
+      /** get the child according to the selector
+       *  @param  head (INPUT) the head fo the decay tree
+       *  @return child particle
+       */
+      HepMC3::ConstGenParticlePtr child( const HepMC3::ConstGenParticlePtr & head ) const;
+      /** get the child according to the selector
+       *  @param head      (INPUT) the head fo the decay tree
+       *  @param daughters (UPDATE)
+       *  @return number of particles
+       */
+      unsigned int children( const HepMC3::ConstGenParticlePtr & head, LoKi::GenTypes::ConstVector& daughters ) const;
+      // ======================================================================
+    public:
+      // ======================================================================
+      /// check the validity the child-selector
+      bool valid() const;
+      /// try to validate it!
+      StatusCode validate( const LHCb::IParticlePropertySvc* svc ) const;
+      // ======================================================================
+    private:
+      // ======================================================================
+      /// build the decay tree form the descriptor
+      StatusCode buildTree( const std::string& descriptor, const std::string& factory );
+      // ======================================================================
+    private:
+      // ======================================================================
+      /// the child selector by index
+      std::vector<unsigned int> m_indices; // the child selector by index
+      /// rule to find the child
+      Decays::IGenDecay::Finder m_finder; //      rule to find the child
+      /// cut set
+      bool m_setCut; //                     cut set
+      /// the cut
+      LoKi::Types::GCut m_cut; //                     the cut
+      // ======================================================================
+    };
+    // ========================================================================
+    /** Trivial accessor to the daughter particles for the given particle.
+     *  @param  particle (const) pointer to mother particle
+     *  @param  dscriptor
+     *  @author Vanya BELYAEV Ivan.Belyaev@itep.ru
+     *  @date   2016-06-21
+     */
+    GAUDI_API
+    HepMC3::ConstGenParticlePtr child( const HepMC3::ConstGenParticlePtr & particle, const std::string& descriptor );
+    // ========================================================================
+    /** Trivial accessor to the daughter particles for the given particle.
+     *  @param  particle (const) pointer to mother particle
+     *  @param  cuts     (INPUT) cuts to be used
+     *  @author Vanya BELYAEV Ivan.Belyaev@itep.ru
+     *  @date   2016-06-21
+     */
+    GAUDI_API
+    HepMC3::ConstGenParticlePtr child( const HepMC3::ConstGenParticlePtr & particle, const LoKi::Types::GCuts& cuts );
+    // ========================================================================
+    /** accessor to certain children particles for the given particle
+     *  @param  particle   (INPUT) pointer to mother particle
+     *  @param  descriptor (INPUT) the descriptor
+     *  @return the container of found particles
+     *  @author Vanya BELYAEV Ivan.Belyaev@itep.ru
+     *  @date   2016-06-21
+     */
+    GAUDI_API
+    LoKi::GenTypes::ConstVector children( const HepMC3::ConstGenParticlePtr & particle, const std::string& descriptor );
+    // ========================================================================
+    /** accessor to certain children particles for the given particle
+     *  @param  particle (INPUT) pointer to mother particle
+     *  @param  cuts     (INPUT) cuts to be used
+     *  @return the container of found particles
+     *  @author Vanya BELYAEV Ivan.Belyaev@itep.ru
+     *  @date   2016-06-21
+     */
+    GAUDI_API
+    LoKi::GenTypes::ConstVector children( const HepMC3::ConstGenParticlePtr & particle, const LoKi::Types::GCuts& cuts );
+    // ========================================================================
+  } // namespace GenChild
+  // ==========================================================================
+} //                                                      end of namespace LoKi
+// ============================================================================
+//                                                                      The END
+// ============================================================================
+#endif // LOKI_GENCHILDSELECTOR_H
diff --git a/Gen/LoKiGen/LoKi/GenDecayChain.h b/Gen/LoKiGen/LoKi/GenDecayChain.h
new file mode 100644
index 000000000..ab3206b97
--- /dev/null
+++ b/Gen/LoKiGen/LoKi/GenDecayChain.h
@@ -0,0 +1,272 @@
+/*****************************************************************************\
+* (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration      *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                             *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+// ============================================================================
+#ifndef LOKI_GENDECAYCHAIN_H
+#define LOKI_GENDECAYCHAIN_H 1
+// ============================================================================
+// Include files
+// ============================================================================
+// GenEvent
+// ============================================================================
+#include "HepMC3/GenEvent.h"
+// ============================================================================
+// LoKi
+// ============================================================================
+#include "LoKi/BuildGenTrees.h"
+#include "LoKi/DecayChainBase.h"
+#include "LoKi/GenTypes.h"
+// ============================================================================
+/** @file
+ *
+ *  This file is a part of LoKi project -
+ *    "C++ ToolKit  for Smart and Friendly Physics Analysis"
+ *
+ *  The package has been designed with the kind help from
+ *  Galina PAKHLOVA and Sergey BARSUK.  Many bright ideas,
+ *  contributions and advices from G.Raven, J.van Tilburg,
+ *  A.Golutvin, P.Koppenburg have been used in the design.
+ *
+ *  @author Vanya Belyaev Ivan.Belyaev@cern.ch
+ *  @date   2011-06-03
+ *
+ */
+// ============================================================================
+namespace LoKi {
+  // ==========================================================================
+  /** @class GenDecayChain
+   *  Utility to print the decays
+   *
+   *  @author Vanya Belyaev Ivan.Belyaev@cern.ch
+   *  @date   2011-06-03
+   */
+  class GAUDI_API GenDecayChain final : public virtual DecayChainBase {
+  protected:
+    // ========================================================================
+    typedef LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::BooleanConstant AcceptGen;
+    // ========================================================================
+  public:
+    // ========================================================================
+    /** Standard constructor
+     *  @param maxDepth  maximal decay depth
+     *  @param vertex    vertex info to be printed
+     *  @param mode      mode for printout of 4-vectors
+     *  @param fg        color for foreground for 'marked' lines
+     *  @param bg        color for background for 'marked' lines
+     *  @param vertexe   end-vertex info for MC particles to be printed
+     */
+    GenDecayChain( const size_t maxDepth = 10, const bool vertex = false, const Mode mode = LV_WITHPT,
+                   const MSG::Color& fg = MSG::YELLOW, const MSG::Color& bg = MSG::RED, const bool vertexe = true );
+    /** Standard constructor
+     *  @param vertexe   end-vertex info for MC particles to be printed
+     */
+    GenDecayChain( const LoKi::DecayChainBase& base, const bool vertexe = true );
+    // ========================================================================
+  public:
+    // ========================================================================
+    /// print end-vertex info ?
+    bool vertexe() const { return m_vertexe; }
+    void setVertexE( const bool value ) { m_vertexe = value; }
+    // ========================================================================
+  public:
+    // ========================================================================
+    /** print decay chain for sequence of objects
+     *  @param first    begin of sequence of objects
+     *  @param last     end   of sequence of objects
+     *  @param stream   reference to output stream
+     *  @param term     stream terminator
+     */
+    template <class PARTICLE, class STREAM, class TERMINATOR, class ACCEPT, class MARK>
+    STREAM& print( PARTICLE first, PARTICLE last, STREAM& stream, TERMINATOR term, const ACCEPT& accept,
+                   const MARK& mark, const std::string& prefix, const size_t depth ) const;
+    // ========================================================================
+  public:
+    // ========================================================================
+    /** print the decay chain for HepMC3::GenParticle
+     *
+     *  @code
+     *
+     *    GenDecayChain dc ;
+     *    HepMC3::ConstGenParticlePtr head = ... ;
+     *
+     *    /// print decay chain to standard output
+     *    dc.print ( head , std::cout , std::endl ) ;
+     *
+     *    /// print decay chain to gausdi message stream
+     *    MsgStream log( msgSvc() , name() ) ;
+     *    dc.print ( head , log , endmsg          ) ;
+     *
+     *  @endcode
+     *
+     *  @param particle pointer to the particle
+     *  @param stream   reference to output stream
+     *  @param term     stream terminator
+     */
+
+    template <class STREAM, class TERMINATOR, class ACCEPT, class MARK>
+    STREAM& print( const HepMC3::ConstGenParticlePtr & particle, STREAM& stream, TERMINATOR term, const ACCEPT& accept,
+                   const MARK& mark, const std::string& prefix = " ", const size_t depth = 0 ) const {
+      // invalid particle
+      if ( 0 == particle ) {
+        Error( " HepMC3::GenParticlePtr points to NULL" );
+        return stream; // RETURN
+      }
+      //
+      stream << term;
+      //
+      // FIXME: Raw pointer here as some functions args are const void *
+      const bool marked = LoKi::GenTypes::_ptr_wrap(mark)( particle );
+      //
+      size_t _indent = 0;
+      {
+        // use colors :-))
+        MarkStream<STREAM> ms( stream, marked, fg(), bg() );
+        //
+        const std::string   p_name  = name( LHCb::ParticleID( particle->pdg_id() ) );
+        const unsigned long l_depth = std::max( 3 * ( std::min( maxDepth(), size_t( 20 ) ) - depth ), size_t( 0 ) );
+        const std::string   l_blank = blank( 1 + l_depth );
+        //
+        stream << ( marked ? '*' : ' ' ) << depth << prefix << "|->" << p_name << l_blank;
+        //
+        _indent += 2;
+        _indent += prefix.length();
+        _indent += 2;
+        _indent += p_name.length();
+        _indent += l_blank.length();
+        //
+        if ( depth > 9 ) { _indent += 1; }
+        if ( depth > 99 ) { _indent += 1; }
+        if ( depth > 999 ) { _indent += 1; }
+        //
+      }
+      //
+      if ( !marked && maxDepth() < depth ) {
+        stream << " ... (max depth)     ";
+        return stream;
+      } // RETURN
+      //
+      // FIXME: Raw pointer here as some functions args are const void *
+      if ( !marked && !LoKi::GenTypes::_ptr_wrap(accept)( particle ) ) {
+        stream << " ... (skip  by cuts) ";
+        return stream;
+      } // RETURN
+      //
+      stream << toString( LoKi::LorentzVector( particle->momentum() ) );
+      stream << " #" << toString( particle->id() ) << "/" << toString( particle->status() );
+      //
+      auto vertex = particle->production_vertex();
+      if ( m_vertex && 0 != vertex ) {
+        // use the terminator
+        stream << term;
+        stream << blank( _indent + 5 );
+        stream << " Origin    " << toString( LoKi::Point3D( vertex->position() ) );
+        stream << " #" << toString( vertex->id() );
+      }
+      // print all end-vertices
+      auto evertex = particle->end_vertex();
+      if ( m_vertex && m_vertexe && 0 != evertex ) {
+        // use terminator
+        stream << term;
+        stream << blank( _indent + 5 );
+        stream << " EndVertex " << toString( LoKi::Point3D( evertex->position() ) );
+        stream << " #" << toString( evertex->id() );
+      }
+      //
+      if ( 0 != evertex ) {
+        auto particles = HepMC3::Relatives::CHILDREN(evertex);
+        auto begin = std::begin(particles);
+        auto end   = std::end(particles);
+        print( begin, end, stream, term, accept, mark, prefix + "   ", depth + 1 );
+      }
+      //
+      return stream;
+    }
+    // ========================================================================
+    /** print the decay chain for HepMC3::GenEvent
+     *
+     *  Essentially it prints the decay tree from "signal_vertex"
+     *  or vertex with barcode equal to -1
+     *
+     *  @code
+     *
+     *    GenDecayChain dc ;
+     *    const HepMC3::GenEvent* event = ... ;
+     *
+     *    /// print decay chain to standard output
+     *    dc.print ( event , std::cout , std::endl ) ;
+     *
+     *    /// print decay chain to gaudi message stream
+     *    MsgStream log( msgSvc() , name() ) ;
+     *    dc.print ( event , log , endmsg          ) ;
+     *
+     *  @endcode
+     *
+     *  @param event    pointer to the event
+     *  @param stream   reference to output stream
+     *  @param term     stream terminator
+     */
+    template <class STREAM, class TERMINATOR, class ACCEPT, class MARK>
+    STREAM& print( const HepMC3::GenEvent* event, STREAM& stream, TERMINATOR term, const ACCEPT& accept,
+                   const MARK& mark, const std::string& prefix = " ", const size_t depth = 0 ) const {
+      // invalid event
+      if ( !event ) {
+        Error( " HepMC3::GenEvent* points to NULL" );
+        return stream;
+      }
+      // select the trees
+      LoKi::GenTypes::GenContainer trees;
+      trees.reserve( event->particles().size() );
+      LoKi::GenTrees::buildTrees( std::begin(event->particles()), std::end(event->particles()), std::back_inserter( trees ) );
+      // print the trees
+      return print( trees.begin(), trees.end(), stream, term, accept, mark, prefix, depth );
+    }
+    // ========================================================================
+  public:
+    // ========================================================================
+    /// predefined printout
+    std::string print_( const HepMC3::ConstGenParticlePtr & p, const LoKi::Types::GCuts& accept = AcceptGen( true ),
+                        const LoKi::Types::GCuts& mark = AcceptGen( false ) ) const;
+    /// predefined printout
+    std::string print_( const LoKi::Types::GRange& e, const LoKi::Types::GCuts& accept = AcceptGen( true ),
+                        const LoKi::Types::GCuts& mark = AcceptGen( false ) ) const;
+    /// predefined printout
+    std::string print_( const LoKi::GenTypes::GenContainer& e, const LoKi::Types::GCuts& accept = AcceptGen( true ),
+                        const LoKi::Types::GCuts& mark = AcceptGen( false ) ) const;
+    /// predefined printout
+    std::string print_( const HepMC3::GenEvent* e, const LoKi::Types::GCuts& accept = AcceptGen( true ),
+                        const LoKi::Types::GCuts& mark = AcceptGen( false ) ) const;
+    // ========================================================================
+  private:
+    // ========================================================================
+    /// print all end-vertices information
+    bool m_vertexe; // print all end-vertices  information
+    // ========================================================================
+  };
+  // ==========================================================================
+} //                                                      end of namespace LoKi
+// ============================================================================
+/*  print decay chain for sequence of objects
+ *  @param first    begin of sequence of objects
+ *  @param last     end   of sequence of objects
+ *  @param stream   reference to output stream
+ *  @param term     stream terminator
+ */
+// ============================================================================
+template <class PARTICLE, class STREAM, class TERMINATOR, class ACCEPT, class MARK>
+STREAM& LoKi::GenDecayChain::print( PARTICLE first, PARTICLE last, STREAM& stream, TERMINATOR term,
+                                    const ACCEPT& accept, const MARK& mark, const std::string& prefix,
+                                    const size_t depth ) const {
+  for ( ; first != last; ++first ) { print( *first, stream, term, accept, mark, prefix, depth ); }
+  return stream;
+}
+// ============================================================================
+//                                                                      The END
+// ============================================================================
+#endif // LOKI_GENDECAYCHAIN_H
diff --git a/Gen/LoKiGen/LoKi/GenDecays.h b/Gen/LoKiGen/LoKi/GenDecays.h
new file mode 100644
index 000000000..bd9b4eba8
--- /dev/null
+++ b/Gen/LoKiGen/LoKi/GenDecays.h
@@ -0,0 +1,1063 @@
+/*****************************************************************************\
+* (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration      *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                             *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+// ============================================================================
+#ifndef LOKI_GENDECAYS_H
+#define LOKI_GENDECAYS_H 1
+// ============================================================================
+// Include files
+// ============================================================================
+// Event
+// ============================================================================
+#include "HepMC3/GenEvent.h"
+// ============================================================================
+// PartProp
+// ============================================================================
+#include "Kernel/Nodes.h"
+#include "Kernel/NodesPIDs.h"
+// ============================================================================
+// LoKiDecay
+// ============================================================================
+#include "LoKi/DecayDescriptor.h"
+#include "LoKi/Trees.h"
+// ============================================================================
+/** @file
+ *  Implementation file for LoKi HepMC3-specific decay/tree-functors
+ *  @author Vanya BELYAEV Ivan.BELYAEV@nikhef.nl
+ *  @date   2008-06-10
+ */
+// ============================================================================
+namespace Decays {
+  // ==========================================================================
+  namespace Trees {
+    // ======================================================================
+    /** @class GenExclusive
+     *  Simple sub tree which consists of the node ("mother") and
+     *  subtrees ("children"). Essentially it represent also the
+     *  "semi-exclusive" decay (as well as any decay with the fixed
+     *  number of components for comparisons).
+     *
+     *  Define the simple regular decay, e.g. \f$ B^0 \to \pi^+ \pi^- \f$:
+     *
+     *  @code
+     *
+     *   // " B0 -> pi+ pi- "
+     *
+     *   using namespace Decays ;
+     *
+     *   typedef Trees::GenExclusive::TreeList    Children ;
+     *
+     *   // define daughters:
+     *   Children children ;
+     *   children.push_back ( Trees::GenExclusive ( "pi+" ) ) ;
+     *   children.push_back ( Trees::GenExclusive ( "pi-" ) ) ;
+     *
+     *   Decays::Trees::GenExclusive decay
+     *             ( "B0"    ,     // the parent
+     *               chidren ) ;   // children
+     *
+     *  @endcode
+     *
+     *  Define the "decay-in-sections", e.g. all following
+     *  decays will be correctly matched with the descriptor
+     *  <c>" B0 --> pi+ pi- pi0 "</c>":
+     *    - \f$ B^0 \to \left( \rho^0 \to \pi^+ \pi^-   \right)
+     *               \left( \pi^0  \to \gamma \gamma \right) \f$
+     *    - \f$ B^0 \to \left( \rho^+ \to \pi^+ \pi^0   \right) \pi^-\f$
+     *    - \f$ B^0 \to \left( \rho^- \to \pi^- \pi^0   \right) \pi^+\f$
+     *
+     *  @code
+     *
+     *   // " B0 --> pi+ pi- pi0 "
+     *
+     *   using namespace Decays ;
+     *
+     *   typedef Trees::GenExclusive::TreeList    Children ;
+     *
+     *   // define daughters:
+     *   Children children ;
+     *   children.push_back ( Trees::GenExclusive ( "pi+" ) ) ;
+     *   children.push_back ( Trees::GenExclusive ( "pi-" ) ) ;
+     *   children.push_back ( Trees::GenExclusive ( "pi0" ) ) ;
+     *
+     *   Trees::GenExclusive decay
+     *             ( "B0"            ,   // parent
+     *               chidren         ,   // children
+     *               Trees::Sections ) ; // matching algorithm
+     *
+     *  @endcode
+     *
+     *  Define the "decay-with-oscillation". Here the mother particle
+     *  is required to oscillate before the decay, e.g.
+     *  \f$ B^0 \to \bar{B}^0 \to \pi^+ \pi^- \f$:
+     *
+     *  @code
+     *
+     *   // " [B0]os -> pi+ pi- "
+     *
+     *   using namespace Decays ;
+     *
+     *   typedef Trees::GenExclusive::SubTrees    Children ;
+     *
+     *   // define daughters:
+     *   Children children ;
+     *   children.push_back ( Trees::GenExclusive ( "pi+" ) ) ;
+     *   children.push_back ( Trees::GenExclusive ( "pi-" ) ) ;
+     *
+     *   Trees::GenExclusive decay
+     *             ( "B0"              ,   // parent
+     *               chidren           ,   // children
+     *               Trees::Daughetrs  ,   // matching algorithm
+     *               Trees::Oscillated ) ; // oscillation flag
+     *
+     *  @endcode
+     *
+     *  Define the "decay-without-oscillations":
+     *
+     *  @code
+     *
+     *   // " [B0]nos --> pi+ pi- pi0 "
+     *
+     *   using namespace Decays ;
+     *
+     *   typedef Trees::GenExclusive::TreeList    Children ;
+     *
+     *   // define daughters:
+     *   Children children ;
+     *   children.push_back ( Trees::GenExclusive ( "pi+" ) ) ;
+     *   children.push_back ( Trees::GenExclusive ( "pi-" ) ) ;
+     *   children.push_back ( Trees::GenExclusive ( "pi0" ) ) ;
+     *
+     *   Trees::GenExclusive decay
+     *             ( "B0"                 ,   // parent
+     *               chidren              ,   // children
+     *               Trees::Sections      ,   // matching algorithm
+     *               Trees::NotOscillated ) ; // oscillation flag
+     *
+     *  @endcode
+     *
+     *
+     *  Define the complex decay, e.g.
+     *  \f$  B^0 \to \bar{B}^0 \to
+     *    \left( \rho^0 \to \pi^+ \pi^- \right) \pi^0 \f$:
+     *
+     *  @code
+     *
+     *   // " [B0]os -> ( rho(770)0 -> pi+ pi- ) pi0 "
+     *
+     *
+     *   using namespace Decays ;
+     *
+     *   typedef Trees::GenExclusive::TreeList    Children ;
+     *
+     *   // define daughters:
+     *   Children children ;
+     *   children.push_back ( Trees::GenExclusive ( "pi+" ) ) ;
+     *   children.push_back ( Trees::GenExclusive ( "pi-" ) ) ;
+     *
+     *   Trees::GenExclusive rho
+     *             ( "rho(770)0"          ,   // parent
+     *               chidren              ) ; // children
+     *
+     *   children.clear()
+     *   children.push_back ( rho ) ;
+     *   children.push_back ( Trees::GenExclusive ( "pi0" ) ) ;
+     *
+     *   Trees::GenExclusive decay
+     *             ( "B0"                 ,   // parent
+     *               chidren              ,   // children
+     *               Trees::Daughters     ,   // matching algorithm
+     *               Trees::NotOscillated ) ; // oscillation flag
+     *  @endcode
+     *
+     *  Define "semi-inclusive" decays, e.g.
+     *  \f$ B^0 \to X^+ X^- \f$, where
+     *  \f$X^+\f$ and \f$X^-\f$ are any posively and negatively
+     *  charged particles:
+     *
+     *  @code
+     *
+     *   // " B0 -> X+ X- "
+     *
+     *   using namespace Decays ;
+     *
+     *   typedef Trees::GenExclusive::TreeList    Children ;
+     *
+     *   // define daughters:
+     *   Children children ;
+     *   children.push_back ( Trees::GenExclusive ( Nodes::Positive () ) ) ;
+     *   children.push_back ( Trees::GenExclusive ( Nodes::Negative () ) ) ;
+     *
+     *   Trees::GenExclusive decay
+     *             ( "B0"    ,     // the parent
+     *               chidren ) ;   // chidlren
+     *
+     *  @endcode
+     *
+     *  The <c>algorithm</c> is defined by the length  of the arrow:
+     *
+     *    - <c> "->"</c> the decay is defined in terms of direct daughters
+     *    - <c>"-->"</c> the decay is defined in terms of "Sections"
+     *
+     *  For some decays useful shortcuts could be created:
+     *  @code
+     *
+     *   // " B0 -> pi+ pi- "
+     *
+     *   using namespace Decays ;
+     *
+     *   Trees::GenExclusive decay ( "B0" ) ;
+     *   decay += "pi+" ;
+     *   decay += "pi-" ;
+     *
+     *  @endcode
+     *  Or
+     *  @code
+     *
+     *   // " [B0]os --> pi+ pi- pi0"
+     *
+     *   using namespace Decays ;
+     *
+     *   Trees::GenExclusive decay ( "B0"              ,
+     *                               Trees::Sections   ,
+     *                               Trees::Oscilalted ) ;
+     *   decay += "pi+" ;
+     *   decay += "pi-" ;
+     *   decay += "pi0" ;
+     *
+     *  @endcode
+     *
+     *  @author Vanya BELYAEV Ivan.Belyaev@nikhef.nl
+     *  @date 2008-06-10
+     */
+    class GenExclusive : public Decays::iTree_<HepMC3::ConstGenParticlePtr> {
+    protected:
+      // ======================================================================
+      typedef HepMC3::ConstGenParticlePtr       PARTICLE;
+      typedef Decays::Trees::Types_<PARTICLE> Types;
+      // ======================================================================
+    public:
+      // ======================================================================
+      /// the actual type of the container of children trees
+      typedef Types::TreeList TreeList;
+      // ======================================================================
+    public:
+      // ======================================================================
+      /** full constructor from the node (mother), subtrees & flags
+       *  @param mother the mother node
+       *  @param children the list of daughter substrees
+       *  @param alg the matching algorithm
+       *  @param oscillation check the oscilaltion flag
+       */
+      GenExclusive( const Decays::iNode& mother, const TreeList& children, const Alg alg = Daughters,
+                    const Oscillation oscillation = Undefined );
+      /** constructor from the node (mother) & flags
+       *  @param mother the mother node
+       *  @param alg the matching algorithm
+       *  @param oscillation check the oscillation flag
+       */
+      GenExclusive( const Decays::iNode& mother, const Alg alg = Daughters, const Oscillation oscillation = Undefined );
+      /** constructor from the node (mother) & flags
+       *  @param oscillation check the oscillation flag
+       *  @param mother the mother node
+       */
+      GenExclusive( const Oscillation oscillation, const Decays::iNode& mother );
+      /** constructor from the decay & flags
+       *  @param decay the decay
+       *  @param alg the matching algorithm
+       *  @param oscillation check the oscillation flag
+       */
+      GenExclusive( const Decays::Decay& decay, const Alg alg = Daughters, const Oscillation oscillation = Undefined );
+      // ======================================================================
+    public:
+      // ======================================================================
+      /// MANDATORY: clone method ("virtual constructor")
+      GenExclusive* clone() const override { return new GenExclusive( *this ); }
+      /// MANDATORY: the only one essential method:
+      bool operator()( Decays::iTree_<PARTICLE>::argument p ) const override;
+      /// MANDATORY: check the validity
+      bool valid() const override;
+      /// MANDATORY: validate the tree
+      StatusCode validate( const LHCb::IParticlePropertySvc* svc ) const override;
+      /// MANDATORY: reset the tree
+      void reset() const override;
+      /// collect the marked elements
+      size_t collect( Decays::iTree_<PARTICLE>::Collection& output ) const override;
+      /// MANDATORY: the specific printout
+      std::ostream& fillStream( std::ostream& s ) const override;
+      /// has marked elements  in the tree?
+      bool marked() const override;
+      // ======================================================================
+    private:
+      // ======================================================================
+      /// MANDATORY: implementation of operator()
+      virtual bool p_match( Decays::iTree_<PARTICLE>::argument p ) const;
+      // ======================================================================
+    protected:
+      // ======================================================================
+      /** check the validness & mother & oscillation
+       *  @param p particle to be checked
+       *  @return oscilalted or not
+       */
+      HepMC3::ConstGenParticlePtr ok( const HepMC3::ConstGenParticlePtr & p ) const;
+      // ======================================================================
+    public:
+      // ======================================================================
+      /// get the algorithm
+      Alg         alg() const { return m_alg; }
+      Oscillation oscillation() const { return m_oscillation; }
+      // ======================================================================
+    public:
+      // ======================================================================
+      /// get the algorithm
+      void setAlg( Alg value ) { m_alg = value; }
+      void setOscillation( Oscillation value ) { m_oscillation = value; }
+      // ======================================================================
+    public:
+      // ======================================================================
+      /// set children
+      void setChildren( const TreeList& children ) { m_children = children; }
+      /// set children
+      void setChildren( const std::vector<std::string>& chidlren );
+      /// set children
+      void setChildren( const std::vector<Decays::Decay::Item>& chidlren );
+      /// set children
+      void setChildren( const std::vector<LHCb::ParticleID>& children );
+      /// set children
+      void setChildren( const std::vector<const LHCb::ParticleProperty*>& children );
+      // ======================================================================
+    public:
+      // ======================================================================
+      /// add one more daughter to the decay
+      void addDaughter( const Decays::iTree_<PARTICLE>& tree );
+      /// add one more daughter to the decay
+      void addDaughter( const Decays::iNode& node );
+      // ======================================================================
+      /// add one more daughter to the decay
+      void addDaughter( const std::string& node );
+      // ======================================================================
+      /// add one more daughter to the decay
+      void addDaughter( const LHCb::ParticleID& node );
+      // ======================================================================
+      /// add one more daughter to the decay
+      void addDaughter( const Decays::Decay::Item& node );
+      // ======================================================================
+      /// add one more daughter to the decay
+      void addDaughter( const LHCb::ParticleProperty* node );
+      // ======================================================================
+    public:
+      // ======================================================================
+      /// add one more node to the tree
+      GenExclusive& operator+=( const Decays::iTree_<PARTICLE>& node ) {
+        addDaughter( node );
+        return *this;
+      }
+      /// add one more node to the tree
+      GenExclusive& operator+=( const Decays::iNode& node ) {
+        addDaughter( node );
+        return *this;
+      }
+      // ======================================================================
+      /// add one more node to the tree
+      GenExclusive& operator+=( const std::string& node ) {
+        addDaughter( node );
+        return *this;
+      }
+      // ======================================================================
+      /// add one more node to the tree
+      GenExclusive& operator+=( const LHCb::ParticleID& node ) {
+        addDaughter( node );
+        return *this;
+      }
+      // ======================================================================
+      /// add one more node to the tree
+      GenExclusive& operator+=( const Decays::Decay::Item& node ) {
+        addDaughter( node );
+        return *this;
+      }
+      // ======================================================================
+      /// add one more node to the tree
+      GenExclusive& operator+=( const LHCb::ParticleProperty* node ) {
+        addDaughter( node );
+        return *this;
+      }
+      // ======================================================================
+    protected:
+      // ======================================================================
+      inline const TreeList& children() const { return m_children; }
+      // ======================================================================
+      TreeList::const_iterator childBegin() const { return m_children.begin(); }
+      TreeList::const_iterator childEnd() const { return m_children.end(); }
+      // ======================================================================
+      TreeList::const_reference front() const { return m_children.front(); }
+      TreeList::const_reference back() const { return m_children.back(); }
+      // ======================================================================
+      size_t nChildren() const { return m_children.size(); }
+      // ======================================================================
+      // reset the cache
+      inline void i_reset() const {
+        std::for_each( childBegin(), childEnd(), []( const _Tree_<PARTICLE>& t ) { t.reset(); } );
+      }
+      // ======================================================================
+      const Decays::iNode& mother() const { return m_mother; }
+      // ======================================================================
+      inline bool mother( const LHCb::ParticleID& pid ) const { return m_mother.node( pid ); }
+      // ======================================================================
+    private:
+      // ======================================================================
+      /// The mother
+      Decays::Node m_mother; //    the mother
+      /// The children
+      TreeList m_children; //  the children
+      /// The algorithm
+      Decays::Trees::Alg m_alg; // the algorithm
+      /// Oscillation flag
+      Decays::Trees::Oscillation m_oscillation; //   oscillation
+      // ======================================================================
+    };
+    // ========================================================================
+    /** @class GenInclusive
+     *  Simple sub tree which consists of the node ("mother") and
+     *  subtrees ("children"). Essentially it represent the
+     *  inclusive decays.
+     *
+     *  The inclusive decays are identified with ellipses: "..." ;
+     *
+     *  Define the simple regular decay, e.g.
+     *   \f$ B^0 \to \pi^+ \pi^- + ... \f$:
+     *  @code
+     *
+     *   // " B0 -> pi+ pi- ... "
+     *
+     *   using namespace Decays ;
+     *
+     *   typedef Trees::GenExclusive::SubTrees    Children ;
+     *
+     *   // define daughters:
+     *   Children children ;
+     *   children.push_back ( Trees::GenExclusive ( "pi+" ) ) ;
+     *   children.push_back ( Trees::GenExclusive ( "pi-" ) ) ;
+     *
+     *   Trees::GenInclusive decay
+     *             ( "B0"    ,     // the parent
+     *               chidren ) ;   // children
+     *
+     *  @endcode
+     *
+     *  Define the "decay-in-sections", e.g. all following
+     *  decays will be correctly matched with the descriptor
+     *  <c>" B0 --> pi+ pi- pi0 ... "</c>":
+     *    - \f$ B^0 \to \left( \rho^0 \to \pi^+ \pi^- \right)
+     *               \left( \pi^0  \to \gamma \gamma  \right) + ...         \f$
+     *    - \f$ B^0 \to \left( \rho^0 \to \pi^+ \pi^- + ... \right)
+     *               \left( \pi^0  \to \gamma \gamma  \right)               \f$
+     *    - \f$ B^0 \to \left( \rho^+ \to \pi^+ \pi^0 + ...  \right) \pi^-  \f$
+     *    - \f$ B^0 \to \left( \rho^+ \to \pi^+ \pi^0 \right) \pi^- + ...   \f$
+     *    - \f$ B^0 \to \left( \rho^- \to \pi^- \pi^0 + ... \right) \pi^+   \f$
+     *    - \f$ B^0 \to \left( \rho^- \to \pi^- \pi^0   \right) \pi^+ + ... \f$
+     *    - \f$ B^0 \to \pi^+ \pi^- \pi^0 + ... \f$
+     *
+     *  @code
+     *
+     *   // " B0 --> pi+ pi- pi0 ... "
+     *
+     *   using namespace Decays ;
+     *
+     *   typedef Trees::GenExclusive::TreeList    Children ;
+     *
+     *   // define daughters:
+     *   Children children ;
+     *   children.push_back ( Trees::GenExclusive ( "pi+" ) ) ;
+     *   children.push_back ( Trees::GenExclusive ( "pi-" ) ) ;
+     *   children.push_back ( Trees::GenExclusive ( "pi0" ) ) ;
+     *
+     *   Trees::GenInclusive decay
+     *             ( "B0"            ,   // parent
+     *               chidren         ,   // children
+     *               Trees::Sections ) ; // matching algorithm
+     *
+     *  @endcode
+     *
+     *  Define the "decay-with-oscillation". Here the mother particle
+     *  is required to oscillate before the decay, e.g.
+     *  \f$ B^0 \to \bar{B}^0 \to \pi^+ \pi^- + ... \f$:
+     *
+     *  @code
+     *
+     *   // " [B0]os -> pi+ pi- ... "
+     *
+     *   using namespace Decays ;
+     *
+     *   typedef Trees::GenExclusive::TreeList    Children ;
+     *
+     *   // define daughters:
+     *   Children children ;
+     *   children.push_back ( Trees::GenExclusive ( "pi+" ) ) ;
+     *   children.push_back ( Trees::GenExclusive ( "pi-" ) ) ;
+     *
+     *   Trees::GenInclusive decay
+     *             ( "B0"              ,   // parent
+     *               chidren           ,   // children
+     *               Trees::Daughetrs  ,   // matching algorithm
+     *               Trees::Oscillated ) ; // oscillation flag
+     *
+     *  @endcode
+     *
+     *  Define the "decay-without-oscillations":
+     *
+     *  @code
+     *
+     *   // " [B0]nos --> pi+ pi- pi0 ... "
+     *
+     *   using namespace Decays ;
+     *
+     *   typedef Trees::GenExclusive::TreeList    Children ;
+     *
+     *   // define daughters:
+     *   Children children ;
+     *   children.push_back ( Trees::GenExclusive ( "pi+" ) ) ;
+     *   children.push_back ( Trees::GenExclusive ( "pi-" ) ) ;
+     *   children.push_back ( Trees::GenExclusive ( "pi0" ) ) ;
+     *
+     *   Trees::GenInclusive decay
+     *             ( "B0"                 ,   // parent
+     *               chidren              ,   // children
+     *               Trees::Sections      ,   // matching algorithm
+     *               Trees::NotOscillated ) ; // oscillation flag
+     *
+     *  @endcode
+     *
+     *  The <c>algorithm</c> is defined by the length  of the arrow:
+     *
+     *    - <c> "->"</c> the decay is defined in terms of direct daughters
+     *    - <c>"-->"</c> the decay is defined in terms of "Sections"
+     *
+     *  It is rather convinient to create the inclusive decay
+     *  from the corresponding regular decay:
+     *
+     *  @code
+     *
+     *   using namespace Decays ;
+     *
+     *   const Trees::GenExclusive& regular = ... ;
+     *
+     *   const Trees::GenInclusive decay ( regular ) ;
+     *
+     *  @endcode
+     *
+     *  @author Vanya BELYAEV Ivan.Belyaev@nikhef.nl
+     *  @date 2008-06-10
+     */
+    class GenInclusive : public GenExclusive {
+    public:
+      // ====================================================================
+      /** full constructor from the node (mother), subtrees  & flags
+       *  @param mother the mother node
+       *  @param children the list of daughter substrees
+       *  @param alg the matching algorithm
+       *  @param osc  the oscilaltion flag
+       */
+      GenInclusive( const Decays::iNode& mother, const TreeList& children, const Alg alg = Daughters,
+                    const Oscillation osc = Undefined );
+      /** constructor from the node (mother), subtrees and "final" flag
+       *  @param mother the mother node
+       *  @param alg the matching algorithm
+       *  @param osc require the oscillation flag for mother
+       */
+      GenInclusive( const Decays::iNode& mother, const Alg alg = Daughters, const Oscillation osc = Undefined );
+      /** constructor from the decay & flags
+       *  @param decay the decay
+       *  @param alg the matching algorithm
+       *  @param oscillation check the oscillation flag
+       */
+      GenInclusive( const Decays::Decay& decay, const Alg alg = Daughters, const Oscillation oscillation = Undefined );
+      /** constructor from exclusive decay
+       *  @param mother the mother node
+       */
+      GenInclusive( const GenExclusive& right );
+      // ====================================================================
+    public:
+      // ====================================================================
+      /// MANDATORY: clone method ("virtual constructor")
+      GenInclusive* clone() const override { return new GenInclusive( *this ); }
+      /// MANDATORY: check the validity of the tree
+      bool valid() const override;
+      /// MANDATORY: the specific printout
+      std::ostream& fillStream( std::ostream& s ) const override;
+      // ====================================================================
+    private:
+      // ======================================================================
+      /// MANDATORY: implementation of operator()
+      bool p_match( Decays::iTree_<PARTICLE>::argument p ) const override;
+      // ======================================================================
+    public:
+      // ====================================================================
+      /// add one more node to the tree
+      GenInclusive& operator+=( const Decays::iTree_<PARTICLE>& node ) {
+        addDaughter( node );
+        return *this;
+      }
+      /// add one more node to the tree
+      GenInclusive& operator+=( const Decays::iNode& node ) {
+        addDaughter( node );
+        return *this;
+      }
+      /// add one more node to the tree
+      GenInclusive& operator+=( const std::string& node ) {
+        addDaughter( node );
+        return *this;
+      }
+      /// add one more node to the tree
+      GenInclusive& operator+=( const LHCb::ParticleID& node ) {
+        addDaughter( node );
+        return *this;
+      }
+      /// add one more node to the tree
+      GenInclusive& operator+=( const Decays::Decay::Item& node ) {
+        addDaughter( node );
+        return *this;
+      }
+      // ====================================================================
+      /// add one more node to the tree
+      GenInclusive& operator+=( const LHCb::ParticleProperty* node ) {
+        addDaughter( node );
+        return *this;
+      }
+      // ====================================================================
+    };
+    // ======================================================================
+    /** @class GenOptional
+     *  Simple sub tree which consists of the node ("mother") and
+     *  subtrees ("children") and optional nodes.
+     *  Essentially it represent the decays with "optional" particles.
+     *
+     *  Define the simple regular decay with optional components, e.g.
+     *     - \f$ B^0 \to \pi^+ \pi^-       \f$
+     *     - \f$ B^0 \to \pi^+ \pi^- \pi^0 \f$
+     *
+     *  @code
+     *
+     *   // " B0 -> pi+ pi-  { pi0 } "
+     *
+     *   using namespace Decays ;
+     *
+     *   typedef Trees::GenExclusive::TreeList    Children ;
+     *   typedef Trees::GenExclusive::TreeList    Optional ;
+     *
+     *   // define daughters:
+     *   Children children ;
+     *   children.push_back ( Trees::GenExclusive ( "pi+" ) ) ;
+     *   children.push_back ( Trees::GenExclusive ( "pi-" ) ) ;
+     *
+     *   // define optional
+     *   Optional optional ;
+     *   optional.push_back ( Trees::GenExclusive ( "pi0" ) ) ;
+     *
+     *   Trees::GenOptional decay
+     *             ( "B0"     ,     // the parent
+     *               chidren  ,     // children
+     *               optional ) ;   // optional
+     *
+     *  @endcode
+     *
+     *  The <c>algorithm</c> is defined by the length  of the arrow:
+     *
+     *    - <c> "->"</c> the decay is defined in terms of direct daughters
+     *    - <c>"-->"</c> the decay is defined in terms of "Sections"
+     *
+     *  The most convinient way to create the "optional" decay is from
+     *  the regular decay:
+     *
+     *  @code
+     *
+     *   using namespace Decays ;
+     *
+     *   typedef Trees::GenExclusive::TreeList  Optional ;
+     *
+     *   // define optional
+     *   Optional optional ;
+     *   optional.push_back ( Trees::GenExclusive ( "pi0" ) ) ;
+     *
+     *   const Trees::GenExclusive& regular = ... ;
+     *
+     *   Trees::GenOptional decay
+     *             ( regular  ,
+     *               optional ) ;   // optional
+     *
+     *  @endcode
+     *
+     *  @author Vanya BELYAEV Ivan.Belyaev@nikhef.nl
+     *  @date 2008-04-13
+     */
+    class GenOptional : public GenExclusive {
+    public:
+      // ====================================================================
+      /** full constructor from the node (mother) and subtrees
+       *  @param mother the mother node
+       *  @param children the list of children
+       *  @param optional the list of optional components
+       *  @param alg the matching algorithm
+       *  @param oscillation check the oscilaltion flag
+       */
+      GenOptional( const Decays::iNode& mother, const TreeList& children = TreeList(),
+                   const TreeList& optional = TreeList(), const Alg alg = Daughters,
+                   const Oscillation osc = Undefined );
+      // ====================================================================
+      /** constructor from decay descriptor, optional and flags
+       *  @param decay the decay descriptor
+       *  @param optional the list of optional components
+       *  @param alg the matching algorithm
+       *  @param oscillation check the oscilaltion flag
+       */
+      GenOptional( const Decays::Decay& decay, const TreeList& optional = TreeList(), const Alg alg = Daughters,
+                   const Oscillation oscillated = Undefined );
+      /// constructor  from GenExclusive & optional stuff
+      GenOptional( const GenExclusive& right, const TreeList& optional = TreeList() );
+      // ====================================================================
+    public:
+      // ====================================================================
+      /// MANDATORY: clone method ("virtual constructor")
+      GenOptional* clone() const override { return new GenOptional( *this ); }
+      /// MANDATORY: check the validity of the tree
+      bool valid() const override;
+      /// MANDATORY: the specific printout
+      std::ostream& fillStream( std::ostream& s ) const override;
+      /// MANDATORY: the proper validation of the tree
+      StatusCode validate( const LHCb::IParticlePropertySvc* svc ) const override;
+      /// has marked elements  in the tree?
+      bool marked() const override;
+      // ====================================================================
+    private:
+      // ======================================================================
+      /// MANDATORY: implementation of operator()
+      bool p_match( Decays::iTree_<PARTICLE>::argument p ) const override;
+      // ======================================================================
+    public:
+      // ====================================================================
+      /// set optional
+      void setOptional( const TreeList& optional ) { m_optional = optional; }
+      /// set optional
+      void setOptional( const std::vector<std::string>& chidlren );
+      /// set children
+      void setOptional( const std::vector<Decays::Decay::Item>& chidlren );
+      /// set optional
+      void setOptional( const std::vector<LHCb::ParticleID>& children );
+      /// set optional
+      void setOptional( const std::vector<const LHCb::ParticleProperty*>& children );
+      // ====================================================================
+    public:
+      // ====================================================================
+      /// add one more daughter to the decay
+      void addOptional( const Decays::iTree_<PARTICLE>& tree );
+      /// add one more daughter to the decay
+      void addOptional( const Decays::iNode& node );
+      /// add one more daughter to the decay
+      void addOptional( const std::string& node );
+      /// add one more daughter to the decay
+      void addOptional( const LHCb::ParticleID& node );
+      /// add one more daughter to the decay
+      void addOptional( const Decays::Decay::Item& node );
+      /// add one more daughter to the decay
+      void addOptional( const LHCb::ParticleProperty* node );
+      // ====================================================================
+    public:
+      // ====================================================================
+      /// add one more node to the tree
+      GenOptional& operator+=( const Decays::iTree_<PARTICLE>& node ) {
+        addDaughter( node );
+        return *this;
+      }
+      /// add one more node to the tree
+      GenOptional& operator+=( const Decays::iNode& node ) {
+        addDaughter( node );
+        return *this;
+      }
+      /// add one more node to the tree
+      GenOptional& operator+=( const std::string& node ) {
+        addDaughter( node );
+        return *this;
+      }
+      /// add one more node to the tree
+      GenOptional& operator+=( const LHCb::ParticleID& node ) {
+        addDaughter( node );
+        return *this;
+      }
+      /// add one more node to the tree
+      GenOptional& operator+=( const Decays::Decay::Item& node ) {
+        addDaughter( node );
+        return *this;
+      }
+      /// add one more node to the tree
+      GenOptional& operator+=( const LHCb::ParticleProperty* node ) {
+        addDaughter( node );
+        return *this;
+      }
+      // ======================================================================
+    protected:
+      // ======================================================================
+      TreeList::const_iterator optBegin() const { return m_optional.begin(); }
+      TreeList::const_iterator optEnd() const { return m_optional.end(); }
+      size_t                   optSize() const { return m_optional.size(); }
+      size_t                   nOptional() const { return optSize(); }
+      // ======================================================================
+    private:
+      // ======================================================================
+      /// the optional particles in the tree
+      TreeList m_optional; // the optional particles in the tree
+      // ======================================================================
+    };
+    // ========================================================================
+    /** @class GenPhotos
+     *  Simple sub-tree which can contains an undefined number of "photons"
+     *
+     *
+     *  Define the decay with undefined number of photons, e.g.
+     *  \f$ B^0 \to \pi^+ \pi^- n\gamma \f$:
+     *  @code
+     *
+     *   // " B0 => pi+ pi- "
+     *
+     *   using namespace Decays ;
+     *
+     *   typedef Trees::GenExclusive::SubTrees    Children ;
+     *
+     *   // define daughters:
+     *   Children children ;
+     *   children.push_back ( Trees::GenExclusive ( "pi+" ) ) ;
+     *   children.push_back ( Trees::GenExclusive ( "pi-" ) ) ;
+     *
+     *   Trees::GenPhotos decay
+     *             ( "B0"    ,     // the parent
+     *               chidren ) ;   // children
+     *
+     *  @endcode
+     *
+     *  The <c>algorithm</c> is defined by the length  of the arrow:
+     *
+     *    - <c> "=>"</c> the decay is defined in terms of direct daughters
+     *    - <c>"==>"</c> the decay is defined in terms of "Sections"
+     *
+     *  The most convinient way to create the Photos-aware decay
+     *  is from the regular one:
+     *
+     *  @code
+     *
+     *   using namespace Decays ;
+     *
+     *   const Trees::GenExclusive& regular = ... ;
+     *
+     *   const Trees::GenPhotons decay ( regular ) ;
+     *
+     *  @endcode
+     *
+     *  @author Vanya BELYAEV Ivan.Belyaev@nikhef.nl
+     *  @date 2008-04-21
+     */
+    class GenPhotos : public GenExclusive {
+    public:
+      // ======================================================================
+      /** full constructor from the node (mother) and subtrees
+       *  @param mother the mother node
+       *  @param children the list of children
+       *  @param alg the matching algorithm
+       *  @param oscillation check the oscilaltion flag
+       */
+      GenPhotos( const Decays::iNode& mother, const TreeList& children = TreeList(),
+                 const Decays::Trees::Alg alg = Daughters, const Oscillation oscillation = Undefined );
+      /** constructor from the decay descriptor and flags
+       *  @param decay the decay descriptor
+       *  @param alg the matching algorithm
+       *  @param oscillation check the oscilaltion flag
+       */
+      GenPhotos( const Decays::Decay& decay, const Decays::Trees::Alg alg = Daughters,
+                 const Oscillation oscillated = Undefined );
+      /// constructor from GenExclusive
+      GenPhotos( const GenExclusive& right );
+      // ======================================================================
+    public:
+      // ======================================================================
+      /// MANDATORY: clone method ("virtual constructor")
+      GenPhotos* clone() const override { return new GenPhotos( *this ); }
+      /// MANDATORY: check the validness
+      bool valid() const override { return m_photon.valid() && GenExclusive::valid(); }
+      /// MANDATORY: the proper validation of the tree
+      StatusCode validate( const LHCb::IParticlePropertySvc* svc ) const override;
+      /// MANDATORY: the specific printout
+      std::ostream& fillStream( std::ostream& s ) const override;
+      // ======================================================================
+    private:
+      // ======================================================================
+      /// MANDATORY: implementation of operator()
+      bool p_match( Decays::iTree_<PARTICLE>::argument p ) const override;
+      // ======================================================================
+    public:
+      // ======================================================================
+      /// add one more node to the tree
+      GenPhotos& operator+=( const Decays::iTree_<PARTICLE>& node ) {
+        addDaughter( node );
+        return *this;
+      }
+      /// add one more node to the tree
+      GenPhotos& operator+=( const Decays::iNode& node ) {
+        addDaughter( node );
+        return *this;
+      }
+      /// add one more node to the tree
+      GenPhotos& operator+=( const std::string& node ) {
+        addDaughter( node );
+        return *this;
+      }
+      /// add one more node to the tree
+      GenPhotos& operator+=( const LHCb::ParticleID& node ) {
+        addDaughter( node );
+        return *this;
+      }
+      /// add one more node to the tree
+      GenPhotos& operator+=( const Decays::Decay::Item& node ) {
+        addDaughter( node );
+        return *this;
+      }
+      /// add one more node to the tree
+      GenPhotos& operator+=( const LHCb::ParticleProperty* node ) {
+        addDaughter( node );
+        return *this;
+      }
+      // ======================================================================
+    private:
+      // ======================================================================
+      /// the photon subtree/node ("photon")
+      Decays::Nodes::Pid m_photon; // the sub-trees
+      // ======================================================================
+    };
+    // ========================================================================
+    /** @class GenPhotosOptional
+     *  Simple sub tree which consists of the node ("mother") and
+     *  subtrees ("children") and optional nodes. Essentially it represent the
+     *  decays with optional particles
+     *
+     *  The <c>algorithm</c> is defined by the length  of the arrow:
+     *
+     *    - <c> "=>"</c> the decay is defined in terms of direct daughters
+     *    - <c>"==>"</c> the decay is defined in terms of "Sections"
+     *
+     *  The most convinient way to define "photos-aware" decay with the
+     *  optional components if from the regular decay woth otional
+     *  components:
+     *
+     *  @code
+     *
+     *   using namespace Decays ;
+     *
+     *   const Trees::GenOptional& regular = ... ;
+     *
+     *   const Trees::GenPhotonsOptional decay ( regular ) ;
+     *
+     *  @endcode
+     *
+     *  @author Vanya BELYAEV Ivan.Belyaev@nikhef.nl
+     *  @date 2008-06-10
+     */
+    class GenPhotosOptional : public GenOptional {
+    public:
+      // ======================================================================
+      /** full constructor from the node (mother) and subtrees
+       *  @param mother the mother node
+       *  @param children the list of children
+       *  @param optional the list of optional components
+       *  @param alg the matching algorithm
+       *  @param oscillation check the oscilaltion flag
+       */
+      GenPhotosOptional( const Decays::iNode& mother, const TreeList& children = TreeList(),
+                         const TreeList& optional = TreeList(), const Alg alg = Daughters,
+                         const Oscillation osc = Undefined );
+      /** constructor from decay descriptor, optional and flags
+       *  @param decay the decay descriptor
+       *  @param optional the list of optional components
+       *  @param alg the matching algorithm
+       *  @param oscillation check the oscilaltion flag
+       */
+      GenPhotosOptional( const Decays::Decay& decay, const TreeList& optional = TreeList(), const Alg alg = Daughters,
+                         const Oscillation oscillated = Undefined );
+      /// constructor from GenOptional
+      GenPhotosOptional( const GenOptional& right );
+      /// constructor from GenExclusive & optional stuff
+      GenPhotosOptional( const GenExclusive& right, const TreeList& optional = TreeList() );
+      // ======================================================================
+    public:
+      // ======================================================================
+      /// MANDATORY: clone method ("virtual constructor")
+      GenPhotosOptional* clone() const override { return new GenPhotosOptional( *this ); }
+      /// MANDATORY: the specific printout
+      std::ostream& fillStream( std::ostream& s ) const override;
+      // ======================================================================
+      /// MANDATORY: check the validness
+      bool valid() const override;
+      /// MANDATORY: the proper validation of the tree
+      StatusCode validate( const LHCb::IParticlePropertySvc* svc ) const override;
+      // ======================================================================
+    private:
+      // ======================================================================
+      /// MANDATORY: implementation of operator()
+      bool p_match( Decays::iTree_<PARTICLE>::argument p ) const override;
+      // ======================================================================
+    public:
+      // ======================================================================
+      /// add one more node to the tree
+      GenPhotosOptional& operator+=( const Decays::iTree_<PARTICLE>& node ) {
+        addDaughter( node );
+        return *this;
+      }
+      /// add one more node to the tree
+      GenPhotosOptional& operator+=( const Decays::iNode& node ) {
+        addDaughter( node );
+        return *this;
+      }
+      /// add one more node to the tree
+      GenPhotosOptional& operator+=( const std::string& node ) {
+        addDaughter( node );
+        return *this;
+      }
+      /// add one more node to the tree
+      GenPhotosOptional& operator+=( const LHCb::ParticleID& node ) {
+        addDaughter( node );
+        return *this;
+      }
+      /// add one more node to the tree
+      GenPhotosOptional& operator+=( const Decays::Decay::Item& node ) {
+        addDaughter( node );
+        return *this;
+      }
+      /// add one more node to the tree
+      GenPhotosOptional& operator+=( const LHCb::ParticleProperty* node ) {
+        addDaughter( node );
+        return *this;
+      }
+      // ======================================================================
+    private:
+      // ======================================================================
+      /// the photon subtree/node ("photon")
+      Decays::Nodes::Pid m_photon; // the sub-trees
+      // ======================================================================
+    };
+    // ========================================================================
+    // treat properly the stable trees
+    // ========================================================================
+    template <>
+    bool Stable_<HepMC3::ConstGenParticlePtr>::operator()( Decays::iTree_<HepMC3::ConstGenParticlePtr>::argument p ) const;
+    // ========================================================================
+  } // namespace Trees
+  // ==========================================================================
+} //                                                    end of namespace Decays
+// ============================================================================
+
+// ============================================================================
+// The END
+// ============================================================================
+#endif // LOKI_GENDECAYS_H
diff --git a/Gen/LoKiGen/LoKi/GenDump.h b/Gen/LoKiGen/LoKi/GenDump.h
new file mode 100644
index 000000000..c86def0f4
--- /dev/null
+++ b/Gen/LoKiGen/LoKi/GenDump.h
@@ -0,0 +1,73 @@
+/*****************************************************************************\
+* (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration      *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                             *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+// ============================================================================
+#ifndef LOKI_GENDUMP_H
+#define LOKI_GENDUMP_H 1
+// ============================================================================
+// Include files
+// ============================================================================
+// LoKi
+// ============================================================================
+#include "LoKi/Dumper.h"
+#include "LoKi/Filters.h"
+#include "LoKi/GenTypes.h"
+// ============================================================================
+/** @file
+ *
+ *  This file is a part of LoKi project -
+ *    "C++ ToolKit  for Smart and Friendly Physics Analysis"
+ *
+ *  The package has been designed with the kind help from
+ *  Galina PAKHLOVA and Sergey BARSUK.  Many bright ideas,
+ *  contributions and advices from G.Raven, J.van Tilburg,
+ *  A.Golutvin, P.Koppenburg have been used in the design.
+ *
+ *  @author Vanya Belyaev Ivan.Belyaev@cern.ch
+ *  @date   2011-06-03
+ *
+ */
+// ============================================================================
+namespace LoKi {
+  // ==========================================================================
+  namespace Functors {
+    // ========================================================================
+    /** template specialization of ``dumpers''
+     *  @see LoKi::Functors::Dump_
+     *  @author Vanya Belyaev Ivan.Belyaev@cern.ch
+     *  @date   2011-06-03
+     */
+    template <>
+    std::vector<HepMC3::ConstGenParticlePtr> Dump_<HepMC3::ConstGenParticlePtr>::
+                                           operator()( const std::vector<HepMC3::ConstGenParticlePtr>& a ) const;
+    // ========================================================================
+    /** template specialization of ``dumpers''
+     *  @see LoKi::Functors::Dump1_
+     *  @author Vanya Belyaev Ivan.Belyaev@itep.ru
+     *  @date   2012-01-28
+     */
+    template <>
+    bool Dump1_<HepMC3::ConstGenParticlePtr, bool>::operator()( const HepMC3::ConstGenParticlePtr & a ) const;
+    // ========================================================================
+    /** template specialization of ``dumpers''
+     *  @see LoKi::Functors::Dump1_
+     *  @author Vanya Belyaev Ivan.Belyaev@itep.ru
+     *  @date   2012-01-28
+     */
+    template <>
+    double Dump1_<HepMC3::ConstGenParticlePtr, double>::operator()( const HepMC3::ConstGenParticlePtr & a ) const;
+    // ========================================================================
+  } // namespace Functors
+  // ==========================================================================
+} //                                                      end of namespace LoKi
+// ============================================================================
+//                                                                      The END
+// ============================================================================
+#endif // LOKI_GENDUMP_H
diff --git a/Gen/LoKiGen/LoKi/GenExtract.h b/Gen/LoKiGen/LoKi/GenExtract.h
new file mode 100644
index 000000000..4cd47f03d
--- /dev/null
+++ b/Gen/LoKiGen/LoKi/GenExtract.h
@@ -0,0 +1,268 @@
+/*****************************************************************************\
+* (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration      *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                             *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+// ============================================================================
+#ifndef LOKI_GENEXTRACT_H
+#define LOKI_GENEXTRACT_H 1
+// ============================================================================
+// Include files
+// ============================================================================
+// GaudiKernel
+// ============================================================================
+#include "GaudiKernel/StatusCode.h"
+// ============================================================================
+// HepMC3
+// ============================================================================
+#include "HepMC3/GenEvent.h"
+#include "HepMC3/GenParticle.h"
+#include "HepMC3/GenVertex.h"
+#include "HepMC3/Relatives.h"
+#include "LoKi/GenTypes.h"
+// ============================================================================
+#include <algorithm>
+// ============================================================================
+/** @file
+ *
+ *  Collection of useful function to extract the information from  HepMC3
+ *
+ *  This file is a part of LoKi project -
+ *    "C++ ToolKit  for Smart and Friendly Physics Analysis"
+ *
+ *  The package has been designed with the kind help from
+ *  Galina PAKHLOVA and Sergey BARSUK.  Many bright ideas,
+ *  contributions and advices from G.Raven, J.van Tilburg,
+ *  A.Golutvin, P.Koppenburg have been used in the design.
+ *
+ *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+ *  @date 2001-01-23
+ *
+ */
+// ============================================================================
+namespace LoKi {
+  // ==========================================================================
+  namespace Extract {
+    // ========================================================================
+    /** simple function which allows to extract a certain
+     *  particles from HepMC3 vertex
+     *
+     *  @see HepMC3::GenParticle
+     *  @see HepMC3::GenVertex
+     *
+     *  @author Vanya BELYAEV belyaev@lapp.in2p3.fr
+     *  @date   2005-03-26
+     */
+    template <class OUTPUT, class PREDICATE>
+    inline OUTPUT genParticles( const HepMC3::ConstGenVertexPtr & vertex, const HepMC3::Relatives & range, OUTPUT output,
+                                const PREDICATE& predicate );
+    // ========================================================================
+    /** simple function which allows to extract a certain
+     *  particles from HepMC3 vertex
+     *
+     *  @see HepMC3::GenParticle
+     *  @see HepMC3::GenVertex
+     *
+     *  @author Vanya BELYAEV belyaev@lapp.in2p3.fr
+     *  @date   2005-03-26
+     */
+    template <class OUTPUT, class PREDICATE>
+    inline OUTPUT genParticles( const HepMC3::ConstGenParticlePtr & particle, OUTPUT output, const PREDICATE& predicate );
+    // ========================================================================
+    /** simple function which allow to extract a certain
+     *  particles from HepMC3 graph.
+     *
+     *  @see LoKi::Cuts::GABSID
+     *  @see LoKi::Cuts::GNINTREE
+     *  @see HepMC3::GenEvent
+     *
+     *  @author Vanya BELYAEV belyaev@lapp.in2p3.fr
+     *  @date   2005-03-26
+     */
+    template <class INPUT, class OUTPUT, class PREDICATE>
+    inline OUTPUT getGenParticles( INPUT first, INPUT last, OUTPUT output, const PREDICATE& predicate );
+    // ========================================================================
+    /** Simple function which allow to extract a certain
+     *  particles from HepMC3 graph.
+     *
+     *  e.g. one can get all  b(and anti-b)quarks from
+     *  Higgs decay
+     *
+     *  @code
+     *
+     *  const HepMC3::GenEvent* event = ... ;
+     *
+     *  SEQUENCE bquarks ;
+     *  LoKi::Extract::getGenParticles
+     *     ( event                          ,
+     *       std::back_inserter( bquarks )  ,
+     *       ( "b" == GABSID ) &&
+     *       0 != GNINTREE( "H_10" == GABSID , HepMC3::parents ) ) ;
+     *
+     *  @endcode
+     *
+     *  @see LoKi::Cuts::GABSID
+     *  @see LoKi::Cuts::GNINTREE
+     *  @see HepMC3::GenEvent
+     *
+     *  @author Vanya BELYAEV belyaev@lapp.in2p3.fr
+     *  @date   2005-03-26
+     */
+    template <class OUTPUT, class PREDICATE>
+    inline OUTPUT getGenParticles( const HepMC3::GenEvent* event, OUTPUT output, const PREDICATE& predicate ) {
+      if ( 0 == event ) { return output; }
+      for ( auto & p : event->particles() ) {
+        if ( !LoKi::GenTypes::_ptr_wrap(predicate)( p ) ) { continue; } // CONTINUE
+        //
+        const HepMC3::ConstGenParticlePtr particle = p;
+        *output                            = particle;
+        ++output; // NB!
+        //
+      }
+      return output;
+    }
+    // ========================================================================
+    /** simple function which allows to extract a certain
+     *  particles from HepMC3 vertex
+     *
+     *  @see HepMC3::GenParticle
+     *  @see HepMC3::GenVertex
+     *
+     *  @author Vanya BELYAEV belyaev@lapp.in2p3.fr
+     *  @date   2005-03-26
+     */
+    template <class OUTPUT, class PREDICATE>
+    inline OUTPUT getGenParticles( const HepMC3::ConstGenVertexPtr & vertex, const HepMC3::Relatives & range, OUTPUT output,
+                                   const PREDICATE& predicate ) {
+      if ( !vertex ) { return output; } // RETURN
+      //
+      auto particles = range(vertex);
+      auto wrapped_predicate = LoKi::GenTypes::_ptr_wrap(predicate);
+      return std::copy_if( std::begin(particles), std::end(particles), output, wrapped_predicate );
+
+    }
+    // ========================================================================
+    /** simple function which allows to extract a certain
+     *  particles from HepMC3 particle tree
+     *
+     *  @see HepMC3::GenParticle
+     *  @see HepMC3::GenVertex
+     *
+     *  @author Vanya BELYAEV belyaev@lapp.in2p3.fr
+     *  @date   2005-03-26
+     */
+    template <class OUTPUT, class PREDICATE>
+    inline OUTPUT getGenParticles( const HepMC3::ConstGenParticlePtr & particle, OUTPUT output, const PREDICATE& predicate ) {
+      if ( particle ) {
+        output = genParticles( particle->end_vertex(), HepMC3::Relatives::DESCENDANTS, output, predicate ); // RECURSION
+      }
+      /// check the particle
+      if ( predicate( particle ) ) {
+        *output = particle;
+        ++output; // NB!
+      }
+      return output; // RETURN
+    }
+    // ========================================================================
+    /** simple function which allow to extract a certain
+     *  particles from HepMC3 graph.
+     *
+     *  @see LoKi::Cuts::GABSID
+     *  @see LoKi::Cuts::GNINTREE
+     *  @see HepMC3::GenEvent
+     *
+     *  @author Vanya BELYAEV belyaev@lapp.in2p3.fr
+     *  @date   2005-03-26
+     */
+    template <class INPUT, class OUTPUT, class PREDICATE>
+    inline OUTPUT getGenParticles( INPUT first, INPUT last, OUTPUT output, const PREDICATE& predicate ) {
+      for ( ; first != last; ++first ) { output = getGenParticles( *first, output, predicate ); }
+      return output;
+    }
+    // ========================================================================
+    /** simple function which allow to extract a certain
+     *  particles from HepMC3 graph.
+     *
+     *  e.g. one can get all  b(and anti-b)quarks from
+     *  Higgs decay
+     *
+     *  @code
+     *
+     *  const HepMC3::GenEvent* event = ... ;
+     *
+     *  SEQUENCE bquarks ;
+     *  LoKi::Extract::genParticles
+     *     ( event                          ,
+     *       std::back_inserter( bquarks )  ,
+     *       ( "b" == GABSID ) &&
+     *       0 != GNINTREE( "H_10" == GABSID , HepMC3::parents ) ) ;
+     *
+     *  @endcode
+     *
+     *  @see LoKi::Cuts::GABSID
+     *  @see LoKi::Cuts::GNINTREE
+     *  @see HepMC3::GenEvent
+     *
+     *  @author Vanya BELYAEV belyaev@lapp.in2p3.fr
+     *  @date   2005-03-26
+     */
+    template <class OUTPUT, class PREDICATE>
+    inline OUTPUT genParticles( const HepMC3::GenEvent* event, OUTPUT output, const PREDICATE& predicate ) {
+      return getGenParticles( event, output, predicate );
+    }
+    // ========================================================================
+    /** simple function which allows to extract a certain
+     *  particles from HepMC3 vertex
+     *
+     *  @see HepMC3::GenParticle
+     *  @see HepMC3::GenVertex
+     *
+     *  @author Vanya BELYAEV belyaev@lapp.in2p3.fr
+     *  @date   2005-03-26
+     */
+    template <class OUTPUT, class PREDICATE>
+    inline OUTPUT genParticles( const HepMC3::ConstGenVertexPtr & vertex, const HepMC3::Relatives & range, OUTPUT output,
+                                const PREDICATE& predicate ) {
+      return getGenParticles( vertex, range, output, predicate );
+    }
+    // ========================================================================
+    /** simple function which allows to extract a certain
+     *  particles from HepMC3 vertex
+     *
+     *  @see HepMC3::GenParticle
+     *  @see HepMC3::GenVertex
+     *
+     *  @author Vanya BELYAEV belyaev@lapp.in2p3.fr
+     *  @date   2005-03-26
+     */
+    template <class OUTPUT, class PREDICATE>
+    inline OUTPUT genParticles( const HepMC3::ConstGenParticlePtr & particle, OUTPUT output, const PREDICATE& predicate ) {
+      return getGenParticles( particle, output, predicate );
+    }
+    // ========================================================================
+    /** simple function which allow to extract a certain
+     *  particles from HepMC3 graph.
+     *
+     *  @see LoKi::Cuts::GABSID
+     *  @see LoKi::Cuts::GNINTREE
+     *  @see HepMC3::GenEvent
+     *
+     *  @author Vanya BELYAEV belyaev@lapp.in2p3.fr
+     *  @date   2005-03-26
+     */
+    template <class INPUT, class OUTPUT, class PREDICATE>
+    inline OUTPUT genParticles( INPUT first, INPUT last, OUTPUT output, const PREDICATE& predicate ) {
+      return getGenParticles( first, last, output, predicate );
+    }
+    // ========================================================================
+  } // namespace Extract
+} // end of namespace LoKi
+// ============================================================================
+// The END
+// ============================================================================
+#endif // LOKI_GENEXTRACT_H
diff --git a/Gen/LoKiGen/LoKi/GenExtractDicts.h b/Gen/LoKiGen/LoKi/GenExtractDicts.h
new file mode 100644
index 000000000..7c14a30ca
--- /dev/null
+++ b/Gen/LoKiGen/LoKi/GenExtractDicts.h
@@ -0,0 +1,48 @@
+/*****************************************************************************\
+* (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration      *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                             *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+// ============================================================================
+#ifndef LOKI_GENEXTRACTDICTS_H
+#define LOKI_GENEXTRACTDICTS_H 1
+// ============================================================================
+// Include files
+// ============================================================================
+// LoKi
+// ============================================================================
+#include "LoKi/GenExtract.h"
+#include "LoKi/GenTypes.h"
+// ============================================================================
+namespace LoKi {
+  namespace GenExtract {
+    // ======================================================================
+    /// extract the particles from the event
+    std::vector<HepMC3::ConstGenParticlePtr> genParticles( const HepMC3::GenEvent*       event,
+                                                         const LoKi::GenTypes::GCuts& cuts );
+    // ======================================================================
+    /// extract the particles from the vertex
+    std::vector<HepMC3::ConstGenParticlePtr> genParticles( const HepMC3::ConstGenVertexPtr &      veretx,
+                                                         const LoKi::GenTypes::GCuts& cuts,
+                                                         const HepMC3::Relatives & range = HepMC3::Relatives::DESCENDANTS);
+    // ======================================================================
+    /// extract the particles from the vertex
+    std::vector<HepMC3::ConstGenParticlePtr> genParticles( const HepMC3::ConstGenVertexPtr & veretx,
+                                                         const HepMC3::Relatives &    range = HepMC3::Relatives::DESCENDANTS);
+    // ======================================================================
+    /// extract the particles from the particle
+    std::vector<HepMC3::ConstGenParticlePtr> genParticles( const HepMC3::ConstGenParticlePtr &    particle,
+                                                         const LoKi::GenTypes::GCuts& cuts );
+    // ======================================================================
+  } // namespace GenExtract
+  // ==========================================================================
+} //                                                      end of namespace LoKi
+// ============================================================================
+// The END
+// ============================================================================
+#endif // LOKI_GENEXTRACTDICTS_H
diff --git a/Gen/LoKiGen/LoKi/GenHybridEngine.h b/Gen/LoKiGen/LoKi/GenHybridEngine.h
new file mode 100644
index 000000000..15229bc7e
--- /dev/null
+++ b/Gen/LoKiGen/LoKi/GenHybridEngine.h
@@ -0,0 +1,129 @@
+/*****************************************************************************\
+* (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration      *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                             *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+// ============================================================================
+#ifndef LOKI_GENHYBRIDENGINE_H
+#define LOKI_GENHYBRIDENGINE_H 1
+// ============================================================================
+// Include files
+// ============================================================================
+#include <string>
+// ============================================================================
+// LoKi
+// ============================================================================
+#include "LoKi/IGenHybridTool.h"
+// ============================================================================
+/** @file
+ *
+ *  This file is a part of LoKi project -
+ *    "C++ ToolKit  for Smart and Friendly Physics Analysis"
+ *
+ *  The package has been designed with the kind help from
+ *  Galina PAKHLOVA and Sergey BARSUK.  Many bright ideas,
+ *  contributions and advices from G.Raven, J.van Tilburg,
+ *  A.Golutvin, P.Koppenburg have been used in the design.
+ *
+ */
+// ============================================================================
+namespace LoKi {
+  // ==========================================================================
+  namespace Hybrid {
+    // ========================================================================
+    /** @class GenEngine GenHybridEngine.h LoKi/GenHybridEngine.h
+     *
+     *  Helper class forn implementation of Hybrid Tools
+     *
+     *  This file is a part of LoKi project -
+     *    "C++ ToolKit  for Smart and Friendly Physics Analysis"
+     *
+     *  The package has been designed with the kind help from
+     *  Galina PAKHLOVA and Sergey BARSUK.  Many bright ideas,
+     *  contributions and advices from G.Raven, J.van Tilburg,
+     *  A.Golutvin, P.Koppenburg have been used in the design.
+     *
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date   2004-06-30
+     */
+    class GenEngine final {
+    public:
+      // ======================================================================
+      /// constructor
+      GenEngine() = default;
+      // ======================================================================
+    public:
+      // ======================================================================
+      // predicates
+      // ======================================================================
+      /// add the cut
+      StatusCode process( const std::string& name, const LoKi::Types::GCuts& cut ) const;
+      /// add the cut
+      StatusCode process( const std::string& name, const LoKi::Types::GVCuts& cut ) const;
+      // ======================================================================
+    public:
+      // ======================================================================
+      // functions
+      // ======================================================================
+      /// add the function
+      StatusCode process( const std::string& name, const LoKi::Types::GFunc& func ) const;
+      /// add the function
+      StatusCode process( const std::string& name, const LoKi::Types::GVFunc& func ) const;
+      // ======================================================================
+    public:
+      // ======================================================================
+      // maps
+      // ======================================================================
+      /// add the map
+      StatusCode process( const std::string& name, const LoKi::Types::GMaps& func ) const;
+      /// add the map
+      StatusCode process( const std::string& name, const LoKi::Types::GVMaps& func ) const;
+      // ======================================================================
+    public:
+      // ======================================================================
+      // pipes
+      // ======================================================================
+      /// add the pipe
+      StatusCode process( const std::string& name, const LoKi::Types::GPipes& func ) const;
+      /// add the pipe
+      StatusCode process( const std::string& name, const LoKi::Types::GVPipes& func ) const;
+      // ======================================================================
+    public:
+      // ======================================================================
+      // fun-vals
+      // ======================================================================
+      /// add the fun-val
+      StatusCode process( const std::string& name, const LoKi::Types::GFunVals& func ) const;
+      /// add the fun-val
+      StatusCode process( const std::string& name, const LoKi::Types::GVFunVals& func ) const;
+      // ======================================================================
+    public:
+      // ======================================================================
+      // cut-vals
+      // ======================================================================
+      /// add the fun-val
+      StatusCode process( const std::string& name, const LoKi::Types::GCutVals& func ) const;
+      // ======================================================================
+    public:
+      // ======================================================================
+      // sources
+      // ======================================================================
+      /// add the source
+      StatusCode process( const std::string& name, const LoKi::Types::GSources& func ) const;
+      /// add the source
+      StatusCode process( const std::string& name, const LoKi::Types::GVSources& func ) const;
+      // ======================================================================
+    };
+    // ========================================================================
+  } // namespace Hybrid
+  // ==========================================================================
+} //                                                      end of namespace LoKi
+// ============================================================================
+//                                                                      The END
+// ============================================================================
+#endif // LOKI_CUTSHOLDERHELPER_H
diff --git a/Gen/LoKiGen/LoKi/GenHybridEngineActor.h b/Gen/LoKiGen/LoKi/GenHybridEngineActor.h
new file mode 100644
index 000000000..4428b5863
--- /dev/null
+++ b/Gen/LoKiGen/LoKi/GenHybridEngineActor.h
@@ -0,0 +1,165 @@
+/*****************************************************************************\
+* (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration      *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                             *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+// ===========================================================================
+#ifndef LOKI_GENCUTSHOLDER_H
+#define LOKI_GENCUTSHOLDER_H 1
+// ===========================================================================
+// Include files
+// ===========================================================================
+// STD&STL
+// ===========================================================================
+#include <stack>
+// ===========================================================================
+// LoKi
+// ===========================================================================
+#include "LoKi/Context.h"
+#include "LoKi/IGenHybridTool.h"
+#include "LoKi/Interface.h"
+// ===========================================================================
+/** @file
+ *
+ *  This file is a part of LoKi project -
+ *    "C++ ToolKit  for Smart and Friendly Physics Analysis"
+ *
+ *  The package has been designed with the kind help from
+ *  Galina PAKHLOVA and Sergey BARSUK.  Many bright ideas,
+ *  contributions and advices from G.Raven, J.van Tilburg,
+ *  A.Golutvin, P.Koppenburg have been used in the design.
+ *
+ */
+// ============================================================================
+namespace LoKi {
+  // ==========================================================================
+  namespace Hybrid {
+    // ========================================================================
+    /** @class GenEngineActor LoKi/GenHybridEngineActor.h
+     *
+     *  This file is a part of LoKi project -
+     *    "C++ ToolKit  for Smart and Friendly Physics Analysis"
+     *
+     *  The package has been designed with the kind help from
+     *  Galina PAKHLOVA and Sergey BARSUK.  Many bright ideas,
+     *  contributions and advices from G.Raven, J.van Tilburg,
+     *  A.Golutvin, P.Koppenburg have been used in the design.
+     *
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date   2004-06-29
+     */
+    class GenEngineActor {
+    public:
+      // ======================================================================
+      // get the static instance
+      static GenEngineActor& instance();
+      /// connect the hybrid tool for code translation
+      StatusCode connect( const LoKi::IGenHybridTool* factory, const LoKi::Context& context );
+      /// disconnect the tool
+      StatusCode disconnect( const LoKi::IGenHybridTool* factory );
+      // ======================================================================
+      /** get the current context
+       *  contex is valid only in between <code>connect/disconnect</code>
+       *  @return the current active context
+       */
+      const LoKi::Context* context() const;
+      // ======================================================================
+    public:
+      // ======================================================================
+      // predicates
+      // ======================================================================
+      /// propagate the cut to the tool
+      StatusCode process( const std::string& name, const LoKi::Types::GCuts& cut ) const;
+      /// propagate the cut to the tool
+      StatusCode process( const std::string& name, const LoKi::Types::GVCuts& cut ) const;
+      // ======================================================================
+    public:
+      // ======================================================================
+      // functions
+      // ======================================================================
+      /// propagate the function to the tool
+      StatusCode process( const std::string& name, const LoKi::Types::GFunc& func ) const;
+      /// propagate the function to the tool
+      StatusCode process( const std::string& name, const LoKi::Types::GVFunc& func ) const;
+      // ======================================================================
+    public:
+      // ======================================================================
+      // maps
+      // ======================================================================
+      /// propagate the map to the tool
+      StatusCode process( const std::string& name, const LoKi::Types::GMaps& func ) const;
+      /// propagate the map to the tool
+      StatusCode process( const std::string& name, const LoKi::Types::GVMaps& func ) const;
+      // ======================================================================
+    public:
+      // ======================================================================
+      // pipes
+      // ======================================================================
+      /// propagate the pipe to the tool
+      StatusCode process( const std::string& name, const LoKi::Types::GPipes& func ) const;
+      /// propagate the pipe to the tool
+      StatusCode process( const std::string& name, const LoKi::Types::GVPipes& func ) const;
+      // ======================================================================
+    public:
+      // ======================================================================
+      // fun-vals
+      // ======================================================================
+      /// propagate the fun-val to the tool
+      StatusCode process( const std::string& name, const LoKi::Types::GFunVals& func ) const;
+      /// propagate the fun-val to the tool
+      StatusCode process( const std::string& name, const LoKi::Types::GVFunVals& func ) const;
+      // ======================================================================
+    public:
+      // ======================================================================
+      // cut-vals
+      // ======================================================================
+      /// propagate the fun-val to the tool
+      StatusCode process( const std::string& name, const LoKi::Types::GCutVals& func ) const;
+      // ======================================================================
+    public:
+      // ======================================================================
+      // sources
+      // ======================================================================
+      /// propagate the source to the tool
+      StatusCode process( const std::string& name, const LoKi::Types::GSources& func ) const;
+      /// propagate the source to the tool
+      StatusCode process( const std::string& name, const LoKi::Types::GVSources& func ) const;
+      // ======================================================================
+    protected:
+      // ======================================================================
+      /// Standard constructor
+      GenEngineActor() = default;
+      // ======================================================================
+    private:
+      // ======================================================================
+      /// just to save some lines
+      template <class TYPE>
+      inline StatusCode _add( const std::string& name, const TYPE& cut ) const;
+      // ======================================================================
+      // the copy contructor is disabled
+      GenEngineActor( const GenEngineActor& ) = delete;
+      // the assignement operator is disabled
+      GenEngineActor& operator=( const GenEngineActor& ) = delete;
+      // ======================================================================
+    private:
+      // ======================================================================
+      typedef LoKi::Interface<LoKi::IGenHybridTool> Tool;
+      typedef std::pair<Tool, LoKi::Context>        Entry;
+      typedef std::stack<Entry>                     Stack;
+      ///  the stack of active factories
+      Stack m_stack{}; // the stack of active factories
+      // ======================================================================
+    };
+    // ========================================================================
+  } // namespace Hybrid
+  // ==========================================================================
+} //                                                      end of namespace LoKi
+// ============================================================================
+//                                                                      The END
+// ============================================================================
+#endif // LOKI_MCCUTSHOLDER_H
diff --git a/Gen/LoKiGen/LoKi/GenHybridLock.h b/Gen/LoKiGen/LoKi/GenHybridLock.h
new file mode 100644
index 000000000..6d1138a17
--- /dev/null
+++ b/Gen/LoKiGen/LoKi/GenHybridLock.h
@@ -0,0 +1,73 @@
+/*****************************************************************************\
+* (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration      *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                             *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+// ============================================================================
+#ifndef LOKI_GENHYBRIDLOCK_H
+#define LOKI_GENHYBRIDLOCK_H 1
+// ============================================================================
+// Include files
+// ============================================================================
+// LoKi
+// ============================================================================
+#include "LoKi/Context.h"
+#include "LoKi/IGenHybridTool.h"
+#include "LoKi/Interface.h"
+// ============================================================================
+/** @file
+ *
+ *  This file is a part of LoKi project -
+ *    "C++ ToolKit  for Smart and Friendly Physics Analysis"
+ *
+ *  The package has been designed with the kind help from
+ *  Galina PAKHLOVA and Sergey BARSUK.  Many bright ideas,
+ *  contributions and advices from G.Raven, J.van Tilburg,
+ *  A.Golutvin, P.Koppenburg have been used in the design.
+ *
+ *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+ *  @date 2007-10-31
+ *
+ */
+namespace LoKi {
+  // ==========================================================================
+  namespace Hybrid {
+    // ========================================================================
+    /** @class GenLock  LoKi/GenHybridLock.h
+     *  Helper class (sentry) to connent IGenHybridTool to GenEngine
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date 2007-06-09
+     */
+    class GenLock final {
+    public:
+      // ======================================================================
+      /// constructor : Lock
+      GenLock( const IGenHybridTool* factory, // contructor : Lock
+               const LoKi::Context&  context );
+      /// destructor : UnLock
+      ~GenLock(); // destructor : UnLock
+      // ======================================================================
+      /// no copy constructor
+      GenLock( const GenLock& ) = delete; // no copy constructor
+      /// no assignement operator
+      GenLock& operator=( const GenLock& ) = delete; // no assignement operator
+      // ======================================================================
+    private:
+      // ======================================================================
+      /// the tool itself
+      LoKi::Interface<LoKi::IGenHybridTool> m_tool; // the tool itself
+      // ======================================================================
+    };
+    // ========================================================================
+  } // namespace Hybrid
+  // ==========================================================================
+} //                                                      end of namespace LoKi
+// ============================================================================
+// The END
+// ============================================================================
+#endif // LOKI_MCHYBRIDLOCK_H
diff --git a/Gen/LoKiGen/LoKi/GenKinematics.h b/Gen/LoKiGen/LoKi/GenKinematics.h
new file mode 100644
index 000000000..f1a16f042
--- /dev/null
+++ b/Gen/LoKiGen/LoKi/GenKinematics.h
@@ -0,0 +1,128 @@
+/*****************************************************************************\
+* (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration      *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                             *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+// ============================================================================
+#ifndef LOKI_GENKINEMATICS_H
+#define LOKI_GENKINEMATICS_H 1
+// ============================================================================
+// Include files
+// ============================================================================
+// LoKiCore
+// ============================================================================
+#include "LoKi/Kinematics.h"
+// ============================================================================
+// HepMC3
+// ============================================================================
+#ifdef __INTEL_COMPILER
+#  pragma warning( disable : 1572 ) // floating-point equality and inequality comparisons are unreliable
+#  pragma warning( push )
+#endif
+#include "HepMC3/GenParticle.h"
+#ifdef __INTEL_COMPILER
+#  pragma warning( pop )
+#endif
+/** @file
+ *
+ *  This file is a part of LoKi project -
+ *    "C++ ToolKit  for Smart and Friendly Physics Analysis"
+ *
+ *  The package has been designed with the kind help from
+ *  Galina PAKHLOVA and Sergey BARSUK.  Many bright ideas,
+ *  contributions and advices from G.Raven, J.van Tilburg,
+ *  A.Golutvin, P.Koppenburg have been used in the design.
+ *
+ *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+ *  @date 2001-01-23
+ */
+// ============================================================================
+namespace LoKi {
+  namespace GenKinematics {
+    // ========================================================================
+    /** The most trivial function.
+     *  It seems to be almost useless from the first sight, but
+     *  effectivel it is useful in conjunction with
+     *  algorithms, acting as "converter" of the particle
+     *  into the 4-momentum
+     *  @param p particle
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date 2006-02-08
+     */
+    inline LoKi::LorentzVector momentum( const HepMC3::ConstGenParticlePtr & p ) {
+      if ( 0 == p ) { return LoKi::LorentzVector(); }
+      return LoKi::LorentzVector( p->momentum() );
+    }
+    // ========================================================================
+    /** @struct Gen4Momentum
+     *  the simple object which acts as a converter of HepMC3::GenPartile
+     *  to LoKi::LorentzVector
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date 2006-02-08
+     */
+    struct Gen4Momentum {
+      LoKi::LorentzVector operator()( const HepMC3::ConstGenParticlePtr & p ) const { return momentum( p ); }
+    };
+    // ========================================================================
+    /** trivial function to evaluate the mass HepMC3::GenParticle
+     *  @param  p particle
+     *  @return invariant mass
+     *  @see HepMC3::GenParticle
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date 2006-01-17
+     */
+    double mass( const HepMC3::ConstGenParticlePtr & p );
+    // ========================================================================
+    /** trivial function to evaluate the mass HepMC3::GenParticle
+     *  @param  p1 the first particle
+     *  @param  p2 the second particle
+     *  @return invariant mass
+     *  @see HepMC3::GenParticle
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date 2006-01-17
+     */
+    double mass( const HepMC3::ConstGenParticlePtr & p1, HepMC3::ConstGenParticlePtr p2 );
+    // ========================================================================
+    /** trivial function to evaluate the mass HepMC3::GenParticle
+     *  @param  p1 the first particle
+     *  @param  p2 the third particle
+     *  @param  p3 the second particle
+     *  @return invariant mass
+     *  @see HepMC3::GenParticle
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date 2006-01-17
+     */
+    double mass( const HepMC3::ConstGenParticlePtr & p1, HepMC3::ConstGenParticlePtr p2, HepMC3::ConstGenParticlePtr p3 );
+    // ========================================================================
+    /** trivial function to evaluate the mass HepMC3::GenParticle
+     *  @param  p1 the first particle
+     *  @param  p2 the second particle
+     *  @param  p3 the third  particle
+     *  @param  p4 the fourth  particle
+     *  @return invariant mass
+     *  @see HepMC3::GenParticle
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date 2006-01-17
+     */
+    double mass( const HepMC3::ConstGenParticlePtr & p1, HepMC3::ConstGenParticlePtr p2, HepMC3::ConstGenParticlePtr p3,
+                 HepMC3::ConstGenParticlePtr p4 );
+    // ========================================================================
+  } // namespace GenKinematics
+  // ==========================================================================
+  namespace Kinematics {
+    // ========================================================================
+    // export the namespace into more general scope
+    using namespace LoKi::GenKinematics;
+    // ========================================================================
+  } // namespace Kinematics
+  // ==========================================================================
+} // end of namespace LoKi
+// ============================================================================
+// The END
+// ============================================================================
+#endif // LOKI_GENKINEMATICS_H
diff --git a/Gen/LoKiGen/LoKi/GenMoniDicts.h b/Gen/LoKiGen/LoKi/GenMoniDicts.h
new file mode 100644
index 000000000..13cb4c038
--- /dev/null
+++ b/Gen/LoKiGen/LoKi/GenMoniDicts.h
@@ -0,0 +1,32 @@
+/*****************************************************************************\
+* (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration      *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                             *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+// ============================================================================
+#ifndef LOKI_GENMONIDICTS_H
+#define LOKI_GENMONIDICTS_H 1
+// ============================================================================
+// Include files
+// ============================================================================
+// LoKi
+// ============================================================================
+#include "LoKi/GenTypes.h"
+// ============================================================================
+// forward declarations
+// ============================================================================
+class StatEntity;
+namespace AIDA {
+  class IHistogram1D;
+}
+// ============================================================================
+namespace LoKi {
+  namespace Dicts {} // namespace Dicts
+} // end of namespace LoKi
+// ============================================================================
+#endif // LOKI_GENMONIDICTS_H
diff --git a/Gen/LoKiGen/LoKi/GenOscillated.h b/Gen/LoKiGen/LoKi/GenOscillated.h
new file mode 100644
index 000000000..52ebaa6cd
--- /dev/null
+++ b/Gen/LoKiGen/LoKi/GenOscillated.h
@@ -0,0 +1,68 @@
+/*****************************************************************************\
+* (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration      *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                             *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+// ============================================================================
+#ifndef LOKI_GENOSCILLATED_H
+#define LOKI_GENOSCILLATED_H 1
+// ============================================================================
+// Include files
+// ============================================================================
+// GaudiKerne
+// ============================================================================
+#include "GaudiKernel/Kernel.h"
+#include "HepMC3/GenParticle_fwd.h"
+// ============================================================================
+namespace HepMC3 {
+  class GenParticle;
+}
+// ============================================================================
+/** @file
+ *
+ *  This file is a part of LoKi project -
+ *    "C++ ToolKit  for Smart and Friendly Physics Analysis"
+ *
+ *  The package has been designed with the kind help from
+ *  Galina PAKHLOVA and Sergey BARSUK.  Many bright ideas,
+ *  contributions and advices from G.Raven, J.van Tilburg,
+ *  A.Golutvin, P.Koppenburg have been used in the design.
+ *
+ *  @author Vanya BELYAEV Ivan.Belyaev@cern.ch
+ *
+ */
+// ===========================================================================
+namespace LoKi {
+  // ==========================================================================
+  namespace GenParticles {
+    // ========================================================================
+    /** check the oscillation for the particle
+     *  @param p the particle
+     *  @return the oscillated mother particle
+     *  @author Vanya BELYAEV  Ivan.Belyaev@nikhef.nl
+     *  @date 2008-06-03
+     */
+    GAUDI_API
+    const HepMC3::ConstGenParticlePtr oscillated1( const HepMC3::ConstGenParticlePtr & p );
+    // ========================================================================
+    /** check the oscillation for the particle
+     *  @param p the particle
+     *  @return the oscillated daughter particle
+     *  @author Vanya BELYAEV  Ivan.Belyaev@nikhef.nl
+     *  @date 2008-06-03
+     */
+    GAUDI_API
+    const HepMC3::ConstGenParticlePtr oscillated2( const HepMC3::ConstGenParticlePtr & p );
+    // ========================================================================
+  } // namespace GenParticles
+  // ==========================================================================
+} //                                                      end of namespace LoKi
+// ============================================================================
+//                                                                      The END
+// ============================================================================
+#endif // LOKI_GENOSCILLATED_H
diff --git a/Gen/LoKiGen/LoKi/GenPIDOperators.h b/Gen/LoKiGen/LoKi/GenPIDOperators.h
new file mode 100644
index 000000000..8daae67f3
--- /dev/null
+++ b/Gen/LoKiGen/LoKi/GenPIDOperators.h
@@ -0,0 +1,452 @@
+/*****************************************************************************\
+* (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration      *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                             *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+// ============================================================================
+#ifndef LOKI_GENPIDOPERATORS_H
+#define LOKI_GENPIDOPERATORS_H 1
+// ============================================================================
+// Include files
+// ============================================================================
+// LCbKernel
+// ============================================================================
+#include "Kernel/ParticleID.h"
+// ============================================================================
+// LoKi
+// ============================================================================
+#include "LoKi/GenParticles.h"
+#include "LoKi/Operators.h"
+// ============================================================================
+/** @file
+ *
+ *  This file is a part of LoKi project -
+ *    "C++ ToolKit  for Smart and Friendly Physics Analysis"
+ *
+ *  The package has been designed with the kind help from
+ *  Galina PAKHLOVA and Sergey BARSUK.  Many bright ideas,
+ *  contributions and advices from G.Raven, J.van Tilburg,
+ *  A.Golutvin, P.Koppenburg have been used in the design.
+ *
+ *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+ *  @date 2001-01-23
+ */
+// ============================================================================
+namespace LoKi {
+  // ==========================================================================
+  namespace GenParticles {
+    // ========================================================================
+    struct Identifier;
+    struct AbsIdentifier;
+    // ========================================================================
+
+    // ========================================================================
+    // ID ==
+    // ========================================================================
+    LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator==( const LoKi::GenParticles::Identifier& /* id  */, const LHCb::ParticleID& pid );
+    // ========================================================================
+    LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator==( const LoKi::GenParticles::Identifier& /* id */, const long pid );
+    // ========================================================================
+    LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator==( const LoKi::GenParticles::Identifier& /* id */, const unsigned long pid );
+    // ========================================================================
+    LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator==( const LoKi::GenParticles::Identifier& /* id */, const std::string& pid );
+    // ========================================================================
+    LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator==( const LoKi::GenParticles::Identifier& /* id  */, const std::vector<LHCb::ParticleID>& pid );
+    // ========================================================================
+    LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator==( const LoKi::GenParticles::Identifier& /* id */, const std::vector<int>& pid );
+    // ========================================================================
+    LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator==( const LoKi::GenParticles::Identifier& /* id */, const std::vector<unsigned int>& pid );
+    // ========================================================================
+    LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator==( const LoKi::GenParticles::Identifier& /* id */, const std::vector<long>& pid );
+    // ========================================================================
+    LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator==( const LoKi::GenParticles::Identifier& /* id */, const std::vector<unsigned long>& pid );
+    // ========================================================================
+    LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator==( const LoKi::GenParticles::Identifier& /* id */, const std::vector<std::string>& pid );
+    // ========================================================================
+
+    // ========================================================================
+    // ABSID ==
+    // ========================================================================
+    LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator==( const LoKi::GenParticles::AbsIdentifier& /* id  */, const LHCb::ParticleID& pid );
+    // ========================================================================
+    LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator==( const LoKi::GenParticles::AbsIdentifier& /* id */, const long pid );
+    // ========================================================================
+    LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator==( const LoKi::GenParticles::AbsIdentifier& /* id */, const unsigned long pid );
+    // ========================================================================
+    LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator==( const LoKi::GenParticles::AbsIdentifier& /* id */, const std::string& pid );
+    // ========================================================================
+    LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator==( const LoKi::GenParticles::AbsIdentifier& /* id  */, const std::vector<LHCb::ParticleID>& pid );
+    // ========================================================================
+    LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator==( const LoKi::GenParticles::AbsIdentifier& /* id */, const std::vector<int>& pid );
+    // ========================================================================
+    LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator==( const LoKi::GenParticles::AbsIdentifier& /* id */, const std::vector<unsigned int>& pid );
+    // ========================================================================
+    LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator==( const LoKi::GenParticles::AbsIdentifier& /* id */, const std::vector<long>& pid );
+    // ========================================================================
+    LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator==( const LoKi::GenParticles::AbsIdentifier& /* id */, const std::vector<unsigned long>& pid );
+    // ========================================================================
+    LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator==( const LoKi::GenParticles::AbsIdentifier& /* id */, const std::vector<std::string>& pid );
+    // ========================================================================
+
+    // ========================================================================
+    // ID !=
+    // ========================================================================
+    LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator!=( const LoKi::GenParticles::Identifier& /* id  */, const LHCb::ParticleID& pid );
+    // ========================================================================
+    LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator!=( const LoKi::GenParticles::Identifier& /* id */, const long pid );
+    // ========================================================================
+    LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator!=( const LoKi::GenParticles::Identifier& /* id */, const unsigned long pid );
+    // ========================================================================
+    LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator!=( const LoKi::GenParticles::Identifier& /* id */, const std::string& pid );
+    // ========================================================================
+    LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator!=( const LoKi::GenParticles::Identifier& /* id  */, const std::vector<LHCb::ParticleID>& pid );
+    // ========================================================================
+    LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator!=( const LoKi::GenParticles::Identifier& /* id */, const std::vector<int>& pid );
+    // ========================================================================
+    LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator!=( const LoKi::GenParticles::Identifier& /* id */, const std::vector<unsigned int>& pid );
+    // ========================================================================
+    LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator!=( const LoKi::GenParticles::Identifier& /* id */, const std::vector<long>& pid );
+    // ========================================================================
+    LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator!=( const LoKi::GenParticles::Identifier& /* id */, const std::vector<unsigned long>& pid );
+    // ========================================================================
+    LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator!=( const LoKi::GenParticles::Identifier& /* id */, const std::vector<std::string>& pid );
+    // ========================================================================
+
+    // ========================================================================
+    // ABSID !=
+    // ========================================================================
+    LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator!=( const LoKi::GenParticles::AbsIdentifier& /* id  */, const LHCb::ParticleID& pid );
+    // ========================================================================
+    LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator!=( const LoKi::GenParticles::AbsIdentifier& /* id */, const long pid );
+    // ========================================================================
+    LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator!=( const LoKi::GenParticles::AbsIdentifier& /* id */, const unsigned long pid );
+    // ========================================================================
+    LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator!=( const LoKi::GenParticles::AbsIdentifier& /* id */, const std::string& pid );
+    // ========================================================================
+    LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator!=( const LoKi::GenParticles::AbsIdentifier& /* id  */, const std::vector<LHCb::ParticleID>& pid );
+    // ========================================================================
+    LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator!=( const LoKi::GenParticles::AbsIdentifier& /* id */, const std::vector<int>& pid );
+    // ========================================================================
+    LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator!=( const LoKi::GenParticles::AbsIdentifier& /* id */, const std::vector<unsigned int>& pid );
+    // ========================================================================
+    LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator!=( const LoKi::GenParticles::AbsIdentifier& /* id */, const std::vector<long>& pid );
+    // ========================================================================
+    LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator!=( const LoKi::GenParticles::AbsIdentifier& /* id */, const std::vector<unsigned long>& pid );
+    // ========================================================================
+    LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator!=( const LoKi::GenParticles::AbsIdentifier& /* id */, const std::vector<std::string>& pid );
+    // ========================================================================
+
+    // ========================================================================
+    // ID ==
+    // ========================================================================
+    inline LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator==( const LHCb::ParticleID& pid, const LoKi::GenParticles::Identifier& id ) {
+      return id == pid;
+    }
+
+    // ========================================================================
+    inline LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator==( const long pid, const LoKi::GenParticles::Identifier& id ) {
+      return id == pid;
+    }
+    // ========================================================================
+    inline LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator==( const unsigned long pid, const LoKi::GenParticles::Identifier& id ) {
+      return id == pid;
+    }
+    // ========================================================================
+    inline LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator==( const std::string& pid, const LoKi::GenParticles::Identifier& id ) {
+      return id == pid;
+    }
+    // ========================================================================
+    inline LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator==( const std::vector<LHCb::ParticleID>& pid, const LoKi::GenParticles::Identifier& id ) {
+      return id == pid;
+    }
+    // ========================================================================
+    inline LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator==( const std::vector<int>& pid, const LoKi::GenParticles::Identifier& id ) {
+      return id == pid;
+    }
+    // ========================================================================
+    inline LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator==( const std::vector<unsigned int>& pid, const LoKi::GenParticles::Identifier& id ) {
+      return id == pid;
+    }
+    // ========================================================================
+    inline LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator==( const std::vector<long>& pid, const LoKi::GenParticles::Identifier& id ) {
+      return id == pid;
+    }
+    // ========================================================================
+    inline LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator==( const std::vector<unsigned long>& pid, const LoKi::GenParticles::Identifier& id ) {
+      return id == pid;
+    }
+    // ========================================================================
+    inline LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator==( const std::vector<std::string>& pid, const LoKi::GenParticles::Identifier& id ) {
+      return id == pid;
+    }
+    // ========================================================================
+
+    // ========================================================================
+    // ABSID ==
+    // ========================================================================
+    inline LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator==( const LHCb::ParticleID& pid, const LoKi::GenParticles::AbsIdentifier& id ) {
+      return id == pid;
+    }
+    // ========================================================================
+    inline LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator==( const long pid, const LoKi::GenParticles::AbsIdentifier& id ) {
+      return id == pid;
+    }
+    // ========================================================================
+    inline LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator==( const unsigned long pid, const LoKi::GenParticles::AbsIdentifier& id ) {
+      return id == pid;
+    }
+    // ========================================================================
+    inline LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator==( const std::string& pid, const LoKi::GenParticles::AbsIdentifier& id ) {
+      return id == pid;
+    }
+    // ========================================================================
+    inline LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator==( const std::vector<LHCb::ParticleID>& pid, const LoKi::GenParticles::AbsIdentifier& id ) {
+      return id == pid;
+    }
+    // ========================================================================
+    inline LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator==( const std::vector<int>& pid, const LoKi::GenParticles::AbsIdentifier& id ) {
+      return id == pid;
+    }
+    // ========================================================================
+    inline LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator==( const std::vector<unsigned int>& pid, const LoKi::GenParticles::AbsIdentifier& id ) {
+      return id == pid;
+    }
+    // ========================================================================
+    inline LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator==( const std::vector<long>& pid, const LoKi::GenParticles::AbsIdentifier& id ) {
+      return id == pid;
+    }
+    // ========================================================================
+    inline LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator==( const std::vector<unsigned long>& pid, const LoKi::GenParticles::AbsIdentifier& id ) {
+      return id == pid;
+    }
+    // ========================================================================
+    inline LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator==( const std::vector<std::string>& pid, const LoKi::GenParticles::AbsIdentifier& id ) {
+      return id == pid;
+    }
+    // ========================================================================
+
+    // ========================================================================
+    // ID !=
+    // ========================================================================
+    inline LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator!=( const LHCb::ParticleID& pid, const LoKi::GenParticles::Identifier& id ) {
+      return id != pid;
+    }
+    // ========================================================================
+    inline LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator!=( const long pid, const LoKi::GenParticles::Identifier& id ) {
+      return id != pid;
+    }
+    // ========================================================================
+    inline LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator!=( const unsigned long pid, const LoKi::GenParticles::Identifier& id ) {
+      return id != pid;
+    }
+    // ========================================================================
+    inline LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator!=( const std::string& pid, const LoKi::GenParticles::Identifier& id ) {
+      return id != pid;
+    }
+    // ========================================================================
+    inline LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator!=( const std::vector<LHCb::ParticleID>& pid, const LoKi::GenParticles::Identifier& id ) {
+      return id != pid;
+    }
+    // ========================================================================
+    inline LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator!=( const std::vector<int>& pid, const LoKi::GenParticles::Identifier& id ) {
+      return id != pid;
+    }
+    // ========================================================================
+    inline LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator!=( const std::vector<unsigned int>& pid, const LoKi::GenParticles::Identifier& id ) {
+      return id != pid;
+    }
+    // ========================================================================
+    inline LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator!=( const std::vector<long>& pid, const LoKi::GenParticles::Identifier& id ) {
+      return id != pid;
+    }
+    // ========================================================================
+    inline LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator!=( const std::vector<unsigned long>& pid, const LoKi::GenParticles::Identifier& id ) {
+      return id != pid;
+    }
+    // ========================================================================
+    inline LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator!=( const std::vector<std::string>& pid, const LoKi::GenParticles::Identifier& id ) {
+      return id != pid;
+    }
+    // ========================================================================
+
+    // ========================================================================
+    // ABSID !=
+    // ========================================================================
+    inline LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator!=( const LHCb::ParticleID& pid, const LoKi::GenParticles::AbsIdentifier& id ) {
+      return id != pid;
+    }
+    // ========================================================================
+    inline LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator!=( const long pid, const LoKi::GenParticles::AbsIdentifier& id ) {
+      return id != pid;
+    }
+    // ========================================================================
+    inline LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator!=( const unsigned long pid, const LoKi::GenParticles::AbsIdentifier& id ) {
+      return id != pid;
+    }
+    // ========================================================================
+    inline LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator!=( const std::string& pid, const LoKi::GenParticles::AbsIdentifier& id ) {
+      return id != pid;
+    }
+    // ========================================================================
+    inline LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator!=( const std::vector<LHCb::ParticleID>& pid, const LoKi::GenParticles::AbsIdentifier& id ) {
+      return id != pid;
+    }
+    // ========================================================================
+    inline LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator!=( const std::vector<int>& pid, const LoKi::GenParticles::AbsIdentifier& id ) {
+      return id != pid;
+    }
+    // ========================================================================
+    inline LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator!=( const std::vector<unsigned int>& pid, const LoKi::GenParticles::AbsIdentifier& id ) {
+      return id != pid;
+    }
+    // ========================================================================
+    inline LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator!=( const std::vector<long>& pid, const LoKi::GenParticles::AbsIdentifier& id ) {
+      return id != pid;
+    }
+    // ========================================================================
+    inline LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator!=( const std::vector<unsigned long>& pid, const LoKi::GenParticles::AbsIdentifier& id ) {
+      return id != pid;
+    }
+    // ========================================================================
+    inline LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator!=( const std::vector<std::string>& pid, const LoKi::GenParticles::AbsIdentifier& id ) {
+      return id != pid;
+    }
+    // ========================================================================
+
+    // ========================================================================
+    inline LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator==( const LoKi::GenParticles::Identifier& id, const int pid ) {
+      return id == LHCb::ParticleID( pid );
+    }
+    // ========================================================================
+    inline LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator==( const LoKi::GenParticles::AbsIdentifier& id, const int pid ) {
+      return id == LHCb::ParticleID( pid );
+    }
+    // ========================================================================
+    inline LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator!=( const LoKi::GenParticles::Identifier& id, const int pid ) {
+      return id != LHCb::ParticleID( pid );
+    }
+    // ========================================================================
+    inline LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator!=( const LoKi::GenParticles::AbsIdentifier& id, const int pid ) {
+      return id != LHCb::ParticleID( pid );
+    }
+    // ========================================================================
+
+    // ========================================================================
+    inline LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator==( const int pid, const LoKi::GenParticles::Identifier& id ) {
+      return id == LHCb::ParticleID( pid );
+    }
+    // ========================================================================
+    inline LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator==( const int pid, const LoKi::GenParticles::AbsIdentifier& id ) {
+      return id == LHCb::ParticleID( pid );
+    }
+    // ========================================================================
+    inline LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator!=( const int pid, const LoKi::GenParticles::Identifier& id ) {
+      return id != LHCb::ParticleID( pid );
+    }
+    // ========================================================================
+    inline LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator!=( const int pid, const LoKi::GenParticles::AbsIdentifier& id ) {
+      return id != LHCb::ParticleID( pid );
+    }
+    // ========================================================================
+
+    // ========================================================================
+  } // namespace GenParticles
+  // ==========================================================================
+} // namespace LoKi
+// ============================================================================
+// The END
+// ============================================================================
+#endif // LOKI_GENPIDOPERATORS_H
diff --git a/Gen/LoKiGen/LoKi/GenParticleCuts.h b/Gen/LoKiGen/LoKi/GenParticleCuts.h
new file mode 100644
index 000000000..320eb3776
--- /dev/null
+++ b/Gen/LoKiGen/LoKi/GenParticleCuts.h
@@ -0,0 +1,1261 @@
+/*****************************************************************************\
+* (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration      *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                             *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+// ============================================================================
+#ifndef LOKI_GENPARTICLECUTS_H
+#define LOKI_GENPARTICLECUTS_H 1
+// ============================================================================
+// Include files
+// ============================================================================
+// LoKi
+// ============================================================================
+#include "LoKi/GenPIDOperators.h"
+#include "LoKi/GenParticles.h"
+#include "LoKi/GenParticles2.h"
+#include "LoKi/GenParticles3.h"
+#include "LoKi/GenParticles4.h"
+#include "LoKi/GenSources.h"
+#include "LoKi/GenTypes.h"
+#include "LoKi/Monitoring.h"
+#include "LoKi/MoreFunctions.h"
+// ============================================================================
+/** @file
+ *
+ *  Collection of useful functions/predicates to deal with
+ *  HepMC3 generator information
+ *
+ *  This file is a part of LoKi project -
+ *    "C++ ToolKit  for Smart and Friendly Physics Analysis"
+ *
+ *  The package has been designed with the kind help from
+ *  Galina PAKHLOVA and Sergey BARSUK.  Many bright ideas,
+ *  contributions and advices from G.Raven, J.van Tilburg,
+ *  A.Golutvin, P.Koppenburg have been used in the design.
+ *
+ *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+ *  @date 2006-01-23
+ */
+// ============================================================================
+namespace LoKi {
+  // ==========================================================================
+  namespace Cuts {
+    // ========================================================================
+    /** @var G3Q
+     *  The trivial evaluator of 3*chareg of the particle
+     *
+     *  @code
+     *
+     *  HepMC3::ConstGenParticlePtr p = ... ;
+     *
+     *  const bool positive = 0 < G3Q( p ) ;
+     *
+     *  @endcode
+     *
+     *  Algorithm:
+     *
+     *   HepMC3::GenParticle:pdg_id -> LHCb::ParticleID -> threeCharge
+     *
+     *  @author Vanya BELYAVE ibelyaev@physics.syr.edu
+     *  @date 2006-03-07
+     */
+    inline const auto G3Q = LoKi::GenParticles::ThreeCharge{};
+    // ========================================================================
+    /** @var GABSID
+     *  primitive evaluator of absolute value for
+     *      ParticleID for HepMC3::GenParticle
+     *
+     *  The schematic algorithm:
+     *
+     *   HepMC3::GenParticle::pdg_id() ->
+     *                     ParticleID -> ParticleID::abspid()
+     *
+     *   @code
+     *
+     *    HepMC3::ConstGenParticlePtr p = ... ;
+     *
+     *    const  long pid = (long) GABSID( p ) ;
+     *
+     *   @endcode
+     *
+     *  @see HepMC3::GenParticle
+     *  @see LoKi::GenParticles::Identifier
+     *
+     *  @author Vanya BELYAEV belyaev@lapp.in2p3.fr
+     *  @date 2005-03-26
+     */
+    inline const auto GABSID = LoKi::GenParticles::AbsIdentifier{};
+    // ========================================================================
+    /** @var GALL
+     *  primitive predicate, "always true"
+     *  @see LoKi::BooleanConstant
+     *  @see LoKi::GenTypes::GTRUE
+     *  @author Vanya BELYAEV belyaev@lapp.in2p3.fr
+     *  @date 2005-03-27
+     */
+    inline const auto GALL = LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::BooleanConstant{true};
+    // ========================================================================
+    /** @typedef GANCESTOR
+     *  trivial function which evaluates for true for all
+     *  'ancestors' of given particle
+     *
+     *  @code
+     *
+     *   const HepMC3::GenParticle bquark = ... ;
+     *
+     *   // get all particles from b-quark
+     *  typedef std::vector<HepMC3::ConstGenParticlePtr> GPs ;
+     *  GPs gps ;
+     *  const HepMC3Events* events = ... ;
+     *  LoKi::Extract::genParticles
+     *                 (  events                     ,   // source
+     *                    std::back_inserter ( gps ) ,   // target
+     *                    GANCESTOR ( bquark )      ) ; // predicate
+     *
+     *  @endcode
+     *
+     *  @see LoKi::GenParticles::IsAnAncestor
+     *
+     *  @author Vanya BELYAEV  Ivan.Belyaev@lapp.in2p3.fr
+     *  @date   2005-05-16
+     */
+    using GANCESTOR = LoKi::GenParticles::IsAnAncestor;
+    // ========================================================================
+    /** @var GBAR
+     *  the most primitive function - it return the "barcode"
+     *  of HepMC3::GenParticle object
+     *
+     *  @see LoKi::Cuts::BarCode
+     *  @see HepMC3::GenParticle
+     *
+     *  @author Vanya BELYAEV belyaev@lapp.in2p3.fr
+     *  @date   2005-03-26
+     */
+    inline const auto GBAR = LoKi::GenParticles::BarCode{};
+    // ========================================================================
+    /** @var GBARCODE
+     *  the most primitive function - it return the "barcode"
+     *  of HepMC3::GenParticle object
+     *
+     *  @see LoKi::Cuts::BarCode
+     *  @see HepMC3::GenParticle
+     *
+     *  @author Vanya BELYAEV belyaev@lapp.in2p3.fr
+     *  @date   2005-03-26
+     */
+    inline const auto GBARCODE = LoKi::GenParticles::BarCode{};
+    // ========================================================================
+    /** @var GBARYON
+     *  Check for particle type
+     *
+     *  @code
+     *
+     *   HepMC3::ConstGenParticlePtr p  = ...         ;
+     *
+     *   const bool baryon  = GBARYON  ( p ) ;
+     *
+     *  @endcode
+     *
+     *  @see HepMC3::GenParticle
+     *  @see LoKi::GenParticles::IsBaryon
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date 2006-01-18
+     */
+    inline const auto GBARYON = LoKi::GenParticles::IsBaryon{};
+    // ========================================================================
+    /** @var GBEAUTY
+     *  Check for bottom quark
+     *
+     *  @code
+     *
+     *   HepMC3::ConstGenParticlePtr p  = ...         ;
+     *
+     *   const bool beauty  = GBEAUTY ( p ) ;
+     *
+     *  @endcode
+     *
+     *  @see HepMC3::GenParticle
+     *  @see LoKi::GenParticles::HasQuark
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date 2006-01-18
+     */
+    inline const auto GBEAUTY = LoKi::GenParticles::HasQuark{LHCb::ParticleID::bottom};
+    // ========================================================================
+    /** @var GCHARGED
+     *  Check for particle charge
+     *
+     *  @code
+     *
+     *   const HepMC3::Particle* p  = ...         ;
+     *
+     *   const bool charged = GCHARGED ( p ) ;
+     *
+     *  @endcode
+     *
+     *  @see HepMC3::GenParticle
+     *  @see LoKi::GenParticles::IsCharged
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date 2006-01-18
+     */
+    inline const auto GCHARGED = LoKi::GenParticles::IsCharged{};
+    // ========================================================================
+    /** @var GCHARM
+     *  Check for charm quark
+     *
+     *  @code
+     *
+     *   HepMC3::ConstGenParticlePtr p  = ...         ;
+     *
+     *   const bool charm  = GCHARM ( p ) ;
+     *
+     *  @endcode
+     *
+     *  @see MCParticle
+     *  @see LoKi::GenParticles::HasQuark
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date 2006-01-18
+     */
+    inline const auto GCHARM = LoKi::GenParticles::HasQuark{LHCb::ParticleID::charm};
+    // ========================================================================
+    /** @typedef GCHILD
+     *  Simple adapter that delegates the function to certain child particle
+     *  @see LoKi::GenParticles::ChildFun
+     *  @see LoKi::GenChild::Selector
+     *  @see LoKi::Cuts::GCHILDFUN
+     *  @author Vanya BELYAEV Ivan.Belyaev@cern.ch
+     *  @date 2011-12-13
+     */
+    using GCHILD = LoKi::GenParticles::ChildFun;
+    // ========================================================================
+    /** @typedef GCHILDCUT
+     *  Simple adapter that delegates the predicate to certain child particle
+     *  @see LoKi::GenParticles::ChildCut
+     *  @see LoKi::GenChild::Selector
+     *  @author Vanya BELYAEV Ivan.Belyaev@cern.ch
+     *  @date 2011-12-13
+     */
+    typedef LoKi::GenParticles::ChildCut GCHILDCUT;
+    // ========================================================================
+    /** @typedef GCHILDFUN
+     *  Simple adapter that delegates the function to certain child particle
+     *  @see LoKi::GenParticles::ChildFun
+     *  @see LoKi::GenChild::Selector
+     *  @see LoKi::Cuts::GCHILD
+     *  @author Vanya BELYAEV Ivan.Belyaev@cern.ch
+     *  @date 2011-12-13
+     */
+    typedef LoKi::GenParticles::ChildFun GCHILDFUN;
+    // ========================================================================
+    /** @typedef GCOUNTER
+     *  Simple monitoring counter for predicates
+     *
+     *  @code
+     *
+     *  // some predicate to be monitored
+     *  GCut cut = ... ;
+     *
+     *  // Create the monitored predicate using the generic counter
+     *  // either local counter, or the counter from IStatSvc
+     *  StatEntity* counter = ... ; ///< the generic counter
+     *  GCut mon = COUNTER ( cut , counter ) ;
+     *
+     *  for ( ... )
+     *    {
+     *      ...
+     *      HepMC3::ConstGenParticlePtr p = ... ;
+     *      const bool result = mon( p ) ; ///< use the predicate
+     *      ...
+     *    }
+     *
+     *  ...
+     *  info ()
+     *     << " Monitoring results : "                       << endmsg
+     *     << " NEntries:  #" << counter->entries ()         << endmsg
+     *     << " Efficiency:(" << counter->eff     ()
+     *     << "+="            << counter->effErr  () << ")%" << endmsg ;
+     *
+     *  @endcode
+     *
+     *  The alternative (recommended) way to create the monitored predicate:
+     *  @code
+     *
+     *  GCut cut = ... ;
+     *
+     *  GCut mon = monitor ( cut , counter("SomeEffCounter") ) ;
+     *
+     *  @endcode
+     *
+     *  The substitution of the predicate by monitored predicate
+     *  cound be done "on-flight" without the disturbing of the
+     *  actual processing:
+     *  @code
+     *
+     *  // some predicate to be monitored
+     *  GCut cut = ... ;
+     *
+     *  if ( monitoring )
+     *    {
+     *       cut = monitor ( cut , "Efficiency1" ) ;
+     *    }
+     *
+     *  @endcode
+     *
+     *  @attention The string representation of the object
+     *             is delegated to the underlying prediate,
+     *             therefore the object is NOT recontructable
+     *             from its string representations. It is done
+     *             on purpose to avoid the disturbing of ids.
+     *
+     *  @see LoKi::Monitoring::Counter
+     *  @see LoKi::monitor
+     *  @see StatEntity
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date 2007-03-03
+     */
+    typedef LoKi::Monitoring::Counter<HepMC3::ConstGenParticlePtr, bool> GCOUNTER;
+    // ========================================================================
+    /** @var GCTAU
+     *  evaluator of particle proper lifetime c*tau (in HepMC3 units)
+     *
+     *  @see LoKi::GenParticles::ProperLifeTime
+     *
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date 2006-01-18
+     */
+    inline const auto GCTAU = LoKi::GenParticles::ProperLifeTime{};
+    // ========================================================================
+    /** @typedef GDECNODE
+     *  the trivial predicate whcih acts on ParticleID
+     *
+     *
+     *  @code
+     *
+     *  // construct some node:
+     *  Decays::Node node = Decays::Nodes::Lepton() && Decays::Nodes::Positive() ;
+     *
+     *  HepMC3::ConstGenParticlePtr p = .... ;
+     *
+     *  // create the predicate:
+     *  GCut good = GDECNODE( node  ) ;
+     *
+     *  // use the predicate:
+     *  const ok = good ( p ) ;
+     *
+     *  @endcode
+     *
+     *  @see LHCb::ParticleID
+     *  @see LHCb::ParticleID
+     *  @see Decays::iNode
+     *  @see Decays::Node
+     *  @see Decays::Nodes
+     *  @author Vanya BELYAEV Ivane.Belyaev@nikhef.nl
+     *  @date 2008-12-17
+     */
+    typedef LoKi::GenParticles::DecNode GDECNODE;
+    // ========================================================================
+    /** @typedef GDECTREE
+     *  the trivial predicate which acts on decay structure
+     *
+     *  @code
+     *
+     *  // construct some tree
+     *  Decays::Tree_<HepMC3::ConstGenParticlePtr> tree =  ... ;
+     *
+     *  HepMC3::ConstGenParticlePtr p = .... ;
+     *
+     *  // create the predicate:
+     *  GCut good = GDECTREE ( tree  ) ;
+     *
+     *  // use the predicate:
+     *  const ok = good ( p ) ;
+     *
+     *  @endcode
+     *
+     *  @see LHCb::ParticleID
+     *  @see Decays::iTree_
+     *  @see Decays::Tree_
+     *  @see Decays::Trees
+     *  @author Vanya BELYAEV Ivane.Belyaev@nikhef.nl
+     *  @date 2008-12-17
+     */
+    typedef LoKi::GenParticles::DecTree GDECTREE;
+    // ========================================================================
+    /** @var GFALSE
+     *  primitive predicate, "always false"
+     *  @see LoKi::BooleanConstant
+     *  @see LoKi::GenTypes::GTRUE
+     *  @see LoKi::Cuts::PFALSE
+     *  @see LoKi::Cuts::VFALSE
+     *  @see LoKi::Cuts::MCFALSE
+     *  @see LoKi::Cuts::MCVFALSE
+     *  @author Vanya BELYAEV belyaev@lapp.in2p3.fr
+     *  @date 2005-03-27
+     */
+    inline const auto GFALSE = LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::BooleanConstant{false};
+    // ========================================================================
+    /** @typedef GFAEVX
+     *  helper adapter which delegates the evaluation of the
+     *  "vertex" function to end vertex of the particle
+     *
+     *  Extract all particles, which are decayed after z > 1000
+     *
+     *  @code
+     *
+     *  const LHCb::HepMC3Events* events
+     *    get<LHCb::HepMC3Events>( LHCb::HepMC3EventLocation::Default ) ;
+     *
+     *  typedef std::vector<HepMC3::GenParticlePtr> PARTICLES ;
+     *
+     *  PARTICLES parts ;
+     *
+     *  // create the predicate:
+     *  GCut cut = GFAEVX( GVZ  , 10000  ) >  1000 ;
+     *
+     *  LoKi::Extract::genParticles
+     *    ( events , std::back_inserter ( parts )  , cut ) ;
+     *
+     *  @endcode
+     *
+     *  @see LoKi::Cuts::GVZ
+     *  @see HepMC3::GenParticle
+     *  @see HepMC3::GenVertex
+     *  @see LoKi::Extract::genParticles
+     *  @see LoKi::GenParticles::AdapterToEndVertex
+     *
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date 2006-02-08
+     */
+    typedef LoKi::GenParticles::AdapterToEndVertex GFAEVX;
+    // ========================================================================
+    /** @typedef GFAPVX
+     *  helper adapter which delegates the evaluation of the
+     *  "vertex" function to production vertex of the particle
+     *
+     *  Extract all particles, which are produces at |z|<10
+     *
+     *  @code
+     *
+     *  const LHCb::HepMC3Events* events
+     *    get<LHCb::HepMC3Events>( LHCb::HepMC3EventLocation::Default ) ;
+     *
+     *  typedef std::vector<HepMC3::GenParticlePtr> PARTICLES ;
+     *
+     *  PARTICLES parts ;
+     *
+     *  // create the predicate:
+     *  GCut cut = GFAPVX( abs( GVZ  ) , 0 )  < 10 ;
+     *
+     *  LoKi::Extract::genParticles
+     *    ( events , std::back_inserter ( parts )  , cut ) ;
+     *
+     *  @endcode
+     *
+     *  @see LoKi::Cuts::GVZ
+     *  @see HepMC3::GenParticle
+     *  @see HepMC3::GenVertex
+     *  @see LoKi::Extract::genParticles
+     *  @see LoKi::GenParticles::AdapterToProductionVertex
+     *
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date 2006-02-08
+     */
+    typedef LoKi::GenParticles::AdapterToProductionVertex GFAPVX;
+    // ========================================================================
+    /** @typedef GFROMTREE
+     *  trivial function which evaluates for true for all
+     *  particles whcih belongs to "descendents" of given particle/vertex
+     *
+     *  @code
+     *
+     *   const HepMC3::GenParticle bquark = ... ;
+     *
+     *   // get all particles from b-quark
+     *  typedef std::vector<HepMC3::ConstGenParticlePtr> GPs ;
+     *  GPs gps ;
+     *  const HepMC3Events* events = ... ;
+     *  LoKi::Extract::genParticles
+     *                 (  events                     ,   // source
+     *                    std::back_inserter ( gps ) ,   // target
+     *                    GFROMTREE ( bquark )       ) ; // predicate
+     *
+     *  @endcode
+     *
+     *  @see LoKi::GenParticles::FromHepMCTree
+     *
+     *  @author Vanya BELYAEV  Ivan.Belyaev@lapp.in2p3.fr
+     *  @date   2005-05-16
+     */
+    typedef LoKi::GenParticles::FromHepMCTree GFROMTREE;
+    // ========================================================================
+    /** @var GHADRON
+     *  Check for particle type
+     *
+     *  @code
+     *
+     *   HepMC3::ConstGenParticlePtr p  = ...         ;
+     *
+     *   const bool hadron  = GHADRON  ( p ) ;
+     *
+     *  @endcode
+     *
+     *  @see HepMC3::GenParticle
+     *  @see LoKi::GenParticles::IsHadron
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date 2006-01-18
+     */
+    inline const auto GHADRON = LoKi::GenParticles::IsHadron{};
+    // ========================================================================
+    /** @var GID
+     *  primitive evaluator of ParticleID for HepMC3::GenParticle
+     *
+     *  The schematic algorithm:
+     *
+     *   HepMC3::GenParticle::pdg_id() ->
+     *                     ParticleID -> ParticleID::pid()
+     *
+     *   @code
+     *
+     *    HepMC3::ConstGenParticlePtr p = ... ;
+     *
+     *    const  long pid = (long) GID( p ) ;
+     *
+     *   @endcode
+     *
+     *  @see HepMC3::GenParticle
+     *  @see LoKi::GenParticles::Identifier
+     *
+     *  @author Vanya BELYAEV belyaev@lapp.in2p3.fr
+     *  @date 2005-03-26
+     */
+    inline const auto GID = LoKi::GenParticles::Identifier{};
+    // ========================================================================
+    /** @typedef GINTREE
+     *  simple meta function to check the presence of the particle in the
+     *  decay tree of the particle:
+     *
+     *  @code
+     *   // check for semiletonic decays of B-meson:
+     *   HepMC3::ConstGenParticlePtr B = ... ;
+     *   // create the predicate:
+     *   GCut hasEorMu = GINTREE ( "e+" == GABSID || "mu+" == GABSID ) ;
+     *   // use the predicate!
+     *   const bool semileptonic = hasEorMu ( B ) ;
+     *
+     *  @endcode
+     *  @see LoKi::GenAlgs::found
+     *  @see LoKi::GenParticles::InTree
+     *  @author Vanya BELYAEV ibelyaev@physic.syr.edu
+     *  @date 2007-06-03
+     */
+    typedef LoKi::GenParticles::InTree GINTREE;
+    // ========================================================================
+    /** @var GLNGLIVED
+     *  the trivial predicate taht check if th eparticle if "long-lived'
+     *
+     *  @code
+     *
+     *  HepMC3::ConstGenParticlePtr p = .... ;
+     *
+     *  // use the predicate:
+     *  const ok = GLONGLIVED ( p ) ;
+     *
+     *  @endcode
+     *
+     *  @see LHCb::ParticleID
+     *  @see Decays::iNode
+     *  @see Decays::Node
+     *  @see Decays::Nodes
+     *  @see Decays::Nodes::LongLived_
+     *  @author Vanya BELYAEV Ivan.Belyaev@itep.ru
+     *  @date 2016-06-21
+     */
+    inline const auto GLONGLIVED = LoKi::GenParticles::LongLived{};
+    // ========================================================================
+    /** @var GLEPTON
+     *  Check for particle type
+     *
+     *  @code
+     *
+     *   HepMC3::ConstGenParticlePtr p  = ...         ;
+     *
+     *   const bool lepton  = GLEPTON  ( p ) ;
+     *
+     *  @endcode
+     *
+     *  @see HepMC3::GenParticle
+     *  @see LoKi::GenParticles::IsLepton
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date 2006-01-18
+     */
+    inline const auto GLEPTON = LoKi::GenParticles::IsLepton{};
+    // ========================================================================
+    /** @var GMESON
+     *  Check for particle type
+     *
+     *  @code
+     *
+     *   HepMC3::ConstGenParticlePtr p  = ...         ;
+     *
+     *   const bool meson   = GMESON   ( p ) ;
+     *
+     *  @endcode
+     *
+     *  @see HepMC3::GenParticle
+     *  @see LoKi::GenParticles::IsMeson
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date 2006-01-18
+     */
+    inline const auto GMESON = LoKi::GenParticles::IsMeson{};
+    // ========================================================================
+    /** @typedef  GMAXTREE
+     *  find a maximal value of certain functor in the tree
+     *  @code
+     *  auto fun = GMAXTREE ( GPT , "pi+" == GABSID ) ;
+     *  @endcode
+     *  @see  LoKi::GenParticles::MaxTree
+     *  @author Vanya BELYAEV Ivan.Belyaev@itep.ru
+     *  @date 2018-06-12
+     */
+    typedef LoKi::GenParticles::MaxTree GMAXTREE;
+    // ========================================================================
+    /** @typedef  GMINTREE
+     *  find a minimal value of certain functor in the tree
+     *  @code
+     *  auto fun = GMINTREE ( GPT , "K+" == GABSID ) ;
+     *  @endcode
+     *  @see  LoKi::GenParticles::MinTree
+     *  @author Vanya BELYAEV Ivan.Belyaev@itep.ru
+     *  @date 2018-06-12
+     */
+    typedef LoKi::GenParticles::MinTree GMINTREE;
+    // ========================================================================
+    /** @typedef  GMULTTREE
+     *  accumulate product of value of certain functor in the tree
+     *  @code
+     *  auto fun = GMULTTREE ( GPT , "mu+" == GABSID ) ;
+     *  @endcode
+     *  @see  LoKi::GenParticles::MultTree
+     *  @author Vanya BELYAEV Ivan.Belyaev@itep.ru
+     *  @date 2018-06-12
+     */
+    typedef LoKi::GenParticles::MultTree GMULTTREE;
+    // ========================================================================
+    /** @typedef GMOMDIST
+     *  The evaluator of euclidian distance with
+     *  respect to the given 4-momentum, useful
+     *  e.g. for trivial "kinematical matching".
+     *  One can find
+     *  the particle with "closest" 4-momentum
+     *  to the given one:
+     *
+     *  @code
+     *
+     *  SEQUENCE            mcparticles = ... ;
+     *  LoKi::LorentzVector vct         = ... ;
+     *
+     *  // find "best match"
+     *  SEQUENCE::const_iterator imin =
+     *    LoKi::select_min( genparticles.begin () ,
+     *                      genparticles.end   () ,
+     *                      GMOMDIST ( vct )    ) ;
+     *
+     *  @endcode
+     *
+     *  E.g. it could be used in a combination with
+     *  LoKi::Extract::genParticles to find a "best matched"
+     *  generator particle:
+     *
+     *  @code
+     *
+     *  const Particle* particle = ...
+     *  // or
+     *  // const MCParticle* particle = ... ;
+     *
+     *  // get 4-momentum and ID from "original" particle:
+     *  const LoKi::LorentzVector& vct = particle->momentum()  ;
+     *  const ParticleID&          pid = particle->particleID() ;
+     *
+     *  // get all HepMC3Particles with the same ID :
+     *  typedef std::vector<HepMC3::ConstGenParticlePtr> GenParticles ;
+     *
+     *  GenParticles particles ;
+     *  // get HepMC3 graphs from Gaudi TES:
+     *  const HepMC3Events* events =
+     *      get<HepMC3Events>( HepMC3EventLocation::Default ) ;
+     *  LoKi::Extract::genParticles
+     *      ( events                          ,    // source
+     *        std::back_inserter( particles ) ,    // target
+     *        pid == GID                      ) ;  // criteria
+     *
+     *  // find the best match:
+     *  GenParticles::const_iterator ibest =
+     *    LoKi::select_min ( particles.begin     () ,
+     *                       particles.end       () ,
+     *                       GMOMDIST ( vct / GeV ) ) ;
+     *
+     *  if ( particles.end() != ibest )
+     *  {
+     *    // the best 4-momentum match !!
+     *    HepMC3::ConstGenParticlePtr best = *ibest ;
+     *  }
+     *
+     *  @endcode
+     *
+     *  @see LoKi::Extract::genParticles
+     *  @see LoKi::select_min
+     *  @see HepMC3::GenParticle
+     *  @see LoKi::LorentzVector
+     *  @see LoKi::GenParticles::MomentumDistance
+     *
+     *  @author Vanya BELYAEV belyaev@lapp.in2p3.fr
+     *  @date 2005-03-23
+     */
+    typedef LoKi::GenParticles::MomentumDistance GMOMDIST;
+    // ========================================================================
+    /** @var GNEUTRAL
+     *  Check for particle charge
+     *
+     *  @code
+     *
+     *   HepMC3::ConstGenParticlePtr p  = ...         ;
+     *
+     *   const bool neutral = GNEUTRAL ( p ) ;
+     *
+     *  @endcode
+     *
+     *  @see HepMC3::GenParticle
+     *  @see LoKi::GenParticles::IsNeutral
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date 2006-01-18
+     */
+    inline const auto GNEUTRAL = LoKi::GenParticles::IsNeutral{};
+    // ========================================================================
+    /** @typedef GNINTREE
+     *  simple evaluator of number of particles in the tree
+     *  which satisfy a certain predicate
+     *
+     *  @warning current implementation is valid only for
+     *       HepMC3::parents, HepMC3::children,
+     *       HepMC3::ancestors and HepMC3::descendants
+     *
+     *  E.g. could be used to extract all b/anti-b quarks
+     *  which comes from decay of Higgs
+     *
+     *  @code
+     *
+     *  // get Generator information
+     *  const HepMC3Events* events =
+     *          get<HepMC3Events>( HepMC3EventLocation::Default ) ;
+     *
+     *  typedef std::vector<HepMC3::ConstGenParticlePtr> GenParticles ;
+     *
+     *  // select b(and antib) quarks from decay of higgs
+     *  GenParticles bquarks ;
+     *  LoKi::Extract::genParticles
+     *   ( events                         ,
+     *     std::back_inserter( bquarks )  ,
+     *     ( "b" == GABSID ) &&
+     *    1 == GNINTREE( "H_10" == GABSID , HepMC3::parents ) ) ;
+     *
+     *  @endcode
+     *
+     *  @see const HepMC3::Relatives &
+     *  @see HepMC3::parents
+     *  @see HepMC3::GenParticle
+     *  @see HepMC3::GenVertex
+     *  @see LoKi::Cuts::GABSID
+     *  @see LoKi::Extract::getParticles
+     *  @see LoKi::GenParticles::NInTree
+     *
+     *  @author Vanya BELYAEV belyaev@lapp.in2p3.fr
+     *  @date 2005-03-23
+     */
+    typedef LoKi::GenParticles::NInTree GNINTREE;
+    // ========================================================================
+    /** @var GNLT
+     *  evaluator of particle NOMINAL proper lifetime c*tau (in HepMC3 units)
+     *
+     *  @see LoKi::GenParticles::NominalLifeTime
+     *
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date 2006-01-18
+     */
+    inline const auto GNLT = LoKi::GenParticles::NominalLifeTime{};
+    // ========================================================================
+    /** @var GNONE
+     *  primitive predicate, "always false"
+     *  @see LoKi::BooleanConstant
+     *  @see LoKi::GenTypes::GFALSE
+     *  @author Vanya BELYAEV belyaev@lapp.in2p3.fr
+     *  @date 2005-03-27
+     */
+    inline const auto GNONE = LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::BooleanConstant{false};
+    // ========================================================================
+    /** @var GNUCLEUS
+     *  Check for particle type
+     *
+     *  @code
+     *
+     *   HepMC3::ConstGenParticlePtr p  = ...         ;
+     *
+     *   const bool nucleus = GNUCLEUS ( p ) ;
+     *
+     *  @endcode
+     *
+     *  @see HepMC3::GenParticle
+     *  @see LoKi::GenParticles::IsNucleus
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date 2006-01-18
+     */
+    inline const auto GNUCLEUS = LoKi::GenParticles::IsNucleus{};
+    // ========================================================================
+    /** @var GONE
+     *  primitive function, "always 1"
+     *  @see LoKi::Constant
+     *  @author Vanya BELYAEV belyaev@lapp.in2p3.fr
+     *  @date 2005-03-27
+     */
+    inline const auto GONE = LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::Constant{1};
+    // ========================================================================
+    /** @var GOSCILLATED
+     *  Check if the particle oscillated.
+     *
+     *  Note: the concept of oscillation in EvtGen/Pythia/HepMC3 is a bit
+     *  mislleading
+     *
+     *  if one has
+     *  @\f[  \mathrm{B}^0 \to \bar{\mathrm{}}^0 \to \mathrm {X} $\f]
+     *  in this case both @\f[\mathrm{B}^0$\f] and  $\f[ \bar{\mathrm{}}^0 @\f]
+     *  are considered as "oscillated"
+     *
+     *  @see LoKi::GenParticles::Oscillated
+     *  @see LoKi::GenParticles::oscillated1
+     *  @see LoKi::GenParticles::oscillated2
+     *
+     *  @code
+     *  @endcode
+     *  @author Vanay BELYAEV Ivan.Belyaev@nikhef.nl
+     *  @author 2008-07-03
+     */
+    inline const auto GOSCILLATED = LoKi::GenParticles::Oscillated{};
+    // ========================================================================
+    /** @var GOSCILLATED1
+     *  Check if the particle oscillated.
+     *
+     *  @see LoKi::GenParticles::Oscillated1
+     *  @see LoKi::GenParticles::oscillated1
+     *
+     *  @author Vanay BELYAEV Ivan.Belyaev@nikhef.nl
+     *  @author 2008-07-03
+     */
+    inline const auto GOSCILLATED1 = LoKi::GenParticles::Oscillated1{};
+    // ========================================================================
+    /** @var GOSCILLATED2
+     *  Check if the particle oscillated.
+     *
+     *  @see LoKi::GenParticles::Oscillated2
+     *  @see LoKi::GenParticles::oscillated2
+     *
+     *  @author Vanay BELYAEV Ivan.Belyaev@nikhef.nl
+     *  @author 2008-07-03
+     */
+    inline const auto GOSCILLATED2 = LoKi::GenParticles::Oscillated2{};
+    // ========================================================================
+    /** @typedef GPLOT
+     *  Simple monitoring histogram for the functions
+     *
+     *  @code
+     *
+     *  // some function to be monitored
+     *  GFun fun = ... ;
+     *
+     *  // Create the monitored function using the histogram:
+     *  AIDA::IHistogram1D* histo = ... ;
+     *  GFun mon = PLOT ( fun , histo ) ;
+     *
+     *  for ( ... )
+     *    {
+     *      ...
+     *      const LHCb::Particle* p = ... ;
+     *      const double result = mon( p ) ; ///< use the function
+     *      ...
+     *    }
+     *
+     *  @endcode
+     *
+     *  The alternative (recommended) way to create the monitored function
+     *  @code
+     *
+     *  // some function to be monitored
+     *  GFun fun = ... ;
+     *
+     *  AIDA::IHistogram1D* histo = ... ;
+     *  GFun mon = monitor ( fun , histo ) ;
+     *
+     *  @endcode
+     *
+     *  The substitution of the function by monitored function
+     *  cound be done "on-flight" without the disturbing of the
+     *  actual processing:
+     *  @code
+     *
+     *  // some function to be monitored
+     *  GFun fun = ... ;
+     *
+     *  if ( monitoring )
+     *    {
+     *       AIDA::IHistogram1D* histo = ... ;
+     *       fun = monitor ( fun , histo ) ;
+     *    }
+     *
+     *  @endcode
+     *
+     *  @attention The string representation of the object
+     *             is delegated to the underlying function,
+     *             therefore the object is NOT recontructable
+     *             from its string representations. It is done
+     *             on purpose to avoid the disturbing of ids.
+     *
+     *  @see LoKi::Monitoring::Plot
+     *  @see LoKi::monitor
+     *  @see AIDA::IHistogram1D
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date 2007-03-03
+     */
+    typedef LoKi::Monitoring::Plot<HepMC3::ConstGenParticlePtr, double> GPLOT;
+    // ========================================================================
+    /** @typedef GPTDIR
+     *  simple evaluator of transverse momentum
+     *  relative to some 3-vector (e.g. jet axis)
+     *
+     *  @code
+     *
+     *  // vector (e.g. jet axis)
+     *  const LoKi::ThreeVector& vct = ... ;
+     *
+     *  // particle
+     *  HepMC3::ConstGenParticlePtr particle = ... ;
+     *
+     *  // create function
+     *  GFun ptDir = GPTDIR( vct ) ;
+     *
+     *  // use the function:
+     *  const double pt = ptDir( particle ) ;
+     *
+     *  @endcode
+     *
+     *  @see HepMC3::GenParticle
+     *  @see LoKi::ThreeVector
+     *  @see LoKi::GenParticles::TransverseMomentumRel
+     *
+     *  @author Vanya BELYAEV belyaev@lapp.in2p3.fr
+     *  @date 2005-03-23
+     */
+    typedef LoKi::GenParticles::TransverseMomentumRel GPTDIR;
+    // ========================================================================
+    /** @typedef GPTREL
+     *  simple evaluator of transverse momentum
+     *  relative to some 3-vector (e.g. jet axis)
+     *
+     *  @code
+     *
+     *  // vector (e.g. jet axis)
+     *  const LoKi::ThreeVector& vct = ... ;
+     *
+     *  // particle
+     *  HepMC3::ConstGenParticlePtr particle = ... ;
+     *
+     *  // create function
+     *  GFun ptDir = GPTREL ( vct ) ;
+     *
+     *  // use the function:
+     *  const double pt = ptDir( particle ) ;
+     *
+     *  @endcode
+     *
+     *  @see HepMC3::GenParticle
+     *  @see LoKi::ThreeVector
+     *  @see LoKi::GenParticles::TransverseMomentumRel
+     *  @see LoKi::Cut::GPTDIR
+     *
+     *  @author Vanya BELYAEV belyaev@lapp.in2p3.fr
+     *  @date 2005-03-23
+     */
+    typedef LoKi::GenParticles::TransverseMomentumRel GPTREL;
+    // ========================================================================
+    /** @typedef GQUARK
+     *  quark content
+     *
+     *  @code
+     *
+     *   HepMC3::ConstGenParticlePtr p  = ...         ;
+     *   GCut cut = GQUARK( ParticleID::bottom )
+     *
+     *   const bool beauty  = cut ( p ) ;
+     *
+     *  @endcode
+     *
+     *  @see HepMC3::GenParticle
+     *  @see LoKi::GenParticles::HasQuark
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date 2006-01-18
+     */
+    typedef LoKi::GenParticles::HasQuark GQUARK;
+    // ========================================================================
+    /** Simple "switch"
+     *  The function evaluated the predicate and returns
+     *  one of the predefined values, depending on result on
+     *  predicate evaluation.
+     *  In some sense it is a conversion of "predicate" to "function"
+     *
+     *  @code
+     *
+     *   HepMC3::ConstGenParticlePtr mcp = ...  ;
+     *
+     *   GFun fun = GSSWITCH( GHADRON , 1 , -1 )
+     *
+     *   const double value = fun( p ) ;
+     *
+     *  @endcode
+     *
+     *  For this example function returns 1 if  the particle is hadron and
+     *   particle and -1 otherwise
+     *
+     *  @see LoKi::SipleSwitch
+     *
+     *  @author Vanya BELYAEV belyaev@lapp.in2p3.fr
+     */
+    typedef LoKi::SimpleSwitch<HepMC3::ConstGenParticlePtr> GSSWITCH;
+    // ========================================================================
+    /** @typedef GSTAT
+     *  Simple monitoring counter for the functions
+     *
+     *  @code
+     *
+     *  // some function to be monitored
+     *  GFun fun = ... ;
+     *
+     *  // Create the monitored function using the generic counter
+     *  // either local counter, or the counter from IStatSvc
+     *  StatEntity* counter = ... ; ///< the generic counter
+     *  GFun mon = STAT ( fun , counter ) ;
+     *
+     *  for ( ... )
+     *    {
+     *      ...
+     *      HepMC3::ConstGenParticlePtr p = ... ;
+     *      const double result = mon( p ) ; ///< use the function
+     *      ...
+     *    }
+     *
+     *  ...
+     *  info ()
+     *     << " Monitoring results : "                 << endmsg
+     *     << " NEntries:  #" << counter->entries  ()  << endmsg
+     *     << " TotalSum:   " << counter->flag     ()  << endmsg
+     *     << " Mean+-RMS:  " << counter->flagMean ()
+     *     << "+="            << counter->flagRMS  ()  << endmsg
+     *     << " Min/Max:    " << counter->flagMin  ()
+     *     << "/"             << counter->flagMax  ()  << endmsg ;
+     *
+     *  @endcode
+     *
+     *  The alternative (recommended) way to create the monitored function
+     *  @code
+     *
+     *  // some function to be monitored
+     *  GFun fun = ... ;
+     *
+     *  GFun mon = monitor ( fun , counter("SomeCounter") ) ;
+     *
+     *  @endcode
+     *
+     *  The substitution of the function by monitored function
+     *  cound be done "on-flight" without the disturbing of the
+     *  actual processing:
+     *  @code
+     *
+     *  // some function to be monitored
+     *  GFun fun = ... ;
+     *
+     *  if ( monitoring )
+     *    {
+     *       fun = monitor ( fun , "MonitoredFun" ) ;
+     *    }
+     *
+     *  @endcode
+     *
+     *  @attention The string representation of the object
+     *             is delegated to the underlying function,
+     *             therefore the object is NOT recontructable
+     *             from its string representations. It is done
+     *             on purpose to avoid the disturbing of ids.
+     *
+     *  @see LoKi::Monitoring::Counter
+     *  @see LoKi::monitor
+     *  @see StatEntity
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date 2007-03-03
+     */
+    typedef LoKi::Monitoring::Counter<HepMC3::ConstGenParticlePtr, double> GSTAT;
+    // ========================================================================
+    /** @var GSTATUS
+     *  the primitive evaluator of HepMC3::Particle::status()
+     *
+     *  @code
+     *
+     *  HepMC3::ConstGenParticlePtr p = ... ;
+     *  const int status = (int) GSTATUS( p ) ;
+     *
+     *  @endcode
+     *
+     *  @see HepMC3::GenParticle
+     *  @see LoKi::GenParticles::Status
+     *
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date 2006-08-26
+     */
+    inline const auto GSTATUS = LoKi::GenParticles::Status{};
+    // ========================================================================
+    /** @var GSTRANGE
+     *  Check for strange quark
+     *
+     *  @code
+     *
+     *   HepMC3::ConstGenParticlePtr p  = ...         ;
+     *
+     *   const bool strange = GSTRANGE ( p ) ;
+     *
+     *  @endcode
+     *
+     *  @see HepMC3::GenParticle
+     *  @see LoKi::GenParticles::HasQuark
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date 2006-01-18
+     */
+    inline const auto GSTRANGE = LoKi::GenParticles::HasQuark{LHCb::ParticleID::strange};
+    // ========================================================================
+    /** @typedef  GSUMTREE
+     *  find a sum over the certain functor in the tree
+     *  @code
+     *  auto fun = GSUMTREE ( GPT , "K+" == GABSID ) ;
+     *  @endcode
+     *  @see  LoKi::GenParticles::SumTree
+     *  @author Vanya BELYAEV Ivan.Belyaev@itep.ru
+     *  @date 2018-06-12
+     */
+    typedef LoKi::GenParticles::SumTree GSUMTREE;
+    // ========================================================================
+    /** switch"
+     *  The function evaluates the predicate and returns
+     *  the values of one of the predefined functions,
+     *  depending on result on predicate evaluation.
+     *
+     *  @code
+     *
+     *   const HepMC3::Particle* mcp = ...  ;
+     *
+     *   GFun fun = GSWITCH( HADRON , GP , GE ) ;
+     *
+     *   const double value = fun( p ) ;
+     *
+     *  @endcode
+     *
+     *  For this example function returns the value of
+     *  P for hadrons and E for other particles
+     *
+     *  @see LoKi::Switch
+     *
+     *  @author Vanya BELYAEV belyaev@lapp.in2p3.fr
+     */
+    typedef LoKi::Switch<HepMC3::ConstGenParticlePtr> GSWITCH;
+    // ========================================================================
+    /** @var GTIME
+     *  evaluator of particle proper lifetime c*tau (in HepMC3 units)
+     *
+     *  @see LoKi::GenParticles::ProperLifeTime
+     *
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date 2006-01-18
+     */
+    inline const auto GTIME = LoKi::GenParticles::ProperLifeTime{};
+    // ========================================================================
+    /** @var GTOP
+     *  Check for TOP  quark
+     *
+     *  @code
+     *
+     *   HepMC3::ConstGenParticlePtr p  = ...         ;
+     *
+     *   const bool top  = GTOP( p ) ;
+     *
+     *  @endcode
+     *
+     *  @see HepMC3::GenParticle
+     *  @see LoKi::GenParticles::HasQuark
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date 2006-01-18
+     */
+    inline const auto GTOP = LoKi::GenParticles::HasQuark{LHCb::ParticleID::top};
+    // ========================================================================
+    /** @var GTRUE
+     *  primitive predicate, "always true"
+     *  @see LoKi::BooleanConstant
+     *  @see LoKi::Cuts::PTRUE
+     *  @see LoKi::Cuts::VTRUE
+     *  @see LoKi::Cuts::MCTRUE
+     *  @see LoKi::Cuts::MCVTRUE
+     *  @author Vanya BELYAEV belyaev@lapp.in2p3.fr
+     *  @date 2005-03-27
+     */
+    inline const auto GTRUE = LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::BooleanConstant{true};
+    // ========================================================================
+    /** @var GVALID
+     *  Simple predicate which checks the ildty of the pointer
+     *  @author Vanya BELYAEV belyaev@physics.syr.edu
+     *  @date 2007-07-22
+     */
+    inline const auto GVALID = LoKi::Valid<HepMC3::ConstGenParticlePtr>{};
+    // ========================================================================
+    /** @var GVEV
+     *  primitive predicate to check the validity of "end_vertex"
+     *  for HepMC3::GenParticle object
+     *
+     *  The schematic algorithm:
+     *
+     *    0 != HepMC3::GenParticle::end_vertex()
+     *
+     *   @code
+     *
+     *    HepMC3::ConstGenParticlePtr p = ... ;
+     *
+     *    const bool valid  = GVEV ( p ) ;
+     *
+     *   @endcode
+     *
+     *  @author Vanya BELYAEV belyaev@lapp.in2p3.fr
+     *  @date 2005-03-26
+     */
+    inline const auto GVEV = LoKi::GenParticles::ValidEndVertex{};
+    // ========================================================================
+    /** @var GZERO
+     *  primitive function, "always 0"
+     *  @see LoKi::Constant
+     *  @author Vanya BELYAEV belyaev@lapp.in2p3.fr
+     *  @date 2005-03-27
+     */
+    inline const auto GZERO = LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::Constant{0};
+    // ========================================================================
+  } // namespace Cuts
+  // ==========================================================================
+} //                                                      end of namespace LoKi
+// ============================================================================
+// The END
+// ============================================================================
+#endif // LOKI_GENPARTICLECUTS_H
diff --git a/Gen/LoKiGen/LoKi/GenParticles.h b/Gen/LoKiGen/LoKi/GenParticles.h
new file mode 100644
index 000000000..2ff173086
--- /dev/null
+++ b/Gen/LoKiGen/LoKi/GenParticles.h
@@ -0,0 +1,1282 @@
+/*****************************************************************************\
+* (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration      *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                             *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+// ============================================================================
+#ifndef LOKI_GENPARTICLES_H
+#define LOKI_GENPARTICLES_H 1
+// ============================================================================
+// Include files
+// ============================================================================
+// LHCbKernel
+// ============================================================================
+#include "Kernel/NodesPIDs.h"
+#include "Kernel/ParticleID.h"
+#include "Kernel/iNode.h"
+#include "LoKi/iTree.h"
+// ============================================================================
+// LoKi
+// ============================================================================
+#include "LoKi/BasicFunctors.h"
+#include "LoKi/Constants.h"
+#include "LoKi/Functions.h"
+#include "LoKi/GenChildSelector.h"
+#include "LoKi/GenTypes.h"
+#include "LoKi/PidFunctions.h"
+// ============================================================================
+// HepMC3
+// ============================================================================
+#include "HepMC3/GenParticle.h"
+#include "HepMC3/GenVertex.h"
+#include "HepMC3/GenEvent.h"
+#include "HepMC3/Relatives.h"
+// ============================================================================
+/** @file
+ *
+ *  This file is a part of LoKi project -
+ *    "C++ ToolKit  for Smart and Friendly Physics Analysis"
+ *
+ *  The package has been designed with the kind help from
+ *  Galina PAKHLOVA and Sergey BARSUK.  Many bright ideas,
+ *  contributions and advices from G.Raven, J.van Tilburg,
+ *  A.Golutvin, P.Koppenburg have been used in the design.
+ *
+ *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+ *  @date 2006-01-23
+ *
+ */
+// ============================================================================
+namespace LoKi {
+  // ==========================================================================
+  /** @namespace LoKi::GenParticles GenParticles.h LoKi/GenParticles.h
+   *
+   *  Collection of LoKi functions and predicates to manipulate with
+   *  generator (HepMC3) information
+   *
+   *  @author Vanya BELYAEV belyaev@lapp.in2p3.fr
+   *  @date   2005-03-26
+   */
+  namespace GenParticles {
+    // ========================================================================
+    /** @class BarCode
+     *  the most primitive function - it returns the "barcode"
+     *  of HepMC3::GenParticle object
+     *
+     *  @see LoKi::Cuts::GBAR
+     *  @see HepMC3::GenParticle
+     *
+     *  @author Vanya BELYAEV belyaev@lapp.in2p3.fr
+     *  @date   2005-03-26
+     */
+    struct GAUDI_API BarCode : LoKi::GenTypes::GFunc {
+      // ======================================================================
+      /// MANDATORY: clone method ("virtual" constructor")
+      BarCode* clone() const override;
+
+      /// MANDATORY: the only one essential method
+      virtual double operator()( const HepMC3::ConstGenParticlePtr & p ) const override;
+      /// "SHORT" representation, @see LoKi::AuxFunBase
+      std::ostream& fillStream( std::ostream& s ) const override;
+      // ======================================================================
+    };
+    // ========================================================================
+    /** @class Identifier
+     *  primitive function to extract the
+     *  particle identifier from HepMC3::GenParticle
+     *
+     *   Algorithm:
+     *
+     *   int -> ParticleID -> ParticleID::pid()
+     *
+     *  @see ParticleID
+     *  @see HepMC3::GenParticle
+     *  @see LoKi::Cuts::GID
+     *
+     *  @author Vanya BELYAEV belyaev@lapp.in2p3.fr
+     *  @date   2005-03-26
+     */
+    struct GAUDI_API Identifier : LoKi::GenTypes::GFunc {
+      // ======================================================================
+      /// MANDATORY: clone method ("virtual" constructor")
+      Identifier* clone() const override;
+      /// MANDATORY: the only one essential method
+      double operator()( const HepMC3::ConstGenParticlePtr & p ) const override;
+      /// "SHORT" representation, @see LoKi::AuxFunBase
+      std::ostream& fillStream( std::ostream& s ) const override;
+      // ======================================================================
+    };
+    // ========================================================================
+    /** @class AbsIdentifier
+     *  primitive function to extract the absolute value of
+     *  particle identifier from HepMC3::GenParticle
+     *
+     *   Algorithm:
+     *
+     *   int -> ParticleID -> ParticleID::abspid()
+     *
+     *  @see ParticleID
+     *  @see HepMC3::GenParticle
+     *  @see LoKi::Cuts::GABSID
+     *
+     *  @author Vanya BELYAEV belyaev@lapp.in2p3.fr
+     *  @date   2005-03-26
+     */
+    struct GAUDI_API AbsIdentifier : LoKi::GenTypes::GFunc {
+      // ======================================================================
+      /// MANDATORY: clone method ("virtual" constructor")
+      AbsIdentifier* clone() const override;
+      /// MANDATORY: the only one essential method
+      double operator()( const HepMC3::ConstGenParticlePtr & p ) const override;
+      /// "SHORT" representation, @see LoKi::AuxFunBase
+      std::ostream& fillStream( std::ostream& s ) const override;
+      // ======================================================================
+    };
+
+    // ========================================================================
+    /** @class IsID
+     *  new verison of PID-comparison
+     */
+    // ========================================================================
+    struct GAUDI_API IsID : LoKi::GenTypes::GCuts, LoKi::Pids::GetPids {
+      // ======================================================================
+      IsID( const long id );
+      IsID( const unsigned long id );
+      IsID( const LHCb::ParticleID& id );
+      IsID( const std::string& id );
+      IsID( const std::vector<int>& ids );
+      IsID( const std::vector<long>& ids );
+      IsID( const std::vector<unsigned int>& ids );
+      IsID( const std::vector<unsigned long>& ids );
+      IsID( const std::vector<LHCb::ParticleID>& ids );
+      IsID( const std::vector<std::string>& ids );
+      IsID( const LoKi::Pids::GetPids& ids );
+      // ======================================================================
+      IsID* clone() const override;
+      /// the only one essential method
+      bool operator()( const HepMC3::ConstGenParticlePtr & p ) const override;
+      /// "SHORT" representation, @see LoKi::AuxFunBase
+      std::ostream& fillStream( std::ostream& s ) const override;
+      // ======================================================================
+    };
+    // ========================================================================
+    /** @class IsNotID
+     *  new verison of PID-comparison
+     */
+    // ========================================================================
+    struct GAUDI_API IsNotID : LoKi::GenParticles::IsID {
+      // ======================================================================
+      IsNotID( const long id );
+      IsNotID( const unsigned long id );
+      IsNotID( const LHCb::ParticleID& id );
+      IsNotID( const std::string& id );
+      IsNotID( const std::vector<int>& ids );
+      IsNotID( const std::vector<long>& ids );
+      IsNotID( const std::vector<unsigned int>& ids );
+      IsNotID( const std::vector<unsigned long>& ids );
+      IsNotID( const std::vector<LHCb::ParticleID>& ids );
+      IsNotID( const std::vector<std::string>& ids );
+      IsNotID( const LoKi::Pids::GetPids& ids );
+      // ======================================================================
+      IsNotID* clone() const override;
+      /// the only one essential method
+      bool operator()( const HepMC3::ConstGenParticlePtr & p ) const override;
+      /// "SHORT" representation, @see LoKi::AuxFunBase
+      std::ostream& fillStream( std::ostream& s ) const override;
+      // ======================================================================
+    };
+    // ========================================================================
+    struct GAUDI_API IsAbsID : LoKi::GenParticles::IsID {
+      // ======================================================================
+      IsAbsID( const long id );
+      IsAbsID( const unsigned long id );
+      IsAbsID( const LHCb::ParticleID& id );
+      IsAbsID( const std::string& id );
+      IsAbsID( const std::vector<int>& ids );
+      IsAbsID( const std::vector<long>& ids );
+      IsAbsID( const std::vector<unsigned int>& ids );
+      IsAbsID( const std::vector<unsigned long>& ids );
+      IsAbsID( const std::vector<LHCb::ParticleID>& ids );
+      IsAbsID( const std::vector<std::string>& ids );
+      IsAbsID( const LoKi::Pids::GetPids& ids );
+      // ======================================================================
+      IsAbsID* clone() const override;
+      /// the only one essential method
+      bool operator()( const HepMC3::ConstGenParticlePtr & p ) const override;
+      /// "SHORT" representation, @see LoKi::AuxFunBase
+      std::ostream& fillStream( std::ostream& s ) const override;
+      // ======================================================================
+    };
+    // ========================================================================
+    struct GAUDI_API IsNotAbsID : LoKi::GenParticles::IsAbsID {
+      // ======================================================================
+      IsNotAbsID( const long id );
+      IsNotAbsID( const unsigned long id );
+      IsNotAbsID( const LHCb::ParticleID& id );
+      IsNotAbsID( const std::string& id );
+      IsNotAbsID( const std::vector<int>& ids );
+      IsNotAbsID( const std::vector<long>& ids );
+      IsNotAbsID( const std::vector<unsigned int>& ids );
+      IsNotAbsID( const std::vector<unsigned long>& ids );
+      IsNotAbsID( const std::vector<LHCb::ParticleID>& ids );
+      IsNotAbsID( const std::vector<std::string>& ids );
+      IsNotAbsID( const LoKi::Pids::GetPids& ids );
+      // ======================================================================
+      IsNotAbsID* clone() const override;
+      /// the only one essential method
+      bool operator()( const HepMC3::ConstGenParticlePtr & p ) const override;
+      /// "SHORT" representation, @see LoKi::AuxFunBase
+      std::ostream& fillStream( std::ostream& s ) const override;
+      // ======================================================================
+    };
+    // ========================================================================
+    /** @class Status
+     *  the most primitive function - it return the "status"
+     *  of HepMC3::GenParticle object
+     *
+     *  @see LoKi::Cuts::GTATUS
+     *  @see HepMC3::GenParticle
+     *
+     *  @author Vanya BELYAEV belyaev@lapp.in2p3.fr
+     *  @date   2005-03-26
+     */
+    struct GAUDI_API Status : LoKi::GenTypes::GFunc {
+      // ======================================================================
+      /// MANDATORY: clone method ("virtual" constructor")
+      Status* clone() const override;
+      /// MANDATORY: the only one essential method
+      double operator()( const HepMC3::ConstGenParticlePtr & p ) const override;
+      /// "SHORT" representation, @see LoKi::AuxFunBase
+      std::ostream& fillStream( std::ostream& s ) const override;
+      // ======================================================================
+    };
+    // ========================================================================
+    /** @class ValidEndVertex
+     *  primitive predicate to test the validity of
+     *  "end-vertex" for HepMC3::GenParticle object
+     *
+     *  @see HepMC3::GenVertex
+     *  @see HepMC3::GenParticle
+     *  @see LoKi::Cuts::GVEV
+     *
+     *  @author Vanya BELYAEV belyaev@lapp.in2p3.fr
+     *  @date   2005-03-26
+     */
+    struct GAUDI_API ValidEndVertex : LoKi::GenTypes::GCuts {
+      // ======================================================================
+      /// MANDATORY: clone method ("virtual constructor")
+      ValidEndVertex* clone() const override;
+      /// MANDATORY: the only one essential method
+      bool operator()( const HepMC3::ConstGenParticlePtr & p ) const override;
+      /// "SHORT" representation, @see LoKi::AuxFunBase
+      std::ostream& fillStream( std::ostream& s ) const override;
+      // ======================================================================
+    };
+    // ========================================================================
+    /** @class MomentumDistance
+     *  Trivial evaluator of euclidian distance
+     *  of 4-momentums useful e.g. for trivial
+     *  "kinematical matching".
+     *  One can find
+     *   the particle with "closest" 4-momentum
+     *   to the given one:
+     *
+     *  @code
+     *
+     *  SEQUENCE            genparticles = ... ;
+     *  LoKi::LorentzVector vct       = ... ;
+     *
+     *  // find "best match"
+     *  SEQUENCE::const_iterator imin =
+     *    LoKi::select_min( genparticles.begin () ,
+     *                      genparticles.end   () ,
+     *                      GMOMDIST ( vct )    ) ;
+     *
+     *  @endcode
+     *
+     *  @see HepMC3::GenParticle
+     *  @see LoKi::LorentzVector
+     *  @see LoKi::Cuts::GMOMDIST
+     *
+     *  @author Vanya BELYAEV belyaev@lapp.in2p3.fr
+     *  @date 2005-03-23
+     */
+    class GAUDI_API MomentumDistance : public LoKi::GenTypes::GFunc {
+    public:
+      // ======================================================================
+      /// constructor from 4 components
+      MomentumDistance( const double px, const double py, const double pz, const double e );
+      /** constructor
+       *  @param vct the reference 4-momentum
+       */
+      MomentumDistance( const LoKi::LorentzVector& vct );
+      /// MANDATORY: clone function ("virtual constructor")
+      MomentumDistance* clone() const override;
+      /// MANDATORY: the only one essential method
+      double operator()( const HepMC3::ConstGenParticlePtr & p ) const override;
+      /// "SHORT" representation, @see LoKi::AuxFunBase
+      std::ostream& fillStream( std::ostream& s ) const override;
+      // ======================================================================
+    private:
+      // ======================================================================
+      LoKi::LorentzVector m_vct;
+      // ======================================================================
+    };
+    // ========================================================================
+    /** @class TransverseMomentumRel
+     *  Trivial evaluator of the transverse momenrum,
+     *  relatve to the given direction
+     *
+     *  @code
+     *
+     *  HepMC3::ConstGenParticlePtr  genparticle = ... ;
+     *  LoKi::ThreeVector  vct  = ... ;
+     *
+     *  GFun pt = GPTDIR( vct ) ;
+     *  const double pt = pt ( genparticle ) ;
+     *
+     *  @endcode
+     *
+     *  @see LoKi::Cuts::GPTDIR
+     *  @author Vanya BELYAEV belyaev@lapp.in2p3.fr
+     *  @date 2005-03-23
+     */
+    class GAUDI_API TransverseMomentumRel : public LoKi::GenTypes::GFunc {
+    public:
+      // ======================================================================
+      /** constructor from theta and phi
+       *  @param theta theta angle for the direction
+       *  @param phi phi angle for the direction
+       */
+      TransverseMomentumRel( const double theta, const double phi );
+      /** constructor from x,y,z
+       *  @param x x-component of the direction vector
+       *  @param y y-component of the direction vector
+       *  @param z z-component of the direction vector
+       */
+      TransverseMomentumRel( const double x, const double y, const double z );
+      /** constructor from direction vector
+       *  @param vct direction vertor
+       *  @see LoKi::ThreeVector
+       */
+      TransverseMomentumRel( const LoKi::ThreeVector& vct );
+      /** constructor from direction vector
+       *  @param vct direction vertor
+       *  @see LoKi::LorentzVector
+       */
+      TransverseMomentumRel( const LoKi::LorentzVector& vct );
+      /// MANDATORY: clone function ("virtual constructor")
+      TransverseMomentumRel* clone() const override;
+      /// MANDATORY: the only one essential method
+      double operator()( const HepMC3::ConstGenParticlePtr & p ) const override;
+      /// "SHORT" representation, @see LoKi::AuxFunBase
+      std::ostream& fillStream( std::ostream& s ) const override;
+      // ======================================================================
+    private:
+      // ======================================================================
+      LoKi::ThreeVector m_vct;
+      // ======================================================================
+    };
+    // ========================================================================
+    /** @class FromHepMCTree
+     *  simple predicate to test if a certain
+     *  HepMC3::GenParticle comes from HepMC3 graph
+     *  of another HepMC3::GenParticle or vertex
+     *
+     *
+     *  @see LoKi::Cuts::GFROMTREE
+     *  @author Vanya BELYAEV Ivan.Belyaev@lapp.in2p3.fr
+     *  @date 2005-05-16
+     */
+    class GAUDI_API FromHepMCTree : public LoKi::GenTypes::GCuts {
+    public:
+      // ======================================================================
+      /** constructor from particle ("head")
+       *  @param p pointer to HepMC3::GenParticle
+       */
+      FromHepMCTree( const HepMC3::ConstGenParticlePtr & p );
+      /// constructor from vector of particles
+      FromHepMCTree( const LoKi::GenTypes::GenContainer& r );
+      /// constructor from range of particles
+      FromHepMCTree( const LoKi::Types::GRange& r );
+      /** constructor from vertex  ("head")
+       *  @param v pointer to HepMC3::GenParticle
+       */
+      FromHepMCTree( const HepMC3::ConstGenVertexPtr & v );
+      /// templated constructor
+      template <class ITERATOR>
+      FromHepMCTree( ITERATOR first, ITERATOR last ) : LoKi::GenTypes::GCuts() {
+        _add( first, last );
+      }
+      /// MANDATORY: clone method ("virtual constructor")
+      FromHepMCTree* clone() const override;
+      /// MANDATORY: the only one essential method
+      bool operator()( const HepMC3::ConstGenParticlePtr & p ) const override;
+      /// "SHORT" representation, @see LoKi::AuxFunBase
+      std::ostream& fillStream( std::ostream& s ) const override;
+      // ======================================================================
+    public:
+      // ======================================================================
+      template <class ITERATOR>
+      FromHepMCTree& add( ITERATOR first, ITERATOR last ) {
+        _add( first, last );
+        return *this;
+      }
+      FromHepMCTree& add( const HepMC3::ConstGenParticlePtr & p ) {
+        _add( p );
+        return *this;
+      }
+      FromHepMCTree& add( const HepMC3::ConstGenVertexPtr & p ) {
+        _add( p );
+        return *this;
+      }
+      FromHepMCTree& add( const LoKi::Types::GRange& p ) {
+        _add( p.begin(), p.end() );
+        return *this;
+      }
+      FromHepMCTree& remove( const HepMC3::ConstGenVertexPtr & v );
+      FromHepMCTree& remove( const HepMC3::ConstGenParticlePtr & v );
+      // ======================================================================
+    protected:
+      // ======================================================================
+      template <class ITERATOR>
+      void _add( ITERATOR first, ITERATOR last ) {
+        for ( ; first != last; ++first ) { _add( *first ); }
+      }
+      void _add( const HepMC3::ConstGenParticlePtr & p );
+      void _add( const HepMC3::ConstGenVertexPtr & v );
+      // ======================================================================
+    private:
+      // ======================================================================
+      typedef std::vector<HepMC3::ConstGenVertexPtr> VERTICES;
+      VERTICES                               m_vertices;
+      // ======================================================================
+    };
+    // ========================================================================
+    /** @class IsAnAncestor
+     *  simple predicate to test if a certain
+     *  HepMC3::GenParticle is an ancestor
+     *  of another HepMC3::GenParticle
+     *
+     *
+     *  @see LoKi::Cuts::GANCESTOR
+     *  @author Vanya BELYAEV Ivan.Belyaev@lapp.in2p3.fr
+     *  @date 2005-05-16
+     */
+    class GAUDI_API IsAnAncestor : public LoKi::GenTypes::GCuts {
+    public:
+      // ======================================================================
+      /** constructor from particle
+       *  @param p pointer to HepMC3::GenParticle
+       */
+      IsAnAncestor( const HepMC3::ConstGenParticlePtr & p );
+      /// MANDATORY: clone method ("virtual constructor")
+      IsAnAncestor* clone() const override;
+      /// MANDATORY: the only one essential method
+      bool operator()( const HepMC3::ConstGenParticlePtr & p ) const override;
+      /// "SHORT" representation, @see LoKi::AuxFunBase
+      std::ostream& fillStream( std::ostream& s ) const override;
+      // ======================================================================
+    private:
+      // ======================================================================
+      const HepMC3::ConstGenParticlePtr m_particle;
+      // ======================================================================
+    };
+    // ========================================================================
+    /** @class HasQuark
+     *  simple predicate , return true if particle has quark 'quark'
+     *
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date   2006-01-18
+     */
+    class GAUDI_API HasQuark : public LoKi::GenTypes::GCuts {
+    public:
+      // ======================================================================
+      HasQuark( const LHCb::ParticleID::Quark quark );
+      /// clone method (mandatory!)
+      HasQuark* clone() const override;
+      /// the only one essential method
+      bool operator()( const HepMC3::ConstGenParticlePtr & p ) const override;
+      /// "SHORT" representation, @see LoKi::AuxFunBase
+      std::ostream&           fillStream( std::ostream& s ) const override;
+      LHCb::ParticleID::Quark quark() const { return m_quark; }
+      // ======================================================================
+    private:
+      // ======================================================================
+      LHCb::ParticleID::Quark m_quark;
+      // ======================================================================
+    };
+    // ========================================================================
+    /** @class IsCharged
+     *  simple predicate , return true of particle is charged
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date   2006-01-18
+     */
+    struct GAUDI_API IsCharged : LoKi::GenTypes::GCuts {
+      // ======================================================================
+      /// clone method (mandatory!)
+      IsCharged* clone() const override;
+      /// the only one essential method
+      bool operator()( const HepMC3::ConstGenParticlePtr & p ) const override;
+      /// "SHORT" representation, @see LoKi::AuxFunBase
+      std::ostream& fillStream( std::ostream& s ) const override;
+      // ======================================================================
+    };
+    // ========================================================================
+    /** @class IsNeutral
+     *  simple predicate , return true of particle is neutral
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date   2006-01-18
+     */
+    struct GAUDI_API IsNeutral : LoKi::GenTypes::GCuts {
+      // ======================================================================
+      /// clone method (mandatory!)
+      IsNeutral* clone() const override;
+      /// the only one essential method
+      bool operator()( const HepMC3::ConstGenParticlePtr & p ) const override;
+      /// "SHORT" representation, @see LoKi::AuxFunBase
+      std::ostream& fillStream( std::ostream& s ) const override;
+      // ======================================================================
+    };
+    // ========================================================================
+    /** @class IsLepton
+     *  simple predicate , return true if the particle is a lepton
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date   2006-01-18
+     */
+    struct GAUDI_API IsLepton : LoKi::GenTypes::GCuts {
+    public:
+      // ======================================================================
+      /// clone method (mandatory!)
+      IsLepton* clone() const override;
+      /// the only one essential method
+      bool operator()( const HepMC3::ConstGenParticlePtr & p ) const override;
+      /// "SHORT" representation, @see LoKi::AuxFunBase
+      std::ostream& fillStream( std::ostream& s ) const override;
+      // ======================================================================
+    };
+    // ========================================================================
+    /** @class IsMeson
+     *  simple predicate , return true if particle is a meson
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date   2006-01-18
+     */
+    struct GAUDI_API IsMeson : LoKi::GenTypes::GCuts {
+    public:
+      // ======================================================================
+      /// clone method (mandatory!)
+      IsMeson* clone() const override;
+      /// the only one essential method
+      bool operator()( const HepMC3::ConstGenParticlePtr & p ) const override;
+      /// "SHORT" representation, @see LoKi::AuxFunBase
+      std::ostream& fillStream( std::ostream& s ) const override;
+      // ======================================================================
+    };
+    // ========================================================================
+    /** @class IsBaryon
+     *  simple predicate , return true if the particle is a baryon
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date   2006-01-18
+     */
+    struct GAUDI_API IsBaryon : LoKi::GenTypes::GCuts {
+      // ======================================================================
+      /// clone method (mandatory!)
+      IsBaryon* clone() const override;
+      /// the only one essential method
+      bool operator()( const HepMC3::ConstGenParticlePtr & p ) const override;
+      /// "SHORT" representation, @see LoKi::AuxFunBase
+      std::ostream& fillStream( std::ostream& s ) const override;
+      // ======================================================================
+    };
+    // ========================================================================
+    /** @class IsHadron
+     *  simple predicate , return true of particle is hadron
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date   2006-01-18
+     */
+    struct GAUDI_API IsHadron : LoKi::GenTypes::GCuts {
+    public:
+      // ======================================================================
+      /// clone method (mandatory!)
+      IsHadron* clone() const override;
+      /// the only one essential method
+      bool operator()( const HepMC3::ConstGenParticlePtr & p ) const override;
+      /// "SHORT" representation, @see LoKi::AuxFunBase
+      std::ostream& fillStream( std::ostream& s ) const override;
+      // ======================================================================
+    };
+    // ========================================================================
+    /** @class IsNucleus
+     *  simple predicate , return true of particle is nucleus
+     *  @author Vanya BELYAEV Ivan.Belyaev@itep.ru
+     *  @date   2004-01-25
+     */
+    struct GAUDI_API IsNucleus : LoKi::GenTypes::GCuts {
+      // ======================================================================
+      /// clone method (mandatory!)
+      IsNucleus* clone() const override;
+      /// the only one essential method
+      bool operator()( const HepMC3::ConstGenParticlePtr & p ) const override;
+      /// "SHORT" representation, @see LoKi::AuxFunBase
+      std::ostream& fillStream( std::ostream& s ) const override;
+      // ======================================================================
+    };
+    // ========================================================================
+    /** @class ProperLifeTime
+     *  simple function which evaluate the
+     *  proper lifetime (c*tau) of the particle in HepMC3 units
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date 2006-01-18
+     */
+    class GAUDI_API ProperLifeTime : public LoKi::GenTypes::GFunc {
+    public:
+      // ======================================================================
+      /** constructor
+       *  @param bad the valut toi be returned for particles
+       *  where the evaluation end vertex is not possible
+       */
+      ProperLifeTime( const double bad = LoKi::Constants::InfiniteTime );
+      /// clone method (mandatory!)
+      ProperLifeTime* clone() const override;
+      /// the only one essential method
+      double operator()( const HepMC3::ConstGenParticlePtr & p ) const override;
+      /// "SHORT" representation, @see LoKi::AuxFunBase
+      std::ostream& fillStream( std::ostream& s ) const override;
+      // ======================================================================
+    private:
+      // ======================================================================
+      double m_bad;
+      // ======================================================================
+    };
+    // ========================================================================
+    /** @class NominalLifeTime
+     *  (c*tau) evaluator of the nominal lifetime of the particle
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date 2006-01-18
+     */
+    struct GAUDI_API NominalLifeTime : LoKi::GenTypes::GFunc {
+      // ======================================================================
+      /// clone method (mandatory!)
+      NominalLifeTime* clone() const override;
+      /// the only one essential method
+      double operator()( const HepMC3::ConstGenParticlePtr & p ) const override;
+      /// "SHORT" representation, @see LoKi::AuxFunBase
+      std::ostream& fillStream( std::ostream& s ) const override;
+      // ======================================================================
+    };
+    // ========================================================================
+    /** @class AdapterToProductionVertex
+     *
+     *  Simple adapter, which delegates the evaluation of
+     *  "vertex" funtion to "production vertex" of the particle:
+     *
+     *  @see LoKi::Cuts::GFAPVX
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date 2006-02-08
+     */
+    class GAUDI_API AdapterToProductionVertex : public LoKi::GenTypes::GFunc {
+    public:
+      // ======================================================================
+      /** constructor from vertex function and "bad" value
+       *  @param fun verted function to be used
+       *  @param bad the value to be returnedd for invalid vertex
+       */
+      AdapterToProductionVertex( const LoKi::Types::GVFunc& fun, const double bad );
+      /// clone method (mandatory!)
+      AdapterToProductionVertex* clone() const override;
+      /// the only one essential method
+      double operator()( const HepMC3::ConstGenParticlePtr & p ) const override;
+      /// "SHORT" representation, @see LoKi::AuxFunBase
+      std::ostream& fillStream( std::ostream& s ) const override;
+      // ======================================================================
+    private:
+      // ======================================================================
+      LoKi::Types::GVFun m_fun;
+      double             m_bad;
+      // ======================================================================
+    };
+    // ========================================================================
+    /** @class AdapterToEndVertex
+     *
+     *  Simple adapter, which delegates the evaluation of
+     *  "vertex" funtion to "end vertex" of the particle:
+     *
+     *  @see LoKi::Cuts::GFAEVX
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date 2006-02-08
+     */
+    class GAUDI_API AdapterToEndVertex : public LoKi::GenTypes::GFunc {
+    public:
+      // ======================================================================
+      /** constructor from vertex function and "bad" value
+       *  @param fun verted function to be used
+       *  @param bad the value to be returnedd for invalid vertex
+       */
+      AdapterToEndVertex( const LoKi::Types::GVFunc& fun, const double bad );
+      /// clone method (mandatory!)
+      AdapterToEndVertex* clone() const override;
+      /// the only one essential method
+      double operator()( const HepMC3::ConstGenParticlePtr & p ) const override;
+      /// "SHORT" representation, @see LoKi::AuxFunBase
+      std::ostream& fillStream( std::ostream& s ) const override;
+      // ======================================================================
+    private:
+      // ======================================================================
+      LoKi::Types::GVFun m_fun;
+      double             m_bad;
+      // ======================================================================
+    };
+    // ========================================================================
+    /** @class ThreeCharge
+     *  primitive function to extract the 3*charge from HepMC3::GenParticle
+     *
+     *   Algorithm:
+     *
+     *   pdg_id -> LHCb::ParticleID -> threeCharge
+     *
+     *  @see ParticleID
+     *  @see HepMC3::GenParticle
+     *  @see LoKi::Cuts::G3Q
+     *
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date   2006-03-07
+     */
+    struct GAUDI_API ThreeCharge : LoKi::GenTypes::GFunc {
+      // ======================================================================
+      /// MANDATORY: clone method ("virtual" constructor")
+      ThreeCharge* clone() const override { return new ThreeCharge( *this ); }
+      /// MANDATORY: the only one essential method
+      double operator()( const HepMC3::ConstGenParticlePtr & p ) const override;
+      /// "SHORT" representation, @see LoKi::AuxFunBase
+      std::ostream& fillStream( std::ostream& s ) const override;
+      // ======================================================================
+    };
+    // ========================================================================
+    /** @class NInTree
+     *  simple evaluator of number of particles in the tree
+     *  which satisfy a certain predicate
+     *
+     *  @warning current implementation is valid only for
+     *       HepMC3::parents, HepMC3::children,
+     *       HepMC3::ancestors and HepMC3::descendants
+     *
+     *  @code
+     *
+     *  // get Generator information
+     *  const HepMC3Events* events =
+     *          get<HepMC3Events>( HepMC3EventLocation::Default ) ;
+     *
+     *  typedef std::vector<HepMC3::ConstGenParticlePtr> GenParticles ;
+     *
+     *  // select b(and antib) quarks from decay of higgs
+     *  GenParticles bquarks ;
+     *  LoKi::Extract::genParticles
+     *   ( events                         ,
+     *     std::back_inserter( bquarks )  ,
+     *     ( "b" == GABSID ) &&
+     *    1 == GNINTREE( "H_10" == GABSID , HepMC3::parents ) ) ;
+     *
+     *  @endcode
+     *
+     *  @see const HepMC3::Relatives &
+     *  @see HepMC3::parents
+     *  @see HepMC3::GenParticle
+     *  @see HepMC3::GenVertex
+     *  @see LoKi::Cuts::GABSID
+     *  @see LoKi::Extract::getParticles
+     *  @see LoKi::Cuts::GNINTREE
+     *
+     *  @author Vanya BELYAEV belyaev@lapp.in2p3.fr
+     *  @date 2005-03-23
+     */
+    class GAUDI_API NInTree : public LoKi::GenTypes::GFunc {
+    public:
+      // ======================================================================
+      /** constructor
+       *  @param cut    predicate to be used for counting
+       *  @param range  "iterator range", see const HepMC3::Relatives &
+       *  @see const HepMC3::Relatives &
+       */
+      NInTree( const LoKi::GenTypes::GCuts& cut, const HepMC3::Relatives & range = HepMC3::Relatives::DESCENDANTS );
+      /// MANDATORY: clone function ("virtual constructor")
+      NInTree* clone() const override;
+      /// MANDATORY: the only one essential method
+      double operator()( const HepMC3::ConstGenParticlePtr & p ) const override;
+      /// "SHORT" representation, @see LoKi::AuxFunBase
+      std::ostream& fillStream( std::ostream& s ) const override;
+      // ======================================================================
+    protected:
+      // ======================================================================
+      /** count the particles in the tree according
+       *  the predicat eand iterator range
+       *  @see HepMC3::GenVertex
+       *  @param vertex  root of the tree
+       *  @return number of particles
+       */
+      size_t count( const HepMC3::ConstGenVertexPtr & vertex ) const;
+      size_t count( const HepMC3::ConstGenParticlePtr & particles ) const;
+      // ======================================================================
+    protected:
+      // ======================================================================
+      LoKi::GenTypes::GCut m_cut;
+      const HepMC3::Relatives & m_range;
+      // ======================================================================
+    };
+    // ========================================================================
+    /** @class MaxTree
+     *  simple evaluator maximal valeu of certain functor in the tree
+     *
+     *  @warning current implementation is valid only for
+     *       HepMC3::parents, HepMC3::children,
+     *       HepMC3::ancestors and HepMC3::descendants
+     *
+     *  @see const HepMC3::Relatives &
+     *  @see HepMC3::parents
+     *  @see HepMC3::GenParticle
+     *  @see HepMC3::GenVertex
+     *  @see LoKi::Cuts::GABSID
+     *  @see LoKi::Extract::getParticles
+     *  @see LoKi::Cuts::GMAXTREE
+     *
+     *  @author Vanya BELYAEV Ivan.Belyaev@itep.ru
+     *  @date 2018-06-12
+     */
+    class GAUDI_API MaxTree : public NInTree {
+    public:
+      // ======================================================================
+      /** constructor
+       *  @param cut    predicate to be used for counting
+       *  @param range  "iterator range", see const HepMC3::Relatives &
+       *  @see const HepMC3::Relatives &
+       */
+      MaxTree( const LoKi::GenTypes::GFunc& fun, const LoKi::GenTypes::GCuts& cut,
+          const HepMC3::Relatives & range = HepMC3::Relatives::DESCENDANTS);
+      /// MANDATORY: clone function ("virtual constructor")
+      MaxTree* clone() const override;
+      /// MANDATORY: the only one essential method
+      double operator()( const HepMC3::ConstGenParticlePtr & p ) const override;
+      /// "SHORT" representation, @see LoKi::AuxFunBase
+      std::ostream& fillStream( std::ostream& s ) const override;
+      // ======================================================================
+    protected:
+      // ======================================================================
+      LoKi::GenTypes::GFun m_fun;
+      // ======================================================================
+    };
+    // ========================================================================
+    /** @class MinTree
+     *  simple evaluator minimal value of certain functor in the tree
+     *
+     *  @warning current implementation is valid only for
+     *       HepMC3::parents, HepMC3::children,
+     *       HepMC3::ancestors and HepMC3::descendants
+     *
+     *  @see const HepMC3::Relatives &
+     *  @see HepMC3::parents
+     *  @see HepMC3::GenParticle
+     *  @see HepMC3::GenVertex
+     *  @see LoKi::Cuts::GABSID
+     *  @see LoKi::Extract::getParticles
+     *  @see LoKi::Cuts::GMINTREE
+     *
+     *  @author Vanya BELYAEV Ivan.Belyaev@itep.ru
+     *  @date 2018-06-12
+     */
+    class GAUDI_API MinTree : public MaxTree {
+    public:
+      // ======================================================================
+      /** constructor
+       *  @param cut    predicate to be used for counting
+       *  @param range  "iterator range", see const HepMC3::Relatives &
+       *  @see const HepMC3::Relatives &
+       */
+      MinTree( const LoKi::GenTypes::GFunc& fun, const LoKi::GenTypes::GCuts& cut,
+               const HepMC3::Relatives & range = HepMC3::Relatives::DESCENDANTS);
+      /// MANDATORY: clone function ("virtual constructor")
+      MinTree* clone() const override;
+      /// MANDATORY: the only one essential method
+      double operator()( const HepMC3::ConstGenParticlePtr & p ) const override;
+      /// "SHORT" representation, @see LoKi::AuxFunBase
+      std::ostream& fillStream( std::ostream& s ) const override;
+      // ======================================================================
+    };
+    // ========================================================================
+    /** @class SumTree
+     *  simple evaluato of sum over  certain functor values in the tree
+     *
+     *  @warning current implementation is valid only for
+     *       HepMC3::parents, HepMC3::children,
+     *       HepMC3::ancestors and HepMC3::descendants
+     *
+     *  @see const HepMC3::Relatives &
+     *  @see HepMC3::parents
+     *  @see HepMC3::GenParticle
+     *  @see HepMC3::GenVertex
+     *  @see LoKi::Cuts::GABSID
+     *  @see LoKi::Extract::getParticles
+     *  @see LoKi::Cuts::GSUMTREE
+     *
+     *  @author Vanya BELYAEV Ivan.Belyaev@itep.ru
+     *  @date 2018-06-12
+     */
+    class GAUDI_API SumTree : public MinTree {
+    public:
+      // ======================================================================
+      /** constructor
+       *  @param cut    predicate to be used for counting
+       *  @param range  "iterator range", see const HepMC3::Relatives &
+       *  @see const HepMC3::Relatives &
+       */
+      SumTree( const LoKi::GenTypes::GFunc& fun, const LoKi::GenTypes::GCuts& cut,
+               const HepMC3::Relatives & range = HepMC3::Relatives::DESCENDANTS);
+
+      /// MANDATORY: clone function ("virtual constructor")
+      SumTree* clone() const override;
+      /// MANDATORY: the only one essential method
+      double operator()( const HepMC3::ConstGenParticlePtr & p ) const override;
+      /// "SHORT" representation, @see LoKi::AuxFunBase
+      std::ostream& fillStream( std::ostream& s ) const override;
+      // ======================================================================
+    };
+    // ========================================================================
+    /** @class MultTree
+     *  simple evaluator of the product over  certain functor values in the tree
+     *
+     *  @warning current implementation is valid only for
+     *       HepMC3::parents, HepMC3::children,
+     *       HepMC3::ancestors and HepMC3::descendants
+     *
+     *  @see const HepMC3::Relatives &
+     *  @see HepMC3::parents
+     *  @see HepMC3::GenParticle
+     *  @see HepMC3::GenVertex
+     *  @see LoKi::Cuts::GABSID
+     *  @see LoKi::Extract::getParticles
+     *  @see LoKi::Cuts::GMULTTREE
+     *
+     *  @author Vanya BELYAEV Ivan.Belyaev@itep.ru
+     *  @date 2018-06-12
+     */
+    class GAUDI_API MultTree : public SumTree {
+    public:
+      // ======================================================================
+      /** constructor
+       *  @param cut    predicate to be used for counting
+       *  @param range  "iterator range", see const HepMC3::Relatives &
+       *  @see const HepMC3::Relatives &
+       */
+      MultTree( const LoKi::GenTypes::GFunc& fun, const LoKi::GenTypes::GCuts& cut,
+                const HepMC3::Relatives & range = HepMC3::Relatives::DESCENDANTS);
+      /// MANDATORY: clone function ("virtual constructor")
+      MultTree* clone() const override;
+      /// MANDATORY: the only one essential method
+      double operator()( const HepMC3::ConstGenParticlePtr & p ) const override;
+      /// "SHORT" representation, @see LoKi::AuxFunBase
+      std::ostream& fillStream( std::ostream& s ) const override;
+      // ======================================================================
+    };
+    // ========================================================================
+    /** @class InTree
+     *  The trivial predicate which evaluates to true
+     *  if there is at least one particle in the decay
+     *  tree of the given particle which satisfies the
+     *  certain criteria
+     *
+     *  The function uses the algorithm LoKi::GenAlgs::found
+     *
+     *  @see LoKi::GenAlgs::found
+     *  @see LoKi::Cuts::GINTREE
+     *
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date 2004-05-05
+     */
+    class GAUDI_API InTree : public LoKi::GenTypes::GCuts {
+    public:
+      /** standard constructor
+       *  @param cut cut to be checked
+       */
+      InTree( const LoKi::GenTypes::GCuts& cut );
+      /// MANDATORY: clone function ("virtual constructor")
+      InTree* clone() const override;
+      /// MANDATORY: the only one essential method
+      bool operator()( const HepMC3::ConstGenParticlePtr & p ) const override;
+      /// OPTIONAL: the specific printout
+      std::ostream& fillStream( std::ostream& s ) const override;
+
+    private:
+      // ======================================================================
+      /// the criteria itself:
+      LoKi::GenTypes::GCut m_cut; // the criteria itself
+      // ======================================================================
+    };
+    // ========================================================================
+    /** @class Oscillated
+     *  Simple class to check the oscillation of the particle
+     *  It evaluates to "true" for both particles
+     *  @see LoKi::GenParticles::oscillated1
+     *  @see LoKi::GenParticles::oscillated2
+     *  @see LoKi::Cuts::GOSCILLATED
+     *  @author Vanya BELYAEV Ivan.Belyaev@nkhef.nl
+     *  @date 2008-07-03
+     */
+    struct GAUDI_API Oscillated : LoKi::GenTypes::GCuts {
+      // ======================================================================
+      /// MANDATORY: clone method ("virtual constructor")
+      Oscillated* clone() const override;
+      /// MANDATORY: the only one essential method
+      bool operator()( const HepMC3::ConstGenParticlePtr & p ) const override;
+      /// OPTIONAL: the specific printout
+      std::ostream& fillStream( std::ostream& s ) const override;
+      // ======================================================================
+    };
+    // ========================================================================
+    /** @class Oscillated1
+     *  Simple class to check the oscillation of the particle
+     *  @see LoKi::GenParticles::oscillated1
+     *  @see LoKi::Cuts::GOSCILLATED1
+     *  @author Vanya BELYAEV Ivan.Belyaev@nkhef.nl
+     *  @date 2008-07-03
+     */
+    struct Oscillated1 : LoKi::GenTypes::GCuts {
+      // ======================================================================
+      /// MANDATORY: clone method ("virtual constructor")
+      Oscillated1* clone() const override;
+      /// MANDATORY: the only one essential method
+      bool operator()( const HepMC3::ConstGenParticlePtr & p ) const override;
+      /// OPTIONAL: the specific printout
+      std::ostream& fillStream( std::ostream& s ) const override;
+      // ======================================================================
+    };
+    // ========================================================================
+    /** @class Oscillated2
+     *  Simple class to check the oscillation of the particle
+     *  @see LoKi::GenParticles::oscillated2
+     *  @see LoKi::Cuts::GOSCILLATED2
+     *  @author Vanya BELYAEV Ivan.Belyaev@nkhef.nl
+     *  @date 2008-07-03
+     */
+    struct GAUDI_API Oscillated2 : LoKi::GenTypes::GCuts {
+      // ======================================================================
+      /// MANDATORY: clone method ("virtual constructor")
+      Oscillated2* clone() const override;
+      /// MANDATORY: the only one essential method
+      bool operator()( const HepMC3::ConstGenParticlePtr & p ) const override;
+      /// OPTIONAL: the specific printout
+      std::ostream& fillStream( std::ostream& s ) const override;
+      // ======================================================================
+    };
+    // ========================================================================
+    /** @class DecNode
+     *  simple predicate, which acts on the particleID of the particle
+     *  @see LHCb::ParticleID
+     *  @see Decays::iNode
+     *  @author Vanya BELYAEV Ivan.Belyaev@nikhef.nl
+     *  @date 2008-12-17
+     */
+    class GAUDI_API DecNode : public LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::Predicate {
+    public:
+      // ======================================================================
+      /// constructor from the actual node
+      DecNode( const Decays::iNode& node );
+      /// MANDATORY: clone method ("virtual constructor")
+      DecNode* clone() const override { return new DecNode( *this ); }
+      /// MANDATORY: the only one essential method
+      bool operator()( const HepMC3::ConstGenParticlePtr & p ) const override;
+      /// OPTIONAL: the nice printout
+      std::ostream& fillStream( std::ostream& s ) const override;
+      // ======================================================================
+      /// get the decay node
+      const Decays::iNode& node() const { return m_node.node(); }
+      /// valid node ?
+      bool valid() const { return m_node.valid(); }
+      // validate the node
+      StatusCode validate( const LHCb::IParticlePropertySvc* svc ) const { return m_node.validate( svc ); }
+      // ======================================================================
+    private:
+      // ======================================================================
+      /// the decay node itself
+      Decays::Node m_node; // the decay node itself
+      // ======================================================================
+    };
+    // ========================================================================
+    /** @class LongLived
+     *  simple predicate that select long-lived particles
+     *  @see LoKi::Cuts::GLOONGLIVED
+     *  @see LHCb::ParticleID
+     *  @see Decays::iNode
+     *  @see Decays::Nodes::LongLived_
+     *  @see LoKi::GenParticles::DecNode
+     *  @author Vanya BELYAEV Ivan.Belyaev@itep.ru
+     *  @date 2016-06-21
+     */
+    struct GAUDI_API LongLived : DecNode {
+      // ======================================================================
+      /// constructor
+      LongLived() : DecNode( Decays::Nodes::LongLived_() ) {}
+      /// MANDATORY: clone method ("virtual constructor")
+      LongLived* clone() const override;
+      /// OPTIONAL: the nice printout
+      std::ostream& fillStream( std::ostream& s ) const override;
+      // ======================================================================
+    };
+    // ========================================================================
+    /** @class DecTree
+     *  simple predicate, which acts on the decay structuire/tree for the particle
+     *  @see Decays::iTree
+     *  @author Vanya BELYAEV Ivan.Belyaev@nikhef.nl
+     *  @date 2008-12-17
+     */
+    class GAUDI_API DecTree : public LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::Predicate {
+    public:
+      // ======================================================================
+      /// the actual type of tree (interface
+      typedef Decays::iTree_<HepMC3::ConstGenParticlePtr> iTree; // the tree
+      // ======================================================================
+    private:
+      // ======================================================================
+      /// the actual type of tree (assignable)
+      typedef Decays::Tree_<HepMC3::ConstGenParticlePtr> Tree; // the tree
+      // ======================================================================
+    public:
+      // ======================================================================
+      /// constructor from the actual node
+      DecTree( const iTree& node, const bool autovalidate = true );
+      /// constructor from the decay descriptor
+      DecTree( const std::string& descriptor );
+      /// MANDATORY: clone method ("virtual constructor")
+      DecTree* clone() const override { return new DecTree( *this ); }
+      /// MANDATORY: the only one essential method
+      bool operator()( const HepMC3::ConstGenParticlePtr & p ) const override;
+      /// OPTIONAL: the nice printout
+      std::ostream& fillStream( std::ostream& s ) const override;
+      // ======================================================================
+    public:
+      // ======================================================================
+      /// get the decay node
+      const iTree& tree() const { return m_tree.tree(); }
+      // ======================================================================
+      /// valid tree ?
+      bool valid() const { return m_tree.valid(); }
+      // validate the teh tree
+      StatusCode validate( const LHCb::IParticlePropertySvc* svc ) const { return m_tree.validate( svc ); }
+      // reset the collection
+      void reset() const { m_tree.reset(); }
+      // ======================================================================
+    private:
+      // ======================================================================
+      /// the decay tree itself
+      Tree m_tree; // the decay tree itself
+      //
+      bool m_autovalidate;
+      // ======================================================================
+    };
+    // ========================================================================
+    /** @class ChildFun
+     *  adapter to child-function
+     *  @see LoKi::Cuts::GCHILD
+     *  @see LoKi::Cuts::GCHILDFUN
+     *  @author Vanya BELYAEV Ivan.Belyaev@cern.ch
+     *  @date   2011-12-11
+     */
+    class GAUDI_API ChildFun : public LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::Function {
+    public:
+      ChildFun( const LoKi::GenTypes::GFunc& fun, const LoKi::GenChild::Selector& selector );
+      /** constructor from the function and child selector
+       *  @param fun      the function to be used
+       *  @param selector the child selector
+       */
+      ChildFun( const LoKi::GenTypes::GFunc& fun, const std::string& selector );
+      /** constructor from the function and child selector
+       *  @param fun      the function to be used
+       *  @param selector the child selector
+       */
+      ChildFun( const LoKi::GenTypes::GFunc& fun, const Decays::IGenDecay::iTree& selector );
+      /** constructor from the function and child selector
+       *  @param fun      the function to be used
+       *  @param selector the child selector
+       */
+      ChildFun( const LoKi::GenTypes::GFunc& fun, const Decays::iNode& selector );
+      /** constructor from the function and child selector
+       *  @param fun      the function to be used
+       *  @param selector the child selector
+       */
+      ChildFun( const LoKi::GenTypes::GFunc& fun, const LoKi::GenTypes::GCuts& selector );
+      // ======================================================================
+      /// MANDATORY: clone method ("virtual constructor")
+      ChildFun* clone() const override;
+      /// MANDATORY: the only one essential method
+      double operator()( const HepMC3::ConstGenParticlePtr & p ) const override;
+      /// OPTIONAL:  specific printout
+      std::ostream& fillStream( std::ostream& s ) const override;
+      // ======================================================================
+    private:
+      // ======================================================================
+      /// the function itself
+      LoKi::GenTypes::GFun m_fun; // the function itself
+      /// the child selector
+      LoKi::GenChild::Selector m_child; //  the child selector
+      // ======================================================================
+    };
+    // ========================================================================
+    /** @class ChildCut
+     *  adapter to child-predicate
+     *  @see LoKi::Cuts::GCHILDCUT
+     *  @author Vanya BELYAEV Ivan.Belyaev@cern.ch
+     *  @date   2011-12-11
+     */
+    class GAUDI_API ChildCut : public LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::Predicate {
+    public:
+      /** constructor from the function and child selector
+       *  @param fun      the function to be used
+       *  @param selector the child selector
+       */
+      ChildCut( const LoKi::GenTypes::GCuts& fun, const LoKi::GenChild::Selector& selector );
+      /** constructor from the function and child selector
+       *  @param fun      the function to be used
+       *  @param selector the child selector
+       */
+      ChildCut( const LoKi::GenTypes::GCuts& fun, const std::string& selector );
+      /** constructor from the function and child selector
+       *  @param fun      the function to be used
+       *  @param selector the child selector
+       */
+      ChildCut( const LoKi::GenTypes::GCuts& fun, const Decays::IGenDecay::iTree& selector );
+      /** constructor from the function and child selector
+       *  @param fun      the function to be used
+       *  @param selector the child selector
+       */
+      ChildCut( const LoKi::GenTypes::GCuts& fun, const Decays::iNode& selector );
+      /** constructor from the function and child selector
+       *  @param fun      the function to be used
+       *  @param selector the child selector
+       */
+      ChildCut( const LoKi::GenTypes::GCuts& fun, const LoKi::GenTypes::GCuts& selector );
+      // ======================================================================
+      /// MANDATORY: clone method ("virtual constructor")
+      ChildCut* clone() const override;
+      /// MANDATORY: the only one essential method
+      bool operator()( const HepMC3::ConstGenParticlePtr & p ) const override;
+      /// OPTIONAL:  specific printout
+      std::ostream& fillStream( std::ostream& s ) const override;
+      // ======================================================================
+    private:
+      // ======================================================================
+      /// the function itself
+      LoKi::GenTypes::GCut m_fun; // the function itself
+      /// the child selector
+      LoKi::GenChild::Selector m_child; //  the child selector
+      // ======================================================================
+    };
+    // ========================================================================
+  } // namespace GenParticles
+  // ==========================================================================
+} //                                                      end of namespace LoKi
+// ============================================================================
+//                                                                      The END
+// ============================================================================
+#endif // LOKI_GENPARTICLES_H
diff --git a/Gen/LoKiGen/LoKi/GenParticles2.h b/Gen/LoKiGen/LoKi/GenParticles2.h
new file mode 100644
index 000000000..15a139593
--- /dev/null
+++ b/Gen/LoKiGen/LoKi/GenParticles2.h
@@ -0,0 +1,891 @@
+/*****************************************************************************\
+* (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration      *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                             *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+// ============================================================================
+#ifndef LOKI_GENPARTICLES2_H
+#define LOKI_GENPARTICLES2_H 1
+// ============================================================================
+// Include files
+// ============================================================================
+// Event
+// ============================================================================
+#include "HepMC3/GenEvent.h"
+#include "HepMC3/GenParticle.h"
+#include "HepMC3/GenVertex.h"
+#include "HepMC3/Relatives.h"
+// ============================================================================
+// LHCbKernel
+// ============================================================================
+#include "Kernel/ParticleID.h"
+#include "Kernel/iNode.h"
+// ============================================================================
+// LoKi
+// ============================================================================
+#include "LoKi/Constants.h"
+#include "LoKi/GenChildSelector.h"
+#include "LoKi/GenTypes.h"
+#include "LoKi/IGenDecay.h"
+#include "LoKi/Kinematics.h"
+#include "LoKi/iTree.h"
+// ============================================================================
+/** @file
+ *
+ *  This file is a part of LoKi project -
+ *    "C++ ToolKit  for Smart and Friendly Physics Analysis"
+ *
+ *  The package has been designed with the kind help from
+ *  Galina PAKHLOVA and Sergey BARSUK.  Many bright ideas,
+ *  contributions and advices from G.Raven, J.van Tilburg,
+ *  A.Golutvin, P.Koppenburg have been used in the design.
+ *
+ *  @author Vanya BELYAEV Ivan.Belyaev@itep.ru
+ *  @date 2006-01-23
+ *
+ */
+// ============================================================================
+namespace LoKi {
+  // ==========================================================================
+  namespace GenParticles {
+    // ========================================================================
+    /** @class PolarizationAngle
+     *  Simple functor that evaluates the polarization of daughter
+     *  (vector) particle in the rest system of mother particle
+     *
+     *  It is defined for the following decay topologies:
+     *
+     *   -  1 ->  ... +  1 + ... + 1 + ....
+     *   -  1 ->  ... +  ( 1 -> 1 + 1 ) +  ...
+     *
+     *  @see LoKi::Kinematics::decayAngle
+     *  @see LoKi::Kinematics::cosDecayAngle
+     *  @see IP2VVMCPartAngleCalculator
+     *  @see IP2VVAngleCalculator
+     *  @see IP2VVPartAngleCalculator
+     *  @see LoKi::Cuts::GCOSPOL
+     *  @see LoKi::MCParticles::PolarizationAngle
+     *  @see LoKi::Cuts::MCCOSPOL
+     *  @see LoKi::Particles::PolarizationAngle
+     *  @see LoKi::Cuts::COSPOL
+     *
+     *  @author Vanya BELYAEV Ivan.Belyaev@itep.ru
+     *  @date 2012-01-26
+     */
+    class GAUDI_API PolarizationAngle : public LoKi::GenTypes::GFunc {
+    public:
+      // ======================================================================
+      /// constructor from child selector
+      PolarizationAngle( const LoKi::GenChild::Selector& daughter, const LoKi::GenChild::Selector& parent,
+                         const bool mother = true );
+      /// constructor from two trees
+      PolarizationAngle( const Decays::IGenDecay::iTree& daughter, const Decays::IGenDecay::iTree& parent,
+                         const bool mother = true );
+      /// constructor from two nodes
+      PolarizationAngle( const Decays::iNode& daughter, const Decays::iNode& parent, const bool mother = true );
+      /// constructor from two functions
+      PolarizationAngle( const LoKi::GenTypes::GCuts& daughter, const LoKi::GenTypes::GCuts& parent,
+                         const bool mother = true );
+      /// constructor from two trees
+      PolarizationAngle( const std::string& daughter, const std::string& parent, const bool mother = true,
+                         const std::string& factory = "LoKi::GenDecay" );
+      /// MANDATORY: clone method ("virtual constructor")
+      PolarizationAngle* clone() const override;
+      /// MANDATORY: the only one essential method
+      double operator()( const HepMC3::ConstGenParticlePtr & p ) const override;
+      /// OPTIONAL: the nice printout
+      std::ostream& fillStream( std::ostream& s ) const override;
+      // ======================================================================
+    protected:
+      // ======================================================================
+      /// get the proper decay components
+      StatusCode getComponents12( const HepMC3::ConstGenParticlePtr & p, Decays::IGenDecay::iTree::Collection& vct ) const;
+      /// valid trees?
+      bool valid() const { return m_first.valid() && m_second.valid(); }
+      // ======================================================================
+    public:
+      // ======================================================================
+      /// the first child
+      const LoKi::GenChild::Selector& child1() const { return m_first; }
+      /// the second tree
+      const LoKi::GenChild::Selector& child2() const { return m_second; }
+      // ======================================================================
+    private:
+      // ======================================================================
+      /// rule to find the first  particle
+      LoKi::GenChild::Selector m_first; //  rule to find the first particle
+      /// rule to find the second pa rticle
+      LoKi::GenChild::Selector m_second; // rule to find the second particle
+      /// use (dauther-parent) or two-daughters rule ?
+      bool m_mother;
+      // ======================================================================
+    };
+    // ========================================================================
+    /** @class SinChi
+     *  Simple functor that evaluates the (sine) angle between the
+     *  decay planes of daughter particles
+     *
+     *  @see LoKi::Kinematics::sinDecayAngleChi
+     *  @see IP2VVAngleCalculator
+     *  @see IP2VVPartAngleCalculator
+     *  @see IP2VVMCPartAngleCalculator
+     *  @see LoKi::Cuts::GSINCHI
+     *  @see LoKi::Cuts::MCSINCHI
+     *  @see LoKi::Cuts::SINCHI
+     *
+     *  @attention It is very important to know the structure
+     *             of the decay for proper use of this functor
+     *
+     *  The angle is  calculated using the explicit
+     *   Lorentz-invariant expression:
+     *   \f[
+     *   \sin \chi =
+     *   \frac  {
+     *   \epsilon_{\mu\nu\lambda\delta}
+     *   L_D^{\mu}L_H^{\nu}H^{\lambda}M^{\delta} }
+     *   { \sqrt{
+     *   \left[ -L_D^2 \right]\left[ -L_H^2 \right]
+     *   \left[ \left( H\ cdot M\right)^2-H^2M^2 \right]
+     *   }} = \frac {
+     *   \epsilon_{\mu\nu\lambda\delta}
+     *   d_1^{\mu}d_2^{\nu}h_1^{\lambda}h_2^{\delta}
+     *   \left( \left( D \cdot H \right)^2 - D^2H^2 \right) }
+     *   { \sqrt{
+     *   \left[ -L_D^2 \right]\left[ -L_H^2    \right]
+     *   \left[ \left(H\cdot M\right)^2-H^2M^2 \right]
+     *   }},
+     *  \f]
+     *  where "4-normales" are defined as:
+     *  \f$
+     *  L_D^{\mu} = \epsilon_{\mu\nu\lambda\kappa}
+     *                d_1^{\nu}d_2^{\lambda}\left(h_1+h_2\right)^{\kappa}
+     *  \f$,
+     *  \f$
+     *  L_H^{\mu} = \epsilon_{\mu\lambda\delta\rho}
+     *  h_1^{\lambda}h_2^{\delta}\left(d_1+d_2\right)^{\rho}
+     *  \f$
+     *  and   \f$ D = d_1 + d_2 \f$,
+     *        \f$ H = h_1 + h_2 \f$,
+     *        \f$ M = D + H = d_1 + d_2 + h_1+h_2 \f$.
+     *
+     *  The sign for <c>sin</c> is set according to
+     *  Thomas Blake's code from
+     *  P2VVAngleCalculator tool
+     *  @see P2VVAngleCalculator
+     *
+     *  @author Vanya BELYAEV Ivan.Belyaev@itep.ru
+     *  @date 2011-01-28
+     */
+    // ========================================================================
+    class GAUDI_API SinChi : public PolarizationAngle {
+    public:
+      // ======================================================================
+      /// constructor from child-selector
+      SinChi( const LoKi::GenChild::Selector& particle1, const LoKi::GenChild::Selector& particle2,
+              const LoKi::GenChild::Selector& particle3, const LoKi::GenChild::Selector& particle4 );
+      /// constructor form the trees
+      SinChi( const Decays::IGenDecay::iTree& particle1, const Decays::IGenDecay::iTree& particle2,
+              const Decays::IGenDecay::iTree& particle3, const Decays::IGenDecay::iTree& particle4 );
+      /// constructor form the nodes
+      SinChi( const Decays::iNode& particle1, const Decays::iNode& particle2, const Decays::iNode& particle3,
+              const Decays::iNode& particle4 );
+      /// constructor form the cuts
+      SinChi( const LoKi::GenTypes::GCuts& particle1, const LoKi::GenTypes::GCuts& particle2,
+              const LoKi::GenTypes::GCuts& particle3, const LoKi::GenTypes::GCuts& particle4 );
+      /// constructor from the decay descriptors
+      SinChi( const std::string& particle1, const std::string& particle2, const std::string& particle3,
+              const std::string& particle4, const std::string& factory = "LoKi::GenDecay" );
+      /// MANDATORY: clone method ("virtual constructor")
+      SinChi* clone() const override;
+      /// MANDATORY: the only one essential method
+      double operator()( const HepMC3::ConstGenParticlePtr & p ) const override;
+      /// OPTIONAL: the nice printout
+      std::ostream& fillStream( std::ostream& s ) const override;
+      // ======================================================================
+    protected:
+      // ======================================================================
+      /// get the proper decay components
+      StatusCode getComponents34( const HepMC3::ConstGenParticlePtr & p, Decays::IGenDecay::iTree::Collection& vct ) const;
+      // ======================================================================
+    public:
+      // ======================================================================
+      /// get the proper decay components
+      StatusCode getComponents( const HepMC3::ConstGenParticlePtr & p, Decays::IGenDecay::iTree::Collection& vct ) const;
+      // ======================================================================
+    public:
+      // ======================================================================
+      const LoKi::GenChild::Selector& child3() const { return m_tree3; }
+      const LoKi::GenChild::Selector& child4() const { return m_tree4; }
+      // ======================================================================
+    private:
+      // ======================================================================
+      /// the tree to find the third  particle
+      LoKi::GenChild::Selector m_tree3; // the tree to find the third  particle
+      /// the tree to find the fourth particle
+      LoKi::GenChild::Selector m_tree4; // the tree to find the fourth particle
+      // ======================================================================
+    };
+    // ========================================================================
+    /** @class CosChi
+     *  Simple functor that evaluates the (cosine) angle between the
+     *  decay planes of daughter particles
+     *
+     *  @see LoKi::Kinematics::cosDecayAngleChi
+     *  @see IP2VVAngleCalculator
+     *  @see IP2VVPartAngleCalculator
+     *  @see LoKi::Cuts::MCCOSCHI
+     *
+     *  The angle is evaluated using the explicit
+     *  Lorenzt-invariant expression:
+     *  \f[
+     *  \cos \chi =
+     *   - \frac{ L_D^{\mu} L_H^{\mu} }
+     *     { \sqrt{ \left[ -L_D^2 \right]\left[ -L_H^2 \right] }},
+     &   =
+     *   - \frac{
+           *     \epsilon_{ijkl}d_1^{j}d_2^{k}\left(h_1+h_2\right)^l
+     *     \epsilon_{imnp}h_1^{m}h_2^{n}\left(d_1+d_2\right)^p }
+     *     { \sqrt{ \left[ -L_D^2 \right]\left[ -L_H^2 \right] }},
+     *  \f$
+     *  where "4-normales" are defined as:
+     *  \f$
+     *   L_D^{\mu} = \epsilon_{\mu\nu\lambda\kappa}
+     *                d_1^{\nu}d_2^{\lambda}\left(h_1+h_2\right)^{\kappa}
+     *  \f$
+     *   and
+     *  \f$
+     *   L_H^{\mu} = \epsilon_{\mu\lambda\delta\rho}
+     *                h_1^{\lambda}h_2^{\delta}\left(d_1+d_2\right)^{\rho}
+     *  \f].
+     *
+     *  @attention It is very important to know the structure
+     *             of the decay for proper use of this functor
+     *
+     *  @author Vanya BELYAEV Ivan.Belyaev@itep.ru
+     *  @date 2011-01-28
+     */
+    // ========================================================================
+    struct GAUDI_API CosChi : SinChi {
+      // ======================================================================
+      /// constructor from child-selector
+      CosChi( const LoKi::GenChild::Selector& particle1, const LoKi::GenChild::Selector& particle2,
+              const LoKi::GenChild::Selector& particle3, const LoKi::GenChild::Selector& particle4 );
+      /// constructor form the trees
+      CosChi( const Decays::IGenDecay::iTree& particle1, const Decays::IGenDecay::iTree& particle2,
+              const Decays::IGenDecay::iTree& particle3, const Decays::IGenDecay::iTree& particle4 );
+      /// constructor form the noeds
+      CosChi( const Decays::iNode& particle1, const Decays::iNode& particle2, const Decays::iNode& particle3,
+              const Decays::iNode& particle4 );
+      /// constructor form the cuts
+      CosChi( const LoKi::GenTypes::GCuts& particle1, const LoKi::GenTypes::GCuts& particle2,
+              const LoKi::GenTypes::GCuts& particle3, const LoKi::GenTypes::GCuts& particle4 );
+      /// constructor from the decay descriptors
+      CosChi( const std::string& particle1, const std::string& particle2, const std::string& particle3,
+              const std::string& particle4, const std::string& factory = "LoKi::GenDecay" );
+      /// MANDATORY: clone method ("virtual constructor")
+      CosChi* clone() const override;
+      /// MANDATORY: the only one essential method
+      double operator()( const HepMC3::ConstGenParticlePtr & p ) const override;
+      /// OPTIONAL: the nice printout
+      std::ostream& fillStream( std::ostream& s ) const override;
+      // ======================================================================
+    };
+    // ========================================================================
+    /** @class AngleChi
+     *  Simple functor that evaluates the angle between the
+     *  decay planes of daughter particles
+     *
+     *  @see LoKi::Kinematics::decayAngleChi
+     *  @see LoKi::Kinematics::sinDecayAngleChi
+     *  @see LoKi::Kinematics::cosDecayAngleChi
+     *  @see IP2VVAngleCalculator
+     *  @see IP2VVPartAngleCalculator
+     *  @see LoKi::Cuts::GANGLECHI
+     *  @see LoKi::Cuts::ANGLECHI
+     *  @see LoKi::Cuts::MCANGLECHI
+     *
+     *  @attention It is very important to know the structure
+     *             of the decay for proper use of this functor
+     *
+     *  @author Vanya BELYAEV Ivan.Belyaev@itep.ru
+     *  @date 2011-01-28
+     */
+    struct GAUDI_API AngleChi : CosChi {
+      // ======================================================================
+      /// constructor from child-selector
+      AngleChi( const LoKi::GenChild::Selector& particle1, const LoKi::GenChild::Selector& particle2,
+                const LoKi::GenChild::Selector& particle3, const LoKi::GenChild::Selector& particle4 );
+      /// constructor from the trees
+      AngleChi( const Decays::IGenDecay::iTree& particle1, const Decays::IGenDecay::iTree& particle2,
+                const Decays::IGenDecay::iTree& particle3, const Decays::IGenDecay::iTree& particle4 );
+      /// constructor from the nodes
+      AngleChi( const Decays::iNode& particle1, const Decays::iNode& particle2, const Decays::iNode& particle3,
+                const Decays::iNode& particle4 );
+      /// constructor form the cuts
+      AngleChi( const LoKi::GenTypes::GCuts& particle1, const LoKi::GenTypes::GCuts& particle2,
+                const LoKi::GenTypes::GCuts& particle3, const LoKi::GenTypes::GCuts& particle4 );
+      /// constructor from the decay descriptors
+      AngleChi( const std::string& particle1, const std::string& particle2, const std::string& particle3,
+                const std::string& particle4, const std::string& factory = "LoKi::GenDecay" );
+      /// MANDATORY: clone method ("virtual constructor")
+      AngleChi* clone() const override;
+      /// MANDATORY: the only one essential method
+      double operator()( const HepMC3::ConstGenParticlePtr & p ) const override;
+      /// OPTIONAL: the nice printout
+      std::ostream& fillStream( std::ostream& s ) const override;
+      // ======================================================================
+    };
+    // ========================================================================
+    /** @class CosThetaTr
+     *  Simple functor that evaluates the cosine of the
+     *  transverse angele theta, \f$\cos \theta_{\mathrm{tr}}\f$,
+     *
+     *  The evaluation is performed using the explicit Lorentz-invariant
+     *  expression:
+     *  \f[
+     *   \cos \theta_{\mathrm{tr}} =
+     *    \frac{ \epsilon_{\mu\nu\lambda\kappa}
+     *          d_1^{\mu}h_1^{\nu}h_2^{\lambda}L_H^{\kappa} }
+     *    {
+     *     \sqrt{  \left( d_1 \cdot D  \right) / D^2 - d_1^2 }
+     *     \sqrt{  - L_H^2 }
+     *    },
+     *  \f]
+     * where 4-normal \f$ L_H^{\mu}\f$ is defined as
+     *  \f$
+     *  L_H^{\mu} = \epsilon_{\mu\lambda\delta\rho}
+     *  h_1^{\lambda}h_2^{\delta}\left(d_1+d_2\right)^{\rho}
+     *  \f$, and \f$ D = d_1 + d_2 \f$.
+     *
+     *
+     *  @see LoKi::Kinematics::cosThetaTr
+     *  @see IP2VVAngleCalculator
+     *  @see IP2VVPartAngleCalculator
+     *  @see LoKi::Cuts::GCOSTHETATR
+     *  @see LoKi::Cuts::MCCOSTHETATR
+     *  @see LoKi::Cuts::COSTHETATR
+     *
+     *  @attention It is very important to know the structure
+     *             of the decay for proper use of this functor
+     *
+     *  @author Vanya BELYAEV Ivan.Belyaev@itep.ru
+     *  @date 2012-01-28
+     */
+    struct GAUDI_API CosThetaTr : AngleChi {
+      // ======================================================================
+      /// constructor from child-selector
+      CosThetaTr( const LoKi::GenChild::Selector& particle1, const LoKi::GenChild::Selector& particle2,
+                  const LoKi::GenChild::Selector& particle3, const LoKi::GenChild::Selector& particle4 );
+      /// constructor from the trees
+      CosThetaTr( const Decays::IGenDecay::iTree& particle1, const Decays::IGenDecay::iTree& particle2,
+                  const Decays::IGenDecay::iTree& particle3, const Decays::IGenDecay::iTree& particle4 );
+      /// constructor from the nodes
+      CosThetaTr( const Decays::iNode& particle1, const Decays::iNode& particle2, const Decays::iNode& particle3,
+                  const Decays::iNode& particle4 );
+      /// constructor form the cuts
+      CosThetaTr( const LoKi::GenTypes::GCuts& particle1, const LoKi::GenTypes::GCuts& particle2,
+                  const LoKi::GenTypes::GCuts& particle3, const LoKi::GenTypes::GCuts& particle4 );
+      /// constructor from the decay descriptors
+      CosThetaTr( const std::string& particle1, const std::string& particle2, const std::string& particle3,
+                  const std::string& particle4, const std::string& factory = "LoKi::GenDecay" );
+      /// MANDATORY: clone method ("virtual constructor")
+      CosThetaTr* clone() const override;
+      /// MANDATORY: the only one essential method
+      double operator()( const HepMC3::ConstGenParticlePtr & p ) const override;
+      /// OPTIONAL: the nice printout
+      std::ostream& fillStream( std::ostream& s ) const override;
+      // ======================================================================
+    };
+    // ========================================================================
+    /** @class SinPhiTr
+     *  Simple functor that evaluates the sine of the
+     *  transverse angel phi, \f$\sin \phi_{\mathrm{tr}}\f$,
+     *
+     *  The evaluation is performed using the explicit Lorentz-invariant
+     *  expression:
+     *  \f[
+     *   \sin \phi_{\mathrm{tr}} =
+     *    - frac {
+     *      \epsilon_{\mu\nu\lambda\kappa}
+     *       d_1^{\mu}L_H^{\mu}D^{\lambda}H^{\kappa}
+     *     }{
+     *     \sqrt{ -L^2 }
+     *     \sqrt{  D^2 }
+     *     \sqrt{ \left( q \cdot D  \right) / D^2 - q^2 }
+     *     \sqrt{ \left( M \cdot D  \right) / D^2 - M^2 }
+     *     }
+     *  \f]
+     * where 4-normal \f$ L_H^{\mu}\f$ is defined as
+     *  \f$
+     *  L_H^{\mu} = \epsilon_{\mu\lambda\delta\rho}
+     *  h_1^{\lambda}h_2^{\delta}\left(d_1+d_2\right)^{\rho}
+     *  \f$,
+     * \f$ D = d_1 + d_2 \f$,
+     * \f$ H = h_1 + h_2 \f$,
+     * \f$ M = D+ H \f$ and ``in-plane'' 4-vector \f$q\f$ is defined as
+     *  \f$  q = d_1 - \frac{ d_1 \cdot L_H}{L_H^2}L_H \f$.
+     *
+     *  @see LoKi::Kinematics::sinPhiTr
+     *  @see IP2VVAngleCalculator
+     *  @see IP2VVPartAngleCalculator
+     *  @see LoKi::Cuts::GSINPHITR
+     *  @see LoKi::Cuts::MCSINPHITR
+     *  @see LoKi::Cuts::SINPHITR
+     *
+     *  @attention It is very important to know the structure
+     *             of the decay for proper use of this functor
+     *
+     *  @author Vanya BELYAEV Ivan.Belyaev@itep.ru
+     *  @date 2012-01-20
+     */
+    struct GAUDI_API SinPhiTr : CosThetaTr {
+      // ======================================================================
+      /// constructor from child-selector
+      SinPhiTr( const LoKi::GenChild::Selector& particle1, const LoKi::GenChild::Selector& particle2,
+                const LoKi::GenChild::Selector& particle3, const LoKi::GenChild::Selector& particle4 );
+      /// constructor from the trees
+      SinPhiTr( const Decays::IGenDecay::iTree& particle1, const Decays::IGenDecay::iTree& particle2,
+                const Decays::IGenDecay::iTree& particle3, const Decays::IGenDecay::iTree& particle4 );
+      /// constructor from the nodes
+      SinPhiTr( const Decays::iNode& particle1, const Decays::iNode& particle2, const Decays::iNode& particle3,
+                const Decays::iNode& particle4 );
+      /// constructor from the cuts
+      SinPhiTr( const LoKi::GenTypes::GCuts& particle1, const LoKi::GenTypes::GCuts& particle2,
+                const LoKi::GenTypes::GCuts& particle3, const LoKi::GenTypes::GCuts& particle4 );
+      /// constructor from the decay descriptors
+      SinPhiTr( const std::string& particle1, const std::string& particle2, const std::string& particle3,
+                const std::string& particle4, const std::string& factory = "LoKi::GenDecay" );
+      /// MANDATORY: clone method ("virtual constructor")
+      SinPhiTr* clone() const override;
+      /// MANDATORY: the only one essential method
+      double operator()( const HepMC3::ConstGenParticlePtr & p ) const override;
+      /// OPTIONAL: the nice printout
+      std::ostream& fillStream( std::ostream& s ) const override;
+      // ======================================================================
+    };
+    // ========================================================================
+    /** @class CosPhiTr
+     *  Simple functor that evaluates the cosine of the
+     *  transverse angel phi, \f$\cos \phi_{\mathrm{tr}}\f$,
+     *
+     *  @see LoKi::Kinematics::cosPhiTr
+     *  @see IP2VVAngleCalculator
+     *  @see IP2VVPartAngleCalculator
+     *  @see LoKi::Cuts::GCOSPHITR
+     *  @see LoKi::Cuts::MCCOSPHITR
+     *  @see LoKi::Cuts::COSPHITR
+     *
+     *  @attention It is very important to know the structure
+     *             of the decay for proper use of this functor
+     *
+     *  @author Vanya BELYAEV Ivan.Belyaev@itep.ru
+     *  @date 2012-01-28
+     */
+    struct GAUDI_API CosPhiTr : SinPhiTr {
+      // ======================================================================
+      /// constructor from child-selector
+      CosPhiTr( const LoKi::GenChild::Selector& particle1, const LoKi::GenChild::Selector& particle2,
+                const LoKi::GenChild::Selector& particle3, const LoKi::GenChild::Selector& particle4 );
+      /// constructor from the trees
+      CosPhiTr( const Decays::IGenDecay::iTree& particle1, const Decays::IGenDecay::iTree& particle2,
+                const Decays::IGenDecay::iTree& particle3, const Decays::IGenDecay::iTree& particle4 );
+      /// constructor from the nodes
+      CosPhiTr( const Decays::iNode& particle1, const Decays::iNode& particle2, const Decays::iNode& particle3,
+                const Decays::iNode& particle4 );
+      /// constructor form the cuts
+      CosPhiTr( const LoKi::GenTypes::GCuts& particle1, const LoKi::GenTypes::GCuts& particle2,
+                const LoKi::GenTypes::GCuts& particle3, const LoKi::GenTypes::GCuts& particle4 );
+      /// constructor from the decay descriptors
+      CosPhiTr( const std::string& particle1, const std::string& particle2, const std::string& particle3,
+                const std::string& particle4, const std::string& factory = "LoKi::GenDecay" );
+      /// MANDATORY: clone method ("virtual constructor")
+      CosPhiTr* clone() const override;
+      /// MANDATORY: the only one essential method
+      double operator()( const HepMC3::ConstGenParticlePtr & p ) const override;
+      /// OPTIONAL: the nice printout
+      std::ostream& fillStream( std::ostream& s ) const override;
+      // ======================================================================
+    };
+    // ========================================================================
+    /** @class AnglePhiTr
+     *  Simple functor that evaluates the
+     *  transverse angel phi, \f$\phi_{\mathrm{tr}}\f$,
+     *
+     *  @see LoKi::Kinematics::anglePhiTr
+     *  @see IP2VVAngleCalculator
+     *  @see IP2VVPartAngleCalculator
+     *  @see LoKi::Cuts::GANGLEPHITR
+     *  @see LoKi::Cuts::MCANGLEPHITR
+     *  @see LoKi::Cuts::ANGLEPHITR
+     *
+     *  @attention It is very important to know the structure
+     *             of the decay for proper use of this functor
+     *
+     *  @author Vanya BELYAEV Ivan.Belyaev@itep.ru
+     *  @date 2012-01-28
+     */
+    struct GAUDI_API AnglePhiTr : CosPhiTr {
+      // ======================================================================
+      /// constructor from child-selector
+      AnglePhiTr( const LoKi::GenChild::Selector& particle1, const LoKi::GenChild::Selector& particle2,
+                  const LoKi::GenChild::Selector& particle3, const LoKi::GenChild::Selector& particle4 );
+      /// constructor from the trees
+      AnglePhiTr( const Decays::IGenDecay::iTree& particle1, const Decays::IGenDecay::iTree& particle2,
+                  const Decays::IGenDecay::iTree& particle3, const Decays::IGenDecay::iTree& particle4 );
+      /// constructor from the nodes
+      AnglePhiTr( const Decays::iNode& particle1, const Decays::iNode& particle2, const Decays::iNode& particle3,
+                  const Decays::iNode& particle4 );
+      /// constructor form the cuts
+      AnglePhiTr( const LoKi::GenTypes::GCuts& particle1, const LoKi::GenTypes::GCuts& particle2,
+                  const LoKi::GenTypes::GCuts& particle3, const LoKi::GenTypes::GCuts& particle4 );
+      /// constructor from the decay descriptors
+      AnglePhiTr( const std::string& particle1, const std::string& particle2, const std::string& particle3,
+                  const std::string& particle4, const std::string& factory = "LoKi::GenDecay" );
+      /// MANDATORY: clone method ("virtual constructor")
+      AnglePhiTr* clone() const override;
+      /// MANDATORY: the only one essential method
+      double operator()( const HepMC3::ConstGenParticlePtr & p ) const override;
+      /// OPTIONAL: the nice printout
+      std::ostream& fillStream( std::ostream& s ) const override;
+      // ======================================================================
+    };
+    // ========================================================================
+  } // namespace GenParticles
+  // ==========================================================================
+  namespace Cuts {
+    // ========================================================================
+    /** @typedef GCOSPOL
+     *
+     *   Evaluate polarization of  J/psi from B-decays
+     *   @code
+     *
+     *   const GCOSPOL cosPol = GCOSPOL (
+     *             "Xb ==>  ( J/psi(1S) => ^mu+ mu- ) ... " ,
+     *             "Xb ==> ^( J/psi(1S) =>  mu+ mu- ) ... " ) ;
+     *
+     *   HepMC3::ConstGenParticlePtr mcp = ... ;
+     *
+     *   const double value = cosPol ( mcp ) ;
+     *
+     *   @endcode
+     *
+     *  @see LoKi::Kinematics::decayAngle
+     *  @see LoKi::GenParticles::PolarizationAngle
+     *  @see LoKi::MCParticles::PolarizationAngle
+     *  @see LoKi::Particles::PolarizationAngle
+     *  @see LoKi::Cuts::MCCOSPOL
+     *  @see LoKi::Cuts::COSPOL
+     *  @author Vaanya BELYAEV Ivan.Belyaev@itep.ru
+     *  @date 2012-01-26
+     */
+    typedef LoKi::GenParticles::PolarizationAngle GCOSPOL;
+    // ========================================================================
+    /** @typedef GSINCHI
+     *  evaluator of sine of the angle chi
+     *
+     *   @code
+     *
+     *   const GSINCHI sinChi = GSINCHI (
+     *             "Xb ==> ( J/psi(1S) => ^mu+  mu- ) ( phi(1020) =>  K+  K- ) " ,
+     *             "Xb ==> ( J/psi(1S) =>  mu+ ^mu- ) ( phi(1020) =>  K+  K- ) " ,
+     *             "Xb ==> ( J/psi(1S) =>  mu+  mu- ) ( phi(1020) => ^K+  K- ) " ,
+     *             "Xb ==> ( J/psi(1S) =>  mu+  mu- ) ( phi(1020) =>  K+ ^K- ) " ) ;
+     *
+     *   HepMC3::ConstGenParticlePtr mcp = ... ;
+     *
+     *   const double value = sinChi ( mcp ) ;
+     *
+     *   @endcode
+     *
+     *  The angle is  calculated using the explicit
+     *   Lorentz-invariant expression:
+     *
+     *  \f$
+     *   \sin \chi =
+     *   \frac  {
+     *   \epsilon_{\mu\nu\lambda\delta}
+     *   L_D^{\mu}L_H^{\nu}H^{\lambda}M^{\delta} }
+     *   { \sqrt{
+     *   \left[ -L_D^2 \right]\left[ -L_H^2 \right]
+     *   \left[ \left( H\ cdot M\right)^2-H^2M^2 \right]
+     *   }} = \frac {
+     *   \epsilon_{\mu\nu\lambda\delta}
+     *   d_1^{\mu}d_2^{\nu}h_1^{\lambda}h_2^{\delta}
+     *   \left( \left( D \cdot H \right)^2 - D^2H^2 \right) }
+     *   { \sqrt{
+     *   \left[ -L_D^2 \right]\left[ -L_H^2    \right]
+     *   \left[ \left(H\cdot M\right)^2-H^2M^2 \right]
+     *   }},
+     * \f$
+     *  where "4-normales" are defined as:
+     *  \f$
+     *  L_D^{\mu} = \epsilon_{\mu\nu\lambda\kappa}
+     *                d_1^{\nu}d_2^{\lambda}\left(h_1+h_2\right)^{\kappa}
+     *  \f$,
+     *  \f$
+     *  L_H^{\mu} = \epsilon_{\mu\lambda\delta\rho}
+     *  h_1^{\lambda}h_2^{\delta}\left(d_1+d_2\right)^{\rho}
+     *  \f$
+     *  and   \f$ D = d_1 + d_2 \f$,
+     *        \f$ H = h_1 + h_2 \f$,
+     *        \f$ M = D + H = d_1 + d_2 + h_1+h_2 \f$.
+     *
+     *  The sign for <c>sin</c> is set according to
+     *  Thomas Blake's code from
+     *  P2VVAngleCalculator tool
+     *  @see P2VVAngleCalculator
+     *
+     *  @see LoKi::Kinematics::sinDecayAngelChi
+     *  @see LoKi::GenParticles::SinChi
+     *  @see LoKi::MCParticles::SinChi
+     *  @see LoKi::Particles::SinChi
+     *  @author Vanya BELYAEV Ivan.Belyaev@itep.ru
+     *  @date 2012-01-28
+     */
+    typedef LoKi::GenParticles::SinChi GSINCHI;
+    // ========================================================================
+    /** @typedef GCOSCHI
+     *  evaluator of cosine of the angle chi
+     *
+     *
+     *   @code
+     *
+     *   const GCOSCHI cosChi = GCOSCHI (
+     *             "Xb ==> ( J/psi(1S) => ^mu+  mu- ) ( phi(1020) =>  K+  K- ) " ,
+     *             "Xb ==> ( J/psi(1S) =>  mu+ ^mu- ) ( phi(1020) =>  K+  K- ) " ,
+     *             "Xb ==> ( J/psi(1S) =>  mu+  mu- ) ( phi(1020) => ^K+  K- ) " ,
+     *             "Xb ==> ( J/psi(1S) =>  mu+  mu- ) ( phi(1020) =>  K+ ^K- ) " ) ;
+     *
+     *   HepMC3::ConstGenParticlePtr mcp = ... ;
+     *
+     *   const double value = cosChi ( mcp ) ;
+     *
+     *   @endcode
+     *
+     *  The angle is evaluated using the explicit
+     *  Lorenzt-invariant expression:
+     *  \f[
+     *  \cos \chi =
+     *   - \frac{ L_D^{\mu} L_H^{\mu} }
+     *     { \sqrt{ \left[ -L_D^2 \right]\left[ -L_H^2 \right] }},
+     *   =
+     *   - \frac{
+     *     \epsilon_{ijkl}d_1^{j}d_2^{k}\left(h_1+h_2\right)^l
+     *     \epsilon_{imnp}h_1^{m}h_2^{n}\left(d_1+d_2\right)^p }
+     *     { \sqrt{ \left[ -L_D^2 \right]\left[ -L_H^2 \right] }},
+     *  \f]
+     *  where "4-normales" are defined as:
+     *  \f$
+     *   L_D^{\mu} = \epsilon_{\mu\nu\lambda\kappa}
+     *                d_1^{\nu}d_2^{\lambda}\left(h_1+h_2\right)^{\kappa}
+     *  \f$
+     *   and
+     *  \f$
+     *   L_H^{\mu} = \epsilon_{\mu\lambda\delta\rho}
+     *                h_1^{\lambda}h_2^{\delta}\left(d_1+d_2\right)^{\rho}
+     *   \f$.
+     *
+     *  @see LoKi::GenParticles::CosChi
+     *  @see LoKi::MCParticles::CosChi
+     *  @see LoKi::Particles::CosChi
+     *  @author Vanya BELYAEV Ivan.Belyaev@itep.ru
+     *  @date 2012-01-28
+     */
+    typedef LoKi::GenParticles::CosChi GCOSCHI;
+    // ========================================================================
+    /** @typedef GANGLECHI
+     *  evaluator of the angle chi
+     *
+     *   @code
+     *
+     *   const GANGLECHI chi = GANGLECHI (
+     *             "Xb ==> ( J/psi(1S) => ^mu+  mu- ) ( phi(1020) =>  K+  K- ) " ,
+     *             "Xb ==> ( J/psi(1S) =>  mu+ ^mu- ) ( phi(1020) =>  K+  K- ) " ,
+     *             "Xb ==> ( J/psi(1S) =>  mu+  mu- ) ( phi(1020) => ^K+  K- ) " ,
+     *             "Xb ==> ( J/psi(1S) =>  mu+  mu- ) ( phi(1020) =>  K+ ^K- ) " ) ;
+     *
+     *   HepMC3::ConstGenParticlePtr mcp = ... ;
+     *
+     *   const double value = chi ( mcp ) ;
+     *
+     *   @endcode
+     *
+     *  @see LoKi::Kinematics::decayAngleChi
+     *  @see LoKi::GenParticles::AngleChi
+     *  @see LoKi::MCParticles::AngleChi
+     *  @see LoKi::Particles::AngleChi
+     *  @see LoKi::Cuts::MCSINCHI
+     *  @see LoKi::Cuts::MCCOSCHI
+     *  @see LoKi::Cuts::GSINCHI
+     *  @see LoKi::Cuts::GCOSCHI
+     *  @see LoKi::Cuts::SINCHI
+     *  @see LoKi::Cuts::COSCHI
+     *  @author Vanya BELYAEV Ivan.Belyaev@itep.ru
+     *  @date 2012-01-28
+     */
+    typedef LoKi::GenParticles::AngleChi GANGLECHI;
+    // ========================================================================
+    /** @typedef GCOSTHETATR
+     *  Simple evaluator of \f$ \cos \theta_{\mathrm{tr}}\f$
+     *
+     *   @code
+     *
+     *   const GCOSTHETATR cosThetaTr = GCOSTHETATR (
+     *             "Xb ==> ( J/psi(1S) => ^mu+  mu- ) ( phi(1020) =>  K+  K- ) " ,
+     *             "Xb ==> ( J/psi(1S) =>  mu+ ^mu- ) ( phi(1020) =>  K+  K- ) " ,
+     *             "Xb ==> ( J/psi(1S) =>  mu+  mu- ) ( phi(1020) => ^K+  K- ) " ,
+     *             "Xb ==> ( J/psi(1S) =>  mu+  mu- ) ( phi(1020) =>  K+ ^K- ) " ) ;
+     *
+     *   HepMC3::ConstGenParticlePtr mcp = ... ;
+     *
+     *   const double value = cosThetaTr ( mcp ) ;
+     *
+     *   @endcode
+     *
+     *  The evaluation is performed using the explicit Lorentz-invariant
+     *  expression:
+     *  \f[
+     *   \cos \theta_{\mathrm{tr}} =
+     *    \frac{ \epsilon_{\mu\nu\lambda\kappa}
+     *          d_1^{\mu}h_1^{\nu}h_2^{\lambda}L_H^{\kappa} }
+     *    {
+     *     \sqrt{  \left( d_1 \cdot D  \right) / D^2 - d_1^2 }
+     *     \sqrt{  - L_H^2 }
+     *    },
+     *  \f]
+     * where 4-normal \f$ L_H^{\mu}\f$ is defined as
+     *  \f$
+     *  L_H^{\mu} = \epsilon_{\mu\lambda\delta\rho}
+     *  h_1^{\lambda}h_2^{\delta}\left(d_1+d_2\right)^{\rho}
+     *  \f$, and \f$ D = d_1 + d_2 \f$.
+     *
+     *  @see LoKi::MCParticles::CosThetaTr
+     *  @see LoKi::Kinematics::cosThetaTr
+     *  @author Vanya BELYAEV Ivan.Belyaev@nikhef.nl
+     *  @date 2010-06-02
+     */
+    typedef LoKi::GenParticles::CosThetaTr GCOSTHETATR;
+    // ========================================================================
+    /** @typedef GSINPHITR
+     *  Simple evaluator of \f$ \sin \phi_{\mathrm{tr}}\f$
+     *
+     *   @code
+     *
+     *   const GSINPHITR sinPhiTr = GSINPHITR (
+     *             "Xb ==> ( J/psi(1S) => ^mu+  mu- ) ( phi(1020) =>  K+  K- ) " ,
+     *             "Xb ==> ( J/psi(1S) =>  mu+ ^mu- ) ( phi(1020) =>  K+  K- ) " ,
+     *             "Xb ==> ( J/psi(1S) =>  mu+  mu- ) ( phi(1020) => ^K+  K- ) " ,
+     *             "Xb ==> ( J/psi(1S) =>  mu+  mu- ) ( phi(1020) =>  K+ ^K- ) " ) ;
+     *
+     *   HepMC3::ConstGenParticlePtr mcp = ... ;
+     *
+     *   const double value = sinPhiTr ( mcp ) ;
+     *
+     *   @endcode
+     *
+     *  The evaluation is performed using the explicit Lorentz-invariant
+     *  expression:
+     *  \f[
+     *   \sin \phi_{\mathrm{tr}} =
+     *    - frac {
+     *      \epsilon_{\mu\nu\lambda\kappa}
+     *       d_1^{\mu}L_H^{\mu}D^{\lambda}H^{\kappa}
+     *     }{
+     *     \sqrt{ -L^2 }
+     *     \sqrt{  D^2 }
+     *     \sqrt{ \left( q \cdot D  \right) / D^2 - q^2 }
+     *     \sqrt{ \left( M \cdot D  \right) / D^2 - M^2 }
+     *     }
+     *  \f]
+     * where 4-normal \f$ L_H^{\mu}\f$ is defined as
+     *  \f$
+     *  L_H^{\mu} = \epsilon_{\mu\lambda\delta\rho}
+     *  h_1^{\lambda}h_2^{\delta}\left(d_1+d_2\right)^{\rho}
+     *  \f$,
+     * \f$ D = d_1 + d_2 \f$,
+     * \f$ H = h_1 + h_2 \f$,
+     * \f$ M = D+ H \f$ and ``in-plane'' 4-vector \f$q\f$ is defined as
+     *  \f$  q = d_1 - \frac{ d_1 \cdot L_H}{L_H^2}L_H \f$.
+     *
+     *  @see LoKi::GenParticles::SinPhiTr
+     *  @see LoKi::MCParticles::SinPhiTr
+     *  @see LoKi::Particles::SinPhiTr
+     *  @see LoKi::Kinematics::sinPhiTr
+     *  @author Vanya BELYAEV Ivan.Belyaev@itep.ru
+     *  @date 2012-01-28
+     */
+    typedef LoKi::GenParticles::SinPhiTr GSINPHITR;
+    // ========================================================================
+    /** @typedef GCOSPHITR
+     *  Simple evaluator of \f$ \cos \phi_{\mathrm{tr}}\f$
+     *
+     *   @code
+     *
+     *   const GCOSPHITR cosPhiTr = GCOSPHITR (
+     *             "Xb ==> ( J/psi(1S) => ^mu+  mu- ) ( phi(1020) =>  K+  K- ) " ,
+     *             "Xb ==> ( J/psi(1S) =>  mu+ ^mu- ) ( phi(1020) =>  K+  K- ) " ,
+     *             "Xb ==> ( J/psi(1S) =>  mu+  mu- ) ( phi(1020) => ^K+  K- ) " ,
+     *             "Xb ==> ( J/psi(1S) =>  mu+  mu- ) ( phi(1020) =>  K+ ^K- ) " ) ;
+     *
+     *   HepMC3::ConstGenParticlePtr mcp = ... ;
+     *
+     *   const double value = cosPhiTr ( mcp ) ;
+     *
+     *   @endcode
+     *
+     *  The evaluation is performed using the explicit Lorentz-invariant
+     *  expression as angle between the ``in-plane'' vector \f$q\f$, and
+     *  vector \f$H\f$ in rest frame of \f$D\f$, where
+     *  \f$  q = d_1 - \frac{ d_1 \cdot L_H}{L_H^2}L_H \f$,
+     *  the ``4-normal'' is defiend as
+     *  \f$  L_H^{\mu} = \epsilon_{\mu\lambda\delta\rho}
+     *  h_1^{\lambda}h_2^{\delta}\left(d_1+d_2\right)^{\rho}
+     *  \f$, \f$ D = d_1 + d_2 \f$, \f$ H = h_1 + h_2 \f$.
+     *
+     *  @see LoKi::GenParticles::CosPhiTr
+     *  @see LoKi::MCParticles::CosPhiTr
+     *  @see LoKi::Particles::CosPhiTr
+     *  @see LoKi::Kinematics::cosPhiTr
+     *  @author Vanya BELYAEV Ivan.Belyaev@nikhef.nl
+     *  @date 2010-06-02
+     */
+    typedef LoKi::GenParticles::CosPhiTr GCOSPHITR;
+    // ========================================================================
+    /** @typedef GANGLEPHITR
+     *  Simple evaluator of \f$ \phi_{\mathrm{tr}}\f$
+     *
+     *   @code
+     *
+     *   const GANGLEPHITR phiTr = GANGLEPHITR (
+     *             "Xb ==> ( J/psi(1S) => ^mu+  mu- ) ( phi(1020) =>  K+  K- ) " ,
+     *             "Xb ==> ( J/psi(1S) =>  mu+ ^mu- ) ( phi(1020) =>  K+  K- ) " ,
+     *             "Xb ==> ( J/psi(1S) =>  mu+  mu- ) ( phi(1020) => ^K+  K- ) " ,
+     *             "Xb ==> ( J/psi(1S) =>  mu+  mu- ) ( phi(1020) =>  K+ ^K- ) " ) ;
+     *
+     *   HepMC3::ConstGenParticlePtr mcp = ... ;
+     *
+     *   const double value = phiTr ( mcp ) ;
+     *
+     *   @endcode
+     *
+     *  @see LoKi::GenParticles::AnglePhiTr
+     *  @see LoKi::MCParticles::AnglePhiTr
+     *  @see LoKi::Particles::AnglePhiTr
+     *  @see LoKi::Kinematics::anglePhiTr
+     *  @author Vanya BELYAEV Ivan.Belyaev@nikhef.nl
+     *  @date 2010-06-02
+     */
+    typedef LoKi::GenParticles::AnglePhiTr GANGLEPHITR;
+    // ========================================================================
+  } // namespace Cuts
+  // ==========================================================================
+} // namespace LoKi
+// ============================================================================
+//                                                                      The END
+// ============================================================================
+#endif // LOKI_GENPARTICLES2_H
diff --git a/Gen/LoKiGen/LoKi/GenParticles3.h b/Gen/LoKiGen/LoKi/GenParticles3.h
new file mode 100644
index 000000000..01fb0c92b
--- /dev/null
+++ b/Gen/LoKiGen/LoKi/GenParticles3.h
@@ -0,0 +1,177 @@
+/*****************************************************************************\
+* (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration      *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                             *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+// ============================================================================
+#ifndef LOKI_GENPARTICLES3_H
+#define LOKI_GENPARTICLES3_H 1
+// ============================================================================
+// Include files
+// ============================================================================
+// Event
+// ============================================================================
+#include "HepMC3/GenEvent.h"
+#include "HepMC3/GenParticle.h"
+#include "HepMC3/GenVertex.h"
+#include "HepMC3/Relatives.h"
+// ============================================================================
+// LoKi
+// ============================================================================
+#include "LoKi/GenTypes.h"
+// ============================================================================
+/** @file
+ *
+ *  This file is a part of LoKi project -
+ *    "C++ ToolKit  for Smart and Friendly Physics Analysis"
+ *
+ *  The package has been designed with the kind help from
+ *  Galina PAKHLOVA and Sergey BARSUK.  Many bright ideas,
+ *  contributions and advices from G.Raven, J.van Tilburg,
+ *  A.Golutvin, P.Koppenburg have been used in the design.
+ *
+ *  @author Vanya BELYAEV Ivan.Belyaev@itep.ru
+ *  @date 2012-01-28
+ *
+ */
+// ============================================================================
+namespace LoKi {
+  // ==========================================================================
+  namespace GenParticles {
+    // ========================================================================
+    /** @class Count
+     *  simple class which counts how many particles
+     *  satisfy the certain criteria
+     *
+     *  @see LoKi::Cuts::GCOUNT
+     *  @see HepMC3::GenParticle
+     *  @see HepMC3::GenVertex
+     *
+     *  @author Vanya BELYAEV belyaev@itep.ru
+     *  @date   2012-01-28
+     */
+    class GAUDI_API Count : public LoKi::GenTypes::GFunc {
+    public:
+      // ======================================================================
+      /** constructor from the criteria and "range"
+       *  @param cut the criteria
+       *  @param range search region
+       *  @see const HepMC3::Relatives &
+       */
+      Count( const LoKi::Types::GCuts& cut, const HepMC3::Relatives & range );
+      /** constructor from the criteria and "range"
+       *  @param range search region
+       *  @param cut the criteria
+       *  @see const HepMC3::Relatives &
+       */
+      Count( const HepMC3::Relatives & range, const LoKi::Types::GCuts& cut );
+      // ======================================================================
+      /// MANDATORY: clone method ("virtual contructor")
+      Count* clone() const override;
+      /// MANDATORY: the only one essential method
+      double operator()( const HepMC3::ConstGenParticlePtr & v ) const override;
+      /// OPTIONAL: nice printout
+      std::ostream& fillStream( std::ostream& s ) const override;
+      // ======================================================================
+    private:
+      // ======================================================================
+      LoKi::Types::GCut    m_cut;
+      const HepMC3::Relatives & m_range;
+      // ======================================================================
+    };
+    // ========================================================================
+    /** @class Has
+     *  simple class which check the presence of particles
+     *  satisfy the certain criteria
+     *
+     *  @see LoKi::Cuts::GHAS
+     *  @see HepMC3::GenParticle
+     *  @see HepMC3::GenVertex
+     *
+     *  @author Vanya BELYAEV belyaev@itep.ru
+     *  @date   2012-01-28
+     */
+    class GAUDI_API Has : public LoKi::GenTypes::GCuts {
+    public:
+      // ======================================================================
+      /** constructor from the criteria and "range"
+       *  @param cut the criteria
+       *  @param range search region
+       *  @see const HepMC3::Relatives &
+       */
+      Has( const LoKi::Types::GCuts& cut, const HepMC3::Relatives & range );
+      /** constructor from the criteria and "range"
+       *  @param range search region
+       *  @param cut the criteria
+       *  @see const HepMC3::Relatives &
+       */
+      Has( const HepMC3::Relatives & range, const LoKi::Types::GCuts& cut );
+      // ======================================================================
+      /// MANDATORY: clone method ("virtual contructor")
+      Has* clone() const override;
+      /// MANDATORY: the only one essential method
+      bool operator()( const HepMC3::ConstGenParticlePtr & v ) const override;
+      /// OPTIONAL: nice printout
+      std::ostream& fillStream( std::ostream& s ) const override;
+      // ======================================================================
+    private:
+      // ======================================================================
+      LoKi::Types::GCut    m_cut;
+      const HepMC3::Relatives & m_range;
+      // ======================================================================
+    };
+    // ========================================================================
+  } // namespace GenParticles
+  // ==========================================================================
+  namespace Cuts {
+    // ========================================================================
+    /** @typedef GCOUNT
+     *  simple functor to count certain particles in HepMC3-graph
+     *
+     *  @code
+     *
+     *   const GCOUNT cnt = GCOUNT ( "pi+" == GABSID , HepMC3.descendents ) ;
+     *
+     *   HepMC3::ConstGenParticlePtr p = ... ;
+     *
+     *   const double numPi = cnt ( p ) ;
+     *
+     *  @endcode
+     *
+     *  @see LoKi:GenParticles::Count
+     *  @see LoKi:GenVertices::CountIF
+     *  @author Vanya BELYAEV Ivan.Belyaev@itep.ru
+     *  @date 2012-01-28
+     */
+    typedef LoKi::GenParticles::Count GCOUNT;
+    // ========================================================================
+    /** @typedef GHAS
+     *  simple functor to check certain particles in HepMC3-graph
+     *  @code
+     *
+     *   const GHAS chk = GHAS ( "pi+" == GABSID , HepMC3.descendents ) ;
+     *
+     *   HepMC3::ConstGenParticlePtr p = ... ;
+     *
+     *   const bool hasPi = chk ( p ) ;
+     *
+     *  @endcode
+     *
+     *  @see LoKi:GenParticles::Has
+     *  @author Vanya BELYAEV Ivan.Belyaev@itep.ru
+     *  @date 2012-01-28
+     */
+    typedef LoKi::GenParticles::Has GHAS;
+    // ========================================================================
+  } // namespace Cuts
+  // ==========================================================================
+} //                                                      end of namespace LoKi
+// ============================================================================
+//                                                                      The END
+// ============================================================================
+#endif // LOKI_GENPARTICLES3_H
diff --git a/Gen/LoKiGen/LoKi/GenParticles4.h b/Gen/LoKiGen/LoKi/GenParticles4.h
new file mode 100644
index 000000000..58091f076
--- /dev/null
+++ b/Gen/LoKiGen/LoKi/GenParticles4.h
@@ -0,0 +1,903 @@
+/*****************************************************************************\
+* (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration      *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                             *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+// ============================================================================
+#ifndef LOKI_GENPARTICLES4_H
+#define LOKI_GENPARTICLES4_H 1
+// ============================================================================
+// Include files
+// ============================================================================
+// Event
+// ============================================================================
+#include "HepMC3/GenEvent.h"
+#include "HepMC3/GenParticle.h"
+#include "HepMC3/GenVertex.h"
+// ============================================================================
+// LoKi
+// ============================================================================
+#include "LoKi/GenChildSelector.h"
+#include "LoKi/GenTypes.h"
+#include "LoKi/Kinematics.h"
+// ============================================================================
+/** @file
+ *
+ *  This file is a part of LoKi project -
+ *    "C++ ToolKit  for Smart and Friendly Physics Analysis"
+ *
+ *  The package has been designed with the kind help from
+ *  Galina PAKHLOVA and Sergey BARSUK.  Many bright ideas,
+ *  contributions and advices from G.Raven, J.van Tilburg,
+ *  A.Golutvin, P.Koppenburg have been used in the design.
+ *
+ *  @author Vanya BELYAEV Ivan.Belyaev@itep.ru
+ *  @date 2012-01-28
+ *
+ */
+// ============================================================================
+namespace LoKi {
+  // ==========================================================================
+  namespace GenParticles {
+    // ========================================================================
+    /** @class FourMomentum
+     *  base class for implementation of many function dealing
+     *  with the various subcombinations of particles
+     *  @author Vanya BELYAEV Ivan.Belyaev@itep.ru
+     *  @date 2012-06-17
+     */
+    class GAUDI_API FourMomentum : public LoKi::GenTypes::GFunc {
+    public:
+      // ======================================================================
+      /// constructor from one
+      FourMomentum( const LoKi::GenChild::Selector& c1 );
+      /// constructor from two selectors
+      FourMomentum( const LoKi::GenChild::Selector& c1, const LoKi::GenChild::Selector& c2 );
+      /// constructor from three selectors
+      FourMomentum( const LoKi::GenChild::Selector& c1, const LoKi::GenChild::Selector& c2,
+                    const LoKi::GenChild::Selector& c3 );
+      /// constructor from four selectors
+      FourMomentum( const LoKi::GenChild::Selector& c1, const LoKi::GenChild::Selector& c2,
+                    const LoKi::GenChild::Selector& c3, const LoKi::GenChild::Selector& c4 );
+      /// contructor from list of selectors
+      FourMomentum( const LoKi::GenChild::Selector::Vector& cs );
+      // ======================================================================
+      /// constructor from one selector
+      FourMomentum( const LoKi::GenTypes::GCuts& c1 );
+      /// constructor from two selectors
+      FourMomentum( const LoKi::GenTypes::GCuts& c1, const LoKi::GenTypes::GCuts& c2 );
+      /// constructor from three selectors
+      FourMomentum( const LoKi::GenTypes::GCuts& c1, const LoKi::GenTypes::GCuts& c2, const LoKi::GenTypes::GCuts& c3 );
+      /// constructor from four selectors
+      FourMomentum( const LoKi::GenTypes::GCuts& c1, const LoKi::GenTypes::GCuts& c2, const LoKi::GenTypes::GCuts& c3,
+                    const LoKi::GenTypes::GCuts& c4 );
+      /// default constructor
+      FourMomentum() = default;
+      // ======================================================================
+    public:
+      // ======================================================================
+      /// evaluate the full four momentum of combination
+      LoKi::LorentzVector momentum( const HepMC3::ConstGenParticlePtr & p ) const;
+      /**  get the rapidity y
+       *  \f$ y = \frac{1}{2}\log \frac{ E + p_z }{ E - p_z } \f$
+       */
+      double y( const LoKi::LorentzVector& lv ) const;
+      /**  get the rapidity y0
+       *  \f$ y_0 = \frac{1}{2}\log \frac{ E + p }{ E - p } \f$
+       */
+      double y0( const LoKi::LorentzVector& lv ) const;
+      // get the angle phi
+      double phi( const LoKi::LorentzVector& lv ) const;
+      // get the pseudorapidity
+      double eta( const LoKi::LorentzVector& lv ) const;
+      // get beta-factor
+      double beta( const LoKi::LorentzVector& lv ) const;
+      // get gamma-factor
+      double gamma( const LoKi::LorentzVector& lv ) const;
+      // get beta*gamma-factor
+      double bgamma( const LoKi::LorentzVector& lv ) const;
+      // ======================================================================
+    protected:
+      // ======================================================================
+      /// base class printput
+      std::ostream& print_( std::ostream& s, const std::string& n1, const std::string& n2 ) const;
+      // ======================================================================
+    private:
+      // ======================================================================
+      /// the actual list of selectors
+      LoKi::GenChild::Selector::Vector m_children;
+      // ======================================================================
+    };
+    // ========================================================================
+    /** @class Mass
+     *  evaluator of the 'Mass for particle and/or combination of daughters
+     *
+     *  @see HepMC3::GenParticle
+     *  @see LoKi::Cuts::GM
+     *  @see LoKi::Cuts::GMASS
+     *  @author Vanya BELYAEV Ivan.Belyaev@itep.ru
+     *  @date   2006-01-17
+     */
+    struct GAUDI_API Mass : LoKi::GenParticles::FourMomentum {
+      // ======================================================================
+      /// forward to base-class constructors
+      using LoKi::GenParticles::FourMomentum::FourMomentum;
+      /// MANDATORY: clone method ("virtual destructor")
+      Mass* clone() const override;
+      /// MANDATORY: the only one essential method
+      double operator()( const HepMC3::ConstGenParticlePtr & p ) const override;
+      /// OPTIONAL: nice printout
+      std::ostream& fillStream( std::ostream& s ) const override;
+      // ======================================================================
+    };
+    // ========================================================================
+    /** @class Energy
+     *  evaluator of the 'Energy for particle and/or combination of daughters
+     *
+     *  @see HepMC3::GenParticle
+     *  @see LoKi::Cuts::GE
+     *  @see LoKi::Cuts::GENERGY
+     *  @author Vanya BELYAEV Ivan.Belyaev@itep.ru
+     *  @date   2006-01-17
+     */
+    struct GAUDI_API Energy : LoKi::GenParticles::FourMomentum {
+      // ======================================================================
+      /// forward to base-class constructor
+      using LoKi::GenParticles::FourMomentum::FourMomentum;
+      /// MANDATORY: clone method ("virtual constructor")
+      Energy* clone() const override;
+      /// MANDATORY: the only one essential method
+      double operator()( const HepMC3::ConstGenParticlePtr & p ) const override;
+      /// OPTIONAL: nice printout
+      std::ostream& fillStream( std::ostream& s ) const override;
+      // ======================================================================
+    };
+    // ========================================================================
+    /** @class Momentum
+     *  evaluator of the 3-momentum for particle and/or combination of daughters
+     *
+     *  @see HepMC3::GenParticle
+     *  @see LoKi::Cuts::GP
+     *  @see LoKi::Cuts::GMOMENTUM
+     *  @author Vanya BELYAEV Ivan.Belyaev@itep.ru
+     *  @date   2006-01-17
+     */
+    struct GAUDI_API Momentum : LoKi::GenParticles::FourMomentum {
+      // ======================================================================
+      /// forward to base class constructor
+      using LoKi::GenParticles::FourMomentum::FourMomentum;
+      /// MANDATORY: clone method ("virtual destructor")
+      Momentum* clone() const override;
+      /// MANDATORY: the only one essential method
+      double operator()( const HepMC3::ConstGenParticlePtr & p ) const override;
+      /// OPTIONAL: nice printout
+      std::ostream& fillStream( std::ostream& s ) const override;
+      // ======================================================================
+    };
+    // ========================================================================
+    /** @class MomentumX
+     *  evaluator of the x-momentum for particle and/or combination of daughters
+     *
+     *  @see HepMC3::GenParticle
+     *  @see LoKi::Cuts::GPX
+     *  @see LoKi::Cuts::GMOMX
+     *  @author Vanya BELYAEV Ivan.Belyaev@itep.ru
+     *  @date   2006-01-17
+     */
+    struct GAUDI_API MomentumX : LoKi::GenParticles::FourMomentum {
+      // ======================================================================
+      /// forward to base class constructors
+      using LoKi::GenParticles::FourMomentum::FourMomentum;
+      /// MANDATORY: clone method ("virtual destructor")
+      MomentumX* clone() const override;
+      /// MANDATORY: the only one essential method
+      double operator()( const HepMC3::ConstGenParticlePtr & p ) const override;
+      /// OPTIONAL: nice printout
+      std::ostream& fillStream( std::ostream& s ) const override;
+      // ======================================================================
+    };
+    // ========================================================================
+    /** @class MomentumY
+     *  evaluator of the x-momentum for particle and/or combination of daughters
+     *
+     *  @see HepMC3::GenParticle
+     *  @see LoKi::Cuts::GPY
+     *  @see LoKi::Cuts::GMOMY
+     *  @author Vanya BELYAEV Ivan.Belyaev@itep.ru
+     *  @date   2006-01-17
+     */
+    struct GAUDI_API MomentumY : LoKi::GenParticles::FourMomentum {
+      // ======================================================================
+      /// constructor from one selectors
+      using LoKi::GenParticles::FourMomentum::FourMomentum;
+      /// MANDATORY: clone method ("virtual destructor")
+      MomentumY* clone() const override;
+      /// MANDATORY: the only one essential method
+      double operator()( const HepMC3::ConstGenParticlePtr & p ) const override;
+      /// OPTIONAL: nice printout
+      std::ostream& fillStream( std::ostream& s ) const override;
+      // ======================================================================
+    };
+    // ========================================================================
+    /** @class MomentumZ
+     *  evaluator of the x-momentum for particle and/or combination of daughters
+     *
+     *  @see HepMC3::GenParticle
+     *  @see LoKi::Cuts::GPZ
+     *  @see LoKi::Cuts::GMOMZ
+     *  @author Vanya BELYAEV Ivan.Belyaev@itep.ru
+     *  @date   2006-01-17
+     */
+    struct GAUDI_API MomentumZ : LoKi::GenParticles::FourMomentum {
+      // ======================================================================
+      /// forward to base-class constructors
+      using LoKi::GenParticles::FourMomentum::FourMomentum;
+      /// MANDATORY: clone method ("virtual destructor")
+      MomentumZ* clone() const override;
+      /// MANDATORY: the only one essential method
+      double operator()( const HepMC3::ConstGenParticlePtr & p ) const override;
+      /// OPTIONAL: nice printout
+      std::ostream& fillStream( std::ostream& s ) const override;
+      // ======================================================================
+    };
+    // ========================================================================
+    /** @class TransverseMomentum
+     *  evaluator of the x-momentum for particle and/or combination of daughters
+     *
+     *  @see HepMC3::GenParticle
+     *  @see LoKi::Cuts::GPT
+     *  @see LoKi::Cuts::GMOMT
+     *  @author Vanya BELYAEV Ivan.Belyaev@itep.ru
+     *  @date   2006-01-17
+     */
+    struct GAUDI_API TransverseMomentum : LoKi::GenParticles::FourMomentum {
+      // ======================================================================
+      /// forward to base-class constructors
+      using LoKi::GenParticles::FourMomentum::FourMomentum;
+      /// MANDATORY: clone method ("virtual constructor")
+      TransverseMomentum* clone() const override;
+      /// MANDATORY: the only one essential method
+      double operator()( const HepMC3::ConstGenParticlePtr & p ) const override;
+      /// OPTIONAL: nice printout
+      std::ostream& fillStream( std::ostream& s ) const override;
+      // ======================================================================
+    };
+    // ========================================================================
+    /** @class PseudoRapidity
+     *  evaluator of the x-momentum for particle and/or combination of daughters
+     *
+     *  @see HepMC3::GenParticle
+     *  @see LoKi::Cuts::GETA
+     *  @see LoKi::Cuts::GPSEUDORAPIDITY
+     *  @author Vanya BELYAEV Ivan.Belyaev@itep.ru
+     *  @date   2006-01-17
+     */
+    struct GAUDI_API PseudoRapidity : LoKi::GenParticles::FourMomentum {
+      // ======================================================================
+      /// forward to base-class constructors
+      using LoKi::GenParticles::FourMomentum::FourMomentum;
+      /// MANDATORY: clone method ("virtual constructor")
+      PseudoRapidity* clone() const override;
+      /// MANDATORY: the only one essential method
+      double operator()( const HepMC3::ConstGenParticlePtr & p ) const override;
+      /// OPTIONAL: nice printout
+      std::ostream& fillStream( std::ostream& s ) const override;
+      // ======================================================================
+    };
+    // ========================================================================
+    /** @class Rapidity
+     *  evaluator of the rapidity for particle and/or combination of daughters
+     *
+     *  \f$ y = \frac{1}{2}\log \frac{ E + p_z }{ E - p_z } \f$
+     *
+     *  @see HepMC3::GenParticle
+     *  @see LoKi::Cuts::GY
+     *  @see LoKi::Cuts::GRAPIDITY
+     *  @author Vanya BELYAEV Ivan.Belyaev@itep.ru
+     *  @date   2006-01-17
+     */
+    struct GAUDI_API Rapidity : LoKi::GenParticles::FourMomentum {
+      // ======================================================================
+      /// forward to base-class constructors
+      using LoKi::GenParticles::FourMomentum::FourMomentum;
+      /// MANDATORY: clone method ("virtual destructor")
+      Rapidity* clone() const override;
+      /// MANDATORY: the only one essential method
+      double operator()( const HepMC3::ConstGenParticlePtr & p ) const override;
+      /// OPTIONAL: nice printout
+      std::ostream& fillStream( std::ostream& s ) const override;
+      // ======================================================================
+    };
+    // ========================================================================
+    /** @class Rapidity0
+     *  evaluator of the rapidity0 for particle and/or combination of daughters
+     *
+     *  \f$ y_0 = \frac{1}{2}\log \frac{ E + p }{ E - p } \f$
+     *
+     *  @see HepMC3::GenParticle
+     *  @see LoKi::Cuts::GY0
+     *  @see LoKi::Cuts::GRAPIDITY0
+     *  @author Vanya BELYAEV Ivan.Belyaev@itep.ru
+     *  @date   2006-01-17
+     */
+    struct GAUDI_API Rapidity0 : LoKi::GenParticles::FourMomentum {
+      // ======================================================================
+      /// forward to base-class constructors
+      using LoKi::GenParticles::FourMomentum::FourMomentum;
+      /// MANDATORY: clone method ("virtual destructor")
+      Rapidity0* clone() const override;
+      /// MANDATORY: the only one essential method
+      double operator()( const HepMC3::ConstGenParticlePtr & p ) const override;
+      /// OPTIONAL: nice printout
+      std::ostream& fillStream( std::ostream& s ) const override;
+      // ======================================================================
+    };
+    // ========================================================================
+    /** @class Phi
+     *  evaluator of the \f$\phi\f$ for particle and/or combination of daughters
+     *
+     *  @see HepMC3::GenParticle
+     *  @see LoKi::Cuts::GPHI
+     *  @see LoKi::Cuts::GASYMUTH
+     *  @author Vanya BELYAEV Ivan.Belyaev@itep.ru
+     *  @date   2006-01-17
+     */
+    struct GAUDI_API Phi : LoKi::GenParticles::FourMomentum {
+      // ======================================================================
+      /// forward to base-class constructors
+      using LoKi::GenParticles::FourMomentum::FourMomentum;
+      /// MANDATORY: clone method ("virtual destructor")
+      Phi* clone() const override;
+      /// MANDATORY: the only one essential method
+      double operator()( const HepMC3::ConstGenParticlePtr & p ) const override;
+      /// OPTIONAL: nice printout
+      std::ostream& fillStream( std::ostream& s ) const override;
+      // ======================================================================
+    };
+    // ========================================================================
+    /** @class Theta
+     *  evaluator of the \f$\phi\f$ for particle and/or combination of daughters
+     *
+     *  @see HepMC3::GenParticle
+     *  @see LoKi::Cuts::GPHI
+     *  @see LoKi::Cuts::GASYMUTH
+     *  @author Vanya BELYAEV Ivan.Belyaev@itep.ru
+     *  @date   2006-01-17
+     */
+    struct GAUDI_API Theta : LoKi::GenParticles::FourMomentum {
+      // ======================================================================
+      /// forward to base-class constructors
+      using LoKi::GenParticles::FourMomentum::FourMomentum;
+      /// MANDATORY: clone method ("virtual destructor")
+      Theta* clone() const override;
+      /// MANDATORY: the only one essential method
+      double operator()( const HepMC3::ConstGenParticlePtr & p ) const override;
+      /// OPTIONAL: nice printout
+      std::ostream& fillStream( std::ostream& s ) const override;
+      // ======================================================================
+    };
+    // ========================================================================
+    /** @class Beta
+     *  evaluator of the \f$\beta\f$ for particle and/or combination of daughters
+     *
+     *  @see HepMC3::GenParticle
+     *  @see LoKi::Cuts::GBETA
+     *  @author Vanya BELYAEV Ivan.Belyaev@itep.ru
+     *  @date   2013-04-14
+     */
+    struct GAUDI_API Beta : LoKi::GenTypes::GFunc {
+      /// MANDATORY: clone method ("virtual destructor")
+      Beta* clone() const override;
+      /// MANDATORY: the only one essential method
+      double operator()( const HepMC3::ConstGenParticlePtr & p ) const override;
+      /// OPTIONAL: nice printout
+      std::ostream& fillStream( std::ostream& s ) const override;
+      // ======================================================================
+      // get beta-factor
+      double beta( const HepMC3::ConstGenParticlePtr & p ) const;
+      // get gamma-factor
+      double gamma( const HepMC3::ConstGenParticlePtr & p ) const;
+      // get beta*gamma-factor
+      double betagamma( const HepMC3::ConstGenParticlePtr & p ) const;
+      // ======================================================================
+    };
+    // ========================================================================
+    /** @class Gamma
+     *  evaluator of the \f$\gamma\f$ for particle and/or combination of daughters
+     *
+     *  @see HepMC3::GenParticle
+     *  @see LoKi::Cuts::GGAMMA
+     *  @author Vanya BELYAEV Ivan.Belyaev@itep.ru
+     *  @date   2013-04-14
+     */
+    struct GAUDI_API Gamma : LoKi::GenParticles::Beta {
+      // ======================================================================
+      /// MANDATORY: clone method ("virtual destructor")
+      Gamma* clone() const override;
+      /// MANDATORY: the only one essential method
+      double operator()( const HepMC3::ConstGenParticlePtr & p ) const override;
+      /// OPTIONAL: nice printout
+      std::ostream& fillStream( std::ostream& s ) const override;
+      // ======================================================================
+    };
+    // ========================================================================
+    /** @class BetaGamma
+     *  evaluator of the \f$\beta\gamma\f$ for particle and/or combination of daughters
+     *
+     *  @see HepMC3::GenParticle
+     *  @see LoKi::Cuts::GBETAGAMMA
+     *  @see LoKi::Cuts::GBGAMMA
+     *  @see LoKi::Cuts::GBG
+     *  @author Vanya BELYAEV Ivan.Belyaev@itep.ru
+     *  @date   2013-04-14
+     */
+    struct GAUDI_API BetaGamma : LoKi::GenParticles::Beta {
+      // ======================================================================
+      /// MANDATORY: clone method ("virtual destructor")
+      BetaGamma* clone() const override;
+      /// MANDATORY: the only one essential method
+      double operator()( const HepMC3::ConstGenParticlePtr & p ) const override;
+      /// OPTIONAL: nice printout
+      std::ostream& fillStream( std::ostream& s ) const override;
+      // ======================================================================
+    };
+    // ========================================================================
+    /** @class DeltaPhi
+     *  Simple evaluator of "DeltaPhi" for the particle
+     *
+     *  @see LoKi::Cuts::GDPHI
+     *
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date 2007-03-03
+     */
+    class GAUDI_API DeltaPhi : public LoKi::GenParticles::Phi {
+    public:
+      // ======================================================================
+      /// constructor from the angle
+      DeltaPhi( const double phi );
+      /// constructor from the vector
+      DeltaPhi( const LoKi::ThreeVector& v );
+      /// constructor from the vector
+      DeltaPhi( const LoKi::LorentzVector& v );
+      /// constructor from the particle
+      DeltaPhi( const HepMC3::ConstGenParticlePtr & p );
+      /// MANDATORY: clone method ("virtual constructor")
+      DeltaPhi* clone() const override;
+      /// MANDATORY: the only essential method
+      double operator()( const HepMC3::ConstGenParticlePtr & p ) const override;
+      /// OPTIONAL: "SHORT" representation
+      std::ostream& fillStream( std::ostream& s ) const override;
+      // ======================================================================
+    public:
+      // ======================================================================
+      /// get the phi
+      double phi0() const { return m_phi; } // get the phi
+      double dphi( const HepMC3::ConstGenParticlePtr & p ) const;
+      // ======================================================================
+    private:
+      // ======================================================================
+      /// the angle itself
+      double m_phi; // the angle itself
+      // ======================================================================
+    };
+    // ========================================================================
+    /** @class DeltaEta
+     *  Simple evaluator of "DeltaEta" for the particle
+     *
+     *  @see LoKi::Cuts::GDETA
+     *
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date 2007-03-03
+     */
+    class GAUDI_API DeltaEta : public LoKi::GenParticles::PseudoRapidity {
+    public:
+      // ======================================================================
+      /// constructor from the eta
+      DeltaEta( const double eta );
+      /// constructor from the vector
+      DeltaEta( const LoKi::ThreeVector& v );
+      /// constructor from the vector
+      DeltaEta( const LoKi::LorentzVector& v );
+      /// constructor from the particle
+      DeltaEta( const HepMC3::ConstGenParticlePtr & p );
+      /// MANDATORY: clone method ("virtual constructor")
+      DeltaEta* clone() const override;
+      /// MANDATORY: the only essential method
+      double operator()( const HepMC3::ConstGenParticlePtr & p ) const override;
+      /// OPTIONAL: "SHORT" representation
+      std::ostream& fillStream( std::ostream& s ) const override;
+      // ======================================================================
+      /// get the eta
+      double eta0() const { return m_eta; }
+      double deta( const HepMC3::ConstGenParticlePtr & p ) const;
+      // ======================================================================
+    private:
+      // ======================================================================
+      /// the angle itself
+      double m_eta; // the angle itself
+      // ======================================================================
+    };
+    // ========================================================================
+    /** @class DeltaR2
+     *  Simple evaluator of "DeltaPhi**2+ DeltaEta**2"
+     *
+     *  @see LoKi::Cuts::GDR2
+     *  @see LoKi::Cuts::GDELTAR2
+     *  @see LoKi::Cuts::GDPHI
+     *  @see LoKi::Cuts::GDETA
+     *  @see LoKi::GenParticles::DeltaPhi
+     *  @see LoKi::GenParticles::DeltaEta
+     *  @see LoKi::GenParticles::Phi
+     *  @see LoKi::GenParticles::PseudoRapidity
+     *
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date 2007-03-03
+     */
+    class GAUDI_API DeltaR2 : public LoKi::GenParticles::DeltaPhi {
+    public:
+      // ======================================================================
+      /// constructor from eta & phi
+      DeltaR2( const double eta, const double phi );
+      /// constructor from the vector
+      DeltaR2( const LoKi::ThreeVector& v );
+      /// constructor from the vector
+      DeltaR2( const LoKi::LorentzVector& v );
+      /// constructor from the particle
+      DeltaR2( const HepMC3::ConstGenParticlePtr & p );
+      /// MANDATORY: clone method ("virtual constructor")
+      DeltaR2* clone() const override;
+      /// MANDATORY: the only essential method
+      double operator()( const HepMC3::ConstGenParticlePtr & p ) const override;
+      /// OPTIONAL: "SHORT" representation
+      std::ostream& fillStream( std::ostream& s ) const override;
+      // ======================================================================
+    public:
+      // ======================================================================
+      /// get the eta
+      double eta0() const { return m_deta.eta0(); }
+      double deta( const HepMC3::ConstGenParticlePtr & p ) const { return m_deta.deta( p ); }
+      // ======================================================================
+    private:
+      // ======================================================================
+      /// the actual evaluator of delta eta
+      LoKi::GenParticles::DeltaEta m_deta; // the actual evaluator of delta eta
+      // ======================================================================
+    };
+    // ========================================================================
+  } // namespace GenParticles
+  // ==========================================================================
+  namespace Cuts {
+    // ========================================================================
+    /** @var GM
+     *  evaluator of particle mass
+     *
+     *  @see LoKi::Cuts::GMASS
+     *  @see LoKi::GenParticles::Mass
+     *
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date 2006-01-18
+     */
+    inline const auto GM = LoKi::GenParticles::Mass{};
+    // ========================================================================
+    /** @typedef GMASS
+     *  evaluator of particle mass
+     *
+     *  @see LoKi::Cuts::GM
+     *  @see LoKi::GenParticles::Mass
+     *
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date 2006-01-18
+     */
+    using GMASS = LoKi::GenParticles::Mass;
+    // ========================================================================
+    /** @var GE
+     *  evaluator of particle energy
+     *
+     *  @see LoKi::Cuts::GENERGY
+     *  @see LoKi::GenParticles::Energy
+     *
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date 2006-01-18
+     */
+    inline const auto GE = LoKi::GenParticles::Energy{};
+    // ========================================================================
+    /** @typedef GENERGY
+     *  evaluator of particle energy
+     *
+     *  @see LoKi::Cuts::GE
+     *  @see LoKi::GenParticles::Energy
+     *
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date 2006-01-18
+     */
+    using GENERGY = LoKi::GenParticles::Energy;
+    // ========================================================================
+    /** @var GP
+     *  evaluator of particle momentum
+     *
+     *  @see LoKi::Cuts::GENERGY
+     *  @see LoKi::GenParticles::Momentum
+     *
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date 2006-01-18
+     */
+    inline const auto GP = LoKi::GenParticles::Momentum{};
+    // ========================================================================
+    /** @typedef GMOMENTUM
+     *  evaluator of particle momentum
+     *
+     *  @see LoKi::Cuts::GP
+     *  @see LoKi::Cuts::GMOMENTUM
+     *  @see LoKi::GenParticles::Momentum
+     *
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date 2006-01-18
+     */
+    using GMOMENTUM = LoKi::GenParticles::Momentum;
+    // ========================================================================
+    /** @var GPX
+     *  evaluator of particle momentum
+     *
+     *  @see LoKi::Cuts::GMOMX
+     *  @see LoKi::GenParticles::MomentumX
+     *
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date 2006-01-18
+     */
+    inline const auto GPX = LoKi::GenParticles::MomentumX{};
+    // ========================================================================
+    /** @typedef GMOMX
+     *  evaluator of particle momentum
+     *
+     *  @see LoKi::Cuts::GPX
+     *  @see LoKi::GenParticles::MomentumX
+     *
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date 2006-01-18
+     */
+    using GMOMX = LoKi::GenParticles::MomentumX;
+    // ========================================================================
+    /** @var GPY
+     *  evaluator of particle momentum
+     *
+     *  @see LoKi::Cuts::GMOMY
+     *  @see LoKi::GenParticles::MomentumY
+     *
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date 2006-01-18
+     */
+    inline const auto GPY = LoKi::GenParticles::MomentumY{};
+    // ========================================================================
+    /** @typedef GMOMY
+     *  evaluator of particle momentum
+     *
+     *  @see LoKi::Cuts::GPY
+     *  @see LoKi::GenParticles::MomentumY
+     *
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date 2006-01-18
+     */
+    using GMOMY = LoKi::GenParticles::MomentumY;
+    // ========================================================================
+    /** @var GPZ
+     *  evaluator of particle momentum
+     *
+     *  @see LoKi::Cuts::GMOMZ
+     *  @see LoKi::GenParticles::MomentumZ
+     *
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date 2006-01-18
+     */
+    inline const auto GPZ = LoKi::GenParticles::MomentumZ{};
+    // ========================================================================
+    /** @typedef GMOMZ
+     *  evaluator of particle momentum
+     *
+     *  @see LoKi::Cuts::GPZ
+     *  @see LoKi::GenParticles::MomentumZ
+     *
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date 2006-01-18
+     */
+    using GMOMZ = LoKi::GenParticles::MomentumZ;
+    // ========================================================================
+    /** @var GPT
+     *  evaluator of particle transverse momentum
+     *
+     *  @see LoKi::Cuts::GMOMT
+     *  @see LoKi::GenParticles::TransverseMomentum
+     *
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date 2006-01-18
+     */
+    inline const auto GPT = LoKi::GenParticles::TransverseMomentum{};
+    // ========================================================================
+    /** @typedef GMOMT
+     *  evaluator of particle transverse momentum
+     *
+     *  @see LoKi::Cuts::GPZ
+     *  @see LoKi::GenParticles::TransverseMomentum
+     *
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date 2006-01-18
+     */
+    using GMOMT = LoKi::GenParticles::TransverseMomentum;
+    // ========================================================================
+    /** @var GETA
+     *  evaluator of particle pseudorapidity
+     *
+     *  @see LoKi::Cuts::GPSEUDORAPIDITY
+     *  @see LoKi::GenParticles::PseudoRapidity
+     *
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date 2006-01-18
+     */
+    inline const auto GETA = LoKi::GenParticles::PseudoRapidity{};
+    // ========================================================================
+    /** @typedef GPSEUDORAPIDITY
+     *  evaluator of particle transverse momentum
+     *
+     *  @see LoKi::Cuts::GETA
+     *  @see LoKi::GenParticles::PseudoRapidity
+     *
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date 2006-01-18
+     */
+    using GPSEUDORAPIDITY = LoKi::GenParticles::PseudoRapidity;
+    // ========================================================================
+    /** @var GY
+     *  evaluator of particle rapidity
+     *
+     *  \f$ y = \frac{1}{2}\log \frac{ E + p_z }{ E - p_z } \f$
+     *
+     *  @see LoKi::Cuts::GRAPIDITY
+     *  @see LoKi::GenParticles::Rapidity
+     *
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date 2006-01-18
+     */
+    inline const auto GY = LoKi::GenParticles::Rapidity{};
+    // ========================================================================
+    /** @typedef GRAPIDITY
+     *  evaluator of particle rapidity
+     *
+     *  \f$ y = \frac{1}{2}\log \frac{ E + p_z }{ E - p_z } \f$
+     *
+     *  @see LoKi::Cuts::GY
+     *  @see LoKi::GenParticles::Rapidity
+     *
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date 2006-01-18
+     */
+    using GRAPIDITY = LoKi::GenParticles::Rapidity;
+    // ========================================================================
+    /** @var GY0
+     *  evaluator of particle rapidity0
+     *
+     *  \f$ y_0 = \frac{1}{2}\log \frac{ E + p }{ E - p } \f$
+     *
+     *  @see LoKi::Cuts::GRAPIDITY0
+     *  @see LoKi::GenParticles::Rapidity0
+     *
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date 2006-01-18
+     */
+    inline const auto GY0 = LoKi::GenParticles::Rapidity0{};
+    // ========================================================================
+    /** @typedef GRAPIDITY0
+     *  evaluator of particle rapidity0
+     *
+     *  \f$ y_0 = \frac{1}{2}\log \frac{ E + p }{ E - p } \f$
+     *
+     *  @see LoKi::Cuts::GY0
+     *  @see LoKi::GenParticles::Rapidity0
+     *
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date 2006-01-18
+     */
+    using GRAPIDITY0 = LoKi::GenParticles::Rapidity0;
+    // ========================================================================
+    /** @var GPHI
+     *  evaluator of particle \f$\phi\f$
+     *
+     *  @see LoKi::Cuts::GASYMUTH
+     *  @see LoKi::GenParticles::Phi
+     *
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date 2006-01-18
+     */
+    inline const auto GPHI = LoKi::GenParticles::Phi{};
+    // ========================================================================
+    /** @typedef GASYMUTH
+     *  evaluator of particle \f$\phi\f$
+     *
+     *  @see LoKi::Cuts::GPHI
+     *  @see LoKi::GenParticles::Phi
+     *
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date 2006-01-18
+     */
+    using GASYMUTH = LoKi::GenParticles::Phi;
+    // ========================================================================
+    /** @var GTHETA
+     *  evaluator of particle \f$\theta\f$
+     *
+     *  @see LoKi::Cuts::GPOLAR
+     *  @see LoKi::GenParticles::Theta
+     *
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date 2006-01-18
+     */
+    inline const auto GTHETA = LoKi::GenParticles::Theta{};
+    // ========================================================================
+    /** @typedef GPOLAR
+     *  evaluator of particle \f$\theta\f$
+     *
+     *  @see LoKi::Cuts::GTHETA
+     *  @see LoKi::GenParticles::Theta
+     *
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date 2006-01-18
+     */
+    typedef LoKi::GenParticles::Theta GPOLAR;
+    // ========================================================================
+    /** @typedef GDPHI
+     *  evaluator of \f$\Delta\phi\f$
+     *  @see LoKi::GenParticles::DeltaPhi
+     */
+    typedef LoKi::GenParticles::DeltaPhi GDPHI;
+    // ========================================================================
+    /** @typedef GDETA
+     *  evaluator of \f$\Delta\eta\f$
+     *  @see LoKi::GenParticles::DeltaEta
+     */
+    typedef LoKi::GenParticles::DeltaEta GDETA;
+    // ========================================================================
+    /** @typedef GDR2
+     *  evaluator of \f$\Delta\eta^2+\Delta\phi^2\f$
+     *  @see LoKi::GenParticles::DeltaR2
+     */
+    typedef LoKi::GenParticles::DeltaR2 GDR2;
+    // ========================================================================
+    /** @var GBETA
+     *  get \f$\beta\f$ for the particle
+     *  @see LoKi::GenParticles::Beta
+     */
+    inline const auto GBETA = LoKi::GenParticles::Beta{};
+    // ========================================================================
+    /** @var GGAMMA
+     *  get \f$\gamma\f$ for the particle
+     *  @see LoKi::GenParticles::Gamma
+     */
+    inline const auto GGAMMA = LoKi::GenParticles::Gamma{};
+    // ========================================================================
+    /** @var GBETAGAMMA
+     *  get \f$\beta\gamma\f$ for the particle
+     *  @see LoKi::GenParticles::BetaGamma
+     */
+    inline const auto GBETAGAMMA = LoKi::GenParticles::BetaGamma{};
+    // ========================================================================
+    /** @var GBGAMMA
+     *  get \f$\beta\gamma\f$ for the particle
+     *  @see LoKi::GenParticles::BetaGamma
+     */
+    inline const auto GBGAMMA = LoKi::GenParticles::BetaGamma{};
+    // ========================================================================
+    /** @var GBG
+     *  get \f$\beta\gamma\f$ for the particle
+     *  @see LoKi::GenParticles::BetaGamma
+     */
+    inline const auto GBG = LoKi::GenParticles::BetaGamma{};
+    // ========================================================================
+  } // namespace Cuts
+  // ==========================================================================
+} //                                                      end of namespace LoKi
+// ============================================================================
+//                                                                      The END
+// ============================================================================
+#endif // LOKI_GENPARTICLES4_H
diff --git a/Gen/LoKiGen/LoKi/GenParticles5.h b/Gen/LoKiGen/LoKi/GenParticles5.h
new file mode 100644
index 000000000..f24ae0500
--- /dev/null
+++ b/Gen/LoKiGen/LoKi/GenParticles5.h
@@ -0,0 +1,121 @@
+/*****************************************************************************\
+* (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration      *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                             *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+// ============================================================================
+#ifndef LOKI_GENPARTICLES5_H
+#define LOKI_GENPARTICLES5_H 1
+// ============================================================================
+// Include files
+// ============================================================================
+// Event
+// ============================================================================
+#include "HepMC3/GenEvent.h"
+#include "HepMC3/GenParticle.h"
+#include "HepMC3/GenVertex.h"
+// ============================================================================
+// LoKi
+// ============================================================================
+#include "LoKi/GenTypes.h"
+#include "LoKi/Kinematics.h"
+// ============================================================================
+/** @file
+ *
+ *  This file is a part of LoKi project -
+ *    "C++ ToolKit  for Smart and Friendly Physics Analysis"
+ *
+ *  The package has been designed with the kind help from
+ *  Galina PAKHLOVA and Sergey BARSUK.  Many bright ideas,
+ *  contributions and advices from G.Raven, J.van Tilburg,
+ *  A.Golutvin, P.Koppenburg have been used in the design.
+ *
+ *  @author Vanya BELYAEV Ivan.Belyaev@itep.ru
+ *  @date 2012-01-28
+ *
+ */
+// ============================================================================
+namespace LoKi {
+  // ==========================================================================
+  namespace GenParticles {
+    // ========================================================================
+    /** @class FlightDistance
+     *  evaluator of flight  distance of particle
+     *  @see LoKi::Cuts::GPVFLIGHT
+     *  @see LoKi::Cuts::GFLIGHTPV
+     *  @see LoKi::Cuts::GFLIGHT
+     *  @author Vanya BELYAEV Ivan.Belyaev@itep.ru
+     *  @date 2013-04-14
+     */
+    class GAUDI_API Flight : public LoKi::GenTypes::GFunc {
+    public:
+      // ======================================================================
+      /** constructor from the flag
+       *  @param primary use primary vertex, otherwise use own vertex
+       */
+      Flight( const bool primary = false );
+      /// MANDATORY: clone method ("virtual destructor")
+      Flight* clone() const override;
+      /// MANDATORY: the only one essential method
+      double operator()( const HepMC3::ConstGenParticlePtr & p ) const override;
+      /// OPTIONAL: nice printout
+      std::ostream& fillStream( std::ostream& s ) const override;
+      // ======================================================================
+      /// use primary vertex ?
+      bool primary() const { return m_primary; } // use primary vertex ?
+      // ======================================================================
+    private:
+      // ======================================================================
+      /// use primary vertex
+      bool m_primary; // use primary vertex
+      // ======================================================================
+    };
+    // ========================================================================
+  } // namespace GenParticles
+  // ==========================================================================
+  namespace Cuts {
+    // ========================================================================
+    /** @var GFLIGHTPV
+     *  evaluator of flight distance from PV
+     *  @see LoKi::GenParticles::Flight
+     *  @see LoKi::Cuts::GPVFLIGHT
+     *  @author Vanya BELYAEV Ivan.Belyaev@itep.ru
+     *  @date 2013-04-14
+     */
+    inline const auto GFLIGHTPV = LoKi::GenParticles::Flight{true};
+    // ========================================================================
+    /** @var GPVFLIGHT
+     *  evaluator of flight distance from PV
+     *  @code
+     *  @endcode
+     *  @see LoKi::GenParticles::Flight
+     *  @see LoKi::Cuts::GFLIGHTPV
+     *  @author Vanya BELYAEV Ivan.Belyaev@itep.ru
+     *  @date 2013-04-14
+     */
+    inline const auto GPVFLIGHT = LoKi::GenParticles::Flight{true};
+    // ========================================================================
+    /** @var GFLIGHT
+     *  evaluator of flight distance
+     *  @code
+     *  @endcode
+     *  @see LoKi::GenParticles::Flight
+     *  @see LoKi::Cuts::GFLIGHTPV
+     *  @see LoKi::Cuts::GPVFLIGHT
+     *  @author Vanya BELYAEV Ivan.Belyaev@itep.ru
+     *  @date 2013-04-14
+     */
+    inline const auto GFLIGHT = LoKi::GenParticles::Flight{false};
+    // ========================================================================
+  } // namespace Cuts
+  // ==========================================================================
+} //                                                      end of namespace LoKi
+// ============================================================================
+//                                                                      The END
+// ============================================================================
+#endif // LOKI_GENPARTICLES5_H
diff --git a/Gen/LoKiGen/LoKi/GenSections.h b/Gen/LoKiGen/LoKi/GenSections.h
new file mode 100644
index 000000000..b15a111bd
--- /dev/null
+++ b/Gen/LoKiGen/LoKi/GenSections.h
@@ -0,0 +1,89 @@
+/*****************************************************************************\
+* (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration      *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                             *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+// ============================================================================
+#ifndef LOKI_GENSECTIONS_H
+#define LOKI_GENSECTIONS_H 1
+// ============================================================================
+// Include files
+// ============================================================================
+// Event
+// ============================================================================
+#include "HepMC3/GenEvent.h"
+// ============================================================================
+// LoKi
+// ============================================================================
+#include "LoKi/GenChild.h"
+// ============================================================================
+/** @file LoKi/GenSections.h
+ *
+ *  Collection of varios functions related to the "sections" for
+ *  the certain graph/tree
+ *
+ *  This file is a part of LoKi project -
+ *    "C++ ToolKit  for Smart and Friendly Physics Analysis"
+ *
+ *  The package has been designed with the kind help from
+ *  Galina PAKHLOVA and Sergey BARSUK.  Many bright ideas,
+ *  contributions and advices from G.Raven, J.van Tilburg,
+ *  A.Golutvin, P.Koppenburg have been used in the design.
+ *
+ *  @author Vanya  BELYAEV Ivan.Belyaev@nikhef.nl
+ *  @date   2008-04-29
+ */
+// ============================================================================
+namespace Decays {
+  // ========================================================================
+  /// the actual type for the graph/tree section
+  typedef std::vector<HepMC3::ConstGenParticlePtr> GenSection;
+  // ========================================================================
+  /// the actual type for collection of sections
+  typedef std::vector<GenSection> GenSections;
+  // ========================================================================
+  /** simple function to extarct all section from the graph/tree
+   *  @param particle the head of th egraph/tree
+   *  @param output the sections of the graph/tree
+   *  @return size of the section container
+   */
+  size_t sections( const HepMC3::ConstGenParticlePtr & particle, GenSections& output );
+  // ========================================================================
+  /** simple function to extarct all section from the graph/tree
+   *  @param particle the head of th egraph/tree
+   *  @return sice of the section container
+   */
+  inline GenSections sections( const HepMC3::ConstGenParticlePtr & particle ) {
+    GenSections result;
+    sections( particle, result );
+    return result;
+  }
+  // ========================================================================
+  /** get the most trivial section (daughters)
+   *  @author Vanya  BELYAEV Ivan.Belyaev@nikhef.nl
+   *  @date   2008-05-25
+   */
+  inline size_t section( const HepMC3::ConstGenParticlePtr & particle, GenSection& output ) {
+    return LoKi::GenChild::daughters( particle, output );
+  }
+  // ========================================================================
+  /** get the most trivial section (daughters)
+   *  @author Vanya  BELYAEV Ivan.Belyaev@nikhef.nl
+   *  @date   2008-05-25
+   */
+  inline GenSection section( const HepMC3::ConstGenParticlePtr & particle ) {
+    GenSection result;
+    section( particle, result );
+    return result;
+  }
+  // ========================================================================
+} // end of namespace Decays
+// ============================================================================
+// The END
+// ============================================================================
+#endif // LOKI_GENSECTIONS_H
diff --git a/Gen/LoKiGen/LoKi/GenSources.h b/Gen/LoKiGen/LoKi/GenSources.h
new file mode 100644
index 000000000..a46a0332b
--- /dev/null
+++ b/Gen/LoKiGen/LoKi/GenSources.h
@@ -0,0 +1,195 @@
+/*****************************************************************************\
+* (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration      *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                             *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+// ============================================================================
+#ifndef LOKI_GENSOURCES_H
+#define LOKI_GENSOURCES_H 1
+// ============================================================================
+// Include files
+// ============================================================================
+// GaudiKErnel
+// ============================================================================
+#include "GaudiKernel/IDataProviderSvc.h"
+// ============================================================================
+// GenEvent
+// ============================================================================
+#include "HepMC3/GenEvent.h"
+// ============================================================================
+// LoKi
+// ============================================================================
+#include "LoKi/BasicFunctors.h"
+#include "LoKi/GenTypes.h"
+#include "LoKi/Interface.h"
+#include "LoKi/Sources.h"
+
+#include "Defaults/Locations.h"
+// ============================================================================
+/** @file LoKi/GenSources.h
+ *
+ *  This file is a part of LoKi project -
+ *    "C++ ToolKit  for Smart and Friendly Physics Analysis"
+ *
+ *  The package has been designed with the kind help from
+ *  Galina PAKHLOVA and Sergey BARSUK.  Many bright ideas,
+ *  contributions and advices from G.Raven, J.van Tilburg,
+ *  A.Golutvin, P.Koppenburg have been used in the design.
+ *
+ */
+// ============================================================================
+namespace LoKi {
+  // ==========================================================================
+  namespace Functors {
+    // ========================================================================
+    template <>
+    inline LoKi::GenTypes::GenContainer
+    LoKi::Functors::Source<HepMC3::ConstGenParticlePtr, LoKi::GenTypes::GenContainer, std::vector<HepMC3::GenEvent>>::
+    operator()() const {
+      return LoKi::GenTypes::GenContainer();
+    }
+    // ========================================================================
+  } // namespace Functors
+  // ==========================================================================
+  namespace GenParticles {
+    // ========================================================================
+    /** @class SourceTES
+     *  @see LoKi::Cuts::GSOURCE
+     *  simple "source for the generator particles"
+     *  @author Vanya BELYAEV ibelyav@physics.syr.edu
+     *  @date 2006-12-07
+     */
+    class SourceTES
+        : public LoKi::Functors::Source<HepMC3::ConstGenParticlePtr, LoKi::GenTypes::GenContainer, std::vector<HepMC3::GenEvent>> {
+      // =====================================================================
+      typedef LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::Source _Source;
+      typedef LoKi::Functors::Source<HepMC3::ConstGenParticlePtr, LoKi::GenTypes::GenContainer, std::vector<HepMC3::GenEvent>>
+          _Base;
+      // ======================================================================
+      static_assert( std::is_base_of<_Source, _Base>::value, "Invalid base" );
+      // ======================================================================
+    public:
+      // =====================================================================
+      /// constructor from the service, TES location and cuts
+      SourceTES( const IDataProviderSvc* svc, const std::string& path = Gaussino::HepMCEventLocation::Default );
+      /// constructor from the service, TES location and cuts
+      SourceTES( const IDataProviderSvc* svc, const LoKi::GenTypes::GCuts& cuts,
+                 const std::string& path = Gaussino::HepMCEventLocation::Default );
+      // ======================================================================
+      /// constructor from the service, TES location and cuts
+      SourceTES( const GaudiAlgorithm* alg, const std::string& path = Gaussino::HepMCEventLocation::Default,
+                 const bool useRootInTES = true );
+      /// constructor from the service, TES location and cuts
+      SourceTES( const GaudiAlgorithm* alg, const LoKi::GenTypes::GCuts& cuts,
+                 const std::string& path = Gaussino::HepMCEventLocation::Default, const bool useRootInTES = true );
+      /// MANDATORY: clone method ("virtual constructor")
+      SourceTES* clone() const override { return new SourceTES( *this ); }
+      /// MANDATORY: the only essential method:
+      std::vector<HepMC3::ConstGenParticlePtr> operator()() const override;
+      /// OPTIONAL: the nice printout
+      std::ostream& fillStream( std::ostream& o ) const override;
+      // ======================================================================
+    private:
+      // ======================================================================
+      /// 'on-flight' filter
+      LoKi::GenTypes::GCut m_cut; // 'on-flight' filter
+      // ======================================================================
+    };
+    // ========================================================================
+    /** @class TESData
+     *  special source that relies on DataHandle to access data in TES
+     *  @see LoKi::TES::DataHanble
+     *  @see DataObjectReadHandle
+     *  @see LoKi::Cuts::GTESDATA
+     *  @author Vanya BELYAEV Ivan.BElyaev@itep.ru
+     *  @date    2018-08-20
+     */
+    class TESData : public LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::Source,
+                    public LoKi::TES::DataHandle<std::vector<HepMC3::GenEvent>> {
+    public:
+      // ======================================================================
+      /// constructor
+      TESData( const GaudiAlgorithm* algorithm, const std::string& location = Gaussino::HepMCEventLocation::Default );
+      /// constructor with cuts
+      TESData( const GaudiAlgorithm* algorithm, const std::string& location, const LoKi::GenTypes::GCuts& cuts );
+      /// constructor with cuts
+      TESData( const GaudiAlgorithm* algorithm, const LoKi::GenTypes::GCuts& cuts,
+               const std::string& location = Gaussino::HepMCEventLocation::Default );
+      /// MANDATORY: clone method ("virtual constructor")
+      TESData* clone() const override;
+      /// MANDATORY: the only essential method:
+      result_type operator()() const override;
+      /// OPTIONAL: the nice printout
+      std::ostream& fillStream( std::ostream& o ) const override;
+      // ======================================================================
+    private:
+      // ======================================================================
+      /// 'on-flight' filter
+      LoKi::GenTypes::GCut m_cuts; // 'on-flight' filter
+      // ======================================================================
+    };
+    // ========================================================================
+    /** @class TESCounter
+     *  simple functor to count number of 'good'-objects form TES
+     *  @author Vanya BELYAEV Ivan.Belyaev@itep.ru
+     *  @see LoKi::Cuts::GNUM
+     *  @date   2018-08-22
+     */
+    class GAUDI_API TESCounter : public LoKi::Functor<void, double> {
+    public:
+      // ======================================================================
+      /// constructor from the source
+      explicit TESCounter( const LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::Source& s );
+      // =============================================================================
+      /// MANDATORY: clone method ("virtual constructor")
+      TESCounter* clone() const override;
+      /// MANDATORY: the only essential method:
+      double operator()() const override;
+      /// OPTIONAL: the nice printout
+      std::ostream& fillStream( std::ostream& o ) const override;
+      // ======================================================================
+    private:
+      // ======================================================================
+      /// the actual source
+      LoKi::Assignable_t<LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::Source> m_source; // the actual source
+      // ======================================================================
+    };
+    // ========================================================================
+  } // namespace GenParticles
+  // ==========================================================================
+  namespace Cuts {
+    // ========================================================================
+    /** @typedef GSOURCE
+     *  The simple ``source'' of HepMC3-particles
+     *  @author Vanya BELYAEV Ivan.BElyaev@cern.ch
+     *  @date 2006-12-07
+     */
+    typedef LoKi::GenParticles::SourceTES GSOURCE;
+    // ========================================================================
+    /** @typedef GTESDATA
+     *  The simple ``source'' of HepMC3-particles
+     *  @attention DataHandler is used
+     *  @author Vanya BELYAEV Ivan.Belyaev@itep.ru
+     *  @date 2018-08-22
+     */
+    typedef LoKi::GenParticles::TESData GTESDATA;
+    // ========================================================================
+    /** @typedef GNUM
+     *  Count particles from the source
+     *  @author Vanya BELYAEV Ivan.Belyaev@cern.ch
+     *  @date 2006-12-07
+     */
+    typedef LoKi::GenParticles::TESCounter GNUM;
+    // ========================================================================
+  } // namespace Cuts
+  // ==========================================================================
+} // namespace LoKi
+// ============================================================================
+//                                                                      The END
+// ============================================================================
+#endif // LOKI_GENSOURCES_H
diff --git a/Gen/LoKiGen/LoKi/GenToCpp.h b/Gen/LoKiGen/LoKi/GenToCpp.h
new file mode 100644
index 000000000..dcfc02db0
--- /dev/null
+++ b/Gen/LoKiGen/LoKi/GenToCpp.h
@@ -0,0 +1,32 @@
+#include "HepMC3/Relatives.h"
+#include <utility>
+// ============================================================================
+namespace Gaudi {
+// ==========================================================================
+namespace Utils {
+std::string toCpp( const int o );
+// ========================================================================
+// strings and chars
+// ========================================================================
+inline std::string toCpp(const HepMC3::Relatives& range) {
+  if (dynamic_cast<const HepMC3::Parents*>(&range)) {
+    const int i = 0;
+    return toCpp( i );
+  }
+  if (dynamic_cast<const HepMC3::Children*>(&range)) {
+    const int i = 1;
+    return toCpp( i );
+  }
+  if (dynamic_cast<const HepMC3::Ancestors*>(&range)) {
+    const int i = 3;
+    return toCpp( i );
+  }
+  if (dynamic_cast<const HepMC3::Descendants*>(&range)) {
+    const int i = 4;
+    return toCpp( i );
+  }
+  const int i = -1;
+  return toCpp( i );
+}
+}  // namespace Utils
+}  // namespace Gaudi
diff --git a/Gen/LoKiGen/LoKi/GenTreesFactory.h b/Gen/LoKiGen/LoKi/GenTreesFactory.h
new file mode 100644
index 000000000..714a2e7d0
--- /dev/null
+++ b/Gen/LoKiGen/LoKi/GenTreesFactory.h
@@ -0,0 +1,97 @@
+/*****************************************************************************\
+* (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration      *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                             *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+// ============================================================================
+#ifndef LOKI_GENTREESFACTORY_H
+#define LOKI_GENTREESFACTORY_H 1
+// ============================================================================
+// Include files
+// ============================================================================
+// LoKi
+// ============================================================================
+#include "LoKi/Trees.h"
+#include "LoKi/iTree.h"
+// ============================================================================
+// forward declarations
+// ============================================================================
+#include "HepMC3/GenParticle_fwd.h"
+// ============================================================================
+/** @file LoKi/GenTreesFactory.h
+ *
+ *  This file is a part of LoKi project -
+ *    "C++ ToolKit  for Smart and Friendly Physics Analysis"
+ *
+ *  The package has been designed with the kind help from
+ *  Galina PAKHLOVA and Sergey BARSUK.  Many bright ideas,
+ *  contributions and advices from G.Raven, J.van Tilburg,
+ *  A.Golutvin, P.Koppenburg have been used in the design.
+ *
+ *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+ *  @date 2001-01-23
+ *
+ */
+// ============================================================================
+namespace Decays {
+  // ==========================================================================
+  namespace Parsers {
+    class Tree;
+  }
+  // ==========================================================================
+  namespace Trees {
+    // ========================================================================
+    /** "Factory" to create the proper Tree from the full description
+     *   @param tree       (OUTPUT) the constructed tree
+     *   @param mother     (INPUT)  the mother particle
+     *   @param oscillated (INPUT)  the oscillation flag
+     *   @param arrow      (INPUT)  the type of arrow
+     *   @param daughters  (INPUT)  the list of daughter trees
+     *   @param inclusive  (INPUT)  the flag for inclusive
+     *   @param optional   (INPUT)  the list of "optional" particles
+     *   @param stream     (OUTPUT) the stream to report errors
+     *   @return StatusCode
+     *   @author Vanya BELYAEV Ivan.Belyaev@nikhef.nl
+     *   @date   2009-05-06
+     */
+    StatusCode factory( Decays::Trees::Types_<HepMC3::ConstGenParticlePtr>::Tree& tree, const Decays::iNode& mother,
+                        const Decays::Trees::Oscillation& oscillated, const Decays::Trees::Arrow& arrow,
+                        const Decays::Trees::Types_<HepMC3::ConstGenParticlePtr>::TreeList& daughters,
+                        const bool                                                        inclusive,
+                        const Decays::Trees::Types_<HepMC3::ConstGenParticlePtr>::TreeList& optional,
+                        std::ostream&                                                     stream );
+    // ========================================================================
+    /** "Factory" to create the proper Tree from "short" descriptor
+     *   @param tree       (OUTPUT) the constructed tree
+     *   @param mother     (INPUT)  the mother particle
+     *   @param oscillated (INPUT)  the oscillation flag
+     *   @return status code
+     *   @author Vanya BELYAEV Ivan.Belyaev@nikhef.nl
+     *   @date   2009-05-06
+     */
+    StatusCode factory( Decays::Trees::Types_<HepMC3::ConstGenParticlePtr>::Tree& tree, const Decays::iNode& mother,
+                        const Decays::Trees::Oscillation& oscillated );
+    // ========================================================================
+    /** "Factory" to create the proper Tree from the parsed tree
+     *   @param tree       (OUTPUT) the constructed tree
+     *   @param parsed     (INPUT)  the parsed tree
+     *   @param stream     (OUTPUT) the stream to report errors
+     *   @return status code
+     *   @author Vanya BELYAEV Ivan.Belyaev@nikhef.nl
+     *   @date   2009-05-22
+     */
+    StatusCode factory( Decays::Trees::Types_<HepMC3::ConstGenParticlePtr>::Tree& tree,
+                        const Decays::Parsers::Tree& parsed, std::ostream& stream );
+    // ========================================================================
+  } // namespace Trees
+  // ==========================================================================
+} //                                                    end of namespace Decays
+// ============================================================================
+// The END
+// ============================================================================
+#endif // LOKI_GENTREESFACTORY_H
diff --git a/Gen/LoKiGen/LoKi/GenTypes.h b/Gen/LoKiGen/LoKi/GenTypes.h
new file mode 100644
index 000000000..b2e229558
--- /dev/null
+++ b/Gen/LoKiGen/LoKi/GenTypes.h
@@ -0,0 +1,260 @@
+/*****************************************************************************\
+* (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration      *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                             *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+// ============================================================================
+#ifndef LOKI_GENTYPES_H
+#define LOKI_GENTYPES_H 1
+// ============================================================================
+// Include files
+// ============================================================================
+// LoKi
+// ============================================================================
+#include "LoKi/CoreTypes.h"
+#include "LoKi/Functions.h"
+#include "LoKi/RangeList.h"
+#include "LoKi/Selected.h"
+// ============================================================================
+// HepMC3
+// ============================================================================
+#include "HepMC3/GenParticle_fwd.h"
+#include "HepMC3/GenVertex_fwd.h"
+namespace HepMC3 {
+  class GenEvent;
+}
+// ============================================================================
+// ============================================================================
+/** @file LoKi/GenTypes.h
+ *
+ *  Collection of useful function to extract the information from  HepMC3
+ *
+ *  This file is a part of LoKi project -
+ *    "C++ ToolKit  for Smart and Friendly Physics Analysis"
+ *
+ *  The package has been designed with the kind help from
+ *  Galina PAKHLOVA and Sergey BARSUK.  Many bright ideas,
+ *  contributions and advices from G.Raven, J.van Tilburg,
+ *  A.Golutvin, P.Koppenburg have been used in the design.
+ *
+ *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+ *  @date 2001-01-23
+ *
+ */
+// ============================================================================
+namespace LoKi {
+  // ==========================================================================
+  /** @namespace LoKi::GenTypes GenTypes.h LoKi/GenTypes.h
+   *  @author Vanya BELYAEV belyaev@lapp.in2p3.fr
+   *  @date   2005-03-27
+   */
+  namespace GenTypes {
+
+    template <typename M> class _ptr_wrap {
+      const M & mm;
+      public:
+      _ptr_wrap(const M & m) : mm(m){}
+      template <typename arg> auto operator()(arg a) -> decltype(mm(a)){
+        return (mm(a));
+      }
+      template <typename arg> auto operator()(arg a) -> decltype(mm(a.get())){
+        return (mm(a.get()));
+      }
+    };
+    // ========================================================================
+    /// the basic imported type for the sequence of HepMC3-particles
+    typedef std::vector<HepMC3::ConstGenParticlePtr> GenContainer;
+    /// the basic imported type for the sequence of HepMC3-particles
+    typedef GenContainer ConstVector;
+    /// the basic imported type for the sequence of HepMC3-vertices
+    typedef std::vector<HepMC3::ConstGenVertexPtr> GenVContainer;
+    //
+    typedef LoKi::Selected_<GenContainer>  GenSelected;
+    typedef LoKi::Selected_<GenVContainer> GenVSelected;
+    //
+    /// the actual type of the range of HepMC3-particles
+    typedef GenSelected::Range GRange;
+    /// the actual type of the range  of HepMC3-vertices
+    typedef GenVSelected::Range GVRange;
+    /// type of 'cuts' for HepMC3::GenParticle        (interface)
+    typedef LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::Predicate GCuts;
+    /// type of 'functions' for HEpMC::GenParticle   (interface)
+    typedef LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::Function GFunc;
+    /// type of 'cuts' for HepMC3::GenParticle        (assignable)
+    typedef LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate GCut;
+    /// type of 'functions' for HepMC3::GenParticle   (assignable)
+    typedef LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::FunctionFromFunction GFun;
+    //
+    /// type of 'cuts' for HepMC3::GenVertex          (interface)
+    typedef LoKi::BasicFunctors<HepMC3::ConstGenVertexPtr>::Predicate GVCuts;
+    /// type of 'functions' for HepMC3::GenVertex     (interface)
+    typedef LoKi::BasicFunctors<HepMC3::ConstGenVertexPtr>::Function GVFunc;
+    /// type of 'cuts' for HepMC3::GenVertex          (assignable)
+    typedef LoKi::BasicFunctors<HepMC3::ConstGenVertexPtr>::PredicateFromPredicate GVCut;
+    /// type of 'functions' for HepMC3::GenVertex     (assignable)
+    typedef LoKi::BasicFunctors<HepMC3::ConstGenVertexPtr>::FunctionFromFunction GVFun;
+    //
+    // functional types for HepMC3::GenParticle
+    //
+    // type of "map" for HepMC3::GenParticle   (interface)
+    typedef LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::Map GMaps;
+    // type of "map" for HepMC3::GenParticle   (assignable)
+    typedef LoKi::Assignable_t<GMaps> GMap;
+    // type of "pipe" for HepMC3::GenParticle   (interface)
+    typedef LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::Pipe GPipes;
+    // type of "pipe" for HepMC3::GenParticle   (assignable)
+    typedef LoKi::Assignable_t<GPipes> GPipe;
+    // type of "fun-val" for HepMC3::GenParticle   (interface)
+    typedef LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::FunVal GFunVals;
+    // type of "fun-val" for HepMC3::GenParticle   (assignable)
+    typedef LoKi::Assignable_t<GFunVals> GFunVal;
+    // type of "cut-val" for HepMC3::GenParticle   (interface)
+    typedef LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::CutVal GCutVals;
+    // type of "cut-val" for HepMC3::GenParticle   (assignable)
+    typedef LoKi::Assignable_t<GCutVals> GCutVal;
+    // type of "source" for HepMC3::GenParticle   (interface)
+    typedef LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::Source GSources;
+    // type of "source" for HepMC3::GenParticle   (assignable)
+    typedef LoKi::Assignable_t<GSources> GSource;
+    //
+    // functional types for HepMC3::GenVertex
+    //
+    // type of "map" for HepMC3GenVertex   (interface)
+    typedef LoKi::BasicFunctors<HepMC3::GenVertexPtr>::Map GVMaps;
+    // type of "map" for HepMC3GenVertex   (assignable)
+    typedef LoKi::Assignable_t<GVMaps> GVMap;
+    // type of "pipe" for HepMC3GenVertex   (interface)
+    typedef LoKi::BasicFunctors<HepMC3::GenVertexPtr>::Pipe GVPipes;
+    // type of "pipe" for HepMC3GenVertex   (assignable)
+    typedef LoKi::Assignable_t<GVPipes> GVPipe;
+    // type of "fun-val" for HepMC3GenVertex   (interface)
+    typedef LoKi::BasicFunctors<HepMC3::GenVertexPtr>::FunVal GVFunVals;
+    // type of "fun-val" for HepMC3GenVertex   (assignable)
+    typedef LoKi::Assignable_t<GVFunVals> GVFunVal;
+    // type of "cut-val" for HepMC3GenVertex   (interface)
+    typedef LoKi::BasicFunctors<HepMC3::GenVertexPtr>::CutVal GVCutVals;
+    // type of "cut-val" for HepMC3GenVertex   (assignable)
+    typedef LoKi::Assignable_t<GVCutVals> GVCutVal;
+    // type of "source" for HepMC3GenVertex   (interface)
+    typedef LoKi::BasicFunctors<HepMC3::GenVertexPtr>::Source GVSources;
+    // type of "source" for HepMC3GenVertex   (assignable)
+    typedef LoKi::Assignable_t<GVSources> GVSource;
+    //
+    // ========================================================================
+  } // end of namespace GenTypes
+  // ==========================================================================
+  namespace Types {
+    // ========================================================================
+    /// type of 'cuts' for HepMC3::GenParticle       (interface)
+    typedef LoKi::GenTypes::GCuts GCuts;
+    /// type of 'functions' for HepMC3::GenParticle  (interface)
+    typedef LoKi::GenTypes::GFunc GFunc;
+    /// type of 'cuts' for HepMC3::GenParticle       (assignable)
+    typedef LoKi::GenTypes::GCut GCut;
+    /// type of 'functions' for HepMC3::GenParticle  (assignable)
+    typedef LoKi::GenTypes::GFun GFun;
+    /// type of 'cuts' for HepMC3::GenVertex       (interface)
+    typedef LoKi::GenTypes::GVCuts GVCuts;
+    /// type of 'functions' for HepMC3::GenVertex  (interface)
+    typedef LoKi::GenTypes::GVFunc GVFunc;
+    /// type of 'cuts' for HepMC3::GenVertex       (assignable)
+    typedef LoKi::GenTypes::GVCut GVCut;
+    /// type of 'functions' for HepMC3::GenVertex  (assignable)
+    typedef LoKi::GenTypes::GVFun GVFun;
+    /// the actual type of the range of HepMC3-particles
+    typedef LoKi::GenTypes::GRange GRange;
+    /// the actual type of the range of HepMC3-vertices
+    typedef LoKi::GenTypes::GVRange GVRange;
+    /// Range list for HepMC3-particles:
+    typedef LoKi::RangeList_<GRange> GRangeL;
+    /// Range list for HepMC3-vertices
+    typedef LoKi::RangeList_<GVRange> GVRangeL;
+    //
+
+    // functional types for HepMC3::GenParticle
+
+    // type of "map" for HepMC3::GenParticle  (interface)
+    typedef LoKi::GenTypes::GMaps GMaps;
+    // type of "map" for HepMC3::GenParticle  (assignable)
+    typedef LoKi::GenTypes::GMap GMap;
+    // type of "pipe" for HepMC3::GenParticle  (interface)
+    typedef LoKi::GenTypes::GPipes GPipes;
+    // type of "pipe" for HepMC3::GenParticle  (assignable)
+    typedef LoKi::GenTypes::GPipe GPipe;
+    // type of "fun-val" for HepMC3::GenParticle  (interface)
+    typedef LoKi::GenTypes::GFunVals GFunVals;
+    // type of "fun-val" for HepMC3::GenParticle  (assignable)
+    typedef LoKi::GenTypes::GFunVal GFunVal;
+    // type of "cut-val" for HepMC3::GenParticle  (interface)
+    typedef LoKi::GenTypes::GCutVals GCutVals;
+    // type of "cut-val" for HepMC3::GenParticle  (assignable)
+    typedef LoKi::GenTypes::GCutVal GCutVal;
+    // type of "source" for HepMC3::GenParticle  (interface)
+    typedef LoKi::GenTypes::GSources GSources;
+    // type of "source" for HepMC3::GenParticle  (assignable)
+    typedef LoKi::GenTypes::GSource GSource;
+
+    // functional types for HepMC3::GenVertex
+
+    // type of "map" for HepMC3::GenVertex  (interface)
+    typedef LoKi::GenTypes::GVMaps GVMaps;
+    // type of "map" for HepMC3::GenVertex  (assignable)
+    typedef LoKi::GenTypes::GVMap GVMap;
+    // type of "pipe" for HepMC3::GenVertex  (interface)
+    typedef LoKi::GenTypes::GVPipes GVPipes;
+    // type of "pipe" for HepMC3::GenVertex  (assignable)
+    typedef LoKi::GenTypes::GVPipe GVPipe;
+    // type of "fun-val" for HepMC3::GenVertex  (interface)
+    typedef LoKi::GenTypes::GVFunVals GVFunVals;
+    // type of "fun-val" for HepMC3::GenVertex  (assignable)
+    typedef LoKi::GenTypes::GVFunVal GVFunVal;
+    // type of "cut-val" for HepMC3::GenVertex  (interface)
+    typedef LoKi::GenTypes::GVCutVals GVCutVals;
+    // type of "cut-val" for HepMC3::GenVertex  (assignable)
+    typedef LoKi::GenTypes::GVCutVal GVCutVal;
+    // type of "source" for HepMC3::GenVertex  (interface)
+    typedef LoKi::GenTypes::GVSources GVSources;
+    // type of "source" for HepMC3::GenVertex  (assignable)
+    typedef LoKi::GenTypes::GVSource GVSource;
+    // ========================================================================
+  } //                                                   end of namespace Types
+  // ==========================================================================
+} //                                                      end of namespace LoKi
+// ============================================================================
+namespace LoKi {
+  // ==========================================================================
+  // the specialized printout
+  // ==========================================================================
+  template <>
+  inline std::ostream& Constant<HepMC3::ConstGenParticlePtr, bool>::fillStream( std::ostream& s ) const {
+    return s << ( this->m_value ? "GALL" : "GNONE" );
+  }
+  // ==========================================================================
+  // the specialized printout
+  // ==========================================================================
+  template <>
+  inline std::ostream& Constant<HepMC3::ConstGenVertexPtr, bool>::fillStream( std::ostream& s ) const {
+    return s << ( this->m_value ? "GVALL" : "GVNONE" );
+  }
+  // ==========================================================================
+} //                                                      end of namespace LoKi
+// ============================================================================
+// a little bit of streamers
+// ============================================================================
+GAUDI_API
+LoKi::GenTypes::GenContainer operator>>( const LoKi::GenTypes::GenContainer& input, const LoKi::Types::GCuts& cuts );
+// ============================================================================
+GAUDI_API
+LoKi::GenTypes::GenContainer operator>>( const LoKi::GenTypes::GRange& input, const LoKi::Types::GCuts& cuts );
+// ============================================================================
+GAUDI_API
+LoKi::GenTypes::GenContainer operator>>( const HepMC3::GenEvent* event, const LoKi::Types::GCuts& cuts );
+// ============================================================================
+//                                                                      The END
+// ============================================================================
+#endif // LOKI_GENTYPES_H
diff --git a/Gen/LoKiGen/LoKi/GenVertexCuts.h b/Gen/LoKiGen/LoKi/GenVertexCuts.h
new file mode 100644
index 000000000..86385a42b
--- /dev/null
+++ b/Gen/LoKiGen/LoKi/GenVertexCuts.h
@@ -0,0 +1,274 @@
+/*****************************************************************************\
+* (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration      *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                             *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+// ============================================================================
+#ifndef LOKI_GENVERTEXCUTS_H
+#define LOKI_GENVERTEXCUTS_H 1
+// ============================================================================
+// Include files
+// ============================================================================
+// HepMC3
+// ============================================================================
+#include "HepMC3/GenVertex.h"
+// ============================================================================
+// LoKiGen
+// ============================================================================
+#include "LoKi/GenTypes.h"
+#include "LoKi/GenVertices.h"
+//
+#include "LoKi/Filters.h"
+// ============================================================================
+/** @file LoKi/GenVertexCuts.h
+ *
+ *  Collection of useful functions/predicates to deal with
+ *  HepMC3 generator information
+ *
+ *  This file is a part of LoKi project -
+ *    "C++ ToolKit  for Smart and Friendly Physics Analysis"
+ *
+ *  The package has been designed with the kind help from
+ *  Galina PAKHLOVA and Sergey BARSUK.  Many bright ideas,
+ *  contributions and advices from G.Raven, J.van Tilburg,
+ *  A.Golutvin, P.Koppenburg have been used in the design.
+ *
+ *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+ *  @date 2006-02-08
+ *
+ */
+// ============================================================================
+namespace LoKi {
+  // ==========================================================================
+  namespace Cuts {
+    // ========================================================================
+    /** @var GVTRUE
+     *  trivial predicate which always returns "true"
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date 2006-02-08
+     */
+    inline const auto GVTRUE = LoKi::BasicFunctors<HepMC3::ConstGenVertexPtr>::BooleanConstant{true};
+    // ========================================================================
+    /** @var GVFALSE
+     *  trivial predicate which always returns "false"
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date 2006-02-08
+     */
+    inline const auto GVFALSE = LoKi::BasicFunctors<HepMC3::ConstGenVertexPtr>::BooleanConstant{false};
+    // ========================================================================
+    /** @var GVALL
+     *  trivial predicate which always returns "true"
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date 2006-02-08
+     */
+    inline const auto GVALL = LoKi::BasicFunctors<HepMC3::ConstGenVertexPtr>::BooleanConstant{true};
+    // ========================================================================
+    /** @var GVNONE
+     *  trivial predicate which always returns "false"
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date 2006-02-08
+     */
+    inline const auto GVNONE = LoKi::BasicFunctors<HepMC3::ConstGenVertexPtr>::BooleanConstant{false};
+    // ========================================================================
+    /** @var GVONE
+     *  trivial function which always returns 1
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date 2006-02-08
+     */
+    inline const auto GVONE = LoKi::BasicFunctors<HepMC3::ConstGenVertexPtr>::Constant{1};
+    // ========================================================================
+    /** @var GVNULL
+     *  trivial function which always returns 0
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date 2006-02-08
+     */
+    inline const auto GVNULL = LoKi::BasicFunctors<HepMC3::ConstGenVertexPtr>::Constant{0};
+    // ========================================================================
+    /** @var GVZERO
+     *  trivial function which always returns 0
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date 2006-02-08
+     */
+    inline const auto GVZERO = LoKi::BasicFunctors<HepMC3::ConstGenVertexPtr>::Constant{0};
+    // ========================================================================
+    /** Minimum from 2 functions
+     *
+     *  @code
+     *
+     *  GVFun f1 = ... ;
+     *  GVFun f2 = ... ;
+     *
+     *  GVFun f = GVMIN( f1 , f2 ) ;
+     *
+     *  @endcode
+     *
+     *  @see LoKi::Min
+     */
+    typedef LoKi::Min<HepMC3::ConstGenVertexPtr> GVMIN;
+    // ========================================================================
+    /** Maximum from 2 functions
+     *
+     *  @code
+     *
+     *  GVFun f1 = ... ;
+     *  GVFun f2 = ... ;
+     *
+     *  GVFun f = GVMAX( f1 , f2 ) ;
+     *
+     *  @endcode
+     *
+     *  @see LoKi::MAX
+     */
+    typedef LoKi::Min<HepMC3::ConstGenVertexPtr> GVMAX;
+    // ========================================================================
+    /** @var GVBAR
+     *  trivial function which returns the "bar-code" for
+     *  HepMC3::GenVertex
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date 2006-02-08
+     */
+    inline const auto GVBAR = LoKi::GenVertices::BarCode{};
+    // ========================================================================
+    /** @var GVBARCODE
+     *  trivial function which returns the "bar-code" for
+     *  HepMC3::GenVertex
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date 2006-02-08
+     */
+    inline const auto GVBARCODE = LoKi::GenVertices::BarCode{};
+    // ========================================================================
+    /** @var GVX
+     *  trivial function which returns the X-position of
+     *  HepMC3::GenVertex
+     *  @see HepMC3::GenVertex
+     *  @see LoKi::GenVertices::PositionX
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date 2006-02-08
+     */
+    inline const auto GVX = LoKi::GenVertices::PositionX{};
+    // ========================================================================
+    /** @var GVY
+     *  trivial function which returns the X-position of
+     *  HepMC3::GenVertex
+     *  @see HepMC3::GenVertex
+     *  @see LoKi::GenVertices::PositionY
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date 2006-02-08
+     */
+    inline const auto GVY = LoKi::GenVertices::PositionY{};
+    // ========================================================================
+    /** @var GVZ
+     *  trivial function which returns the Z-position of
+     *  HepMC3::GenVertex
+     *  @see HepMC3::GenVertex
+     *  @see LoKi::GenVertices::PositionZ
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date 2006-02-08
+     */
+    inline const auto GVZ = LoKi::GenVertices::PositionZ{};
+    // ========================================================================
+    /** @var GVRHO
+     *  trivial function which returns the rho(zylindrical)-position of
+     *  HepMC3::GenVertex
+     *  @see HepMC3::GenVertex
+     *  @see LoKi::GenVertices::Rho
+     *  @author Vanya BELYAEV Ivan.Belyaev@itep.ru
+     *  @date 2012-02-13
+     */
+    inline const auto GVRHO = LoKi::GenVertices::Rho{};
+    // ========================================================================
+    /** @var GVT
+     *  trivial function which returns the T-position of
+     *  HepMC3::GenVertex
+     *  @see HepMC3::GenVertex
+     *  @see LoKi::GenVertices::PositionT
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date 2006-02-08
+     */
+    inline const auto GVT = LoKi::GenVertices::PositionT{};
+    // ========================================================================
+    /** @var GVTIME
+     *  trivial function which returns the T-position of
+     *  HepMC3::GenVertex
+     *  @see HepMC3::GenVertex
+     *  @see LoKi::GenVertices::PositionT
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date 2006-02-08
+     */
+    inline const auto GVTIME = LoKi::GenVertices::PositionT{};
+    // ========================================================================
+    /** the adapter function which counts number of particles
+     *  which satisfy certain criteria within the specified range
+     *
+     *  E.g. find the decay H -> b b~ X :
+     *
+     *  @code
+     *
+     *  // number of b-quarks withing children particles
+     *  GVFun num1 =  GVCOUNT( "b"  == GID , HepMC3::children ) ;
+     *
+     *  // number of b~-quarks withing children particles
+     *  GVFun num2 =  GVCOUNT( "b~" == GID , HepMC3::children ) ;
+     *
+     *  // use adapter function to End vertex
+     *  GFun num = GFAEVX ( num1 + num2 , 0 ) ;
+     *
+     *  // find the decay H -> b b :
+     *
+     *  const LHCB::HepMC3Events* events = ... ;
+     *
+     *  GCut decay = ( 2 == num ) && ( "H_10" == GID ) ;
+     *
+     *  const bool good = LoKi::GenAlgs::found ( events , decay ) ;
+     *
+     *  @endcode
+     *
+     *  @see HepMC3::GenVertex
+     *  @see HepMC3::GenParticle
+     *  @see LoKi::GenVertices::CountIF
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date 2006-02-08
+     */
+    typedef LoKi::GenVertices::CountIF GVCOUNT;
+    // ========================================================================
+    /** the adapter function which accumulated the value of
+     *  given function over the particles which satisfy
+     *  certain criteria within the specified range
+     *
+     *  Total energy of all stable daughter charged leptons:
+     *
+     *  @code
+     *
+     *  GVFun e1 = GVSUM( GE , HepMC3::descendants ,
+     *                           GCHARGED && GLEPTON ) ;
+     *
+     *  GFun eLep = GFAEVX( e1 )
+     *
+     *  HepMC3::ConstGenParticlePtr p = ... ;
+     *
+     *  const double eTot = eLep( p ) ;
+     *
+     *  @endcode
+     *
+     *  @see HepMC3::GenVertex
+     *  @see HepMC3::GenParticle
+     *  @see LoKi::Cuts::GFAEVX
+     *  @see LoKi::GenVertices::SumIF
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date 2006-02-08
+     */
+    typedef LoKi::GenVertices::SumIF GVSUM;
+    // ========================================================================
+    // ========================================================================
+  } // namespace Cuts
+  // ==========================================================================
+} //                                                      end of namespace LoKi
+// ============================================================================
+//                                                                      The END
+// ============================================================================
+#endif // LOKI_GENVERTEXCUTS_H
diff --git a/Gen/LoKiGen/LoKi/GenVertices.h b/Gen/LoKiGen/LoKi/GenVertices.h
new file mode 100644
index 000000000..5b683a0ee
--- /dev/null
+++ b/Gen/LoKiGen/LoKi/GenVertices.h
@@ -0,0 +1,294 @@
+/*****************************************************************************\
+* (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration      *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                             *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+// ============================================================================
+#ifndef LOKI_GENVERTICES_H
+#define LOKI_GENVERTICES_H 1
+// ============================================================================
+// Include files
+// ============================================================================
+// HepMC3
+// ============================================================================
+#include "HepMC3/GenVertex.h"
+#include "HepMC3/Relatives.h"
+// ============================================================================
+// LoKi
+// ============================================================================
+#include "LoKi/Constants.h"
+#include "LoKi/GenTypes.h"
+#include "LoKi/Kinematics.h"
+// ============================================================================
+/** @file LoKi/GenVertices.h
+ *
+ *  This file is a part of LoKi project -
+ *    "C++ ToolKit  for Smart and Friendly Physics Analysis"
+ *
+ *  The package has been designed with the kind help from
+ *  Galina PAKHLOVA and Sergey BARSUK.  Many bright ideas,
+ *  contributions and advices from G.Raven, J.van Tilburg,
+ *  A.Golutvin, P.Koppenburg have been used in the design.
+ *
+ *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+ *  @date 2006-02-08
+ *
+ */
+namespace LoKi {
+  // ==========================================================================
+  /** @namespace LoKi::GenVertices GenVertices.h LoKi/GenVertices.h
+   *
+   *  Collection of LoKi functions and predicates to manipulate with
+   *  generator (HepMC3) information
+   *
+   *  @author Vanya  BELYAEV ibelyaev@physics.syr.edu
+   *  @date   2006-02-08
+   */
+  namespace GenVertices {
+    // ========================================================================
+    /** @class BarCode
+     *  the most primitive function - it return the "barcode"
+     *  of HepMC3::GenVertex object
+     *
+     *  @see LoKi::Cuts::GVBAR
+     *  @see HepMC3::GenVertex
+     *
+     *  @author Vanya BELYAEV belyaev@lapp.in2p3.fr
+     *  @date   2005-03-26
+     */
+    struct GAUDI_API BarCode : LoKi::GenTypes::GVFunc {
+      // ======================================================================
+      /// MANDATORY: clone method ("virtual" constructor")
+      BarCode* clone() const override;
+      /// MANDATORY: the only one essential method
+      double operator()( const HepMC3::ConstGenVertexPtr & p ) const override;
+      /// "SHORT" representation, @see LoKi::AuxFunBase
+      std::ostream& fillStream( std::ostream& s ) const override;
+      // ======================================================================
+    };
+    // ========================================================================
+    /** @class PositionX
+     *
+     *  the most primitive function - it return the position
+     *  of HepMC3::GenVertex object
+     *
+     *  @see LoKi::Cuts::GVX
+     *  @see HepMC3::GenVertex
+     *
+     *  @author Vanya BELYAEV belyaev@lapp.in2p3.fr
+     *  @date   2005-03-26
+     */
+    struct GAUDI_API PositionX : LoKi::GenTypes::GVFunc {
+      // ======================================================================
+      /// MANDATORY: clone method ("virtual" constructor")
+      PositionX* clone() const override;
+      /// MANDATORY: the only one essential method
+      double operator()( const HepMC3::ConstGenVertexPtr & p ) const override;
+      /// "SHORT" representation, @see LoKi::AuxFunBase
+      std::ostream& fillStream( std::ostream& s ) const override;
+      // ======================================================================
+    };
+    // ========================================================================
+    /** @class PositionY
+     *
+     *  the most primitive function - it return the position
+     *  of HepMC3::GenVertex object
+     *
+     *  @see LoKi::Cuts::GVY
+     *  @see HepMC3::GenVertex
+     *
+     *  @author Vanya BELYAEV belyaev@lapp.in2p3.fr
+     *  @date   2005-03-26
+     */
+    struct GAUDI_API PositionY : LoKi::GenTypes::GVFunc {
+      // ======================================================================
+      /// MANDATORY: clone method ("virtual" constructor")
+      PositionY* clone() const override;
+      /// MANDATORY: the only one essential method
+      double operator()( const HepMC3::ConstGenVertexPtr & p ) const override;
+      /// "SHORT" representation, @see LoKi::AuxFunBase
+      std::ostream& fillStream( std::ostream& s ) const override;
+      // ======================================================================
+    };
+    // ========================================================================
+    /** @class PositionZ
+     *
+     *  the most primitive function - it return the position
+     *  of HepMC3::GenVertex object
+     *
+     *  @see LoKi::Cuts::GVZ
+     *  @see HepMC3::GenVertex
+     *
+     *  @author Vanya BELYAEV belyaev@lapp.in2p3.fr
+     *  @date   2005-03-26
+     */
+    struct GAUDI_API PositionZ : LoKi::GenTypes::GVFunc {
+      // ======================================================================
+      /// MANDATORY: clone method ("virtual" constructor")
+      PositionZ* clone() const override;
+      /// MANDATORY: the only one essential method
+      double operator()( const HepMC3::ConstGenVertexPtr & p ) const override;
+      /// "SHORT" representation, @see LoKi::AuxFunBase
+      std::ostream& fillStream( std::ostream& s ) const override;
+      // ======================================================================
+    };
+    // ========================================================================
+    /** @class PositionT
+     *
+     *  the most primitive function - it return the time component of
+     *  the position for HepMC3::GenVertex object
+     *
+     *  @see LoKi::Cuts::GVT
+     *  @see HepMC3::GenVertex
+     *
+     *  @author Vanya BELYAEV belyaev@lapp.in2p3.fr
+     *  @date   2005-03-26
+     */
+    struct GAUDI_API PositionT : LoKi::GenTypes::GVFunc {
+      // ======================================================================
+      /// MANDATORY: clone method ("virtual" constructor")
+      PositionT* clone() const override;
+      /// MANDATORY: the only one essential method
+      double operator()( const HepMC3::ConstGenVertexPtr & p ) const override;
+      /// "SHORT" representation, @see LoKi::AuxFunBase
+      std::ostream& fillStream( std::ostream& s ) const override;
+      // ======================================================================
+    };
+    // ========================================================================
+    /** @class Rho
+     *
+     *  the most primitive function - it return the rho-position (cylindrical)
+     *  HepMC3::GenVertex object
+     *
+     *  @see LoKi::Cuts::GVRHO
+     *  @see HepMC3::GenVertex
+     *
+     *  @author Vanya BELYAEV Ivan.Belyaev@itep.ru
+     *  @date   2012-02-13
+     */
+    struct GAUDI_API Rho : LoKi::GenTypes::GVFunc {
+      // ======================================================================
+      /// MANDATORY: clone method ("virtual" constructor")
+      Rho* clone() const override;
+      /// MANDATORY: the only one essential method
+      double operator()( const HepMC3::ConstGenVertexPtr & p ) const override;
+      /// "SHORT" representation, @see LoKi::AuxFunBase
+      std::ostream& fillStream( std::ostream& s ) const override;
+      // ======================================================================
+    };
+    // ========================================================================
+    /** @class CountIF
+     *  simple class which counts how many particles
+     *  satisfy the certain criteria
+     *
+     *  @see LoKi::Cuts::GVCOUNT
+     *  @see HepMC3::GenParticle
+     *  @see HepMC3::GenVertex
+     *
+     *  @author Vanya BELYAEV belyaev@lapp.in2p3.fr
+     *  @date   2005-03-26
+     */
+    class GAUDI_API CountIF : public LoKi::GenTypes::GVFunc {
+    public:
+      // ======================================================================
+      /** constructor from the criteria and "range"
+       *  @param cut the criteria
+       *  @param range search region
+       *  @see const HepMC3::Relatives &
+       */
+      CountIF( const LoKi::Types::GCuts& cut, const HepMC3::Relatives & range );
+      /** constructor from the criteria and "range"
+       *  @param range search region
+       *  @param cut the criteria
+       *  @see const HepMC3::Relatives &
+       */
+      CountIF( const HepMC3::Relatives & range, const LoKi::Types::GCuts& cut );
+      /// MANDATORY: clone method ("virtual contructor")
+      CountIF* clone() const override;
+      /// MANDATORY: the only one essential method
+      double operator()( const HepMC3::ConstGenVertexPtr & v ) const override;
+      /// "SHORT" representation, @see LoKi::AuxFunBase
+      std::ostream& fillStream( std::ostream& s ) const override;
+      // ======================================================================
+    private:
+      // ======================================================================
+      LoKi::Types::GCut    m_cut;
+      const HepMC3::Relatives & m_range;
+      // ======================================================================
+    };
+    // ========================================================================
+    /** @class SumIF
+     *  simple class which accumulates the function values
+     *  for particles from the given range which
+     *  satisfy the certain criteria
+     *
+     *  @see LoKi::Cuts::GVSUM
+     *  @see HepMC3::GenParticle
+     *  @see HepMC3::GenVertex
+     *
+     *  @author Vanya BELYAEV belyaev@lapp.in2p3.fr
+     *  @date   2005-03-26
+     */
+    class GAUDI_API SumIF : public LoKi::GenTypes::GVFunc {
+    public:
+      // ======================================================================
+      /** constructor from the function and the "range"
+       *  @param fun function to be accuulated
+       *  @param range search region
+       *  @see const HepMC3::Relatives &
+       */
+      SumIF( const LoKi::Types::GFunc& fun, const HepMC3::Relatives & range );
+      /** constructor from the function and the "range"
+       *  @param fun function to be accuulated
+       *  @param range search region
+       *  @see const HepMC3::Relatives &
+       */
+      SumIF( const HepMC3::Relatives & range, const LoKi::Types::GFunc& fun );
+      /** constructor from the function, "range" and criteria
+       *  @param fun function to be accuulated
+       *  @param range search region
+       *  @param cut the criteria
+       *  @see const HepMC3::Relatives &
+       */
+      SumIF( const LoKi::Types::GFunc& fun, const HepMC3::Relatives & range, const LoKi::Types::GCuts& cut );
+      /** constructor from the function, "range" and criteria
+       *  @param fun function to be accuulated
+       *  @param cut the criteria
+       *  @param range search region
+       *  @see const HepMC3::Relatives &
+       */
+      SumIF( const LoKi::Types::GFunc& fun, const LoKi::Types::GCuts& cut, const HepMC3::Relatives & range );
+      /** constructor from the function, "range" and criteria
+       *  @param cut the criteria
+       *  @param fun function to be accuulated
+       *  @param range search region
+       *  @see const HepMC3::Relatives &
+       */
+      SumIF( const LoKi::Types::GCuts& cut, const LoKi::Types::GFunc& fun, const HepMC3::Relatives & range );
+      /// MANDATORY: clone method ("virtual contructor")
+      SumIF* clone() const override;
+      /// MANDATORY: the only one essential method
+      double operator()( const HepMC3::ConstGenVertexPtr & v ) const override;
+      /// "SHORT" representation, @see LoKi::AuxFunBase
+      std::ostream& fillStream( std::ostream& s ) const override;
+      // ======================================================================
+    private:
+      // ======================================================================
+      LoKi::Types::GFun    m_fun;
+      LoKi::Types::GCut    m_cut;
+      const HepMC3::Relatives & m_range;
+      // ======================================================================
+    };
+    // ========================================================================
+  } // namespace GenVertices
+  // ==========================================================================
+} //                                                      end of namespace LoKi
+// ============================================================================
+//                                                                      The END
+// ============================================================================
+#endif // LOKI_GENVERTICES_H
diff --git a/Gen/LoKiGen/LoKi/IGenDecay.h b/Gen/LoKiGen/LoKi/IGenDecay.h
new file mode 100644
index 000000000..646eabd6f
--- /dev/null
+++ b/Gen/LoKiGen/LoKi/IGenDecay.h
@@ -0,0 +1,72 @@
+/*****************************************************************************\
+* (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration      *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                             *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+// ============================================================================
+#ifndef LOKI_IGENDECAY_H
+#define LOKI_IGENDECAY_H 1
+// ============================================================================
+// Include files
+// ============================================================================
+// LoKi
+// ============================================================================
+#include "LoKi/DecayFinder.h"
+#include "LoKi/IDecayNode.h"
+#include "LoKi/iTree.h"
+// ============================================================================
+// forward declaration
+// ============================================================================
+#include "HepMC3/GenParticle_fwd.h"
+// ============================================================================
+/** @file LoKi/IGenDecay.h
+ *
+ *  This file is a part of LoKi project -
+ *    "C++ ToolKit  for Smart and Friendly Physics Analysis"
+ *
+ *  The package has been designed with the kind help from
+ *  Galina PAKHLOVA and Sergey BARSUK.  Many bright ideas,
+ *  contributions and advices from G.Raven, J.van Tilburg,
+ *  A.Golutvin, P.Koppenburg have been used in the design.
+ *
+ *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+ *  @date 2001-01-23
+ *
+ */
+// ============================================================================
+namespace Decays {
+  // ==========================================================================
+  /** @class IGenDecay LoKi/IGenDecay.h
+   *  New "Decay Finder"
+   *  @author Ivan BELYAEV
+   *  @date   2009-05-22
+   */
+  struct GAUDI_API IGenDecay : extend_interfaces<IDecayNode> {
+    // ========================================================================
+    /// the actual type of the tree
+    typedef Decays::Tree_<HepMC3::ConstGenParticlePtr> Tree;
+    /// the actual type of the tree
+    typedef Decays::iTree_<HepMC3::ConstGenParticlePtr> iTree;
+    /// the actual type of decay finder:
+    typedef Decays::Finder_<HepMC3::ConstGenParticlePtr> Finder;
+    // ========================================================================
+    /** create the decay tree from the descriptor
+     *  @param descriptor (INPUT)  the decay descriptor
+     *  @param tree       (OUTPUT) the decay tree
+     */
+    virtual Tree tree( const std::string& decay = "" ) const = 0;
+    // ========================================================================
+    DeclareInterfaceID( IGenDecay, 2, 0 );
+    // ========================================================================
+  };
+  // ==========================================================================
+} //                                                    end of namespace Decays
+// ============================================================================
+//                                                                      The END
+// ============================================================================
+#endif // LOKI_IGENDECAY_H
diff --git a/Gen/LoKiGen/LoKi/IGenHybridFactory.h b/Gen/LoKiGen/LoKi/IGenHybridFactory.h
new file mode 100644
index 000000000..b8e96694e
--- /dev/null
+++ b/Gen/LoKiGen/LoKi/IGenHybridFactory.h
@@ -0,0 +1,181 @@
+/*****************************************************************************\
+* (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration      *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                             *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+// ============================================================================
+#ifndef LOKI_IGENHYBRIDFACTORY_H
+#define LOKI_IGENHYBRIDFACTORY_H 1
+// ============================================================================
+// Include files
+// ============================================================================
+// STD & STL
+// ============================================================================
+#include <string>
+// ============================================================================
+// GaudiKernel
+// ============================================================================
+#include "GaudiKernel/IAlgTool.h"
+#include "GaudiKernel/StatusCode.h"
+// ============================================================================
+// LoKi
+// ============================================================================
+#include "LoKi/GenTypes.h"
+// ============================================================================
+/** @file LoKi/IGenHybridFactory.h
+ *
+ *  This file is a part of LoKi project -
+ *    "C++ ToolKit  for Smart and Friendly Physics Analysis"
+ *
+ *  The package has been designed with the kind help from
+ *  Galina PAKHLOVA and Sergey BARSUK.  Many bright ideas,
+ *  contributions and advices from G.Raven, J.van Tilburg,
+ *  A.Golutvin, P.Koppenburg have been used in the design.
+ *
+ */
+namespace LoKi {
+  // ==========================================================================
+  /** @class IGenHybridFactory IMCHybridFactory.h LoKi/IMCHybridFactory.h
+   *  The abstract interface to "hybrid factory"
+   *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+   *  @date   2007-06-10
+   */
+  struct GAUDI_API IGenHybridFactory : extend_interfaces<IAlgTool> {
+    // ========================================================================
+    DeclareInterfaceID( IGenHybridFactory, 5, 0 );
+    // ========================================================================
+    // predicates
+    // ========================================================================
+    /** "Factory": get the the object form python code
+     *  @param pycode the python pseudo-code of the function
+     *  @param cuts the placeholder for the result
+     *  @param context context code fragment to be executed
+     *  @return StatusCode
+     */
+    virtual StatusCode get( const std::string& pycode, LoKi::Types::GCut& cuts, const std::string& context = "" ) = 0;
+    // ========================================================================
+    /** "Factory": get the the object form python code
+     *  @param pycode the python pseudo-code of the function
+     *  @param cuts the placeholder for the result
+     *  @param context context code fragment to be executed
+     *  @return StatusCode
+     */
+    virtual StatusCode get( const std::string& pycode, LoKi::Types::GVCut& cuts, const std::string& context = "" ) = 0;
+    // ========================================================================
+    // functions
+    // ========================================================================
+    /** "Factory": get the the object form python code
+     *  @param pycode the python pseudo-code of the function
+     *  @param func the placeholder for the result
+     *  @param context context code fragment to be executed
+     *  @return StatusCode
+     */
+    virtual StatusCode get( const std::string& pycode, LoKi::Types::GFun& func, const std::string& context = "" ) = 0;
+    // ========================================================================
+    /** "Factory": get the the object form python code
+     *  @param pycode the python pseudo-code of the function
+     *  @param func the placeholder for the result
+     *  @param context context code fragment to be executed
+     *  @return StatusCode
+     */
+    virtual StatusCode get( const std::string& pycode, LoKi::Types::GVFun& func, const std::string& context = "" ) = 0;
+    // ========================================================================
+    // maps
+    // ========================================================================
+    /** "Factory": get the the object form python code
+     *  @param pycode the python pseudo-code of the function
+     *  @param func the placeholder for the result
+     *  @param context context code fragment to be executed
+     *  @return StatusCode
+     */
+    virtual StatusCode get( const std::string& pycode, LoKi::Types::GMap& func, const std::string& context = "" ) = 0;
+    // ========================================================================
+    /** "Factory": get the the object form python code
+     *  @param pycode the python pseudo-code of the function
+     *  @param func the placeholder for the result
+     *  @param context context code fragment to be executed
+     *  @return StatusCode
+     */
+    virtual StatusCode get( const std::string& pycode, LoKi::Types::GVMap& func, const std::string& context = "" ) = 0;
+    // ========================================================================
+    // pipes
+    // ========================================================================
+    /** "Factory": get the the object form python code
+     *  @param pycode the python pseudo-code of the function
+     *  @param func the placeholder for the result
+     *  @param context context code fragment to be executed
+     *  @return StatusCode
+     */
+    virtual StatusCode get( const std::string& pycode, LoKi::Types::GPipe& func, const std::string& context = "" ) = 0;
+    // ========================================================================
+    /** "Factory": get the the object form python code
+     *  @param pycode the python pseudo-code of the function
+     *  @param func the placeholder for the result
+     *  @param context context code fragment to be executed
+     *  @return StatusCode
+     */
+    virtual StatusCode get( const std::string& pycode, LoKi::Types::GVPipe& func, const std::string& context = "" ) = 0;
+    // ========================================================================
+    // fun-vals
+    // ========================================================================
+    /** "Factory": get the the object form python code
+     *  @param pycode the python pseudo-code of the function
+     *  @param func the placeholder for the result
+     *  @param context context code fragment to be executed
+     *  @return StatusCode
+     */
+    virtual StatusCode get( const std::string& pycode, LoKi::Types::GFunVal& func,
+                            const std::string& context = "" ) = 0;
+    // ========================================================================
+    /** "Factory": get the the object form python code
+     *  @param pycode the python pseudo-code of the function
+     *  @param func the placeholder for the result
+     *  @param context context code fragment to be executed
+     *  @return StatusCode
+     */
+    virtual StatusCode get( const std::string& pycode, LoKi::Types::GVFunVal& func,
+                            const std::string& context = "" ) = 0;
+    // ========================================================================
+    // cut-vals
+    // ========================================================================
+    /** "Factory": get the the object form python code
+     *  @param pycode the python pseudo-code of the function
+     *  @param func the placeholder for the result
+     *  @param context context code fragment to be executed
+     *  @return StatusCode
+     */
+    virtual StatusCode get( const std::string& pycode, LoKi::Types::GCutVal& func,
+                            const std::string& context = "" ) = 0;
+    // ========================================================================
+    // sources
+    // ========================================================================
+    /** "Factory": get the the object form python code
+     *  @param pycode the python pseudo-code of the function
+     *  @param func the placeholder for the result
+     *  @param context context code fragment to be executed
+     *  @return StatusCode
+     */
+    virtual StatusCode get( const std::string& pycode, LoKi::Types::GSource& func,
+                            const std::string& context = "" ) = 0;
+    // ========================================================================
+    /** "Factory": get the the object form python code
+     *  @param pycode the python pseudo-code of the function
+     *  @param func the placeholder for the result
+     *  @param context context code fragment to be executed
+     *  @return StatusCode
+     */
+    virtual StatusCode get( const std::string& pycode, LoKi::Types::GVSource& func,
+                            const std::string& context = "" ) = 0;
+    // ========================================================================
+  };
+  // ==========================================================================
+} //                                                      end of namespace LoKi
+// ============================================================================
+//                                                                      The END
+// ============================================================================
+#endif // LOKI_IGENHYBRIDFACTORY_H
diff --git a/Gen/LoKiGen/LoKi/IGenHybridTool.h b/Gen/LoKiGen/LoKi/IGenHybridTool.h
new file mode 100644
index 000000000..3e80078ee
--- /dev/null
+++ b/Gen/LoKiGen/LoKi/IGenHybridTool.h
@@ -0,0 +1,104 @@
+/*****************************************************************************\
+* (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration      *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                             *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+// ============================================================================
+#ifndef LOKI_IGENHYBRIDTOOL_H
+#define LOKI_IGENHYBRIDTOOL_H 1
+// ============================================================================
+// Include files
+// ============================================================================
+// STD & STL
+// ============================================================================
+#include <string>
+// ============================================================================
+// from Gaudi
+// ============================================================================
+#include "GaudiKernel/IAlgTool.h"
+#include "GaudiKernel/StatusCode.h"
+// ============================================================================
+// LoKi
+// ============================================================================
+#include "LoKi/GenTypes.h"
+// ============================================================================
+namespace LoKi {
+  // ==========================================================================
+  /** @class IGenHybridTool LoKi/IGenHybridTool.h
+   *
+   *  Helper interface for implementation of C++/Python "Hybrid" solution
+   *
+   *  This file is a part of LoKi project -
+   *    "C++ ToolKit  for Smart and Friendly Physics Analysis"
+   *
+   *  The package has been designed with the kind help from
+   *  Galina PAKHLOVA and Sergey BARSUK.  Many bright ideas,
+   *  contributions and advices from G.Raven, J.van Tilburg,
+   *  A.Golutvin, P.Koppenburg have been used in the design.
+   *
+   *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+   *  @date   2004-06-29
+   */
+  struct GAUDI_API IGenHybridTool : extend_interfaces<IAlgTool> {
+    // ========================================================================
+    DeclareInterfaceID( IGenHybridTool, 5, 0 );
+    // ========================================================================
+    // predicates:
+    // ========================================================================
+    /// set the C++ predicate for HepMC3::GenParticle
+    virtual void set( const LoKi::Types::GCuts& cut ) = 0;
+    /// set the C++ predicate for HepMC3::GenVertex
+    virtual void set( const LoKi::Types::GVCuts& cut ) = 0;
+    // ========================================================================
+    // functions
+    // ========================================================================
+    /// set the C++ function for HepMC3::GenParticle
+    virtual void set( const LoKi::Types::GFunc& cut ) = 0;
+    /// set the C++ function for HepMC3::GenVertex
+    virtual void set( const LoKi::Types::GVFunc& cut ) = 0;
+    // ========================================================================
+    // maps
+    // ========================================================================
+    /// set the C++ function for HepMC3::GenParticle
+    virtual void set( const LoKi::Types::GMaps& cut ) = 0;
+    /// set the C++ function for HepMC3::GenVertex
+    virtual void set( const LoKi::Types::GVMaps& cut ) = 0;
+    // ========================================================================
+    // pipes
+    // ========================================================================
+    /// set the C++ function for HepMC3::GenParticle
+    virtual void set( const LoKi::Types::GPipes& cut ) = 0;
+    /// set the C++ function for HepMC3::GenVertex
+    virtual void set( const LoKi::Types::GVPipes& cut ) = 0;
+    // ========================================================================
+    // fun-vals
+    // ========================================================================
+    /// set the C++ function for HepMC3::GenParticle
+    virtual void set( const LoKi::Types::GFunVals& cut ) = 0;
+    /// set the C++ function for HepMC3::GenVertex
+    virtual void set( const LoKi::Types::GVFunVals& cut ) = 0;
+    // ========================================================================
+    // cut-vals
+    // ========================================================================
+    /// set the C++ function for HepMC3::GenParticle
+    virtual void set( const LoKi::Types::GCutVals& cut ) = 0;
+    // ========================================================================
+    // sources
+    // ========================================================================
+    /// set the C++ function for HepMC3::GenParticle
+    virtual void set( const LoKi::Types::GSources& cut ) = 0;
+    /// set the C++ function for HepMC3::GenVertex
+    virtual void set( const LoKi::Types::GVSources& cut ) = 0;
+    // ========================================================================
+  };
+  // ==========================================================================
+} //                                                      end of namespace LoKi
+// ============================================================================
+//                                                                      The END
+// ============================================================================
+#endif // LOKI_IGENHYBRIDTOOL_H
diff --git a/Gen/LoKiGen/LoKi/LoKiGen.h b/Gen/LoKiGen/LoKi/LoKiGen.h
new file mode 100644
index 000000000..d6a904755
--- /dev/null
+++ b/Gen/LoKiGen/LoKi/LoKiGen.h
@@ -0,0 +1,50 @@
+/*****************************************************************************\
+* (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration      *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                             *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+// ============================================================================
+#ifndef LOKI_LOKIGEN_H
+#define LOKI_LOKIGEN_H 1
+// ============================================================================
+// Include files
+// ============================================================================
+#include "LoKi/MoreFunctions.h"
+// ============================================================================
+#include "LoKi/BuildGenTrees.h"
+#include "LoKi/GenAlgs.h"
+#include "LoKi/GenChild.h"
+#include "LoKi/GenExtract.h"
+#include "LoKi/GenKinematics.h"
+#include "LoKi/GenParticleCuts.h"
+#include "LoKi/GenParticles.h"
+#include "LoKi/GenSources.h"
+#include "LoKi/GenTypes.h"
+#include "LoKi/GenVertexCuts.h"
+#include "LoKi/GenVertices.h"
+#include "LoKi/IGenHybridFactory.h"
+#include "LoKi/PrintHepMCDecay.h"
+// ============================================================================
+/** @file LoKi/LoKiGen.h
+ *
+ *  This file is a part of LoKi project -
+ *    "C++ ToolKit  for Smart and Friendly Physics Analysis"
+ *
+ *  The package has been designed with the kind help from
+ *  Galina PAKHLOVA and Sergey BARSUK.  Many bright ideas,
+ *  contributions and advices from G.Raven, J.van Tilburg,
+ *  A.Golutvin, P.Koppenburg have been used in the design.
+ *
+ *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+ *  @date 2001-01-23
+ *
+ */
+// ============================================================================
+// The END
+// ============================================================================
+#endif // LOKI_LOKIGEN_H
diff --git a/Gen/LoKiGen/LoKi/LoKiGen_dct.h b/Gen/LoKiGen/LoKi/LoKiGen_dct.h
new file mode 100644
index 000000000..a7bc70907
--- /dev/null
+++ b/Gen/LoKiGen/LoKi/LoKiGen_dct.h
@@ -0,0 +1,422 @@
+/*****************************************************************************\
+* (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration      *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                             *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+// ============================================================================
+#ifndef LOKI_LOKIGEN_DCT_H
+#define LOKI_LOKIGEN_DCT_H 1
+// ============================================================================
+// Include files
+// ============================================================================
+// HepMC3
+// ============================================================================
+#ifdef __INTEL_COMPILER
+#  pragma warning( disable : 1572 ) // floating-point equality and inequality comparisons are unreliable
+#  pragma warning( push )
+#endif
+// ============================================================================
+#include "HepMC3/GenParticle.h"
+#include "HepMC3/GenVertex.h"
+// ============================================================================
+#ifdef __INTEL_COMPILER
+#  pragma warning( pop )
+#endif
+// ============================================================================
+// LoKi
+// ============================================================================
+#include "LoKi/Keeper.h"
+#include "LoKi/LoKiGen.h"
+#include "LoKi/Monitoring.h"
+#include "LoKi/Operators.h"
+#include "LoKi/TreeOps.h"
+#include "LoKi/Trees.h"
+#include "LoKi/UniqueKeeper.h"
+// ============================================================================
+#include "LoKi/Dicts.h"
+#include "LoKi/GenAlgsDicts.h"
+#include "LoKi/GenChildSelector.h"
+#include "LoKi/GenDecayChain.h"
+#include "LoKi/GenDecays.h"
+#include "LoKi/GenDump.h"
+#include "LoKi/GenExtractDicts.h"
+#include "LoKi/GenMoniDicts.h"
+#include "LoKi/GenParticles.h"
+#include "LoKi/GenParticles2.h"
+#include "LoKi/GenParticles3.h"
+#include "LoKi/GenParticles4.h"
+#include "LoKi/GenParticles5.h"
+// ============================================================================
+#include "LoKi/FinderDict.h"
+#include "LoKi/IGenDecay.h"
+// ============================================================================
+#include "LoKi/GenHybridEngine.h"
+#include "LoKi/IGenHybridTool.h"
+// ============================================================================
+/** @file
+ *  The dictionaries for the package Phys/LoKiGen
+ *
+ *  This file is a part of LoKi project -
+ *    "C++ ToolKit  for Smart and Friendly Physics Analysis"
+ *
+ *  The package has been designed with the kind help from
+ *  Galina PAKHLOVA and Sergey BARSUK.  Many bright ideas,
+ *  contributions and advices from G.Raven, J.van Tilburg,
+ *  A.Golutvin, P.Koppenburg have been used in the design.
+ *
+ *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+ *  @date 2007-12-01
+ */
+// ============================================================================
+namespace LoKi {
+  // ==========================================================================
+  namespace Functors {
+    // ========================================================================
+    // the specialized printout
+    // ========================================================================
+    template <>
+    inline std::ostream& Empty<HepMC3::ConstGenVertexPtr>::fillStream( std::ostream& s ) const {
+      return s << "GVEMPTY";
+    }
+    // ========================================================================
+    // the specialized printout
+    // ========================================================================
+    template <>
+    inline std::ostream& Empty<HepMC3::ConstGenParticlePtr>::fillStream( std::ostream& s ) const {
+      return s << "GEMPTY ";
+    }
+    // ========================================================================
+    // the specialized printout
+    // ========================================================================
+    template <>
+    inline std::ostream& Size<HepMC3::ConstGenVertexPtr>::fillStream( std::ostream& s ) const {
+      return s << "GVSIZE";
+    }
+    // ========================================================================
+    // the specialized printout
+    // ========================================================================
+    template <>
+    inline std::ostream& Size<HepMC3::ConstGenParticlePtr>::fillStream( std::ostream& s ) const {
+      return s << "GSIZE ";
+    }
+    // ========================================================================
+  } // namespace Functors
+  // ==========================================================================
+} //                                                      end of namespace LoKi
+// ============================================================================
+namespace LoKi {
+  // ==========================================================================
+  namespace Dicts {
+    // ========================================================================
+    template <>
+    class FunCalls<HepMC3::GenParticle> {
+    private:
+      // ======================================================================
+      typedef HepMC3::ConstGenParticlePtr                         Type;
+      typedef LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::Function Fun;
+      typedef LoKi::details::result_t<Fun>               result_type;
+      // ======================================================================
+    public:
+      // ======================================================================
+      // __call__
+      static result_type __call__( const Fun& fun, const Type& o ) { return fun( o ); }
+      // ======================================================================
+      // __rrshift__
+      static result_type __rrshift__( const Fun& fun, const Type& o ) { return o >> fun; }
+      // __rrshift__
+      static std::vector<result_type> __rrshift__( const Fun& fun, const LoKi::GenTypes::GenContainer& o ) {
+        return o >> fun;
+      }
+      // ======================================================================
+      // _rshift_
+      static LoKi::FunctorFromFunctor<Type, double> __rshift__( const Fun&                           fun,
+                                                                       const LoKi::Functor<double, double>& o ) {
+        return fun >> o;
+      }
+      // _rshift_
+      static LoKi::FunctorFromFunctor<Type, bool> __rshift__( const Fun&                         fun,
+                                                                     const LoKi::Functor<double, bool>& o ) {
+        return fun >> o;
+      }
+      // ======================================================================
+    };
+    // ========================================================================
+    template <>
+    class CutCalls<HepMC3::GenParticle> {
+    private:
+      // ======================================================================
+      typedef HepMC3::ConstGenParticlePtr                          Type;
+      typedef LoKi::BasicFunctors<Type>::Predicate Fun;
+      typedef LoKi::details::result_t<Fun>                result_type;
+      // ======================================================================
+    public:
+      // ======================================================================
+      // __call__
+      static result_type __call__( const Fun& fun, const Type& o ) { return fun( o ); }
+      //
+      // __call__ as filter
+      //
+      // __call__
+      static LoKi::GenTypes::GenContainer __call__( const Fun& fun, const LoKi::GenTypes::GenContainer& o ) {
+        return o >> fun;
+      }
+      // __call__
+      static LoKi::GenTypes::GenContainer __call__( const Fun& fun, const LoKi::GenTypes::GRange& o ) {
+        return o >> fun;
+      }
+      // __call__
+      static LoKi::GenTypes::GenContainer __call__( const Fun& fun, const HepMC3::GenEvent* e ) { return e >> fun; }
+      // ======================================================================
+    public:
+      // ======================================================================
+      // __rrshift__
+      static result_type __rrshift__( const Fun& fun, const Type& o ) { return o >> fun; }
+      //
+      // rrshift as "filter"
+      //
+      // __rrshift__
+      static LoKi::GenTypes::GenContainer __rrshift__( const Fun& fun, const LoKi::GenTypes::GenContainer& o ) {
+        return o >> fun;
+      }
+      // __rrshift__
+      static LoKi::GenTypes::GenContainer __rrshift__( const Fun& fun, const LoKi::GenTypes::GRange& o ) {
+        return o >> fun;
+      }
+      // __rrshift__
+      static LoKi::GenTypes::GenContainer __rrshift__( const Fun& fun, const HepMC3::GenEvent* e ) { return e >> fun; }
+      // ======================================================================
+    public:
+      // ======================================================================
+      // __rshift__
+      static LoKi::FunctorFromFunctor<Type, bool> __rshift__( const Fun& fun, const Fun& o ) { return fun >> o; }
+      // ======================================================================
+    };
+    // ========================================================================
+    template <>
+    class FunCalls<HepMC3::GenVertex> {
+    private:
+      // ======================================================================
+      typedef HepMC3::ConstGenVertexPtr                           Type;
+      typedef LoKi::BasicFunctors<Type>::Function Fun;
+      typedef LoKi::details::result_t<Fun>               result_type;
+      // ======================================================================
+    public:
+      // ======================================================================
+      // __call__
+      static result_type __call__( const Fun& fun, const Type& o ) { return fun( o ); }
+      // ======================================================================
+    public:
+      // ======================================================================
+      // __rrshift__
+      static result_type __rrshift__( const Fun& fun, const Type& o ) { return o >> fun; }
+      // __rrshift__
+      static std::vector<result_type> __rrshift__( const Fun& fun, const LoKi::GenTypes::GenVContainer& o ) {
+        return o >> fun;
+      }
+      // ======================================================================
+    public:
+      // ======================================================================
+      // _rshift_
+      static LoKi::FunctorFromFunctor<Type, double> __rshift__( const Fun&                           fun,
+                                                                       const LoKi::Functor<double, double>& o ) {
+        return fun >> o;
+      }
+      // _rshift_
+      static LoKi::FunctorFromFunctor<Type, bool> __rshift__( const Fun&                         fun,
+                                                                     const LoKi::Functor<double, bool>& o ) {
+        return fun >> o;
+      }
+      // ======================================================================
+    };
+    // ========================================================================
+    template <>
+    class CutCalls<HepMC3::GenVertex> {
+    private:
+      // ======================================================================
+      typedef HepMC3::ConstGenVertexPtr                            Type;
+      typedef LoKi::BasicFunctors<Type>::Predicate Fun;
+      typedef LoKi::details::result_t<Fun>                result_type;
+      // ======================================================================
+    public:
+      // ======================================================================
+      // __call__
+      static result_type __call__( const Fun& fun, const Type& o ) { return fun( o ); }
+      // ======================================================================
+    public:
+      // ======================================================================
+      // __rrshift__
+      static result_type __rrshift__( const Fun& fun, const Type& o ) { return o >> fun; }
+      // __rrshift__
+      static const LoKi::GenTypes::GenVContainer __rrshift__( const Fun& fun, const LoKi::GenTypes::GenVContainer& o ) {
+        return o >> fun;
+      }
+      // ======================================================================
+    public:
+      // ======================================================================
+      // __rrshift__
+      static LoKi::FunctorFromFunctor<Type, bool> __rshift__( const Fun& fun, const Fun& o ) { return fun >> o; }
+      // ======================================================================
+    };
+    // ========================================================================
+  } // namespace Dicts
+  // ==========================================================================
+} // namespace LoKi
+// ============================================================================
+namespace LoKi {
+  // ==========================================================================
+  namespace Dicts {
+    // ========================================================================
+    template <>
+    struct FinderDicts_<HepMC3::ConstGenParticlePtr> {
+      // ======================================================================
+      /// get the actual "stripped" type
+      typedef HepMC3::ConstGenParticlePtr              TYPE;
+      typedef HepMC3::ConstGenParticlePtr              Type;
+      typedef std::vector<HepMC3::ConstGenParticlePtr> ConstVector;
+      // ======================================================================
+    public:
+      // ======================================================================
+      static bool __hasDecay__( const Decays::Finder_<TYPE>& finder, const ConstVector& input ) {
+        return finder.hasDecay( input.begin(), input.end() );
+      }
+      // ======================================================================
+      static bool __hasDecay__( const Decays::Finder_<TYPE>& finder, const HepMC3::GenEvent* event ) {
+        return event && finder.hasDecay( std::begin(event->particles()), std::end(event->particles()) );
+      }
+      // ======================================================================
+      static bool __hasDecay__( const Decays::Finder_<TYPE>& finder, HepMC3::ConstGenVertexPtr vertex,
+                                const HepMC3::Relatives & range ) {
+        if ( !vertex ) { return false; }
+        auto particles = range(vertex);
+        return finder.hasDecay( std::begin(particles), std::end(particles) );
+      }
+      // ======================================================================
+    public:
+      // ======================================================================
+      static size_t __findDecay__( const Decays::Finder_<TYPE>& finder, const ConstVector& input,
+                                   ConstVector& output ) {
+        return finder.findDecay( input.begin(), input.end(), output );
+      }
+      // ======================================================================
+      static size_t __findDecay__( const Decays::Finder_<TYPE>& finder, const HepMC3::GenEvent* event,
+                                   ConstVector& output ) {
+        return event ? finder.findDecay( std::begin(event->particles()), std::end(event->particles()), output ) : 0;
+      }
+      // ======================================================================
+      static size_t __findDecay__( const Decays::Finder_<TYPE>& finder, HepMC3::ConstGenVertexPtr vertex,
+                                   const HepMC3::Relatives & range, ConstVector& output ) {
+        if ( !vertex ) { return false; }
+        auto particles = range(vertex);
+        return finder.findDecay( std::begin(particles), std::end(particles), output );
+      }
+      // ======================================================================
+    public:
+      // ======================================================================
+      static ConstVector __findDecay__( const Decays::Finder_<TYPE>& finder, const ConstVector& input ) {
+        ConstVector output;
+        __findDecay__( finder, input, output );
+        return output;
+      }
+      // ======================================================================
+      static ConstVector __findDecay__( const Decays::Finder_<TYPE>& finder, const HepMC3::GenEvent* event ) {
+        ConstVector output;
+        __findDecay__( finder, event, output );
+        return output;
+      }
+      // ======================================================================
+      static ConstVector __findDecay__( const Decays::Finder_<TYPE>& finder, HepMC3::ConstGenVertexPtr vertex,
+                                        const HepMC3::Relatives & range ) {
+        ConstVector output;
+        __findDecay__( finder, vertex, range, output );
+        return output;
+      }
+      // ======================================================================
+    };
+    // ========================================================================
+  } // namespace Dicts
+  // ==========================================================================
+} //                                                      end of namespace LoKi
+// ============================================================================
+namespace {
+  // ==========================================================================
+  struct _Instantiations {
+    // ========================================================================
+    /// fictive constructor
+    _Instantiations();
+    // ========================================================================
+    // the basic types
+    LoKi::Types::GRange  m_r1;
+    LoKi::Types::GVRange m_r2;
+    // rangelists:
+    LoKi::Types::GRangeL  m_l1;
+    LoKi::Types::GVRangeL m_l2;
+    // keepers:
+    LoKi::Keeper<HepMC3::GenParticle> m_k1;
+    LoKi::Keeper<HepMC3::GenVertex>   m_k2;
+    // unique keepers
+    LoKi::UniqueKeeper<HepMC3::GenParticle> m_u1;
+    LoKi::UniqueKeeper<HepMC3::GenVertex>   m_u2;
+    // the basic functions
+    LoKi::Dicts::Funcs<HepMC3::ConstGenParticlePtr>  m_f1;
+    LoKi::Dicts::Funcs<HepMC3::ConstGenVertexPtr>    m_f2;
+    LoKi::Dicts::VFuncs<HepMC3::ConstGenParticlePtr> m_f3;
+    LoKi::Dicts::VFuncs<HepMC3::ConstGenVertexPtr>   m_f4;
+    // operators
+    LoKi::Dicts::FuncOps<HepMC3::ConstGenParticlePtr> m_o1;
+    LoKi::Dicts::FuncOps<HepMC3::ConstGenVertexPtr>   m_o2;
+    LoKi::Dicts::CutsOps<HepMC3::ConstGenParticlePtr> m_o3;
+    LoKi::Dicts::CutsOps<HepMC3::ConstGenVertexPtr>   m_o4;
+    // functional parts:
+    LoKi::Dicts::MapsOps<HepMC3::ConstGenParticlePtr>   m_fo1;
+    LoKi::Dicts::PipeOps<HepMC3::ConstGenParticlePtr>   m_fo2;
+    LoKi::Dicts::FunValOps<HepMC3::ConstGenParticlePtr> m_fo3;
+    LoKi::Dicts::CutValOps<HepMC3::ConstGenParticlePtr> m_fo31;
+    LoKi::Dicts::MapsOps<HepMC3::ConstGenVertexPtr>     m_fo5;
+    LoKi::Dicts::PipeOps<HepMC3::ConstGenVertexPtr>     m_fo6;
+    LoKi::Dicts::FunValOps<HepMC3::ConstGenVertexPtr>   m_fo7;
+    LoKi::Dicts::CutValOps<HepMC3::ConstGenVertexPtr>   m_fo71;
+    LoKi::Dicts::SourceOps<HepMC3::ConstGenVertexPtr>   m_fo9;
+    LoKi::Dicts::SourceOps<HepMC3::ConstGenParticlePtr> m_fo10;
+    /// mathematics:
+    LoKi::Dicts::FunCalls<HepMC3::GenParticle> m_c1;
+    LoKi::Dicts::FunCalls<HepMC3::GenVertex>   m_c2;
+    LoKi::Dicts::CutCalls<HepMC3::GenParticle> m_c3;
+    LoKi::Dicts::CutCalls<HepMC3::GenVertex>   m_c4;
+    /// the special operators for identifiers
+    LoKi::Dicts::PIDOps<LoKi::GenParticles::Identifier>    m_i1;
+    LoKi::Dicts::PIDOps<LoKi::GenParticles::AbsIdentifier> m_i2;
+    /// same ?
+    LoKi::TheSame<HepMC3::ConstGenParticlePtr> m_s1;
+    LoKi::TheSame<HepMC3::ConstGenVertexPtr>   m_s2;
+    /// trivia
+    LoKi::Functors::Empty<HepMC3::ConstGenParticlePtr> m_e1;
+    LoKi::Functors::Size<HepMC3::ConstGenParticlePtr>  m_si1;
+    LoKi::Functors::Empty<HepMC3::ConstGenVertexPtr>   m_e2;
+    LoKi::Functors::Size<HepMC3::ConstGenVertexPtr>    m_si2;
+    // decay funders:
+    Decays::Tree_<HepMC3::ConstGenParticlePtr>          m_tree1;
+    Decays::Trees::Any_<HepMC3::ConstGenParticlePtr>    m_tree2;
+    Decays::Trees::None_<HepMC3::ConstGenParticlePtr>   m_tree3;
+    Decays::Trees::Stable_<HepMC3::ConstGenParticlePtr> m_tree4;
+    LoKi::Dicts::TreeOps<HepMC3::ConstGenParticlePtr>   m_trops;
+    // ========================================================================
+    // Decay Finder
+    // ========================================================================
+    Decays::IGenDecay::Finder                            m_finder;
+    Decays::IGenDecay::Tree                              m_tree;
+    LoKi::Dicts::FinderDicts_<HepMC3::ConstGenParticlePtr> m_finderDicts;
+    // ========================================================================
+  };
+  // ==========================================================================
+} // end of anonymous namespace
+// ============================================================================
+
+// ============================================================================
+// The END
+// ============================================================================
+#endif // LOKI_LOKIGEN_DCT_H
diff --git a/Gen/LoKiGen/LoKi/PrintHepMCDecay.h b/Gen/LoKiGen/LoKi/PrintHepMCDecay.h
new file mode 100644
index 000000000..074fc76b4
--- /dev/null
+++ b/Gen/LoKiGen/LoKi/PrintHepMCDecay.h
@@ -0,0 +1,178 @@
+/*****************************************************************************\
+* (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration      *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                             *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+// ============================================================================
+#ifndef LOKI_PRINTHEPMCDECAY_H
+#define LOKI_PRINTHEPMCDECAY_H 1
+// ============================================================================
+// Include files
+// ===========================================================================
+// STD & STL
+// ===========================================================================
+#include <iostream>
+#include <limits>
+#include <string>
+// ===========================================================================
+// HepMC3
+// ===========================================================================
+#include "HepMC3/GenParticle.h"
+// ===========================================================================
+// LoKi
+// ===========================================================================
+#include "LoKi/GenTypes.h"
+// ===========================================================================
+// forward declarations
+// ===========================================================================
+class MsgStream;
+// ============================================================================
+/** @file
+ *
+ *  This file is a part of LoKi project -
+ *    "C++ ToolKit  for Smart and Friendly Physics Analysis"
+ *
+ *  The package has been designed with the kind help from
+ *  Galina PAKHLOVA and Sergey BARSUK.  Many bright ideas,
+ *  contributions and advices from G.Raven, J.van Tilburg,
+ *  A.Golutvin, P.Koppenburg have been used in the design.
+ *
+ *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+ *  @date 2006-05-26
+ */
+// ============================================================================
+namespace LoKi {
+  namespace PrintHepMC {
+    // ========================================================================
+    /// the maximal recursion level
+    const int s_maxLevel1 = std::numeric_limits<int>::max();
+    // ========================================================================
+    /** Simple function to print HepMC3 decay in more or less "readable" format
+     *
+     *  @code
+     *
+     *  HepMC3::ConstGenParticlePtr p = ... ;
+     *
+     *  printDecay( p , std::cout ) ;
+     *
+     *  @endcode
+     *
+     *  @param particle pointer to HepMC3::GenParticle to be printed
+     *  @param stream   stream to be used
+     *  @param cut      condition
+     *  @param blank    to be printed instead of cutted particles
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date   2006-01-18
+     */
+    std::ostream& printDecay( const HepMC3::ConstGenParticlePtr & particle, std::ostream& stream,
+                              const LoKi::GenTypes::GCuts& cut, const int level = s_maxLevel1,
+                              const std::string& blank = "<cut>" );
+    // ========================================================================
+    /** Simple function to print HepMC3 decay in more or less "readable" format
+     *
+     *  @code
+     *
+     *  HepMC3::ConstGenParticlePtr p = ... ;
+     *
+     *  printDecay( p , std::cout ) ;
+     *
+     *  @endcode
+     *
+     *  @param particle pointer to HepMC3::GenParticle to be printed
+     *  @param stream   stream to be used
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date   2006-01-18
+     */
+    std::ostream& printDecay( const HepMC3::ConstGenParticlePtr & particle, std::ostream& stream );
+    // ========================================================================
+    /** Simple function to print HepMC3 decay in more or less "readable" format
+     *
+     *  @code
+     *
+     *  HepMC3::ConstGenParticlePtr p = ... ;
+     *
+     *  printDecay( p , always() ) ;
+     *
+     *  @endcode
+     *
+     *  @param particle pointer to HepMC3::GenParticle to be printed
+     *  @param stream   stream to be used
+     *  @param cut      condition
+     *  @param blank    to be printed instead of cutted particles
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date   2006-01-18
+     */
+    MsgStream& printDecay( const HepMC3::ConstGenParticlePtr & particle, MsgStream& stream, const LoKi::GenTypes::GCuts& cut,
+                           const int level = s_maxLevel1, const std::string& blank = "<cut>" );
+    // ========================================================================
+    /** Simple function to print HepMC3 decay in more or less "readable" format
+     *
+     *  @code
+     *
+     *  HepMC3::ConstGenParticlePtr p = ... ;
+     *
+     *  printDecay( p , always() ) ;
+     *
+     *  @endcode
+     *
+     *  @param particle pointer to HepMC3::GenParticle to be printed
+     *  @param stream   stream to be used
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date   2006-01-18
+     */
+    MsgStream& printDecay( const HepMC3::ConstGenParticlePtr & particle, MsgStream& stream );
+    // ========================================================================
+    /** Simple function to print HepMC3 decay in more or less "readable" format
+     *
+     *  @code
+     *
+     *  HepMC3::ConstGenParticlePtr p = ... ;
+     *
+     *  info() << printHepMC3Decay( p ) ;
+     *
+     *  @endcode
+     *
+     *  @param particle pointer to HepMC3::GenParticle to be printed
+     *  @param cut      condition
+     *  @param blank    to be printed instead of cutted particles
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date   2006-01-18
+     */
+    std::string printDecay( const HepMC3::ConstGenParticlePtr & particle, const LoKi::GenTypes::GCuts& cut,
+                            const int level = s_maxLevel1, const std::string& blank = "<cut>" );
+    // ========================================================================
+    /** Simple function to print HepMC3 decay in more or less "readable" format
+     *
+     *  @code
+     *
+     *  HepMC3::ConstGenParticlePtr p = ... ;
+     *
+     *  info() << printDecay( p ) ;
+     *
+     *  @endcode
+     *
+     *  @param particle pointer to HepMC3::GenParticle to be printed
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date   2006-01-18
+     */
+    std::string printDecay( const HepMC3::ConstGenParticlePtr & particle );
+    // ========================================================================
+  } // namespace PrintHepMC
+  // ==========================================================================
+  namespace Print {
+    // ========================================================================
+    // import into namespace LoKi::Print
+    // ========================================================================
+    using namespace LoKi::PrintHepMC;
+    // ========================================================================
+  } // namespace Print
+} // end of namespace LoKi
+// ============================================================================
+// The END
+// ============================================================================
+#endif // LOKI_PRINTHEPMCDECAY_H
diff --git a/Gen/LoKiGen/dict/LoKiGen.xml b/Gen/LoKiGen/dict/LoKiGen.xml
new file mode 100644
index 000000000..192848fa7
--- /dev/null
+++ b/Gen/LoKiGen/dict/LoKiGen.xml
@@ -0,0 +1,176 @@
+<!--
+    (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration
+
+    This software is distributed under the terms of the GNU General Public
+    Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".
+
+    In applying this licence, CERN does not waive the privileges and immunities
+    granted to it by virtue of its status as an Intergovernmental Organization
+    or submit itself to any jurisdiction.
+-->
+<!-- 
+     * ========================================================================
+     * @file
+     * The seleciton file to build Reflex dictionaries for Phys/LoKiGen package
+     *
+     *  This file is a part of LoKi project - 
+     *    "C++ ToolKit  for Smart and Friendly Physics Analysis"
+     *
+     *  The package has been designed with the kind help from
+     *  Galina PAKHLOVA and Sergey BARSUK.  Many bright ideas, 
+     *  contributions and advices from G.Raven, J.van Tilburg, 
+     *  A.Golutvin, P.Koppenburg have been used in the design.
+     *
+     * @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     * @date 2006-02-06
+     * ========================================================================
+-->
+
+<lcgdict>
+  
+  <class pattern   = "Gaudi::Range_<*HepMC3::*>"      />
+  <class pattern   = "Gaudi::NamedRange_<*HepMC3::*>" />
+  <class pattern   = "LoKi::RangeList_<*HepMC3::*>"   />
+  
+  <class pattern   = "LoKi::Keeper<HepMC3::*>"        />
+  <class pattern   = "LoKi::UniqueKeeper<HepMC3::*>"  />
+  <class pattern   = "LoKi::Interface<*>"            />
+  
+
+  <class pattern   = "LoKi::BasicFunctors<*HepMC3::*>"      />
+  <class pattern   = "LoKi::Functor<*HepMC3::*>"            />
+  <class pattern   = "LoKi::FunctorFromFunctor<*HepMC3::*>" />
+  <class pattern   = "LoKi::Constant<*HepMC3::*>"           />
+
+  <class pattern   = "LoKi::Functors::Empty<*HepMC3::*>"  />
+  <class pattern   = "LoKi::Functors::Size<*HepMC3::*>"   />
+  
+  <class pattern   = "LoKi::Valid<*HepMC3::*>"            />
+  <class pattern   = "LoKi::TheSame<*HepMC3::*>"          />
+  
+  <class pattern   = "LoKi::GenParticles::*"             />
+  <class pattern   = "LoKi::GenVertices::*"              />
+  
+  <function pattern = "LoKi::GenKinematics::*"           />
+  <function pattern = "LoKi::PrintHepMC::*"              />
+  <function pattern = "LoKi::GenChild::*"                />
+  <function pattern = "LoKi::GenExtract::*"              />
+  <function pattern = "LoKi::Dicts::GenAlgs::*"          />
+  <function name    = "LoKi::GenParticles::hex_id"       />
+  <function name    = "LoKi::GenParticles::hash"         />
+  
+  <class name = "LoKi::GenChild::Selector"         />
+  
+  <class pattern   = "LoKi::Dicts::FuncOps<*HepMC3::*>"    />
+  <class pattern   = "LoKi::Dicts::CutsOps<*HepMC3::*>"    />
+  <class pattern   = "LoKi::Dicts::FuncOps__<*HepMC3::*>"  />
+  <class pattern   = "LoKi::Dicts::FuncOps_<*HepMC3::*>"   />
+  <class pattern   = "LoKi::Dicts::CutsOps_<*HepMC3::*>"   />
+
+  <class pattern   = "LoKi::Dicts::MapsOps<*HepMC3::*>"    />
+  <class pattern   = "LoKi::Dicts::PipeOps<*HepMC3::*>"    />
+  <class pattern   = "LoKi::Dicts::FunValOps<*HepMC3::*>"  />
+  <class pattern   = "LoKi::Dicts::CutValOps<*HepMC3::*>"  />
+  <class pattern   = "LoKi::Dicts::SourceOps<*HepMC3::*>"  />
+
+  <class pattern   = "LoKi::Dicts::PIDOps<LoKi::Gen*>"    />
+  <class pattern   = "LoKi::Dicts::FunCalls<HepMC3::Gen*>" />
+  <class pattern   = "LoKi::Dicts::CutCalls<HepMC3::Gen*>" />
+  
+  
+  <class name    = "LoKi::IGenHybridFactory"  />
+  <class name    = "LoKi::IGenHybridTool"     />
+  <class pattern = "LoKi::Hybrid::*"    />
+  
+  <class name = "std::vector<HepMC3::ConstGenParticlePtr>"  />
+  <class name = "std::vector<HepMC3::ConstGenVertexPtr>"    />  
+  
+  <class name = "Decays::Trees::Any_<HepMC3::ConstGenParticlePtr>"    />
+  <class name = "Decays::Trees::None_<HepMC3::ConstGenParticlePtr>"   />
+  <class name = "Decays::Trees::Stable_<HepMC3::ConstGenParticlePtr>" />
+  <class name = "Decays::Trees::GenExclusive" />
+  <class name = "Decays::Trees::GenInclusive" />
+  <class name = "Decays::Trees::GenOptional"  />
+  <class name = "Decays::Trees::GenPhotos"  />
+  <class name = "Decays::Trees::GenPhotosOptional"  />
+  <class name = "LoKi::Dicts::TreeOps<HepMC3::ConstGenParticlePtr>" />
+  <class name = "Decays::iTree_<HepMC3::ConstGenParticlePtr>"            />
+  <class name = "Decays::Tree_<HepMC3::ConstGenParticlePtr>"             />
+  <class name = "Decays::Trees::_Tree_<HepMC3::ConstGenParticlePtr>"     />
+  <class name = "Decays::TreeList_<HepMC3::ConstGenParticlePtr>"         />
+  <class name = "Decays::TreeList_<HepMC3::ConstGenParticlePtr>::Trees_" />
+
+  <class name = "Decays::IGenDecay"         />
+  <class name = "Decays::IGenDecay::Finder" />
+  <class name = "Decays::IGenDecay::Tree"   />
+  <class name = "LoKi::Dicts::FinderDicts_<HepMC3::ConstGenParticlePtr>"   />
+  
+  <class name = "LoKi::GenDecayChain"     />
+  
+  <exclusion>
+    <class name ="LoKi::GenParticles::FromHepMCTree::VERTICES" />
+    <class name ="LoKi::Interface<LoKi::ILoKiSvc>"   />
+    <class name ="LoKi::Interface<IDataProviderSvc>" />
+    <class name ="LoKi::Interface<IChronoSvc>"   />
+
+    <class pattern="LoKi::GenParticles::*">
+      <method name="=" />
+    </class>
+    <class pattern="LoKi::GenVertices::*">
+      <method name="=" />
+    </class>
+
+    <class pattern="LoKi::Dicts::*">
+      <method name="=" />
+    </class>
+    <class pattern="LoKi::Interface&lt;*&gt;">
+      <method name="=" />
+    </class>
+    <class pattern="LoKi::I*">
+      <method name="=" />
+    </class>
+    <class pattern="LoKi::Hybrid::*">
+      <method name="=" />
+    </class>
+    
+    <class pattern="LoKi::Functor&lt;*&gt;">
+      <method name="=" />
+    </class>
+    <class pattern="LoKi::Constant&lt;*&gt;">
+      <method name="=" />
+    </class>
+    <class pattern="LoKi::Valid&lt;*&gt;">
+      <method name="=" />
+    </class>
+    <class pattern="LoKi::TheSame&lt;*&gt;">
+      <method name="=" />
+    </class>
+    <class pattern="Gaudi::Range_&lt;*&gt;">
+      <method name="=" />
+    </class>
+    <class pattern="Gaudi::NamedRange_&lt;*&gt;">
+      <method name="=" />
+    </class>
+    <class pattern="LoKi::RangeList_&lt;*&gt;">
+      <method name="=" />
+    </class>
+    <class pattern="LoKi::Keeper&lt;*&gt;">
+      <method name="=" />
+    </class>
+    <class pattern="LoKi::UniqueKeeper&lt;*&gt;">
+      <method name="=" />
+    </class>
+
+    <class pattern="LoKi::Functors::*">
+      <method name="=" />
+    </class>
+    
+    <class pattern="Decays::*">
+      <method name="=" />
+    </class>
+    
+    <class name="LoKi::Interface<GaudiAlgorithm>"/>
+    
+  </exclusion>
+  
+</lcgdict>
diff --git a/Gen/LoKiGen/dict/LoKiGenDict.h b/Gen/LoKiGen/dict/LoKiGenDict.h
new file mode 100644
index 000000000..7ac04f299
--- /dev/null
+++ b/Gen/LoKiGen/dict/LoKiGenDict.h
@@ -0,0 +1,36 @@
+/*****************************************************************************\
+* (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration      *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                             *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+// ============================================================================
+#ifndef LOKI_LOKIGENDICT_H
+#define LOKI_LOKIGENDICT_H 1
+// ============================================================================
+// Include files
+// ============================================================================
+#include "LoKi/LoKiGen_dct.h"
+// ============================================================================
+/** @file
+ *  The dictionaries for the package Phys/LoKiGen
+ *
+ *  This file is a part of LoKi project -
+ *    "C++ ToolKit  for Smart and Friendly Physics Analysis"
+ *
+ *  The package has been designed with the kind help from
+ *  Galina PAKHLOVA and Sergey BARSUK.  Many bright ideas,
+ *  contributions and advices from G.Raven, J.van Tilburg,
+ *  A.Golutvin, P.Koppenburg have been used in the design.
+ *
+ *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+ *  @date 2007-12-01
+ */
+// ============================================================================
+// The END
+// ============================================================================
+#endif // LOKI_LOKIGENDICT_H
diff --git a/Gen/LoKiGen/doc/release.notes b/Gen/LoKiGen/doc/release.notes
new file mode 100644
index 000000000..307f7e0ee
--- /dev/null
+++ b/Gen/LoKiGen/doc/release.notes
@@ -0,0 +1,730 @@
+! -----------------------------------------------------------------------------
+! Package     : Phys/LoKiGen
+! Responsible : Vanya BELYAEV
+! Purpose     : Functions and algorithms for "LoKi for HepMC"
+! -----------------------------------------------------------------------------
+!
+!   This file is a part of LoKi project -
+!     "C++ ToolKit  for Smart and Friendly Physics Analysis"
+!
+!   The package has been designed with the kind help from
+!   Galina PAKHLOVA and Sergey BARSUK.  Many bright ideas,
+!   contributions and advices from G.Raven, J.van Tilburg,
+!   A.Golutvin, P.Koppenburg have been used in the design.
+! -----------------------------------------------------------------------------
+
+! 2016-07-29 - Marco Cattaneo
+ - Fix clang warnings: ToolFactory is now a struct, no longer a class
+
+! 2016-04-27 - Vanya Belyaev
+ - fix the issue with hash 
+
+! 2016-04-27 - Vanya Belyaev
+ - add missing hep_id function...
+
+!========================= LoKiGen v10r24 2016-03-16 =========================
+! 2016-03-12 - Vanya Belyaev
+ - GenExlusive.cpp
+   fix a bug with matching of oscillating/non-oscillating patterns
+   (thanks to Marco Cattaneo and Coverity for reporting the  bug)
+
+! 2016-02-17 - Vanya Belyaev
+ - remove the explicit loading of HepMC reflex library 
+
+!========================= LoKiGen v10r23 2016-01-27 =========================
+! 2016-01-25 - Vanya Belyaev
+ - add Graphviz into CMT&CMAKE 
+
+! 2016-01-17 - Vanya Belyaev
+ - LoKiGen.graph: several improvements 
+ - remove old GetHepMC stuff 
+ - add methods to get HepMC-treed  from event, events, containers, ...
+
+! 2016-01-16 - Vanya Belyaev
+ - add new module LoKiGen.graph to produce decay tree graphs 
+
+     import LoKiGen.graph 
+     hepmc = ...
+     hepmc.view() 
+
+!========================= LoKiGen v10r22 2015-11-23 =========================
+! 2015-11-01 - Gerhard Raven
+ - replace LoKi::select with std::copy_if
+
+!========================= LoKiGen v10r21 2015-10-12 =========================
+! 2015-10-06 - Vanya Belyaev
+  - attempt to speedup decay tree matchers ( aka "descriptors")
+    with optional particles " {} " 
+
+! 2015-08-03 - Gerhard Raven
+ - remove #include of obsolete Gaudi headers
+
+!========================= LoKiGen v10r20 2015-02-23 =========================
+! 2015-01-23 - Vanya Belyaev
+ - steps towards autogeneration of C++ code 
+
+!========================= LoKiGen v10r19 2014-12-11 =========================
+! 2014-11-26 - Marco Clemencic
+ - Reverted work around for spurious entries in the rootmap files.
+
+!========================= LoKiGen v10r18 2014-10-14 =========================
+! 2014-09-17 - Marco Clemencic
+ - Fixed genreflex warnings (ROOT 6).
+
+!========================= LoKiGen v10r17 2014-07-14 =========================
+! 2014-07-11 - Marco Clemencic
+ - Strip spurious entry from the rootmap (ROOT 6 problem).
+
+!========================= LoKiGen v10r16 2014-05-12 =========================
+! 2014-04-23 - Marco Cattaneo
+ - Remove duplicate dictionary for LoKi::Interface<IChronoSvc>,
+   already defined in LoKiCore
+
+! 2014-04-16 - Vanya Belyaev
+    add qmtest for JIRA-LBCORE-461
+    it makes seghmentation fault for ROOT6 and runs smoothly for ROOT5
+
+!========================= LoKiGen v10r15 2014-03-17 =========================
+! 2014-02-21 - Marco Clemencic
+ - Moved the PID operators to the namespace LoKi::GenParticles to fix an issue
+   with ROOT 6.
+   See https://sft.its.cern.ch/jira/browse/ROOT-6044 for details.
+
+! 2014-02-21 - Marco Clemencic
+ - Fixes to header guard macros.
+
+!========================= LoKiGen v10r14 2014-02-17 =========================
+! 2014-02-01 - Vanya Belyaev
+ - add dictionaries for new FuncOps__
+
+! 2014-01-06 - Marco Clemencic
+ - Replaced import of GaudiPython with import of cppyy (to allow usage of the
+   modules in configuration files).
+
+! 2013-06-27 - Marco Clemencic
+ - Replaced PyCintex with ROOT (preparing migration to ROOT 6).
+
+!========================= LoKiGen v10r13 2013-09-30 =========================
+! 2013-09-30 - Pieter David
+ - Decays::GenExclusive (and derived): make sure the cache is emptied
+   when no match is found
+
+!========================= LoKiGen v10r12p1 2013-09-30 =========================
+! 2013-09-17 - Marco Cattaneo
+ - Remove unnecessary linkopts macro from requirements
+
+!========================= LoKiGen v10r12 2013-04-29 =========================
+! 2013-04-29 - Marco Cattaneo
+ - Replace endreq by endmsg
+ - Remove unnecessary disclaimers from file documentation blocks
+
+! 2013-04-19 - Vanya Belyaev
+ - fix warning message for coverity
+
+! 2013-04-15 - Marco Clemencic
+ - Added default constructors to fix compilation errors with clang.
+
+! 2013-04-14 - Vanya Belyaev
+ - add GFLIGHT, GPVFLIGHT, GBETA , GGGAMMA and GBETAGAMMA symbols
+   (mainly for MC-production)
+
+! 2013-03-25 - Chris Jones
+ - Fix compilation issues with gcc 4.7
+
+!========================= LoKiGen v10r11 2013-03-20 =========================
+! 2013-02-21 - Vanya Belyaev
+ - symbol GY was masked by incorrect redefinition.
+   Many thanks for Wenbin Qian for the hints
+
+!========================= LoKiGen v10r10 2012-11-26 =========================
+! 2012-11-15 - Marco Clemencic
+ - Added CMake configuration file.
+
+!========================= LoKiGen v10r9 2012-10-22 =========================
+! 2012-10-19 - Vanya Belyaev
+ - bug fix in 4-vector-functors
+   many tahnks to Regis Lefevre for problem report
+
+!========================= LoKiGen v10r8 2012-06-25 =========================
+! 2012-06-18 - Vanya Belyaev
+ - redesign kinematical functors
+
+! 2012-06-16 - Vanya Belyaev
+ - improge child selection
+
+! 2012-05-24 - Vanya Belyaev
+ - more improvements for decorators
+
+!========================= LoKiGen v10r7 2012-05-24 =========================
+! 2012-05-19 - Vanya Belyaev
+ - add more rrshift/calls decorators
+
+!========================= LoKiGen v10r6 2012-02-28 =========================
+! 2012-02-13 - Vanya Belyaev
+ - add GVRHO functor for Marc-Olivier
+
+!========================= LoKiGen v10r5 2012-01-31 =========================
+! 2012-01-29 - Vanya Belyaev
+ - add dumping functors
+
+! 2012-01-28 - Vanya Belyaev
+ - add various functors for polarizations
+
+! 2012-01-26 - Vanya Belyaev
+ - add GCOSPOL functor
+
+!========================= LoKiGen v10r4 2011-12-14 =========================
+! 2011-12-13 - Vanya Belyaev
+ - add GCHILD/GCHILDFUN and GCHILDCUT functors on Jibo's request
+
+! 2011-11-11 - Vanya Belyaev
+ - fix the oscillation flags in decay tree matching functions
+
+!========================= LoKiGen v10r3 2011-07-25 =========================
+! 2011-07-25 - Vanya Belyaev
+ - fix ICC compliler warning
+
+! 2011-07-23 - Vanya Belyaev
+ - more decorators for HepMC.GenParticle
+
+! 2011-07-15 - Alexey Novoselov
+ - add useful constructor for GDECTREE functors
+
+! 2011-07-03 - Vanya Belyaev
+ - small polishing of python iterators
+
+!========================= LoKiGen v10r2 2011-06-14 =========================
+! 2011-06-05 - Vanya Belyaev
+ - reduce compilation warnings for ICC compiler
+
+! 2011-06-04 - Vanya Belyaev
+ - better printout of decay chains
+
+! 2011-06-02 - Vanya Belyaev
+ - add LoKi::GenFilter algorithm to allow some filtering based on
+  properties of generator event.
+
+ - cmt/requirements
+     version incrment to v10r2
+
+!========================= LoKiGen v10r1 2011-04-26 =========================
+! 2011-04-09 - Vanya Belyaev
+ - add missing "cutvals" into Tool/Factory interface
+   they are needed for generic cut-tool in Gauss
+
+!========================= LoKiGen v10r0 2011-04-04 =========================
+! 2011-03-18 - Vanya Belyaev
+ - add protection against double lock
+
+! 2011-03-10 - Vanya Belyaev
+ - update for removal of 'Element'-concept
+
+!========================= LoKiGen v9r6 2011-02-22 =========================
+! 2011-02-21 - Marco Cattaneo
+ - Suppress Intel compiler warnings about missing default constructor
+   In this case the compiler generated constructor is fine, since there are
+   no member data to be intialised
+
+!========================= LoKiGen v9r5 2011-01-31 =========================
+! 2011-01-13 - Marco Cattaneo
+ - Fix most ICC warnings and remarks
+
+!========================= LoKiGen v9r4 2010-11-27 =========================
+! 2010-11-12 - Rob Lambert
+ - remove print statement
+
+!========================= LoKiGen v9r3 2010-10-25 =========================
+
+! 2010-10-24 - Vanya Belyaev
+ - add concept of stable particle in decay descriptors
+ - cmt/requirements
+     version incrment to v9r2
+
+
+!========================== LoKiGen v9r2 2010-09-28 ===========================
+! 2010-09-28 - Vanya Belyaev
+ - LoKiGen/trees.py
+     fix for new module in LoKiCore
+
+ - cmt/requirements
+     version incrment to v9r2
+
+!========================== LoKiGen v9r1 2010-06-18 ===========================
+! 2010-05-30 - Vanya Belyaev
+
+ - polish for various functions
+
+ - cmt/requirements
+   version incrment to v9r1
+
+!========================== LoKiGen v9r0 2010-04-26 ===========================
+! 2010-04-09 - Vanya Belyaev
+
+  - LoKiGen/functions.py
+
+     LoKi.NamedRange -> Gaudi.NamedRange
+
+! 2010-04-06 - Vanya Belyaev
+
+ - replace LoKi::Raneg by Gaudi::Range
+
+ - cmt/requirements
+     version incremen tto v9r0
+
+
+!========================== LoKiGen v8r8 2010-02-12 ===========================
+! 2010-02-10 - Vanya Belyaev
+ Add new symbols
+    GY    LoKi::GenParticles::Rapidity   for evaluation of rapidity  (y)
+    GY0   LoKi::GenParticles::Rapidity0  for evaluation of rapidity0 (y_0)
+
+ - cmt/requirements
+    version increment to v8r8
+
+!========================== LoKiGen v8r7 2009-09-02 ===========================
+! 2009-09-02 - Marco Cattaneo
+ - Remove obsolete file src/Components/LoKiGen_dll.cpp
+
+! 2009-08-12 - Vanya  BELYAEV
+
+ - add useful typedef
+
+!========================== LoKiGen v8r6 2009-07-12 ===========================
+! 2009-07-12 - Vanya BELYAEV
+
+ - minor fix to please Bender
+ - cmt/requirements
+   version increment to v8r6
+
+
+!========================== LoKiGen v8r5 2009-06-29 ===========================
+! 2009-06-28 - Vanya Belyaev
+
+ - improvements for decay finder
+ - cmt/requirements
+
+    version increment to v8r5
+
+
+!========================== LoKiGen v8r4 2009-06-16 ===========================
+! 2009-06-02 - Vanya BELYAEV
+ - further polishing of decay finder
+
+! 2009-05-27 - Vanya BELYAEV
+ - LoKi::GenDecay
+    new HepMC-decay finder tool
+
+ - cmt/requirements
+    version increment to v8r4
+
+!========================== LoKiGen v8r3 2009-05-25 ===========================
+! 2009-05-14 - Vanya Belyaev
+ - clean-up the trees
+
+! 2009-05-11 - Vanya Belyaev
+ - fix for changes in Kernel/PartProp
+
+! 2009-05-09 - Vanya BELYAEV
+ - remove unnesessary std::unary/binary_function bases
+ - cmt/requirements
+   version incremen to v8r3
+
+!========================== LoKiGen v8r2 2009-05-07 ===========================
+! 2009-05-06 - Vanya BELYAEV
+ - few improvements for new decay finders
+ - cmt/requirements
+    version increment to v8r2
+
+!========================== LoKiGen v8r1 2009-01-08 ===========================
+! 2008-12-18 - Vanya Belyaev
+ - many fixes for trees ,
+   add new symbols:
+     GDECNODE
+     GDECTREE
+
+! 2008-11-23 - Vanya BELYAEV
+  - add QMTest
+  - new functors:
+    GSIZE
+    GEMTPTY
+    GOSCILLATED1
+    GOSCILLATED2
+  - better treatment  of "CutVals"
+  - cmt/requirements
+    version increment to v8r1
+
+
+!============================ LoKiGen v8r0 2008-11-17 =========================
+! 2008-11-02 - Vanya BELYAEV
+ - fixes for various compilers
+
+! 2008-10-30 - Vanya BELYAEV
+ - fix for LCG-preview
+
+! 2008-10-29 - Vanya BELYAEV
+ - fixes for gcc43 compilation
+
+! 2008-10-19 - Vanya BELYAEV
+ - adaptation for new LoKiCore
+
+     new structure of decorators
+
+ - cmt/requirements
+
+     version increment to v8r0
+
+!============================ LoKiGen v7r6 2008-09-04 =========================
+! 2008-08-04 - Vanya BELYAEV
+ - LoKi/GenDecays.h
+   src/GenDecays.cpp
+
+     1) make more uniform interface for LoKi::Decays::Trees::Gen*
+     2) improve Doxygen comments
+
+ - cmt/requirements
+
+     version increment to v7r6
+
+!============================ LoKiGen v7r5 2008-07-16 =========================
+! 2008-07-09 - Vanya BELYAEV
+
+ - Many changes for (Gen) Decay Finder
+ - cmt/requirements
+    version inrement to v7r5
+
+!============================ LoKiGen v7r4 2008-06-30 =========================
+! 2008-06-26 - Vanya BELYAEV
+ - LoKi/CmpBarCode.h & src/GenChild.cpp
+     fix some compilation problmes
+
+! 2008-06-25 - Vanya BELYAEV
+ - src/GenParticles.cpp
+    suppress "empty vertices list"-error message for FromHepMCTree
+
+! 2008-06-24 - Vanya BELYAEV
+ - LoKi/CmtBarCode.h
+    - new utility LoKi::GenParticles::CmpBarCode
+      to compare HepMC::GenParticle by barcode
+    - new typedef for the std::set of particles using CmtBarCode
+      as the ordering criteria
+
+! 2008-06-12 - Vanya BELYAEV
+ -  LoKi/GenDecays.h
+    src/LoKiGenDecays.cpp
+
+    Implemenmtation of HepMC-trees (functors which acts on the decay
+    structure), needed for new (HepMC)DecayFinder
+
+ - cmt/requirements
+    version incrmeent to v7r4
+
+!============================ LoKiGen v7r3 2008-05-05 =========================
+! 2008-05-05 - Marco Cattaneo
+ - Fix many broken doxygen comments, too much cut and paste without edit!
+
+! 2008-05-04 - Vanya BELYAEV
+ - LoKi/GenSections.h, src/GenSections.cpp
+     new files with functions which produce "sections" for the decay trees.
+
+ - LoKi/GenChild.h, src/GenChild.cpp
+     add "daughters" to the list of the available functions
+
+ - cmt/requirmeents
+    version increment to v7r3
+
+!============================ LoKiGen v7r2 2008-04-03 =========================
+! 2008-03-30 - Vanya BELYAEV
+  - introduce the proper shift-operators __rshift__ (streamers)
+  - add the proper specialization for printout of boolean constants
+  - cmt/requirements
+     version increment to v7r2
+
+!============================ LoKiGen v7r1 2008-02-19 =========================
+! 2008-02-19 - Vanya BELYAEV
+ - All *Hybrid* stuff:
+     everything is extended for "functional" functors also
+
+! 2008-02-11 - Vanya BELYAEV
+ - many small fixes for new Gaudi/ROOT/Reflex
+ - cmt/requirements
+     version increment to v7r1
+
+!============================ LoKiGen v7r0 2007-12-09 =========================
+! 2007-12-09 - Vanya BELYAEV
+
+ - implement sources ( on Gerhard's request )
+    new files:  LoKi/GenSources.h & src/GenSources.cpp
+
+! 2007-12-01 - Vanya BELYAEV
+
+ - The major update for the new LoKi v7r0  (The Powerful Streamers)
+
+   cmt/requirements
+
+   version increment to v7r0
+
+!============================ LoKiGen v6r1 2007-10-08 =========================
+! 2007-10-07 - Vanya BELYAEV
+ - cmt/requirements
+    increment version to v6r1
+    use new pattern for python modules
+
+!============================ LoKiGen v6r0 2007-09-04 =========================
+! 2007-08-20 - Vanya Belyaev
+ - increment the major version to v6r0
+
+! 2007-07-25 - Vanya BELYAEV
+ - add all "hybrid"-functionality for the
+   interplay between C++ and Python, in particular for hybrid factory.
+
+New Files:
+  LoKi/GenHybridEngine.h
+  LoKi/GenHybridEngineActor.h
+  LoKi/GenHybridLock.h
+  LoKi/IGenHybridFactory.h
+  LoKi/IGenHybridTool.h
+  src/GenHybridEngine.cpp
+  src/GenHybridEngineActor.cpp
+  src/GenHybridLock.cpp
+  src/IGenHybridFactory.cpp
+  src/IGenHybridTool.cpp
+  src/Components/GenHybridTool.cpp
+  src/Components/LoKiGen_dll.cpp
+
+! 2007-07-23 - Vanya BELYAEV
+ - many tiny updates to minimize the dependencies,
+   reduce the dictionaries, decrease the compilation time
+   and improve the doxygen documentation
+ - cmt/requirements
+    version increment to v3r1
+
+!============================ LoKiGen v3r0 2007-06-11 =========================
+! 2007-06-10 - Vanya BELYAEV
+ - minor fixes to please Reflex and make the classes/method vizible in python
+
+! 2007-06-01 - Vanya BELYAEV
+ - prepare for the version v3r0 :
+   all dictionaries are built locally
+
+   - New files:
+
+    LoKi/GetHepMC.h
+    src/GetHepMC.cpp
+
+    dict/LoKiGen.xml
+    dict/LoKiGenDict.h
+
+    python/LoKiGen/__init__.py
+    python/LoKiGen/decorators.py
+    python/LoKiGen/functions.py
+    python/LoKiGen/tests.py
+
+   - Modified files:
+
+    LoKi/GenPIDOperators.h
+    LoKi/GenTypes.h
+    LoKi/LoKiGen.h
+
+ - cmt/requirements version increment to v3r0
+
+!============================ LoKiGen v2r1 2007-03-05 =========================
+! 2007-03-04 - Vanya BELYAEV
+ - LoKi/GenParticles.h, LoKi/GenParticleCuts.h,  src/GenParticles.cpp
+   . Add 3 new functions DeltaPhi, DeltaEta and DeltaR2, very useful for
+     jet-studies
+
+! 2007-02-26 - Marco Cattaneo
+ - Fix many doxygen warnings
+
+! 2007-01-23 - Vanya BELYAEV
+ - LoKi/GenParticles.h, src/GenParticles.cpp
+     many tiny fixes to build Ex/LoKiExample package
+
+ - cmt/requirements
+     version increment to v2r1
+
+! =========================== LoKiGen v2r0 2007-01-19 =========================
+! 2007-01-19 - Vanya BELYAEV
+ - LoKi/BuildGenTrees.h
+    new file with utilities to select the independent trees from
+    the flat list of HepMC-particles
+
+! 2006-12-06 - Florence RANJARD
+ - apply_pattern install_more_includes
+
+!============================ LoKiGen v1r8 2006-11-27 =========================
+! 2006-11-25 - Vanya BELYAEV
+ -  src/PrintHepMCDecay.h
+    fix a treatment of cut-off for maximal max-level printouts
+ -  improve Doxygen comments for nested namespaces
+ -  cmt/requirements
+    version increment to v1r8
+
+!============================ LoKiGen v1r7 2006-11-10 =========================
+! 2006-11-09 - Vanya BELYAEV
+ - LoKi/PrintHepMCDecay.h
+   src/PrintHepMCDecay.h
+     1) move all functions into the namespace LoKi::Print
+     2) add a maximum recursion level
+ - cmt/requirements
+     version increment to v1r7
+
+!============================ LoKiGen v1r6 2006-10-12 =========================
+! 2006-10-10 - Vanya BELYAEV
+ - LoKi/GenExtract.h
+   fix for dictionaries
+
+! 2006-10-05 - Vanya BELYAEV
+ - LoKi/GenAlgs.h
+    fix for SLC4 compilation error
+ - cmt/requirements
+    version increment to b1r6
+
+!============================ LoKiGen v1r5 2006-09-09 =========================
+! 2006-09-06 - Vanya BELYAEV
+ - LoKi/GenTypes.h
+     add the formal defintions of containers and ranges [needed for Phys/AlgoMC]
+ - cmt/requirements
+     version increment to v1r5
+
+!=========================== LoKiGen v1r4 2006-08-30 ==========================
+! 2006-08-26 - Vanya BELYAEV
+ - LoKi/GenParticles.h
+   src/GenParticles.cpp
+
+     add the new primitive function(functor) LoKi::GenPArticles::Status
+      for evaluation of HepMC::GenParticles::status()
+
+ - LoKi/GenParticleCuts.h
+
+     add a shortcut LoKi::Cuts::GSTATUS as a shortcut for the instance
+     fo LoKi::GenParticles::Status()
+
+ - cmt/requirements
+
+      version increment to v1r4
+
+!=========================== LoKiGen v1r3 2006-06-09 ==========================
+! 2006-06-09 - Marco Cattaneo
+ - Fix typo in GenExtract.h
+
+! 2006-05-27 - Vanya BELYAEV
+ - LoKi/PrintHepMCDecay.h src/PrintHepMCDecay.cpp
+   set of new functions LoKi::pritnHepMCDecay and LoKi::printDecay
+   for the printout of the HepMC decay tree
+
+! 2006-05-26 - Vanya BELYAEV
+
+ - LoKi/GenParticles.h src/GenParticles.cpp
+   increase functionality of FromHepMCTree function.
+   now it can treat the list of trees.
+ - cmt/requirements
+   version increment to v1r3
+
+!=========================== LoKiGen v1r2 2006-05-02 ==========================
+! 2006-05-02 - Vanya Belyaev
+ - *ALL* files are modified (well, actually censored)
+ - cmt/requirements
+   version increment to v1r2
+
+!=========================== LoKiGen v1r1 2006-03-28 ==========================
+! 2006-03-03 - Vanya BELYAEV
+ - Add G3Q and GP<*> functions
+
+!=========================== LoKiGen v1r0 2006-02-17 ==========================
+! 2006-02-09 - Vanya BELYAEV
+ - new set of functions:
+
+   A) adapter functions
+     - AdapterToProductionVertex - alias GFAPVX
+     - AdapterToEndVertex        - alias GFAEVX
+     trivial funtions which gelegated the evaluation of
+     "vertex" fucntion to production/end vertices of
+     given HepMC::GenParticle :
+
+     *  Extract all particles, which are decayed after z > 1000
+     *
+     *  @code
+     *
+     *  const LHCb::HepMCEvents* events
+     *    get<LHCb::HepMCEvents>( LHCb::HepMCEventLocation::Default ) ;
+     *
+     *  typedef std::vector<HepMC::GenParticle*> PARTICLES ;
+     *
+     *  PARTICLES parts ;
+     *
+     *  // create the predicate:
+     *  GCut cut = GFAEVX( GVZ  , 10000  ) >  1000 ;
+     *
+     *  LoKi::Extract::genParticles
+     *    ( events , std::back_inserter ( parts )  , cut ) ;
+     *
+     *  @endcode
+     *
+
+   B) a lot of "Vertex" funcitons  (Convention: the name starts with "GV"):
+     the trivial generic functios:
+       - GVTRUE, GVFALSE, GVALL, GVNONE, GVONE, GVNULL, GVZERO, GVMIN
+       - GVBAR, GVBARCODE - returns the "bar-code" for the given vertex
+       - GVX,GVY,GVZ,GVT,GVTIME - returns corresponding "position" of the vertex
+       - GVCOUNT - counts number of particles withing the sepcified range,
+                   which atisfy the certain criteria:
+
+     *  E.g. find the decay H -> b b~ X :
+     *
+     *  @code
+     *
+     *  // number of b-quarks withing children particles
+     *  GVFun num1 =  GVCOUNT( "b"  == GID , HepMC::children ) ;
+     *
+     *  // number of b~-quarks withing children particles
+     *  GVFun num2 =  GVCOUNT( "b~" == GID , HepMC::children ) ;
+     *
+     *  // use adapter function to End vertex
+     *  GFun num = GFAEVX ( num1 + num2 , 0 ) ;
+     *
+     *  // find the decay H -> b b :
+     *
+     *  const LHCB::HepMCEvents* events = ... ;
+     *
+     *  GCut decay = ( 2 == num ) && ( "H_10" == GID ) ;
+     *
+     *  const bool good = LoKi::GenAlgs::found ( events , decay ) ;
+     *
+     *  @endcode
+
+      - GVSUM - accumulates the valeu of function for particles
+                withing teh specified range whcih satisfy the certain criteria:
+
+     *  Total energy of all stable daughter charged leptons:
+     *
+     *  @code
+     *
+     *  GVFun e1 = GVSUM( GE , HepMC::descendants ,
+     *                           GCHARGED && GLEPTON ) ;
+     *
+     *  GFun eLep = GFAEVX( e1 )
+     *
+     *  HepMC3::ConstGenParticlePtr p = ... ;
+     *
+     *  const double eTot = eLep( p ) ;
+     *
+     *  @endcode
+
+    new files:
+    - LoKi/GenVertices.h
+    - LoKi/GenVertexCuts.h
+    - src/GenVertoces.cpp
+
+! 2006-01-24 - Vanya BELYAEV
+ - New import: the parts of LoKi project,
+   directly related to generator information in HepMC format
+
+   The package contains the HepMC-dependent parts of LoKi project:
+     -- basic functors & predicates
+     -- helper utilities to manipulate HepMC graphs
+     -- STL-like algorithms for selections of particles
+
+! -----------------------------------------------------------------------------
+! The END
+! -----------------------------------------------------------------------------
diff --git a/Gen/LoKiGen/python/LoKiGen/HepMC.py b/Gen/LoKiGen/python/LoKiGen/HepMC.py
new file mode 100755
index 000000000..863550993
--- /dev/null
+++ b/Gen/LoKiGen/python/LoKiGen/HepMC.py
@@ -0,0 +1,659 @@
+#!/usr/bin/env python
+###############################################################################
+# (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration      #
+#                                                                             #
+# This software is distributed under the terms of the GNU General Public      #
+# Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   #
+#                                                                             #
+# In applying this licence, CERN does not waive the privileges and immunities #
+# granted to it by virtue of its status as an Intergovernmental Organization  #
+# or submit itself to any jurisdiction.                                       #
+###############################################################################
+# =============================================================================
+## @file
+#  collection of utilities for useful 'decoration' of HepMC-objects
+#
+#  This file is a part of LoKi project -
+#   'C++ ToolKit  for Smart and Friendly Physics Analysis'
+#
+#  The package has been designed with the kind help from
+#  Galina PAKHLOVA and Sergey BARSUK.  Many bright ideas,
+#  contributions and advices from G.Raven, J.van Tilburg,
+#  A.Golutvin, P.Koppenburg have been used in the design.
+#
+#  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+#  @date 2007-08-11
+# =============================================================================
+"""
+Collection of utilities for useful 'decoration' of HepMC-objects
+
+This file is a part of LoKi project -
+'C++ ToolKit  for Smart and Friendly Physics Analysis'
+
+The package has been designed with the kind help from
+Galina PAKHLOVA and Sergey BARSUK.  Many bright ideas,
+contributions and advices from G.Raven, J.van Tilburg,
+A.Golutvin, P.Koppenburg have been used in the design.
+
+
+"""
+# =============================================================================
+__author__ = 'Vanya BELYAEV ibelyaev@physics.syr.edu'
+__date__ = "2007-08-11"
+__version__ = ""
+# =============================================================================
+import LoKiCore.decorators as _LoKiCore
+from LoKiGen.functions import HepMC, LoKi, Gaudi, std, cpp
+from LoKiCore.decorators import LHCb
+import LHCbMath.Types
+
+## namespace HepMC {
+##     /// type of iteration
+##     enum IteratorRange { parents, children, family,
+##                          ancestors, descendants, relatives };
+## } // HepMC
+if not hasattr(HepMC, 'parents'): HepMC.parents = 0
+if not hasattr(HepMC, 'children'): HepMC.children = 1
+# if not hasattr(HepMC, 'family'): HepMC.family = 2
+if not hasattr(HepMC, 'ancestors'): HepMC.ancestors = 3
+if not hasattr(HepMC, 'descendants'): HepMC.descendants = 4
+# if not hasattr(HepMC, 'relatives'): HepMC.relatives = 5
+
+if not hasattr(HepMC.GenParticle, '_orig_momentum_'):
+    _orig_momentum_ = HepMC.GenParticle.momentum
+    HepMC.GenParticle._orig_momentum_ = _orig_momentum_
+
+    def _momentum_(p):
+        """4-momentumtum of HepMC::GenParticle
+        >>> p = ...
+        >>> v = p.momentum()
+        """
+        m = p._orig_momentum_()
+        return Gaudi.LorentzVector(m.px(), m.py(), m.pz(), m.e())
+
+    HepMC.GenParticle.momentum = _momentum_
+
+
+# =============================================================================
+## Get number of child particles :
+def nChildren(p, *args):
+    """
+    Get number of child particles :
+
+    >>> n = nChildren ( p )
+    """
+    return LoKi.GenChild.nChildren(p, *args)
+
+
+nChildren.__doc__ += "\n\n" + LoKi.GenChild.nChildren.__doc__
+
+HepMC.GenParticle.nChildren = nChildren
+HepMC.GenParticle.nDaughters = nChildren
+HepMC.GenParticle.__nChildren__ = nChildren
+HepMC.GenParticle.__nDaughters__ = nChildren
+
+
+# =============================================================================
+## get the child
+def child(p, *a):
+    """
+    Get the child for 'particle'
+
+    >>> p = ...
+    >>> d1  = child ( p , 1 )
+    >>> d12 = child ( p , 1 , 2 )
+
+    ATTTENTION: indices start from 1.
+    Index 0 corresponds to the particle itself.
+    """
+    return LoKi.GenChild.child(p, *a)
+
+
+child.__doc__ += "\n\n" + LoKi.GenChild.child.__doc__
+
+HepMC.GenParticle.child = child
+HepMC.GenParticle.daughter = child
+HepMC.GenParticle.__child__ = child
+HepMC.GenParticle.__daughter__ = child
+
+HepMC.GenParticle.__call__ = child
+HepMC.GenParticle.__getitem__ = child
+
+
+# =============================================================================
+## Get all 'in'-particles for the given HepMC::Vertex
+def particles_in(v):
+    """
+    Get all 'in'-particles for the given HepMC::Vertex
+
+    >>> v = ...
+    >>> for p in particles_in ( v ) :
+    ...   print p
+
+    """
+    return LoKi.GenChild.particles_in(v)
+
+
+particles_in.__doc__ += "\n\n" + LoKi.GenChild.particles_in.__doc__
+
+HepMC.GenVertex.particles_in = particles_in
+HepMC.GenVertex.__particles_in__ = particles_in
+
+
+# =============================================================================
+## Get all 'out'-particles for the given HepMC::Vertex
+def particles_out(v):
+    """
+    Get all 'out'-particles for the given HepMC::Vertex
+
+    >>> v = ...
+    >>> for p in particles_out ( v ) :
+    ...   print p
+
+    """
+    return LoKi.GenChild.particles_out(v)
+
+
+particles_out.__doc__ += "\n\n" + LoKi.GenChild.particles_out.__doc__
+
+HepMC.GenVertex.particles_out = particles_out
+HepMC.GenVertex.__particles_out__ = particles_out
+
+
+# =============================================================================
+## Get all particles for the given HepMC::GenEvent
+def particles_all(e):
+    """
+    Get all particles for the given HepMC::GenEvent
+
+    >>> e = ...
+    >>> for p in particles_all ( e ) :
+    ...   print p
+
+    """
+    return LoKi.GenChild.particles_all(e)
+
+
+particles_all.__doc__ += "\n\n" + LoKi.GenChild.particles_all.__doc__
+
+HepMC.GenEvent.particles_all = particles_all
+HepMC.GenEvent.__particles_all__ = particles_all
+
+
+# =============================================================================
+## Get all vertices for the given HepMC::GenEvent
+def vertices_all(e):
+    """
+    Get all vertices for the given HepMC::GenEvent
+
+    >>> e = ...
+    >>> for v in vertices_all ( e ) :
+    ...   print v
+
+    """
+    return LoKi.GenChild.vertices_all(e)
+
+
+vertices_all.__doc__ += "\n\n" + LoKi.GenChild.vertices_all.__doc__
+
+HepMC.GenEvent.vertices_all = vertices_all
+HepMC.GenEvent.__vertices_all__ = vertices_all
+
+
+# =============================================================================
+## Get all parents from the given HepMC::GenVertex
+def parents(v):
+    """
+    Get all parents from the given HepMC::GenVertex
+
+    >>> v = ...
+    >>> for p in parents ( v ) :
+    ...    print p
+
+    """
+    return LoKi.GenChild.parents(v)
+
+
+parents.__doc__ += "\n\n" + LoKi.GenChild.parents.__doc__
+
+HepMC.GenVertex.parents = parents
+HepMC.GenVertex.__parents__ = parents
+
+
+# =============================================================================
+## Get all children from the given HepMC::GenParticle or HepMC::GenVertex
+def children(o):
+    """
+    Get all children from the given HepMC::GenVertex or HepMC::GenParticle
+
+    >>> o = ...
+    >>> for p in children ( o ) :
+    ...    print p
+
+    """
+    return LoKi.GenChild.children(o)
+
+
+children.__doc__ += "\n\n" + LoKi.GenChild.children.__doc__
+
+HepMC.GenVertex.children = children
+HepMC.GenVertex.__children__ = children
+HepMC.GenVertex.daughters = children
+HepMC.GenVertex.__daughters__ = children
+
+HepMC.GenParticle.children = children
+HepMC.GenParticle.__children__ = children
+HepMC.GenParticle.daughters = children
+HepMC.GenParticle.__daughters__ = children
+
+
+# =============================================================================
+## Get all 'family'-particles from the given HepMC::GenVertex
+# def family(v):
+    # """
+    # Get all 'family'-particles from the given HepMC::GenVertex
+
+    # >>> v = ...
+    # >>> for p in family ( v ) :
+    # ...    print p
+
+    # """
+    # return LoKi.GenChild.family(v)
+
+
+# family.__doc__ += "\n\n" + LoKi.GenChild.family.__doc__
+
+# HepMC.GenVertex.family = family
+# HepMC.GenVertex.__family__ = family
+
+
+# =============================================================================
+## Get all ancestors from the given HepMC::GenParticel or GenVertex
+def ancestors(o):
+    """
+    Get all ancestors from the given HepMC::GenVertex or HepMC::GenParticle
+
+    >>> o = ...
+    >>> for p in ancestors ( o ) :
+    ...    print p
+
+    """
+    return LoKi.GenChild.ancestors(o)
+
+
+ancestors.__doc__ += "\n\n" + LoKi.GenChild.ancestors.__doc__
+
+HepMC.GenVertex.ancestors = ancestors
+HepMC.GenVertex.__ancestors__ = ancestors
+
+HepMC.GenParticle.ancestors = ancestors
+HepMC.GenParticle.__ancestors__ = ancestors
+
+
+# =============================================================================
+## Get all descendants from the given HepMC::GenParticel or GenVertex
+def descendants(o):
+    """
+    Get all descendants from the given HepMC::GenVertex or HepMC::GenParticle
+
+    >>> o = ...
+    >>> for p in descendants ( o ) :
+    ...    print p
+
+    """
+    return LoKi.GenChild.descendants(o)
+
+
+descendants.__doc__ += "\n\n" + LoKi.GenChild.descendants.__doc__
+
+HepMC.GenVertex.descendants = descendants
+HepMC.GenVertex.__descendants__ = descendants
+
+HepMC.GenParticle.descendants = descendants
+HepMC.GenParticle.__descendants__ = descendants
+
+
+# =============================================================================
+## Get all 'relatives'-particles from the given HepMC::GenVertex
+# def relatives(v):
+    # """
+    # Get all 'relatives'-particles from the given HepMC::GenVertex
+
+    # >>> v = ...
+    # >>> for p in relatives ( v ) :
+    # ...    print p
+
+    # """
+    # return LoKi.GenChild.relatives(v)
+
+
+# relatives.__doc__ += "\n\n" + LoKi.GenChild.relatives.__doc__
+
+# HepMC.GenVertex.relatives = relatives
+# HepMC.GenVertex.__relatives__ = relatives
+
+
+# =============================================================================
+## get all trees from GenEvent/HepMCEvent/HepMCEvents
+#  @code
+#  v = ...
+#  for t in trees ( v ) : print p
+#  @endcode
+#  @author Vanya BELYAEV van.Belyaev@itep.ru
+#  @date 2016-01-16
+def trees(v):
+    """Get all trees from GenEvent/HepMCEvent/HepMCEvents
+    >>> v = ...
+    >>> for t in trees ( v ) : print p
+    """
+    return LoKi.GenChild.trees(v)
+
+
+HepMC.GenEvent.trees = trees
+LHCb.HepMCEvent.trees = trees
+
+
+# =============================================================================
+## Extract the certain elements from decay trees and/or containers
+def genParticles(o, *a):
+    """
+    Extract the certain elements from decay trees and/or containers
+
+    >>> event = ... ;
+    >>> for pion in genParticles ( event , 'pi+' == GABSID ) :
+    ...    print pion
+
+    """
+    return LoKi.GenExtract.genParticles(o, *a)
+
+
+genParticles.__doc__ += "\n\n" + LoKi.GenExtract.genParticles.__doc__
+getParticles = genParticles
+particles = genParticles
+extract = genParticles
+
+
+# =============================================================================
+## Count number of 'interesting' elements in the decay tree or container,
+def count_if(s, *a):
+    """Count number of 'interesting' elements in the decay tree or container,
+    which satisfy certain criteria
+
+    >>> o = ...
+    >>> number_of_pions = count_if ( o , 'pi+' == GABSID )
+
+    """
+    return LoKi.Dicts.GenAlgs.count_if(s, *a)
+
+
+count_if.__doc__ += "\n\n" + LoKi.Dicts.GenAlgs.count_if.__doc__
+
+
+# =============================================================================
+## Check the presence of 'interesting' elements in the decay tree or container,
+def found(s, *a):
+    """Check the presence of 'interesting' elements in the decay tree or container,
+    which satisfy certain criteria
+
+    >>> o = ...
+    >>> good = found ( o , 'pi+' == GABSID )
+
+    """
+    return LoKi.Dicts.GenAlgs.found(s, *a)
+
+
+found.__doc__ += "\n\n" + LoKi.Dicts.GenAlgs.found.__doc__
+
+
+# =============================================================================
+## Accumulate through the decay tree or container,
+def accumulate(s, *a):
+    """Accumulate through the decay tree or container,
+
+    >>> o = ...
+    >>> ptOfAllPions= accumulate ( o , GPT , 'pi+' == GABSID )
+
+    """
+    return LoKi.Dicts.GenAlgs.accumulate(s, *a)
+
+
+accumulate.__doc__ += "\n\n" + LoKi.Dicts.GenAlgs.accumulate.__doc__
+
+
+# =============================================================================
+## Find the minimal value through decay tree or  container
+def min_value(s, *a):
+    """Find the minimal value through decay tree or  container
+
+    >>> o = ...
+    >>> minPT = min_value ( o , GPT , 'pi+' == GABSID )
+
+    """
+    return LoKi.Dicts.GenAlgs.min_value(s, *a)
+
+
+min_value.__doc__ += "\n\n" + LoKi.Dicts.GenAlgs.min_value.__doc__
+
+
+# =============================================================================
+## Find the maximal value through decay tree or  container
+def max_value(s, *a):
+    """Find the maximal value through decay tree or  container
+
+    >>> o = ...
+    >>> maxPT = max_value ( o , GPT , 'pi+' == GABSID )
+
+    """
+    return LoKi.Dicts.GenAlgs.max_value(s, *a)
+
+
+max_value.__doc__ += "\n\n" + LoKi.Dicts.GenAlgs.max_value.__doc__
+
+
+# =============================================================================
+## Find the minimal element through decay tree or  container
+def min_element(s, *a):
+    """
+    Find the minimal element through decay tree or  container
+
+    >>> o = ...
+    >>> pion = min_element ( o , GPT , 'pi+' == GABSID )
+
+    """
+    return LoKi.Dicts.GenAlgs.min_element(s, *a)
+
+
+min_element.__doc__ += "\n\n" + LoKi.Dicts.GenAlgs.min_element.__doc__
+
+
+# =============================================================================
+## Find the maximal element through decay tree or  container
+def max_element(s, *a):
+    """Find the maximal element through decay tree or  container
+
+    >>> o = ...
+    >>> pion = max_element ( o , GPT , 'pi+' == GABSID )
+
+    """
+    return LoKi.Dicts.GenAlgs.max_element(s, *a)
+
+
+max_element.__doc__ += "\n\n" + LoKi.Dicts.GenAlgs.max_element.__doc__
+
+for t in (HepMC.GenParticle, HepMC.GenVertex, HepMC.GenEvent, LHCb.HepMCEvent):
+
+    ## GenExtract
+    if not hasattr(t, 'genParticles'): t.genParticles = genParticles
+    if not hasattr(t, '__genParticles__'): t.__genParticles__ = genParticles
+    if not hasattr(t, 'getParticles'): t.getParticles = genParticles
+    if not hasattr(t, '__genParticles__'): t.__getParticles__ = genParticles
+    if not hasattr(t, 'particles'): t.particles = genParticles
+    if not hasattr(t, '__particles__'): t.__particles__ = genParticles
+    if not hasattr(t, 'extract'): t.extract = genParticles
+    if not hasattr(t, '__extract__'): t.__extract__ = genParticles
+
+    #@ GenAlgs:
+    if not hasattr(t, 'count_if'): t.count_if = count_if
+    if not hasattr(t, '__count_if__'): t.__count_if__ = count_if
+    if not hasattr(t, 'found'): t.found = found
+    if not hasattr(t, '__found__'): t.__found__ = found
+    if not hasattr(t, 'accumulate'): t.accumulate = accumulate
+    if not hasattr(t, '__accumulate__'): t.__accumulate__ = accumulate
+    if not hasattr(t, 'min_value'): t.min_value = min_value
+    if not hasattr(t, '__min_value__'): t.__min_value__ = min_value
+    if not hasattr(t, 'max_value'): t.max_value = max_value
+    if not hasattr(t, '__max_value__'): t.__max_value__ = max_value
+    if not hasattr(t, 'min_element'): t.min_element = min_element
+    if not hasattr(t, '__min_element__'): t.__min_element__ = min_element
+    if not hasattr(t, 'max_element'): t.max_element = max_element
+    if not hasattr(t, '__max_element__'): t.__max_element__ = max_element
+
+
+# =============================================================================
+## print the decay
+def printDecay(s, *a):
+    """Print the decay of HepMC::GenParticle
+
+    >>> p = ...
+    >>> printDecay ( p )
+
+    """
+    return LoKi.PrintHepMC.printDecay(s, *a)
+
+
+printDecay.__doc__ += "\n\n" + LoKi.PrintHepMC.printDecay.__doc__
+
+if not hasattr(HepMC.GenParticle, 'printDecay'):
+    HepMC.GenParticle.printDecay = printDecay
+    HepMC.GenParticle.decay = printDecay
+if not hasattr(HepMC.GenParticle, '__printDecay__'):
+    HepMC.GenParticle.__printDecay__ = printDecay
+    HepMC.GenParticle.__decay__ = printDecay
+
+
+def __particleID__(self):
+    """
+    Get the ParticleID obejct for the particle
+
+    >>> p =
+    >>> pid = p.particleID()
+
+    """
+    return LHCb.ParticleID(self.pdg_id())
+
+
+HepMC.GenParticle.__particleID__ = __particleID__
+HepMC.GenParticle.particleID = __particleID__
+
+import LoKiCore.functions as _LCF
+HepMC.GenParticle.pname = _LCF.__pname__
+HepMC.GenParticle.name = _LCF.__pname__
+HepMC.GenParticle.__pname__ = _LCF.__pname__
+
+_LCF.nChildren.__doc__ += "\n" + LoKi.GenChild.nChildren.__doc__
+_LCF.child.__doc__ += "\n" + LoKi.GenChild.child.__doc__
+_LCF.daughter.__doc__ += "\n" + LoKi.GenChild.child.__doc__
+_LCF.particles_out.__doc__ += "\n" + LoKi.GenChild.particles_out.__doc__
+_LCF.parents.__doc__ += "\n" + LoKi.GenChild.parents.__doc__
+_LCF.children.__doc__ += "\n" + LoKi.GenChild.children.__doc__
+_LCF.daughters.__doc__ += "\n" + LoKi.GenChild.children.__doc__
+_LCF.descendants.__doc__ += "\n" + LoKi.GenChild.descendants.__doc__
+_LCF.ancestors.__doc__ += "\n" + LoKi.GenChild.ancestors.__doc__
+
+_LCF.extract.__doc__ += "\n" + LoKi.GenExtract.genParticles.__doc__
+_LCF.particles.__doc__ += "\n" + LoKi.GenExtract.genParticles.__doc__
+_LCF.getParticles.__doc__ += "\n" + LoKi.GenExtract.genParticles.__doc__
+
+_LCF.count_if.__doc__ += "\n" + LoKi.Dicts.GenAlgs.count_if.__doc__
+_LCF.found.__doc__ += "\n" + LoKi.Dicts.GenAlgs.found.__doc__
+_LCF.accumulate.__doc__ += "\n" + LoKi.Dicts.GenAlgs.accumulate.__doc__
+_LCF.min_value.__doc__ += "\n" + LoKi.Dicts.GenAlgs.min_value.__doc__
+_LCF.max_value.__doc__ += "\n" + LoKi.Dicts.GenAlgs.max_value.__doc__
+_LCF.min_element.__doc__ += "\n" + LoKi.Dicts.GenAlgs.min_element.__doc__
+_LCF.max_element.__doc__ += "\n" + LoKi.Dicts.GenAlgs.max_element.__doc__
+
+_LCF.printDecay.__doc__ += "\n" + LoKi.PrintHepMC.printDecay.__doc__
+
+if not hasattr(HepMC.GenParticle, 'ConstVector'):
+    HepMC.GenParticle.ConstVector = std.vector('HepMC3::ConstGenParticlePtr')
+if not hasattr(HepMC.GenVertex, 'ConstVector'):
+    HepMC.GenVertex.ConstVector = std.vector('HepMC3::ConstGenVertexPtr')
+
+if not hasattr(HepMC.GenParticle, 'Range'):
+    HepMC.GenParticle.Range = Gaudi.NamedRange_(HepMC.GenParticle.ConstVector)
+if not hasattr(HepMC.GenVertex, 'Range'):
+    HepMC.GenVertex.Range = Gaudi.NamedRange_(HepMC.GenVertex.ConstVector)
+
+for r in (HepMC.GenParticle.Range, HepMC.GenVertex.Range,
+          cpp.Gaudi.Range_(HepMC.GenParticle.ConstVector),
+          cpp.Gaudi.Range_(HepMC.GenVertex.ConstVector)):
+
+    import LoKiCore.decorators as _LCD
+
+    r.__iter__ = _LCD._iter_1_
+    r.__getslice__ = _LCD._slice_
+    r.__getitem__ = r.__call__
+    r.__setitem__ = None
+
+if not hasattr(LHCb.HepMCEvent, 'Container'):
+    LHCb.HepMCEvent.Container = cpp.KeyedContainer(
+        LHCb.HepMCEvent, 'Containers::KeyedObjectManager<Containers::hashmap>')
+
+LHCb.HepMCEvent.Container.trees = trees
+HepMC.GenParticle.ConstVector.trees = trees
+HepMC.GenParticle.Range.trees = trees
+
+
+# =============================================================================
+## define various printers
+def _print_(self,
+            accept=None,
+            mark=None,
+            maxDepth=5,
+            vertex=False,
+            mode=LoKi.DecayChainBase.LV_WITHPT,
+            fg=cpp.MSG.YELLOW,
+            bg=cpp.MSG.RED,
+            vertexe=True):
+    """
+    Define the print functions for some MC-objects
+    for details see LoKi::GenDecayChain
+    """
+    _printer = LoKi.GenDecayChain(maxDepth, vertex, mode, fg, bg, vertexe)
+    if accept and not mark:
+        return _printer.print_(self, accept)
+    elif accept and mark:
+        return _printer.print_(self, accept, mark)
+    #
+    return _printer.print_(self)
+
+
+_print_.__doc__ += "\n" + LoKi.GenDecayChain.print_.__doc__
+
+HepMC.GenParticle.hex_id = lambda s: LoKi.GenParticles.hex_id(s)
+HepMC.GenParticle.__hash__ = lambda s: LoKi.GenParticles.hash(s)
+HepMC.GenVertex.__hash__ = lambda s: LoKi.GenParticles.hash(s)
+
+for t in (HepMC.GenParticle, HepMC.GenParticle.Range,
+          cpp.Gaudi.Range_(HepMC.GenParticle.ConstVector),
+          HepMC.GenParticle.ConstVector, HepMC.GenEvent, LHCb.HepMCEvent,
+          LHCb.HepMCEvent.Container):
+    t._print_ = _print_
+    t.__str__ = _print_
+    t.__repr__ = _print_
+
+# =============================================================================
+if '__main__' == __name__:
+
+    print 80 * '*'
+    print __doc__
+    print ' Author  : ', __author__
+    print ' Version : ', __version__
+    print ' Date    : ', __date__
+    print 80 * '*'
+    for i in dir():
+        print i
+
+# =============================================================================
+# The END
+# =============================================================================
diff --git a/Gen/LoKiGen/python/LoKiGen/__init__.py b/Gen/LoKiGen/python/LoKiGen/__init__.py
new file mode 100755
index 000000000..507c91ace
--- /dev/null
+++ b/Gen/LoKiGen/python/LoKiGen/__init__.py
@@ -0,0 +1,46 @@
+###############################################################################
+# (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration      #
+#                                                                             #
+# This software is distributed under the terms of the GNU General Public      #
+# Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   #
+#                                                                             #
+# In applying this licence, CERN does not waive the privileges and immunities #
+# granted to it by virtue of its status as an Intergovernmental Organization  #
+# or submit itself to any jurisdiction.                                       #
+###############################################################################
+# =============================================================================
+## @file  LoKiGen/__init__.py
+#  Helper file to manage LoKiGen package
+#
+#  This file is a part of LoKi project -
+#   'C++ ToolKit  for Smart and Friendly Physics Analysis'
+#
+#  The package has been designed with the kind help from
+#  Galina PAKHLOVA and Sergey BARSUK.  Many bright ideas,
+#  contributions and advices from G.Raven, J.van Tilburg,
+#  A.Golutvin, P.Koppenburg have been used in the design.
+#
+#  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+#  @date 2007-05-29
+# =============================================================================
+"""
+Helper file to manage LoKiGen package
+
+This file is a part of LoKi project -
+'C++ ToolKit  for Smart and Friendly Physics Analysis'
+
+The package has been designed with the kind help from
+Galina PAKHLOVA and Sergey BARSUK.  Many bright ideas,
+contributions and advices from G.Raven, J.van Tilburg,
+A.Golutvin, P.Koppenburg have been used in the design.
+
+"""
+# =============================================================================
+__author__ = "Vanya BELYAEV ibelyaev@physics.syr.edu"
+__date__ = "2007-05-29"
+__version__ = ""
+# =============================================================================
+import LoKiCore.decorators
+# =============================================================================
+# The END
+# =============================================================================
diff --git a/Gen/LoKiGen/python/LoKiGen/decorators.py b/Gen/LoKiGen/python/LoKiGen/decorators.py
new file mode 100755
index 000000000..3c4100004
--- /dev/null
+++ b/Gen/LoKiGen/python/LoKiGen/decorators.py
@@ -0,0 +1,207 @@
+#!/usr/bin/env python
+###############################################################################
+# (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration      #
+#                                                                             #
+# This software is distributed under the terms of the GNU General Public      #
+# Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   #
+#                                                                             #
+# In applying this licence, CERN does not waive the privileges and immunities #
+# granted to it by virtue of its status as an Intergovernmental Organization  #
+# or submit itself to any jurisdiction.                                       #
+###############################################################################
+# =============================================================================
+## @file LoKiGen/decorators.py
+#  The set of basic decorator for objects from LoKiGen library
+#
+#  This file is a part of LoKi project -
+#   'C++ ToolKit  for Smart and Friendly Physics Analysis'
+#
+#  The package has been designed with the kind help from
+#  Galina PAKHLOVA and Sergey BARSUK.  Many bright ideas,
+#  contributions and advices from G.Raven, J.van Tilburg,
+#  A.Golutvin, P.Koppenburg have been used in the design.
+#
+#  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+# =============================================================================
+"""
+The set of basic decorators for obejcts from LoKiGen library
+
+This file is a part of LoKi project -
+'C++ ToolKit  for Smart and Friendly Physics Analysis'
+
+The package has been designed with the kind help from
+Galina PAKHLOVA and Sergey BARSUK.  Many bright ideas,
+contributions and advices from G.Raven, J.van Tilburg,
+A.Golutvin, P.Koppenburg have been used in the design.
+
+"""
+# =============================================================================
+__author__ = "Vanya BELYAEV ibelyaev@physics.syr.edu"
+__date__ = "????-??-??"
+__version__ = ""
+# =============================================================================
+
+from LoKiGen.functions import *
+from LoKiGen.trees import *
+import LoKiGen.HepMC
+
+_name = __name__
+
+
+# =============================================================================
+## make the decoration of all objects fomr this module
+def _decorate(name=_name):
+    """ Make the decoration of all objects fomr this module """
+    import LoKiCore.decorators as _LoKiCore
+    _gp = 'HepMC3::ConstGenParticlePtr'
+    _gv = 'HepMC3::ConstGenVertexPtr'
+
+    ## _vgp = std.vector ( _gp      )
+    ## _vgv = std.vector ( _gv      )
+    ## _vd  = std.vector ( 'double' )
+
+    _vgp = 'std::vector<HepMC3::ConstGenParticlePtr>'
+    _vgv = 'std::vector<HepMC3::ConstGenVertexPtr>'
+    _vd = 'std::vector<double>'
+
+    # T -> double
+
+    _decorated = _LoKiCore.getAndDecorateFunctions(
+        name,  ## moduel name
+        LoKi.Functor(_gp, 'double'),  ## the base
+        LoKi.Dicts.FunCalls(HepMC.GenParticle),  ## call-traits
+        LoKi.Dicts.FuncOps(_gp))  ## operators&operations
+
+    _decorated |= _LoKiCore.getAndDecorateFunctions(
+        name,  ## module name
+        LoKi.Functor(_gv, 'double'),  ## the base
+        LoKi.Dicts.FunCalls(HepMC.GenVertex),  ## call-traits
+        LoKi.Dicts.FuncOps(_gv))  ## operators&operations
+
+    # T -> bool
+
+    _decorated |= _LoKiCore.getAndDecoratePredicates(
+        name,  ## module name
+        LoKi.Functor(_gp, bool),  ## the base
+        LoKi.Dicts.CutCalls(HepMC.GenParticle),  ## call-traits
+        LoKi.Dicts.CutsOps(_gp))  ## operators&operations
+
+    _decorated |= _LoKiCore.getAndDecoratePredicates(
+        name,  ## module name
+        LoKi.Functor(_gv, bool),  ## the base
+        LoKi.Dicts.CutCalls(HepMC.GenVertex),  ## call-traits
+        LoKi.Dicts.CutsOps(_gv))  ## operators&operations
+
+    # functional part
+
+    # map: vector<T> -> vector<double>
+
+    _decorated |= _LoKiCore.getAndDecorateMaps(
+        name,  ## moduel name
+        LoKi.Functor(_vgp, _vd),  ## the base
+        LoKi.Dicts.MapsOps(_gp))  ## call-traits
+    _decorated |= _LoKiCore.getAndDecorateMaps(
+        name,  ## moduel name
+        LoKi.Functor(_vgv, _vd),  ## the base
+        LoKi.Dicts.MapsOps(_gv))  ## call-traits
+
+    # pipe: vector<T> -> vector<T>
+
+    _decorated |= _LoKiCore.getAndDecoratePipes(
+        name,  ## module name
+        LoKi.Functor(_vgp, _vgp),  ## the base
+        LoKi.Dicts.PipeOps(_gp))  ## call-traits
+    _decorated |= _LoKiCore.getAndDecoratePipes(
+        name,  ## module name
+        LoKi.Functor(_vgv, _vgv),  ## the base
+        LoKi.Dicts.PipeOps(_gv))  ## call-traits
+
+    # vector<T> -> double
+
+    _decorated |= _LoKiCore.getAndDecorateFunVals(
+        name,  ## module name
+        LoKi.Functor(_vgp, 'double'),  ## the base
+        LoKi.Dicts.FunValOps(_gp))  ## call-traits
+    _decorated |= _LoKiCore.getAndDecorateFunVals(
+        name,  ## module name
+        LoKi.Functor(_vgv, 'double'),  ## the base
+        LoKi.Dicts.FunValOps(_gv))  ## call-traits
+
+    # vector<T> -> bool
+
+    _decorated |= _LoKiCore.getAndDecorateCutVals(
+        name,  ## module name
+        LoKi.Functor(_vgp, bool),  ## the base
+        LoKi.Dicts.CutValOps(_gp))  ## call-traits
+
+    _decorated |= _LoKiCore.getAndDecorateCutVals(
+        name,  ## module name
+        LoKi.Functor(_vgv, bool),  ## the base
+        LoKi.Dicts.CutValOps(_gv))  ## call-traits
+
+    #sources : void -> vector<T>
+
+    _decorated |= _LoKiCore.getAndDecorateSources(
+        name,  ## module name
+        LoKi.Functor('void', _vgp),  ## the base
+        LoKi.Dicts.SourceOps(_gp))  ## call-traits
+
+    _decorated |= _LoKiCore.getAndDecorateSources(
+        name,  ## module name
+        LoKi.Functor('void', _vgv),  ## the base
+        LoKi.Dicts.SourceOps(_gv))  ## call-traits
+
+    # decorate pids (Comparison with strings, integers and ParticleID objects:
+    for t in (GID, GABSID):
+        t = type(t)
+        _LoKiCore.decoratePID(t, LoKi.Dicts.PIDOps(t))
+        _decorated.add(t)
+    ##
+    return _decorated  ## RETURN
+
+
+# =============================================================================
+## perform the decoration
+_decorated = _decorate()  ## ATTENTION
+# =============================================================================
+
+## ============================================================================
+# /// Status code in HepMC::GenParticle
+#  enum statusType{ Unknown = 0,
+#                  StableInProdGen = 1,
+#                  DecayedByProdGen = 2,
+#                  DocumentationParticle = 3,
+#                  DecayedByDecayGen = 777,
+#                  DecayedByDecayGenAndProducedByProdGen = 888,
+#                  SignalInLabFrame = 889,
+#                  SignalAtRest = 998,
+#                  StableInDecayGen = 999
+#   };
+# @see  LHCb::HepMCEvent
+# @see  LHCb::HepMCEvent::statusType
+GUNKNOWNSTATUS = GSTATUS == LHCb.HepMCEvent.Unknown
+GSTABLEINPRODGEN = GSTATUS == LHCb.HepMCEvent.StableInProdGen
+GDECAYEDBYPRODGEN = GSTATUS == LHCb.HepMCEvent.DecayedByProdGen
+GDOCUMENTATION = GSTATUS == LHCb.HepMCEvent.DocumentationParticle
+GDOCUMENTATIONPARTICLE = GSTATUS == LHCb.HepMCEvent.DocumentationParticle
+GDECAYEDBYDECAYGEN = GSTATUS == LHCb.HepMCEvent.DecayedByDecayGen
+GDECAYEDBYDECAYGENANDPRODUCEDBYPRODGEN = GSTATUS == LHCb.HepMCEvent.DecayedByDecayGenAndProducedByProdGen
+GSIGNALINLABFRAME = GSTATUS == LHCb.HepMCEvent.SignalInLabFrame
+GSIGNALATREST = GSTATUS == LHCb.HepMCEvent.SignalAtRest
+GSTABLEINDECAYGEN = GSTATUS == LHCb.HepMCEvent.StableInDecayGen
+
+# =============================================================================
+if '__main__' == __name__:
+    print 80 * '*'
+    print __doc__
+    print ' Author    :  ', __author__
+    print ' Version   :  ', __version__
+    print ' Date      :  ', __date__
+    print ' Decorated : #', len(_decorated)
+    print 80 * '*'
+    for i in dir():
+        print i
+
+# =============================================================================
+# The END
+# =============================================================================
diff --git a/Gen/LoKiGen/python/LoKiGen/functions.py b/Gen/LoKiGen/python/LoKiGen/functions.py
new file mode 100755
index 000000000..6ed985e46
--- /dev/null
+++ b/Gen/LoKiGen/python/LoKiGen/functions.py
@@ -0,0 +1,410 @@
+#!/usr/bin/env python
+###############################################################################
+# (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration      #
+#                                                                             #
+# This software is distributed under the terms of the GNU General Public      #
+# Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   #
+#                                                                             #
+# In applying this licence, CERN does not waive the privileges and immunities #
+# granted to it by virtue of its status as an Intergovernmental Organization  #
+# or submit itself to any jurisdiction.                                       #
+###############################################################################
+# =============================================================================
+## @file LoKiGen/functions.py
+#  The full set of useful objects from LoKiGen library
+#
+#  This file is a part of LoKi project -
+#   'C++ ToolKit  for Smart and Friendly Physics Analysis'
+#
+#  The package has been designed with the kind help from
+#  Galina PAKHLOVA and Sergey BARSUK.  Many bright ideas,
+#  contributions and advices from G.Raven, J.van Tilburg,
+#  A.Golutvin, P.Koppenburg have been used in the design.
+#
+#  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+#  @date 2007-12-01
+# =============================================================================
+"""
+The full set of useful objects from LoKiGen library
+
+This file is a part of LoKi project -
+'C++ ToolKit  for Smart and Friendly Physics Analysis'
+
+The package has been designed with the kind help from
+Galina PAKHLOVA and Sergey BARSUK.  Many bright ideas,
+contributions and advices from G.Raven, J.van Tilburg,
+A.Golutvin, P.Koppenburg have been used in the design.
+
+"""
+# =============================================================================
+__author__ = "Vanya BELYAEV <ibelyaev@physics.syr.edu>"
+__date__ = "2007-12-01"
+__version__ = ""
+# =============================================================================
+
+import LoKiCore.decorators as _LoKiCore
+
+import cppyy
+cppyy.gbl.gInterpreter.Declare('#include "HepMC3/GenParticle.h"')
+cppyy.gbl.gInterpreter.Declare('#include "HepMC3/GenVertex.h"')
+cppyy.gbl.gInterpreter.Declare('#include "HepMC3/GenEvent.h"')
+cppyy.gbl.gInterpreter.Declare('#include "HepMC3/Relatives.h"')
+
+# Namespaces:
+cpp = _LoKiCore.cpp
+std = _LoKiCore.std
+LoKi = _LoKiCore.LoKi
+LHCb = _LoKiCore.LHCb
+HepMC = cpp.HepMC3
+Gaudi = cpp.Gaudi
+
+_GP = 'HepMC3::ConstGenParticlePtr'
+_GV = 'HepMC3::ConstGenVertexPtr'
+
+_c1 = std.vector(_GP)
+_c2 = std.vector(_GV)
+
+## ranges
+GRange = Gaudi.NamedRange_(_c1)
+GVRange = Gaudi.NamedRange_(_c2)
+## range-lists:
+GRangeL = LoKi.RangeList_(GRange)
+GVRangeL = LoKi.RangeList_(GVRange)
+
+# =============================================================================
+## "The main" types
+# =============================================================================
+
+## @see LoKi::Types::GFunc
+GFunc = LoKi.Functor(_GP + ',double')
+## @see LoKi::Types::GCuts
+GCuts = LoKi.Functor(_GP + ',bool')
+## @see LoKi::Types::GFun
+GFun = LoKi.FunctorFromFunctor(_GP + ',double')
+## @see LoKi::Types::GCut
+GCut = LoKi.FunctorFromFunctor(_GP + ',bool')
+## @see LoKi::Types::GFunc
+GVFunc = LoKi.Functor(_GV + ',double')
+## @see LoKi::Types::GCuts
+GVCuts = LoKi.Functor(_GV + ',bool')
+## @see LoKi::Types::GFun
+GVFun = LoKi.FunctorFromFunctor(_GV + ',double')
+## @see LoKi::Types::GCut
+GVCut = LoKi.FunctorFromFunctor(_GV + ',bool')
+
+# =============================================================================
+## All concrete types
+# =============================================================================
+
+## @see LoKi::Cuts::G3Q
+G3Q = LoKi.GenParticles.ThreeCharge()
+## @see LoKi::Cuts::GABSID
+GABSID = LoKi.GenParticles.AbsIdentifier()
+## @see LoKi::Cuts::GALL
+GALL = LoKi.Constant(_GP + ',bool')(True)
+## @see LoKi::Cuts::GANCESTOR
+GANCESTOR = LoKi.GenParticles.IsAnAncestor
+## @see LoKi::Cuts::GBAR
+GBAR = LoKi.GenParticles.BarCode()
+## @see LoKi::Cuts::GBARCODE
+GBARCODE = LoKi.GenParticles.BarCode()
+## @see LoKi::Cuts::GBARYON
+GBARYON = LoKi.GenParticles.IsBaryon()
+## @see LoKi::Cuts::GBEAUTY
+##GBEAUTY   = GQUARK( LHCb.ParticleID.bottom  )
+GBEAUTY = LoKi.GenParticles.HasQuark(5)
+## @see LoKi::Cuts::GCHARGED
+GCHARGED = LoKi.GenParticles.IsCharged()
+## @see LoKi::Cuts::GCHARM
+##GCHARM  = GQUARK( LHCb.ParticleID.charm  )
+GCHARM = LoKi.GenParticles.HasQuark(4)
+## @see LoKi::Cuts::GCHILD
+GCHILD = LoKi.GenParticles.ChildFun
+## @see LoKi::Cuts::GCHILDCUT
+GCHILDCUT = LoKi.GenParticles.ChildCut
+## @see LoKi::Cuts::GCHILDFUN
+GCHILDFUN = LoKi.GenParticles.ChildFun
+## @see LoKi::Cuts::GCTAU
+GCTAU = LoKi.GenParticles.ProperLifeTime()
+## @see LoKi::Cuts::GDECNODE
+GDECNODE = LoKi.GenParticles.DecNode
+## @see LoKi::Cuts::GLONGLIVED
+GLONGLIVED = LoKi.GenParticles.LongLived()
+## @see LoKi::Cuts::GDECTREE
+GDECTREE = LoKi.GenParticles.DecTree
+## @see LoKi::Cuts::GDELTAR2
+GDELTAR2 = LoKi.GenParticles.DeltaR2
+## @see LoKi::Cuts::GDETA
+GDETA = LoKi.GenParticles.DeltaEta
+## @see LoKi::Cuts::GDPHI
+GDPHI = LoKi.GenParticles.DeltaPhi
+## @see LoKi::Cuts::GDR2
+GDR2 = LoKi.GenParticles.DeltaR2
+## @see LoKi::Cuts::GFALSE
+GFALSE = LoKi.Constant(_GP + ',bool')(False)
+## @see LoKi::Cuts::GFAEVX
+GFAEVX = LoKi.GenParticles.AdapterToEndVertex
+## @see LoKi::Cuts::GFAPVX
+GFAPVX = LoKi.GenParticles.AdapterToProductionVertex
+## @see LoKi::Cuts::GFROMTREE
+GFROMTREE = LoKi.GenParticles.FromHepMCTree
+## @see LoKi::Cuts::GHADRON
+GHADRON = LoKi.GenParticles.IsHadron()
+## @see LoKi::Cuts::GID
+GID = LoKi.GenParticles.Identifier()
+## @see LoKi::Cuts::GINTREE
+GINTREE = LoKi.GenParticles.InTree
+## @see LoKi::Cuts::GLEPTON
+GLEPTON = LoKi.GenParticles.IsLepton()
+## @see LoKi::Cuts::GMESON
+GMESON = LoKi.GenParticles.IsMeson()
+## @see LoKi::Cuts::GMOMDIST
+GMOMDIST = LoKi.GenParticles.MomentumDistance
+## @see LoKi::Cuts::GNEUTRAL
+GNEUTRAL = LoKi.GenParticles.IsNeutral()
+## @see LoKi::Cuts::GNINTREE
+GNINTREE = LoKi.GenParticles.NInTree
+## @see LoKi::Cuts::GNLT
+GNLT = LoKi.GenParticles.NominalLifeTime()
+## @see LoKi::Cuts::GNONE
+GNONE = LoKi.Constant(_GP + ',bool')(False)
+## @see LoKi::Cuts::GNUCLEUS
+GNUCLEUS = LoKi.GenParticles.IsNucleus()
+## @see LoKi::Cuts::GONE
+GONE = LoKi.Constant(_GP + ',double')(1.0)
+## @see LoKi::Cust::GOSCILLATED
+GOSCILLATED = LoKi.GenParticles.Oscillated()
+## @see LoKi::Cust::GOSCILLATED1
+GOSCILLATED1 = LoKi.GenParticles.Oscillated1()
+## @see LoKi::Cust::GOSCILLATED2
+GOSCILLATED2 = LoKi.GenParticles.Oscillated2()
+## @see LoKi::Cuts::GPT0
+GPT0 = LoKi.GenParticles.TransverseMomentum()
+## @see LoKi::Cuts::GPTDIR
+GPTDIR = LoKi.GenParticles.TransverseMomentumRel
+## @see LoKi::Cuts::GPTREL
+GPTREL = LoKi.GenParticles.TransverseMomentumRel
+## @see LoKi::Cuts::GQUARK
+GQUARK = LoKi.GenParticles.HasQuark
+## @see LoKi::Cuts::GSAME
+GSAME = LoKi.TheSame(_GP)
+## @see LoKi::Cuts::GSTATUS
+GSTATUS = LoKi.GenParticles.Status()
+## @see LoKi::Cuts::GSTRANGE
+## GSTRANGE  = LoKi.GenParticles.HasQuark ( LHCb.ParticleID.strange )
+GSTRANGE = LoKi.GenParticles.HasQuark(3)
+## @see LoKi::Cuts::GTIME
+GTIME = LoKi.GenParticles.ProperLifeTime()
+## @see LoKi::Cuts::GTOP
+## GTOP  = LoKi.GenParticles.HasQuark ( LHCb.ParticleID.top )
+GTOP = LoKi.GenParticles.HasQuark(6)
+## @see LoKi::Cuts::GTRUE
+GTRUE = LoKi.Constant(_GP, bool)(True)
+## @see LoKi::Cuts::GVALID
+GVALID = LoKi.Valid(_GP)()
+## @see LoKi::Cuts::GVEV
+GVEV = LoKi.GenParticles.ValidEndVertex()
+## @see LoKi::Cuts::GZERO
+GZERO = LoKi.Constant(_GP + ',double')(0.0)
+
+## @see LoKi::Cuts::GM
+GM = LoKi.GenParticles.Mass()
+## @see LoKi::Cuts::GMASS
+GMASS = LoKi.GenParticles.Mass
+
+## @see LoKi::Cuts::GE
+GE = LoKi.GenParticles.Energy()
+## @see L oKi::Cuts::GENERGY
+GENERGY = LoKi.GenParticles.Energy
+
+## @see LoKi::Cuts::GP
+GP = LoKi.GenParticles.Momentum()
+## @see LoKi::Cuts::GMOMENTUM
+GMOMENTUM = LoKi.GenParticles.Momentum
+
+## @see LoKi::Cuts::GPX
+GPX = LoKi.GenParticles.MomentumX()
+## @see LoKi::Cuts::GMOMX
+GMOMX = LoKi.GenParticles.MomentumX
+
+## @see LoKi::Cuts::GPY
+GPY = LoKi.GenParticles.MomentumY()
+## @see LoKi::Cuts::GMOMY
+GMOMY = LoKi.GenParticles.MomentumY
+
+## @see LoKi::Cuts::GPZ
+GPZ = LoKi.GenParticles.MomentumZ()
+## @see LoKi::Cuts::GMOMENTUM
+GMOMZ = LoKi.GenParticles.MomentumZ
+
+## @see LoKi::Cuts::GPT
+GPT = LoKi.GenParticles.TransverseMomentum()
+## @see LoKi::Cuts::GMOMENTUM
+GMOMT = LoKi.GenParticles.TransverseMomentum
+
+## @see LoKi::Cuts::GMAXTREE
+GMAXTREE = LoKi.GenParticles.MaxTree
+## @see LoKi::Cuts::GMINTREE
+GMINTREE = LoKi.GenParticles.MinTree
+## @see LoKi::Cuts::GSUMTREE
+GSUMTREE = LoKi.GenParticles.SumTree
+## @see LoKi::Cuts::GMULTTREE
+GMULTTREE = LoKi.GenParticles.MultTree
+
+## @see LoKi::Cuts::GETA
+GETA = LoKi.GenParticles.PseudoRapidity()
+## @see LoKi::Cuts::GPSEUDORAPIDITY
+GPSEUDORAPIDITY = LoKi.GenParticles.PseudoRapidity
+
+## @see LoKi::Cuts::GBETA
+GBETA = LoKi.GenParticles.Beta()
+## @see LoKi::Cuts::GGAMMA
+GGAMMA = LoKi.GenParticles.Gamma()
+## @see LoKi::Cuts::GBETAGAMMA
+GBETAGAMMA = LoKi.GenParticles.BetaGamma()
+## @see LoKi::Cuts::GBGAMMA
+GBGAMMA = LoKi.GenParticles.BetaGamma()
+## @see LoKi::Cuts::GBG
+GBG = LoKi.GenParticles.BetaGamma()
+
+## @see LoKi::Cuts::GY
+GY = LoKi.GenParticles.Rapidity()
+## @see LoKi::Cuts::GRAPIDITY
+GRAPIDITY = LoKi.GenParticles.Rapidity
+
+## @see LoKi::Cuts::GY0
+GY0 = LoKi.GenParticles.Rapidity0()
+## @see LoKi::Cuts::GRAPIDITY0
+GRAPIDITY0 = LoKi.GenParticles.Rapidity0
+
+## @see LoKi::Cuts::GPHI
+GPHI = LoKi.GenParticles.Phi()
+## @see LoKi::Cuts::GASYMUTH
+GASYMUTH = LoKi.GenParticles.Phi
+
+## @see LoKi::Cuts::GTHETA
+GTHETA = LoKi.GenParticles.Theta()
+## @see LoKi::Cuts::GASYMUTH
+GPOLAR = LoKi.GenParticles.Theta
+
+## @see LoKi::Cuts::GFLIGHTPV
+GFLIGHTPV = LoKi.GenParticles.Flight(True)
+## @see LoKi::Cuts::GPVFLIGHT
+GPVFLIGHT = LoKi.GenParticles.Flight(True)
+## @see LoKi::Cuts::GFLIGHT
+GFLIGHT = LoKi.GenParticles.Flight(False)
+
+## @see LoKi::Cuts::GCOUNT
+GCOUNT = LoKi.GenParticles.Count
+## @see LoKi::Cuts::GHAS
+GHAS = LoKi.GenParticles.Has
+
+## @see LoKi::Cuts::GVTRUE
+GVTRUE = LoKi.Constant(_GV, bool)(True)
+## @see LoKi::Cuts::GVFALSE
+GVFALSE = LoKi.Constant(_GV, bool)(False)
+## @see LoKi::Cuts::GVALL
+GVALL = GVTRUE
+## @see LoKi::Cuts::GVNONE
+GVNONE = GVFALSE
+## @see LoKi::Cuts::GVONE
+GVONE = LoKi.Constant(_GV + ',double')(1.0)
+## @see LoKi::Cuts::GVZERO
+GVZERO = LoKi.Constant(_GV + ',double')(0.0)
+## @see LoKi::Cuts::GVVALID
+GVVALID = LoKi.Valid(_GV)()
+## @see LoKi::Cuts::GVSAME
+GVSAME = LoKi.TheSame(_GV)
+## @see LoKi::Cuts::GVBAR
+GVBAR = LoKi.GenVertices.BarCode()
+## @see LoKi::Cuts::GVBARCODE
+GVBARCODE = GVBAR
+## @see LoKi::Cuts::GVTIME
+GVTIME = LoKi.GenVertices.PositionT()
+## @see LoKi::Cuts::GVCOUNT
+GVCOUNT = LoKi.GenVertices.CountIF
+## @see LoKi::Cuts::GVSUM
+GVSUM = LoKi.GenVertices.SumIF
+
+## @see LoKi::Cuts::GVX
+GVX = LoKi.GenVertices.PositionX()
+## @see LoKi::Cuts::GVY
+GVY = LoKi.GenVertices.PositionY()
+## @see LoKi::Cuts::GVZ
+GVZ = LoKi.GenVertices.PositionZ()
+## @see LoKi::Cuts::GVRHO
+GVRHO = LoKi.GenVertices.Rho()
+## @see LoKi::Cuts::GVT
+GVT = LoKi.GenVertices.PositionT()
+
+## @see LoKi::Cuts::GCOSPOL
+GCOSPOL = LoKi.GenParticles.PolarizationAngle
+## @see LoKi::Cuts::GSINCHI
+GSINCHI = LoKi.GenParticles.SinChi
+## @see LoKi::Cuts::GCOSCHI
+GCOSCHI = LoKi.GenParticles.CosChi
+## @see LoKi::Cuts::GANGLECHI
+GANGLECHI = LoKi.GenParticles.AngleChi
+## @see LoKi::Cuts::GCOSTHETATR
+GCOSTHETATR = LoKi.GenParticles.CosThetaTr
+## @see LoKi::Cuts::GSINPHITR
+GSINPHITR = LoKi.GenParticles.SinPhiTr
+## @see LoKi::Cuts::GCOSPHITR
+GCOSPHITR = LoKi.GenParticles.CosPhiTr
+## @see LoKi::Cuts::GANGLEPHITR
+GANGLEPHITR = LoKi.GenParticles.AnglePhiTr
+
+## functional part
+#_vgp      = std.vector ( _GP    )
+#_vgv      = std.vector ( _GV    )
+#_vd       = std.vector ('double')
+_vgp = 'std::vector<HepMC3::ConstGenParticlePtr>'
+_vgv = 'std::vector<HepMC3::ConstGenVertexPtr>'
+_vd = 'std::vector<double>'
+
+#
+GMaps = LoKi.Functor(_vgp, _vd)
+GMap = LoKi.FunctorFromFunctor(_vgp, _vd)
+GPipes = LoKi.Functor(_vgp, _vgp)
+GPipe = LoKi.FunctorFromFunctor(_vgp, _vgp)
+GFunVals = LoKi.Functor(_vgp, 'double')
+GFunVal = LoKi.FunctorFromFunctor(_vgp, 'double')
+GCutVals = LoKi.Functor(_vgp, bool)
+GCutVal = LoKi.FunctorFromFunctor(_vgp, bool)
+GSources = LoKi.Functor('void', _vgp)
+GSource = LoKi.FunctorFromFunctor('void', _vgp)
+
+#
+GVMaps = LoKi.Functor(_vgv, _vd)
+GVMap = LoKi.FunctorFromFunctor(_vgv, _vd)
+GVPipes = LoKi.Functor(_vgv, _vgv)
+GVPipe = LoKi.FunctorFromFunctor(_vgv, _vgv)
+GVFunVals = LoKi.Functor(_vgv, 'double')
+GVFunVal = LoKi.FunctorFromFunctor(_vgv, 'double')
+GVCutVals = LoKi.Functor(_vgv, bool)
+
+GVCutVal = LoKi.FunctorFromFunctor(_vgv, bool)
+
+GSOURCE = LoKi.GenParticles.SourceTES
+GTESDATA = LoKi.GenParticles.TESData  ## <-- DataHandle used
+GNUM = LoKi.GenParticles.TESCounter
+
+GEMPTY = LoKi.Functors.Empty(_GP)()
+GVEMPTY = LoKi.Functors.Empty(_GV)()
+GSIZE = LoKi.Functors.Size(_GP)()
+GVSIZE = LoKi.Functors.Size(_GV)()
+
+# =============================================================================
+if '__main__' == __name__:
+    print 80 * '*'
+    print __doc__
+    print ' Author  : ', __author__
+    print ' Version : ', __version__
+    print ' Date    : ', __date__
+    print 80 * '*'
+    for i in dir():
+        print i
+
+# =============================================================================
+# The END
+# =============================================================================
diff --git a/Gen/LoKiGen/python/LoKiGen/graph.py b/Gen/LoKiGen/python/LoKiGen/graph.py
new file mode 100644
index 000000000..d3fc1a909
--- /dev/null
+++ b/Gen/LoKiGen/python/LoKiGen/graph.py
@@ -0,0 +1,226 @@
+#!/usr/bin/env python
+###############################################################################
+# (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration      #
+#                                                                             #
+# This software is distributed under the terms of the GNU General Public      #
+# Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   #
+#                                                                             #
+# In applying this licence, CERN does not waive the privileges and immunities #
+# granted to it by virtue of its status as an Intergovernmental Organization  #
+# or submit itself to any jurisdiction.                                       #
+###############################################################################
+# =============================================================================
+## @file LoKiGen/graph.py
+#  Simple utilities to vizualize the decay tree
+#
+#        This file is a part of LoKi project -
+#    "C++ ToolKit  for Smart and Friendly Physics Analysis"
+#
+#  The package has been designed with the kind help from
+#  Galina PAKHLOVA and Sergey BARSUK.  Many bright ideas,
+#  contributions and advices from G.Raven, J.van Tilburg,
+#  A.Golutvin, P.Koppenburg have been used in the design.
+#
+#  @author Vanya BELYAEV Ivan.Belyaev@itep.ru
+#  @date   2016-01-16
+# =============================================================================
+"""Simple utilities to vizualize the decay tree
+
+      This file is a part of LoKi project -
+'C++ ToolKit  for Smart and Friendly Physics Analysis'
+
+The package has been designed with the kind help from
+Galina PAKHLOVA and Sergey BARSUK.  Many bright ideas,
+contributions and advices from G.Raven, J.van Tilburg,
+A.Golutvin, P.Koppenburg have been used in the design.
+"""
+# =============================================================================
+__author__ = "Vanya BELYAEV Ivan.Belyaev@itep.ru"
+__date__ = "2015-01-16"
+__version__ = ""
+__all__ = (
+    'graph',  ## function to produce graph
+    'view',  ## function to produce graph and immediately display it
+    'HepMCDecayGraph'  ## helper class to produce graph
+)
+# =============================================================================
+import pydot
+from LoKiGen.HepMC import HepMC, LHCb
+#
+node_attributes = {
+    'shape': 'ellipse',
+    'fillcolor': 'yellow',
+    'color': 'red',
+    'style': 'filled'
+}
+edge_attributes = {'color': 'red'}
+#
+PARTICLE = HepMC.GenParticle
+HEPMCEVENT = HepMC.GenEvent
+LHCBEVENT = LHCb.HepMCEvent
+LHCBEVENTS = LHCb.HepMCEvent.Container
+CONTAINER = HepMC.GenParticle.ConstVector
+RANGE = HepMC.GenParticle.Range
+
+
+#
+# =============================================================================
+## @class HepMCDecayGraph
+#  Make graphical (dot) representation of the decay tree
+#  @code
+#  p     = ...
+#  dg    = HepMCDecayGraph ( p )
+#  graph = gd.graph()
+#  graph.write('graph.png', format = 'png')
+#  @endcode
+#  @author Vanya BELYAEV Ivan.Belyaev@itep.ru
+#  @date 2016-01-16
+class HepMCDecayGraph(object):
+    """ Make graphical representation of the decay tree
+    >>> p     = ...
+    >>> dg    = MCDecayGraph ( p )
+    >>> graph = gd.graph()
+    >>> graph.write('graph.png', format = 'png')
+    """
+
+    def __init__(self, trees):
+        self._nodes = set()
+        self._edges = set()
+        self._graph = pydot.Dot('DecayTree', graph_type='digraph')
+
+        if isinstance(trees, PARTICLE): trees = [trees]
+        elif isinstance(trees, (HEPMCEVENT, LHCBEVENT, LHCBEVENTS)):
+            trees = trees.trees()
+
+        for t in trees:
+            self.add_tree(t)
+
+    ## construct node-id for the given particle
+    def node_id(self, p):
+        if not p: return ''
+        nid = '%s:%s:#%d/%d' % (p.name(), p.hex_id(), p.barcode(), p.status())
+        return pydot.quote_if_necessary(nid)
+
+    ## add particle to graph
+    def add_tree(self, p):
+
+        nid = self.node_id(p)
+        if nid in self._nodes: return nid
+
+        # create new node
+        node = pydot.Node(name=nid, label=p.name(), **node_attributes)
+
+        self._nodes.add(nid)
+        self._graph.add_node(node)
+
+        for c in p.children():
+            nidc = self.add_tree(c)  ## NB: recursion here
+            edge = nid, nidc
+            if not edge in self._edges:
+                self._graph.add_edge(pydot.Edge(
+                    *edge, **edge_attributes))  ## create edge
+                self._edges.add(edge)
+
+        return nid
+
+    ## get the graph
+    def graph(self):
+        return self._graph
+
+
+# =============================================================================
+## make a graph for given particle or container of particles
+#  @code
+#  p               = ...
+#  graph_file_name = graph( p , format  = 'png' )
+#  @endcode
+#  @author Vanya BELYAEV Ivan.Belyaev@itep.ru
+#  @date 2016-01-16
+def graph(particle, format='png', filename='hepmcdecaytree'):
+    """ Make a graph for given particle
+    >>> p               = ...
+    >>> graph_file_name = graph( p , format  = 'png' )
+    """
+    dg = HepMCDecayGraph(particle)
+    dt = dg.graph()
+    #
+    f, d, e = filename.rpartition('.')
+    if not d: filename += '.' + format
+    #
+    return filename if dt.write(filename, format=format) else None
+
+
+# =============================================================================
+## prepare the graph and vizualize it
+#  @code
+#  p = ...
+#  p.view ( format  = 'png' )
+#  @endcode
+#  @author Vanya BELYAEV Ivan.Belyaev@itep.ru
+#  @date 2016-01-16
+def view(particle, command=None, format='png'):
+    """Prepare the graph and vizualize it
+    p = ...
+    p.view ( format  = 'png' )
+    p.view ( format  = 'png' , commmand = 'eog' )
+    """
+
+    class _TmpName_(object):
+        def __init__(self, suffix='png'):
+            self.suffix = '.' + suffix
+
+        def __enter__(self):
+            import tempfile
+            self.name = tempfile.mktemp(suffix=self.suffix)
+            return self.name
+
+        def __exit__(self, *_):
+            import os
+            try:
+                if os.path.exists(self.name):
+                    os.remove(self.name)
+            except:
+                pass
+
+    with _TmpName_(format) as ofile:
+
+        if not graph(particle, format, filename=ofile):
+            print 'Error producing the graph for %s ' % particle.decay()
+            return
+
+        if not command:
+            import distutils.spawn as ds
+            for i in ('eog', 'display', 'gnome-photos', 'gwenview', 'gimp',
+                      'gthumb', 'google-chrome'):
+                command = ds.find_executable(i)
+                if command: break
+
+        if not command:
+            print 'No valid command is found!'
+            return
+
+        import subprocess
+        try:
+            subprocess.check_call("%s %s " % (command, ofile), shell=True)
+        except subprocess.CalledProcessError:
+            pass
+
+
+for t in (PARTICLE, PARTICLE.Range, PARTICLE.ConstVector, HEPMCEVENT,
+          LHCBEVENT, LHCBEVENTS):
+    t.graph = graph
+    t.view = view
+
+# =============================================================================
+if '__main__' == __name__:
+
+    print 80 * '*'
+    print __doc__
+    print ' Author  : ', __author__
+    print ' Version : ', __version__
+    print ' Date    : ', __date__
+    print 80 * '*'
+
+# =============================================================================
+# The END
+# =============================================================================
diff --git a/Gen/LoKiGen/python/LoKiGen/tests.py b/Gen/LoKiGen/python/LoKiGen/tests.py
new file mode 100755
index 000000000..f9699adb0
--- /dev/null
+++ b/Gen/LoKiGen/python/LoKiGen/tests.py
@@ -0,0 +1,118 @@
+#!/usr/bin/env python
+###############################################################################
+# (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration      #
+#                                                                             #
+# This software is distributed under the terms of the GNU General Public      #
+# Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   #
+#                                                                             #
+# In applying this licence, CERN does not waive the privileges and immunities #
+# granted to it by virtue of its status as an Intergovernmental Organization  #
+# or submit itself to any jurisdiction.                                       #
+###############################################################################
+# =============================================================================
+## @file   LoKiGen/tests.py
+#
+#  This file is a part of LoKi project -
+#   'C++ ToolKit  for Smart and Friendly Physics Analysis'
+#
+#  The package has been designed with the kind help from
+#  Galina PAKHLOVA and Sergey BARSUK.  Many bright ideas,
+#  contributions and advices from G.Raven, J.van Tilburg,
+#  A.Golutvin, P.Koppenburg have been used in the design.
+#
+#  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+#  @date 2007-05-29
+# =============================================================================
+"""
+The basic tests for LoKiGen package
+
+This file is a part of LoKi project -
+'C++ ToolKit  for Smart and Friendly Physics Analysis'
+
+The package has been designed with the kind help from
+Galina PAKHLOVA and Sergey BARSUK.  Many bright ideas,
+contributions and advices from G.Raven, J.van Tilburg,
+A.Golutvin, P.Koppenburg have been used in the design.
+
+"""
+# =============================================================================
+__author__ = "Vanya BELYAEV ibelyaev@physics.syr.edu"
+__date__ = "2007-05-29"
+__version__ = ""
+# =============================================================================
+
+# temporary
+import GaudiPython.Pythonizations
+
+import LoKiNumbers.decorators
+import LoKiGen.HepMC
+
+from LoKiGen.decorators import *
+from LoKiCore.functions import *
+from LoKiCore.math import *
+
+
+def test1():
+
+    p = HepMC.GenParticle()
+    p.set_pdg_id(11)
+
+    print 'particle: %s/%s ' % (p.name(), pname(p))
+    print 'particle: (GPX,GPY,GPZ,GM)=(%s,%s,%s,%s)' % (GPX(p), GPY(p), GPZ(p),
+                                                        GM(p))
+    print 'particle: ( p>>GID , p>>cos(GE) )=(%s,%s)' % (p >> GID,
+                                                         p >> cos(GE))
+
+    gpv = std.vector('HepMC3::ConstGenParticlePtr')
+    v = gpv()
+
+    v.push_back(p)
+    p1 = HepMC.GenParticle()
+    p1.set_pdg_id(13)
+    v.push_back(p1)
+    p2 = HepMC.GenParticle()
+    p2.set_pdg_id(22)
+    v.push_back(p2)
+
+    print ' v>>GID                           : %s' % (v >> GID)
+    print ' v>>yields(GID)                   : %s' % (v >> yields(GID))
+    print ' v>>process(GID)>>min_value(GP)   : %s' % (
+        v >> process(GID) >> min_value(GP))
+    print '(v>>min_element(GID))[0].name()   : %s' % (
+        v >> min_element(GID))[0].name()
+    print ' v>>min_value(GID)                : %s' % (v >> min_value(GID))
+    print ' v>>("e+"!=GABSID)>>GSIZE         : %s' % (
+        v >> ('e+' != GABSID) >> GSIZE)
+    print ' v>>select("mu+"!=GABSID)>>GEMPTY : %s' % (
+        v >> select('mu+' != GABSID) >> GEMPTY)
+
+    f1 = in_list(GID, ["e+", "e-", 'mu+', 'mu-'])
+    f2 = in_list(GABSID, ["e+", "e-", 'mu+', 'mu-'])
+    print ' in_list ( GID    , [ "e+" , "e-" , "mu+" , "mu-"] ) : %s %s ' % (
+        f1, f1(p1))
+    print ' in_list ( GABSID , [ "e+" , "e-" , "mu+" , "mu-"] ) : %s %s ' % (
+        f2, f2(p1))
+
+
+# =============================================================================
+def testAll():
+    test1()
+
+
+# =============================================================================
+if '__main__' == __name__:
+
+    print 80 * '*'
+    print __doc__
+    print ' Author  : ', __author__
+    print ' Version : ', __version__
+    print ' Date    : ', __date__
+    print 80 * '*'
+    for i in dir():
+        print i
+
+    testAll()
+
+# =============================================================================
+# The END
+# =============================================================================
diff --git a/Gen/LoKiGen/python/LoKiGen/trees.py b/Gen/LoKiGen/python/LoKiGen/trees.py
new file mode 100755
index 000000000..8d73922c3
--- /dev/null
+++ b/Gen/LoKiGen/python/LoKiGen/trees.py
@@ -0,0 +1,81 @@
+#!/usr/bin/env python
+###############################################################################
+# (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration      #
+#                                                                             #
+# This software is distributed under the terms of the GNU General Public      #
+# Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   #
+#                                                                             #
+# In applying this licence, CERN does not waive the privileges and immunities #
+# granted to it by virtue of its status as an Intergovernmental Organization  #
+# or submit itself to any jurisdiction.                                       #
+###############################################################################
+# =============================================================================
+## @file functions.py LoKiGen/trees.py
+#  The set of basic decorator for Tree-objects from LoKiPhys library
+#  The file is a part of LoKi and Bender projects
+#
+#        This file is a part of LoKi project -
+#    "C++ ToolKit  for Smart and Friendly Physics Analysis"
+#
+#  The package has been designed with the kind help from
+#  Galina PAKHLOVA and Sergey BARSUK.  Many bright ideas,
+#  contributions and advices from G.Raven, J.van Tilburg,
+#  A.Golutvin, P.Koppenburg have been used in the design.
+#
+#  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+# =============================================================================
+"""
+The set of basic decorators for Tree-objects from LoKiGen library
+
+      This file is a part of LoKi project -
+'C++ ToolKit  for Smart and Friendly Physics Analysis'
+
+The package has been designed with the kind help from
+Galina PAKHLOVA and Sergey BARSUK.  Many bright ideas,
+contributions and advices from G.Raven, J.van Tilburg,
+A.Golutvin, P.Koppenburg have been used in the design.
+"""
+# =============================================================================
+__author__ = "Vanya BELYAEV ibelyaev@physics.syr.edu"
+# =============================================================================
+
+import LoKiCore.decorators as _LoKiCore
+
+# Namespaces:
+from LoKiCore.basic import cpp, std, LoKi
+Decays = cpp.Decays
+
+_GP = 'HepMC3::ConstGenParticlePtr'
+
+_decorated = _LoKiCore.decorateTrees(
+    (Decays.iTree_(_GP), Decays.Tree_(_GP), Decays.Trees.Any_(_GP),
+     Decays.Trees.None_(_GP), Decays.Trees.Stable_(_GP),
+     Decays.Trees.GenExclusive, Decays.Trees.GenInclusive,
+     Decays.Trees.GenOptional, Decays.Trees.GenPhotos,
+     Decays.Trees.GenPhotosOptional), LoKi.Dicts.TreeOps(_GP))
+
+#print dir( LoKi.Dicts.TreeOps(_GP) )
+
+## decay trees
+iGTree = Decays.iTree_(_GP)
+GTree = Decays.Tree_(_GP)
+GAny = Decays.Trees.Any_(_GP)()  ## instance!!!
+GNone = Decays.Trees.None_(_GP)()  ## instance!!!
+GStable = Decays.Trees.Stable_(_GP)
+GenExclusive = Decays.Trees.GenExclusive
+GenInclusive = Decays.Trees.GenInclusive
+GenOptional = Decays.Trees.GenOptional
+GenPhotos = Decays.Trees.GenPhotos
+GenPhotosOptional = Decays.Trees.GenPhotosOptional
+
+IGenDecay = Decays.IGenDecay
+GenFinder = _LoKiCore.decorateFinder(IGenDecay.Finder,
+                                     LoKi.Dicts.FinderDicts_(_GP))
+
+# =============================================================================
+#if '__main__' == __name__ :
+#    for o in dir() : print o
+
+# =============================================================================
+# The END
+# =============================================================================
diff --git a/Gen/LoKiGen/src/Components/DumpHepMC.cpp b/Gen/LoKiGen/src/Components/DumpHepMC.cpp
new file mode 100644
index 000000000..3d41ab8c0
--- /dev/null
+++ b/Gen/LoKiGen/src/Components/DumpHepMC.cpp
@@ -0,0 +1,145 @@
+/*****************************************************************************\
+* (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration      *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                             *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+// ============================================================================
+// Include files
+// ============================================================================
+// GaudiKernel
+// ============================================================================
+#include "GaudiKernel/IService.h"
+// ============================================================================
+// GaudiAlg
+// ============================================================================
+#include "GaudiAlg/GaudiAlgorithm.h"
+#include "GaudiKernel/AnyDataHandle.h"
+// ============================================================================
+// LoKi
+// ============================================================================
+#include "LoKi/GenDecayChain.h"
+#include "LoKi/Objects.h"
+
+#include "Defaults/Locations.h"
+// ============================================================================
+namespace LoKi {
+  // ==========================================================================
+  /** @class DumpHepMC3
+   *  Simple class to dump HepMC3-infomration
+   *  @author Vanya BELYAEV Ivan.Belyaev@nikhef.nl
+   *  @date 2008-05-04
+   */
+  class DumpHepMC3 : public GaudiAlgorithm {
+  public:
+    // ========================================================================
+    /// standard initialization of the algorithm
+    StatusCode initialize() override {
+      StatusCode sc = GaudiAlgorithm::initialize();
+      if ( sc.isFailure() ) { return sc; }
+      /// get LoKi service
+      svc<IService>( "LoKiSvc", true );
+      return StatusCode::SUCCESS;
+    }
+    /// the only one essential method : execution of the algorithm
+    StatusCode execute() override;
+    /** The standard constructor
+     *  @param name algorithm instance name
+     *  @param svc  Service Locator
+     */
+    DumpHepMC3( const std::string& name, // algorithm instance name
+               ISvcLocator*       svc )       // service locator
+        : GaudiAlgorithm( name, svc )
+        , m_depth( 10 )                                // the maximal printout depth
+        , m_vertex( true )                             // print vertex information
+        , m_vertexe( true )                            // print end-vertex information?
+        , m_mode( LoKi::DecayChainBase::LV_WITHPT )    // printout mode
+    {
+      declareProperty( "Depth", m_depth, "The maximal printout depth" );
+      declareProperty( "PrintVertex", m_vertex, "Print vertex information?" );
+      declareProperty( "PrintEndVertex", m_vertexe, "Print end-vertex information?" );
+      declareProperty( "Mode", m_mode, "Printout mode, see LoKi::DecayChainBase::Mode" );
+    }
+    // ========================================================================
+  private:
+    // ========================================================================
+    /// the maximal printout dephth
+    unsigned short m_depth; // the maximal printout dephth
+    /// print vertex information ?
+    bool m_vertex; // print vertex information ?
+    /// print end-vertex information ?
+    bool m_vertexe; // print end-vertex information ?
+    /// printout mode  ( @see LoKi::DecayChainBase::Mode )
+    unsigned short m_mode; // printout mode
+    // ========================================================================
+    mutable AnyDataHandle<std::vector<HepMC3::GenEvent>> m_handle{this, Gaudi::DataHandle::Writer, "Location", Gaussino::HepMCEventLocation::Default};
+  };
+  // ==========================================================================
+} // end of namespace LoKi
+// ============================================================================
+// the only one essential method : execution of the algorithm
+StatusCode LoKi::DumpHepMC3::execute() {
+  // get HepMC3 data:
+  auto events = m_handle.get();
+
+  LoKi::DecayChainBase::Mode mode = LoKi::DecayChainBase::LV_WITHPT;
+  switch ( m_mode ) {
+  case LoKi::DecayChainBase::LV_STD:
+    mode = LoKi::DecayChainBase::LV_STD;
+    break;
+  case LoKi::DecayChainBase::LV_MASS:
+    mode = LoKi::DecayChainBase::LV_MASS;
+    break;
+  case LoKi::DecayChainBase::LV_WITHPT:
+    mode = LoKi::DecayChainBase::LV_WITHPT;
+    break;
+  case LoKi::DecayChainBase::LV_ONLYP:
+    mode = LoKi::DecayChainBase::LV_ONLYP;
+    break;
+  case LoKi::DecayChainBase::LV_SHORT:
+    mode = LoKi::DecayChainBase::LV_SHORT;
+    break;
+  case LoKi::DecayChainBase::LV_MPTYPHI:
+    mode = LoKi::DecayChainBase::LV_MPTYPHI;
+    break;
+  case LoKi::DecayChainBase::LV_MPTETAPHI:
+    mode = LoKi::DecayChainBase::LV_MPTETAPHI;
+    break;
+  case LoKi::DecayChainBase::LV_MPTY:
+    mode = LoKi::DecayChainBase::LV_MPTY;
+    break;
+  case LoKi::DecayChainBase::LV_MPTETA:
+    mode = LoKi::DecayChainBase::LV_MPTETA;
+    break;
+  default:
+    mode = LoKi::DecayChainBase::LV_WITHPT;
+    break;
+  }
+
+  // get the smart printer
+  LoKi::GenDecayChain printer( m_depth, m_vertex, mode, MSG::YELLOW, MSG::RED, m_vertexe );
+
+  MsgStream& log = always();
+  //
+  for(auto & evt: *events){
+  printer.print( &evt,                  // input data
+                 log.stream(),            // the stream
+                 '\n',                    // the terminator
+                 LoKi::Objects::_ALL_,    // accept
+                 LoKi::Objects::_NONE_ ); // mark
+  }
+  //
+  log << endmsg;
+  //
+  return StatusCode::SUCCESS;
+}
+// ============================================================================
+/// Declaration of the Algorithm Factory
+DECLARE_COMPONENT( LoKi::DumpHepMC3 )
+// ============================================================================
+// The END
+// ============================================================================
diff --git a/Gen/LoKiGen/src/Components/GenDecay.cpp b/Gen/LoKiGen/src/Components/GenDecay.cpp
new file mode 100644
index 000000000..490db2fa6
--- /dev/null
+++ b/Gen/LoKiGen/src/Components/GenDecay.cpp
@@ -0,0 +1,127 @@
+/*****************************************************************************\
+* (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration      *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                             *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+// ============================================================================
+// Include
+// ============================================================================
+// HepMC3
+// ============================================================================
+#ifdef __INTEL_COMPILER
+#  pragma warning( disable : 1572 ) // floating-point equality and inequality comparisons are unreliable
+#  pragma warning( push )
+#endif
+#include "HepMC3/GenParticle.h"
+#ifdef __INTEL_COMPILER
+#  pragma warning( pop )
+#endif
+// ============================================================================
+// LoKi
+// ============================================================================
+#include "LoKi/DecayBase.h"
+#include "LoKi/GenTreesFactory.h"
+#include "LoKi/IGenDecay.h"
+#include "LoKi/TreeHelpers.h"
+#include "LoKi/Trees.h"
+// ============================================================================
+namespace LoKi {
+  // ==========================================================================
+  /** @class GenDecay
+   *  simple implementation of interface Decays::IGenDecay
+   *  @author Vanya BELYAEV Ivan.Belyaev@nikhef.nl
+   *  @date 2009-05-27
+   */
+  class GenDecay : public LoKi::DecayBase, public virtual Decays::IGenDecay {
+    // ========================================================================
+    typedef Decays::Trees::Types_<HepMC3::ConstGenParticlePtr>::Invalid Invalid;
+    // ========================================================================
+  public:
+    // ========================================================================
+    /** create the decay tree from the descriptor
+     *  @param descriptor (INPUT)  the decay descriptor
+     *  @param tree       (OUTPUT) the decay tree
+     */
+    Tree tree( const std::string& decay ) const override;
+    // ========================================================================
+  public:
+    // ========================================================================
+    /// build the node form the node descriptor
+    Decays::Node node( const std::string& descriptor ) const override { return LoKi::DecayBase::node( descriptor ); }
+    // ========================================================================
+    /** constructor form the type, name and parent
+     *  @param type the tool type (?)
+     *  @param name the instance name
+     *  @param parent the parent
+     */
+    GenDecay( const std::string& type,   //     the tool type
+              const std::string& name,   // the instance name
+              const IInterface*  parent ) //        the parent
+        : LoKi::DecayBase( type, name, parent ), m_tree( Invalid() ) {
+      declareInterface<Decays::IGenDecay>( this );
+      declareInterface<Decays::IDecayNode>( this );
+    }
+    // ========================================================================
+  private:
+    // ========================================================================
+    /// the default tree
+    mutable Tree m_tree; // the default tree
+    // ========================================================================
+  }; //                                                  end of class GenDecay
+  // ==========================================================================
+} //                                                      end of namespace LoKi
+// ============================================================================
+// create the decay tree from the descriptor
+// ============================================================================
+Decays::IGenDecay::Tree LoKi::GenDecay::tree( const std::string& decay ) const {
+  // check for the default tree
+  if ( decay.empty() && m_tree.valid() ) { return m_tree; } // default tree?
+
+  MsgStream& err = error();
+
+  // 1) parse the the descriptor into "generic tree"
+  Decays::Parsers::Tree ptree;
+  StatusCode            sc = _parse( ptree, decay );
+  if ( sc.isFailure() ) {
+    Error( "Error from _parse('" + decay + "')", sc );
+    return Invalid(); // RETURN
+  }
+  // 2) convert parsed tree into reasonable decay tree
+  Tree tree = Invalid();
+  sc        = Decays::Trees::factory( tree, ptree, err.stream() );
+  if ( sc.isFailure() ) {
+    err << endmsg;
+    Error( "Unable to create the tree from '" + ptree.toString() + "'", sc );
+    return Invalid(); // RETURN
+  }
+  // 3) validate the tree
+  if ( !tree ) {
+    sc = tree.validate( ppSvc() );
+    if ( sc.isFailure() ) {
+      Error( "Unable to validate the tree '" + tree.toString() + "'", sc );
+      return Invalid(); // RETURN
+    }
+  }
+
+  // 4) store the default tree
+  if ( decay.empty() ) { m_tree = tree; } // store the default tree
+
+  // 5) finally:
+  return tree;
+}
+// ============================================================================
+
+// ============================================================================
+//                                                the factory for instantiation
+// ============================================================================
+DECLARE_COMPONENT( LoKi::GenDecay )
+// ============================================================================
+
+// ============================================================================
+// The END
+// ============================================================================
diff --git a/Gen/LoKiGen/src/Components/GenFilter.cpp b/Gen/LoKiGen/src/Components/GenFilter.cpp
new file mode 100644
index 000000000..9ce90b893
--- /dev/null
+++ b/Gen/LoKiGen/src/Components/GenFilter.cpp
@@ -0,0 +1,167 @@
+/*****************************************************************************\
+* (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration      *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                             *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+// ============================================================================
+// Include files
+// ============================================================================
+#include <vector>
+#include "HepMC3/GenEvent.h"
+#include "HepMC3/GenParticle.h"
+#include "HepMC3/GenVertex.h"
+// ============================================================================
+// LoKi
+// ============================================================================
+#include "LoKi/FilterAlg.h"
+#include "LoKi/GenTypes.h"
+#include "LoKi/IGenHybridFactory.h"
+#include "Defaults/Locations.h"
+#include "GaudiKernel/AnyDataHandle.h"
+// ============================================================================
+/** @file
+ *
+ *  This file is a part of LoKi project -
+ *    "C++ ToolKit  for Smart and Friendly Physics Analysis"
+ *
+ *  The package has been designed with the kind help from
+ *  Galina PAKHLOVA and Sergey BARSUK.  Many bright ideas,
+ *  contributions and advices from G.Raven, J.van Tilburg,
+ *  A.Golutvin, P.Koppenburg have been used in the design.
+ *
+ */
+// ============================================================================
+namespace LoKi {
+  // ==========================================================================
+  /** @class ODINFilter
+   *  Simple filtering algorithm bases on LoKi/Bender "hybrid" framework
+   *  for filtering according to Generator (HepMC3) information
+   *  @author Vanya BELYAEV Ivan.Belyaev@cern.ch
+   *  @date 2011-06-02
+   */
+  class GenFilter : public LoKi::FilterAlg {
+  public:
+    // ========================================================================
+    /// the main method: execute
+    StatusCode execute() override;
+    StatusCode finalize() override;
+    // ========================================================================
+  public:
+    // ========================================================================
+    /** Decode the functor (use the factory)
+     *  @see LoKi::FilterAlg
+     *  @see LoKi::FilterAlg::decode
+     *  @see LoKi::FilterAlg::i_decode
+     */
+    StatusCode decode() override {
+      StatusCode sc = i_decode<LoKi::IGenHybridFactory>( m_cut );
+      Assert( sc.isSuccess(), "Unable to decode the functor!" );
+      return StatusCode::SUCCESS;
+    }
+    // ========================================================================
+    /** standard constructor
+     *  @see LoKi::FilterAlg
+     *  @see GaudiAlgorithm
+     *  @see      Algorithm
+     *  @see      AlgFactory
+     *  @see     IAlgFactory
+     *  @param name the algorithm instance name
+     *  @param pSvc pointer to Service Locator
+     */
+    GenFilter( const std::string& name, // the algorithm instance name
+               ISvcLocator*       pSvc );     // pointer to the service locator
+    // ========================================================================
+  private:
+    // ========================================================================
+    /// the functor itself
+    LoKi::Types::GCutVal m_cut; // the functor itself
+    /// TES location of LHCb::HepMC3Event::Container object
+    mutable AnyDataHandle<std::vector<HepMC3::GenEvent>> m_handle{this, Gaudi::DataHandle::Writer, "Location", Gaussino::HepMCEventLocation::Default};
+    // ========================================================================
+  };
+  // ==========================================================================
+} //                                                      end of namespace LoKi
+// ============================================================================
+namespace {
+  // ==========================================================================
+  LoKi::BasicFunctors<LoKi::GenTypes::GenContainer>::BooleanConstant s_NONE{false};
+  // ==========================================================================
+} // namespace
+// ============================================================================
+/* standard constructor
+ *  @see LoKi::FilterAlg
+ *  @see GaudiAlgorithm
+ *  @see      Algorithm
+ *  @see      AlgFactory
+ *  @see     IAlgFactory
+ *  @param name the algorithm instance name
+ *  @param pSvc pointer to Service Locator
+ */
+// ===========================================================================
+LoKi::GenFilter::GenFilter( const std::string& name, // the algorithm instance name
+                            ISvcLocator*       pSvc )      // pointer to the service locator
+    : LoKi::FilterAlg( name, pSvc )
+    // the functor itself
+    , m_cut( s_NONE ){
+  //
+  //
+  StatusCode sc = setProperty( "Code", "~GEMPTY" );
+  Assert( sc.isSuccess(), "Unable (re)set property 'Code'", sc );
+  sc = setProperty( "Factory", "LoKi::Hybrid::GenTool/GenFactory:PUBLIC" );
+  Assert( sc.isSuccess(), "Unable (re)set property 'Factory'", sc );
+}
+// ============================================================================
+// finalize
+// ============================================================================
+StatusCode LoKi::GenFilter::finalize() {
+  m_cut = s_NONE;
+  return LoKi::FilterAlg::finalize();
+}
+// ============================================================================
+// the main method: execute
+// ============================================================================
+StatusCode LoKi::GenFilter::execute() // the main method: execute
+{
+  if ( updateRequired() ) {
+    StatusCode sc = decode();
+    Assert( sc.isSuccess(), "Unable to decode the functor!" );
+  }
+  //
+  // get HepMC3 information from TES
+  //
+  auto events = m_handle.get();
+  if ( 0 == events ) { return StatusCode::FAILURE; }
+  //
+  // copy all particles into single vector
+  //
+  LoKi::GenTypes::GenContainer particles;
+  for ( auto & evt: *events ) {
+    //
+    particles.insert( particles.end(), std::begin(evt.particles()), std::end(evt.particles()) );
+  }
+  //
+  // use the functor
+  //
+  const bool result = m_cut( particles );
+  //
+  // some statistics
+  //
+  counter( "#passed" ) += result;
+  //
+  // set the filter:
+  //
+  setFilterPassed( result );
+  //
+  return StatusCode::SUCCESS;
+}
+// ============================================================================
+/// the factory (needed for instantiation)
+DECLARE_COMPONENT( LoKi::GenFilter )
+// ============================================================================
+// The END
+// ============================================================================
diff --git a/Gen/LoKiGen/src/Components/GenHybridTool.cpp b/Gen/LoKiGen/src/Components/GenHybridTool.cpp
new file mode 100644
index 000000000..f98f37930
--- /dev/null
+++ b/Gen/LoKiGen/src/Components/GenHybridTool.cpp
@@ -0,0 +1,405 @@
+/*****************************************************************************\
+* (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration      *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                             *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+// ============================================================================
+// Include files
+// ============================================================================
+// STD&STL
+// ============================================================================
+#include <mutex>
+// ============================================================================
+// GaudiKernel
+// ============================================================================
+#include "GaudiKernel/System.h"
+// ============================================================================
+// LoKi
+// ============================================================================
+#include "LoKi/GenHybridLock.h"
+#include "LoKi/HybridBase.h"
+#include "LoKi/IGenHybridFactory.h"
+#include "LoKi/IGenHybridTool.h"
+// ============================================================================
+// Local
+// ============================================================================
+/** @file
+ *  definitione and the implementation file for class LoKi::Hybrid::GenTool
+ *
+ *  This file is a part of LoKi project -
+ *    "C++ ToolKit  for Smart and Friendly Physics Analysis"
+ *
+ *  The package has been designed with the kind help from
+ *  Galina PAKHLOVA and Sergey BARSUK.  Many bright ideas,
+ *  contributions and advices from G.Raven, J.van Tilburg,
+ *  A.Golutvin, P.Koppenburg have been used in the design.
+ *
+ *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+ *  @date 2004-06-29
+ */
+namespace LoKi {
+  // ==========================================================================
+  namespace Hybrid {
+    // ========================================================================
+    /** @class GenTool
+     *
+     *  Concrete impelmentation of LoKi::IGenHybridTool interface
+     *  This file is a part of LoKi project -
+     *    "C++ ToolKit  for Smart and Friendly Physics Analysis"
+     *
+     *  The package has been designed with the kind help from
+     *  Galina PAKHLOVA and Sergey BARSUK.  Many bright ideas,
+     *  contributions and advices from G.Raven, J.van Tilburg,
+     *  A.Golutvin, P.Koppenburg have been used in the design.
+     *
+     *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+     *  @date   2004-06-29
+     */
+    class GenTool : public LoKi::Hybrid::Base, public virtual IGenHybridTool, public virtual IGenHybridFactory {
+    public:
+      // ======================================================================
+      /// initialization of the tool
+      StatusCode initialize() override;
+      /// finalization   of the tool
+      StatusCode finalize() override;
+      // ======================================================================
+    public:
+      // ======================================================================
+      // predicates
+      // ======================================================================
+      /** "Factory": get the the object form python code
+       *  @param pycode the python pseudo-code of the function
+       *  @param cuts the placeholder for the result
+       *  @return StatusCode
+       */
+      StatusCode get( const std::string& pycode, LoKi::Types::GCut& cuts, const std::string& context ) override {
+        return _get( pycode, m_gcuts, cuts, context );
+      }
+      // ======================================================================
+      /** "Factory": get the the object form python code
+       *  @param pycode the python pseudo-code of the function
+       *  @param cuts the placeholder for the result
+       *  @return StatusCode
+       */
+      StatusCode get( const std::string& pycode, LoKi::Types::GVCut& cuts, const std::string& context ) override {
+        return _get( pycode, m_gvcuts, cuts, context );
+      }
+      // ======================================================================
+    public:
+      // ======================================================================
+      // functions
+      // ======================================================================
+      /** "Factory": get the the object form python code
+       *  @param pycode the python pseudo-code of the function
+       *  @param func the placeholder for the result
+       *  @return StatusCode
+       */
+      StatusCode get( const std::string& pycode, LoKi::Types::GFun& func, const std::string& context ) override {
+        return _get( pycode, m_gfunc, func, context );
+      }
+      // ======================================================================
+      /** "Factory": get the the object form python code
+       *  @param pycode the python pseudo-code of the function
+       *  @param func the placeholder for the result
+       *  @return StatusCode
+       */
+      StatusCode get( const std::string& pycode, LoKi::Types::GVFun& func, const std::string& context ) override {
+        return _get( pycode, m_gvfunc, func, context );
+      }
+      // ======================================================================
+    public:
+      // ======================================================================
+      // maps
+      // ======================================================================
+      /** "Factory": get the the object form python code
+       *  @param pycode the python pseudo-code of the function
+       *  @param func the placeholder for the result
+       *  @return StatusCode
+       */
+      StatusCode get( const std::string& pycode, LoKi::Types::GMap& func, const std::string& context ) override {
+        return _get( pycode, m_gmap, func, context );
+      }
+      // ======================================================================
+      /** "Factory": get the the object form python code
+       *  @param pycode the python pseudo-code of the function
+       *  @param func the placeholder for the result
+       *  @return StatusCode
+       */
+      StatusCode get( const std::string& pycode, LoKi::Types::GVMap& func, const std::string& context ) override {
+        return _get( pycode, m_gvmap, func, context );
+      }
+      // ======================================================================
+    public:
+      // ======================================================================
+      // pipes
+      // ======================================================================
+      /** "Factory": get the the object form python code
+       *  @param pycode the python pseudo-code of the function
+       *  @param func the placeholder for the result
+       *  @return StatusCode
+       */
+      StatusCode get( const std::string& pycode, LoKi::Types::GPipe& func, const std::string& context ) override {
+        return _get( pycode, m_gpipe, func, context );
+      }
+      // ======================================================================
+      /** "Factory": get the the object form python code
+       *  @param pycode the python pseudo-code of the function
+       *  @param func the placeholder for the result
+       *  @return StatusCode
+       */
+      StatusCode get( const std::string& pycode, LoKi::Types::GVPipe& func, const std::string& context ) override {
+        return _get( pycode, m_gvpipe, func, context );
+      }
+      // ======================================================================
+    public:
+      // ======================================================================
+      // fun-vals
+      // ======================================================================
+      /** "Factory": get the the object form python code
+       *  @param pycode the python pseudo-code of the function
+       *  @param func the placeholder for the result
+       *  @return StatusCode
+       */
+      StatusCode get( const std::string& pycode, LoKi::Types::GFunVal& func, const std::string& context ) override {
+        return _get( pycode, m_gfunval, func, context );
+      }
+      // ======================================================================
+      /** "Factory": get the the object form python code
+       *  @param pycode the python pseudo-code of the function
+       *  @param func the placeholder for the result
+       *  @return StatusCode
+       */
+      StatusCode get( const std::string& pycode, LoKi::Types::GVFunVal& func, const std::string& context ) override {
+        return _get( pycode, m_gvfunval, func, context );
+      }
+      // ======================================================================
+    public:
+      // ======================================================================
+      // cut-vals
+      // ======================================================================
+      /** "Factory": get the the object form python code
+       *  @param pycode the python pseudo-code of the function
+       *  @param func the placeholder for the result
+       *  @return StatusCode
+       */
+      StatusCode get( const std::string& pycode, LoKi::Types::GCutVal& func, const std::string& context ) override {
+        return _get( pycode, m_gcutval, func, context );
+      }
+      // ======================================================================
+    public:
+      // ======================================================================
+      // sources
+      // ======================================================================
+      /** "Factory": get the the object form python code
+       *  @param pycode the python pseudo-code of the function
+       *  @param func the placeholder for the result
+       *  @return StatusCode
+       */
+      StatusCode get( const std::string& pycode, LoKi::Types::GSource& func, const std::string& context ) override {
+        return _get( pycode, m_gsource, func, context );
+      }
+      // ======================================================================
+      /** "Factory": get the the object form python code
+       *  @param pycode the python pseudo-code of the function
+       *  @param func the placeholder for the result
+       *  @return StatusCode
+       */
+      StatusCode get( const std::string& pycode, LoKi::Types::GVSource& func, const std::string& context ) override {
+        return _get( pycode, m_gvsource, func, context );
+      }
+      // ======================================================================
+    public:
+      // ======================================================================
+      // predicates
+      // ======================================================================
+      /// set the C++ predicate for HepMC3::GenParticle
+      void set( const LoKi::Types::GCuts& cut ) override { LoKi::Hybrid::Base::_set( m_gcuts, cut ); }
+      /// set the C++ predicate for HepMC3::GenVertex
+      void set( const LoKi::Types::GVCuts& cut ) override { LoKi::Hybrid::Base::_set( m_gvcuts, cut ); }
+      // ======================================================================
+    public:
+      // ======================================================================
+      // functions
+      // ======================================================================
+      /// set the C++ function for HepMC3::GenParticle
+      void set( const LoKi::Types::GFunc& cut ) override { LoKi::Hybrid::Base::_set( m_gfunc, cut ); }
+      /// set the C++ function for HepMC3::GenVertex
+      void set( const LoKi::Types::GVFunc& cut ) override { LoKi::Hybrid::Base::_set( m_gvfunc, cut ); }
+      // ======================================================================
+    public:
+      // ======================================================================
+      // maps
+      // ======================================================================
+      /// set the C++ "map" for HepMC3::GenParticle
+      void set( const LoKi::Types::GMaps& cut ) override { LoKi::Hybrid::Base::_set( m_gmap, cut ); }
+      /// set the C++ "map" for HepMC3::GenVertex
+      void set( const LoKi::Types::GVMaps& cut ) override { LoKi::Hybrid::Base::_set( m_gvmap, cut ); }
+      // ======================================================================
+    public:
+      // ======================================================================
+      // pipes
+      // ======================================================================
+      /// set the C++ "pipe" for HepMC3::GenParticle
+      void set( const LoKi::Types::GPipes& cut ) override { LoKi::Hybrid::Base::_set( m_gpipe, cut ); }
+      /// set the C++ "pipe" for HepMC3::GenVertex
+      void set( const LoKi::Types::GVPipes& cut ) override { LoKi::Hybrid::Base::_set( m_gvpipe, cut ); }
+      // ======================================================================
+    public:
+      // ======================================================================
+      // funvals
+      // ======================================================================
+      /// set the C++ "fun-val" for HepMC3::GenParticle
+      void set( const LoKi::Types::GFunVals& cut ) override { LoKi::Hybrid::Base::_set( m_gfunval, cut ); }
+      /// set the C++ "pipe" for HepMC3::GenVertex
+      void set( const LoKi::Types::GVFunVals& cut ) override { LoKi::Hybrid::Base::_set( m_gvfunval, cut ); }
+      // ======================================================================
+    public:
+      // ======================================================================
+      // cutvals
+      // ======================================================================
+      /// set the C++ "cut-val" for HepMC3::GenParticle
+      void set( const LoKi::Types::GCutVals& cut ) override { LoKi::Hybrid::Base::_set( m_gcutval, cut ); }
+      // ======================================================================
+    public:
+      // ======================================================================
+      // sources
+      // ======================================================================
+      /// set the C++ "source" for HepMC3::GenParticle
+      void set( const LoKi::Types::GSources& cut ) override { LoKi::Hybrid::Base::_set( m_gsource, cut ); }
+      /// set the C++ "source" for HepMC3::GenVertex
+      void set( const LoKi::Types::GVSources& cut ) override { LoKi::Hybrid::Base::_set( m_gvsource, cut ); }
+      // ======================================================================
+      /// constrcutor
+      GenTool( const std::string& type, const std::string& name, const IInterface* parent );
+      // ======================================================================
+    private:
+      // ======================================================================
+      /// helper method to save many lines:
+      template <class TYPE1, class TYPE2>
+      inline StatusCode _get( const std::string& pycode, std::unique_ptr<LoKi::Functor<TYPE1, TYPE2>>& local,
+                              LoKi::Assignable_t<LoKi::Functor<TYPE1, TYPE2>>& output, const std::string& context );
+      // ======================================================================
+    protected:
+      // ======================================================================
+      //
+      //   local holders of cuts
+      //
+      // predicates:
+      std::unique_ptr<LoKi::Types::GCuts>  m_gcuts;
+      std::unique_ptr<LoKi::Types::GVCuts> m_gvcuts;
+      // functions:
+      std::unique_ptr<LoKi::Types::GFunc>  m_gfunc;
+      std::unique_ptr<LoKi::Types::GVFunc> m_gvfunc;
+      // maps:
+      std::unique_ptr<LoKi::Types::GMaps>  m_gmap;
+      std::unique_ptr<LoKi::Types::GVMaps> m_gvmap;
+      // pipes:
+      std::unique_ptr<LoKi::Types::GPipes>  m_gpipe;
+      std::unique_ptr<LoKi::Types::GVPipes> m_gvpipe;
+      // fun-vals:
+      std::unique_ptr<LoKi::Types::GFunVals>  m_gfunval;
+      std::unique_ptr<LoKi::Types::GVFunVals> m_gvfunval;
+      // cut-vals:
+      std::unique_ptr<LoKi::Types::GCutVals> m_gcutval;
+      // sources:
+      std::unique_ptr<LoKi::Types::GSources>  m_gsource;
+      std::unique_ptr<LoKi::Types::GVSources> m_gvsource;
+      //
+      typedef std::vector<std::string> Modules;
+      Modules                          m_modules;
+      std::string                      m_actor;
+      typedef std::vector<std::string> Lines;
+      Lines                            m_lines;
+      // ======================================================================
+    };
+    // ========================================================================
+  } // namespace Hybrid
+  // ==========================================================================
+} //                                                      end of namespace LoKi
+// ============================================================================
+// helper method to sdave many lines:
+// ============================================================================
+template <class TYPE1, class TYPE2>
+inline StatusCode
+LoKi::Hybrid::GenTool::_get( const std::string& pycode, std::unique_ptr<LoKi::Functor<TYPE1, TYPE2>>& local,
+                             LoKi::Assignable_t<LoKi::Functor<TYPE1, TYPE2>>& output, const std::string& context ) {
+  std::lock_guard guard( m_mutex );
+  // prepare the actual python code
+  std::string code = makeCode( m_modules, m_actor, pycode, m_lines, context );
+  /// define and lock the scope:
+  LoKi::Hybrid::GenLock lock( this, make_context() );
+  // use the base class method
+  StatusCode sc = LoKi::Hybrid::Base::_get_( code, local, output );
+  if ( sc.isFailure() ) {
+    return Error( "Invalid object for the code '" + pycode +
+                  "' (hash: " + std::to_string( LoKi::Cache::makeHash( code ) ) + ")" );
+  } // RETURN
+  //
+  return StatusCode::SUCCESS;
+}
+// ============================================================================
+DECLARE_COMPONENT( LoKi::Hybrid::GenTool )
+// ============================================================================
+// Standard constructor
+// ============================================================================
+LoKi::Hybrid::GenTool::GenTool( const std::string& type, const std::string& name, const IInterface* parent )
+    : LoKi::Hybrid::Base( type, name, parent ), m_actor( "LoKi.Hybrid.GenEngine()" ) {
+  //
+  declareInterface<LoKi::IGenHybridTool>( this );
+  declareInterface<LoKi::IGenHybridFactory>( this );
+  //
+  m_modules.push_back( "LoKiGen.decorators" );
+  // m_modules.push_back ( "LoKiGenMC.decorators" ) ;
+  m_modules.push_back( "LoKiCore.functions" );
+  //
+  declareProperty( "Modules", m_modules, "Python modules to be imported" );
+  declareProperty( "Actor", m_actor, "The processing engine" );
+  declareProperty( "Lines", m_lines, "Additional Python lines to be executed" );
+}
+// ============================================================================
+// initialization of the tool
+// ============================================================================
+StatusCode LoKi::Hybrid::GenTool::initialize() {
+  StatusCode sc = LoKi::Hybrid::Base::initialize();
+  if ( sc.isFailure() ) { return sc; }
+  if ( msgLevel( MSG::DEBUG ) ) { m_lines.insert( m_lines.begin(), "dir()" ); }
+  return StatusCode::SUCCESS;
+}
+// ============================================================================
+// finalization of the tool
+// ============================================================================
+StatusCode LoKi::Hybrid::GenTool::finalize() {
+  // predicates:
+  m_gcuts.reset();
+  m_gvcuts.reset();
+  // functions:
+  m_gfunc.reset();
+  m_gvfunc.reset();
+  // maps:
+  m_gmap.reset();
+  m_gvmap.reset();
+  // pipes:
+  m_gpipe.reset();
+  m_gvpipe.reset();
+  // funvals:
+  m_gfunval.reset();
+  m_gvfunval.reset();
+  // cutvals:
+  m_gcutval.reset();
+  // sources:
+  m_gsource.reset();
+  m_gvsource.reset();
+  //
+  // finalize the base
+  return LoKi::Hybrid::Base::finalize();
+}
+// ============================================================================
+
+// ============================================================================
+// The END
+// ============================================================================
diff --git a/Gen/LoKiGen/src/GenAlgsDicts.cpp b/Gen/LoKiGen/src/GenAlgsDicts.cpp
new file mode 100644
index 000000000..eab3c84dd
--- /dev/null
+++ b/Gen/LoKiGen/src/GenAlgsDicts.cpp
@@ -0,0 +1,181 @@
+/*****************************************************************************\
+* (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration      *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                             *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+// ============================================================================
+// Include files
+// ============================================================================
+// LoKi
+// ============================================================================
+#include "LoKi/GenAlgs.h"
+#include "LoKi/GenAlgsDicts.h"
+#include "LoKi/GenTypes.h"
+// ============================================================================
+/** @file
+ *  Implementation file for namespace LoKi::Dicts::GenAlgs
+ *  @date 2007-06-03
+ *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+ */
+// ============================================================================
+// count the particles in the event
+// ============================================================================
+std::size_t LoKi::Dicts::GenAlgs::count_if( const HepMC3::GenEvent* event, const LoKi::GenTypes::GCuts& cuts ) {
+  return LoKi::GenAlgs::count_if( event, cuts );
+}
+// ============================================================================
+// count the particles in the tree
+// ============================================================================
+std::size_t LoKi::Dicts::GenAlgs::count_if( const HepMC3::ConstGenParticlePtr & particle, const LoKi::GenTypes::GCuts& cuts ) {
+  return LoKi::GenAlgs::count_if( particle, cuts );
+}
+// ============================================================================
+// count the particles in the tree
+// ============================================================================
+std::size_t LoKi::Dicts::GenAlgs::count_if( const HepMC3::ConstGenVertexPtr & vertex, const LoKi::GenTypes::GCuts& cuts,
+                                            const HepMC3::Relatives & range ) {
+  return LoKi::GenAlgs::count_if( vertex, cuts, range );
+}
+// ============================================================================
+//  check the presence in the event
+// ============================================================================
+bool LoKi::Dicts::GenAlgs::found( const HepMC3::GenEvent* event, const LoKi::GenTypes::GCuts& cuts ) {
+  return LoKi::GenAlgs::found( event, cuts );
+}
+// ============================================================================
+//  check the presence in the tree
+// ============================================================================
+bool LoKi::Dicts::GenAlgs::found( const HepMC3::ConstGenParticlePtr & particle, const LoKi::GenTypes::GCuts& cuts ) {
+  return LoKi::GenAlgs::found( particle, cuts );
+}
+// ============================================================================
+//  check the presence in the tree
+// ============================================================================
+bool LoKi::Dicts::GenAlgs::found( const HepMC3::ConstGenVertexPtr & vertex, const LoKi::GenTypes::GCuts& cuts,
+                                  const HepMC3::Relatives & range ) {
+  return LoKi::GenAlgs::found( vertex, cuts, range );
+}
+// ============================================================================
+// accumulate through the addition
+// ============================================================================
+double LoKi::Dicts::GenAlgs::accumulate( const HepMC3::GenEvent* event, const LoKi::GenTypes::GFunc& fun,
+                                         const LoKi::GenTypes::GCuts& cut, double res ) {
+  return LoKi::GenAlgs::accumulate( event, fun, cut, res, std::plus<>() );
+}
+// ============================================================================
+// accumulate through the addition
+// ============================================================================
+double LoKi::Dicts::GenAlgs::accumulate( const HepMC3::ConstGenVertexPtr & vertex, const LoKi::GenTypes::GFunc& fun,
+                                         const LoKi::GenTypes::GCuts& cut, const HepMC3::Relatives & range, double res ) {
+  return LoKi::GenAlgs::accumulate( vertex, fun, cut, res, range, std::plus<>() );
+}
+// ============================================================================
+// accumulate through the addition
+// ============================================================================
+double LoKi::Dicts::GenAlgs::accumulate( const HepMC3::ConstGenParticlePtr & particle, const LoKi::GenTypes::GFunc& fun,
+                                         const LoKi::GenTypes::GCuts& cut, const double res ) {
+  return LoKi::GenAlgs::accumulate( particle, fun, cut, res, std::plus<>() );
+}
+// ============================================================================
+// find minimal value over the event
+// ============================================================================
+double LoKi::Dicts::GenAlgs::min_value( const HepMC3::GenEvent* event, const LoKi::GenTypes::GFunc& fun,
+                                        const LoKi::GenTypes::GCuts& cut, double res ) {
+  return LoKi::GenAlgs::min_value( event, fun, cut, res );
+}
+// ============================================================================
+// find minimal value over the tree:
+// ============================================================================
+double LoKi::Dicts::GenAlgs::min_value( const HepMC3::ConstGenVertexPtr & vertex, const LoKi::GenTypes::GFunc& fun,
+                                        const LoKi::GenTypes::GCuts& cut, const HepMC3::Relatives & range, double res ) {
+  return LoKi::GenAlgs::min_value( vertex, fun, cut, range, res );
+}
+// ============================================================================
+// find minimal value over the tree:
+// ============================================================================
+double LoKi::Dicts::GenAlgs::min_value( const HepMC3::ConstGenParticlePtr & particle, const LoKi::GenTypes::GFunc& fun,
+                                        const LoKi::GenTypes::GCuts& cut, double res ) {
+  return LoKi::GenAlgs::min_value( particle, fun, cut, res );
+}
+// ============================================================================
+// find the maximal value over the event
+// ============================================================================
+double LoKi::Dicts::GenAlgs::max_value( const HepMC3::GenEvent* event, const LoKi::GenTypes::GFunc& fun,
+                                        const LoKi::GenTypes::GCuts& cut, double res ) {
+  return LoKi::GenAlgs::max_value( event, fun, cut, res );
+}
+// ============================================================================
+// find the maximal value over the tree
+// ============================================================================
+double LoKi::Dicts::GenAlgs::max_value( const HepMC3::ConstGenParticlePtr & particle, const LoKi::GenTypes::GFunc& fun,
+                                        const LoKi::GenTypes::GCuts& cut, double res ) {
+  return LoKi::GenAlgs::max_value( particle, fun, cut, res );
+}
+// ============================================================================
+// find the maximal value over the tree:
+// ============================================================================
+double LoKi::Dicts::GenAlgs::max_value( const HepMC3::ConstGenVertexPtr & vertex, const LoKi::GenTypes::GFunc& fun,
+                                        const LoKi::GenTypes::GCuts& cut, const HepMC3::Relatives & range, double res ) {
+  return LoKi::GenAlgs::max_value( vertex, fun, cut, range, res );
+}
+
+// ============================================================================
+// find the minimum element through the event
+// ============================================================================
+HepMC3::ConstGenParticlePtr LoKi::Dicts::GenAlgs::min_element( const HepMC3::GenEvent*       event,
+                                                             const LoKi::GenTypes::GFunc& fun,
+                                                             const LoKi::GenTypes::GCuts& cut ) {
+  return LoKi::GenAlgs::min_element( event, fun, cut );
+}
+// ============================================================================
+//  find the minimum element through the tree
+// ============================================================================
+HepMC3::ConstGenParticlePtr LoKi::Dicts::GenAlgs::min_element( const HepMC3::ConstGenParticlePtr &    particle,
+                                                             const LoKi::GenTypes::GFunc& fun,
+                                                             const LoKi::GenTypes::GCuts& cut ) {
+  return LoKi::GenAlgs::min_element( particle, fun, cut );
+}
+// ============================================================================
+//  find the minimum element through the treec
+// ============================================================================
+HepMC3::ConstGenParticlePtr LoKi::Dicts::GenAlgs::min_element( const HepMC3::ConstGenVertexPtr &      vertex,
+                                                             const LoKi::GenTypes::GFunc& fun,
+                                                             const LoKi::GenTypes::GCuts& cut,
+                                                             const HepMC3::Relatives &         range ) {
+  return LoKi::GenAlgs::min_element( vertex, fun, cut, range );
+}
+
+// ============================================================================
+// find the minimum element through the event
+// ============================================================================
+HepMC3::ConstGenParticlePtr LoKi::Dicts::GenAlgs::max_element( const HepMC3::GenEvent*       event,
+                                                             const LoKi::GenTypes::GFunc& fun,
+                                                             const LoKi::GenTypes::GCuts& cut ) {
+  return LoKi::GenAlgs::max_element( event, fun, cut );
+}
+// ============================================================================
+//  find the minimum element through the tree
+// ============================================================================
+HepMC3::ConstGenParticlePtr LoKi::Dicts::GenAlgs::max_element( const HepMC3::ConstGenParticlePtr &    particle,
+                                                             const LoKi::GenTypes::GFunc& fun,
+                                                             const LoKi::GenTypes::GCuts& cut ) {
+  return LoKi::GenAlgs::max_element( particle, fun, cut );
+}
+// ============================================================================
+//  find the minimum element through the treec
+// ============================================================================
+HepMC3::ConstGenParticlePtr LoKi::Dicts::GenAlgs::max_element( const HepMC3::ConstGenVertexPtr &      vertex,
+                                                             const LoKi::GenTypes::GFunc& fun,
+                                                             const LoKi::GenTypes::GCuts& cut,
+                                                             const HepMC3::Relatives &         range ) {
+  return LoKi::GenAlgs::max_element( vertex, fun, cut, range );
+}
+
+// ============================================================================
+// The END
+// ============================================================================
diff --git a/Gen/LoKiGen/src/GenChild.cpp b/Gen/LoKiGen/src/GenChild.cpp
new file mode 100644
index 000000000..81b7a0e31
--- /dev/null
+++ b/Gen/LoKiGen/src/GenChild.cpp
@@ -0,0 +1,273 @@
+/*****************************************************************************\
+* (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration      *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                             *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+// ============================================================================
+// Include files
+// ============================================================================
+// STD & STL
+// ============================================================================
+#include <algorithm>
+// ============================================================================
+// LoKi
+// ============================================================================
+#include "LoKi/BuildGenTrees.h"
+#include "LoKi/GenChild.h"
+#include "LoKi/GenTypes.h"
+// ============================================================================
+/** @file
+ *
+ *  This file is a part of LoKi project -
+ *    "C++ ToolKit  for Smart and Friendly Physics Analysis"
+ *
+ *  The package has been designed with the kind help from
+ *  Galina PAKHLOVA and Sergey BARSUK.  Many bright ideas,
+ *  contributions and advices from G.Raven, J.van Tilburg,
+ *  A.Golutvin, P.Koppenburg have been used in the design.
+ *
+ *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+ *  @date 2006-01-23
+ */
+// ============================================================================
+/*  get the number of children for the given HepMC3-particle
+ *  @see HepMC3::GenParticle
+ *  @param  mother pointer to HepMC3-particle
+ *  @return number of chilren
+ *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+ *  @date 2007-06-02
+ */
+// ============================================================================
+std::size_t LoKi::GenChild::nChildren( const HepMC3::ConstGenParticlePtr & mother ) {
+  if ( 0 == mother ) { return 0; } // RETURN
+  auto ev = mother->end_vertex();
+  if ( 0 == ev ) { return 0; } // RETURN
+  auto particles = HepMC3::Relatives::CHILDREN(ev);
+  return particles.size();
+}
+// ============================================================================
+/*  Trivial accessor to the daughter "decay" particles for the given
+ *   HepMC3-particle
+ *
+ *  @attention index starts with 1 , null index corresponds
+ *             to the original particle
+ *
+ *  @param  particle (const) pointer to mother particle
+ *  @param  index    index   index of the child particle
+ *  @return daughter particle with given index
+ *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+ *  @date 2007-06-02
+ */
+// ============================================================================
+HepMC3::ConstGenParticlePtr LoKi::GenChild::child( const HepMC3::ConstGenParticlePtr & mother, const size_t index ) {
+  if ( 0 == mother ) { return 0; }     // RETURN
+  if ( 0 == index ) { return mother; } // RETURN
+  auto ev = mother->end_vertex();
+  if ( 0 == ev ) { return 0; } // RETURN
+  auto particles = HepMC3::Relatives::CHILDREN(ev);
+  auto begin = std::begin(particles);
+  auto end   = std::end(particles);
+  size_t                                      curr  = index - 1;
+  while ( begin != end && 0 < curr ) {
+    ++begin;
+    --curr;
+  }
+  if ( begin != end && 0 == curr ) { return *begin; } // REUTRN
+  return 0;                                           // RETURN
+}
+// ============================================================================
+/*  get all particles form the given vertex form the given range
+ *  @see HepMC3::GenVertex::particles_begin
+ *  @see HepMC3::GenVertex::particles_end
+ *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+ *  @date   2007-05-26
+ */
+// ============================================================================
+size_t LoKi::GenChild::particles( const HepMC3::ConstGenVertexPtr & vertex, const HepMC3::Relatives & range,
+                                  std::vector<HepMC3::ConstGenParticlePtr>& output ) {
+  if ( !output.empty() ) { output.clear(); }
+  if ( 0 == vertex ) { return output.size(); }
+  LoKi::GenTypes::GenSet gset;
+  particles( vertex, range, gset );
+  output.insert( output.end(), std::begin(gset), std::end(gset) );
+  return output.size();
+}
+// ============================================================================
+/*  get all particles form the given vertex form the given range
+ *  @see HepMC3::GenVertex::particles_begin
+ *  @see HepMC3::GenVertex::particles_end
+ *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+ *  @date   2007-05-26
+ */
+// ============================================================================
+size_t LoKi::GenChild::particles( const HepMC3::ConstGenVertexPtr & vertex, const HepMC3::Relatives & range,
+                                  LoKi::GenTypes::GenSet& output ) {
+  if ( !output.empty() ) { output.clear(); }
+  if ( 0 == vertex ) { return output.size(); }
+  auto particles = range(vertex);
+  output.insert( std::begin(particles), std::end(particles) );
+  return output.size();
+}
+// ============================================================================
+/*  get all "in"-particles for the given vertex
+ *  @see HepMC3::GenVertex::particles_in_const_begin()
+ *  @see HepMC3::GenVertex::particles_in_const_end()
+ *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+ *  @date   2007-05-26
+ */
+// ============================================================================
+std::vector<HepMC3::ConstGenParticlePtr> LoKi::GenChild::particles_in( const HepMC3::ConstGenVertexPtr & vertex ) {
+  if ( 0 == vertex ) { return std::vector<HepMC3::ConstGenParticlePtr>(); }
+  return std::vector<HepMC3::ConstGenParticlePtr>( std::begin(vertex->particles_in()), std::end(vertex->particles_in()) );
+}
+// ============================================================================
+/*  get all "out"-particles for the given vertex
+ *  @see HepMC3::GenVertex::particles_in_const_begin()
+ *  @see HepMC3::GenVertex::particles_in_const_end()
+ *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+ *  @date   2007-05-26
+ */
+// ===========================================================================
+std::vector<HepMC3::ConstGenParticlePtr> LoKi::GenChild::particles_out( const HepMC3::ConstGenVertexPtr & vertex ) {
+  if ( 0 == vertex ) { return std::vector<HepMC3::ConstGenParticlePtr>(); }
+  return std::vector<HepMC3::ConstGenParticlePtr>( std::begin(vertex->particles_out()),
+                                                   std::end(vertex->particles_out()) );
+}
+// ============================================================================
+/*  get all particles form the given event
+ *  @see HepMC3::GenEvent::particles_begin
+ *  @see HepMC3::GenEvent::particles_end
+ *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+ *  @date   2007-05-26
+ */
+// ============================================================================
+std::vector<HepMC3::ConstGenParticlePtr> LoKi::GenChild::particles_all( const HepMC3::GenEvent* event ) {
+  if ( 0 == event ) { return std::vector<HepMC3::ConstGenParticlePtr>(); }
+  return event->particles();
+}
+// ============================================================================
+/*  get all vertices form the given event
+ *  @see HepMC3::GenEvent::vertices_begin
+ *  @see HepMC3::GenEvent::vertices_end
+ *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+ *  @date   2007-05-26
+ */
+// ============================================================================
+std::vector<HepMC3::ConstGenVertexPtr> LoKi::GenChild::vertices_all( const HepMC3::GenEvent* event ) {
+  if ( 0 == event ) { return std::vector<HepMC3::ConstGenVertexPtr>(); }
+  return event->vertices();
+}
+// ============================================================================
+/*  get all "children" particles form the given particle
+ *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+ *  @date   2007-05-26
+ */
+// ============================================================================
+size_t LoKi::GenChild::daughters( const HepMC3::ConstGenParticlePtr & particle, std::vector<HepMC3::ConstGenParticlePtr>& output ) {
+  if ( !output.empty() ) { output.clear(); }
+  if ( 0 == particle ) { return output.size(); } // RETURN
+  return daughters( particle->end_vertex(), output );
+}
+// ============================================================================
+/*  get all "children" particles form the given particle
+ *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+ *  @date   2007-05-26
+ */
+// ============================================================================
+size_t LoKi::GenChild::daughters( const HepMC3::ConstGenParticlePtr & particle, LoKi::GenTypes::GenSet& output ) {
+  if ( !output.empty() ) { output.clear(); }
+  if ( 0 == particle ) { return output.size(); } // RETURN
+  return daughters( particle->end_vertex(), output );
+}
+// ============================================================================
+/*  get all "ancestors" particles from the given particle
+ *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+ *  @date   2007-05-26
+ */
+// ============================================================================
+std::vector<HepMC3::ConstGenParticlePtr> LoKi::GenChild::ancestors( const HepMC3::ConstGenParticlePtr & particle ) {
+  if ( 0 == particle ) { return std::vector<HepMC3::ConstGenParticlePtr>(); }
+  return LoKi::GenChild::ancestors( particle->production_vertex() );
+}
+// ============================================================================
+/*  get all "descendant" particles form the given particle
+ *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+ *  @date   2007-05-26
+ */
+// ============================================================================
+std::vector<HepMC3::ConstGenParticlePtr> LoKi::GenChild::descendants( const HepMC3::ConstGenParticlePtr & particle ) {
+  if ( 0 == particle ) { return std::vector<HepMC3::ConstGenParticlePtr>(); }
+  return LoKi::GenChild::descendants( particle->end_vertex() );
+}
+// ============================================================================
+/* get all independent decay trees from HepMC3::GenEvent
+ *  @see LoKi::GenTrees::buildTrees
+ *  @author Vanya BELYAEV Ivan.Belyaev@itep.ru
+ *  @date   2016-01-17
+ */
+// ============================================================================
+LoKi::GenTypes::ConstVector LoKi::GenChild::trees( const HepMC3::GenEvent* event ) {
+  if ( 0 == event ) { return LoKi::GenTypes::ConstVector(); }
+  LoKi::GenTypes::ConstVector result;
+  result.reserve( 128 );
+  LoKi::GenTrees::buildTrees( std::begin(event->particles()), std::end(event->particles()), std::back_inserter( result ) );
+  return result;
+}
+// ========================================================================
+/*  get all independent decay trees from container of particles
+ *  @see LoKi::GenTrees::buildTrees
+ *  @author Vanya BELYAEV Ivan.Belyaev@itep.ru
+ *  @date   2016-01-17
+ */
+// ============================================================================
+LoKi::GenTypes::ConstVector LoKi::GenChild::trees( const LoKi::GenTypes::ConstVector& particles ) {
+  LoKi::GenTypes::ConstVector result;
+  result.reserve( particles.size() );
+  LoKi::GenTrees::buildTrees( particles.begin(), particles.end(), std::back_inserter( result ) );
+  return result;
+}
+// ========================================================================
+/*  get all independent decay trees from container of particles
+ *  @see LoKi::GenTrees::buildTrees
+ *  @author Vanya BELYAEV Ivan.Belyaev@itep.ru
+ *  @date   2016-01-17
+ */
+// ============================================================================
+LoKi::GenTypes::ConstVector LoKi::GenChild::trees( const LoKi::GenTypes::GRange& particles ) {
+  LoKi::GenTypes::ConstVector result;
+  result.reserve( particles.size() );
+  LoKi::GenTrees::buildTrees( particles.begin(), particles.end(), std::back_inserter( result ) );
+  return result;
+}
+// ========================================================================
+namespace {
+  // ==========================================================================
+  template <class INDEX>
+  HepMC3::ConstGenParticlePtr _child_( const HepMC3::ConstGenParticlePtr & particle, INDEX begin, INDEX end ) {
+    //
+    if ( 0 == particle ) { return 0; }       // RETURN
+    if ( begin == end ) { return particle; } // RETURN
+    //
+    HepMC3::ConstGenParticlePtr daug = LoKi::GenChild::child( particle, *begin );
+    //
+    if ( 0 == daug ) { return 0; } // RETURN
+    //
+    return _child_( daug, begin + 1, end );
+  }
+  // ==========================================================================
+} // namespace
+// ============================================================================
+HepMC3::ConstGenParticlePtr LoKi::GenChild::child( const HepMC3::ConstGenParticlePtr & particle,
+                                                 const std::vector<unsigned int>& indices ) {
+  return _child_( particle, indices.begin(), indices.end() );
+}
+// ============================================================================
+
+// ============================================================================
+// The END
+// ============================================================================
diff --git a/Gen/LoKiGen/src/GenChildSelector.cpp b/Gen/LoKiGen/src/GenChildSelector.cpp
new file mode 100644
index 000000000..03b8a39d3
--- /dev/null
+++ b/Gen/LoKiGen/src/GenChildSelector.cpp
@@ -0,0 +1,360 @@
+/*****************************************************************************\
+* (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration      *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                             *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+// ============================================================================
+// Include files
+// ============================================================================
+// GaudiKernel
+// ============================================================================
+#include "GaudiKernel/IToolSvc.h"
+#include "GaudiKernel/SmartIF.h"
+#include "GaudiKernel/ToStream.h"
+// ============================================================================
+// PartProp
+// ============================================================================
+#include "Kernel/IParticlePropertySvc.h"
+// ============================================================================
+// LoKi
+// ============================================================================
+#include "LoKi/BasicFunctors.h"
+#include "LoKi/GenAlgs.h"
+#include "LoKi/GenChild.h"
+#include "LoKi/GenChildSelector.h"
+#include "LoKi/GenExtract.h"
+#include "LoKi/GenParticles.h"
+#include "LoKi/ILoKiSvc.h"
+#include "LoKi/Services.h"
+#include "LoKi/Trees.h"
+// ============================================================================
+/** @file
+ *
+ *  This file is a part of LoKi project -
+ *    "C++ ToolKit  for Smart and Friendly Physics Analysis"
+ *
+ *  The package has been designed with the kind help from
+ *  Galina PAKHLOVA and Sergey BARSUK.  Many bright ideas,
+ *  contributions and advices from G.Raven, J.van Tilburg,
+ *  A.Golutvin, P.Koppenburg have been used in the design.
+ *
+ *  @author Vanya Belyaev  Ivan.Belyaev@cern.ch
+ *  @date 2011-12-11
+ *
+ */
+// ============================================================================
+namespace {
+  // ==========================================================================
+  /// invalid decay
+  const Decays::Trees::Types_<HepMC3::ConstGenParticlePtr>::Invalid s_INVALID =
+      Decays::Trees::Types_<HepMC3::ConstGenParticlePtr>::Invalid();
+  /// "None"-selector
+  const LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::BooleanConstant s_NONE( false );
+  /// "Factory"
+  const std::string s_FACTORY = "LoKi::GenDecay";
+  // ==========================================================================
+} // namespace
+// ============================================================================
+// constructor from the index
+// ============================================================================
+LoKi::GenChild::Selector::Selector( const std::vector<unsigned int>& indices )
+    : LoKi::AuxFunBase( std::tie( indices ) )
+    , m_indices( indices )
+    , m_finder( s_INVALID )
+    , m_setCut( false )
+    , m_cut( s_NONE ) {
+  Assert( valid(), "The child selector is invalid" );
+}
+// ============================================================================
+// constructor from decay tree
+// ============================================================================
+LoKi::GenChild::Selector::Selector( const Decays::IGenDecay::iTree& child )
+    : LoKi::AuxFunBase(), m_finder( child ), m_setCut( false ), m_cut( s_NONE ) {
+  //
+  if ( !m_finder ) {
+    LoKi::ILoKiSvc*                     ls = lokiSvc();
+    SmartIF<LHCb::IParticlePropertySvc> pp( ls );
+    const LHCb::IParticlePropertySvc*   ppsvc = pp;
+    if ( 0 == ppsvc ) {
+      const LoKi::Services& services = LoKi::Services::instance();
+      ppsvc                          = services.ppSvc();
+    }
+    StatusCode sc = m_finder.validate( ppsvc );
+    Assert( sc.isSuccess(), " Unable to validate the decay tree!" );
+  }
+  //
+  Assert( valid(), "The child selector is invalid" );
+}
+// ============================================================================
+// constructor from decay onde
+// ============================================================================
+LoKi::GenChild::Selector::Selector( const Decays::iNode& node )
+    : LoKi::AuxFunBase(), m_finder( s_INVALID ), m_setCut( false ), m_cut( s_NONE ) {
+  //
+  m_cut    = LoKi::GenParticles::DecNode( node );
+  m_setCut = true;
+  //
+  Assert( valid(), "The child selector is invalid" );
+}
+// ============================================================================
+// constructor from decay tree
+// ============================================================================
+LoKi::GenChild::Selector::Selector( const Decays::IGenDecay::Finder& child )
+    : LoKi::AuxFunBase(), m_finder( child ), m_setCut( false ), m_cut( s_NONE ) {
+  //
+  if ( !m_finder ) {
+    LoKi::ILoKiSvc*                     ls = lokiSvc();
+    SmartIF<LHCb::IParticlePropertySvc> pp( ls );
+    const LHCb::IParticlePropertySvc*   ppsvc = pp;
+    if ( 0 == ppsvc ) {
+      const LoKi::Services& services = LoKi::Services::instance();
+      ppsvc                          = services.ppSvc();
+    }
+    StatusCode sc = m_finder.validate( ppsvc );
+    Assert( sc.isSuccess(), " Unable to validate the decay tree!" );
+  }
+  //
+  Assert( valid(), "The child selector is invalid" );
+}
+// ============================================================================
+// constructor from the cut
+// ============================================================================
+LoKi::GenChild::Selector::Selector( const LoKi::Types::GCuts& cut )
+    : LoKi::AuxFunBase( std::tie( cut ) ), m_indices(), m_finder( s_INVALID ), m_setCut( true ), m_cut( cut ) {}
+// ============================================================================
+// constructor from decay desctriptor
+// ============================================================================
+LoKi::GenChild::Selector::Selector( const std::string& child )
+    : LoKi::AuxFunBase( std::tie( child ) ), m_indices(), m_finder( s_INVALID ), m_setCut( false ), m_cut( s_NONE ) {
+  StatusCode sc = buildTree( child, s_FACTORY );
+  Assert( sc.isSuccess(), "Unable to decode descriptor '" + child + "'", sc );
+  Assert( valid(), "The child selector is invalid" );
+}
+// ============================================================================
+// constructor from decay desctriptor & factory
+// ============================================================================
+LoKi::GenChild::Selector::Selector( const std::string& child, const std::string& factory )
+    : LoKi::AuxFunBase( std::tie( child, factory ) )
+    , m_indices()
+    , m_finder( s_INVALID )
+    , m_setCut( false )
+    , m_cut( s_NONE ) {
+  StatusCode sc = buildTree( child, factory );
+  Assert( sc.isSuccess(), "Unable to decode descriptor '" + child + "'", sc );
+  Assert( valid(), "The child selector is invalid" );
+}
+// ============================================================================
+// build the decay tree form the descriptor
+// ============================================================================
+StatusCode LoKi::GenChild::Selector::buildTree( const std::string& descriptor, const std::string& factory ) {
+  LoKi::ILoKiSvc*   ls = lokiSvc();
+  SmartIF<IToolSvc> toolSvc( ls );
+  if ( !toolSvc ) { return Error( "getTree: unable to locate tool service" ); }
+
+  Decays::IGenDecay* tool = nullptr;
+  StatusCode         sc   = toolSvc->retrieveTool( factory, tool );
+  if ( sc.isFailure() ) { return Error( "getTree: Unable to retrieve '" + factory + "'", sc ); }
+  if ( 0 == tool ) { return Error( "getTree: Decays::IGenDecay* points to NULL" ); }
+  //
+  m_finder = tool->tree( descriptor );
+  //
+  toolSvc->releaseTool( tool ); // do not need the tool anymore
+  //
+  if ( !m_finder ) { return Error( "getTree: the tree is invalid:  '" + descriptor + "'" ); }
+  if ( !m_finder.marked() ) { Warning( "getTree: the tree is unmarked: '" + descriptor + "'" ); }
+  //
+  return StatusCode::SUCCESS;
+}
+// ============================================================================
+// check the validity the child-selector
+// ============================================================================
+bool LoKi::GenChild::Selector::valid() const { return !m_indices.empty() || m_finder.valid() || m_setCut; }
+// ============================================================================
+
+// ============================================================================
+// try to validate it!
+// ============================================================================
+StatusCode LoKi::GenChild::Selector::validate( const LHCb::IParticlePropertySvc* svc ) const {
+  if ( !m_indices.empty() || m_setCut ) { return StatusCode::SUCCESS; }
+  //
+  StatusCode sc = m_finder.validate( svc );
+  if ( sc.isFailure() ) { return Error( "Unable to validate the tree/decay descriptor", sc ); }
+  //
+  return StatusCode::SUCCESS;
+}
+// ============================================================================
+// OPTIONAL: nice printout
+// ============================================================================
+std::ostream& LoKi::GenChild::Selector::fillStream( std::ostream& s ) const {
+  //
+  if ( !m_indices.empty() ) { return s << " " << Gaudi::Utils::toString( m_indices ) << " "; }
+  //
+  if ( m_setCut ) { return s << " " << m_cut << " "; } // REUTRN
+  //
+  return s << " " << m_finder.tree() << " ";
+}
+// ============================================================================
+/*  get the child according to the selector
+ *  @param mother    (INPUT) the head fo the decay tree
+ *  @param daughetrs (UPDATE)
+ *  @return unmber of particles
+ */
+// ============================================================================
+unsigned int LoKi::GenChild::Selector::children( const HepMC3::ConstGenParticlePtr &    head,
+                                                 LoKi::GenTypes::ConstVector& daughters ) const {
+  if ( 0 == head ) {
+    Error( "children: HepMC3::GenParticlePtr points to NULL" );
+    return 0; // RETURN
+  }
+  //
+  Assert( valid(), "Selector is invalid!" );
+  //
+  if ( !m_indices.empty() ) {
+    HepMC3::ConstGenParticlePtr c = LoKi::GenChild::child( head, m_indices );
+    if ( 0 == c ) { return 0; } // RETURN
+    //
+    daughters.push_back( c );
+    return daughters.size(); // RETURN
+  } else if ( m_setCut ) {
+    LoKi::Extract::genParticles( head, std::back_inserter( daughters ), m_cut );
+    return daughters.size(); // RETURN
+  } else {
+    LoKi::GenTypes::ConstVector input( 1, head );
+    return m_finder.findDecay( input, daughters ); // RETURN
+  }
+}
+// ============================================================================
+/*  get the child according to the selector
+ *  @param  head (INPUT) the head fo the decay tree
+ *  @return child particle
+ */
+// ============================================================================
+HepMC3::ConstGenParticlePtr LoKi::GenChild::Selector::child( const HepMC3::ConstGenParticlePtr & head ) const {
+  //
+  if ( 0 == head ) {
+    Error( "child: HepMC3::GenParticle points to NULL" );
+    return 0;
+  }
+  //
+  Assert( valid(), "Selector is invalid!" );
+  //
+  if ( !m_indices.empty() ) { return LoKi::GenChild::child( head, m_indices ); }
+  //
+  if ( m_setCut ) { return LoKi::GenAlgs::foundFirst( head, m_cut ); }
+  //
+  LoKi::GenTypes::ConstVector daughters;
+  LoKi::GenTypes::ConstVector input( 1, head );
+  //
+  m_finder.findDecay( input, daughters );
+  //
+  if ( daughters.empty() ) { return 0; } // REUTRN
+  //
+  if ( 1 < daughters.size() ) { Warning( "child: >1 daughter particles are found, return the first" ); }
+  //
+  return daughters[0];
+}
+// ============================================================================
+/* Trivial accessor to the daughter particles for the given particle.
+ *  @param  particle (const) pointer to mother particle
+ *  @param  selector the selector
+ *  @author Vanya BELYAEV Ivan.Belyaev@itep.ru
+ *  @date   2012-01-26
+ */
+// ============================================================================
+HepMC3::ConstGenParticlePtr LoKi::GenChild::child( const HepMC3::ConstGenParticlePtr &       particle,
+                                                 const LoKi::GenChild::Selector& selector ) {
+  if ( 0 == particle ) { return 0; } // RETURN
+  return selector.child( particle );
+}
+// ===========================================================================
+/*  accessor to certain children particles for the given particle
+ *  @param  particle (INPUT) pointer to mother particle
+ *  @param  selector (INPUT) the selector
+ *  @param  result   (OUTPUT) the container of found particles
+ *  @return number of found particles
+ *  @author Vanya BELYAEV Ivan.Belyaev@itep.ru
+ *  @date   2012-01-26
+ */
+// ===========================================================================
+unsigned int LoKi::GenChild::children( const HepMC3::ConstGenParticlePtr & particle, const LoKi::GenChild::Selector& selector,
+                                       LoKi::GenTypes::ConstVector& daughters ) {
+  if ( 0 == particle ) { return 0; } // RETURN
+  return selector.children( particle, daughters );
+}
+// ============================================================================
+/*  accessor to certain children particles for the given particle
+ *  @param  particle (INPUT) pointer to mother particle
+ *  @param  selector (INPUT) the selector
+ *  @return the container of found particles
+ *  @author Vanya BELYAEV Ivan.Belyaev@itep.ru
+ *  @date   2010-05-29
+ */
+// ============================================================================
+LoKi::GenTypes::ConstVector LoKi::GenChild::children( const HepMC3::ConstGenParticlePtr &       particle,
+                                                      const LoKi::GenChild::Selector& selector ) {
+  //
+  LoKi::GenTypes::ConstVector result;
+  if ( 0 == particle ) { return result; }
+  //
+  selector.children( particle, result );
+  //
+  return result;
+}
+// ===========================================================================
+/** Trivial accessor to the daughter particles for the given particle.
+ *  @param  particle (const) pointer to mother particle
+ *  @param  dscriptor
+ *  @author Vanya BELYAEV Ivan.Belyaev@itep.ru
+ *  @date   2016-06-21
+ */
+// ===========================================================================
+HepMC3::ConstGenParticlePtr LoKi::GenChild::child( const HepMC3::ConstGenParticlePtr & particle, const std::string& descriptor ) {
+  return nullptr == particle ? nullptr : child( particle, LoKi::GenChild::Selector( descriptor ) );
+}
+// ===========================================================================
+/* Trivial accessor to the daughter particles for the given particle.
+ *  @param  particle (const) pointer to mother particle
+ *  @param  cuts     (INPUT) cuts to be used
+ *  @author Vanya BELYAEV Ivan.Belyaev@itep.ru
+ *  @date   2016-06-21
+ */
+HepMC3::ConstGenParticlePtr LoKi::GenChild::child( const HepMC3::ConstGenParticlePtr & particle, const LoKi::Types::GCuts& cuts ) {
+  return nullptr == particle ? nullptr : child( particle, LoKi::GenChild::Selector( cuts ) );
+}
+// ========================================================================
+/* accessor to certain children particles for the given particle
+ *  @param  particle   (INPUT) pointer to mother particle
+ *  @param  descriptor (INPUT) the descriptor
+ *  @return the container of found particles
+ *  @author Vanya BELYAEV Ivan.Belyaev@itep.ru
+ *  @date   2016-06-21
+ */
+// ========================================================================
+LoKi::GenTypes::ConstVector LoKi::GenChild::children( const HepMC3::ConstGenParticlePtr & particle,
+                                                      const std::string&        descriptor ) {
+  return nullptr == particle ? LoKi::GenTypes::ConstVector()
+                             : children( particle, LoKi::GenChild::Selector( descriptor ) );
+}
+// ========================================================================
+/* accessor to certain children particles for the given particle
+ *  @param  particle (INPUT) pointer to mother particle
+ *  @param  cuts     (INPUT) cuts to be used
+ *  @return the container of found particles
+ *  @author Vanya BELYAEV Ivan.Belyaev@itep.ru
+ *  @date   2016-06-21
+ */
+// ========================================================================
+LoKi::GenTypes::ConstVector LoKi::GenChild::children( const HepMC3::ConstGenParticlePtr & particle,
+                                                      const LoKi::Types::GCuts& cuts ) {
+  return nullptr == particle ? LoKi::GenTypes::ConstVector() : children( particle, LoKi::GenChild::Selector( cuts ) );
+}
+// ========================================================================
+
+// ============================================================================
+// The END
+// ============================================================================
diff --git a/Gen/LoKiGen/src/GenDecayChain.cpp b/Gen/LoKiGen/src/GenDecayChain.cpp
new file mode 100644
index 000000000..a165a8ea6
--- /dev/null
+++ b/Gen/LoKiGen/src/GenDecayChain.cpp
@@ -0,0 +1,102 @@
+/*****************************************************************************\
+* (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration      *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                             *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+// ============================================================================
+// Include files
+// ============================================================================
+// STD & STL
+// ============================================================================
+#include <sstream>
+// ============================================================================
+// LoKi
+// ============================================================================
+#include "LoKi/GenDecayChain.h"
+// ============================================================================
+/** @file
+ *
+ *  This file is a part of LoKi project -
+ *    "C++ ToolKit  for Smart and Friendly Physics Analysis"
+ *
+ *  The package has been designed with the kind help from
+ *  Galina PAKHLOVA and Sergey BARSUK.  Many bright ideas,
+ *  contributions and advices from G.Raven, J.van Tilburg,
+ *  A.Golutvin, P.Koppenburg have been used in the design.
+ *
+ *  @author Vanya Belyaev Ivan.Belyaev@cern.ch
+ *  @date   2011-06-03
+ *
+ */
+// ============================================================================
+/*  Standard constructor
+ *  @param maxDepth  maximal decay depth
+ *  @param vertex    vertex info to be printed
+ *  @param vertexe   end-vertex info for MC particles to be printed
+ *  @param mode      mode for printout of 4-vectors
+ *  @param fg        color for foreground for 'marked' lines
+ *  @param bg        color for background for 'marked' lines
+ */
+// ============================================================================
+LoKi::GenDecayChain::GenDecayChain( const size_t maxDepth, const bool vertex, const Mode mode, const MSG::Color& fg,
+                                    const MSG::Color& bg, const bool vertexe )
+    : LoKi::DecayChainBase( maxDepth, vertex, mode, fg, bg ), m_vertexe( vertexe ) {}
+// ==========================================================================
+/*  Standard constructor
+ *  @param vertexe   end-vertex info for MC particles to be printed
+ */
+// ==========================================================================
+LoKi::GenDecayChain::GenDecayChain( const LoKi::DecayChainBase& base, const bool vertexe )
+    : LoKi::DecayChainBase( base ), m_vertexe( vertexe ) {}
+// ===========================================================================
+// predefined printout
+// ===========================================================================
+std::string LoKi::GenDecayChain::print_( const HepMC3::ConstGenParticlePtr & p, const LoKi::Types::GCuts& accept,
+                                         const LoKi::Types::GCuts& mark ) const {
+  std::ostringstream s;
+  //
+  print( p, s, '\n', accept, mark );
+  //
+  return s.str();
+}
+// ============================================================================
+// predefined printout
+// ============================================================================
+std::string LoKi::GenDecayChain::print_( const LoKi::Types::GRange& e, const LoKi::Types::GCuts& accept,
+                                         const LoKi::Types::GCuts& mark ) const {
+  std::ostringstream s;
+  //
+  print( e.begin(), e.end(), s, '\n', accept, mark, " ", 0 );
+  //
+  return s.str();
+}
+// ============================================================================
+// predefined printout
+// ============================================================================
+std::string LoKi::GenDecayChain::print_( const LoKi::GenTypes::GenContainer& e, const LoKi::Types::GCuts& accept,
+                                         const LoKi::Types::GCuts& mark ) const {
+  std::ostringstream s;
+  //
+  print( e.begin(), e.end(), s, '\n', accept, mark, " ", 0 );
+  //
+  return s.str();
+}
+// ===========================================================================
+// predefined printout
+// ===========================================================================
+std::string LoKi::GenDecayChain::print_( const HepMC3::GenEvent* p, const LoKi::Types::GCuts& accept,
+                                         const LoKi::Types::GCuts& mark ) const {
+  std::ostringstream s;
+  //
+  print( p, s, '\n', accept, mark );
+  //
+  return s.str();
+}
+// ===========================================================================
+// The END
+// ===========================================================================
diff --git a/Gen/LoKiGen/src/GenDecays.cpp b/Gen/LoKiGen/src/GenDecays.cpp
new file mode 100644
index 000000000..583890424
--- /dev/null
+++ b/Gen/LoKiGen/src/GenDecays.cpp
@@ -0,0 +1,976 @@
+/*****************************************************************************\
+* (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration      *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                             *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+// ============================================================================
+// Include files
+// ============================================================================
+#include <algorithm>
+#include <numeric>
+// ============================================================================
+// LoKi
+// ============================================================================
+#include "LoKi/Algs.h"
+#include "LoKi/GenAlgs.h"
+#include "LoKi/GenChild.h"
+#include "LoKi/GenDecays.h"
+#include "LoKi/GenOscillated.h"
+#include "LoKi/GenSections.h"
+#include "LoKi/Trees.h"
+#include "HepMC3/Relatives.h"
+// ============================================================================
+/** @file
+ *  Implementation file for LoKi HepMC3-tree-functors
+ *
+ *  This file is a part of LoKi project -
+ *    "C++ ToolKit  for Smart and Friendly Physics Analysis"
+ *
+ *  The package has been designed with the kind help from
+ *  Galina PAKHLOVA and Sergey BARSUK.  Many bright ideas,
+ *  contributions and advices from G.Raven, J.van Tilburg,
+ *  A.Golutvin, P.Koppenburg have been used in the design.
+ *
+ *  @author Vanya BELYAEV Ivan.BELYAEV@nikhef.nl
+ *  @date   2008-06-10
+ */
+// ============================================================================
+namespace {
+  // ==========================================================================
+  /// the name of photon for PHOTOS
+  static const std::string s_GAMMA = "gamma";
+  // ==========================================================================
+  /** make the decay sections
+   *  @author Vanya BELYAEV Ivan.BELYAEV@nikhef.nl
+   *  @date   2008-05-25
+   */
+  inline void makeSections( const HepMC3::ConstGenParticlePtr & p, const Decays::Trees::Alg alg, Decays::GenSections& sect ) {
+    if ( 0 == p ) { return; }
+    //
+    if ( Decays::Trees::Sections == alg ) {
+      Decays::sections( p, sect );
+    } else {
+      Decays::GenSection s;
+      Decays::section( p, s );
+      sect.push_back( s );
+    }
+  }
+  // ==========================================================================
+  struct NotPid {
+    // ========================================================================
+    /// constructor
+    NotPid( const Decays::Nodes::Pid& pid ) : m_pid( pid ) {}
+    // ========================================================================
+    /// the major method: find "not a pid"
+    inline bool operator()( const HepMC3::ConstGenParticlePtr & p ) const {
+      return 0 != p && !m_pid.check( LHCb::ParticleID( p->pdg_id() ) );
+    }
+    // ========================================================================
+  private:
+    // ========================================================================
+    /// the pid-checker
+    Decays::Nodes::Pid m_pid; // the pid-checker
+    // ========================================================================
+  };
+  // ==========================================================================
+  /** scan the sequence of particles to check that it containes ONLY
+   *  the partiles of the given PID
+   *  @author Vanya BELYAEV Ivan.Belyaev@nikhef.nl
+   *  @date 2008-05-26
+   */
+  template <class TYPE>
+  inline bool onlyPid( TYPE begin, TYPE end, const Decays::Nodes::Pid& pid ) {
+    return end == std::find_if( begin, end, NotPid( pid ) );
+  }
+  // ==========================================================================
+  /// the helper object for comparison
+  typedef Decays::Trees::CheckTree<HepMC3::ConstGenParticlePtr> Equal;
+  // ==========================================================================
+  struct _Pid {
+    /// constructor
+    _Pid( const Decays::Nodes::Pid& pid ) : m_pid( pid ) {}
+    // ========================================================================
+    /// the major method: find "not a pid"
+    inline bool operator()( const HepMC3::ConstGenParticlePtr & p ) const {
+      return 0 != p && m_pid.check( LHCb::ParticleID( p->pdg_id() ) );
+    }
+    // ========================================================================
+  private:
+    // ========================================================================
+    /// the pid-checker
+    Decays::Nodes::Pid m_pid; // the pid-checker
+    // ========================================================================
+  };
+  // ==========================================================================
+} // namespace
+// ============================================================================
+// GENEXCLUSIVE
+// ============================================================================
+/*  constructor from the node (mother), subtrees and "final" flag
+ *  @param mother the mother node
+ *  @param children the list of daughter substrees
+ *  @param alg the matching algorithm
+ */
+// ============================================================================
+Decays::Trees::GenExclusive::GenExclusive( const Decays::iNode&                         mother,
+                                           const Decays::Trees::GenExclusive::TreeList& children,
+                                           const Decays::Trees::Alg alg, const Decays::Trees::Oscillation oscillation )
+    : Decays::iTree_<HepMC3::ConstGenParticlePtr>()
+    , m_mother( mother )
+    , m_children( children )
+    , m_alg( alg )
+    , m_oscillation( oscillation ) {}
+// ============================================================================
+/*  constructor from the node (mother), subtrees and "final" flag
+ *  @param mother the mother node
+ *  @param alg the matching algorithm
+ *  @param osc require the oscillation flag for mother
+ */
+// ============================================================================
+Decays::Trees::GenExclusive::GenExclusive( const Decays::iNode& mother, const Decays::Trees::Alg alg,
+                                           const Decays::Trees::Oscillation oscillation )
+    : Decays::iTree_<HepMC3::ConstGenParticlePtr>()
+    , m_mother( mother )
+    , m_children()
+    , m_alg( alg )
+    , m_oscillation( oscillation ) {}
+// ============================================================================
+/*  constructor from the node (mother), subtrees and "final" flag
+ *  @param osc require the oscillation flag for mother
+ *  @param mother the mother node
+ *  @param osc require the oscillation flag for mother
+ */
+// ============================================================================
+Decays::Trees::GenExclusive::GenExclusive( const Decays::Trees::Oscillation oscillation, const Decays::iNode& mother )
+    : Decays::iTree_<HepMC3::ConstGenParticlePtr>()
+    , m_mother( mother )
+    , m_children()
+    , m_alg( Decays::Trees::Daughters )
+    , m_oscillation( oscillation ) {}
+// ============================================================================
+/*  constructor from the decay
+ *  @param decay the decay
+ *  @param alg the matching algorithm
+ *  @param oscillation check the oscillation flag
+ */
+// ============================================================================
+Decays::Trees::GenExclusive::GenExclusive( const Decays::Decay& decay, const Decays::Trees::Alg alg,
+                                           const Decays::Trees::Oscillation oscillation )
+    : Decays::iTree_<HepMC3::ConstGenParticlePtr>()
+    , m_mother( Decays::Nodes::Pid( decay.mother() ) )
+    , m_children()
+    , m_alg( alg )
+    , m_oscillation( oscillation ) {
+  setChildren( decay.children() );
+}
+// ============================================================================
+// MANDATORY: check the validity
+// ============================================================================
+bool Decays::Trees::GenExclusive::valid() const {
+  return m_mother.valid() && Decays::valid( childBegin(), childEnd() );
+}
+// ============================================================================
+// MANDATORY: validate the tree
+// ============================================================================
+StatusCode Decays::Trees::GenExclusive::validate( const LHCb::IParticlePropertySvc* svc ) const {
+  StatusCode sc = m_mother.validate( svc );
+  if ( sc.isFailure() ) { return sc; }
+  return Decays::validate( childBegin(), childEnd(), svc );
+}
+// ============================================================================
+// reset the collection cache
+// ============================================================================
+void Decays::Trees::GenExclusive::reset() const { i_reset(); }
+// ============================================================================
+// collect the marked elements
+// ============================================================================
+size_t Decays::Trees::GenExclusive::collect( Decays::iTree_<HepMC3::ConstGenParticlePtr>::Collection& output ) const {
+  return std::accumulate( childBegin(), childEnd(), size_t{0},
+                          [&]( size_t s, const auto& child ) { return s + child.collect( output ); } );
+}
+// ============================================================================
+// has marked elements in the tree ?
+// ============================================================================
+bool Decays::Trees::GenExclusive::marked() const {
+  return std::any_of( childBegin(), childEnd(), []( const auto& child ) { return child.marked(); } );
+}
+// ============================================================================
+// operator() implementation for GenExclusive and derived classes
+// ============================================================================
+bool Decays::Trees::GenExclusive::operator()( Decays::iTree_<HepMC3::ConstGenParticlePtr>::argument p ) const {
+  if ( p_match( p ) ) {
+    return true;
+  } else {
+    reset(); // cache should be empty when not matching
+    return false;
+  }
+}
+// ============================================================================
+// the only one essential method
+// ============================================================================
+bool Decays::Trees::GenExclusive::p_match( Decays::iTree_<HepMC3::ConstGenParticlePtr>::argument p ) const {
+  // check the validness and oscillation criteria
+  HepMC3::ConstGenParticlePtr good = ok( p );
+  if ( !good ) { return false; } // RETURN
+  // match children?
+  if ( 0 == nChildren() ) { return true; } // RETURN
+  //
+  // perform the real matching:
+  //
+  // (1) get the proper decay sections:
+  Decays::GenSections sections;
+  makeSections( good, alg(), sections );
+  //
+  // (2) loop over all sections
+  for ( auto isect = sections.begin(); sections.end() != isect; ++isect ) {
+    //
+    // (3) try to match the section
+    // skip the combinations  which does not match at all
+    if ( nChildren() != isect->size() ) { continue; }
+    //
+    // (4) sort the section
+    std::stable_sort( isect->begin(), isect->end() );
+    do // btw - it is my first "do ... while ( .. )" loop..        // ATTENTION
+    {
+      //
+      // (5) match all fields:
+      if ( std::equal( childBegin(), childEnd(), isect->begin(), Equal() ) ) { return true; } // RETURN
+    } // make all possible permutations of the section
+    while ( std::next_permutation( isect->begin(), isect->end() ) );
+  } // next section
+  // no match
+  return false; // RETURN
+}
+// ============================================================================
+// MANDATORY: the specific printout
+// ============================================================================
+std::ostream& Decays::Trees::GenExclusive::fillStream( std::ostream& s ) const {
+  //
+  s << ( ( 0 != nChildren() ) ? " (" : " " );
+  //
+  switch ( oscillation() ) {
+  case Decays::Trees::Oscillated:
+    s << "[" << mother() << "]os ";
+    break; // BREAK
+  case Decays::Trees::NotOscillated:
+    s << "[" << mother() << "]nos ";
+    break; // BREAK
+  default:
+    s << mother();
+  }
+  //
+  if ( 0 == nChildren() ) { return s; }
+  //
+  switch ( this->alg() ) {
+  case Sections:
+    s << "-->";
+    break;
+  default:
+    s << " ->";
+    break;
+  }
+  //
+  for ( auto itree = childBegin(); childEnd() != itree; ++itree ) { s << ( *itree ); }
+  //
+  return s << ") ";
+}
+// ============================================================================
+// add one more node to the tree
+// ============================================================================
+void Decays::Trees::GenExclusive::addDaughter( const Decays::iTree_<HepMC3::ConstGenParticlePtr>& tree ) {
+  m_children += tree;
+}
+// ============================================================================
+// add one more node to the tree
+// ============================================================================
+void Decays::Trees::GenExclusive::addDaughter( const std::string& node ) { addDaughter( Decays::Nodes::Pid( node ) ); }
+// ============================================================================
+// add one more node to the tree
+// ============================================================================
+void Decays::Trees::GenExclusive::addDaughter( const LHCb::ParticleID& node ) {
+  addDaughter( Decays::Nodes::Pid( node ) );
+}
+// ============================================================================
+// add one more node to the tree
+// ============================================================================
+void Decays::Trees::GenExclusive::addDaughter( const Decays::Decay::Item& node ) {
+  addDaughter( Decays::Nodes::Pid( node ) );
+}
+// ============================================================================
+// add one more node to the tree
+// ============================================================================
+void Decays::Trees::GenExclusive::addDaughter( const LHCb::ParticleProperty* node ) {
+  addDaughter( Decays::Nodes::Pid( node ) );
+}
+// ============================================================================
+// add one more node to the tree
+// ============================================================================
+void Decays::Trees::GenExclusive::addDaughter( const Decays::iNode& node ) { addDaughter( GenExclusive( node ) ); }
+// ============================================================================
+// set children
+// ============================================================================
+void Decays::Trees::GenExclusive::setChildren( const std::vector<std::string>& children ) {
+  m_children.clear();
+  for ( auto ichild = children.begin(); children.end() != ichild; ++ichild ) { addDaughter( *ichild ); }
+}
+// ============================================================================
+// set children
+// ============================================================================
+void Decays::Trees::GenExclusive::setChildren( const std::vector<Decays::Decay::Item>& children ) {
+  m_children.clear();
+  for ( auto ichild = children.begin(); children.end() != ichild; ++ichild ) { addDaughter( *ichild ); }
+}
+// ============================================================================
+// set children
+// ============================================================================
+void Decays::Trees::GenExclusive::setChildren( const std::vector<LHCb::ParticleID>& children ) {
+  m_children.clear();
+  for ( auto ichild = children.begin(); children.end() != ichild; ++ichild ) { addDaughter( *ichild ); }
+}
+// ============================================================================
+// set children
+// ============================================================================
+void Decays::Trees::GenExclusive::setChildren( const std::vector<const LHCb::ParticleProperty*>& children ) {
+  m_children.clear();
+  for ( auto ichild = children.begin(); children.end() != ichild; ++ichild ) { addDaughter( *ichild ); }
+}
+// ============================================================================
+/*  check the validness & mother & oscillation
+ *  @param p particle to be checked
+ *  @return oscilalted or not
+ */
+// ============================================================================
+HepMC3::ConstGenParticlePtr Decays::Trees::GenExclusive::ok( const HepMC3::ConstGenParticlePtr & p ) const {
+  if ( 0 == p ) { return 0; } // RETURN
+  //
+  // check mother
+  LHCb::ParticleID pid( p->pdg_id() );
+  //
+  // chargeL
+  const int q3 = pid.threeCharge();
+  //
+  HepMC3::ConstGenParticlePtr osc1 = 0;
+  if ( 0 == q3 ) { osc1 = LoKi::GenParticles::oscillated1( p ); }
+  HepMC3::ConstGenParticlePtr osc2 = 0;
+  if ( 0 == q3 ) { osc2 = LoKi::GenParticles::oscillated2( p ); }
+  //
+  // spaghetti
+  // explicitly requested oscillation
+  if ( Decays::Trees::Oscillated == oscillation() ) {
+    if ( !mother( pid ) ) { return 0; } // RETURN
+    return osc2;
+  }
+  // explicitly requiested non-oscillation
+  else if ( Decays::Trees::NotOscillated == oscillation() ) {
+    //
+    if ( 0 != osc1 || 0 != osc2 ) { return 0; }
+    if ( !mother( pid ) ) { return 0; } // RETURN
+    //
+    return p;
+  }
+  //  oscillation is irrelevant here
+  else if ( 0 != osc2 ) {
+    if ( !mother( pid ) && !mother( LHCb::ParticleID( osc2->pdg_id() ) ) ) { return 0; }
+    return osc2;
+  } else if ( 0 != osc1 ) {
+    if ( !mother( pid ) && !mother( LHCb::ParticleID( osc1->pdg_id() ) ) ) { return 0; }
+    return p;
+  }
+  //
+  // the regular case:
+  if ( !mother( pid ) ) { return 0; } // RETURN
+  //
+  return p;
+}
+// ============================================================================
+// GENINCLUSIVE
+// ============================================================================
+/*  full constructor from the node (mother), subtrees & flags
+ *  @param mother the mother node
+ *  @param children the list of daughter substrees
+ *  @param alg the matching algorithm
+ */
+// ============================================================================
+Decays::Trees::GenInclusive::GenInclusive( const Decays::iNode&                         mother,
+                                           const Decays::Trees::GenExclusive::TreeList& children,
+                                           const Decays::Trees::Alg alg, const Decays::Trees::Oscillation osc )
+    : Decays::Trees::GenExclusive( mother, children, alg, osc ) {}
+// ============================================================================
+/*  constructor from the node (mother), subtrees and "final" flag
+ *  @param mother the mother node
+ *  @param alg the matching algorithm
+ */
+// ============================================================================
+Decays::Trees::GenInclusive::GenInclusive( const Decays::iNode& mother, const Decays::Trees::Alg alg,
+                                           const Decays::Trees::Oscillation osc )
+    : Decays::Trees::GenExclusive( mother, alg, osc ) {}
+// ============================================================================
+/*  constructor from the decay & flags
+ *  @param decay the decay
+ *  @param alg the matching algorithm
+ *  @param oscillation check the oscillation flag
+ */
+Decays::Trees::GenInclusive::GenInclusive( const Decays::Decay& decay, const Decays::Trees::Alg alg,
+                                           const Decays::Trees::Oscillation osc )
+    : Decays::Trees::GenExclusive( decay, alg, osc ) {}
+// ============================================================================
+// constructor  from GenExclusive
+// ============================================================================
+Decays::Trees::GenInclusive::GenInclusive( const Decays::Trees::GenExclusive& right )
+    : Decays::Trees::GenExclusive( right ) {}
+// ============================================================================
+// MANDATORY: check the validity of the tree
+// ============================================================================
+bool Decays::Trees::GenInclusive::valid() const { return GenExclusive::valid() && 0 != nChildren(); }
+// ============================================================================
+// the only one essential method
+// ============================================================================
+bool Decays::Trees::GenInclusive::p_match( Decays::iTree_<HepMC3::ConstGenParticlePtr>::argument p ) const {
+  // check the validness and oscillation criteria
+  HepMC3::ConstGenParticlePtr good = ok( p );
+  if ( !good ) { return false; } // RETURN
+  // perform the real matching:
+  // (0) treat specifically the special case
+  // Only one inclusive particle and look through the whole tree
+  if ( 1 == nChildren() ) {
+    std::vector<HepMC3::ConstGenParticlePtr> d;
+    LoKi::GenChild::daughters( good, d );
+    // in tree
+    if ( Decays::Trees::Sections == alg() ) { return LoKi::GenAlgs::found( d.begin(), d.end(), front() ); }
+    // direct daughters :
+    return d.end() != std::find_if( d.begin(), d.end(), front() );
+  }
+  // (1) get the proper decay sections:
+  Decays::GenSections sections;
+  makeSections( good, alg(), sections );
+  // (2) loop over all sections
+  for ( Decays::GenSections::iterator isect = sections.begin(); sections.end() != isect; ++isect ) {
+    // (3) try to match the section
+    // skip the combinations  which does not match at all
+    if ( nChildren() > isect->size() ) { continue; }
+    // the special case of 2 elements
+    if ( 2 == nChildren() ) {
+      if ( LoKi::Algs::found_2( isect->begin(), isect->end(), front(), back() ) ) { return true; } // RETURN
+      continue;                                                                                    // CONTINUE
+    } else {
+      if ( LoKi::Algs::found_N( isect->begin(), isect->end(), children().trees() ) ) { return true; } // RETURN
+      continue;                                                                                       // CONTINUE ;
+    }
+
+    // never go further, unfortunately the most generic algorithm
+    // it terribly slow... O(N!)
+
+    // (4) sort the section
+    //    std::stable_sort ( isect->begin() , isect->end() ) ;
+    //    do  // loop over all permutations
+    //    {
+    //      // (5) match all fields:
+    //      if ( std::equal ( childBegin() , childEnd() , isect->begin() , Equal() ) )
+    //      { return true ; }                                            // RETURN
+    //    } // make all possible permutations of the section
+    //    while ( std::next_permutation ( isect->begin() , isect->end() ) ) ;
+  } // next section
+  // no match
+  return false; // RETURN
+}
+// ============================================================================
+// MANDATORY: the specific printout
+// ============================================================================
+std::ostream& Decays::Trees::GenInclusive::fillStream( std::ostream& s ) const {
+  //
+  switch ( oscillation() ) {
+  case Decays::Trees::Oscillated:
+    s << " ( [" << mother() << "]os ";
+    break; // BREAK
+  case Decays::Trees::NotOscillated:
+    s << " ( [" << mother() << "]nos ";
+    break; // BREAK
+  default:
+    s << " (" << mother();
+  }
+  //
+  switch ( this->alg() ) {
+  case Sections:
+    s << "-->";
+    break;
+  default:
+    s << " ->";
+    break;
+  }
+  //
+  for ( TreeList::const_iterator itree = childBegin(); childEnd() != itree; ++itree ) { s << ( *itree ); }
+  //
+  return s << " ... ) ";
+}
+// ============================================================================
+// GENOPTIONAL
+// ============================================================================
+/*  full constructor from the node (mother) and subtrees
+ *  @param mother the mother node
+ *  @param children the list of children
+ *  @param optional the list of optional components
+ *  @param alg the matching algorithm
+ *  @param oscillation check the oscilaltion flag
+ */
+// ============================================================================
+Decays::Trees::GenOptional::GenOptional( const Decays::iNode&                         mother,
+                                         const Decays::Trees::GenExclusive::TreeList& children,
+                                         const Decays::Trees::GenExclusive::TreeList& optional,
+                                         const Decays::Trees::Alg alg, const Decays::Trees::Oscillation osc )
+    : Decays::Trees::GenExclusive( mother, children, alg, osc ), m_optional( optional ) {}
+// ============================================================================
+/*  constructor from decay descriptor, optional and flags
+ *  @param decay the decay descriptor
+ *  @param optional the list of optional components
+ *  @param alg the matching algorithm
+ *  @param oscillation check the oscilaltion flag
+ */
+// ============================================================================
+Decays::Trees::GenOptional::GenOptional( const Decays::Decay&                         decay,
+                                         const Decays::Trees::GenExclusive::TreeList& optional,
+                                         const Decays::Trees::Alg alg, const Decays::Trees::Oscillation osc )
+    : Decays::Trees::GenExclusive( decay, alg, osc ), m_optional( optional ) {}
+// ============================================================================
+Decays::Trees::GenOptional::GenOptional( const Decays::Trees::GenOptional::GenExclusive& right,
+                                         const Decays::Trees::GenExclusive::TreeList&    optional )
+    : Decays::Trees::GenExclusive( right ), m_optional( optional ) {}
+// ============================================================================
+// MANDATORY: check the validity of the tree
+// ============================================================================
+bool Decays::Trees::GenOptional::valid() const {
+  return GenExclusive::valid() && 0 != nChildren() && 0 != nOptional() && Decays::valid( optBegin(), optEnd() );
+}
+// ============================================================================
+// MANDATORY: the proper validation of the tree
+// ============================================================================
+StatusCode Decays::Trees::GenOptional::validate( const LHCb::IParticlePropertySvc* svc ) const {
+  StatusCode sc = GenExclusive::validate( svc );
+  return sc.isFailure() ? sc : Decays::validate( optBegin(), optEnd(), svc );
+}
+// ============================================================================
+// has marked elements in the tree ?
+// ============================================================================
+bool Decays::Trees::GenOptional::marked() const {
+  for ( TreeList::const_iterator iopt = optBegin(); optEnd() != iopt; ++iopt ) {
+    if ( iopt->marked() ) { return true; }
+  }
+  return Decays::Trees::GenExclusive::marked();
+}
+// ============================================================================
+// MANDATORY: the specific printout
+// ============================================================================
+std::ostream& Decays::Trees::GenOptional::fillStream( std::ostream& s ) const {
+  //
+  switch ( oscillation() ) {
+  case Decays::Trees::Oscillated:
+    s << " ( [" << mother() << "]os ";
+    break; // BREAK
+  case Decays::Trees::NotOscillated:
+    s << " ( [" << mother() << "]nos ";
+    break; // BREAK
+  default:
+    s << " (" << mother();
+  }
+  //
+  switch ( this->alg() ) {
+  case Sections:
+    s << "-->";
+    break;
+  default:
+    s << " ->";
+    break;
+  }
+  //
+  for ( TreeList::const_iterator itree = childBegin(); childEnd() != itree; ++itree ) { s << ( *itree ); }
+  //
+  for ( TreeList::const_iterator itree = optBegin(); optEnd() != itree; ++itree ) { s << " {" << ( *itree ) << "} "; }
+  //
+  return s << ") ";
+}
+// ============================================================================
+// MANDATORY: the only one essential method
+// ============================================================================
+bool Decays::Trees::GenOptional::p_match( Decays::iTree_<HepMC3::ConstGenParticlePtr>::argument p ) const {
+  // check the validness and oscillation criteria
+  HepMC3::ConstGenParticlePtr good = ok( p );
+  if ( !good ) { return false; } // RETURN
+  // perform the real matching:
+  // (1) get the proper decay sections:
+  Decays::GenSections sections;
+  makeSections( good, alg(), sections );
+  // create local constainer for permutations
+  TreeList opt( m_optional );
+  // (2) loop over all sections
+  for ( Decays::GenSections::iterator isect = sections.begin(); sections.end() != isect; ++isect ) {
+    // (3) try to match the section
+    // skip the combinations  which does not match at all
+    if ( isect->size() < nChildren() ) { continue; }               // CONITNUE
+    if ( isect->size() > nChildren() + nOptional() ) { continue; } // CONTINUE
+    // (4) sort the section
+    std::stable_sort( isect->begin(), isect->end() );
+    // (5) check "inclusive"
+    if ( !LoKi::Algs::found_N( isect->begin(), isect->end(), children().trees() ) ) { continue; } // CONTINUE
+    // (6) make all possible permutations:
+    do // loop over all permutations
+    {
+      // (7) match all declared mandatory fields:
+      if ( std::equal( childBegin(), childEnd(), isect->begin(), Equal() ) ) {
+        // the temporary iterator
+        Decays::GenSection::iterator aux = isect->begin() + nChildren();
+        // create the local container for permutations
+        // TreeList opt ( m_optional ) ;
+        std::for_each( opt.begin(), opt.end(), []( const TreeList::_Tree_& t ) { t.reset(); } );
+        std::stable_sort( opt.begin(), opt.end() ); // sort it!!!
+        // start all possible permutations of the optional stuff
+        do {
+          if ( std::equal( aux, isect->end(), opt.begin(), Equal() ) ) { return true; } // RETURN
+        } // the next permutation for the optional stuff
+        while ( std::next_permutation( opt.begin(), opt.end() ) );
+      } // match mandatory stuff
+    }   // next permutation
+    while ( std::next_permutation( isect->begin(), isect->end() ) );
+  } // next section
+  // no match
+  return false; // RETURN
+}
+// ============================================================================
+// add one more daughter to the decay
+// ============================================================================
+void Decays::Trees::GenOptional::addOptional( const Decays::iTree_<HepMC3::ConstGenParticlePtr>& tree ) {
+  m_optional += tree;
+}
+// ============================================================================
+// add one more daughter to the decay
+// ============================================================================
+void Decays::Trees::GenOptional::addOptional( const Decays::iNode& node ) { addOptional( GenExclusive( node ) ); }
+// ============================================================================
+// add one more daughter to the decay
+// ============================================================================
+void Decays::Trees::GenOptional::addOptional( const std::string& node ) { addOptional( Decays::Nodes::Pid( node ) ); }
+// ============================================================================
+// add one more daughter to the decay
+// ============================================================================
+void Decays::Trees::GenOptional::addOptional( const LHCb::ParticleID& node ) {
+  addOptional( Decays::Nodes::Pid( node ) );
+}
+// ============================================================================
+// add one more daughter to the decay
+// ============================================================================
+void Decays::Trees::GenOptional::addOptional( const Decays::Decay::Item& node ) {
+  addOptional( Decays::Nodes::Pid( node ) );
+}
+// ============================================================================
+// add one more daughter to the decay
+// ============================================================================
+void Decays::Trees::GenOptional::addOptional( const LHCb::ParticleProperty* node ) {
+  addOptional( Decays::Nodes::Pid( node ) );
+}
+// ============================================================================
+// set optional
+// ============================================================================
+void Decays::Trees::GenOptional::setOptional( const std::vector<const LHCb::ParticleProperty*>& optional ) {
+  m_optional.clear();
+  for ( std::vector<const LHCb::ParticleProperty*>::const_iterator iopt = optional.begin(); optional.end() != iopt;
+        ++iopt ) {
+    addOptional( *iopt );
+  }
+}
+// ============================================================================
+// set optional
+// ============================================================================
+void Decays::Trees::GenOptional::setOptional( const std::vector<LHCb::ParticleID>& optional ) {
+  m_optional.clear();
+  for ( std::vector<LHCb::ParticleID>::const_iterator iopt = optional.begin(); optional.end() != iopt; ++iopt ) {
+    addOptional( *iopt );
+  }
+}
+// ============================================================================
+// set optional
+// ============================================================================
+void Decays::Trees::GenOptional::setOptional( const std::vector<Decays::Decay::Item>& optional ) {
+  m_optional.clear();
+  for ( std::vector<Decays::Decay::Item>::const_iterator iopt = optional.begin(); optional.end() != iopt; ++iopt ) {
+    addOptional( *iopt );
+  }
+}
+// ============================================================================
+// set optional
+// ============================================================================
+void Decays::Trees::GenOptional::setOptional( const std::vector<std::string>& optional ) {
+  m_optional.clear();
+  for ( std::vector<std::string>::const_iterator iopt = optional.begin(); optional.end() != iopt; ++iopt ) {
+    addOptional( *iopt );
+  }
+}
+// ============================================================================
+// GENPHOTOS
+// ============================================================================
+/*  full constructor from the node (mother) and subtrees
+ *  @param mother the mother node
+ *  @param children the list of children
+ *  @param alg the matching algorithm
+ *  @param oscillation check the oscilaltion flag
+ */
+// ============================================================================
+Decays::Trees::GenPhotos::GenPhotos( const Decays::iNode& mother, const Decays::Trees::GenPhotos::TreeList& children,
+                                     const Decays::Trees::Alg alg, const Decays::Trees::Oscillation osc )
+    : Decays::Trees::GenExclusive( mother, children, alg, osc ), m_photon( s_GAMMA ) {}
+// ============================================================================
+/*  constructor from the decay descriptor and flags
+ *  @param decay the decay descriptor
+ *  @param alg the matching algorithm
+ *  @param oscillation check the oscilaltion flag
+ */
+// ============================================================================
+Decays::Trees::GenPhotos::GenPhotos( const Decays::Decay& decay, const Decays::Trees::Alg alg,
+                                     const Decays::Trees::Oscillation osc )
+    : Decays::Trees::GenExclusive( decay, alg, osc ), m_photon( s_GAMMA ) {}
+// ============================================================================
+// constructor from the tree
+// ============================================================================
+Decays::Trees::GenPhotos::GenPhotos( const Decays::Trees::GenPhotos::GenExclusive& right )
+    : Decays::Trees::GenExclusive( right ), m_photon( s_GAMMA ) {}
+// ============================================================================
+// MANDATORY: the proper validation of the tree
+// ============================================================================
+StatusCode Decays::Trees::GenPhotos::validate( const LHCb::IParticlePropertySvc* svc ) const {
+  StatusCode sc = m_photon.validate( svc );
+  return sc.isFailure() ? sc : GenExclusive::validate( svc ); // RETURN
+}
+// ============================================================================
+// MANDATORY: the specific printout
+// ============================================================================
+std::ostream& Decays::Trees::GenPhotos::fillStream( std::ostream& s ) const {
+  //
+  switch ( oscillation() ) {
+  case Decays::Trees::Oscillated:
+    s << " ( [" << mother() << "]os ";
+    break; // BREAK
+  case Decays::Trees::NotOscillated:
+    s << " ( [" << mother() << "]nos ";
+    break; // BREAK
+  default:
+    s << " (" << mother();
+  }
+  //
+  switch ( this->alg() ) {
+  case Sections:
+    s << "==>";
+    break;
+  default:
+    s << " =>";
+    break;
+  }
+  //
+  for ( TreeList::const_iterator itree = childBegin(); childEnd() != itree; ++itree ) { s << ( *itree ); }
+  //
+  return s << ") ";
+}
+// ============================================================================
+// MANDATORY: the only one essential method
+// ============================================================================
+bool Decays::Trees::GenPhotos::p_match( Decays::iTree_<HepMC3::ConstGenParticlePtr>::argument p ) const {
+  // check the validness and oscillation criteria
+  HepMC3::ConstGenParticlePtr good = ok( p );
+  if ( !good ) { return false; } // RETURN
+  // perform the real matching:
+  // (1) get the proper decay sections:
+  Decays::GenSections sections;
+  makeSections( good, alg(), sections );
+  // (2) loop over all sections
+  for ( Decays::GenSections::iterator isect = sections.begin(); sections.end() != isect; ++isect ) {
+    // (3) try to match the section
+    // skip the combinations  which does not match at all
+    if ( nChildren() > isect->size() ) { continue; }
+    // (4) count photons
+    const size_t nGamma = std::count_if( isect->begin(), isect->end(), _Pid( m_photon ) );
+    if ( nChildren() + nGamma < isect->size() ) { continue; }
+    // (5) sort the section
+    std::stable_sort( isect->begin(), isect->end() );
+    // (6) check "inclusive"
+    if ( !LoKi::Algs::found_N( isect->begin(), isect->end(), children().trees() ) ) { continue; }
+    // (7) make all possible permutations:
+    do {
+      // (8) match all declared mandatory fields:
+      if ( std::equal( childBegin(), childEnd(), isect->begin(), Equal() ) && // the rest is only photons
+           onlyPid( isect->begin() + nChildren(), isect->end(), m_photon ) ) {
+        return true;
+      }
+    } // next permutation
+    while ( std::next_permutation( isect->begin(), isect->end() ) );
+  } // next section
+  // no match
+  return false; // RETURN
+}
+// ============================================================================
+// GENPHOTOSOPTIONAL
+// ============================================================================
+/*  full constructor from the node (mother) and subtrees
+ *  @param mother the mother node
+ *  @param children the list of children
+ *  @param optional the list of optional components
+ *  @param alg the matching algorithm
+ *  @param oscillation check the oscilaltion flag
+ */
+// ============================================================================
+Decays::Trees::GenPhotosOptional::GenPhotosOptional( const Decays::iNode&                         mother,
+                                                     const Decays::Trees::GenExclusive::TreeList& children,
+                                                     const Decays::Trees::GenExclusive::TreeList& optional,
+                                                     const Decays::Trees::Alg                     alg,
+                                                     const Decays::Trees::Oscillation             osc )
+    : Decays::Trees::GenOptional( mother, children, optional, alg, osc ), m_photon( s_GAMMA ) {}
+// ============================================================================
+/*  constructor from decay descriptor, optional and flags
+ *  @param decay the decay descriptor
+ *  @param optional the list of optional components
+ *  @param alg the matching algorithm
+ *  @param oscillation check the oscilaltion flag
+ */
+// ============================================================================
+Decays::Trees::GenPhotosOptional::GenPhotosOptional( const Decays::Decay&                         decay,
+                                                     const Decays::Trees::GenExclusive::TreeList& optional,
+                                                     const Decays::Trees::Alg                     alg,
+                                                     const Decays::Trees::Oscillation             osc )
+    : Decays::Trees::GenOptional( decay, optional, alg, osc ), m_photon( s_GAMMA ) {}
+// ============================================================================
+// constructor from the tree
+// ============================================================================
+Decays::Trees::GenPhotosOptional::GenPhotosOptional( const Decays::Trees::GenOptional& right )
+    : Decays::Trees::GenOptional( right ), m_photon( s_GAMMA ) {}
+// ============================================================================
+Decays::Trees::GenPhotosOptional::GenPhotosOptional( const Decays::Trees::GenExclusive&           right,
+                                                     const Decays::Trees::GenExclusive::TreeList& optional )
+    : Decays::Trees::GenOptional( right, optional ), m_photon( s_GAMMA ) {}
+// ============================================================================
+// MANDATORY: check the validity of the tree
+// ============================================================================
+bool Decays::Trees::GenPhotosOptional::valid() const { return GenOptional::valid() && m_photon.valid(); }
+// ============================================================================
+// MANDATORY: the proper validation of the tree
+// ============================================================================
+StatusCode Decays::Trees::GenPhotosOptional::validate( const LHCb::IParticlePropertySvc* svc ) const {
+  StatusCode sc = m_photon.validate( svc );
+  return sc.isFailure() ? sc : GenOptional::validate( svc );
+}
+// ============================================================================
+// MANDATORY: the specific printout
+// ============================================================================
+std::ostream& Decays::Trees::GenPhotosOptional::fillStream( std::ostream& s ) const {
+  //
+  switch ( oscillation() ) {
+  case Decays::Trees::Oscillated:
+    s << " ( [" << mother() << "]os ";
+    break; // BREAK
+  case Decays::Trees::NotOscillated:
+    s << " ( [" << mother() << "]nos ";
+    break; // BREAK
+  default:
+    s << " (" << mother();
+  }
+  //
+  switch ( this->alg() ) {
+  case Sections:
+    s << "==>";
+    break;
+  default:
+    s << " =>";
+    break;
+  }
+  //
+  for ( TreeList::const_iterator itree = childBegin(); childEnd() != itree; ++itree ) { s << ( *itree ); }
+  //
+  for ( TreeList::const_iterator itree = optBegin(); optEnd() != itree; ++itree ) { s << " {" << ( *itree ) << "} "; }
+  //
+  return s << ") ";
+}
+// ============================================================================
+// MANDATORY: the only one essential method
+// ============================================================================
+bool Decays::Trees::GenPhotosOptional::p_match( Decays::iTree_<HepMC3::ConstGenParticlePtr>::argument p ) const {
+  // check the validness and oscillation criteria
+  HepMC3::ConstGenParticlePtr good = ok( p );
+  if ( !good ) { return false; } // RETURN
+  // perform the real matching:
+  // (1) get the proper decay sections:
+  Decays::GenSections sections;
+  makeSections( p, alg(), sections );
+  // create the local container for permutations
+  TreeList opt( optBegin(), optEnd() );
+  // (2) loop over all sections
+  for ( auto isect = sections.begin(); sections.end() != isect; ++isect ) {
+    // (3) try to match the section
+    // skip the combinations  which does not match at all
+    if ( nChildren() > isect->size() ) { continue; }
+    // (4) check "inclusive"
+    if ( !LoKi::Algs::found_N( isect->begin(), isect->end(), children().trees() ) ) { continue; } // CONTINUE
+    // (5) sort the section
+    std::stable_sort( isect->begin(), isect->end() );
+    // (6) make all possible permutations:
+    do {
+      // (7) match all declared mandatory fields:
+      if ( std::equal( childBegin(), childEnd(), isect->begin(), Equal() ) ) {
+        // the temporary iterator
+        auto aux = isect->begin() + nChildren();
+        // nothing to match?
+        if ( aux == isect->end() ) { return true; } // RETURN
+        // create the local container for permutations
+        // TreeList opt ( optBegin() , optEnd() ) ;
+        std::for_each( opt.begin(), opt.end(), []( const TreeList::_Tree_& t ) { t.reset(); } );
+        std::stable_sort( opt.begin(), opt.end() ); // sort it!!!
+        // make the nesessary permutations
+        do {
+          for ( auto it = opt.begin(); opt.end() != it; ++it ) {
+            // select only the subsequence of the right length
+            if ( it - opt.begin() <= isect->end() - aux ) {
+              // match the subsequence
+              if ( std::equal( opt.begin(), it, aux, Equal() ) && // the rest is only photons
+                   onlyPid( aux + opt.size(), isect->end(), m_photon ) ) {
+                return true;
+              }
+            }
+            // try to match the back-end of the sequence (save time?)
+            if ( opt.end() - it <= isect->end() - aux ) {
+              // match the subsequence
+              if ( std::equal( it, opt.end(), aux, Equal() ) && // the rest is only photons
+                   onlyPid( aux + opt.size(), isect->end(), m_photon ) ) {
+                return true;
+              }
+            } // match the optional stuff
+          }   // the length of the optional stuff
+        }     // permutations over the optional stuff
+        while ( std::next_permutation( opt.begin(), opt.end() ) );
+      } // match the mandatory stuff
+    }   // next permutation for mandatory stuff
+    while ( std::next_permutation( isect->begin(), isect->end() ) );
+  } // next section
+  // no match
+  return false; // RETURN
+}
+// ============================================================================
+
+// ============================================================================
+// treat properly the stable trees
+// ============================================================================
+template <>
+bool Decays::Trees::Stable_<HepMC3::ConstGenParticlePtr>::
+     operator()( Decays::iTree_<HepMC3::ConstGenParticlePtr>::argument p ) const {
+  //
+  if ( 0 == p ) { return false; }
+  if ( !valid() ) { return false; }
+  if ( !m_head( LHCb::ParticleID( p->pdg_id() ) ) ) { return false; }
+  //
+  auto ev = p->end_vertex();
+  if ( 0 == ev ) { return true; } // RETURN
+  //
+  auto particles = HepMC3::Relatives::CHILDREN(ev);
+  return particles.size() == 0;
+}
+
+// ============================================================================
+// The END
+// ============================================================================
diff --git a/Gen/LoKiGen/src/GenDump.cpp b/Gen/LoKiGen/src/GenDump.cpp
new file mode 100644
index 000000000..a5f370da4
--- /dev/null
+++ b/Gen/LoKiGen/src/GenDump.cpp
@@ -0,0 +1,126 @@
+/*****************************************************************************\
+* (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration      *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                             *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+// ============================================================================
+// Include files
+// ============================================================================
+// STD & STL
+// ============================================================================
+#include <sstream>
+// ============================================================================
+// LoKi
+// ============================================================================
+#include "LoKi/GenDecayChain.h"
+#include "LoKi/GenDump.h"
+#include "LoKi/Objects.h"
+// ============================================================================
+/** @file
+ *
+ *  This file is a part of LoKi project -
+ *    "C++ ToolKit  for Smart and Friendly Physics Analysis"
+ *
+ *  The package has been designed with the kind help from
+ *  Galina PAKHLOVA and Sergey BARSUK.  Many bright ideas,
+ *  contributions and advices from G.Raven, J.van Tilburg,
+ *  A.Golutvin, P.Koppenburg have been used in the design.
+ *
+ *  @author Vanya Belyaev Ivan.Belyaev@cern.ch
+ *  @date   2011-06-03
+ *
+ */
+// ============================================================================
+/*  template specialization of ``dumper''
+ *  @see LoKi::Functors::Dump_
+ *  @author Vanya Belyaev Ivan.Belyaev@cern.ch
+ *  @date   2011-06-03
+ */
+// ============================================================================
+template <>
+std::vector<HepMC3::ConstGenParticlePtr> LoKi::Functors::Dump_<HepMC3::ConstGenParticlePtr>::
+                                       operator()( const std::vector<HepMC3::ConstGenParticlePtr>& a ) const {
+  //
+  const unsigned int mx = std::min( m_dump.nMax(), a.size() );
+  //
+  m_stream << m_dump.open();
+  //
+  LoKi::GenDecayChain printer;
+  printer.print( a.begin(), a.begin() + mx, m_stream, '\n', LoKi::Objects::_VALID_, LoKi::Objects::_NONE_, " ", 0 );
+  //
+  m_stream << m_dump.close();
+  //
+  return a;
+}
+// ============================================================================
+/*  template specialization of ``dumpers''
+ *  @see LoKi::Functors::Dump1_
+ *  @author Vanya Belyaev Ivan.Belyaev@itep.ru
+ *  @date   2012-01-28
+ */
+// ============================================================================
+template <>
+bool LoKi::Functors::Dump1_<HepMC3::ConstGenParticlePtr, bool>::operator()( const HepMC3::ConstGenParticlePtr & a ) const {
+  //
+  if ( m_right ) {
+    m_stream << m_dump.open();
+    //
+    LoKi::GenDecayChain printer;
+    printer.print( a, m_stream, '\n', LoKi::Objects::_VALID_, LoKi::Objects::_NONE_, " ", 0 );
+    //
+    m_stream << m_dump.close();
+    //
+    return m_fun( a );
+  }
+  //
+  auto result = m_fun( a );
+  //
+  m_stream << m_dump.open();
+  //
+  LoKi::GenDecayChain printer;
+  printer.print( a, m_stream, '\n', LoKi::Objects::_VALID_, LoKi::Objects::_NONE_, " ", 0 );
+  //
+  m_stream << m_dump.close();
+  //
+  return result;
+}
+// ============================================================================
+/*  template specialization of ``dumpers''
+ *  @see LoKi::Functors::Dump1_
+ *  @author Vanya Belyaev Ivan.Belyaev@itep.ru
+ *  @date   2012-01-28
+ */
+// ============================================================================
+template <>
+double LoKi::Functors::Dump1_<HepMC3::ConstGenParticlePtr, double>::operator()( const HepMC3::ConstGenParticlePtr & a ) const {
+  //
+  if ( m_right ) {
+    m_stream << m_dump.open();
+    //
+    LoKi::GenDecayChain printer;
+    printer.print( a, m_stream, '\n', LoKi::Objects::_VALID_, LoKi::Objects::_NONE_, " ", 0 );
+    //
+    m_stream << m_dump.close();
+    //
+    return m_fun( a );
+  }
+  //
+  auto result = m_fun( a );
+  //
+  m_stream << m_dump.open();
+  //
+  LoKi::GenDecayChain printer;
+  printer.print( a, m_stream, '\n', LoKi::Objects::_VALID_, LoKi::Objects::_NONE_, " ", 0 );
+  //
+  m_stream << m_dump.close();
+  //
+  return result;
+}
+// ============================================================================
+// The END
+// ============================================================================
diff --git a/Gen/LoKiGen/src/GenExtractDicts.cpp b/Gen/LoKiGen/src/GenExtractDicts.cpp
new file mode 100644
index 000000000..269156be6
--- /dev/null
+++ b/Gen/LoKiGen/src/GenExtractDicts.cpp
@@ -0,0 +1,76 @@
+/*****************************************************************************\
+* (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration      *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                             *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+// ============================================================================
+// Include files
+// ============================================================================
+// HepMC3
+// ============================================================================
+#ifdef __INTEL_COMPILER
+#  pragma warning( disable : 1572 ) // floating-point equality and inequality comparisons are unreliable
+#  pragma warning( push )
+#endif
+#include "HepMC3/GenEvent.h"
+#include "HepMC3/GenParticle.h"
+#include "HepMC3/GenVertex.h"
+#ifdef __INTEL_COMPILER
+#  pragma warning( pop )
+#endif
+// ============================================================================
+// LoKi
+// ============================================================================
+#include "LoKi/GenExtractDicts.h"
+#include "LoKi/Objects.h"
+// ============================================================================
+/** @file
+ *  Implementation file for class LoKi::Dicts::GenExtract
+ *  @date 2007-06-03
+ *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+ */
+// ============================================================================
+// extract the particles from the event
+// ============================================================================
+std::vector<HepMC3::ConstGenParticlePtr> LoKi::GenExtract::genParticles( const HepMC3::GenEvent*       event,
+                                                                       const LoKi::GenTypes::GCuts& cuts ) {
+  std::vector<HepMC3::ConstGenParticlePtr> result;
+  LoKi::Extract::genParticles( event, std::back_inserter( result ), cuts );
+  return result;
+}
+// ============================================================================
+// extract the particles from the vertex
+// ============================================================================
+std::vector<HepMC3::ConstGenParticlePtr> LoKi::GenExtract::genParticles( const HepMC3::ConstGenVertexPtr &      vertex,
+                                                                       const LoKi::GenTypes::GCuts& cuts,
+                                                                       const HepMC3::Relatives &         range ) {
+  std::vector<HepMC3::ConstGenParticlePtr> result;
+  LoKi::Extract::genParticles( vertex, range, std::back_inserter( result ), cuts );
+  return result;
+}
+// ============================================================================
+// extract the particles from the vertex
+// ============================================================================
+std::vector<HepMC3::ConstGenParticlePtr> LoKi::GenExtract::genParticles( const HepMC3::ConstGenVertexPtr & vertex,
+                                                                       const HepMC3::Relatives &    range ) {
+  std::vector<HepMC3::ConstGenParticlePtr> result;
+  LoKi::Extract::genParticles( vertex, range, std::back_inserter( result ), LoKi::Objects::_VALID_ );
+  return result;
+}
+// ============================================================================
+// extract the particles from the event
+// ============================================================================
+std::vector<HepMC3::ConstGenParticlePtr> LoKi::GenExtract::genParticles( const HepMC3::ConstGenParticlePtr &    particle,
+                                                                       const LoKi::GenTypes::GCuts& cuts ) {
+  std::vector<HepMC3::ConstGenParticlePtr> result;
+  LoKi::Extract::genParticles( particle, std::back_inserter( result ), cuts );
+  return result;
+}
+// ============================================================================
+// The END
+// ============================================================================
diff --git a/Gen/LoKiGen/src/GenHybridEngine.cpp b/Gen/LoKiGen/src/GenHybridEngine.cpp
new file mode 100644
index 000000000..ac9ea91b7
--- /dev/null
+++ b/Gen/LoKiGen/src/GenHybridEngine.cpp
@@ -0,0 +1,138 @@
+/*****************************************************************************\
+* (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration      *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                             *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+// ============================================================================
+// Include files
+// ============================================================================
+// local
+// ============================================================================
+#include "LoKi/GenHybridEngine.h"
+#include "LoKi/GenHybridEngineActor.h"
+// ============================================================================
+/** @file
+ *  Implementation file for class LoKi::Hybrid::GenEngine
+ *
+ *  This file is a part of LoKi project -
+ *    "C++ ToolKit  for Smart and Friendly Physics Analysis"
+ *
+ *  The package has been designed with the kind help from
+ *  Galina PAKHLOVA and Sergey BARSUK.  Many bright ideas,
+ *  contributions and advices from G.Raven, J.van Tilburg,
+ *  A.Golutvin, P.Koppenburg have been used in the design.
+ *
+ *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+ *  @date 2004-06-30
+ *
+ */
+// ============================================================================
+namespace {
+  template <class TYPE>
+  inline StatusCode _process( const std::string& name, const TYPE& cut ) {
+    LoKi::Hybrid::GenEngineActor& actor = LoKi::Hybrid::GenEngineActor::instance();
+    return actor.process( name, cut );
+  }
+} // namespace
+// ============================================================================
+// predicates
+// ============================================================================
+// add the cut
+// ============================================================================
+StatusCode LoKi::Hybrid::GenEngine::process( const std::string& name, const LoKi::Types::GCuts& cut ) const {
+  return _process( name, cut );
+}
+// ============================================================================
+// add the cut
+// ============================================================================
+StatusCode LoKi::Hybrid::GenEngine::process( const std::string& name, const LoKi::Types::GVCuts& cut ) const {
+  return _process( name, cut );
+}
+// ============================================================================
+// functions
+// ============================================================================
+// add the function
+// ============================================================================
+StatusCode LoKi::Hybrid::GenEngine::process( const std::string& name, const LoKi::Types::GFunc& cut ) const {
+  return _process( name, cut );
+}
+// ============================================================================
+// add the function
+// ============================================================================
+StatusCode LoKi::Hybrid::GenEngine::process( const std::string& name, const LoKi::Types::GVFunc& cut ) const {
+  return _process( name, cut );
+}
+// ============================================================================
+// maps
+// ============================================================================
+// add the map
+// ============================================================================
+StatusCode LoKi::Hybrid::GenEngine::process( const std::string& name, const LoKi::Types::GMaps& cut ) const {
+  return _process( name, cut );
+}
+// ============================================================================
+// add the map
+// ============================================================================
+StatusCode LoKi::Hybrid::GenEngine::process( const std::string& name, const LoKi::Types::GVMaps& cut ) const {
+  return _process( name, cut );
+}
+// ============================================================================
+// pipe
+// ============================================================================
+// add the pipe
+// ============================================================================
+StatusCode LoKi::Hybrid::GenEngine::process( const std::string& name, const LoKi::Types::GPipes& cut ) const {
+  return _process( name, cut );
+}
+// ============================================================================
+// add the pipe
+// ============================================================================
+StatusCode LoKi::Hybrid::GenEngine::process( const std::string& name, const LoKi::Types::GVPipes& cut ) const {
+  return _process( name, cut );
+}
+// ============================================================================
+// fun-vals
+// ============================================================================
+// add the fun-val
+// ============================================================================
+StatusCode LoKi::Hybrid::GenEngine::process( const std::string& name, const LoKi::Types::GFunVals& cut ) const {
+  return _process( name, cut );
+}
+// ============================================================================
+// add the fun-val
+// ============================================================================
+StatusCode LoKi::Hybrid::GenEngine::process( const std::string& name, const LoKi::Types::GVFunVals& cut ) const {
+  return _process( name, cut );
+}
+// ============================================================================
+// cut-vals
+// ============================================================================
+// add the cut-val
+// ============================================================================
+StatusCode LoKi::Hybrid::GenEngine::process( const std::string& name, const LoKi::Types::GCutVals& cut ) const {
+  return _process( name, cut );
+}
+// ============================================================================
+// sources
+// ============================================================================
+// add the source
+// ============================================================================
+StatusCode LoKi::Hybrid::GenEngine::process( const std::string& name, const LoKi::Types::GSources& cut ) const {
+  return _process( name, cut );
+}
+// ============================================================================
+// add the source
+// ============================================================================
+StatusCode LoKi::Hybrid::GenEngine::process( const std::string& name, const LoKi::Types::GVSources& cut ) const {
+  return _process( name, cut );
+}
+// ============================================================================
+
+// ============================================================================
+// The END
+// ============================================================================
diff --git a/Gen/LoKiGen/src/GenHybridEngineActor.cpp b/Gen/LoKiGen/src/GenHybridEngineActor.cpp
new file mode 100644
index 000000000..da6c225ff
--- /dev/null
+++ b/Gen/LoKiGen/src/GenHybridEngineActor.cpp
@@ -0,0 +1,200 @@
+/*****************************************************************************\
+* (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration      *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                             *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+// ============================================================================
+// Include files
+// ============================================================================
+// STD & STL
+// ============================================================================
+#include <fstream>
+// ============================================================================
+// LoKi
+// ============================================================================
+#include "LoKi/GenHybridEngineActor.h"
+#include "LoKi/Report.h"
+// ============================================================================
+/** @file
+ *  Implementation file for class LoKi::Hybrid::GenEngineActor
+ *
+ *  This file is a part of LoKi project -
+ *    "C++ ToolKit  for Smart and Friendly Physics Analysis"
+ *
+ *  The package has been designed with the kind help from
+ *  Galina PAKHLOVA and Sergey BARSUK.  Many bright ideas,
+ *  contributions and advices from G.Raven, J.van Tilburg,
+ *  A.Golutvin, P.Koppenburg have been used in the design.
+ *
+ *  @date 2004-06-29
+ *  @author Vanya BELYAEV Ivan.Belyaev@itep.ru
+ */
+// ============================================================================
+// helper method to descrease number of lines
+// ============================================================================
+template <class TYPE>
+inline StatusCode LoKi::Hybrid::GenEngineActor::_add( const std::string& name, const TYPE& cut ) const {
+  if ( m_stack.empty() ) { return LoKi::Report::Error( "LoKi:Hybrid::GenEngineActor::addCut/Fun(): empty stack!" ); }
+  //
+  const Entry& entry = m_stack.top();
+  // check the tool
+  if ( !entry.first ) {
+    return LoKi::Report::Error( "LoKi:Hybrid::GenEngineActor::addCut/Fun(): LoKi::IGenHybridTool* is invalid!" );
+  }
+  // one more check
+  if ( name != entry.first->name() ) {
+    return LoKi::Report::Error( "LoKi:Hybrid::GenEngineActor::addCut/Fun() : mismatch in LoKi::IGenHybndrTool name!" );
+  }
+  // set the cut for the tool
+  entry.first->set( cut );
+  //
+  return StatusCode::SUCCESS;
+}
+// ============================================================================
+// accessor to the static instance
+// ============================================================================
+LoKi::Hybrid::GenEngineActor& LoKi::Hybrid::GenEngineActor::instance() {
+  static LoKi::Hybrid::GenEngineActor s_holder;
+  return s_holder;
+}
+// ============================================================================
+// disconnect the tool
+// ============================================================================
+StatusCode LoKi::Hybrid::GenEngineActor::disconnect( const LoKi::IGenHybridTool* factory ) {
+  if ( m_stack.empty() ) { return LoKi::Report::Error( "LoKi:Hybrid::GenEngineActor::disconnect: empty stack!" ); }
+  //
+  const Entry& entry = m_stack.top();
+  //
+  if ( entry.first == factory ) {
+    m_stack.pop();
+  } /// remove the last entry
+  else {
+    return LoKi::Report::Error( "LoKi::Hybrid::GenEngineActor::disconnect: mismatch in tools " );
+  }
+  ///
+  return StatusCode::SUCCESS;
+}
+// ============================================================================
+// connect the hybrid tool for code translation
+// ============================================================================
+StatusCode LoKi::Hybrid::GenEngineActor::connect( const LoKi::IGenHybridTool* factory, const LoKi::Context& context ) {
+  if ( !factory ) { return LoKi::Report::Error( "LoKi::Hybrid::GenEngineActor::connect: Invalid factory" ); }
+  m_stack.emplace( factory, context );
+  return StatusCode::SUCCESS;
+}
+// ============================================================================
+/* get the current context
+ *  contex is valid only inbetween <code>connect/disconnect</code>
+ *  @return the current active context
+ */
+// ============================================================================
+const LoKi::Context* LoKi::Hybrid::GenEngineActor::context() const {
+  if ( m_stack.empty() ) {
+    LoKi::Report::Error( "LoKi::Hybrid::GenEngineActor::context: empty stack" );
+    return nullptr;
+  }
+  const Entry& last = m_stack.top();
+  return &last.second;
+}
+// ============================================================================
+// predicates
+// ============================================================================
+// propagate the cut to the tool
+// ============================================================================
+StatusCode LoKi::Hybrid::GenEngineActor::process( const std::string& name, const LoKi::Types::GCuts& cut ) const {
+  return _add( name, cut );
+}
+// ============================================================================
+// propagate the cut to the tool
+// ============================================================================
+StatusCode LoKi::Hybrid::GenEngineActor::process( const std::string& name, const LoKi::Types::GVCuts& cut ) const {
+  return _add( name, cut );
+}
+// ============================================================================
+// functions
+// ============================================================================
+// propagate the function to the tool
+// ============================================================================
+StatusCode LoKi::Hybrid::GenEngineActor::process( const std::string& name, const LoKi::Types::GFunc& func ) const {
+  return _add( name, func );
+}
+// ============================================================================
+// propagate the function to the tool
+// ============================================================================
+StatusCode LoKi::Hybrid::GenEngineActor::process( const std::string& name, const LoKi::Types::GVFunc& func ) const {
+  return _add( name, func );
+}
+// ============================================================================
+// maps
+// ============================================================================
+// propagate the map to the tool
+// ============================================================================
+StatusCode LoKi::Hybrid::GenEngineActor::process( const std::string& name, const LoKi::Types::GMaps& func ) const {
+  return _add( name, func );
+}
+// ============================================================================
+// propagate the map to the tool
+// ============================================================================
+StatusCode LoKi::Hybrid::GenEngineActor::process( const std::string& name, const LoKi::Types::GVMaps& func ) const {
+  return _add( name, func );
+}
+// ============================================================================
+// pipes
+// ============================================================================
+// propagate the pipe to the tool
+// ============================================================================
+StatusCode LoKi::Hybrid::GenEngineActor::process( const std::string& name, const LoKi::Types::GPipes& func ) const {
+  return _add( name, func );
+}
+// ============================================================================
+// propagate the pipe  to the tool
+// ============================================================================
+StatusCode LoKi::Hybrid::GenEngineActor::process( const std::string& name, const LoKi::Types::GVPipes& func ) const {
+  return _add( name, func );
+}
+// ============================================================================
+// fun-vals
+// ============================================================================
+// propagate the fun-val to the tool
+// ============================================================================
+StatusCode LoKi::Hybrid::GenEngineActor::process( const std::string& name, const LoKi::Types::GFunVals& func ) const {
+  return _add( name, func );
+}
+// ============================================================================
+// propagate the fun-val to the tool
+// ============================================================================
+StatusCode LoKi::Hybrid::GenEngineActor::process( const std::string& name, const LoKi::Types::GVFunVals& func ) const {
+  return _add( name, func );
+}
+// ============================================================================
+// cut-vals
+// ============================================================================
+// propagate the cut-val to the tool
+// ============================================================================
+StatusCode LoKi::Hybrid::GenEngineActor::process( const std::string& name, const LoKi::Types::GCutVals& func ) const {
+  return _add( name, func );
+}
+// ============================================================================
+// sources
+// ============================================================================
+// propagate the source to the tool
+// ============================================================================
+StatusCode LoKi::Hybrid::GenEngineActor::process( const std::string& name, const LoKi::Types::GSources& func ) const {
+  return _add( name, func );
+}
+// ============================================================================
+// propagate the source to the tool
+// ============================================================================
+StatusCode LoKi::Hybrid::GenEngineActor::process( const std::string& name, const LoKi::Types::GVSources& func ) const {
+  return _add( name, func );
+}
+// ============================================================================
+
+// ============================================================================
+// The END
+// ============================================================================
diff --git a/Gen/LoKiGen/src/GenHybridLock.cpp b/Gen/LoKiGen/src/GenHybridLock.cpp
new file mode 100644
index 000000000..1df6cc2e6
--- /dev/null
+++ b/Gen/LoKiGen/src/GenHybridLock.cpp
@@ -0,0 +1,45 @@
+/*****************************************************************************\
+* (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration      *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                             *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+// ============================================================================
+// Include files
+// ============================================================================
+// LoKi
+// ============================================================================
+#include "LoKi/GenHybridLock.h"
+#include "LoKi/GenHybridEngineActor.h"
+#include "LoKi/Report.h"
+// ============================================================================
+/** @file
+ *  Implementation file for class LoKi::Hybrid::GenLock
+ *  @date 2007-06-10
+ *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+ */
+// ============================================================================
+// contructor
+// ============================================================================
+LoKi::Hybrid::GenLock::GenLock( const IGenHybridTool* tool, const LoKi::Context& context ) : m_tool( tool ) {
+  LoKi::Hybrid::GenEngineActor& actor = LoKi::Hybrid::GenEngineActor::instance();
+  // connect the tool to the actor
+  StatusCode sc = actor.connect( m_tool.getObject(), context );
+  if ( sc.isFailure() ) { LoKi::Report::Error( "LoKi::Hybrid::GenLock: error from connectTool", sc ).ignore(); }
+}
+// ============================================================================
+// destructor
+// ============================================================================
+LoKi::Hybrid::GenLock::~GenLock() {
+  LoKi::Hybrid::GenEngineActor& actor = LoKi::Hybrid::GenEngineActor::instance();
+  // connect the tool to the actor
+  StatusCode sc = actor.disconnect( m_tool.getObject() );
+  if ( sc.isFailure() ) { LoKi::Report::Error( "LoKi::Hybrid::GenLock: error from releaseTool", sc ).ignore(); }
+}
+// ============================================================================
+// The END
+// ============================================================================
diff --git a/Gen/LoKiGen/src/GenKinematics.cpp b/Gen/LoKiGen/src/GenKinematics.cpp
new file mode 100644
index 000000000..ca1b1a092
--- /dev/null
+++ b/Gen/LoKiGen/src/GenKinematics.cpp
@@ -0,0 +1,141 @@
+/*****************************************************************************\
+* (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration      *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                             *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+// ============================================================================
+// Include files
+// ============================================================================
+// LoKiCore
+// ============================================================================
+#include "LoKi/Constants.h"
+#include "LoKi/Report.h"
+// ============================================================================
+// LoKiGen
+// ============================================================================
+#include "LoKi/GenKinematics.h"
+// ============================================================================
+/** @file
+ *
+ * Implementation file for class : GenKinematics
+ *
+ *  This file is a part of LoKi project -
+ *    "C++ ToolKit  for Smart and Friendly Physics Analysis"
+ *
+ *  The package has been designed with the kind help from
+ *  Galina PAKHLOVA and Sergey BARSUK.  Many bright ideas,
+ *  contributions and advices from G.Raven, J.van Tilburg,
+ *  A.Golutvin, P.Koppenburg have been used in the design.
+ *
+ *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+ *  @date 2001-01-23
+ */
+// ============================================================================
+/*  trivial function to evaluate the mass HepMC3::GenParticle
+ *  @param  p particle
+ *  @return invariant mass
+ *  @see HepMC3::GenParticle
+ *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+ *  @date 2006-01-17
+ */
+// ============================================================================
+double LoKi::GenKinematics::mass( const HepMC3::ConstGenParticlePtr & p ) {
+  if ( !p ) {
+    LoKi::Report::Error( "mass(HepMC3::GenParticlePtr),invaild argument,return 'InvalidMass'" );
+    return LoKi::Constants::InvalidMass;
+  }
+  return LoKi::Kinematics::mass( LoKi::LorentzVector( p->momentum() ) );
+}
+// ============================================================================
+/*  trivial function to evaluate the mass HepMC3::GenParticle
+ *  @param  p1 the first particle
+ *  @param  p2 the second particle
+ *  @return invariant mass
+ *  @see HepMC3::GenParticle
+ *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+ *  @date 2006-01-17
+ */
+// ============================================================================
+double LoKi::GenKinematics::mass( const HepMC3::ConstGenParticlePtr & p1, HepMC3::ConstGenParticlePtr p2 ) {
+  if ( !p1 ) {
+    LoKi::Report::Error( "mass(2*HepMC3::GenParticlePtr),invaild argument 1,return 'InvalidMass'" );
+    return LoKi::Constants::InvalidMass;
+  }
+  if ( !p2 ) {
+    LoKi::Report::Error( "mass(2*HepMC3::GenParticlePtr),invaild argument 2,return'InvalidMass'" );
+    return LoKi::Constants::InvalidMass;
+  }
+  //
+  return LoKi::Kinematics::mass( LoKi::LorentzVector( p1->momentum() ), LoKi::LorentzVector( p2->momentum() ) );
+}
+// ============================================================================
+/*  trivial function to evaluate the mass HepMC3::GenParticle
+ *  @param  p1 the first particle
+ *  @param  p2 the third particle
+ *  @param  p3 the second particle
+ *  @return invariant mass
+ *  @see HepMC3::GenParticle
+ *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+ *  @date 2006-01-17
+ */
+// ============================================================================
+double LoKi::GenKinematics::mass( const HepMC3::ConstGenParticlePtr & p1, HepMC3::ConstGenParticlePtr p2,
+                                  HepMC3::ConstGenParticlePtr p3 ) {
+  if ( !p1 ) {
+    LoKi::Report::Error( "mass(3*HepMC3::GenParticlePtr),invaild argument 1,return 'InvalidMass'" );
+    return LoKi::Constants::InvalidMass;
+  }
+  if ( !p2 ) {
+    LoKi::Report::Error( "mass(3*HepMC3::GenParticlePtr),invaild argument 2,return 'InvalidMass'" );
+    return LoKi::Constants::InvalidMass;
+  }
+  if ( !p3 ) {
+    LoKi::Report::Error( "mass(3*HepMC3::GenParticlePtr),invaild argument 3,return 'InvalidMass'" );
+    return LoKi::Constants::InvalidMass;
+  }
+  //
+  return LoKi::Kinematics::mass( LoKi::LorentzVector( p1->momentum() ), LoKi::LorentzVector( p2->momentum() ),
+                                 LoKi::LorentzVector( p3->momentum() ) );
+}
+// ============================================================================
+/*  trivial function to evaluate the mass HepMC3::GenParticle
+ *  @param  p1 the first particle
+ *  @param  p2 the second particle
+ *  @param  p3 the third  particle
+ *  @param  p3 the fourth  particle
+ *  @return invariant mass
+ *  @see HepMC3::GenParticle
+ *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+ *  @date 2006-01-17
+ */
+// ============================================================================
+double LoKi::GenKinematics::mass( const HepMC3::ConstGenParticlePtr & p1, HepMC3::ConstGenParticlePtr p2,
+                                  HepMC3::ConstGenParticlePtr p3, HepMC3::ConstGenParticlePtr p4 ) {
+  if ( !p1 ) {
+    LoKi::Report::Error( "mass(4*HepMC3::GenParticlePtr),invaild argument 1,return 'InvalidMass'" );
+    return LoKi::Constants::InvalidMass;
+  }
+  if ( !p2 ) {
+    LoKi::Report::Error( "mass(4*HepMC3::GenParticlePtr),invaild argument 2,return 'InvalidMass'" );
+    return LoKi::Constants::InvalidMass;
+  }
+  if ( !p3 ) {
+    LoKi::Report::Error( "mass(4*HepMC3::GenParticlePtr),invaild argument 3,return 'InvalidMass'" );
+    return LoKi::Constants::InvalidMass;
+  }
+  if ( !p4 ) {
+    LoKi::Report::Error( "mass(4*HepMC3::GenParticlePtr),invaild argument 4,return 'InvalidMass'" );
+    return LoKi::Constants::InvalidMass;
+  }
+  //
+  return LoKi::Kinematics::mass( LoKi::LorentzVector( p1->momentum() ), LoKi::LorentzVector( p2->momentum() ),
+                                 LoKi::LorentzVector( p3->momentum() ), LoKi::LorentzVector( p4->momentum() ) );
+}
+// ============================================================================
+// The END
+// ============================================================================
diff --git a/Gen/LoKiGen/src/GenMoniDicts.cpp b/Gen/LoKiGen/src/GenMoniDicts.cpp
new file mode 100644
index 000000000..536b6cad0
--- /dev/null
+++ b/Gen/LoKiGen/src/GenMoniDicts.cpp
@@ -0,0 +1,24 @@
+/*****************************************************************************\
+* (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration      *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                             *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+// ============================================================================
+// Include files
+// ============================================================================
+// LoKi
+// ============================================================================
+#include "LoKi/Monitoring.h"
+// ============================================================================
+#include "LoKi/GenMoniDicts.h"
+#include "LoKi/GenTypes.h"
+// ========================================================================
+
+// ============================================================================
+// The END
+// ============================================================================
diff --git a/Gen/LoKiGen/src/GenPIDOperators.cpp b/Gen/LoKiGen/src/GenPIDOperators.cpp
new file mode 100644
index 000000000..c28e11998
--- /dev/null
+++ b/Gen/LoKiGen/src/GenPIDOperators.cpp
@@ -0,0 +1,266 @@
+/*****************************************************************************\
+* (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration      *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                             *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+// ============================================================================
+// Include files
+// ============================================================================
+// ST D& STL
+// ============================================================================
+#include <set>
+// ============================================================================
+// Local
+// ============================================================================
+#include "LoKi/GenPIDOperators.h"
+#include "LoKi/GenParticles.h"
+#include "LoKi/ParticleProperties.h"
+// ============================================================================
+/** @file
+ *
+ *  Implementation file for functions from the file LoKi/GenPIDOperators.h
+ *
+ *  This file is a part of LoKi project -
+ *    "C++ ToolKit  for Smart and Friendly Physics Analysis"
+ *
+ *  The package has been designed with the kind help from
+ *  Galina PAKHLOVA and Sergey BARSUK.  Many bright ideas,
+ *  contributions and advices from G.Raven, J.van Tilburg,
+ *  A.Golutvin, P.Koppenburg have been used in the design.
+ *
+ *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+ *  @date 2001-01-23
+ */
+// ============================================================================
+namespace LoKi {
+  // ==========================================================================
+  namespace GenParticles {
+    // ========================================================================
+
+    // ========================================================================
+    // MCID ==
+    // ========================================================================
+    LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator==( const LoKi::GenParticles::Identifier& /* id  */, const LHCb::ParticleID& pid ) {
+      return LoKi::GenParticles::IsID( pid );
+    }
+    // ========================================================================
+    LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator==( const LoKi::GenParticles::Identifier& /* id */, const long pid ) {
+      return LoKi::GenParticles::IsID( pid );
+    }
+    // ========================================================================
+    LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator==( const LoKi::GenParticles::Identifier& /* id */, const unsigned long pid ) {
+      return LoKi::GenParticles::IsID( pid );
+    }
+    // ========================================================================
+    LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator==( const LoKi::GenParticles::Identifier& /* id */, const std::string& pid ) {
+      return LoKi::GenParticles::IsID( pid );
+    }
+    // ========================================================================
+    LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator==( const LoKi::GenParticles::Identifier& /* id  */, const std::vector<LHCb::ParticleID>& pid ) {
+      return LoKi::GenParticles::IsID( pid );
+    }
+    // ========================================================================
+    LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator==( const LoKi::GenParticles::Identifier& /* id */, const std::vector<int>& pid ) {
+      return LoKi::GenParticles::IsID( pid );
+    }
+    // ========================================================================
+    LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator==( const LoKi::GenParticles::Identifier& /* id */, const std::vector<unsigned int>& pid ) {
+      return LoKi::GenParticles::IsID( pid );
+    }
+    // ========================================================================
+    LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator==( const LoKi::GenParticles::Identifier& /* id */, const std::vector<long>& pid ) {
+      return LoKi::GenParticles::IsID( pid );
+    }
+    // ========================================================================
+    LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator==( const LoKi::GenParticles::Identifier& /* id */, const std::vector<unsigned long>& pid ) {
+      return LoKi::GenParticles::IsID( pid );
+    }
+    // ========================================================================
+    LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator==( const LoKi::GenParticles::Identifier& /* id */, const std::vector<std::string>& pid ) {
+      return LoKi::GenParticles::IsID( pid );
+    }
+    // ========================================================================
+
+    // ========================================================================
+    // MCABSID ==
+    // ========================================================================
+    LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator==( const LoKi::GenParticles::AbsIdentifier& /* id  */, const LHCb::ParticleID& pid ) {
+      return LoKi::GenParticles::IsAbsID( pid );
+    }
+    // ========================================================================
+    LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator==( const LoKi::GenParticles::AbsIdentifier& /* id */, const long pid ) {
+      return LoKi::GenParticles::IsAbsID( pid );
+    }
+    // ========================================================================
+    LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator==( const LoKi::GenParticles::AbsIdentifier& /* id */, const unsigned long pid ) {
+      return LoKi::GenParticles::IsAbsID( pid );
+    }
+    LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    // ========================================================================
+    operator==( const LoKi::GenParticles::AbsIdentifier& /* id */, const std::string& pid ) {
+      return LoKi::GenParticles::IsAbsID( pid );
+    }
+    // ========================================================================
+    LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator==( const LoKi::GenParticles::AbsIdentifier& /* id  */, const std::vector<LHCb::ParticleID>& pid ) {
+      return LoKi::GenParticles::IsAbsID( pid );
+    }
+    // ========================================================================
+    LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator==( const LoKi::GenParticles::AbsIdentifier& /* id */, const std::vector<int>& pid ) {
+      return LoKi::GenParticles::IsAbsID( pid );
+    }
+    // ========================================================================
+    LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator==( const LoKi::GenParticles::AbsIdentifier& /* id */, const std::vector<unsigned int>& pid ) {
+      return LoKi::GenParticles::IsAbsID( pid );
+    }
+    // ========================================================================
+    LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator==( const LoKi::GenParticles::AbsIdentifier& /* id */, const std::vector<long>& pid ) {
+      return LoKi::GenParticles::IsAbsID( pid );
+    }
+    // ========================================================================
+    LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator==( const LoKi::GenParticles::AbsIdentifier& /* id */, const std::vector<unsigned long>& pid ) {
+      return LoKi::GenParticles::IsAbsID( pid );
+    }
+    // ========================================================================
+    LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator==( const LoKi::GenParticles::AbsIdentifier& /* id */, const std::vector<std::string>& pid ) {
+      return LoKi::GenParticles::IsAbsID( pid );
+    }
+    // ========================================================================
+
+    // ========================================================================
+    // MCID !=
+    // ========================================================================
+    LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator!=( const LoKi::GenParticles::Identifier& /* id  */, const LHCb::ParticleID& pid ) {
+      return LoKi::GenParticles::IsNotID( pid );
+    }
+    // ========================================================================
+    LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator!=( const LoKi::GenParticles::Identifier& /* id */, const long pid ) {
+      return LoKi::GenParticles::IsNotID( pid );
+    }
+    // ========================================================================
+    LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator!=( const LoKi::GenParticles::Identifier& /* id */, const unsigned long pid ) {
+      return LoKi::GenParticles::IsNotID( pid );
+    }
+    // ========================================================================
+    LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator!=( const LoKi::GenParticles::Identifier& /* id */, const std::string& pid ) {
+      return LoKi::GenParticles::IsNotID( pid );
+    }
+    // ========================================================================
+    LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator!=( const LoKi::GenParticles::Identifier& /* id  */, const std::vector<LHCb::ParticleID>& pid ) {
+      return LoKi::GenParticles::IsNotID( pid );
+    }
+    // ========================================================================
+    LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator!=( const LoKi::GenParticles::Identifier& /* id */, const std::vector<int>& pid ) {
+      return LoKi::GenParticles::IsNotID( pid );
+    }
+    // ========================================================================
+    LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator!=( const LoKi::GenParticles::Identifier& /* id */, const std::vector<unsigned int>& pid ) {
+      return LoKi::GenParticles::IsNotID( pid );
+    }
+    // ========================================================================
+    LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator!=( const LoKi::GenParticles::Identifier& /* id */, const std::vector<long>& pid ) {
+      return LoKi::GenParticles::IsNotID( pid );
+    }
+    // ========================================================================
+    LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator!=( const LoKi::GenParticles::Identifier& /* id */, const std::vector<unsigned long>& pid ) {
+      return LoKi::GenParticles::IsNotID( pid );
+    }
+    // ========================================================================
+    LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator!=( const LoKi::GenParticles::Identifier& /* id */, const std::vector<std::string>& pid ) {
+      return LoKi::GenParticles::IsNotID( pid );
+    }
+    // ========================================================================
+    // ========================================================================
+    // MCABSID !=
+    // ========================================================================
+    LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator!=( const LoKi::GenParticles::AbsIdentifier& /* id  */, const LHCb::ParticleID& pid ) {
+      return LoKi::GenParticles::IsNotAbsID( pid );
+    }
+    // ========================================================================
+    LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator!=( const LoKi::GenParticles::AbsIdentifier& /* id */, const long pid ) {
+      return LoKi::GenParticles::IsNotAbsID( pid );
+    }
+    // ========================================================================
+    LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator!=( const LoKi::GenParticles::AbsIdentifier& /* id */, const unsigned long pid ) {
+      return LoKi::GenParticles::IsNotAbsID( pid );
+    }
+    LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    // ========================================================================
+    operator!=( const LoKi::GenParticles::AbsIdentifier& /* id */, const std::string& pid ) {
+      return LoKi::GenParticles::IsNotAbsID( pid );
+    }
+    // ========================================================================
+    LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator!=( const LoKi::GenParticles::AbsIdentifier& /* id  */, const std::vector<LHCb::ParticleID>& pid ) {
+      return LoKi::GenParticles::IsNotAbsID( pid );
+    }
+    // ========================================================================
+    LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator!=( const LoKi::GenParticles::AbsIdentifier& /* id */, const std::vector<int>& pid ) {
+      return LoKi::GenParticles::IsNotAbsID( pid );
+    }
+    // ========================================================================
+    LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator!=( const LoKi::GenParticles::AbsIdentifier& /* id */, const std::vector<unsigned int>& pid ) {
+      return LoKi::GenParticles::IsNotAbsID( pid );
+    }
+    // ========================================================================
+    LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator!=( const LoKi::GenParticles::AbsIdentifier& /* id */, const std::vector<long>& pid ) {
+      return LoKi::GenParticles::IsNotAbsID( pid );
+    }
+    // ========================================================================
+    LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator!=( const LoKi::GenParticles::AbsIdentifier& /* id */, const std::vector<unsigned long>& pid ) {
+      return LoKi::GenParticles::IsNotAbsID( pid );
+    }
+    // ========================================================================
+    LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::PredicateFromPredicate
+    operator!=( const LoKi::GenParticles::AbsIdentifier& /* id */, const std::vector<std::string>& pid ) {
+      return LoKi::GenParticles::IsNotAbsID( pid );
+    }
+    // ========================================================================
+
+    // ========================================================================
+  } // namespace GenParticles
+  // ==========================================================================
+} // namespace LoKi
+// ============================================================================
+// The END
+// ============================================================================
diff --git a/Gen/LoKiGen/src/GenParticles.cpp b/Gen/LoKiGen/src/GenParticles.cpp
new file mode 100644
index 000000000..6f4305bc3
--- /dev/null
+++ b/Gen/LoKiGen/src/GenParticles.cpp
@@ -0,0 +1,1486 @@
+/*****************************************************************************\
+* (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration      *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                             *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+// ============================================================================
+// Include files
+// ============================================================================
+// STD & STL
+// ============================================================================
+#include <cmath>
+// ============================================================================
+// GaudiKernel
+// ============================================================================
+#include "GaudiKernel/IToolSvc.h"
+#include "GaudiKernel/SmartIF.h"
+// ============================================================================
+// PartProp
+// ============================================================================
+#include "Kernel/IParticlePropertySvc.h"
+#include "Kernel/Nodes.h"
+// ============================================================================
+// LoKi
+// ============================================================================
+#include "LoKi/GenToCpp.h"
+#include "LoKi/Constants.h"
+#include "LoKi/ParticleProperties.h"
+#include "LoKi/Services.h"
+#include "LoKi/Trees.h"
+#include "LoKi/valid.h"
+// this must be included after the others
+#include "LoKi/MoreFunctions.h"
+// ============================================================================
+// LoKiGen
+// ============================================================================
+#include "LoKi/GenAlgs.h"
+#include "LoKi/GenExtract.h"
+#include "LoKi/GenOscillated.h"
+#include "LoKi/GenParticles.h"
+#include "LoKi/IGenDecay.h"
+// ============================================================================
+#include "LoKi/CmpBarCode.h"
+// ============================================================================
+// Boost
+// ============================================================================
+#include "boost/format.hpp"
+// ============================================================================
+#include "HepMCUtils/HepMCUtils.h"
+/** @file
+ *
+ *  Implementation of the functions form namespace LoKi::GenParticles
+ *
+ *  This file is a part of LoKi project -
+ *    "C++ ToolKit  for Smart and Friendly Physics Analysis"
+ *
+ *  The package has been designed with the kind help from
+ *  Galina PAKHLOVA and Sergey BARSUK.  Many bright ideas,
+ *  contributions and advices from G.Raven, J.van Tilburg,
+ *  A.Golutvin, P.Koppenburg have been used in the design.
+ *
+ *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+ *  @date 2001-01-23
+ */
+namespace LoKi {
+  namespace GenParticles {
+    // ============================================================================
+    //  clone method (mandatory!)
+    // ============================================================================
+    BarCode* BarCode::clone() const { return new LoKi::GenParticles::BarCode( *this ); }
+    // ============================================================================
+    //  the only one essential method
+    // ============================================================================
+    double BarCode::operator()( const HepMC3::ConstGenParticlePtr & p ) const {
+      if ( UNLIKELY( !p ) ) {
+        Error( "Invalid HepMC3::GenParticle, return 0 " ).ignore();
+        return 0; // RETURN
+      }
+      return p->id(); // RETURN
+    }
+    // ============================================================================
+    //  "SHORT" representation, @see LoKi::AuxFunBase
+    // ============================================================================
+    std::ostream& BarCode::fillStream( std::ostream& s ) const { return s << "GBAR"; }
+    // ============================================================================
+    //  MANDATORY: clone method ("virtual" constructor")
+    // ============================================================================
+    Identifier* Identifier::clone() const { return new Identifier( *this ); }
+    // ============================================================================
+    //  MANDATORY: the only one essential method
+    // ============================================================================
+    double Identifier::operator()( const HepMC3::ConstGenParticlePtr & p ) const {
+      if ( UNLIKELY( !p ) ) {
+        Error( "HepMC3::GenParticlePtr points to NULL, return InvalidID" ).ignore();
+        return LoKi::Constants::InvalidID;
+      }
+      return p->pdg_id();
+    }
+    // ============================================================================
+    //  "SHORT" representation, @see LoKi::AuxFunBase
+    // ============================================================================
+    std::ostream& Identifier::fillStream( std::ostream& s ) const { return s << "GID"; }
+    // ============================================================================
+    //  MANDATORY: clone method ("virtual" constructor")
+    // ============================================================================
+    Status* Status::clone() const { return new Status( *this ); }
+    // ============================================================================
+    //  MANDATORY: the only one essential method
+    // ============================================================================
+    double Status::operator()( const HepMC3::ConstGenParticlePtr & p ) const {
+      if ( UNLIKELY( !p ) ) {
+        Error( "HepMC3::ConstGenParticlePtr & points to NULL, return -1000 " ).ignore();
+        return -1000;
+      }
+      return p->status();
+    }
+    // ============================================================================
+    //  "SHORT" representation, @see LoKi::AuxFunBase
+    // ============================================================================
+    std::ostream& Status::fillStream( std::ostream& s ) const { return s << "GSTATUS"; }
+    // ============================================================================
+
+    // ============================================================================
+    //  MANDATORY: clone method ("virtual" constructor")
+    // ============================================================================
+    AbsIdentifier* AbsIdentifier::clone() const { return new LoKi::GenParticles::AbsIdentifier( *this ); }
+    // ============================================================================
+    //  MANDATORY: the only one essential method
+    // ============================================================================
+    double AbsIdentifier::operator()( const HepMC3::ConstGenParticlePtr & p ) const {
+      if ( UNLIKELY( !p ) ) {
+        Error( "HepMC3::ConstGenParticlePtr & points to NULL, return InvalidID" ).ignore();
+        return LoKi::Constants::InvalidID;
+      }
+      return std::abs( p->pdg_id() );
+    }
+    // ============================================================================
+    //  "SHORT" representation, @see LoKi::AuxFunBase
+    // ============================================================================
+    std::ostream& AbsIdentifier::fillStream( std::ostream& s ) const { return s << "GABSID"; }
+    // ============================================================================
+
+    // ============================================================================
+    // MANDATORY: clone method ("virtual constructor")
+    // ============================================================================
+    ValidEndVertex* ValidEndVertex::clone() const { return new LoKi::GenParticles::ValidEndVertex( *this ); }
+    // ============================================================================
+    //  MANDATORY: the only one essential method
+    // ============================================================================
+    bool ValidEndVertex::operator()( const HepMC3::ConstGenParticlePtr & p ) const {
+      if ( UNLIKELY( !p ) ) {
+        Error( "HepMC3::ConstGenParticlePtr & points to NULL, return 'false'" ).ignore();
+        return false;
+      }
+      return LoKi::valid( p->end_vertex() );
+    }
+    // ============================================================================
+    //  "SHORT" representation, @see LoKi::AuxFunBase
+    // ============================================================================
+    std::ostream& ValidEndVertex::fillStream( std::ostream& s ) const { return s << "GVEV"; }
+    // ============================================================================
+    //  constructor
+    // ============================================================================
+    MomentumDistance::MomentumDistance( const double px, const double py, const double pz, const double e )
+        : LoKi::AuxFunBase( std::tie( px, py, pz, e ) ) {
+      m_vct.SetXYZT( px, py, pz, e );
+    }
+    // ============================================================================
+    /*  constructor
+     *  @param vct the reference 4-momentum
+     */
+    // ============================================================================
+    MomentumDistance::MomentumDistance( const LoKi::LorentzVector& vct )
+        : LoKi::AuxFunBase( std::tie( vct ) ), m_vct( vct ) {}
+    // ============================================================================
+    //  MANDATORY: clone function ("virtual constructor")
+    // ============================================================================
+    MomentumDistance* MomentumDistance::clone() const { return new LoKi::GenParticles::MomentumDistance( *this ); }
+    // ============================================================================
+    //  MANDATORY: the only one essential method
+    // ============================================================================
+    double MomentumDistance::operator()( const HepMC3::ConstGenParticlePtr & p ) const {
+      if ( UNLIKELY( !p ) ) {
+        Error( "Invalid HepMC3::GenParticlePtr, return (InvalidMomentum)^2" ).ignore();
+        return LoKi::Constants::InvalidMomentum * LoKi::Constants::InvalidMomentum;
+      }
+      const double de = ( p->momentum().e() - m_vct.e() );
+      const double dx = ( p->momentum().x() - m_vct.x() );
+      const double dy = ( p->momentum().y() - m_vct.y() );
+      const double dz = ( p->momentum().z() - m_vct.z() );
+      return de * de + dx * dx + dy * dy + dz * dz;
+    }
+    // ============================================================================
+    //  "SHORT" representation, @see LoKi::AuxFunBase
+    // ============================================================================
+    std::ostream& MomentumDistance::fillStream( std::ostream& s ) const {
+      return s << "GMOMDIST(" << m_vct.Px() << "," << m_vct.Py() << "," << m_vct.Pz() << "," << m_vct.E() << ")";
+    }
+    // ============================================================================
+    /*  constructor from theta and phi
+     *  @param theta theta angle for the direction
+     *  @param phi phi angle for the direction
+     */
+    // ============================================================================
+    TransverseMomentumRel::TransverseMomentumRel( const double theta, const double phi )
+        : LoKi::AuxFunBase( std::tie( theta, phi ) ) {
+      m_vct.SetXYZ( ::sin( theta ) * ::cos( phi ), ::sin( theta ) * ::sin( phi ), ::cos( theta ) );
+    }
+    // ============================================================================
+    /*  constructor from x,y,z
+     *  @param x x-component of the direction vector
+     *  @param y y-component of the direction vector
+     *  @param z z-component of the direction vector
+     */
+    // ============================================================================
+    TransverseMomentumRel::TransverseMomentumRel( const double x, const double y, const double z )
+        : LoKi::AuxFunBase( std::tie( x, y, z ) ) {
+      m_vct.SetXYZ( x, y, z );
+    }
+    // ============================================================================
+    /*  constructor
+     *  @param vct direction vector
+     *  @see LoKi::ThreeVector
+     */
+    // ============================================================================
+    TransverseMomentumRel::TransverseMomentumRel( const LoKi::ThreeVector& vct )
+        : LoKi::AuxFunBase( std::tie( vct ) ), m_vct( vct ) {}
+    // ============================================================================
+    /*  constructor
+     *  @param vct direction vector
+     *  @see LoKi::LorentzVector
+     */
+    // ============================================================================
+    TransverseMomentumRel::TransverseMomentumRel( const LoKi::LorentzVector& vct )
+        : LoKi::AuxFunBase( std::tie( vct ) ), m_vct( vct.Vect() ) {}
+    // ============================================================================
+    //  MANDATORY: clone function ("virtual constructor")
+    // ============================================================================
+    TransverseMomentumRel* TransverseMomentumRel::clone() const {
+      return new LoKi::GenParticles::TransverseMomentumRel( *this );
+    }
+    // ============================================================================
+    //  MANDATORY: the only one essential method
+    // ============================================================================
+    double TransverseMomentumRel::operator()( const HepMC3::ConstGenParticlePtr & p ) const {
+      if ( UNLIKELY( !p ) ) {
+        Error( "Invalid HepMC3::GenParticlePtr, return 'InvalidMomentum'" ).ignore();
+        return LoKi::Constants::InvalidMomentum;
+      }
+      const double            b2 = m_vct.mag2();
+      const LoKi::ThreeVector va( p->momentum().x(), p->momentum().y(), p->momentum().z() );
+      if ( 0 == b2 ) { return ::sqrt( va.mag2() ); }
+      const double            ab = va.Dot( m_vct ) / b2;
+      const LoKi::ThreeVector vd = va - m_vct * ab;
+      return ::sqrt( vd.mag2() );
+    }
+    // ============================================================================
+    //  "SHORT" representation, @see LoKi::AuxFunBase
+    // ============================================================================
+    std::ostream& TransverseMomentumRel::fillStream( std::ostream& s ) const {
+      return s << "GPTDIR(" << m_vct.Theta() << "," << m_vct.Phi() << ")";
+    }
+    // ============================================================================
+    /*  constructor from particle ("head")
+     *  @param p pointer to HepMC3::GenParticle
+     */
+    // ============================================================================
+    FromHepMCTree::FromHepMCTree( const HepMC3::ConstGenParticlePtr & p ) { _add( p ); }
+    // ============================================================================
+    //  constructor from range of particles
+    // ============================================================================
+    FromHepMCTree::FromHepMCTree( const LoKi::Types::GRange& r ) { _add( r.begin(), r.end() ); }
+    // ============================================================================
+    //  constructor from range of particles
+    // ============================================================================
+    FromHepMCTree::FromHepMCTree( const LoKi::GenTypes::GenContainer& r ) { _add( r.begin(), r.end() ); }
+    // ============================================================================
+    /*  constructor from vertex  ("head")
+     *  @param v pointer to HepMC3::GenParticle
+     */
+    // ============================================================================
+    FromHepMCTree::FromHepMCTree( const HepMC3::ConstGenVertexPtr & v ) { _add( v ); }
+    // ============================================================================
+    void FromHepMCTree::_add( const HepMC3::ConstGenParticlePtr & p ) {
+      if ( 0 != p ) { _add( p->end_vertex() ); }
+    }
+    void FromHepMCTree::_add( const HepMC3::ConstGenVertexPtr & v ) {
+      if ( v ) { m_vertices.push_back( v ); }
+    }
+    // ============================================================================
+    FromHepMCTree& FromHepMCTree::remove( const HepMC3::ConstGenVertexPtr & vertex ) {
+      auto ifind = std::remove( m_vertices.begin(), m_vertices.end(), vertex );
+      m_vertices.erase( ifind, m_vertices.end() );
+      return *this;
+    }
+    // ============================================================================
+    FromHepMCTree& FromHepMCTree::remove( const HepMC3::ConstGenParticlePtr & particle ) {
+      if ( 0 == particle ) { return *this; }
+      return remove( particle->end_vertex() );
+    }
+    // ============================================================================
+    //  MANDATORY: clone method ("virtual constructor")
+    // ============================================================================
+    FromHepMCTree* FromHepMCTree::clone() const { return new LoKi::GenParticles::FromHepMCTree( *this ); }
+    // ============================================================================
+    //  MANDATORY: the only one essential method
+    // ============================================================================
+    bool FromHepMCTree::operator()( const HepMC3::ConstGenParticlePtr & p ) const {
+      if ( 0 == p ) {
+        Error( " HepMC3::ConstGenParticlePtr & points to NULL, return 'false' " ).ignore();
+        return false; // RETURN
+      }
+      if ( m_vertices.empty() ) {
+        // Error ( " empty list of vertices , return 'false' " ) ;
+        return false; // RETURN
+      }
+      // loop over vertices
+      for ( auto& vertex : m_vertices ) {
+        if ( 0 == vertex ) {
+          Warning( "NULL vertex is detected, skip" ).ignore();
+          continue;
+        }
+        // explict loop over all descendants
+        auto particles = HepMC3::Relatives::DESCENDANTS(vertex);
+        auto begin = std::begin(particles);
+        auto end   = std::end(particles);
+        if ( std::find( begin, end, p ) != end ) { return true; } // RETURN
+        //
+      }
+      return false; // RETURN
+    }
+    // ============================================================================
+    //  "SHORT" representation, @see LoKi::AuxFunBase
+    // ============================================================================
+    std::ostream& FromHepMCTree::fillStream( std::ostream& s ) const { return s << "GFROMTREE"; }
+    // ============================================================================
+    /*  constructor from particle ("head")
+     *  @param p pointer to HepMC3::GenParticle
+     */
+    // ============================================================================
+    IsAnAncestor::IsAnAncestor( const HepMC3::ConstGenParticlePtr & p ) : m_particle( p ) {}
+    // ============================================================================
+    //  MANDATORY: clone method ("virtual constructor")
+    // ============================================================================
+    IsAnAncestor* IsAnAncestor::clone() const { return new LoKi::GenParticles::IsAnAncestor( *this ); }
+    // ============================================================================
+    //  MANDATORY: the only one essential method
+    // ============================================================================
+    bool IsAnAncestor::operator()( const HepMC3::ConstGenParticlePtr & p ) const {
+      if ( 0 == p || 0 == m_particle ) {
+        Error( " HepMC3::ConstGenParticlePtr & points to NULL, return 'false' " ).ignore();
+        return false; // RETURN
+      }
+      auto vertex = p->end_vertex();
+      if ( 0 == vertex ) { return false; } // RETURN
+      // explict loop over all descendants
+      auto particles = HepMC3::Relatives::DESCENDANTS(vertex);
+      for ( auto dp : particles ) {
+        if ( m_particle == ( dp ) ) { return true; }
+      } // RETURN
+
+      return false;
+    }
+    // ============================================================================
+    //  "SHORT" representation, @see LoKi::AuxFunBase
+    // ============================================================================
+    std::ostream& IsAnAncestor::fillStream( std::ostream& s ) const { return s << "GANCESTOR"; }
+    // ============================================================================
+    //  constructor from Quark
+    // ============================================================================
+    HasQuark::HasQuark( const LHCb::ParticleID::Quark quark )
+        : LoKi::AuxFunBase( std::tie( quark ) ), m_quark( quark ) {}
+    // ============================================================================
+    // the only one essential method
+    // ============================================================================
+    bool HasQuark::operator()( const HepMC3::ConstGenParticlePtr & p ) const {
+      if ( 0 == p ) {
+        Error( "HepMC3::ConstGenParticlePtr & point to NULL, returs 'false'" ).ignore();
+        return false;
+      }
+      return LHCb::ParticleID( p->pdg_id() ).hasQuark( quark() );
+    }
+    // ============================================================================
+    HasQuark* HasQuark::clone() const { return new LoKi::GenParticles::HasQuark( *this ); }
+    // ============================================================================
+    std::ostream& HasQuark::fillStream( std::ostream& s ) const {
+      switch ( quark() ) {
+      case LHCb::ParticleID::top:
+        return s << "GTOP";
+        break;
+      case LHCb::ParticleID::bottom:
+        return s << "GBEAUTY";
+        break;
+      case LHCb::ParticleID::charm:
+        return s << "GCHARM";
+        break;
+      case LHCb::ParticleID::strange:
+        return s << "GSTRANGE";
+        break;
+      default:
+        return s << "GQUARK(" << quark() << ")";
+        break;
+      }
+    }
+    // ============================================================================
+    // the only one essential method
+    // ============================================================================
+    bool IsCharged::operator()( const HepMC3::ConstGenParticlePtr & p ) const {
+      if ( 0 == p ) {
+        Error( "HepMC3::ConstGenParticlePtr & point to NULL, returs 'false'" ).ignore();
+        return false;
+      }
+      return 0 != LHCb::ParticleID( p->pdg_id() ).threeCharge();
+    }
+    // ============================================================================
+    IsCharged* IsCharged::clone() const { return new LoKi::GenParticles::IsCharged( *this ); }
+    // ============================================================================
+    std::ostream& IsCharged::fillStream( std::ostream& s ) const { return s << "GCHARGED"; }
+    // ============================================================================
+    // the only one essential method
+    // ============================================================================
+    bool IsNeutral::operator()( const HepMC3::ConstGenParticlePtr & p ) const {
+      if ( 0 == p ) {
+        Error( "HepMC3::ConstGenParticlePtr & point to NULL, returs 'false'" ).ignore();
+        return false;
+      }
+      return 0 == LHCb::ParticleID( p->pdg_id() ).threeCharge();
+    }
+    // ============================================================================
+    IsNeutral* IsNeutral::clone() const { return new LoKi::GenParticles::IsNeutral( *this ); }
+    // ============================================================================
+    std::ostream& IsNeutral::fillStream( std::ostream& s ) const { return s << "GNEUTRAL"; }
+    // ============================================================================
+    // the only one essential method
+    // ============================================================================
+    bool IsLepton::operator()( const HepMC3::ConstGenParticlePtr & p ) const {
+      if ( 0 == p ) {
+        Error( "HepMC3::ConstGenParticlePtr & point to NULL, returs 'false'" ).ignore();
+        return false;
+      }
+      return LHCb::ParticleID( p->pdg_id() ).isLepton();
+    }
+    // ============================================================================
+    IsLepton* IsLepton::clone() const { return new LoKi::GenParticles::IsLepton( *this ); }
+    // ============================================================================
+    std::ostream& IsLepton::fillStream( std::ostream& s ) const { return s << "GLEPTON"; }
+    // ============================================================================
+    // the only one essential method
+    // ============================================================================
+    bool IsMeson::operator()( const HepMC3::ConstGenParticlePtr & p ) const {
+      if ( 0 == p ) {
+        Error( "HepMC3::ConstGenParticlePtr & point to NULL, returs 'false'" ).ignore();
+        return false;
+      }
+      return LHCb::ParticleID( p->pdg_id() ).isMeson();
+    }
+    // ============================================================================
+    IsMeson* IsMeson::clone() const { return new LoKi::GenParticles::IsMeson( *this ); }
+    // ============================================================================
+    std::ostream& IsMeson::fillStream( std::ostream& s ) const { return s << "GMESON"; }
+    // ============================================================================
+    // the only one essential method
+    // ============================================================================
+    bool IsBaryon::operator()( const HepMC3::ConstGenParticlePtr & p ) const {
+      if ( 0 == p ) {
+        Error( "HepMC3::ConstGenParticlePtr & point to NULL, returs 'false'" ).ignore();
+        return false;
+      }
+      return LHCb::ParticleID( p->pdg_id() ).isBaryon();
+    }
+    // ============================================================================
+    IsBaryon* IsBaryon::clone() const { return new LoKi::GenParticles::IsBaryon( *this ); }
+    // ============================================================================
+    std::ostream& IsBaryon::fillStream( std::ostream& s ) const { return s << "GBARYON"; }
+    // ============================================================================
+    // the only one essential method
+    // ============================================================================
+    bool IsHadron::operator()( const HepMC3::ConstGenParticlePtr & p ) const {
+      if ( 0 == p ) {
+        Error( "HepMC3::ConstGenParticlePtr & point to NULL, returs 'false'" ).ignore();
+        return false;
+      }
+      return LHCb::ParticleID( p->pdg_id() ).isHadron();
+    }
+    // ============================================================================
+    IsHadron* IsHadron::clone() const { return new LoKi::GenParticles::IsHadron( *this ); }
+    // ============================================================================
+    std::ostream& IsHadron::fillStream( std::ostream& s ) const { return s << "GHADRON"; }
+    // ============================================================================
+    // the only one essential method
+    // ============================================================================
+    bool IsNucleus::operator()( const HepMC3::ConstGenParticlePtr & p ) const {
+      if ( 0 == p ) {
+        Error( "HepMC3::ConstGenParticlePtr & point to NULL, returs 'false'" ).ignore();
+        return false;
+      }
+      return LHCb::ParticleID( p->pdg_id() ).isNucleus();
+    }
+    // ============================================================================
+    IsNucleus* IsNucleus::clone() const { return new LoKi::GenParticles::IsNucleus( *this ); }
+    // ============================================================================
+    std::ostream& IsNucleus::fillStream( std::ostream& s ) const { return s << "GNUCLEUS"; }
+    // ============================================================================
+    ProperLifeTime::ProperLifeTime( const double bad ) : LoKi::AuxFunBase( std::tie( bad ) ), m_bad( bad ) {}
+    // ============================================================================
+    ProperLifeTime* ProperLifeTime::clone() const { return new LoKi::GenParticles::ProperLifeTime( *this ); }
+    // ============================================================================
+    std::ostream& ProperLifeTime::fillStream( std::ostream& s ) const { return s << "GTIME"; }
+    // ============================================================================
+    double ProperLifeTime::operator()( const HepMC3::ConstGenParticlePtr & p ) const {
+      if ( 0 == p ) {
+        Error( " Invalid HepMC3::GenParticle, return 'InvalidTime'" ).ignore();
+        return LoKi::Constants::InvalidTime; // RETURN
+      }
+      // end-vertex
+      auto end = p->end_vertex();
+      if ( 0 == end ) { return m_bad; }
+      // production vertex
+      auto origin = p->production_vertex();
+      if ( 0 == origin ) {
+        Error( " Invalid production_vertex, return 'InvalidTime'" ).ignore();
+        return LoKi::Constants::InvalidTime; // RETURN
+      }
+      const double dist = ( LoKi::ThreeVector( end->position() ) - LoKi::ThreeVector( origin->position() ) ).R();
+      const double mass = LoKi::LorentzVector( p->momentum() ).M();
+      const double mom  = LoKi::LorentzVector( p->momentum() ).P();
+      if ( 0 >= mass ) {
+        Error( " Mass is invalid, return 'InvalidTime' " ).ignore();
+        return LoKi::Constants::InvalidTime; // RETURN
+      }
+      if ( 0 >= mom ) {
+        Error( " |Momentum| is invalid, return 'InvalidTime' " ).ignore();
+        return LoKi::Constants::InvalidTime; // RETURN
+      }
+      const double betagamma = mom / mass;
+      //
+      if ( 0 >= betagamma ) {
+        Error( " betagamma is invalid, return 'InvalidTime' " ).ignore();
+        return LoKi::Constants::InvalidTime; // RETURN
+      }
+      //
+      return dist / betagamma;
+    }
+    // ============================================================================
+    NominalLifeTime* NominalLifeTime::clone() const { return new LoKi::GenParticles::NominalLifeTime( *this ); }
+    // ============================================================================
+    double NominalLifeTime::operator()( const HepMC3::ConstGenParticlePtr & p ) const {
+      if ( 0 == p ) {
+        Error( " Invalid HepMC3::GenParticle, return 'InvalidTime'" ).ignore();
+        return LoKi::Constants::InvalidTime; // RETURN
+      }
+      return LoKi::Particles::lifeTime( LHCb::ParticleID( p->pdg_id() ) );
+    }
+    // ============================================================================
+    std::ostream& NominalLifeTime::fillStream( std::ostream& s ) const { return s << "GNLT"; }
+    // ============================================================================
+    /*  constructor from vertex function and "bad" value
+     *  @param fun verted function to be used
+     *  @param bad the value to be returnedd for invalid vertex
+     */
+    // ============================================================================
+    AdapterToProductionVertex::AdapterToProductionVertex( const LoKi::Types::GVFunc& fun, const double bad )
+        : LoKi::AuxFunBase( std::tie( fun, bad ) ), m_fun( fun ), m_bad( bad ) {}
+    // ============================================================================
+    //  clone method (mandatory!)
+    // ============================================================================
+    AdapterToProductionVertex* AdapterToProductionVertex::clone() const {
+      return new AdapterToProductionVertex( *this );
+    }
+    // ============================================================================
+    //  "SHORT" representation, @see LoKi::AuxFunBase
+    // ============================================================================
+    std::ostream& AdapterToProductionVertex::fillStream( std::ostream& stream ) const {
+      return stream << "GFAPVX(" << m_fun << ")";
+    }
+    // ============================================================================
+    //  the only one essential method
+    // ============================================================================
+    double AdapterToProductionVertex::operator()( const HepMC3::ConstGenParticlePtr & p ) const {
+      if ( 0 == p ) { return m_bad; }
+      auto v = p->production_vertex();
+      if ( 0 == v ) { return m_bad; }
+      return m_fun( v );
+    }
+    // ============================================================================
+    /*  constructor from vertex function and "bad" value
+     *  @param fun verted function to be used
+     *  @param bad the value to be returnedd for invalid vertex
+     */
+    // ============================================================================
+    AdapterToEndVertex::AdapterToEndVertex( const LoKi::Types::GVFunc& fun, const double bad )
+        : LoKi::AuxFunBase( std::tie( fun, bad ) ), m_fun( fun ), m_bad( bad ) {}
+    // ============================================================================
+    //  clone method (mandatory!)
+    // ============================================================================
+    AdapterToEndVertex* AdapterToEndVertex::clone() const { return new AdapterToEndVertex( *this ); }
+    // ============================================================================
+    //  "SHORT" representation, @see LoKi::AuxFunBase
+    // ============================================================================
+    std::ostream& AdapterToEndVertex::fillStream( std::ostream& stream ) const {
+      return stream << "GFAEVX(" << m_fun << ")";
+    }
+    // ============================================================================
+    //  the only one essential method
+    // ============================================================================
+    double AdapterToEndVertex::operator()( const HepMC3::ConstGenParticlePtr & p ) const {
+      if ( 0 == p ) { return m_bad; }
+      auto v = p->end_vertex();
+      if ( 0 == v ) { return m_bad; }
+      return m_fun( v );
+    }
+    // ============================================================================
+    //  MANDATORY: the only one essential method
+    // ============================================================================
+    double ThreeCharge::operator()( const HepMC3::ConstGenParticlePtr & p ) const {
+      if ( 0 == p ) {
+        Error( " Invalid Particle, return 'InvalidCharge'" ).ignore();
+        return LoKi::Constants::InvalidCharge; // RETURN
+      }
+      return LHCb::ParticleID( p->pdg_id() ).threeCharge();
+    }
+    // ============================================================================
+    //  "SHORT" representation, @see LoKi::AuxFunBase
+    // ============================================================================
+    std::ostream& ThreeCharge::fillStream( std::ostream& stream ) const { return stream << "G3Q"; }
+
+    // ============================================================================
+    /*  constructor
+     *  @param cut    predicate to be used for counting
+     *  @param range  "iterator range", @see const HepMC3::Relatives &
+     *  @see const HepMC3::Relatives &
+     */
+    // ============================================================================
+    NInTree::NInTree( const LoKi::GenTypes::GCuts& cut, const HepMC3::Relatives & range )
+        : LoKi::AuxFunBase( std::tie( cut, range ) ), m_cut( cut ), m_range( range ) {}
+    // ============================================================================
+    //  MANDATORY: clone function ("virtual constructor")
+    // ============================================================================
+    NInTree* NInTree::clone() const { return new LoKi::GenParticles::NInTree( *this ); }
+    // ============================================================================
+    /*  count the particles in the tree according
+     *  the predicat eand iterator range
+     *  @see HepMC3::GenVertex
+     *  @param vertex  root of the tree
+     *  @return number of particles
+     */
+    // ============================================================================
+    size_t NInTree::count( const HepMC3::ConstGenVertexPtr & vertex ) const {
+      if ( 0 == vertex ) { return 0; }
+      auto particles = m_range(vertex);
+      return std::count_if( std::begin(particles), std::end(particles), m_cut );
+    }
+    size_t NInTree::count( const HepMC3::ConstGenParticlePtr & particle ) const {
+      if ( 0 == particle ) { return 0; }
+      auto particles = m_range(particle);
+      return std::count_if( std::begin(particles), std::end(particles), m_cut );
+    }
+    // ============================================================================
+    //  MANDATORY: the only one essential method
+    // ============================================================================
+    double NInTree::operator()( const HepMC3::ConstGenParticlePtr & p ) const {
+      if ( 0 == p ) {
+        Error( "HepMC3::ConstGenParticlePtr & points to NULL, return 0" ).ignore();
+        return 0; // RETURN
+      };
+      return count( p );
+    }
+    // ============================================================================
+    //  "SHORT" representation, @see LoKi::AuxFunBase
+    // ============================================================================
+    std::ostream& NInTree::fillStream( std::ostream& s ) const {
+      return s << "GNINTREE(" << m_cut << "," << HepMCUtils::RelationToString(m_range) << ")";
+    }
+    // ============================================================================
+
+    // ============================================================================
+    /*  constructor
+     *  @param fun    function to be evaluated
+     *  @param cut    predicate to be used for counting
+     *  @param range  "iterator range", see const HepMC3::Relatives &
+     *  @see const HepMC3::Relatives &
+     */
+    // ============================================================================
+    MaxTree::MaxTree( const LoKi::GenTypes::GFunc& fun, const LoKi::GenTypes::GCuts& cut, const HepMC3::Relatives & range )
+        : LoKi::AuxFunBase( std::tie( fun, cut, range ) ), NInTree( cut, range ), m_fun( fun ) {}
+    // ============================================================================
+    // MANDATORY: clone function ("virtual constructor")
+    // ============================================================================
+    MaxTree* MaxTree::clone() const { return new MaxTree( *this ); }
+    // ============================================================================
+    // MANDATORY: the only one essential method
+    // ============================================================================
+    double MaxTree::operator()( const HepMC3::ConstGenParticlePtr & p ) const {
+      if ( UNLIKELY( !p ) ) {
+        Error( "Invalid HepMC3::GenParticle, return -inf" ).ignore();
+        return LoKi::Constants::NegativeInfinity; // RETURN
+      }
+      //
+      //p
+      auto vertex =
+          ( dynamic_cast<const HepMC3::Parents*>(&m_range) || dynamic_cast<const HepMC3::Ancestors*>(&m_range) )
+              ? p->production_vertex()
+              : ( dynamic_cast<const HepMC3::Children*>(&m_range) || dynamic_cast<const HepMC3::Descendants*>(&m_range) ) ? p->end_vertex() : nullptr;
+      //
+      if ( UNLIKELY( !vertex ) ) {
+        Error( "Invalid HepMC3::GenVertex/range, return -inf" ).ignore();
+        return LoKi::Constants::NegativeInfinity; // RETURN
+      }
+      //
+      double result = LoKi::Constants::NegativeInfinity;
+      //
+      auto particles = m_range(vertex);
+      return LoKi::Algs::max_value( std::begin(particles), std::end(particles), m_fun, m_cut,
+                                    result );
+    }
+    // ============================================================================
+    //  "SHORT" representation, @see LoKi::AuxFunBase
+    // ============================================================================
+    std::ostream& MaxTree::fillStream( std::ostream& s ) const {
+      return s << "GMAXTREE(" << m_fun << "," << m_cut << "," << HepMCUtils::RelationToString(m_range) << ")";
+    }
+    // ============================================================================
+
+    // ============================================================================
+    /*  constructor
+     *  @param fun    function to be evaluated
+     *  @param cut    predicate to be used for counting
+     *  @param range  "iterator range", see const HepMC3::Relatives &
+     *  @see const HepMC3::Relatives &
+     */
+    // ============================================================================
+    MinTree::MinTree( const LoKi::GenTypes::GFunc& fun, const LoKi::GenTypes::GCuts& cut,  const HepMC3::Relatives & range )
+        : LoKi::AuxFunBase( std::tie( fun, cut, range ) ), MaxTree( fun, cut, range ) {}
+    // ============================================================================
+    // MANDATORY: clone function ("virtual constructor")
+    // ============================================================================
+    MinTree* MinTree::clone() const { return new MinTree( *this ); }
+    // ============================================================================
+    // MANDATORY: the only one essential method
+    // ============================================================================
+    double MinTree::operator()( const HepMC3::ConstGenParticlePtr & p ) const {
+      if ( UNLIKELY( !p ) ) {
+        Error( "Invalid HepMC3::GenParticle, return +inf" ).ignore();
+        return LoKi::Constants::PositiveInfinity; // RETURN
+      }
+      //
+      auto vertex =
+          ( dynamic_cast<const HepMC3::Parents*>(&m_range) || dynamic_cast<const HepMC3::Ancestors*>(&m_range) )
+              ? p->production_vertex()
+              : ( dynamic_cast<const HepMC3::Children*>(&m_range) || dynamic_cast<const HepMC3::Descendants*>(&m_range) ) ? p->end_vertex() : nullptr;
+      //
+      if ( UNLIKELY( !vertex ) ) {
+        Error( "Invalid HepMC3::GenVertex/range, return +inf" ).ignore();
+        return LoKi::Constants::PositiveInfinity; // RETURN
+      }
+      //
+      double result = LoKi::Constants::PositiveInfinity;
+      auto particles = m_range(vertex);
+      return LoKi::Algs::min_value( std::begin(particles), std::end(particles), m_fun, m_cut,
+                                    result );
+    }
+    // ============================================================================
+    //  "SHORT" representation, @see LoKi::AuxFunBase
+    // ============================================================================
+    std::ostream& MinTree::fillStream( std::ostream& s ) const {
+      return s << "GMINTREE(" << m_fun << "," << m_cut << "," << HepMCUtils::RelationToString(m_range) << ")";
+    }
+    // ============================================================================
+
+    // ============================================================================
+    /*  constructor
+     *  @param fun    function to be evaluated
+     *  @param cut    predicate to be used for counting
+     *  @param range  "iterator range", see const HepMC3::Relatives &
+     *  @see const HepMC3::Relatives &
+     */
+    // ============================================================================
+    SumTree::SumTree( const LoKi::GenTypes::GFunc& fun, const LoKi::GenTypes::GCuts& cut, const HepMC3::Relatives & range )
+        : LoKi::AuxFunBase( std::tie( fun, cut, range ) ), MinTree( fun, cut, range ) {}
+    // ============================================================================
+    // MANDATORY: clone function ("virtual constructor")
+    // ============================================================================
+    SumTree* SumTree::clone() const { return new SumTree( *this ); }
+    // ============================================================================
+    // MANDATORY: the only one essential method
+    // ============================================================================
+    double SumTree::operator()( const HepMC3::ConstGenParticlePtr & p ) const {
+      if ( UNLIKELY( !p ) ) {
+        Error( "Invalid HepMC3::GenParticle, return -inf" ).ignore();
+        return LoKi::Constants::NegativeInfinity; // RETURN
+      }
+      //
+      auto vertex =
+          ( dynamic_cast<const HepMC3::Parents*>(&m_range) || dynamic_cast<const HepMC3::Ancestors*>(&m_range) )
+              ? p->production_vertex()
+              : ( dynamic_cast<const HepMC3::Children*>(&m_range) || dynamic_cast<const HepMC3::Descendants*>(&m_range) ) ? p->end_vertex() : nullptr;
+      //
+      if ( UNLIKELY( !vertex ) ) {
+        Error( "Invalid HepMC3::GenVertex/range, return -inf" ).ignore();
+        return LoKi::Constants::NegativeInfinity; // RETURN
+      }
+      //
+      double result = 0;
+      //
+      auto particles = m_range(vertex);
+      return LoKi::Algs::accumulate( std::begin(particles), std::end(particles), m_fun, m_cut,
+                                     result, std::plus<double>() );
+    }
+    // ============================================================================
+    //  "SHORT" representation, @see LoKi::AuxFunBase
+    // ============================================================================
+    std::ostream& SumTree::fillStream( std::ostream& s ) const {
+      return s << "GSUMTREE(" << m_fun << "," << m_cut << "," << HepMCUtils::RelationToString(m_range) << ")";
+    }
+    // ============================================================================
+
+    // ============================================================================
+    /*  constructor
+     *  @param fun    function to be evaluated
+     *  @param cut    predicate to be used for counting
+     *  @param range  "iterator range", see const HepMC3::Relatives &
+     *  @see const HepMC3::Relatives &
+     */
+    // ============================================================================
+    MultTree::MultTree( const LoKi::GenTypes::GFunc& fun, const LoKi::GenTypes::GCuts& cut, const HepMC3::Relatives & range )
+        : LoKi::AuxFunBase( std::tie( fun, cut, range ) ), SumTree( fun, cut, range ) {}
+    // ============================================================================
+    // MANDATORY: clone function ("virtual constructor")
+    // ============================================================================
+    MultTree* MultTree::clone() const { return new MultTree( *this ); }
+    // ============================================================================
+    // MANDATORY: the only one essential method
+    // ============================================================================
+    double MultTree::operator()( const HepMC3::ConstGenParticlePtr & p ) const {
+      if ( UNLIKELY( !p ) ) {
+        Error( "Invalid HepMC3::GenParticle, return -inf" ).ignore();
+        return LoKi::Constants::NegativeInfinity; // RETURN
+      }
+      //
+      auto vertex =
+          ( dynamic_cast<const HepMC3::Parents*>(&m_range) || dynamic_cast<const HepMC3::Ancestors*>(&m_range) )
+              ? p->production_vertex()
+              : ( dynamic_cast<const HepMC3::Children*>(&m_range) || dynamic_cast<const HepMC3::Descendants*>(&m_range) ) ? p->end_vertex() : nullptr;
+      //
+      if ( UNLIKELY( !vertex ) ) {
+        Error( "Invalid HepMC3::GenVertex/range, return -inf" ).ignore();
+        return LoKi::Constants::NegativeInfinity; // RETURN
+      }
+      //
+      double result = 1.0;
+      //
+      auto particles = m_range(vertex);
+      return LoKi::Algs::accumulate( std::begin(particles), std::end(particles), m_fun, m_cut,
+                                     result, std::multiplies<double>() );
+    }
+    // ============================================================================
+    //  "SHORT" representation, @see LoKi::AuxFunBase
+    // ============================================================================
+    std::ostream& MultTree::fillStream( std::ostream& s ) const {
+      return s << "GMULTTREE(" << m_fun << "," << m_cut << "," << HepMCUtils::RelationToString(m_range) << ")";
+    }
+    // ============================================================================
+
+    // ============================================================================
+    /*  standard constructor
+     *  @param cut cut to be checked
+     */
+    // ============================================================================
+    InTree::InTree( const LoKi::GenTypes::GCuts& cut )
+        : LoKi::AuxFunBase( std::tie( cut ) ), LoKi::GenTypes::GCuts(), m_cut( cut ) {}
+    // ============================================================================
+    // MANDATORY: clone function ("virtual constructor")
+    // ============================================================================
+    InTree* InTree::clone() const { return new LoKi::GenParticles::InTree( *this ); }
+    // ============================================================================
+    // MANDATORY: the only one essential method
+    // ============================================================================
+    bool InTree::operator()( const HepMC3::ConstGenParticlePtr & p ) const {
+      if ( 0 == p ) { Warning( "HepMC3::ConstGenParticlePtr & points to NULL" ); }
+      return LoKi::GenAlgs::found( p, m_cut );
+    }
+    // ============================================================================
+    //  OPTIONAL: "SHORT" representation, @see LoKi::AuxFunBase
+    // ============================================================================
+    std::ostream& InTree::fillStream( std::ostream& s ) const { return s << "GINTREE(" << m_cut << ")"; }
+    // ============================================================================
+
+    // ============================================================================
+    // MANDATORY: clone method ("virtual constructor")
+    // ============================================================================
+    Oscillated* Oscillated::clone() const { return new LoKi::GenParticles::Oscillated( *this ); }
+    // ============================================================================
+    // MANDATORY: the only one essential method
+    // ============================================================================
+    bool Oscillated::operator()( const HepMC3::ConstGenParticlePtr & p ) const {
+      return 0 != LoKi::GenParticles::oscillated1( p ) || 0 != LoKi::GenParticles::oscillated2( p );
+    }
+    // ============================================================================
+    // OPTIONAL: the specific printout
+    // ============================================================================
+    std::ostream& Oscillated::fillStream( std::ostream& o ) const { return o << "GOSCILLATED"; }
+    // ============================================================================
+
+    // ============================================================================
+    // MANDATORY: clone method ("virtual constructor")
+    // ============================================================================
+    Oscillated1* Oscillated1::clone() const { return new LoKi::GenParticles::Oscillated1( *this ); }
+    // ============================================================================
+    // MANDATORY: the only one essential method
+    // ============================================================================
+    bool Oscillated1::operator()( const HepMC3::ConstGenParticlePtr & p ) const {
+      return 0 != LoKi::GenParticles::oscillated1( p );
+    }
+    // ============================================================================
+    // OPTIONAL: the specific printout
+    // ============================================================================
+    std::ostream& Oscillated1::fillStream( std::ostream& o ) const { return o << "GOSCILLATED1"; }
+    // ============================================================================
+
+    // ============================================================================
+    // MANDATORY: clone method ("virtual constructor")
+    // ============================================================================
+    Oscillated2* Oscillated2::clone() const { return new Oscillated2( *this ); }
+    // ============================================================================
+    // MANDATORY: the only one essential method
+    // ============================================================================
+    bool Oscillated2::operator()( const HepMC3::ConstGenParticlePtr & p ) const {
+      return 0 != LoKi::GenParticles::oscillated2( p );
+    }
+    // ============================================================================
+    // OPTIONAL: the specific printout
+    // ============================================================================
+    std::ostream& Oscillated2::fillStream( std::ostream& o ) const { return o << "GOSCILLATED2"; }
+    // ============================================================================
+
+    // ============================================================================
+    // constructor from the actual node
+    // ============================================================================
+    DecNode::DecNode( const Decays::iNode& node )
+        : LoKi::AuxFunBase( std::tie( node ) )
+        , LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::Predicate()
+        , m_node( node ) {}
+    // ============================================================================
+    // MANDATORY: the only one essential method
+    // ============================================================================
+    bool DecNode::operator()( const HepMC3::ConstGenParticlePtr & p ) const {
+      if ( 0 == p ) {
+        Error( "HepMC3::ConstGenParticlePtr & point to NULL, return false" ).ignore();
+        return false;
+      }
+      //
+      if ( !m_node.valid() ) {
+        LoKi::ILoKiSvc*                     ls = lokiSvc();
+        SmartIF<LHCb::IParticlePropertySvc> ppSvc( ls );
+        StatusCode                          sc = m_node.validate( ppSvc );
+        Assert( sc.isSuccess(), "Unable to validate the node!" );
+      }
+      // use the node for evaluation
+      return m_node.node( LHCb::ParticleID( p->pdg_id() ) );
+    }
+    // ============================================================================
+    // OPTIONAL: the nice printout
+    // ============================================================================
+    std::ostream& DecNode::fillStream( std::ostream& s ) const {
+      if ( !valid() ) { return s << "GDECNODE(invalid)"; }
+      return s << "GDECNODE( " << m_node << ")";
+    }
+    // ============================================================================
+
+    // ============================================================================
+    // MANDATORY: clone method ("virtual constructor")
+    // ============================================================================
+    LongLived* LongLived::clone() const { return new LongLived( *this ); }
+    // ============================================================================
+    // OPTIONAL: the nice printout
+    // ============================================================================
+    std::ostream& LongLived::fillStream( std::ostream& s ) const { return s << "GLONGLIVED"; }
+    // ============================================================================
+
+    namespace {
+      // ==========================================================================
+      /// invalid Node
+      static const Decays::Nodes::Invalid s_NODE{};
+      /// invalid decay
+      static const Decays::Trees::Types_<HepMC3::ConstGenParticlePtr>::Invalid s_TREE{};
+      /// "Factory"
+      static const std::string s_FACTORY = "LoKi::GenDecay";
+      // ==========================================================================
+    } // namespace
+    // ============================================================================
+    // constructor from the actual tree
+    // ============================================================================
+    DecTree::DecTree( const iTree& tree, const bool autovalidate ) : m_tree( tree ), m_autovalidate( autovalidate ) {}
+    // ============================================================================
+    // constructor from the decay descriptor
+    // ============================================================================
+    DecTree::DecTree( const std::string& descriptor )
+        : LoKi::AuxFunBase( std::tie( descriptor ) ), m_tree( s_TREE ), m_autovalidate( true ) {
+      LoKi::ILoKiSvc*   ls = lokiSvc();
+      SmartIF<IToolSvc> toolSvc( ls );
+      Assert( !( !toolSvc ), "Unable to aquire IToolSvc tool" );
+
+      Decays::IGenDecay* tool = 0;
+      StatusCode         sc   = toolSvc->retrieveTool( s_FACTORY, tool );
+      Assert( sc.isSuccess(), "Unable to retrieve '" + s_FACTORY + "'", sc );
+      Assert( 0 != tool, "Decays::IGenDecay* points to NULL" );
+      //
+      m_tree = tool->tree( descriptor );
+      toolSvc->releaseTool( tool ); // do not need the tool anymore
+      //
+      Assert( !( !m_tree ), "The tree is invalid : '" + descriptor + "'" );
+      Assert( !m_tree.marked(), "The tree is marked  : '" + descriptor + "'" );
+      //
+    }
+    // ============================================================================
+    // MANDATORY: the only one essential method
+    // ============================================================================
+    bool DecTree::operator()( const HepMC3::ConstGenParticlePtr & p ) const {
+      if ( 0 == p ) {
+        Error( "HepMC3::GenParticlePtr point to NULL, return false" ).ignore();
+        return false;
+      }
+      //
+      if ( !valid() && m_autovalidate ) {
+        const LoKi::Services&             svcs  = LoKi::Services::instance();
+        const LHCb::IParticlePropertySvc* ppsvc = svcs.ppSvc();
+        Assert( 0 != ppsvc, "LHCb::ParticlePropertySvc* poinst to NULL!" );
+        StatusCode sc = validate( ppsvc );
+        Assert( sc.isSuccess(), "Unable to validate Decays::Tree", sc );
+      }
+      if ( !valid() ) {
+        Error( "LoKi::GenParticles::DecTree::Tree  is invalid, return false" ).ignore();
+        return false;
+      }
+      // use the node for evaluation
+      return m_tree.tree( p );
+    }
+    // ============================================================================
+    // OPTIONAL: the nice printout
+    // ============================================================================
+    std::ostream& DecTree::fillStream( std::ostream& s ) const {
+      if ( !valid() ) { return s << "GDECTREE(invalid)"; }
+      return s << "GDECTREE( " << m_tree << ")";
+    }
+    // ============================================================================
+
+    // ============================================================================
+    /* constructor from the function and child selector
+     *  @param fun      the function to be used
+     *  @param selector the child selector
+     */
+    // ============================================================================
+    ChildFun::ChildFun( const LoKi::GenTypes::GFunc& fun, const LoKi::GenChild::Selector& selector )
+        : LoKi::AuxFunBase( std::tie( fun, selector ) ), m_fun( fun ), m_child( selector ) {
+      Assert( m_child.valid(), "Child selector is invalid!" );
+    }
+    // ============================================================================
+    /* constructor from the function and child selector
+     *  @param fun      the function to be used
+     *  @param selector the child selector
+     */
+    // ============================================================================
+    ChildFun::ChildFun( const LoKi::GenTypes::GFunc& fun, const std::string& selector )
+        : LoKi::AuxFunBase( std::tie( fun, selector ) ), m_fun( fun ), m_child( selector ) {
+      Assert( m_child.valid(), "Child selector is invalid!" );
+    }
+    // ============================================================================
+    /*  constructor from the function and child selector
+     *  @param fun      the function to be used
+     *  @param selector the child selector
+     */
+    // ============================================================================
+    ChildFun::ChildFun( const LoKi::GenTypes::GFunc& fun, const Decays::IGenDecay::iTree& selector )
+        : LoKi::AuxFunBase( std::tie( fun, selector ) ), m_fun( fun ), m_child( selector ) {
+      Assert( m_child.valid(), "Child selector is invalid!" );
+    }
+    // ============================================================================
+    /*  constructor from the function and child selector
+     *  @param fun      the function to be used
+     *  @param selector the child selector
+     */
+    // ============================================================================
+    ChildFun::ChildFun( const LoKi::GenTypes::GFunc& fun, const Decays::iNode& selector )
+        : LoKi::AuxFunBase( std::tie( fun, selector ) ), m_fun( fun ), m_child( selector ) {
+      Assert( m_child.valid(), "Child selector is invalid!" );
+    }
+    // ============================================================================
+    /*  constructor from the function and child selector
+     *  @param fun      the function to be used
+     *  @param selector the child selector
+     */
+    // ============================================================================
+    ChildFun::ChildFun( const LoKi::GenTypes::GFunc& fun, const LoKi::GenTypes::GCuts& selector )
+        : LoKi::AuxFunBase( std::tie( fun, selector ) ), m_fun( fun ), m_child( selector ) {
+      Assert( m_child.valid(), "Child selector is invalid:!" );
+    }
+    // ============================================================================
+    // clone method  ("virtual destructor" )
+    // ============================================================================
+    ChildFun* ChildFun::clone() const { return new LoKi::GenParticles::ChildFun( *this ); }
+    // ============================================================================
+    // MANDATORY: the only one essential method
+    // ============================================================================
+    double ChildFun::operator()( const HepMC3::ConstGenParticlePtr & p ) const {
+      if ( 0 == p ) {
+        Error( "HepMC3::ConstGenParticlePtr & points to NULL, return NegativeInfinity" ).ignore();
+        return LoKi::Constants::NegativeInfinity;
+      }
+      HepMC3::ConstGenParticlePtr c = m_child.child( p );
+      if ( 0 == c ) {
+        Error( " child HepMC3::ConstGenParticlePtr & points to NULL, return NegativeInfinity" ).ignore();
+        return LoKi::Constants::NegativeInfinity;
+      }
+      //
+      return m_fun( c );
+    }
+    // ============================================================================
+    //  OPTIONAL:  specific printout
+    // ============================================================================
+    std::ostream& ChildFun::fillStream( std::ostream& s ) const {
+      return s << " GCHILD(" << m_fun << "," << m_child << " ) ";
+    }
+    // ============================================================================
+
+    // ============================================================================
+    /* constructor from the function and child selector
+     *  @param fun      the function to be used
+     *  @param selector the child selector
+     */
+    // ============================================================================
+    ChildCut::ChildCut( const LoKi::GenTypes::GCuts& fun, const LoKi::GenChild::Selector& selector )
+        : LoKi::AuxFunBase( std::tie( fun, selector ) ), m_fun( fun ), m_child( selector ) {
+      Assert( m_child.valid(), "Child selector is invalid!" );
+    }
+    // ============================================================================
+    /* constructor from the function and child selector
+     *  @param fun      the function to be used
+     *  @param selector the child selector
+     */
+    // ============================================================================
+    ChildCut::ChildCut( const LoKi::GenTypes::GCuts& fun, const std::string& selector )
+        : LoKi::AuxFunBase( std::tie( fun, selector ) ), m_fun( fun ), m_child( selector ) {
+      Assert( m_child.valid(), "Child selector is invalid!" );
+    }
+    // ============================================================================
+    /*  constructor from the function and child selector
+     *  @param fun      the function to be used
+     *  @param selector the child selector
+     */
+    // ============================================================================
+    ChildCut::ChildCut( const LoKi::GenTypes::GCuts& fun, const Decays::IGenDecay::iTree& selector )
+        : LoKi::AuxFunBase( std::tie( fun, selector ) ), m_fun( fun ), m_child( selector ) {
+      Assert( m_child.valid(), "Child selector is invalid!" );
+    }
+    // ============================================================================
+    /*  constructor from the function and child selector
+     *  @param fun      the function to be used
+     *  @param selector the child selector
+     */
+    // ============================================================================
+    ChildCut::ChildCut( const LoKi::GenTypes::GCuts& fun, const Decays::iNode& selector )
+        : LoKi::AuxFunBase( std::tie( fun, selector ) ), m_fun( fun ), m_child( selector ) {
+      Assert( m_child.valid(), "Child selector is invalid!" );
+    }
+    // ============================================================================
+    /*  constructor from the function and child selector
+     *  @param fun      the function to be used
+     *  @param selector the child selector
+     */
+    // ============================================================================
+    ChildCut::ChildCut( const LoKi::GenTypes::GCuts& fun, const LoKi::GenTypes::GCuts& selector )
+        : LoKi::AuxFunBase( std::tie( fun, selector ) ), m_fun( fun ), m_child( selector ) {
+      Assert( m_child.valid(), "Child selector is invalid:!" );
+    }
+    // ============================================================================
+    // clone method  ("virtual destructor" )
+    // ============================================================================
+    ChildCut* ChildCut::clone() const { return new LoKi::GenParticles::ChildCut( *this ); }
+    // ============================================================================
+    // MANDATORY: the only one essential method
+    // ============================================================================
+    bool ChildCut::operator()( const HepMC3::ConstGenParticlePtr & p ) const {
+      if ( 0 == p ) {
+        Error( "HepMC3::ConstGenParticlePtr & points to NULL, return false" ).ignore();
+        return false;
+      }
+      HepMC3::ConstGenParticlePtr c = m_child.child( p );
+      if ( 0 == c ) {
+        Error( " child HepMC3::ConstGenParticlePtr & points to NULL, return false" ).ignore();
+        return false;
+      }
+      //
+      return m_fun( c );
+    }
+    // ============================================================================
+    //  OPTIONAL:  specific printout
+    // ============================================================================
+    std::ostream& ChildCut::fillStream( std::ostream& s ) const {
+      return s << " GCHILDCUT(" << m_fun << "," << m_child << " ) ";
+    }
+    // ============================================================================
+
+    // ============================================================================
+    // IsID
+    // ============================================================================
+    IsID::IsID( const long id ) : LoKi::AuxFunBase( std::tie( id ) ), LoKi::Pids::GetPids( id ) {}
+    // ============================================================================
+    IsID::IsID( const unsigned long id ) : LoKi::AuxFunBase( std::tie( id ) ), LoKi::Pids::GetPids( id ) {}
+    // ============================================================================
+    IsID::IsID( const LHCb::ParticleID& id ) : LoKi::AuxFunBase( std::tie( id ) ), LoKi::Pids::GetPids( id ) {}
+    // ============================================================================
+    IsID::IsID( const std::string& id ) : LoKi::AuxFunBase( std::tie( id ) ), LoKi::Pids::GetPids( id ) {}
+    // ============================================================================
+    IsID::IsID( const std::vector<int>& id ) : LoKi::AuxFunBase( std::tie( id ) ), LoKi::Pids::GetPids( id ) {}
+    // ============================================================================
+    IsID::IsID( const std::vector<unsigned int>& id ) : LoKi::AuxFunBase( std::tie( id ) ), LoKi::Pids::GetPids( id ) {}
+    // ============================================================================
+    IsID::IsID( const std::vector<long>& id ) : LoKi::AuxFunBase( std::tie( id ) ), LoKi::Pids::GetPids( id ) {}
+    // ============================================================================
+    IsID::IsID( const std::vector<unsigned long>& id )
+        : LoKi::AuxFunBase( std::tie( id ) ), LoKi::Pids::GetPids( id ) {}
+    // ============================================================================
+    IsID::IsID( const std::vector<LHCb::ParticleID>& id )
+        : LoKi::AuxFunBase( std::tie( id ) ), LoKi::Pids::GetPids( id ) {}
+    // ============================================================================
+    IsID::IsID( const std::vector<std::string>& id ) : LoKi::AuxFunBase( std::tie( id ) ), LoKi::Pids::GetPids( id ) {}
+    // ============================================================================
+    IsID::IsID( const LoKi::Pids::GetPids& id ) : LoKi::AuxFunBase( std::tie( id ) ), LoKi::Pids::GetPids( id ) {}
+    // ============================================================================
+    IsID* IsID::clone() const { return new LoKi::GenParticles::IsID( *this ); }
+    // ============================================================================
+    std::ostream& IsID::fillStream( std::ostream& s ) const {
+      //
+      s << "(GID== ";
+      //
+      if ( 1 == m_names.size() ) {
+        Gaudi::Utils::toStream( m_names[0], s );
+      } else if ( !m_names.empty() ) {
+        Gaudi::Utils::toStream( m_names, s );
+      } else if ( 1 == m_ints.size() ) {
+        Gaudi::Utils::toStream( m_ints[0], s );
+      } else {
+        Gaudi::Utils::toStream( m_ints, s );
+      }
+      //
+      return s << ")";
+    }
+    // ============================================================================
+    // the only one essential method
+    // ============================================================================
+    bool IsID::operator()( const HepMC3::ConstGenParticlePtr & p ) const {
+      //
+      if ( 0 == p ) {
+        Error( "Invalid Particle, return 'False'" ).ignore();
+        return false; // RETURN
+      }
+      //
+      return in_list( p->pdg_id() );
+    }
+
+    // ============================================================================
+    // IsNotID
+    // ============================================================================
+    IsNotID::IsNotID( const long id ) : LoKi::AuxFunBase( std::tie( id ) ), LoKi::GenParticles::IsID( id ) {}
+    // ============================================================================
+    IsNotID::IsNotID( const unsigned long id ) : LoKi::AuxFunBase( std::tie( id ) ), LoKi::GenParticles::IsID( id ) {}
+    // ============================================================================
+    IsNotID::IsNotID( const LHCb::ParticleID& id )
+        : LoKi::AuxFunBase( std::tie( id ) ), LoKi::GenParticles::IsID( id ) {}
+    // ============================================================================
+    IsNotID::IsNotID( const std::string& id ) : LoKi::AuxFunBase( std::tie( id ) ), LoKi::GenParticles::IsID( id ) {}
+    // ============================================================================
+    IsNotID::IsNotID( const std::vector<int>& id )
+        : LoKi::AuxFunBase( std::tie( id ) ), LoKi::GenParticles::IsID( id ) {}
+    // ============================================================================
+    IsNotID::IsNotID( const std::vector<unsigned int>& id )
+        : LoKi::AuxFunBase( std::tie( id ) ), LoKi::GenParticles::IsID( id ) {}
+    // ============================================================================
+    IsNotID::IsNotID( const std::vector<long>& id )
+        : LoKi::AuxFunBase( std::tie( id ) ), LoKi::GenParticles::IsID( id ) {}
+    // ============================================================================
+    IsNotID::IsNotID( const std::vector<unsigned long>& id )
+        : LoKi::AuxFunBase( std::tie( id ) ), LoKi::GenParticles::IsID( id ) {}
+    // ============================================================================
+    IsNotID::IsNotID( const std::vector<LHCb::ParticleID>& id )
+        : LoKi::AuxFunBase( std::tie( id ) ), LoKi::GenParticles::IsID( id ) {}
+    // ============================================================================
+    IsNotID::IsNotID( const std::vector<std::string>& id )
+        : LoKi::AuxFunBase( std::tie( id ) ), LoKi::GenParticles::IsID( id ) {}
+    // ============================================================================
+    IsNotID* IsNotID::clone() const { return new IsNotID( *this ); }
+    // ============================================================================
+    std::ostream& IsNotID::fillStream( std::ostream& s ) const {
+      //
+      s << "(GID!= ";
+      //
+      if ( 1 == m_names.size() ) {
+        Gaudi::Utils::toStream( m_names[0], s );
+      } else if ( !m_names.empty() ) {
+        Gaudi::Utils::toStream( m_names, s );
+      } else if ( 1 == m_ints.size() ) {
+        Gaudi::Utils::toStream( m_ints[0], s );
+      } else {
+        Gaudi::Utils::toStream( m_ints, s );
+      }
+      //
+      return s << ")";
+    }
+    // ============================================================================
+    // the only one essential method
+    // ============================================================================
+    bool IsNotID::operator()( const HepMC3::ConstGenParticlePtr & p ) const {
+      //
+      if ( 0 == p ) {
+        Error( "Invalid Particle, return 'False'" ).ignore();
+        return false; // RETURN
+      }
+      return not_in_list( p->pdg_id() );
+    }
+
+    // ============================================================================
+    // IsAbsID
+    // ============================================================================
+    IsAbsID::IsAbsID( const long id ) : LoKi::AuxFunBase( std::tie( id ) ), LoKi::GenParticles::IsID( id ) {}
+    // ============================================================================
+    IsAbsID::IsAbsID( const unsigned long id ) : LoKi::AuxFunBase( std::tie( id ) ), LoKi::GenParticles::IsID( id ) {}
+    // ============================================================================
+    IsAbsID::IsAbsID( const LHCb::ParticleID& id )
+        : LoKi::AuxFunBase( std::tie( id ) ), LoKi::GenParticles::IsID( id ) {}
+    // ============================================================================
+    IsAbsID::IsAbsID( const std::string& id ) : LoKi::AuxFunBase( std::tie( id ) ), LoKi::GenParticles::IsID( id ) {}
+    // ============================================================================
+    IsAbsID::IsAbsID( const std::vector<int>& id )
+        : LoKi::AuxFunBase( std::tie( id ) ), LoKi::GenParticles::IsID( id ) {}
+    // ============================================================================
+    IsAbsID::IsAbsID( const std::vector<unsigned int>& id )
+        : LoKi::AuxFunBase( std::tie( id ) ), LoKi::GenParticles::IsID( id ) {}
+    // ============================================================================
+    IsAbsID::IsAbsID( const std::vector<long>& id )
+        : LoKi::AuxFunBase( std::tie( id ) ), LoKi::GenParticles::IsID( id ) {}
+    // ============================================================================
+    IsAbsID::IsAbsID( const std::vector<unsigned long>& id )
+        : LoKi::AuxFunBase( std::tie( id ) ), LoKi::GenParticles::IsID( id ) {}
+    // ============================================================================
+    IsAbsID::IsAbsID( const std::vector<LHCb::ParticleID>& id )
+        : LoKi::AuxFunBase( std::tie( id ) ), LoKi::GenParticles::IsID( id ) {}
+    // ============================================================================
+    IsAbsID::IsAbsID( const std::vector<std::string>& id )
+        : LoKi::AuxFunBase( std::tie( id ) ), LoKi::GenParticles::IsID( id ) {}
+    // ============================================================================
+    IsAbsID::IsAbsID( const LoKi::Pids::GetPids& id )
+        : LoKi::AuxFunBase( std::tie( id ) ), LoKi::GenParticles::IsID( id ) {}
+    // ============================================================================
+    IsAbsID* LoKi::GenParticles::IsAbsID::clone() const { return new LoKi::GenParticles::IsAbsID( *this ); }
+    // ============================================================================
+    std::ostream& IsAbsID::fillStream( std::ostream& s ) const {
+      //
+      s << "(GABSID== ";
+      //
+      if ( 1 == m_names.size() ) {
+        Gaudi::Utils::toStream( m_names[0], s );
+      } else if ( !m_names.empty() ) {
+        Gaudi::Utils::toStream( m_names, s );
+      } else if ( 1 == m_ints.size() ) {
+        Gaudi::Utils::toStream( m_ints[0], s );
+      } else {
+        Gaudi::Utils::toStream( m_ints, s );
+      }
+      //
+      return s << ")";
+    }
+    // ============================================================================
+    // the only one essential method
+    // ============================================================================
+    bool IsAbsID::operator()( const HepMC3::ConstGenParticlePtr & p ) const {
+      //
+      if ( 0 == p ) {
+        Error( "Invalid Particle, return 'False'" ).ignore();
+        return false; // RETURN
+      }
+      //
+      return in_abs_list( p->pdg_id() );
+    }
+
+    // ============================================================================
+    // IsNotAbsID
+    // ============================================================================
+    IsNotAbsID::IsNotAbsID( const long id ) : LoKi::AuxFunBase( std::tie( id ) ), LoKi::GenParticles::IsAbsID( id ) {}
+    // ============================================================================
+    IsNotAbsID::IsNotAbsID( const unsigned long id )
+        : LoKi::AuxFunBase( std::tie( id ) ), LoKi::GenParticles::IsAbsID( id ) {}
+    // ============================================================================
+    IsNotAbsID::IsNotAbsID( const LHCb::ParticleID& id )
+        : LoKi::AuxFunBase( std::tie( id ) ), LoKi::GenParticles::IsAbsID( id ) {}
+    // ============================================================================
+    IsNotAbsID::IsNotAbsID( const std::string& id )
+        : LoKi::AuxFunBase( std::tie( id ) ), LoKi::GenParticles::IsAbsID( id ) {}
+    // ============================================================================
+    IsNotAbsID::IsNotAbsID( const std::vector<int>& id )
+        : LoKi::AuxFunBase( std::tie( id ) ), LoKi::GenParticles::IsAbsID( id ) {}
+    // ============================================================================
+    IsNotAbsID::IsNotAbsID( const std::vector<unsigned int>& id )
+        : LoKi::AuxFunBase( std::tie( id ) ), LoKi::GenParticles::IsAbsID( id ) {}
+    // ============================================================================
+    IsNotAbsID::IsNotAbsID( const std::vector<long>& id )
+        : LoKi::AuxFunBase( std::tie( id ) ), LoKi::GenParticles::IsAbsID( id ) {}
+    // ============================================================================
+    IsNotAbsID::IsNotAbsID( const std::vector<unsigned long>& id )
+        : LoKi::AuxFunBase( std::tie( id ) ), LoKi::GenParticles::IsAbsID( id ) {}
+    // ============================================================================
+    IsNotAbsID::IsNotAbsID( const std::vector<LHCb::ParticleID>& id )
+        : LoKi::AuxFunBase( std::tie( id ) ), LoKi::GenParticles::IsAbsID( id ) {}
+    // ============================================================================
+    IsNotAbsID::IsNotAbsID( const std::vector<std::string>& id )
+        : LoKi::AuxFunBase( std::tie( id ) ), LoKi::GenParticles::IsAbsID( id ) {}
+    // ============================================================================
+    IsNotAbsID::IsNotAbsID( const LoKi::Pids::GetPids& id )
+        : LoKi::AuxFunBase( std::tie( id ) ), LoKi::GenParticles::IsAbsID( id ) {}
+    // ============================================================================
+    IsNotAbsID* IsNotAbsID::clone() const { return new IsNotAbsID( *this ); }
+    // ============================================================================
+
+    std::ostream& IsNotAbsID::fillStream( std::ostream& s ) const {
+      //
+      s << "(GABSID!= ";
+      //
+      if ( 1 == m_names.size() ) {
+        Gaudi::Utils::toStream( m_names[0], s );
+      } else if ( !m_names.empty() ) {
+        Gaudi::Utils::toStream( m_names, s );
+      } else if ( 1 == m_ints.size() ) {
+        Gaudi::Utils::toStream( m_ints[0], s );
+      } else {
+        Gaudi::Utils::toStream( m_ints, s );
+      }
+      //
+      return s << ")";
+    }
+    // ============================================================================
+    // the only one essential method
+    // ============================================================================
+    bool IsNotAbsID::operator()( const HepMC3::ConstGenParticlePtr & p ) const {
+      //
+      if ( 0 == p ) {
+        Error( "Invalid Particle, return 'False'" ).ignore();
+        return false; // RETURN
+      }
+      //
+      return not_in_abs_list( p->pdg_id() );
+    }
+    // ============================================================================
+
+    // ============================================================================
+    // get unique string for HepMC3::Particle
+    // ============================================================================
+    std::string hex_id( const HepMC3::ConstGenParticlePtr & particle ) {
+      if ( 0 == particle ) { return "NULL"; }
+      boost::format fmt( "%p" );
+      const void*   p = particle.get();
+      fmt % p;
+      return fmt.str();
+    }
+
+    // ============================================================================
+    namespace {
+      // hashing function
+      const std::hash<const void*> s_hash{};
+    } // namespace
+    // ============================================================================
+    // get hash function for HepMC3::GenParticle
+    // ============================================================================
+    std::size_t hash( const HepMC3::ConstGenParticlePtr & particle ) { return 0 == particle ? 0 : s_hash( particle.get() ); }
+    // ============================================================================
+    // get hash function for HepMC3::GenVertex
+    // ============================================================================
+    std::size_t hash( const HepMC3::ConstGenVertexPtr & vertex ) { return 0 == vertex ? 0 : s_hash( vertex.get() ); }
+
+  } // namespace GenParticles
+} // namespace LoKi
+// ============================================================================
+// The END
+// ============================================================================
diff --git a/Gen/LoKiGen/src/GenParticles2.cpp b/Gen/LoKiGen/src/GenParticles2.cpp
new file mode 100644
index 000000000..66cb5538c
--- /dev/null
+++ b/Gen/LoKiGen/src/GenParticles2.cpp
@@ -0,0 +1,756 @@
+/*****************************************************************************\
+* (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration      *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                             *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+// ============================================================================
+// Include files
+// ============================================================================
+// GaudiKernel
+// ============================================================================
+#include "GaudiKernel/IToolSvc.h"
+#include "GaudiKernel/SmartIF.h"
+#include "GaudiKernel/ToStream.h"
+// ============================================================================
+// PartProp
+// ============================================================================
+#include "Kernel/IParticlePropertySvc.h"
+// ============================================================================
+// LoKi
+// ============================================================================
+#include "LoKi/Constants.h"
+#include "LoKi/GenChild.h"
+#include "LoKi/GenParticles2.h"
+#include "LoKi/IGenDecay.h"
+#include "LoKi/Kinematics.h"
+#include "LoKi/Trees.h"
+// ============================================================================
+/** @file
+ *  Implementation file for functirons from file  LoKi/GenParticles2.h
+ *
+ *  This file is a part of LoKi project -
+ *    "C++ ToolKit  for Smart and Friendly Physics Analysis"
+ *
+ *  The package has been designed with the kind help from
+ *  Galina PAKHLOVA and Sergey BARSUK.  Many bright ideas,
+ *  contributions and advices from G.Raven, J.van Tilburg,
+ *  A.Golutvin, P.Koppenburg have been used in the design.
+ *
+ *  @author Vaya BELYAEV Ivan.Belyaev@itep.ru
+ *  @date 2012-01-20
+ *
+ */
+namespace LoKi {
+  namespace GenParticles {
+    // ============================================================================
+    // constructor from child-selectors
+    // ============================================================================
+    PolarizationAngle::PolarizationAngle( const LoKi::GenChild::Selector& daughter,
+                                          const LoKi::GenChild::Selector& parent, const bool mother )
+        : m_first( daughter ), m_second( parent ), m_mother( mother ) {
+      Assert( m_first.valid(), "The first  tree is invalid!" );
+      Assert( m_second.valid(), "The second tree is invalid!" );
+    }
+    // ============================================================================
+    // constructor from two trees
+    // ============================================================================
+    PolarizationAngle::PolarizationAngle( const Decays::IGenDecay::iTree& daughter,
+                                          const Decays::IGenDecay::iTree& parent, const bool mother )
+        : m_first( daughter ), m_second( parent ), m_mother( mother ) {
+      Assert( m_first.valid(), "The first  tree is invalid!" );
+      Assert( m_second.valid(), "The second tree is invalid!" );
+    }
+    // ============================================================================
+    // constructor from two nodes
+    // ============================================================================
+    PolarizationAngle::PolarizationAngle( const Decays::iNode& daughter, const Decays::iNode& parent,
+                                          const bool mother )
+        : m_first( daughter ), m_second( parent ), m_mother( mother ) {
+      Assert( m_first.valid(), "The first  tree is invalid!" );
+      Assert( m_second.valid(), "The second tree is invalid!" );
+    }
+    // ============================================================================
+    // constructor from two cuts
+    // ============================================================================
+    PolarizationAngle::PolarizationAngle( const LoKi::GenTypes::GCuts& daughter, const LoKi::GenTypes::GCuts& parent,
+                                          const bool mother )
+        : m_first( daughter ), m_second( parent ), m_mother( mother ) {
+      Assert( m_first.valid(), "The first  tree is invalid!" );
+      Assert( m_second.valid(), "The second tree is invalid!" );
+    }
+    // ============================================================================
+    // constructor from two trees
+    // ============================================================================
+    PolarizationAngle::PolarizationAngle( const std::string& daughter, const std::string& parent, const bool mother,
+                                          const std::string& factory )
+        : m_first( daughter, factory ), m_second( parent, factory ), m_mother( mother ) {
+      Assert( m_first.valid(), "The first  tree is invalid!" );
+      Assert( m_second.valid(), "The second tree is invalid!" );
+    }
+    // ============================================================================
+    // MANDATORY: clone method ("virtual constructor")
+    // ============================================================================
+    PolarizationAngle* PolarizationAngle::clone() const { return new PolarizationAngle( *this ); }
+    // ============================================================================
+    // get the proper decay components
+    // ==========================================================================
+    StatusCode PolarizationAngle::getComponents12( const HepMC3::ConstGenParticlePtr & p,
+                                                   Decays::IGenDecay::iTree::Collection& vct ) const {
+      //
+      if ( 0 == p ) {
+        Error( "HepMC3::GenParticlePtr points to NULL" );
+        return StatusCode::FAILURE; //                                 RETURN
+      }
+      //
+      Assert( m_first.valid(), "The first  tree is invalid!" );
+      Assert( m_second.valid(), "The second tree is invalid!" );
+      //
+      HepMC3::ConstGenParticlePtr c1 = m_first.child( p );
+      if ( 0 == c1 ) {
+        Error( "Invalid first  child : '" + m_first.printOut() + "'" );
+        return StatusCode::FAILURE;
+      }
+      vct.push_back( c1 );
+      //
+      HepMC3::ConstGenParticlePtr c2 = m_second.child( p );
+      if ( 0 == c2 ) {
+        Error( "Invalid second child : '" + m_second.printOut() + "'" );
+        return StatusCode::FAILURE;
+      }
+      vct.push_back( c2 );
+      //
+      return StatusCode::SUCCESS;
+    }
+    // ==========================================================================
+    // MANDATORY: the only one essential method
+    // ==========================================================================
+    double PolarizationAngle::operator()( const HepMC3::ConstGenParticlePtr & p ) const {
+      if ( 0 == p ) {
+        Error( "HepMC3::GenParticlePtr points to NULL" );
+        return 1.0; //                                 RETURN
+      }
+      //
+      Decays::IGenDecay::iTree::Collection vct;
+      vct.reserve( 2 );
+      StatusCode sc = getComponents12( p, vct );
+
+      if ( sc.isFailure() ) {
+        Error( "Unable to get proper decay components (1), return 'InvalidAngle'", sc );
+        return LoKi::Constants::InvalidAngle;
+      }
+      if ( 2 != vct.size() ) {
+        Error( "Unable to get proper decay components (1), return 'InvalidAngle'", sc );
+        return LoKi::Constants::InvalidAngle;
+      }
+      //
+      return m_mother ? LoKi::Kinematics::decayAngle( LoKi::LorentzVector( vct[0]->momentum() ),
+                                                      LoKi::LorentzVector( vct[1]->momentum() ),
+                                                      LoKi::LorentzVector( p->momentum() ) )
+                      : LoKi::Kinematics::decayAngle( LoKi::LorentzVector( vct[0]->momentum() ),
+                                                      LoKi::LorentzVector( vct[0]->momentum() ) +
+                                                          LoKi::LorentzVector( vct[1]->momentum() ),
+                                                      LoKi::LorentzVector( p->momentum() ) );
+    }
+    // ============================================================================
+    // OPTIONAL: the nice printout
+    // ============================================================================
+    std::ostream& PolarizationAngle::fillStream( std::ostream& s ) const {
+      s << " GCOSPOL( " << m_first << " , " << m_second;
+      //
+      if ( !m_mother ) {
+        s << " , ";
+        Gaudi::Utils::toStream( m_mother, s );
+      }
+      //
+      return s << " ) ";
+    }
+
+    // ============================================================================
+    // constructor from child-selector
+    // ============================================================================
+    SinChi::SinChi( const LoKi::GenChild::Selector& particle1, const LoKi::GenChild::Selector& particle2,
+                    const LoKi::GenChild::Selector& particle3, const LoKi::GenChild::Selector& particle4 )
+        : PolarizationAngle( particle1, particle2, false ), m_tree3( particle3 ), m_tree4( particle4 ) {
+      //
+      Assert( m_tree3.valid(), "The third tree is invalid" );
+      Assert( m_tree4.valid(), "The fourh tree is invalid" );
+      //
+    }
+    // ============================================================================
+    // constructor from the trees
+    // ============================================================================
+    SinChi::SinChi( const Decays::IGenDecay::iTree& particle1, const Decays::IGenDecay::iTree& particle2,
+                    const Decays::IGenDecay::iTree& particle3, const Decays::IGenDecay::iTree& particle4 )
+        : PolarizationAngle( particle1, particle2, false ), m_tree3( particle3 ), m_tree4( particle4 ) {
+      //
+      Assert( m_tree3.valid(), "The third tree is invalid" );
+      Assert( m_tree4.valid(), "The fourh tree is invalid" );
+      //
+    }
+    // ============================================================================
+    // constructor from the nodes
+    // ============================================================================
+    SinChi::SinChi( const Decays::iNode& particle1, const Decays::iNode& particle2, const Decays::iNode& particle3,
+                    const Decays::iNode& particle4 )
+        : PolarizationAngle( particle1, particle2, false ), m_tree3( particle3 ), m_tree4( particle4 ) {
+      //
+      Assert( m_tree3.valid(), "The third tree is invalid" );
+      Assert( m_tree4.valid(), "The fourh tree is invalid" );
+      //
+    }
+    // ============================================================================
+    // constructor from the cuts
+    // ============================================================================
+    SinChi::SinChi( const LoKi::GenTypes::GCuts& particle1, const LoKi::GenTypes::GCuts& particle2,
+                    const LoKi::GenTypes::GCuts& particle3, const LoKi::GenTypes::GCuts& particle4 )
+        : PolarizationAngle( particle1, particle2, false ), m_tree3( particle3 ), m_tree4( particle4 ) {
+      //
+      Assert( m_tree3.valid(), "The third tree is invalid" );
+      Assert( m_tree4.valid(), "The fourh tree is invalid" );
+      //
+    }
+    // ============================================================================
+    // constructor from the trees
+    // ============================================================================
+    SinChi::SinChi( const std::string& particle1, const std::string& particle2, const std::string& particle3,
+                    const std::string& particle4, const std::string& factory )
+        : PolarizationAngle( particle1, particle2, false, factory )
+        , m_tree3( particle3, factory )
+        , m_tree4( particle4, factory ) {
+      //
+      Assert( m_tree3.valid(), "The third tree is invalid" );
+      Assert( m_tree4.valid(), "The fourh tree is invalid" );
+      //
+    }
+    // ============================================================================
+    // get the proper decay components
+    // ==========================================================================
+    StatusCode SinChi::getComponents34( const HepMC3::ConstGenParticlePtr & p, Decays::IGenDecay::iTree::Collection& vct ) const {
+      //
+      if ( 0 == p ) {
+        Error( "LHCb::GenParticlePtr points to NULL" );
+        return StatusCode::FAILURE; //                                 RETURN
+      }
+      //
+      Assert( m_tree3.valid(), "The third  tree is invalid!" );
+      Assert( m_tree4.valid(), "The fourth tree is invalid!" );
+      //
+      HepMC3::ConstGenParticlePtr c1 = m_tree3.child( p );
+      if ( 0 == c1 ) {
+        Error( "Invalid third  child : '" + m_tree3.printOut() + "'" );
+        return StatusCode::FAILURE;
+      }
+      vct.push_back( c1 );
+      //
+      HepMC3::ConstGenParticlePtr c2 = m_tree4.child( p );
+      if ( 0 == c2 ) {
+        Error( "Invalid fourth child : '" + m_tree4.printOut() + "'" );
+        return StatusCode::FAILURE;
+      }
+      vct.push_back( c2 );
+      //
+      return StatusCode::SUCCESS;
+    }
+    // ============================================================================
+    // get the proper decay components
+    // ==========================================================================
+    StatusCode SinChi::getComponents( const HepMC3::ConstGenParticlePtr & p, Decays::IGenDecay::iTree::Collection& vct ) const {
+      vct.clear();
+      StatusCode sc1 = getComponents12( p, vct );
+      if ( sc1.isFailure() ) {
+        Error( "Unable to pickup 12-components", sc1 );
+        return sc1;
+      }
+      //
+      StatusCode sc2 = getComponents34( p, vct );
+      if ( sc2.isFailure() ) {
+        Error( "Unable to pickup 34-components", sc2 );
+        return sc2;
+      }
+      return StatusCode::SUCCESS;
+    }
+    // ============================================================================
+    // MANDATORY: clone method ("virtual constructor")
+    // ============================================================================
+    SinChi* SinChi::clone() const { return new SinChi( *this ); }
+    // ============================================================================
+    // MANDATORY: the only one essential method
+    // ============================================================================
+    double SinChi::operator()( const HepMC3::ConstGenParticlePtr & p ) const {
+      if ( 0 == p ) {
+        Error( "HepMC3::GenParticlePtr points to NULL, return 'Invaild Angle'" );
+        return LoKi::Constants::InvalidAngle;
+      }
+      //
+      Decays::IGenDecay::iTree::Collection daughters;
+      daughters.reserve( 4 );
+      //
+      StatusCode sc = getComponents( p, daughters );
+      //
+      if ( sc.isFailure() ) {
+        Error( "Unable to get proper decay components (1), return 'InvalidAngle'" );
+        return LoKi::Constants::InvalidAngle;
+      }
+      if ( 4 != daughters.size() ) {
+        Error( "Unable to get proper decay components (2) , return 'InvalidAngle'" );
+        return LoKi::Constants::InvalidAngle;
+      }
+      // finally evaluate the angle chi:
+      return LoKi::Kinematics::sinDecayAngleChi(
+          LoKi::LorentzVector( daughters[0]->momentum() ), LoKi::LorentzVector( daughters[1]->momentum() ),
+          LoKi::LorentzVector( daughters[2]->momentum() ), LoKi::LorentzVector( daughters[3]->momentum() ) );
+    }
+    // ============================================================================
+    // OPTIONAL: the nice printout
+    // ============================================================================
+    std::ostream& SinChi::fillStream( std::ostream& s ) const {
+      s << " GSINCHI( "
+        << "'" << child1() << "','" << child2() << "','" << child3() << "','" << child4() << "'";
+      //
+      return s << " ) ";
+    }
+    // ============================================================================
+
+    // ============================================================================
+    // constructor from selectors
+    // ============================================================================
+    CosChi::CosChi( const LoKi::GenChild::Selector& particle1, const LoKi::GenChild::Selector& particle2,
+                    const LoKi::GenChild::Selector& particle3, const LoKi::GenChild::Selector& particle4 )
+        : SinChi( particle1, particle2, particle3, particle4 ) {}
+    // ============================================================================
+    // constructor form the trees
+    // ============================================================================
+    CosChi::CosChi( const Decays::IGenDecay::iTree& particle1, const Decays::IGenDecay::iTree& particle2,
+                    const Decays::IGenDecay::iTree& particle3, const Decays::IGenDecay::iTree& particle4 )
+        : SinChi( particle1, particle2, particle3, particle4 ) {}
+    // ============================================================================
+    // constructor from the nodes
+    // ============================================================================
+    CosChi::CosChi( const Decays::iNode& particle1, const Decays::iNode& particle2, const Decays::iNode& particle3,
+                    const Decays::iNode& particle4 )
+        : SinChi( particle1, particle2, particle3, particle4 ) {}
+    // ============================================================================
+    // constructor form the cuts
+    // ============================================================================
+    CosChi::CosChi( const LoKi::GenTypes::GCuts& particle1, const LoKi::GenTypes::GCuts& particle2,
+                    const LoKi::GenTypes::GCuts& particle3, const LoKi::GenTypes::GCuts& particle4 )
+        : SinChi( particle1, particle2, particle3, particle4 ) {}
+    // ============================================================================
+    // constructor from the decay descriptors
+    // ============================================================================
+    CosChi::CosChi( const std::string& particle1, const std::string& particle2, const std::string& particle3,
+                    const std::string& particle4, const std::string& factory )
+        : SinChi( particle1, particle2, particle3, particle4, factory ) {}
+    // ============================================================================
+    // MANDATORY: clone method ("virtual constructor")
+    // ============================================================================
+    CosChi* CosChi::clone() const { return new CosChi( *this ); }
+    // ============================================================================
+    // MANDATORY: the only one essential method
+    // ============================================================================
+    double CosChi::operator()( const HepMC3::ConstGenParticlePtr & p ) const {
+      if ( 0 == p ) {
+        Error( "HepMC3::GenParticlePtr points to NULL, return 'Invaild Angle'" );
+        return LoKi::Constants::InvalidAngle;
+      }
+      //
+      Decays::IGenDecay::iTree::Collection daughters;
+      daughters.reserve( 4 );
+      //
+      StatusCode sc = getComponents( p, daughters );
+      //
+      if ( sc.isFailure() ) {
+        Error( "Unable to get proper decay components (1), return 'InvalidAngle'" );
+        return LoKi::Constants::InvalidAngle;
+      }
+      if ( 4 != daughters.size() ) {
+        Error( "Unable to get proper decay components (2) , return 'InvalidAngle'" );
+        return LoKi::Constants::InvalidAngle;
+      }
+      // finally evaluate the angle chi:
+      return LoKi::Kinematics::cosDecayAngleChi(
+          LoKi::LorentzVector( daughters[0]->momentum() ), LoKi::LorentzVector( daughters[1]->momentum() ),
+          LoKi::LorentzVector( daughters[2]->momentum() ), LoKi::LorentzVector( daughters[3]->momentum() ) );
+    }
+    // ============================================================================
+    // OPTIONAL: the nice printout
+    // ============================================================================
+    std::ostream& CosChi::fillStream( std::ostream& s ) const {
+      s << " GCOSCHI( "
+        << "'" << child1() << "','" << child2() << "','" << child3() << "','" << child4() << "'";
+      //
+      return s << " ) ";
+    }
+    // ============================================================================
+
+    // ============================================================================
+    // constructor from child-selector
+    // ============================================================================
+    AngleChi::AngleChi( const LoKi::GenChild::Selector& particle1, const LoKi::GenChild::Selector& particle2,
+                        const LoKi::GenChild::Selector& particle3, const LoKi::GenChild::Selector& particle4 )
+        : CosChi( particle1, particle2, particle3, particle4 ) {}
+    // ============================================================================
+    // constructor from the trees
+    // ============================================================================
+    AngleChi::AngleChi( const Decays::IGenDecay::iTree& particle1, const Decays::IGenDecay::iTree& particle2,
+                        const Decays::IGenDecay::iTree& particle3, const Decays::IGenDecay::iTree& particle4 )
+        : CosChi( particle1, particle2, particle3, particle4 ) {}
+    // ============================================================================
+    // constructor from the nodes
+    // ============================================================================
+    AngleChi::AngleChi( const Decays::iNode& particle1, const Decays::iNode& particle2, const Decays::iNode& particle3,
+                        const Decays::iNode& particle4 )
+        : CosChi( particle1, particle2, particle3, particle4 ) {}
+    // ============================================================================
+    // constructor form the cuts
+    // ============================================================================
+    AngleChi::AngleChi( const LoKi::GenTypes::GCuts& particle1, const LoKi::GenTypes::GCuts& particle2,
+                        const LoKi::GenTypes::GCuts& particle3, const LoKi::GenTypes::GCuts& particle4 )
+        : CosChi( particle1, particle2, particle3, particle4 ) {}
+    // ============================================================================
+    // constructor from the decay descriptors
+    // ============================================================================
+    AngleChi::AngleChi( const std::string& particle1, const std::string& particle2, const std::string& particle3,
+                        const std::string& particle4, const std::string& factory )
+        : CosChi( particle1, particle2, particle3, particle4, factory ) {}
+    // ============================================================================
+    // MANDATORY: clone method ("virtual constructor")
+    // ============================================================================
+    AngleChi* AngleChi::clone() const { return new AngleChi( *this ); }
+    // ============================================================================
+    // MANDATORY: the only one essential method
+    // ============================================================================
+    double AngleChi::operator()( const HepMC3::ConstGenParticlePtr & p ) const {
+      if ( 0 == p ) {
+        Error( "HepMC3::GenParticlePtr points to NULL, return 'Invaild Angle'" );
+        return LoKi::Constants::InvalidAngle;
+      }
+      //
+      Decays::IGenDecay::iTree::Collection daughters;
+      daughters.reserve( 4 );
+      //
+      StatusCode sc = getComponents( p, daughters );
+      //
+      if ( sc.isFailure() ) {
+        Error( "Unable to get proper decay components (1), return 'InvalidAngle'" );
+        return LoKi::Constants::InvalidAngle;
+      }
+      if ( 4 != daughters.size() ) {
+        Error( "Unable to get proper decay components (2) , return 'InvalidAngle'" );
+        return LoKi::Constants::InvalidAngle;
+      }
+      // finally evaluate the angle chi:
+      return LoKi::Kinematics::decayAngleChi(
+          LoKi::LorentzVector( daughters[0]->momentum() ), LoKi::LorentzVector( daughters[1]->momentum() ),
+          LoKi::LorentzVector( daughters[2]->momentum() ), LoKi::LorentzVector( daughters[3]->momentum() ) );
+    }
+    // ============================================================================
+    // OPTIONAL: the nice printout
+    // ============================================================================
+    std::ostream& AngleChi::fillStream( std::ostream& s ) const {
+      s << " GANGLECHI( "
+        << "'" << child1() << "','" << child2() << "','" << child3() << "','" << child4() << "'";
+      //
+      return s << " ) ";
+    }
+    // ============================================================================
+
+    // ============================================================================
+    // constructor from child-selector
+    // ============================================================================
+    CosThetaTr::CosThetaTr( const LoKi::GenChild::Selector& particle1, const LoKi::GenChild::Selector& particle2,
+                            const LoKi::GenChild::Selector& particle3, const LoKi::GenChild::Selector& particle4 )
+        : AngleChi( particle1, particle2, particle3, particle4 ) {}
+    // ============================================================================
+    // constructor from the trees
+    // ============================================================================
+    CosThetaTr::CosThetaTr( const Decays::IGenDecay::iTree& particle1, const Decays::IGenDecay::iTree& particle2,
+                            const Decays::IGenDecay::iTree& particle3, const Decays::IGenDecay::iTree& particle4 )
+        : AngleChi( particle1, particle2, particle3, particle4 ) {}
+    // ============================================================================
+    // constructor from the nodes
+    // ============================================================================
+    CosThetaTr::CosThetaTr( const Decays::iNode& particle1, const Decays::iNode& particle2,
+                            const Decays::iNode& particle3, const Decays::iNode& particle4 )
+        : AngleChi( particle1, particle2, particle3, particle4 ) {}
+    // ============================================================================
+    // constructor form the cuts
+    // ============================================================================
+    CosThetaTr::CosThetaTr( const LoKi::GenTypes::GCuts& particle1, const LoKi::GenTypes::GCuts& particle2,
+                            const LoKi::GenTypes::GCuts& particle3, const LoKi::GenTypes::GCuts& particle4 )
+        : AngleChi( particle1, particle2, particle3, particle4 ) {}
+    // ============================================================================
+    // constructor from the decay descriptors
+    // ============================================================================
+    CosThetaTr::CosThetaTr( const std::string& particle1, const std::string& particle2, const std::string& particle3,
+                            const std::string& particle4, const std::string& factory )
+        : AngleChi( particle1, particle2, particle3, particle4, factory ) {}
+    // ============================================================================
+    // MANDATORY: clone method ("virtual constructor")
+    // ============================================================================
+    CosThetaTr* CosThetaTr::clone() const { return new CosThetaTr( *this ); }
+    // ============================================================================
+    // MANDATORY: the only one essential method
+    // ============================================================================
+    double CosThetaTr::operator()( const HepMC3::ConstGenParticlePtr & p ) const {
+      if ( 0 == p ) {
+        Error( "HepMC3::GenParticlePtr points to NULL, return 'Invaild Angle'" );
+        return LoKi::Constants::InvalidAngle;
+      }
+      //
+      Decays::IGenDecay::iTree::Collection daughters;
+      daughters.reserve( 4 );
+      //
+      StatusCode sc = getComponents( p, daughters );
+      //
+      if ( sc.isFailure() ) {
+        Error( "Unable to get proper decay components (1), return 'InvalidAngle'" );
+        return LoKi::Constants::InvalidAngle;
+      }
+      if ( 4 != daughters.size() ) {
+        Error( "Unable to get proper decay components (2) , return 'InvalidAngle'" );
+        return LoKi::Constants::InvalidAngle;
+      }
+      // finally evaluate the angle chi:
+      return LoKi::Kinematics::cosThetaTr(
+          LoKi::LorentzVector( daughters[0]->momentum() ), LoKi::LorentzVector( daughters[1]->momentum() ),
+          LoKi::LorentzVector( daughters[2]->momentum() ), LoKi::LorentzVector( daughters[3]->momentum() ) );
+    }
+    // ============================================================================
+    // OPTIONAL: the nice printout
+    // ============================================================================
+    std::ostream& CosThetaTr::fillStream( std::ostream& s ) const {
+      s << " GCOSTHETATR( "
+        << "'" << child1() << "','" << child2() << "','" << child3() << "','" << child4() << "'";
+      //
+      return s << " ) ";
+    }
+    // ============================================================================
+
+    // ============================================================================
+    // constructor from child-selector
+    // ============================================================================
+    SinPhiTr::SinPhiTr( const LoKi::GenChild::Selector& particle1, const LoKi::GenChild::Selector& particle2,
+                        const LoKi::GenChild::Selector& particle3, const LoKi::GenChild::Selector& particle4 )
+        : CosThetaTr( particle1, particle2, particle3, particle4 ) {}
+    // ============================================================================
+    // constructor from the trees
+    // ============================================================================
+    SinPhiTr::SinPhiTr( const Decays::IGenDecay::iTree& particle1, const Decays::IGenDecay::iTree& particle2,
+                        const Decays::IGenDecay::iTree& particle3, const Decays::IGenDecay::iTree& particle4 )
+        : CosThetaTr( particle1, particle2, particle3, particle4 ) {}
+    // ============================================================================
+    // constructor from the nodes
+    // ============================================================================
+    SinPhiTr::SinPhiTr( const Decays::iNode& particle1, const Decays::iNode& particle2, const Decays::iNode& particle3,
+                        const Decays::iNode& particle4 )
+        : CosThetaTr( particle1, particle2, particle3, particle4 ) {}
+    // ============================================================================
+    // constructor form the cuts
+    // ============================================================================
+    SinPhiTr::SinPhiTr( const LoKi::GenTypes::GCuts& particle1, const LoKi::GenTypes::GCuts& particle2,
+                        const LoKi::GenTypes::GCuts& particle3, const LoKi::GenTypes::GCuts& particle4 )
+        : CosThetaTr( particle1, particle2, particle3, particle4 ) {}
+    // ============================================================================
+    // constructor from the decay descriptors
+    // ============================================================================
+    SinPhiTr::SinPhiTr( const std::string& particle1, const std::string& particle2, const std::string& particle3,
+                        const std::string& particle4, const std::string& factory )
+        : CosThetaTr( particle1, particle2, particle3, particle4, factory ) {}
+    // ============================================================================
+    // MANDATORY: clone method ("virtual constructor")
+    // ============================================================================
+    SinPhiTr* SinPhiTr::clone() const { return new SinPhiTr( *this ); }
+    // ============================================================================
+    // MANDATORY: the only one essential method
+    // ============================================================================
+    double SinPhiTr::operator()( const HepMC3::ConstGenParticlePtr & p ) const {
+      if ( 0 == p ) {
+        Error( "HepMC3::GenParticlePtr points to NULL, return 'Invaild Angle'" );
+        return LoKi::Constants::InvalidAngle;
+      }
+      //
+      Decays::IGenDecay::iTree::Collection daughters;
+      daughters.reserve( 4 );
+      //
+      StatusCode sc = getComponents( p, daughters );
+      //
+      if ( sc.isFailure() ) {
+        Error( "Unable to get proper decay components (1), return 'InvalidAngle'" );
+        return LoKi::Constants::InvalidAngle;
+      }
+      if ( 4 != daughters.size() ) {
+        Error( "Unable to get proper decay components (2) , return 'InvalidAngle'" );
+        return LoKi::Constants::InvalidAngle;
+      }
+      // finally evaluate the angle chi:
+      return LoKi::Kinematics::sinPhiTr(
+          LoKi::LorentzVector( daughters[0]->momentum() ), LoKi::LorentzVector( daughters[1]->momentum() ),
+          LoKi::LorentzVector( daughters[2]->momentum() ), LoKi::LorentzVector( daughters[3]->momentum() ) );
+    }
+    // ============================================================================
+    // OPTIONAL: the nice printout
+    // ============================================================================
+    std::ostream& SinPhiTr::fillStream( std::ostream& s ) const {
+      s << " GSINPHITR( "
+        << "'" << child1() << "','" << child2() << "','" << child3() << "','" << child4() << "'";
+      //
+      return s << " ) ";
+    }
+    // ============================================================================
+
+    // ============================================================================
+    // constructor from child-selector
+    // ============================================================================
+    CosPhiTr::CosPhiTr( const LoKi::GenChild::Selector& particle1, const LoKi::GenChild::Selector& particle2,
+                        const LoKi::GenChild::Selector& particle3, const LoKi::GenChild::Selector& particle4 )
+        : SinPhiTr( particle1, particle2, particle3, particle4 ) {}
+    // ============================================================================
+    // constructor from the trees
+    // ============================================================================
+    CosPhiTr::CosPhiTr( const Decays::IGenDecay::iTree& particle1, const Decays::IGenDecay::iTree& particle2,
+                        const Decays::IGenDecay::iTree& particle3, const Decays::IGenDecay::iTree& particle4 )
+        : SinPhiTr( particle1, particle2, particle3, particle4 ) {}
+    // ============================================================================
+    // constructor from the nodes
+    // ============================================================================
+    CosPhiTr::CosPhiTr( const Decays::iNode& particle1, const Decays::iNode& particle2, const Decays::iNode& particle3,
+                        const Decays::iNode& particle4 )
+        : SinPhiTr( particle1, particle2, particle3, particle4 ) {}
+    // ============================================================================
+    // constructor form the cuts
+    // ============================================================================
+    CosPhiTr::CosPhiTr( const LoKi::GenTypes::GCuts& particle1, const LoKi::GenTypes::GCuts& particle2,
+                        const LoKi::GenTypes::GCuts& particle3, const LoKi::GenTypes::GCuts& particle4 )
+        : SinPhiTr( particle1, particle2, particle3, particle4 ) {}
+    // ============================================================================
+    // constructor from the decay descriptors
+    // ============================================================================
+    CosPhiTr::CosPhiTr( const std::string& particle1, const std::string& particle2, const std::string& particle3,
+                        const std::string& particle4, const std::string& factory )
+        : SinPhiTr( particle1, particle2, particle3, particle4, factory ) {}
+    // ============================================================================
+    // MANDATORY: clone method ("virtual constructor")
+    // ============================================================================
+    CosPhiTr* CosPhiTr::clone() const { return new CosPhiTr( *this ); }
+    // ============================================================================
+    // MANDATORY: the only one essential method
+    // ============================================================================
+    double CosPhiTr::operator()( const HepMC3::ConstGenParticlePtr & p ) const {
+      if ( 0 == p ) {
+        Error( "HepMC3::GenParticlePtr points to NULL, return 'Invaild Angle'" );
+        return LoKi::Constants::InvalidAngle;
+      }
+      //
+      Decays::IGenDecay::iTree::Collection daughters;
+      daughters.reserve( 4 );
+      //
+      StatusCode sc = getComponents( p, daughters );
+      //
+      if ( sc.isFailure() ) {
+        Error( "Unable to get proper decay components (1), return 'InvalidAngle'" );
+        return LoKi::Constants::InvalidAngle;
+      }
+      if ( 4 != daughters.size() ) {
+        Error( "Unable to get proper decay components (2) , return 'InvalidAngle'" );
+        return LoKi::Constants::InvalidAngle;
+      }
+      // finally evaluate the cos(phi_tr)
+      return LoKi::Kinematics::cosPhiTr(
+          LoKi::LorentzVector( daughters[0]->momentum() ), LoKi::LorentzVector( daughters[1]->momentum() ),
+          LoKi::LorentzVector( daughters[2]->momentum() ), LoKi::LorentzVector( daughters[3]->momentum() ) );
+    }
+    // ============================================================================
+    // OPTIONAL: the nice printout
+    // ============================================================================
+    std::ostream& CosPhiTr::fillStream( std::ostream& s ) const {
+      s << " GCOSPHITR( "
+        << "'" << child1() << "','" << child2() << "','" << child3() << "','" << child4() << "'";
+      //
+      return s << " ) ";
+    }
+    // ============================================================================
+
+    // ============================================================================
+    // constructor from child-selector
+    // ============================================================================
+    AnglePhiTr::AnglePhiTr( const LoKi::GenChild::Selector& particle1, const LoKi::GenChild::Selector& particle2,
+                            const LoKi::GenChild::Selector& particle3, const LoKi::GenChild::Selector& particle4 )
+        : CosPhiTr( particle1, particle2, particle3, particle4 ) {}
+    // ============================================================================
+    // constructor from the trees
+    // ============================================================================
+    AnglePhiTr::AnglePhiTr( const Decays::IGenDecay::iTree& particle1, const Decays::IGenDecay::iTree& particle2,
+                            const Decays::IGenDecay::iTree& particle3, const Decays::IGenDecay::iTree& particle4 )
+        : CosPhiTr( particle1, particle2, particle3, particle4 ) {}
+    // ============================================================================
+    // constructor from the nodes
+    // ============================================================================
+    AnglePhiTr::AnglePhiTr( const Decays::iNode& particle1, const Decays::iNode& particle2,
+                            const Decays::iNode& particle3, const Decays::iNode& particle4 )
+        : CosPhiTr( particle1, particle2, particle3, particle4 ) {}
+    // ============================================================================
+    // constructor form the cuts
+    // ============================================================================
+    AnglePhiTr::AnglePhiTr( const LoKi::GenTypes::GCuts& particle1, const LoKi::GenTypes::GCuts& particle2,
+                            const LoKi::GenTypes::GCuts& particle3, const LoKi::GenTypes::GCuts& particle4 )
+        : CosPhiTr( particle1, particle2, particle3, particle4 ) {}
+    // ============================================================================
+    // constructor from the decay descriptors
+    // ============================================================================
+    AnglePhiTr::AnglePhiTr( const std::string& particle1, const std::string& particle2, const std::string& particle3,
+                            const std::string& particle4, const std::string& factory )
+        : CosPhiTr( particle1, particle2, particle3, particle4, factory ) {}
+    // ============================================================================
+    // MANDATORY: clone method ("virtual constructor")
+    // ============================================================================
+    AnglePhiTr* AnglePhiTr::clone() const { return new AnglePhiTr( *this ); }
+    // ============================================================================
+    // MANDATORY: the only one essential method
+    // ============================================================================
+    double AnglePhiTr::operator()( const HepMC3::ConstGenParticlePtr & p ) const {
+      if ( 0 == p ) {
+        Error( "HepMC3::GenParticlePtr points to NULL, return 'Invaild Angle'" );
+        return LoKi::Constants::InvalidAngle;
+      }
+      //
+      Decays::IGenDecay::iTree::Collection daughters;
+      daughters.reserve( 4 );
+      //
+      StatusCode sc = getComponents( p, daughters );
+      //
+      if ( sc.isFailure() ) {
+        Error( "Unable to get proper decay components (1), return 'InvalidAngle'" );
+        return LoKi::Constants::InvalidAngle;
+      }
+      if ( 4 != daughters.size() ) {
+        Error( "Unable to get proper decay components (2) , return 'InvalidAngle'" );
+        return LoKi::Constants::InvalidAngle;
+      }
+      // finally evaluate the phi_tr
+      return LoKi::Kinematics::anglePhiTr(
+          LoKi::LorentzVector( daughters[0]->momentum() ), LoKi::LorentzVector( daughters[1]->momentum() ),
+          LoKi::LorentzVector( daughters[2]->momentum() ), LoKi::LorentzVector( daughters[3]->momentum() ) );
+    }
+    // ============================================================================
+    // OPTIONAL: the nice printout
+    // ============================================================================
+    std::ostream& AnglePhiTr::fillStream( std::ostream& s ) const {
+      s << " GANGLEPHITR( "
+        << "'" << child1() << "','" << child2() << "','" << child3() << "','" << child4() << "'";
+      //
+      return s << " ) ";
+    }
+    // ============================================================================
+
+  } // namespace GenParticles
+} // namespace LoKi
+
+// ============================================================================
+// The END
+// ============================================================================
diff --git a/Gen/LoKiGen/src/GenParticles3.cpp b/Gen/LoKiGen/src/GenParticles3.cpp
new file mode 100644
index 000000000..15193225d
--- /dev/null
+++ b/Gen/LoKiGen/src/GenParticles3.cpp
@@ -0,0 +1,143 @@
+/*****************************************************************************\
+* (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration      *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                             *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+// ============================================================================
+// Include files
+// ============================================================================
+// LoKiCore
+// ============================================================================
+#include "LoKi/Algs.h"
+// ============================================================================
+// LoKiGen
+// ============================================================================
+#include "LoKi/GenAlgs.h"
+#include "LoKi/GenExtract.h"
+#include "LoKi/GenParticles3.h"
+#include "HepMCUtils/HepMCUtils.h"
+// ============================================================================
+/** @file
+ *
+ *  This file is a part of LoKi project -
+ *    "C++ ToolKit  for Smart and Friendly Physics Analysis"
+ *
+ *  The package has been designed with the kind help from
+ *  Galina PAKHLOVA and Sergey BARSUK.  Many bright ideas,
+ *  contributions and advices from G.Raven, J.van Tilburg,
+ *  A.Golutvin, P.Koppenburg have been used in the design.
+ *
+ *  @author Vanya BELYAEV Ivan.Belyaev@itep.ru
+ *  @date 2012-01-28
+ *
+ */
+// ============================================================================
+namespace {
+  // ==========================================================================
+  inline std::size_t count_parts( const HepMC3::ConstGenVertexPtr & v, const HepMC3::Relatives & r, const LoKi::GenTypes::GCut& c ) {
+    auto particles = r(v);
+    return v ? LoKi::Algs::count_if( std::begin(particles), std::end(particles), c.func() ) : 0;
+  }
+  // ==========================================================================
+  inline bool has_parts( const HepMC3::ConstGenVertexPtr & v, const HepMC3::Relatives & r, const LoKi::GenTypes::GCut& c ) {
+    auto particles = r(v);
+    return v && LoKi::Algs::found( std::begin(particles), std::end(particles), c.func() );
+  }
+  // ==========================================================================
+} // namespace
+
+namespace LoKi {
+  namespace GenParticles {
+    // ============================================================================
+    /*  constructor from the criteria and "range"
+     *  @param cut the criteria
+     *  @param range search region
+     *  @see const HepMC3::Relatives &
+     */
+    // ============================================================================
+    Count::Count( const LoKi::Types::GCuts& cut, const HepMC3::Relatives & range ) : m_cut( cut ), m_range( range ) {}
+    // ============================================================================
+    /*  constructor from the criteria and "range"
+     *  @param cut the criteria
+     *  @param range search region
+     *  @see const HepMC3::Relatives &
+     */
+    // ============================================================================
+    Count::Count( const HepMC3::Relatives & range, const LoKi::Types::GCuts& cut ) : m_cut( cut ), m_range( range ) {}
+    // ============================================================================
+    // MANDATORY: clone method ("virtual contructor")
+    // ============================================================================
+    Count* Count::clone() const { return new Count( *this ); }
+    // ============================================================================
+    // MANDATORY: the only one essential method
+    // ============================================================================
+    double Count::operator()( const HepMC3::ConstGenParticlePtr & p ) const {
+      //
+      if ( !p ) {
+        Error( "HepMC3::GenParticlePtr points to NULL, return -1000 " );
+        return -1000;
+      }
+      // This should now automatically select the correct vertex
+      return count_parts( p->production_vertex(), m_range, m_cut ); // RETURN
+    }
+    // ============================================================================
+    //  "SHORT" representation, @see LoKi::AuxFunBase
+    // ============================================================================
+    std::ostream& Count::fillStream( std::ostream& stream ) const {
+      stream << " GCOUNT(" << m_cut << ",";
+      stream << HepMCUtils::RelationToString(m_range);
+      return stream << ") ";
+    }
+    // ============================================================================
+
+    // ============================================================================
+    /*  constructor from the criteria and "range"
+     *  @param cut the criteria
+     *  @param range search region
+     *  @see const HepMC3::Relatives &
+     */
+    // ============================================================================
+    Has::Has( const LoKi::Types::GCuts& cut, const HepMC3::Relatives & range ) : m_cut( cut ), m_range( range ) {}
+    // ============================================================================
+    /*  constructor from the criteria and "range"
+     *  @param cut the criteria
+     *  @param range search region
+     *  @see const HepMC3::Relatives &
+     */
+    // ============================================================================
+    Has::Has( const HepMC3::Relatives & range, const LoKi::Types::GCuts& cut ) : m_cut( cut ), m_range( range ) {}
+    // ============================================================================
+    // MANDATORY: clone method ("virtual contructor")
+    // ============================================================================
+    Has* Has::clone() const { return new Has( *this ); }
+    // ============================================================================
+    // MANDATORY: the only one essential method
+    // ============================================================================
+    bool Has::operator()( const HepMC3::ConstGenParticlePtr & p ) const {
+      //
+      if ( !p ) {
+        Error( "HepMC3::GenParticlePtr points to NULL, return false" );
+        return false;
+      }
+      return has_parts( p->production_vertex(), m_range, m_cut ); // RETURN
+    }
+    // ============================================================================
+    //  "SHORT" representation, @see LoKi::AuxFunBase
+    // ============================================================================
+    std::ostream& Has::fillStream( std::ostream& stream ) const {
+      stream << " GHAS(" << m_cut << ",";
+      stream << HepMCUtils::RelationToString(m_range);
+      return stream << ") ";
+    }
+
+  } // namespace GenParticles
+} // namespace LoKi
+
+// ============================================================================
+// The END
+// ============================================================================
diff --git a/Gen/LoKiGen/src/GenParticles4.cpp b/Gen/LoKiGen/src/GenParticles4.cpp
new file mode 100644
index 000000000..5e97a6629
--- /dev/null
+++ b/Gen/LoKiGen/src/GenParticles4.cpp
@@ -0,0 +1,691 @@
+/*****************************************************************************\
+* (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration      *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                             *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+// =============================================================================
+// Include files
+// =============================================================================
+// LHCbMath
+// =============================================================================
+#include "LHCbMath/LHCbMath.h"
+// =============================================================================
+// Local
+// =============================================================================
+#include "LoKi/Constants.h"
+#include "LoKi/GenChildSelector.h"
+#include "LoKi/GenParticles4.h"
+#include "LoKi/Kinematics.h"
+// =============================================================================
+// GaudiKernel
+// =============================================================================
+#include "GaudiKernel/ToStream.h"
+// =============================================================================
+/** @file
+ *
+ *  This file is a part of LoKi project -
+ *    "C++ ToolKit  for Smart and Friendly Physics Analysis"
+ *
+ *  The package has been designed with the kind help from
+ *  Galina PAKHLOVA and Sergey BARSUK.  Many bright ideas,
+ *  contributions and advices from G.Raven, J.van Tilburg,
+ *  A.Golutvin, P.Koppenburg have been used in the design.
+ *
+ *  @author Vanya BELYAEV Ivan.Belyaev@itep.ru
+ *  @date 2012-01-28
+ *
+ */
+// ============================================================================
+namespace {
+  // ==========================================================================
+  /** @var s_equal
+   *  comparison criteria for doubles
+   */
+  const LHCb::Math::Equal_To<double> s_equal;
+  // ==========================================================================
+  // adjust delta phi into the range of [-180:180]degrees
+  // ============================================================================
+  double adjust( double angle ) {
+    static constexpr double s_180 = 180 * Gaudi::Units::degree;
+    static constexpr double s_360 = 360 * Gaudi::Units::degree;
+    //
+    while ( angle > s_180 ) { angle -= s_360; }
+    while ( angle < -1 * s_180 ) { angle += s_360; }
+    //
+    return angle;
+  }
+} // namespace
+
+namespace LoKi {
+  namespace GenParticles {
+    // ============================================================================
+    // constructor from one selector
+    // ============================================================================
+    FourMomentum::FourMomentum( const LoKi::GenChild::Selector& c1 ) : LoKi::GenTypes::GFunc(), m_children( 1, c1 ) {}
+    // ============================================================================
+    // constructor from two selectors
+    // ============================================================================
+    FourMomentum::FourMomentum( const LoKi::GenChild::Selector& c1, const LoKi::GenChild::Selector& c2 )
+        : m_children{c1, c2} {}
+    // ============================================================================
+    // constructor from three selectors
+    // ============================================================================
+    FourMomentum::FourMomentum( const LoKi::GenChild::Selector& c1, const LoKi::GenChild::Selector& c2,
+                                const LoKi::GenChild::Selector& c3 )
+        : m_children{c1, c2, c3} {}
+    // ============================================================================
+    // constructor from four selectors
+    // ============================================================================
+    FourMomentum::FourMomentum( const LoKi::GenChild::Selector& c1, const LoKi::GenChild::Selector& c2,
+                                const LoKi::GenChild::Selector& c3, const LoKi::GenChild::Selector& c4 )
+        : m_children{c1, c2, c3, c4} {}
+    // ============================================================================
+    // constructor from list of  selectors
+    // ============================================================================
+    FourMomentum::FourMomentum( const LoKi::GenChild::Selector::Vector& cs ) : m_children( cs ) {}
+    // ============================================================================
+    // constructor from one selector
+    // ============================================================================
+    FourMomentum::FourMomentum( const LoKi::GenTypes::GCuts& c1 ) : m_children( 1, c1 ) {}
+    // ============================================================================
+    // constructor from two selectors
+    // ============================================================================
+    FourMomentum::FourMomentum( const LoKi::GenTypes::GCuts& c1, const LoKi::GenTypes::GCuts& c2 )
+        : m_children{c1, c2} {}
+    // ============================================================================
+    // constructor from three selectors
+    // ============================================================================
+    FourMomentum::FourMomentum( const LoKi::GenTypes::GCuts& c1, const LoKi::GenTypes::GCuts& c2,
+                                const LoKi::GenTypes::GCuts& c3 )
+        : m_children{c1, c2, c3} {}
+    // ============================================================================
+    // constructor from four selectors
+    // ============================================================================
+    FourMomentum::FourMomentum( const LoKi::GenTypes::GCuts& c1, const LoKi::GenTypes::GCuts& c2,
+                                const LoKi::GenTypes::GCuts& c3, const LoKi::GenTypes::GCuts& c4 )
+        : m_children{c1, c2, c3, c4} {}
+    // ============================================================================
+    // base class printput
+    // ============================================================================
+    std::ostream& FourMomentum::print_( std::ostream& s, const std::string& n1, const std::string& n2 ) const {
+      //
+      if ( m_children.empty() ) { return s << n2; } // RETURN
+      //
+      if ( 4 < m_children.size() ) {
+        s << n1 << "([ ";
+        //
+        for ( auto ii = m_children.cbegin(); m_children.cend() != ii; ++ii ) {
+          if ( m_children.cbegin() != ii ) { s << ","; }
+          s << ( *ii );
+        }
+        //
+        return s << " ]) "; // REUTRN
+      }
+      //
+      s << n1 << "(";
+      for ( auto ii = m_children.cbegin(); m_children.cend() != ii; ++ii ) {
+        if ( m_children.cbegin() != ii ) { s << ","; }
+        s << ( *ii );
+      }
+      //
+      return s << ")";
+    }
+    // ============================================================================
+    // evaluate the full four momentum of combination
+    // ============================================================================
+    LoKi::LorentzVector FourMomentum::momentum( const HepMC3::ConstGenParticlePtr & p ) const {
+      if ( UNLIKELY( !p ) ) {
+        Error( "HepMC3::ConstGenParticlePtr & points to NULL, return empty 4-momentum" );
+        return LoKi::LorentzVector();
+      }
+      //
+      if ( m_children.empty() ) { return LoKi::LorentzVector( p->momentum() ); }
+      //
+      LoKi::LorentzVector result = LoKi::LorentzVector();
+      //
+      for ( auto ii = m_children.begin(); m_children.end() != ii; ++ii ) {
+        HepMC3::ConstGenParticlePtr c = ii->child( p );
+        if ( !c ) {
+          Error( "daughter HepMC3::ConstGenParticlePtr & points to NULL, skip it" );
+          continue;
+        }
+        result += LoKi::LorentzVector( c->momentum() );
+      }
+      //
+      return result;
+    }
+    // ============================================================================
+    // get the rapidity
+    // ============================================================================
+    double FourMomentum::y( const LoKi::LorentzVector& lv ) const {
+      const double e  = lv.E();
+      const double pz = lv.Pz();
+      //
+      return 0.5 * std::log( ( e + pz ) / ( e - pz ) );
+    }
+    // ============================================================================
+    // get the rapidity
+    // ============================================================================
+    double FourMomentum::y0( const LoKi::LorentzVector& lv ) const {
+      const double e = lv.E();
+      const double p = lv.P();
+      //
+      return 0.5 * std::log( ( e + p ) / ( e - p ) );
+    }
+    // ============================================================================
+    // get the phi
+    // ============================================================================
+    double FourMomentum::phi( const LoKi::LorentzVector& lv ) const { return adjust( lv.phi() ); }
+    // ============================================================================
+    // get the eta
+    // ============================================================================
+    double FourMomentum::eta( const LoKi::LorentzVector& lv ) const { return lv.Eta(); }
+    // ==========================================================================
+    // get the beta
+    // ============================================================================
+    double FourMomentum::beta( const LoKi::LorentzVector& lv ) const { return lv.Beta(); }
+    // ==========================================================================
+    // get the gamma
+    // ============================================================================
+    double FourMomentum::gamma( const LoKi::LorentzVector& lv ) const { return lv.Gamma(); }
+    // ==========================================================================
+    // get the beta*gamma
+    // ============================================================================
+    double FourMomentum::bgamma( const LoKi::LorentzVector& lv ) const {
+      //
+      const double m = lv.M();
+      //
+      if ( s_equal( m, 0 ) ) { return LoKi::Constants::PositiveInfinity; }
+      //
+      return lv.P() / m;
+    }
+    // ==========================================================================
+
+    // ============================================================================
+    // MANDATORY: clone method ("virtual destructor")
+    // ============================================================================
+    Mass* Mass::clone() const { return new Mass( *this ); }
+    // ============================================================================
+    // MANDATORY: the only one essential method
+    // ============================================================================
+    double Mass::operator()( const HepMC3::ConstGenParticlePtr & p ) const {
+      //
+      if ( UNLIKELY( !p ) ) {
+        Error( "HepMC3::ConstGenParticlePtr & points to NULL, return Invalid Mass" );
+        return LoKi::Constants::InvalidMass;
+      }
+      //
+      return momentum( p ).M();
+    }
+    // ============================================================================
+    // OPTIONAL: nice printout
+    // ============================================================================
+    std::ostream& Mass::fillStream( std::ostream& s ) const { return print_( s, "GMASS", "GM" ); }
+    // ============================================================================
+
+    // ============================================================================
+    // MANDATORY: clone method ("virtual destructor")
+    // ============================================================================
+    Energy* Energy::clone() const { return new Energy( *this ); }
+    // ============================================================================
+    // MANDATORY: the only one essential method
+    // ============================================================================
+    double Energy::operator()( const HepMC3::ConstGenParticlePtr & p ) const {
+      //
+      if ( UNLIKELY( !p ) ) {
+        Error( "HepMC3::ConstGenParticlePtr & points to NULL, return Invalid Energy" );
+        return LoKi::Constants::InvalidEnergy;
+      }
+      //
+      return momentum( p ).E();
+    }
+    // ============================================================================
+    // OPTIONAL: nice printout
+    // ============================================================================
+    std::ostream& Energy::fillStream( std::ostream& s ) const { return print_( s, "GENERGY", "GE" ); }
+
+    // ============================================================================
+    // MANDATORY: clone method ("virtual destructor")
+    // ============================================================================
+    Momentum* Momentum::clone() const { return new Momentum( *this ); }
+    // ============================================================================
+    // MANDATORY: the only one essential method
+    // ============================================================================
+    double Momentum::operator()( const HepMC3::ConstGenParticlePtr & p ) const {
+      //
+      if ( UNLIKELY( !p ) ) {
+        Error( "HepMC3::ConstGenParticlePtr & points to NULL, return Invalid Momentum" );
+        return LoKi::Constants::InvalidMomentum;
+      }
+      //
+      return momentum( p ).P();
+    }
+    // ============================================================================
+    // OPTIONAL: nice printout
+    // ============================================================================
+    std::ostream& Momentum::fillStream( std::ostream& s ) const { return print_( s, "GMOMENTUM", "GP" ); }
+
+    // ============================================================================
+    // MANDATORY: clone method ("virtual destructor")
+    // ============================================================================
+    MomentumX* MomentumX::clone() const { return new MomentumX( *this ); }
+    // ============================================================================
+    // MANDATORY: the only one essential method
+    // ============================================================================
+    double MomentumX::operator()( const HepMC3::ConstGenParticlePtr & p ) const {
+      //
+      if ( UNLIKELY( !p ) ) {
+        Error( "HepMC3::ConstGenParticlePtr & points to NULL, return Invalid Momentum" );
+        return LoKi::Constants::InvalidMomentum;
+      }
+      //
+      return momentum( p ).Px();
+    }
+    // ============================================================================
+    // OPTIONAL: nice printout
+    // ============================================================================
+    std::ostream& MomentumX::fillStream( std::ostream& s ) const { return print_( s, "GMOMX", "GPX" ); }
+
+    // ============================================================================
+    // MANDATORY: clone method ("virtual destructor")
+    // ============================================================================
+    MomentumY* MomentumY::clone() const { return new MomentumY( *this ); }
+    // ============================================================================
+    // MANDATORY: the only one essential method
+    // ============================================================================
+    double MomentumY::operator()( const HepMC3::ConstGenParticlePtr & p ) const {
+      //
+      if ( UNLIKELY( !p ) ) {
+        Error( "HepMC3::ConstGenParticlePtr & points to NULL, return Invalid Momentum" );
+        return LoKi::Constants::InvalidMomentum;
+      }
+      //
+      return momentum( p ).Py();
+    }
+    // ============================================================================
+    // OPTIONAL: nice printout
+    // ============================================================================
+    std::ostream& MomentumY::fillStream( std::ostream& s ) const { return print_( s, "GMOMY", "GPY" ); }
+
+    // ============================================================================
+    // MANDATORY: clone method ("virtual destructor")
+    // ============================================================================
+    MomentumZ* MomentumZ::clone() const { return new MomentumZ( *this ); }
+    // ============================================================================
+    // MANDATORY: the only one essential method
+    // ============================================================================
+    double MomentumZ::operator()( const HepMC3::ConstGenParticlePtr & p ) const {
+      //
+      if ( UNLIKELY( !p ) ) {
+        Error( "HepMC3::ConstGenParticlePtr & points to NULL, return Invalid Momentum" );
+        return LoKi::Constants::InvalidMomentum;
+      }
+      //
+      return momentum( p ).Pz();
+    }
+    // ============================================================================
+    // OPTIONAL: nice printout
+    // ============================================================================
+    std::ostream& MomentumZ::fillStream( std::ostream& s ) const { return print_( s, "GMOMZ", "GPZ" ); }
+
+    // ============================================================================
+    // MANDATORY: clone method ("virtual destructor")
+    // ============================================================================
+    TransverseMomentum* TransverseMomentum::clone() const { return new TransverseMomentum( *this ); }
+    // ============================================================================
+    // MANDATORY: the only one essential method
+    // ============================================================================
+    double TransverseMomentum::operator()( const HepMC3::ConstGenParticlePtr & p ) const {
+      //
+      if ( UNLIKELY( !p ) ) {
+        Error( "HepMC3::ConstGenParticlePtr & points to NULL, return Invalid Momentum" );
+        return LoKi::Constants::InvalidMomentum;
+      }
+      //
+      return momentum( p ).Pt();
+    }
+    // ============================================================================
+    // OPTIONAL: nice printout
+    // ============================================================================
+    std::ostream& TransverseMomentum::fillStream( std::ostream& s ) const { return print_( s, "GMOMT", "GPT" ); }
+
+    // ============================================================================
+    // MANDATORY: clone method ("virtual destructor")
+    // ============================================================================
+    PseudoRapidity* PseudoRapidity::clone() const { return new PseudoRapidity( *this ); }
+    // ============================================================================
+    // MANDATORY: the only one essential method
+    // ============================================================================
+    double PseudoRapidity::operator()( const HepMC3::ConstGenParticlePtr & p ) const {
+      //
+      if ( UNLIKELY( !p ) ) {
+        Error( "HepMC3::ConstGenParticlePtr & points to NULL, return NegativeInfinity" );
+        return LoKi::Constants::NegativeInfinity;
+      }
+      //
+      return eta( momentum( p ) );
+    }
+    // ============================================================================
+    // OPTIONAL: nice printout
+    // ============================================================================
+    std::ostream& PseudoRapidity::fillStream( std::ostream& s ) const { return print_( s, "GPSEUDORAPIDITY", "GETA" ); }
+
+    // ============================================================================
+    // MANDATORY: clone method ("virtual destructor")
+    // ============================================================================
+    Rapidity* Rapidity::clone() const { return new Rapidity( *this ); }
+    // ============================================================================
+    // MANDATORY: the only one essential method
+    // ============================================================================
+    double Rapidity::operator()( const HepMC3::ConstGenParticlePtr & p ) const {
+      //
+      if ( UNLIKELY( !p ) ) {
+        Error( "HepMC3::ConstGenParticlePtr & points to NULL, return NegativeInfinity" );
+        return LoKi::Constants::NegativeInfinity;
+      }
+      //
+      return y( momentum( p ) );
+      //
+    }
+    // ============================================================================
+    // OPTIONAL: nice printout
+    // ============================================================================
+    std::ostream& Rapidity::fillStream( std::ostream& s ) const { return print_( s, "GRAPIDITY", "GY" ); }
+
+    // ============================================================================
+    // MANDATORY: clone method ("virtual destructor")
+    // ============================================================================
+    Rapidity0* Rapidity0::clone() const { return new Rapidity0( *this ); }
+    // ============================================================================
+    // MANDATORY: the only one essential method
+    // ============================================================================
+    double Rapidity0::operator()( const HepMC3::ConstGenParticlePtr & p ) const {
+      //
+      if ( UNLIKELY( !p ) ) {
+        Error( "HepMC3::ConstGenParticlePtr & points to NULL, return NegativeInfinity" );
+        return LoKi::Constants::NegativeInfinity;
+      }
+      //
+      return y0( momentum( p ) );
+      //
+    }
+    // ============================================================================
+    // OPTIONAL: nice printout
+    // ============================================================================
+    std::ostream& Rapidity0::fillStream( std::ostream& s ) const { return print_( s, "GRAPIDITY0", "GY0" ); }
+
+    // ============================================================================
+    // MANDATORY: clone method ("virtual destructor")
+    // ============================================================================
+    Phi* Phi::clone() const { return new Phi( *this ); }
+    // ============================================================================
+    // MANDATORY: the only one essential method
+    // ============================================================================
+    double Phi::operator()( const HepMC3::ConstGenParticlePtr & p ) const {
+      //
+      if ( UNLIKELY( !p ) ) {
+        Error( "HepMC3::ConstGenParticlePtr & points to NULL, return -100 " );
+        return -100;
+      }
+      //
+      return phi( momentum( p ) );
+      //
+    }
+    // ============================================================================
+    // OPTIONAL: nice printout
+    // ============================================================================
+    std::ostream& Phi::fillStream( std::ostream& s ) const { return print_( s, "GASYMUTH", "GPHI" ); }
+    // ============================================================================
+
+    // ============================================================================
+    // MANDATORY: clone method ("virtual destructor")
+    // ============================================================================
+    Theta* Theta::clone() const { return new Theta( *this ); }
+    // ============================================================================
+    // MANDATORY: the only one essential method
+    // ============================================================================
+    double Theta::operator()( const HepMC3::ConstGenParticlePtr & p ) const {
+      //
+      if ( 0 == p ) {
+        Error( "HepMC3::ConstGenParticlePtr & points to NULL, return -100 " );
+        return -100;
+      }
+      //
+      return momentum( p ).Theta();
+      //
+    }
+    // ============================================================================
+    // OPTIONAL: nice printout
+    // ============================================================================
+    std::ostream& Theta::fillStream( std::ostream& s ) const { return print_( s, "GPOLAR", "GTHETA" ); }
+
+    // ============================================================================
+    // MANDATORY: clone method ("virtual destructor")
+    // ============================================================================
+    Beta* Beta::clone() const { return new Beta( *this ); }
+    // ============================================================================
+    // get beta-factor
+    // ============================================================================
+    double Beta::beta( const HepMC3::ConstGenParticlePtr & p ) const {
+      if ( 0 == p ) {
+        Error( "HepMC3::ConstGenParticlePtr & points to NULL, return -1 " );
+        return -1;
+      }
+      //
+      return LoKi::LorentzVector( p->momentum() ).Beta();
+      //
+    }
+    // ============================================================================
+    // get gamma-factor
+    // ============================================================================
+    double Beta::gamma( const HepMC3::ConstGenParticlePtr & p ) const {
+      if ( 0 == p ) {
+        Error( "HepMC3::ConstGenParticlePtr & points to NULL, return -1 " );
+        return -1;
+      }
+      //
+      const LoKi::LorentzVector lv( p->momentum() );
+      //
+      const auto m = lv.M();
+      const auto E = lv.E();
+      //
+      if ( s_equal( E, m ) ) { return 1; }
+      //
+      if ( UNLIKELY( s_equal( m, 0 ) ) ) {
+        //
+        //
+        Error( "Light-like particle, return +infinity" );
+        return LoKi::Constants::PositiveInfinity;
+      }
+      //
+      return E / m;
+      //
+    }
+    // ============================================================================
+    // get gamma-factor
+    // ============================================================================
+    double Beta::betagamma( const HepMC3::ConstGenParticlePtr & p ) const {
+      if ( UNLIKELY( !p ) ) {
+        Error( "HepMC3::ConstGenParticlePtr & points to NULL, return -1 " );
+        return -1;
+      }
+      //
+      const LoKi::LorentzVector lv( p->momentum() );
+      const double              P = lv.P();
+      if ( s_equal( P, 0 ) ) { return 0; }
+      //
+      const double m = lv.M();
+      if ( s_equal( m, 0 ) ) {
+        //
+        Error( "Light-like particle, return +infinity" );
+        return LoKi::Constants::PositiveInfinity;
+      }
+      //
+      return P / m;
+      //
+    }
+    // ============================================================================
+    // MANDATORY: the only one essential method
+    // ============================================================================
+    double Beta::operator()( const HepMC3::ConstGenParticlePtr & p ) const { return beta( p ); }
+    // ============================================================================
+    // OPTIONAL: nice printout
+    // ============================================================================
+    std::ostream& Beta::fillStream( std::ostream& s ) const { return s << "GBETA"; }
+
+    // ============================================================================
+    // MANDATORY: clone method ("virtual destructor")
+    // ============================================================================
+    Gamma* Gamma::clone() const { return new Gamma( *this ); }
+    // ============================================================================
+    // MANDATORY: the only one essential method
+    // ============================================================================
+    double Gamma::operator()( const HepMC3::ConstGenParticlePtr & p ) const { return gamma( p ); }
+    // ============================================================================
+    // OPTIONAL: nice printout
+    // ============================================================================
+    std::ostream& Gamma::fillStream( std::ostream& s ) const { return s << "GGAMMA"; }
+
+    // ============================================================================
+    // MANDATORY: clone method ("virtual destructor")
+    // ============================================================================
+    BetaGamma* BetaGamma::clone() const { return new BetaGamma( *this ); }
+    // ============================================================================
+    // MANDATORY: the only one essential method
+    // ============================================================================
+    double BetaGamma::operator()( const HepMC3::ConstGenParticlePtr & p ) const { return betagamma( p ); }
+    // ============================================================================
+    // OPTIONAL: nice printout
+    // ============================================================================
+    std::ostream& BetaGamma::fillStream( std::ostream& s ) const { return s << "GBETAGAMMA"; }
+    // ============================================================================
+
+    // ============================================================================
+    //  constructor from the angle
+    // ============================================================================
+    DeltaPhi::DeltaPhi( const double phi ) : m_phi( adjust( phi ) ) {}
+    // ============================================================================
+    //  constructor from the vector
+    // ============================================================================
+    DeltaPhi::DeltaPhi( const LoKi::ThreeVector& v ) : m_phi( adjust( v.Phi() ) ) {}
+    // ============================================================================
+    //  constructor from the vector
+    // ============================================================================
+    DeltaPhi::DeltaPhi( const LoKi::LorentzVector& v ) : m_phi( adjust( v.Phi() ) ) {}
+    // ============================================================================
+    //  constructor from the particle
+    // ============================================================================
+    DeltaPhi::DeltaPhi( const HepMC3::ConstGenParticlePtr & p ) {
+      if ( !p ) { Exception( "Invalid HepMC3::GenParticlePtr" ); }
+      m_phi = adjust( p->momentum().phi() );
+    }
+    // ============================================================================
+    //  MANDATORY: clone method ("virtual constructor")
+    // ============================================================================
+    DeltaPhi* DeltaPhi::clone() const { return new DeltaPhi( *this ); }
+    // ============================================================================
+    //  MANDATORY: the only essential method
+    // ============================================================================
+    double DeltaPhi::operator()( const HepMC3::ConstGenParticlePtr & p ) const {
+      if ( 0 == p ) {
+        Error( "HepMC3::ConstGenParticlePtr & points to NULL, return 'InvalidAngle'" );
+        return LoKi::Constants::InvalidAngle;
+      }
+      return dphi( p );
+    }
+    // ============================================================================
+    double DeltaPhi::dphi( const HepMC3::ConstGenParticlePtr & p ) const { return adjust( phi( momentum( p ) ) - phi0() ); }
+    // ============================================================================
+    //  OPTIONAL: "SHORT" representation
+    // ============================================================================
+    std::ostream& DeltaPhi::fillStream( std::ostream& s ) const { return s << "GDPHI(" << phi0() << ")"; }
+    // ============================================================================
+    //  constructor from the angle
+    // ============================================================================
+    DeltaEta::DeltaEta( const double eta ) : m_eta( eta ) {}
+    // ============================================================================
+    //  constructor from the vector
+    // ============================================================================
+    DeltaEta::DeltaEta( const LoKi::ThreeVector& v ) : m_eta( v.Eta() ) {}
+    // ============================================================================
+    //  constructor from the vector
+    // ============================================================================
+    DeltaEta::DeltaEta( const LoKi::LorentzVector& v ) : m_eta( v.Eta() ) {}
+    // ============================================================================
+    //  constructor from the particle
+    // ============================================================================
+    DeltaEta::DeltaEta( const HepMC3::ConstGenParticlePtr & p ) {
+      if ( !p ) { Exception( "Invalid HepMC3::GenParticlePtr" ); }
+      m_eta = p->momentum().pseudoRapidity();
+    }
+    // ============================================================================
+    //  MANDATORY: clone method ("virtual constructor")
+    // ============================================================================
+    DeltaEta* DeltaEta::clone() const { return new DeltaEta( *this ); }
+    // ============================================================================
+    //  MANDATORY: the only essential method
+    // ============================================================================
+    double DeltaEta::operator()( const HepMC3::ConstGenParticlePtr & p ) const {
+      if ( UNLIKELY( !p ) ) {
+        Error( "HepMC3::ConstGenParticlePtr & points to NULL, return 'InvalidAngle'" );
+        return LoKi::Constants::InvalidAngle;
+      }
+      return deta( p );
+    }
+    // ============================================================================
+    double DeltaEta::deta( const HepMC3::ConstGenParticlePtr & p ) const { return eta( momentum( p ) ) - eta0(); }
+    // ============================================================================
+    //  OPTIONAL: "SHORT" representation
+    // ============================================================================
+    std::ostream& DeltaEta::fillStream( std::ostream& s ) const { return s << "GDETA(" << m_eta << ")"; }
+    // ============================================================================
+    //  constructor from eta and phi
+    // ============================================================================
+    DeltaR2::DeltaR2( const double eta, const double phi ) : DeltaPhi( phi ), m_deta( eta ) {}
+    // ============================================================================
+    //  constructor from the vector
+    // ============================================================================
+    DeltaR2::DeltaR2( const LoKi::ThreeVector& v ) : DeltaPhi( v ), m_deta( v ) {}
+    // ============================================================================
+    //  constructor from the vector
+    // ============================================================================
+    DeltaR2::DeltaR2( const LoKi::LorentzVector& v ) : DeltaPhi( v ), m_deta( v ) {}
+    // ============================================================================
+    //  constructor from the particle
+    // ============================================================================
+    DeltaR2::DeltaR2( const HepMC3::ConstGenParticlePtr & v ) : DeltaPhi( v ), m_deta( v ) {}
+    // ============================================================================
+    //  MANDATORY: clone method ("virtual constructor")
+    // ============================================================================
+    DeltaR2* DeltaR2::clone() const { return new DeltaR2( *this ); }
+    // ============================================================================
+    //  MANDATORY: the only essential method
+    // ============================================================================
+    double DeltaR2::operator()( const HepMC3::ConstGenParticlePtr & p ) const {
+      if ( 0 == p ) {
+        Error( "HepMC3::ConstGenParticlePtr & points to NULL, return 'InvalidDustance'" );
+        return LoKi::Constants::InvalidDistance;
+      }
+      //
+      const double dphi_ = dphi( p );
+      const double deta_ = deta( p );
+      //
+      return dphi_ * dphi_ + deta_ * deta_;
+    }
+    // ============================================================================
+    //  OPTIONAL: "SHORT" representation
+    // ============================================================================
+    std::ostream& DeltaR2::fillStream( std::ostream& s ) const {
+      return s << "GDR2( " << eta0() << "," << phi0() << ")";
+    }
+
+  } // namespace GenParticles
+} // namespace LoKi
+// ============================================================================
+// The END
+// ============================================================================
diff --git a/Gen/LoKiGen/src/GenParticles5.cpp b/Gen/LoKiGen/src/GenParticles5.cpp
new file mode 100644
index 000000000..071846369
--- /dev/null
+++ b/Gen/LoKiGen/src/GenParticles5.cpp
@@ -0,0 +1,111 @@
+/*****************************************************************************\
+* (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration      *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                             *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+// ============================================================================
+// Include files
+// ============================================================================
+// LHCbMath
+// ============================================================================
+#include "LHCbMath/LHCbMath.h"
+// ============================================================================
+// LoKi
+// ============================================================================
+#include "LoKi/Constants.h"
+#include "LoKi/GenParticles5.h"
+#include "LoKi/Geometry.h"
+#include "Defaults/HepMCAttributes.h"
+#include "HepMCUser/VertexAttribute.h"
+// ============================================================================
+/** @file
+ *
+ *  This file is a part of LoKi project -
+ *    "C++ ToolKit  for Smart and Friendly Physics Analysis"
+ *
+ *  The package has been designed with the kind help from
+ *  Galina PAKHLOVA and Sergey BARSUK.  Many bright ideas,
+ *  contributions and advices from G.Raven, J.van Tilburg,
+ *  A.Golutvin, P.Koppenburg have been used in the design.
+ *
+ *  @author Vanya BELYAEV Ivan.Belyaev@itep.ru
+ *  @date 2013-04-14
+ *
+ */
+namespace LoKi {
+  namespace GenParticles {
+    // ============================================================================
+    /** constructor from one
+     *  @param primary use primary vertex, otherwise use own vertex
+     */
+    // ============================================================================
+    Flight::Flight( const bool primary ) : m_primary( primary ) {}
+    // ============================================================================
+    // MANDATORY: clone method ("virtual destructor")
+    // ============================================================================
+    Flight* Flight::clone() const { return new Flight( *this ); }
+    // ============================================================================
+    // OPTIONAL: nice printout
+    // ============================================================================
+    std::ostream& Flight::fillStream( std::ostream& s ) const { return s << ( m_primary ? "GPVFLIGHT" : "GFLIGHT" ); }
+    // ============================================================================
+    // MANDATORY: the only one essential method
+    // ============================================================================
+    double Flight::operator()( const HepMC3::ConstGenParticlePtr & p ) const {
+      //
+      if ( !p ) {
+        Error( "HepMC3::GenParticlePtr points to NULL, return -1*km " );
+        return -1 * Gaudi::Units::km;
+      }
+      // end vertex
+      HepMC3::ConstGenVertexPtr ev = p->end_vertex();
+      //
+      if ( !ev ) {
+        Error( "HepMC3::GenParticle::end_vertex points to NULL, return +1*km " );
+        return Gaudi::Units::km;
+      }
+      //
+      HepMC3::ConstGenVertexPtr v0 = nullptr;
+      if ( primary() ) {
+        //
+        const HepMC3::GenEvent* evt = p->parent_event();
+        if ( !evt ) {
+          Error( "HepMC3::GenParticle::parent_event points to NULL, return -1*km " );
+          return -1 * Gaudi::Units::km;
+        }
+        //
+        v0 = evt->attribute<HepMC3::VertexAttribute>( Gaussino::HepMC::Attributes::SignalProcessVertex )->value();
+        if ( !v0 ) {
+          Error( "HepMC3::GenEvent::signal_process_vertex points to NULL, return -1*km " );
+          return -1 * Gaudi::Units::km;
+        }
+        //
+      } else {
+        //
+        v0 = p->production_vertex();
+        if ( !v0 ) {
+          Error( "HepMC3::GenParticle::production_vertex points to NULL, return -1*km " );
+          return -1 * Gaudi::Units::km;
+        }
+        //
+      }
+      //
+      // calculate the distance
+      if ( ev == v0 ) { return 0; }
+      //
+      const LoKi::Point3D ed( ev->position() );
+      const LoKi::Point3D eo( v0->position() );
+      //
+      return ( ed - eo ).R();
+    }
+
+  } // namespace GenParticles
+} // namespace LoKi
+// ============================================================================
+// The END
+// ============================================================================
diff --git a/Gen/LoKiGen/src/GenSections.cpp b/Gen/LoKiGen/src/GenSections.cpp
new file mode 100644
index 000000000..e0690f9b5
--- /dev/null
+++ b/Gen/LoKiGen/src/GenSections.cpp
@@ -0,0 +1,74 @@
+/*****************************************************************************\
+* (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration      *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                             *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+// ============================================================================
+// Include files
+// ============================================================================
+// STD & STL
+// ============================================================================
+#include <vector>
+// ============================================================================
+// LoKi
+// ============================================================================
+#include "LoKi/Combiner.h"
+#include "LoKi/GenChild.h"
+#include "LoKi/GenSections.h"
+// ============================================================================
+/** @file
+ *  Implementation file for function LoKi::Decay::sections
+ *  @author Vanya BELYAEV Ivan.Belayev@nikhef.nl
+ *  @date 2008-04-29
+ */
+// ============================================================================
+/*  simple function to extract all section from the graph/tree
+ *  @param particle the head of th egraph/tree
+ *  @param output the sections of the graph/tree
+ *  @param decay the boolean flag to consider <b>only</b> decay products
+ *  @return size of the section container
+ */
+// ============================================================================
+size_t Decays::sections( const HepMC3::ConstGenParticlePtr & particle, Decays::GenSections& output ) {
+  // trivial case 1
+  if ( 0 == particle ) { return output.size(); } // RETURN
+  // add the particle itself as one of the section
+  output.push_back( GenSection( 1, particle ) );               // the primitive section
+  if ( 0 == particle->end_vertex() ) { return output.size(); } // RETURN
+  // get all children particles:
+  std::vector<HepMC3::ConstGenParticlePtr> children;
+  LoKi::GenChild::daughters( particle, children );
+  if ( children.empty() ) { return output.size(); } // RETURN
+  // get all sections from daughter particles:
+  std::vector<GenSections> all( children.size() );
+  for ( size_t index = 0; index < children.size(); ++index ) { sections( children[index], all[index] ); } // RECURSION
+  //
+  typedef LoKi::Combiner_<GenSections> Loop;
+  typedef Loop::Range                  Range;
+  typedef Loop::Select                 Select;
+  // create the proper combiner
+  Loop loop;
+  // fill the combiner with the information
+  for ( const auto& i : all ) { loop.add( Range( i ) ); } // Fill the LOOP!
+  ///
+  // make the real looping over all combinations of sections
+  for ( ; loop.valid(); ++loop ) {
+    // get the "current" multi-iterator
+    const Select& sel = loop.current();
+    // construct the section
+    GenSection section;
+    for ( const auto& s : sel ) { section.insert( section.end(), s->begin(), s->end() ); }
+    // add it into the collection of sections
+    output.push_back( section );
+  }
+  //
+  return output.size(); // RETURN
+}
+// ============================================================================
+// The END
+// ============================================================================
diff --git a/Gen/LoKiGen/src/GenSources.cpp b/Gen/LoKiGen/src/GenSources.cpp
new file mode 100644
index 000000000..af684dbbc
--- /dev/null
+++ b/Gen/LoKiGen/src/GenSources.cpp
@@ -0,0 +1,155 @@
+/*****************************************************************************\
+* (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration      *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                             *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+// ============================================================================
+// Include files
+// ============================================================================
+// GaudiKernel
+// ============================================================================
+#include "GaudiKernel/SmartDataPtr.h"
+// ============================================================================
+// LoKi
+// ============================================================================
+#include "LoKi/GenAlgs.h"
+#include "LoKi/GenExtract.h"
+#include "LoKi/GenSources.h"
+#include "LoKi/Services.h"
+
+#include <vector>
+// ============================================================================
+/** @file
+ *  Implementation file for various sources
+ *  @author Vanya BELYAEV ibelyav@physics.syr.edu
+ *  @date 2006-12-07
+ */
+// ============================================================================
+// constructor from the service, TES location and cuts
+// ============================================================================
+LoKi::GenParticles::SourceTES::SourceTES( const IDataProviderSvc* svc, const LoKi::GenTypes::GCuts& cuts,
+                                          const std::string& path )
+    : LoKi::AuxFunBase( std::tie( svc, cuts, path ) ), SourceTES::_Base( svc, path ), m_cut( cuts ) {}
+// ============================================================================
+// constructor from the service, TES location and cuts
+// ============================================================================
+LoKi::GenParticles::SourceTES::SourceTES( const IDataProviderSvc* svc, const std::string& path )
+    : LoKi::AuxFunBase( std::tie( svc, path ) )
+    , SourceTES::_Base( svc, path )
+    , m_cut( LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::BooleanConstant( true ) ) {}
+// ============================================================================
+// constructor from the service, TES location and cuts
+// ============================================================================
+LoKi::GenParticles::SourceTES::SourceTES( const GaudiAlgorithm* svc, const LoKi::GenTypes::GCuts& cuts,
+                                          const std::string& path, const bool useRootInTES )
+    : LoKi::AuxFunBase( std::tie( svc, cuts, path, useRootInTES ) )
+    , SourceTES::_Base( svc, path, useRootInTES )
+    , m_cut( cuts ) {}
+// ============================================================================
+// constructor from the service, TES location and cuts
+// ============================================================================
+LoKi::GenParticles::SourceTES::SourceTES( const GaudiAlgorithm* svc, const std::string& path, const bool useRootInTES )
+    : LoKi::AuxFunBase( std::tie( svc, path, useRootInTES ) )
+    , SourceTES::_Base( svc, path, useRootInTES )
+    , m_cut( LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::BooleanConstant( true ) ) {}
+// ============================================================================
+// MANDATORY: the only essential method:
+std::vector<HepMC3::ConstGenParticlePtr> LoKi::GenParticles::SourceTES::operator()() const {
+
+  const std::vector<HepMC3::GenEvent>* events = LoKi::TES::get_<std::vector<HepMC3::GenEvent>>( *this );
+  Assert( events, "No valid data is found at location '" + path() + "'" );
+  std::vector<HepMC3::ConstGenParticlePtr> particles;
+  particles.reserve( 2000 );
+  //
+  for(auto & evt: *events){
+    LoKi::Extract::getGenParticles( &evt, std::back_inserter( particles ), m_cut.func() );
+  }
+  //
+  return particles;
+}
+// ============================================================================
+// OPTIONAL: the nice printout
+// ============================================================================
+std::ostream& LoKi::GenParticles::SourceTES::fillStream( std::ostream& o ) const {
+  return o << "GSOURCE(" << path() << "," << m_cut << ")";
+}
+// ============================================================================
+
+// ============================================================================
+// constructor
+// ============================================================================
+LoKi::GenParticles::TESData::TESData( const GaudiAlgorithm* algorithm, const std::string& path )
+    : TESData( algorithm, path, LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::BooleanConstant( true ) ) {}
+// ============================================================================
+// constructor
+// ============================================================================
+LoKi::GenParticles::TESData::TESData( const GaudiAlgorithm* algorithm, const std::string& path,
+                                      const LoKi::GenTypes::GCuts& cuts )
+    : LoKi::AuxFunBase( std::tie( algorithm, path, cuts ) )
+    , LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::Source()
+    , LoKi::TES::DataHandle<std::vector<HepMC3::GenEvent>>( algorithm, path )
+    , m_cuts( cuts ) {}
+// ============================================================================
+// constructor
+// ============================================================================
+LoKi::GenParticles::TESData::TESData( const GaudiAlgorithm* algorithm, const LoKi::GenTypes::GCuts& cuts,
+                                      const std::string& path )
+    : TESData( algorithm, path, cuts ) {}
+// ============================================================================
+// MANDATORY: clone method ("virtual constructor")
+// ============================================================================
+LoKi::GenParticles::TESData* LoKi::GenParticles::TESData::clone() const {
+  return new LoKi::GenParticles::TESData( *this );
+}
+// ============================================================================
+// MANDATORY: the only essential method:
+// ============================================================================
+LoKi::GenParticles::TESData::result_type LoKi::GenParticles::TESData::operator()() const {
+  const auto* data = get();
+  result_type result;
+  result.resize( data->size() / 4 );
+
+  for(auto & evt: *data){
+    LoKi::Extract::genParticles( &evt, std::back_inserter( result ), m_cuts );
+  }
+  return result;
+}
+// ============================================================================
+// OPTIONAL: the nice printout
+// ============================================================================
+std::ostream& LoKi::GenParticles::TESData::fillStream( std::ostream& o ) const {
+  return o << "GTESDATA('" << location() << "'," << m_cuts << ")";
+}
+// ============================================================================
+
+// ============================================================================
+// constructor from the service, TES location and cuts
+// ============================================================================
+LoKi::GenParticles::TESCounter::TESCounter( const LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::Source& s )
+    : LoKi::AuxFunBase( std::tie( s ) ), LoKi::Functor<void, double>(), m_source( s ) {}
+// ============================================================================
+// MANDATORY: clone method ("virtual constructor")
+// ============================================================================
+LoKi::GenParticles::TESCounter* LoKi::GenParticles::TESCounter::clone() const {
+  return new LoKi::GenParticles::TESCounter( *this );
+}
+// ============================================================================
+// MANDATORY: the only essential method:
+// ============================================================================
+double LoKi::GenParticles::TESCounter::operator()() const { return m_source().size(); }
+// ============================================================================
+// OPTIONAL: the nice printout
+// ============================================================================
+std::ostream& LoKi::GenParticles::TESCounter::fillStream( std::ostream& o ) const {
+  return o << "GNUM(" << m_source << ")";
+}
+// ============================================================================
+
+// ============================================================================
+//                                                                      The END
+// ============================================================================
diff --git a/Gen/LoKiGen/src/GenStreamers.cpp b/Gen/LoKiGen/src/GenStreamers.cpp
new file mode 100644
index 000000000..9e64aa864
--- /dev/null
+++ b/Gen/LoKiGen/src/GenStreamers.cpp
@@ -0,0 +1,88 @@
+/*****************************************************************************\
+* (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration      *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                             *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+// ============================================================================
+// Include files
+// ============================================================================
+// STD & STL
+// ============================================================================
+#include <set>
+// ============================================================================
+// Local
+// ============================================================================
+#include "LoKi/GenExtract.h"
+#include "LoKi/GenTypes.h"
+// ============================================================================
+/** @file
+ *
+ *  implementation of some MC-streamers
+ *
+ *  This file is a part of LoKi project -
+ *    "C++ ToolKit  for Smart and Friendly Physics Analysis"
+ *
+ *  The package has been designed with the kind help from
+ *  Galina PAKHLOVA and Sergey BARSUK.  Many bright ideas,
+ *  contributions and advices from G.Raven, J.van Tilburg,
+ *  A.Golutvin, P.Koppenburg have been used in the design.
+ *
+ *  @author Vanya BELYAEV Ivan.Belyaev@itep.ru
+ *  @date 2012-05-24
+ *
+ */
+// ============================================================================
+namespace {
+  // ==========================================================================
+  /// get particles
+  template <class PARTICLE>
+  LoKi::GenTypes::GenContainer _get_( PARTICLE first, PARTICLE last, const LoKi::Types::GCuts& cuts ) {
+    //
+    LoKi::GenTypes::GenContainer r;
+    r.reserve( 100 );
+    //
+    LoKi::Extract::genParticles( first, last, std::back_inserter( r ), cuts );
+    //
+    // eliminate duplicates
+    std::set<HepMC3::ConstGenParticlePtr> s( r.begin(), r.end() );
+    //
+    return LoKi::GenTypes::GenContainer( s.begin(), s.end() );
+  }
+  // ==========================================================================
+  template <class PARTICLES>
+  LoKi::GenTypes::GenContainer _get_( const PARTICLES* parts, const LoKi::Types::GCuts& cuts ) {
+    //
+    LoKi::GenTypes::GenContainer r;
+    r.reserve( 100 );
+    //
+    LoKi::Extract::genParticles( parts, std::back_inserter( r ), cuts );
+    //
+    // eliminate duplicates
+    std::set<HepMC3::ConstGenParticlePtr> s( r.begin(), r.end() );
+    //
+    return LoKi::GenTypes::GenContainer( s.begin(), s.end() );
+  }
+  // ==========================================================================
+} // namespace
+// ============================================================================
+LoKi::GenTypes::GenContainer operator>>( const LoKi::GenTypes::GenContainer& input, const LoKi::Types::GCuts& cuts ) {
+  return _get_( input.begin(), input.end(), cuts );
+}
+// =============================================================================
+LoKi::GenTypes::GenContainer operator>>( const LoKi::GenTypes::GRange& input, const LoKi::Types::GCuts& cuts ) {
+  return _get_( input.begin(), input.end(), cuts );
+}
+// ============================================================================
+LoKi::GenTypes::GenContainer operator>>( const HepMC3::GenEvent* event, const LoKi::Types::GCuts& cuts ) {
+  return _get_( event, cuts );
+}
+// ============================================================================
+
+// ============================================================================
+// The END
+// ============================================================================
diff --git a/Gen/LoKiGen/src/GenTreesFactory.cpp b/Gen/LoKiGen/src/GenTreesFactory.cpp
new file mode 100644
index 000000000..81ee34857
--- /dev/null
+++ b/Gen/LoKiGen/src/GenTreesFactory.cpp
@@ -0,0 +1,144 @@
+/*****************************************************************************\
+* (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration      *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                             *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+// ============================================================================
+// Include files
+// ============================================================================
+// LoKi
+// ============================================================================
+#include "LoKi/GenTreesFactory.h"
+#include "LoKi/GenDecays.h"
+#include "LoKi/ParserFactory.h"
+#include "LoKi/Trees.h"
+#include "LoKi/iTree.h"
+// ============================================================================
+/** @file
+ *  Implementation file for function from the file LoKi/GenTreeFactory.h
+ *  @author Vanya BELYAEV Ivan.Belyaev@nikhef.nl
+ *  @date   2009-05-06
+ */
+// ============================================================================
+/*  "Factory" to create the proper Tree from "short" descriptor
+ *   @param tree       (OUTPUT) the constructed tree
+ *   @param mother     (INPUT)  the mother particle
+ *   @return status code
+ *   @author Vanya BELYAEV Ivan.Belyaev@nikhef.nl
+ *   @date   2009-05-06
+ */
+// ============================================================================
+StatusCode Decays::Trees::factory( Decays::Trees::Types_<HepMC3::ConstGenParticlePtr>::Tree& tree,
+                                   const Decays::iNode& mother, const Decays::Trees::Oscillation& oscillated ) {
+  tree = Decays::Trees::GenExclusive( oscillated, mother );
+  return StatusCode::SUCCESS;
+}
+// ==========================================================================
+/* "Factory" to create the proper Tree from the full description
+ *  @param tree       (OUTPUT) the constructed tree
+ *  @param mother     (INPUT)  the mother particle
+ *  @param oscillated (INPUT)  the oscillation flag
+ *  @param arrow      (INPUT)  the type of arrow
+ *  @param daughters  (INPUT)  the list of daughter trees
+ *  @param inclusive  (INPUT)  the flag for inclusive
+ *  @param optional   (INPUT)  the list of "optional" particles
+ *  @param stream     (OUTPUT) the stream to report errors
+ *  @return StatusCode
+ *  @author Vanya BELYAEV Ivan.Belyaev@nikhef.nl
+ *  @date   2009-05-06
+ */
+// ==========================================================================
+StatusCode Decays::Trees::factory( Decays::Trees::Types_<HepMC3::ConstGenParticlePtr>::Tree& tree,
+                                   const Decays::iNode& mother, const Decays::Trees::Oscillation& oscillated,
+                                   const Decays::Trees::Arrow&                                       arrow,
+                                   const Decays::Trees::Types_<HepMC3::ConstGenParticlePtr>::TreeList& daughters,
+                                   const bool                                                        inclusive,
+                                   const Decays::Trees::Types_<HepMC3::ConstGenParticlePtr>::TreeList& optional,
+                                   std::ostream&                                                     stream ) {
+  if ( !Decays::Trees::valid( arrow ) ) {
+    StatusCode code = StatusCode( Decays::Trees::InvalidArrow );
+    stream << "ERROR: Invalid arrow : " << arrow << " " << code << '\n';
+    return code;
+  }
+
+  // decode the arrow
+  const Decays::Trees::Alg alg       = Decays::Trees::algorithm( arrow );
+  const bool               photos    = Decays::Trees::photos( arrow );
+  const bool               decayOnly = Decays::Trees::decayOnly( arrow );
+
+  if ( inclusive && !optional.empty() ) {
+    StatusCode code = StatusCode( Decays::Trees::InclusiveOptional );
+    stream << "ERROR: 'Inclusive' & 'optional' are mutually exclusive " << code << '\n';
+    return code; // RETURN
+  }
+  if ( inclusive && photos ) {
+    StatusCode code = StatusCode( Decays::Trees::InclusivePhotos );
+    stream << "ERROR: 'Inclusive' & 'photos' are mutually exclusive   " << code << '\n';
+    return code; // RETURN
+  }
+  if ( !decayOnly ) {
+    StatusCode code = StatusCode( Decays::Trees::InvalidDecayOnly );
+    stream << "ERROR: invalid 'Decay Only' flag                       " << code << '\n';
+    return code; // RETURN
+  }
+
+  // create the basic decay tree:
+  Decays::Trees::GenExclusive decay( mother, daughters, alg, oscillated );
+  //
+  if ( inclusive && decay.marked() ) {
+    StatusCode code = StatusCode( Decays::Trees::InclusiveMarked );
+    stream << "ERROR: 'Inclusive' & 'marked' can't be properly defined " << code << '\n';
+    return code; // RETURN
+  }
+
+  if ( optional.empty() ) {
+    if ( !inclusive ) // exclusive decays
+    {
+      if ( photos ) {
+        tree = Decays::Trees::GenPhotos( decay );
+      } // + photos
+      else {
+        tree = decay;
+      }
+    } else {
+      tree = Decays::Trees::GenInclusive( decay );
+    }    // inclusive decays
+  } else // decays with optional elements
+  {
+    Decays::Trees::GenOptional opt( decay, optional );
+    if ( photos ) {
+      tree = Decays::Trees::GenPhotosOptional( opt );
+    } // + photos
+    else {
+      tree = opt;
+    }
+    return StatusCode::SUCCESS;
+  }
+
+  //
+  return StatusCode::SUCCESS;
+}
+// ============================================================================
+/*  "Factory" to create the proper Tree from the parsed tree
+ *   @param tree       (OUTPUT) the constructed tree
+ *   @param parsed     (INPUT)  the parsed tree
+ *   @param stream     (OUTPUT) the stream to report errors
+ *   @return status code
+ *   @author Vanya BELYAEV Ivan.Belyaev@nikhef.nl
+ *   @date   2009-05-22
+ */
+// ============================================================================
+StatusCode Decays::Trees::factory( Decays::Trees::Types_<HepMC3::ConstGenParticlePtr>::Tree& tree,
+                                   const Decays::Parsers::Tree& parsed, std::ostream& stream ) {
+  return Decays::Parsers::factory( tree, parsed, stream ); // RETURN
+}
+// ============================================================================
+
+// ============================================================================
+// The END
+// ============================================================================
diff --git a/Gen/LoKiGen/src/GenVertices.cpp b/Gen/LoKiGen/src/GenVertices.cpp
new file mode 100644
index 000000000..6d78220b9
--- /dev/null
+++ b/Gen/LoKiGen/src/GenVertices.cpp
@@ -0,0 +1,278 @@
+/*****************************************************************************\
+* (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration      *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                             *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+// ============================================================================
+// Include files
+// ============================================================================
+#include <numeric>
+// ============================================================================
+// LoKiCore
+// ============================================================================
+#include "LoKi/Constants.h"
+#include "LoKi/Primitives.h"
+// ============================================================================
+// LoKiPhys
+// ============================================================================
+#include "LoKi/GenVertices.h"
+
+#include "HepMCUtils/HepMCUtils.h"
+// ============================================================================
+/** @file
+ *
+ *  This file is a part of LoKi project -
+ *    "C++ ToolKit  for Smart and Friendly Physics Analysis"
+ *
+ *  The package has been designed with the kind help from
+ *  Galina PAKHLOVA and Sergey BARSUK.  Many bright ideas,
+ *  contributions and advices from G.Raven, J.van Tilburg,
+ *  A.Golutvin, P.Koppenburg have been used in the design.
+ *
+ *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+ *  @date 2006-02-08
+ */
+// ============================================================================
+//  MANDATORY: clone method ("virtual" constructor")
+// ============================================================================
+LoKi::GenVertices::BarCode* LoKi::GenVertices::BarCode::clone() const {
+  return new LoKi::GenVertices::BarCode( *this );
+}
+// ============================================================================
+//  MANDATORY: the only one essential method
+// ============================================================================
+double LoKi::GenVertices::BarCode::operator()( const HepMC3::ConstGenVertexPtr & v ) const {
+  if ( UNLIKELY( !v ) ) {
+    Error( "HepMC3::GenVertexPtr points to NULL; return 0" );
+    return 0;
+  }
+  return v->id();
+}
+// ============================================================================
+//  "SHORT" representation, @see LoKi::AuxFunBase
+// ============================================================================
+std::ostream& LoKi::GenVertices::BarCode::fillStream( std::ostream& stream ) const { return stream << "GVBARCODE"; }
+// ============================================================================
+//  MANDATORY: clone method ("virtual" constructor")
+// ============================================================================
+LoKi::GenVertices::PositionX* LoKi::GenVertices::PositionX::clone() const { return new PositionX( *this ); }
+// ============================================================================
+//  MANDATORY: the only one essential method
+// ============================================================================
+double LoKi::GenVertices::PositionX::operator()( const HepMC3::ConstGenVertexPtr & v ) const {
+  if ( UNLIKELY( !v ) ) {
+    Error( "HepMC3::GenVertexPtr points to NULL; return 'InvalidDistance'" );
+    return LoKi::Constants::InvalidDistance;
+  }
+  return v->position().x();
+}
+// ============================================================================
+//  "SHORT" representation, @see LoKi::AuxFunBase
+// ============================================================================
+std::ostream& LoKi::GenVertices::PositionX::fillStream( std::ostream& stream ) const { return stream << "GVX"; }
+// ============================================================================
+//  MANDATORY: clone method ("virtual" constructor")
+// ============================================================================
+LoKi::GenVertices::PositionY* LoKi::GenVertices::PositionY::clone() const { return new PositionY( *this ); }
+// ============================================================================
+//  MANDATORY: the only one essential method
+// ============================================================================
+double LoKi::GenVertices::PositionY::operator()( const HepMC3::ConstGenVertexPtr & v ) const {
+  if ( UNLIKELY( !v ) ) {
+    Error( "HepMC3::GenVertexPtr points to NULL; return 'InvalidDistance'" );
+    return LoKi::Constants::InvalidDistance;
+  }
+  return v->position().y();
+}
+// ============================================================================
+//  "SHORT" representation, @see LoKi::AuxFunBase
+// ============================================================================
+std::ostream& LoKi::GenVertices::PositionY::fillStream( std::ostream& stream ) const { return stream << "GVY"; }
+// ============================================================================
+//  MANDATORY: clone method ("virtual" constructor")
+// ============================================================================
+LoKi::GenVertices::PositionZ* LoKi::GenVertices::PositionZ::clone() const { return new PositionZ( *this ); }
+// ============================================================================
+//  MANDATORY: the only one essential method
+// ============================================================================
+double LoKi::GenVertices::PositionZ::operator()( const HepMC3::ConstGenVertexPtr & v ) const {
+  if ( UNLIKELY( !v ) ) {
+    Error( "HepMC3::GenVertexPtr points to NULL; return 'InvalidDistance'" );
+    return LoKi::Constants::InvalidDistance;
+  }
+  return v->position().z();
+}
+// ============================================================================
+//  "SHORT" representation, @see LoKi::AuxFunBase
+// ============================================================================
+std::ostream& LoKi::GenVertices::PositionZ::fillStream( std::ostream& stream ) const { return stream << "GVZ"; }
+// ============================================================================
+//  MANDATORY: clone method ("virtual" constructor")
+// ============================================================================
+LoKi::GenVertices::PositionT* LoKi::GenVertices::PositionT::clone() const { return new PositionT( *this ); }
+// ============================================================================
+//  MANDATORY: the only one essential method
+// ============================================================================
+double LoKi::GenVertices::PositionT::operator()( const HepMC3::ConstGenVertexPtr & v ) const {
+  if ( UNLIKELY( !v ) ) {
+    Error( "HepMC3::GenVertexPtr points to NULL; return 'InvalidTime'" );
+    return LoKi::Constants::InvalidTime;
+  }
+  return v->position().t();
+}
+// ============================================================================
+//  "SHORT" representation, @see LoKi::AuxFunBase
+// ============================================================================
+std::ostream& LoKi::GenVertices::PositionT::fillStream( std::ostream& stream ) const { return stream << "GVT"; }
+
+// ============================================================================
+//  MANDATORY: clone method ("virtual" constructor")
+// ============================================================================
+LoKi::GenVertices::Rho* LoKi::GenVertices::Rho::clone() const { return new Rho( *this ); }
+// ============================================================================
+//  MANDATORY: the only one essential method
+// ============================================================================
+double LoKi::GenVertices::Rho::operator()( const HepMC3::ConstGenVertexPtr & v ) const {
+  if ( UNLIKELY( !v ) ) {
+    Error( "HepMC3::GenVertexPtr points to NULL; return 'InvalidDistance'" );
+    return LoKi::Constants::InvalidDistance;
+  }
+  return v->position().perp();
+}
+// ============================================================================
+//  "SHORT" representation, @see LoKi::AuxFunBase
+// ============================================================================
+std::ostream& LoKi::GenVertices::Rho::fillStream( std::ostream& stream ) const { return stream << "GVRHO"; }
+
+// ============================================================================
+/*  constructor from the criteria and "range"
+ *  @param cut the criteria
+ *  @param range search region
+ *  @see const HepMC3::Relatives &
+ */
+// ============================================================================
+LoKi::GenVertices::CountIF::CountIF( const LoKi::Types::GCuts& cut, const HepMC3::Relatives & range )
+    : m_cut( cut ), m_range( range ) {}
+// ============================================================================
+/*  constructor from the criteria and "range"
+ *  @param range search region
+ *  @param cut the criteria
+ *  @see const HepMC3::Relatives &
+ */
+// ============================================================================
+LoKi::GenVertices::CountIF::CountIF( const HepMC3::Relatives & range, const LoKi::Types::GCuts& cut )
+    : m_cut( cut ), m_range( range ) {}
+// ============================================================================
+//  MANDATORY: clone method ("virtual contructor")
+// ============================================================================
+LoKi::GenVertices::CountIF* LoKi::GenVertices::CountIF::clone() const { return new CountIF( *this ); }
+// ============================================================================
+//  MANDATORY: the only one essential method
+// ============================================================================
+double LoKi::GenVertices::CountIF::operator()( const HepMC3::ConstGenVertexPtr & v ) const {
+  if ( UNLIKELY( !v ) ) { return 0; }
+  auto particles = m_range(v);
+  return std::count_if( std::begin(particles), std::end(particles), m_cut );
+}
+// ============================================================================
+//  "SHORT" representation, @see LoKi::AuxFunBase
+// ============================================================================
+std::ostream& LoKi::GenVertices::CountIF::fillStream( std::ostream& stream ) const {
+  stream << "GVCOUNT(" << m_cut << ",";
+  stream << HepMCUtils::RelationToString(m_range);
+  return stream << ")";
+}
+// ============================================================================
+/*  constructor from the function and the "range"
+ *  @param range search region
+ *  @see const HepMC3::Relatives &
+ */
+// ============================================================================
+LoKi::GenVertices::SumIF::SumIF( const LoKi::Types::GFunc& fun, const HepMC3::Relatives & range )
+    : m_fun( fun )
+    , m_cut( LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::BooleanConstant( true ) )
+    , m_range( range ) {}
+// ============================================================================
+/*  constructor from the function and the "range"
+ *  @param range search region
+ *  @see const HepMC3::Relatives &
+ */
+// ============================================================================
+LoKi::GenVertices::SumIF::SumIF( const HepMC3::Relatives & range, const LoKi::Types::GFunc& fun )
+    : m_fun( fun )
+    , m_cut( LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::BooleanConstant( true ) )
+    , m_range( range ) {}
+// ============================================================================
+/*  constructor from the function, criteria and "range"
+ *  @param cut the criteria
+ *  @param range search region
+ *  @see const HepMC3::Relatives &
+ */
+// ============================================================================
+LoKi::GenVertices::SumIF::SumIF( const LoKi::Types::GFunc& fun, const HepMC3::Relatives & range,
+                                 const LoKi::Types::GCuts& cut )
+    : m_fun( fun ), m_cut( cut ), m_range( range ) {}
+// ============================================================================
+/*  constructor from the function, "range" and criteria
+ *  @param fun function to be accuulated
+ *  @param cut the criteria
+ *  @param range search region
+ *  @see const HepMC3::Relatives &
+ */
+// ============================================================================
+LoKi::GenVertices::SumIF::SumIF( const LoKi::Types::GFunc& fun, const LoKi::Types::GCuts& cut,
+                                 const HepMC3::Relatives & range )
+    : m_fun( fun ), m_cut( cut ), m_range( range ) {}
+// ============================================================================
+/*  constructor from the function, "range" and criteria
+ *  @param cut the criteria
+ *  @param fun function to be accuulated
+ *  @param range search region
+ *  @see const HepMC3::Relatives &
+ */
+// ============================================================================
+LoKi::GenVertices::SumIF::SumIF( const LoKi::Types::GCuts& cut, const LoKi::Types::GFunc& fun,
+                                 const HepMC3::Relatives & range )
+    : m_fun( fun ), m_cut( cut ), m_range( range ) {}
+// ============================================================================
+//  MANDATORY: clone method ("virtual contructor")
+// ============================================================================
+LoKi::GenVertices::SumIF* LoKi::GenVertices::SumIF::clone() const { return new SumIF( *this ); }
+// ============================================================================
+//  MANDATORY: the only one essential method
+// ============================================================================
+double LoKi::GenVertices::SumIF::operator()( const HepMC3::ConstGenVertexPtr & v ) const {
+  if ( UNLIKELY( !v ) ) {
+    Error( "HepMC3::GenVertexPtr poitns to NULL, return 0 " );
+    return 0;
+  }
+  auto particles = m_range(v);
+
+  return std::accumulate( std::begin(particles), std::end(particles), 0.,
+                          [&]( double r, HepMC3::ConstGenParticlePtr p ) {
+                            if ( UNLIKELY( !p ) ) {
+                              Warning( "HepMC3::GenParticlePtr points to 0; skip it" );
+                            } else if ( m_cut( p ) ) {
+                              r += m_fun( p );
+                            }
+                            return r;
+                          } );
+}
+// ============================================================================
+//  "SHORT" representation, @see LoKi::AuxFunBase
+// ============================================================================
+std::ostream& LoKi::GenVertices::SumIF::fillStream( std::ostream& stream ) const {
+  stream << "GVSUM(" << m_fun << ",";
+  stream << HepMCUtils::RelationToString(m_range);
+  return stream << "," << m_cut << ")";
+}
+// ============================================================================
+
+// ============================================================================
+// The END
+// ============================================================================
diff --git a/Gen/LoKiGen/src/IGenDecay.cpp b/Gen/LoKiGen/src/IGenDecay.cpp
new file mode 100644
index 000000000..796dfd04b
--- /dev/null
+++ b/Gen/LoKiGen/src/IGenDecay.cpp
@@ -0,0 +1,27 @@
+/*****************************************************************************\
+* (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration      *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                             *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+// ============================================================================
+// Include files
+// ============================================================================
+// LoKi
+// ============================================================================
+#include "LoKi/IGenDecay.h"
+// ============================================================================
+/** @file
+ *  Implementation file for class Decays::IGenDecay
+ *  @author Ivan BELYAEV
+ *  @date   2009-05-22
+ */
+// ============================================================================
+
+// ============================================================================
+// The END
+// ============================================================================
diff --git a/Gen/LoKiGen/src/IGenHybridFactory.cpp b/Gen/LoKiGen/src/IGenHybridFactory.cpp
new file mode 100644
index 000000000..ef4b8f3ff
--- /dev/null
+++ b/Gen/LoKiGen/src/IGenHybridFactory.cpp
@@ -0,0 +1,37 @@
+/*****************************************************************************\
+* (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration      *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                             *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+// ============================================================================
+// Include files
+// ============================================================================
+// LoKi
+// ============================================================================
+#include "LoKi/IGenHybridFactory.h"
+// ============================================================================
+/** @file
+ *
+ *  Implementation file for class LoKi::IGenHybridFactory
+ *
+ *  This file is a part of LoKi project -
+ *    "C++ ToolKit  for Smart and Friendly Physics Analysis"
+ *
+ *  The package has been designed with the kind help from
+ *  Galina PAKHLOVA and Sergey BARSUK.  Many bright ideas,
+ *  contributions and advices from G.Raven, J.van Tilburg,
+ *  A.Golutvin, P.Koppenburg have been used in the design.
+ *
+ *  @date 2004-06-29
+ *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+ *
+ */
+// ============================================================================
+// ============================================================================
+// The END
+// ============================================================================
diff --git a/Gen/LoKiGen/src/IGenHybridTool.cpp b/Gen/LoKiGen/src/IGenHybridTool.cpp
new file mode 100644
index 000000000..560c1fe90
--- /dev/null
+++ b/Gen/LoKiGen/src/IGenHybridTool.cpp
@@ -0,0 +1,41 @@
+/*****************************************************************************\
+* (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration      *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                             *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+// ============================================================================
+// Include files
+// ============================================================================
+// GaudiKernel
+// ============================================================================
+#include "GaudiKernel/IInterface.h"
+// ============================================================================
+// LoKi
+// ============================================================================
+#include "LoKi/IGenHybridTool.h"
+// ============================================================================
+/** @file
+ *
+ *  Implementation file for class LoKi::IGenHybridTool
+ *
+ *  This file is a part of LoKi project -
+ *    "C++ ToolKit  for Smart and Friendly Physics Analysis"
+ *
+ *  The package has been designed with the kind help from
+ *  Galina PAKHLOVA and Sergey BARSUK.  Many bright ideas,
+ *  contributions and advices from G.Raven, J.van Tilburg,
+ *  A.Golutvin, P.Koppenburg have been used in the design.
+ *
+ *  @date 2004-06-29
+ *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+ *
+ */
+// ============================================================================
+// ============================================================================
+// The END
+// ============================================================================
diff --git a/Gen/LoKiGen/src/LoKiGen.cpp b/Gen/LoKiGen/src/LoKiGen.cpp
new file mode 100644
index 000000000..4b4abe55b
--- /dev/null
+++ b/Gen/LoKiGen/src/LoKiGen.cpp
@@ -0,0 +1,38 @@
+/*****************************************************************************\
+* (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration      *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                             *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+// ============================================================================
+// Include files
+// ============================================================================
+// LoKiGen
+// ============================================================================
+#include "LoKi/LoKiGen.h"
+#include "LoKi/LoKiGen_dct.h"
+// ============================================================================
+/** @file
+ *
+ *  Implementation file for package LoKiGen
+ *
+ *  Collection of useful function to extract the information from  HepMC3
+ *
+ *  This file is a part of LoKi project -
+ *    "C++ ToolKit  for Smart and Friendly Physics Analysis"
+ *
+ *  The package has been designed with the kind help from
+ *  Galina PAKHLOVA and Sergey BARSUK.  Many bright ideas,
+ *  contributions and advices from G.Raven, J.van Tilburg,
+ *  A.Golutvin, P.Koppenburg have been used in the design.
+ *
+ *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+ *  @date 2001-01-23
+ */
+// ============================================================================
+// The END
+// ============================================================================
diff --git a/Gen/LoKiGen/src/Oscillated.cpp b/Gen/LoKiGen/src/Oscillated.cpp
new file mode 100644
index 000000000..1b331cc06
--- /dev/null
+++ b/Gen/LoKiGen/src/Oscillated.cpp
@@ -0,0 +1,79 @@
+/*****************************************************************************\
+* (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration      *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                             *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+// ============================================================================
+// Include files
+// ============================================================================
+// HepMC3
+// ============================================================================
+#include "HepMC3/GenEvent.h"
+#include "HepMC3/GenParticle.h"
+#include "HepMC3/GenVertex.h"
+// ============================================================================
+// local
+// ============================================================================
+#include "LoKi/GenOscillated.h"
+// ============================================================================
+/** @file
+ *
+ *  This file is a part of LoKi project -
+ *    "C++ ToolKit  for Smart and Friendly Physics Analysis"
+ *
+ *  The package has been designed with the kind help from
+ *  Galina PAKHLOVA and Sergey BARSUK.  Many bright ideas,
+ *  contributions and advices from G.Raven, J.van Tilburg,
+ *  A.Golutvin, P.Koppenburg have been used in the design.
+ *
+ *  @author Vanya BELYAEV Ivan.Belyaev@cern.ch
+ *  @date 2011-11-11
+ *
+ */
+// ===========================================================================
+/* check the oscillation for the particle
+ *  @param p the particle
+ *  @return the oscillated mother particle
+ *  @author Vanya BELYAEV  Ivan.Belyaev@nikhef.nl
+ *  @date 2008-06-03
+ */
+// ============================================================================
+const HepMC3::ConstGenParticlePtr LoKi::GenParticles::oscillated1( const HepMC3::ConstGenParticlePtr & p ) {
+  if ( !p ) { return nullptr; }
+  auto pv = p->production_vertex();
+  if ( !pv ) { return nullptr; }
+  if ( 1 != pv->particles_in().size() ) { return nullptr; }
+  auto m = *std::cbegin( pv->particles_in() );
+  if ( !m ) { return nullptr; }
+  // oscillated ?
+  if ( p->pdg_id() != -m->pdg_id() ) { return nullptr; }
+  //
+  return m;
+}
+// ============================================================================
+/*  check the oscillation for the particle
+ *  @param p the particle
+ *  @return the oscillated daughter particle
+ *  @author Vanya BELYAEV  Ivan.Belyaev@nikhef.nl
+ *  @date 2008-06-03
+ */
+const HepMC3::ConstGenParticlePtr LoKi::GenParticles::oscillated2( const HepMC3::ConstGenParticlePtr & p ) {
+  if ( !p ) { return nullptr; }
+  auto ev = p->end_vertex();
+  if ( !ev ) { return nullptr; }
+  if ( 1 != ev->particles_out().size() ) { return nullptr; }
+  auto d = *std::cbegin(ev->particles_out() );
+  if ( !d ) { return nullptr; }
+  // oscillated ?
+  if ( p->pdg_id() != -d->pdg_id() ) { return nullptr; }
+  //
+  return d;
+}
+// ==========================================================================
+// The END
+// ==========================================================================
diff --git a/Gen/LoKiGen/src/PrintHepMCDecay.cpp b/Gen/LoKiGen/src/PrintHepMCDecay.cpp
new file mode 100644
index 000000000..a3180bbb1
--- /dev/null
+++ b/Gen/LoKiGen/src/PrintHepMCDecay.cpp
@@ -0,0 +1,176 @@
+/*****************************************************************************\
+* (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration      *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                             *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+// ============================================================================
+// Include files
+// ============================================================================
+// Include files
+// ===========================================================================
+// STD & STL
+// ===========================================================================
+#include <iostream>
+#include <string>
+// ============================================================================
+// GaudiKernel
+// ============================================================================
+#include "GaudiKernel/MsgStream.h"
+// ============================================================================
+// HepMC3
+// ============================================================================
+#ifdef __INTEL_COMPILER
+#  pragma warning( disable : 1572 ) // floating-point equality and inequality comparisons are unreliable
+#  pragma warning( push )
+#endif
+#include "HepMC3/GenVertex.h"
+#ifdef __INTEL_COMPILER
+#  pragma warning( pop )
+#endif
+// ============================================================================
+// LoKiCore
+// ============================================================================
+#include "LoKi/ParticleProperties.h"
+#include "LoKi/Primitives.h"
+#include "LoKi/Report.h"
+// ===========================================================================
+// LoKiGen
+// ===========================================================================
+#include "LoKi/GenTypes.h"
+// ===========================================================================
+// Local
+// ===========================================================================
+#include "LoKi/GenOscillated.h"
+#include "LoKi/PrintHepMCDecay.h"
+
+#include "HepMC3/Relatives.h"
+// ============================================================================
+/** @file
+ *
+ *  Implementation file for fuctions LoKi::printDecay
+ *
+ *  This file is a part of LoKi project -
+ *    "C++ ToolKit  for Smart and Friendly Physics Analysis"
+ *
+ *  The package has been designed with the kind help from
+ *  Galina PAKHLOVA and Sergey BARSUK.  Many bright ideas,
+ *  contributions and advices from G.Raven, J.van Tilburg,
+ *  A.Golutvin, P.Koppenburg have been used in the design.
+ *
+ *  By usage of this code one clearly states the disagreement
+ *  with the campain of \<XXXXXXX\> :
+ *  "No Vanya's lines are allowed in LHCb/Gaudi software."
+ *
+ *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
+ *  @date 2006-05-26
+ */
+// ============================================================================
+// Simple function to print decay in more or less "readable" format
+// ============================================================================
+MsgStream& LoKi::PrintHepMC::printDecay( const HepMC3::ConstGenParticlePtr & particle, MsgStream& stream,
+                                         const LoKi::GenTypes::GCuts& cut, const int level, const std::string& blank ) {
+  if ( stream.isActive() ) { LoKi::PrintHepMC::printDecay( particle, stream.stream(), cut, level, blank ); }
+  return stream;
+}
+// ============================================================================
+// Simple function to print decay in more or less "readable" format
+// ============================================================================
+std::string LoKi::PrintHepMC::printDecay( const HepMC3::ConstGenParticlePtr & particle, const LoKi::GenTypes::GCuts& cut,
+                                          const int level, const std::string& blank ) {
+  std::ostringstream stream;
+  LoKi::PrintHepMC::printDecay( particle, stream, cut, level, blank );
+  return stream.str();
+}
+// ============================================================================
+// Simple function to print decay in more or less "readable" format
+// ============================================================================
+std::ostream& LoKi::PrintHepMC::printDecay( const HepMC3::ConstGenParticlePtr & particle, std::ostream& stream,
+                                            const LoKi::GenTypes::GCuts& cut, const int level,
+                                            const std::string& blank ) {
+  if ( !particle ) {
+    LoKi::Report::Warning( "LoKi::printDecay, invalid particle" );
+    return stream << " <NULL> "; // RETURN
+  }
+  //
+  if ( !cut( particle ) ) { return stream << blank; }; // RETURN
+  //
+  HepMC3::ConstGenParticlePtr osc1 = LoKi::GenParticles::oscillated1( particle );
+  HepMC3::ConstGenParticlePtr osc2 = LoKi::GenParticles::oscillated2( particle );
+  //
+  // case 1 :
+  //      osc1 == osc2 == 0
+  //      no oscilation
+  // case 2 :
+  //      osc1 != 0 , osc2 == 0
+  //      oscillated "fictive" particle, print mother ( 'osc1' ) ID
+  //                               and own daughetrs
+  // case 3 :
+  //      osc1 == 0 , osc2 != 0
+  //      oscillated "real" particle, print own ID and grand-daughetrs
+  // case 4 :
+  //      osc1 != 0 , osc2 != 0
+  //      invalid case
+  if ( osc1 && osc2 ) {
+    LoKi::Report::Error( "LoKi::printDecay, invalid oscillation pattern" );
+    return stream << " <INVALID OSCILLATION PATTERN> "; // RETURN
+  }
+  HepMC3::ConstGenParticlePtr self   = particle;
+  HepMC3::ConstGenParticlePtr source = particle;
+  std::string               name;
+  if ( osc1 ) {
+    self = osc1;
+    name = "[" + LoKi::Particles::nameIdFromPID( LHCb::ParticleID( self->pdg_id() ) ) + "]os''";
+  } else if ( osc2 ) {
+    source = osc2;
+    name   = "[" + LoKi::Particles::nameIdFromPID( LHCb::ParticleID( self->pdg_id() ) ) + "]os'";
+  } else {
+    name = LoKi::Particles::nameIdFromPID( LHCb::ParticleID( self->pdg_id() ) );
+  }
+  // get daughters
+  auto ev = source->end_vertex();
+  if ( 0 == ev ) { return stream << " " << name << " "; } // RETURN
+  auto particles = HepMC3::Relatives::CHILDREN(ev);
+  auto begin = std::begin(particles);
+  auto end   = std::end(particles);
+  if ( end == begin ) { return stream << " " << name << " "; } // RETURN
+  // too many levels ?
+  if ( 0 >= level ) { return stream << " " << name << " "; } // RETURN
+  // print the decay
+  stream << " ( " << name << " ->  ";
+  for ( ; begin != end; ++begin ) {
+    LoKi::PrintHepMC::printDecay( *begin, stream, cut, level - 1, blank );
+  } // RECURSION
+  //
+  return stream << " ) "; // RETURN
+}
+// ============================================================================
+//  Simple function to print HepMC3 decay in more or less "readable" format
+// ============================================================================
+std::ostream& LoKi::PrintHepMC::printDecay( const HepMC3::ConstGenParticlePtr & particle, std::ostream& stream ) {
+  return LoKi::PrintHepMC::printDecay( particle, stream,
+                                       LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::BooleanConstant( true ) );
+}
+// ============================================================================
+//  Simple function to print HepMC3 decay in more or less "readable" format
+// ============================================================================
+MsgStream& LoKi::PrintHepMC::printDecay( const HepMC3::ConstGenParticlePtr & particle, MsgStream& stream ) {
+  return LoKi::PrintHepMC::printDecay( particle, stream,
+                                       LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::BooleanConstant( true ) );
+}
+// ============================================================================
+//  Simple function to print HepMC3 decay in more or less "readable" format
+// ============================================================================
+std::string LoKi::PrintHepMC::printDecay( const HepMC3::ConstGenParticlePtr & particle ) {
+  return LoKi::PrintHepMC::printDecay( particle,
+                                       LoKi::BasicFunctors<HepMC3::ConstGenParticlePtr>::BooleanConstant( true ) );
+}
+// ============================================================================
+
+// ============================================================================
+// The END
+// ============================================================================
diff --git a/Gen/LoKiGen/src/tests/GenDecayGrammarTest.cpp b/Gen/LoKiGen/src/tests/GenDecayGrammarTest.cpp
new file mode 100644
index 000000000..9c00eb6c3
--- /dev/null
+++ b/Gen/LoKiGen/src/tests/GenDecayGrammarTest.cpp
@@ -0,0 +1,87 @@
+/*****************************************************************************\
+* (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration      *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                             *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+// ============================================================================
+// Include files
+// ============================================================================
+// STT & STL
+// ============================================================================
+#include <iostream>
+#include <string>
+// ============================================================================
+// GaudiKernel
+// ============================================================================
+#include "GaudiKernel/StatusCode.h"
+// ============================================================================
+// PartProp
+// ============================================================================
+#include "Kernel/Nodes.h"
+#include "Kernel/Symbols.h"
+// ============================================================================
+// Decays
+// ============================================================================
+#include "LoKi/GenTreesFactory.h"
+#include "LoKi/TreeHelpers.h"
+#include "LoKi/TreeParser.h"
+#include "LoKi/Trees.h"
+// ============================================================================
+/** @file
+ *  Simple application to test Decay Tree parsers
+ *  @author Vanya BELYAEV Ivan.Belyaev@nikhef.nl
+ *  @date 2009-05-22
+ */
+// ============================================================================
+int main() {
+
+  const Decays::Symbols& syms = Decays::Symbols::instance();
+
+  std::vector<std::string> symbols, particles;
+  syms.symbols( symbols );
+
+  typedef Decays::Tree_<HepMC3::ConstGenParticlePtr>           Tree;
+  typedef Decays::Trees::Invalid_<HepMC3::ConstGenParticlePtr> Invalid;
+
+  particles.push_back( "B0" );
+  particles.push_back( "B+" );
+  particles.push_back( "B-" );
+  particles.push_back( "D0" );
+  particles.push_back( "D+" );
+  particles.push_back( "D-" );
+  particles.push_back( "X(3872)+" );
+  particles.push_back( "X(3872)~+" );
+
+  std::string input;
+  std::cout << " Enter the tree " << std::endl;
+
+  while ( std::getline( std::cin, input ) ) {
+    if ( input.empty() ) { break; }
+
+    // 1) parse the intout into "generic tree"
+    Decays::Parsers::Tree tree;
+    StatusCode            sc = Decays::Parsers::parse( tree, input, symbols, particles, std::cout );
+
+    std::cout << " Parsing of #'" << input << "'# "
+              << " is " << sc << std::endl
+              << " Result is " << tree << std::endl;
+
+    // 2) convert it into reasonable decay tree
+    Tree gtree = Invalid();
+    sc         = Decays::Trees::factory( gtree, tree, std::cout );
+
+    std::cout << " GTree from #'" << input << "'# "
+              << " is " << sc << std::endl
+              << " Result is " << gtree << std::endl;
+
+    std::cout << " Enter the tree  " << std::endl;
+  }
+}
+// ============================================================================
+// The END
+// ============================================================================
diff --git a/Gen/LoKiGen/tests/GenDecayGrammarTest.txt b/Gen/LoKiGen/tests/GenDecayGrammarTest.txt
new file mode 100644
index 000000000..30b5e62bd
--- /dev/null
+++ b/Gen/LoKiGen/tests/GenDecayGrammarTest.txt
@@ -0,0 +1,12 @@
+( B0  -> X  X0 ) 
+( B0  -> X  X0 ... ) 
+( B0  -> X  X0 { X+ } ) 
+( B0 --> X  X0 ) 
+( B0 --> X  X0 ... ) 
+( B0 --> X  X0 X+ X- { l+} { ( l- -> Nu  ( Beauty & Meson ) ...  ) } )
+( B0  => X  X0 ) 
+( B0  => X  X0 X+ X- { l+} { ( l- -> Nu  ( Beauty & Meson ) ...  ) } )
+( [B0]os   ==> X  X0 ) 
+( [B0]nos  ==> X  X0 Stable ) 
+(  ( B0 | B+ )   => X  X0 X+ X- { l+} { ( l- -> Nu  ( Beauty & Meson ) ...  ) } )
+
diff --git a/Gen/LoKiGen/tests/qmtest/jira_461.qmt b/Gen/LoKiGen/tests/qmtest/jira_461.qmt
new file mode 100644
index 000000000..c97f55adf
--- /dev/null
+++ b/Gen/LoKiGen/tests/qmtest/jira_461.qmt
@@ -0,0 +1,15 @@
+<?xml version="1.0" ?>
+<!--
+    (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration
+
+    This software is distributed under the terms of the GNU General Public
+    Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".
+
+    In applying this licence, CERN does not waive the privileges and immunities
+    granted to it by virtue of its status as an Intergovernmental Organization
+    or submit itself to any jurisdiction.
+-->
+<!DOCTYPE extension  PUBLIC '-//QM/2.3/Extension//EN'  'http://www.codesourcery.com/qm/dtds/2.3/-//qm/2.3/extension//en.dtd'>
+<extension class="GaudiTest.GaudiExeTest" kind="test">
+  <argument name="program">   <text>../tst_JIRA_LBCORE461.py</text></argument>
+</extension>
diff --git a/Gen/LoKiGen/tests/qmtest/lokigen0.qmt b/Gen/LoKiGen/tests/qmtest/lokigen0.qmt
new file mode 100644
index 000000000..36772b988
--- /dev/null
+++ b/Gen/LoKiGen/tests/qmtest/lokigen0.qmt
@@ -0,0 +1,15 @@
+<?xml version="1.0" ?>
+<!--
+    (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration
+
+    This software is distributed under the terms of the GNU General Public
+    Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".
+
+    In applying this licence, CERN does not waive the privileges and immunities
+    granted to it by virtue of its status as an Intergovernmental Organization
+    or submit itself to any jurisdiction.
+-->
+<!DOCTYPE extension  PUBLIC '-//QM/2.3/Extension//EN'  'http://www.codesourcery.com/qm/dtds/2.3/-//qm/2.3/extension//en.dtd'>
+<extension class="GaudiTest.GaudiExeTest" kind="test">
+  <argument name="program">   <text>../../python/LoKiGen/tests.py</text></argument>
+</extension>
diff --git a/Gen/LoKiGen/tests/tst_JIRA_LBCORE461.py b/Gen/LoKiGen/tests/tst_JIRA_LBCORE461.py
new file mode 100755
index 000000000..3be1923e4
--- /dev/null
+++ b/Gen/LoKiGen/tests/tst_JIRA_LBCORE461.py
@@ -0,0 +1,40 @@
+#!/usr/bin/env python
+###############################################################################
+# (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration      #
+#                                                                             #
+# This software is distributed under the terms of the GNU General Public      #
+# Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   #
+#                                                                             #
+# In applying this licence, CERN does not waive the privileges and immunities #
+# granted to it by virtue of its status as an Intergovernmental Organization  #
+# or submit itself to any jurisdiction.                                       #
+###############################################################################
+# =====================================================================================
+from LoKiGen.decorators import *
+
+GPV = std.vector('HepMC3::ConstGenParticlePtr')
+v = GPV()
+
+p = HepMC.GenParticle()
+p.set_pdg_id(11)
+
+v.push_back(p)
+
+p1 = HepMC.GenParticle()
+p1.set_pdg_id(13)
+v.push_back(p1)
+
+p2 = HepMC.GenParticle()
+p2.set_pdg_id(22)
+v.push_back(p2)
+
+## THIS IS OK
+for i in v:
+    print i.pdg_id()
+
+## make a range from vector
+r = GRange(v)
+
+## THIS MAKES SEGMENTATION FAULT FOR ROOT6
+for i in r:
+    print i.pdg_id()
-- 
GitLab


From 53b230b8044d6390dce30176e21e562518c83218 Mon Sep 17 00:00:00 2001
From: Dominik Muller <dominik.muller@cern.ch>
Date: Wed, 4 Dec 2019 17:10:55 +0100
Subject: [PATCH 44/90] Adapted to new HepMC3::GenEventPtrs

---
 Gen/GenCuts/src_future/GenericFullEventCutTool.cpp | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/Gen/GenCuts/src_future/GenericFullEventCutTool.cpp b/Gen/GenCuts/src_future/GenericFullEventCutTool.cpp
index 63c8f2741..8ebcafa06 100644
--- a/Gen/GenCuts/src_future/GenericFullEventCutTool.cpp
+++ b/Gen/GenCuts/src_future/GenericFullEventCutTool.cpp
@@ -62,7 +62,7 @@ namespace LoKi
      *  @see IFullGEnEventrCutTool
      */
     bool studyFullEvent
-    ( const std::vector<HepMC3::GenEvent> & theEvents ,
+    ( const HepMC3::GenEventPtrs & theEvents ,
       const LHCb::GenCollisions & /* theCollisions */ ) const override;
     // =========================================================================
   public:
@@ -160,7 +160,7 @@ StatusCode LoKi::FullGenEventCut::decode()
  */
 // ============================================================================
 bool LoKi::FullGenEventCut::studyFullEvent
-( const std::vector<HepMC3::GenEvent> & theEvents ,
+( const HepMC3::GenEventPtrs & theEvents ,
   const LHCb::GenCollisions & /* theCollisions */ ) const
 {
   //
@@ -172,8 +172,8 @@ bool LoKi::FullGenEventCut::studyFullEvent
   for ( auto & evt: theEvents)
   {
     particles.insert ( particles.end ()          ,
-                       std::begin(evt.particles()) ,
-                       std::end(evt.particles()) ) ;
+                       std::begin(evt->particles()) ,
+                       std::end(evt->particles()) ) ;
   }
   //
   // evaluate the functor:
-- 
GitLab


From ad6dbf842ee01bf33824b97c58d1955482c3bbaa Mon Sep 17 00:00:00 2001
From: Dominik Muller <dominik.muller@cern.ch>
Date: Fri, 31 Jan 2020 15:35:44 +0100
Subject: [PATCH 45/90] Fixes for LoKiGen, working generator cuts now

---
 Gen/LoKiGen/CMakeLists.txt          |  5 +++--
 Gen/LoKiGen/LoKi/GenHybridEngine.h  |  3 +++
 Gen/LoKiGen/LoKi/GenParticles.h     | 10 ++++++++++
 Gen/LoKiGen/LoKi/GenParticles3.h    |  4 ++++
 Gen/LoKiGen/src/GenHybridEngine.cpp |  8 +++++++-
 Gen/LoKiGen/src/GenParticles.cpp    | 11 +++++++++++
 Gen/LoKiGen/src/GenParticles3.cpp   |  5 +++++
 7 files changed, 43 insertions(+), 3 deletions(-)

diff --git a/Gen/LoKiGen/CMakeLists.txt b/Gen/LoKiGen/CMakeLists.txt
index 579632fcf..9b77bbe1f 100644
--- a/Gen/LoKiGen/CMakeLists.txt
+++ b/Gen/LoKiGen/CMakeLists.txt
@@ -16,7 +16,8 @@ gaudi_subdir(LoKiGen v10r24)
 find_package(Graphviz) 
 gaudi_depends_on_subdirs(Phys/LoKiCore
                          Phys/LoKiNumbers
-                         Gen/Generators)
+                         Gen/Generators
+                         HepMCUtils)
 
 include_directories(SYSTEM ${Boost_INCLUDE_DIRS} ${ROOT_INCLUDE_DIRS})
 
@@ -26,7 +27,7 @@ gaudi_add_library(LoKiGenLib
                   src/*.cpp
                   PUBLIC_HEADERS LoKi
                   INCLUDE_DIRS ${HEPMC3_INCLUDE_DIR}
-                  LINK_LIBRARIES GeneratorsLib LoKiCoreLib ${HEPMC3_LIBRARIES})
+                  LINK_LIBRARIES GeneratorsLib LoKiCoreLib ${HEPMC3_LIBRARIES} HepMCUtils)
 
 gaudi_add_module(LoKiGen
                  src/Components/*.cpp
diff --git a/Gen/LoKiGen/LoKi/GenHybridEngine.h b/Gen/LoKiGen/LoKi/GenHybridEngine.h
index 15229bc7e..69c48445e 100644
--- a/Gen/LoKiGen/LoKi/GenHybridEngine.h
+++ b/Gen/LoKiGen/LoKi/GenHybridEngine.h
@@ -18,6 +18,7 @@
 // ============================================================================
 // LoKi
 // ============================================================================
+#include "LoKi/Context.h"
 #include "LoKi/IGenHybridTool.h"
 // ============================================================================
 /** @file
@@ -118,6 +119,8 @@ namespace LoKi {
       /// add the source
       StatusCode process( const std::string& name, const LoKi::Types::GVSources& func ) const;
       // ======================================================================
+      /// get the current context
+      const LoKi::Context* context() const;
     };
     // ========================================================================
   } // namespace Hybrid
diff --git a/Gen/LoKiGen/LoKi/GenParticles.h b/Gen/LoKiGen/LoKi/GenParticles.h
index 2ff173086..40f8703c3 100644
--- a/Gen/LoKiGen/LoKi/GenParticles.h
+++ b/Gen/LoKiGen/LoKi/GenParticles.h
@@ -803,6 +803,8 @@ namespace LoKi {
        *  @see const HepMC3::Relatives &
        */
       NInTree( const LoKi::GenTypes::GCuts& cut, const HepMC3::Relatives & range = HepMC3::Relatives::DESCENDANTS );
+      // Same as above but access range via index as in HepMC2
+      NInTree( const LoKi::GenTypes::GCuts& cut, int idx );
       /// MANDATORY: clone function ("virtual constructor")
       NInTree* clone() const override;
       /// MANDATORY: the only one essential method
@@ -856,6 +858,8 @@ namespace LoKi {
        */
       MaxTree( const LoKi::GenTypes::GFunc& fun, const LoKi::GenTypes::GCuts& cut,
           const HepMC3::Relatives & range = HepMC3::Relatives::DESCENDANTS);
+      MaxTree( const LoKi::GenTypes::GFunc& fun, const LoKi::GenTypes::GCuts& cut,
+          int idx);
       /// MANDATORY: clone function ("virtual constructor")
       MaxTree* clone() const override;
       /// MANDATORY: the only one essential method
@@ -897,6 +901,8 @@ namespace LoKi {
        */
       MinTree( const LoKi::GenTypes::GFunc& fun, const LoKi::GenTypes::GCuts& cut,
                const HepMC3::Relatives & range = HepMC3::Relatives::DESCENDANTS);
+      MinTree( const LoKi::GenTypes::GFunc& fun, const LoKi::GenTypes::GCuts& cut,
+               int idx);
       /// MANDATORY: clone function ("virtual constructor")
       MinTree* clone() const override;
       /// MANDATORY: the only one essential method
@@ -934,6 +940,8 @@ namespace LoKi {
        */
       SumTree( const LoKi::GenTypes::GFunc& fun, const LoKi::GenTypes::GCuts& cut,
                const HepMC3::Relatives & range = HepMC3::Relatives::DESCENDANTS);
+      SumTree( const LoKi::GenTypes::GFunc& fun, const LoKi::GenTypes::GCuts& cut,
+               int idx);
 
       /// MANDATORY: clone function ("virtual constructor")
       SumTree* clone() const override;
@@ -972,6 +980,8 @@ namespace LoKi {
        */
       MultTree( const LoKi::GenTypes::GFunc& fun, const LoKi::GenTypes::GCuts& cut,
                 const HepMC3::Relatives & range = HepMC3::Relatives::DESCENDANTS);
+      MultTree( const LoKi::GenTypes::GFunc& fun, const LoKi::GenTypes::GCuts& cut,
+                int idx);
       /// MANDATORY: clone function ("virtual constructor")
       MultTree* clone() const override;
       /// MANDATORY: the only one essential method
diff --git a/Gen/LoKiGen/LoKi/GenParticles3.h b/Gen/LoKiGen/LoKi/GenParticles3.h
index 01fb0c92b..bb7eacccd 100644
--- a/Gen/LoKiGen/LoKi/GenParticles3.h
+++ b/Gen/LoKiGen/LoKi/GenParticles3.h
@@ -64,12 +64,14 @@ namespace LoKi {
        *  @see const HepMC3::Relatives &
        */
       Count( const LoKi::Types::GCuts& cut, const HepMC3::Relatives & range );
+      Count( const LoKi::Types::GCuts& cut, int range_idx );
       /** constructor from the criteria and "range"
        *  @param range search region
        *  @param cut the criteria
        *  @see const HepMC3::Relatives &
        */
       Count( const HepMC3::Relatives & range, const LoKi::Types::GCuts& cut );
+      Count( int range_idx, const LoKi::Types::GCuts& cut );
       // ======================================================================
       /// MANDATORY: clone method ("virtual contructor")
       Count* clone() const override;
@@ -105,12 +107,14 @@ namespace LoKi {
        *  @see const HepMC3::Relatives &
        */
       Has( const LoKi::Types::GCuts& cut, const HepMC3::Relatives & range );
+      Has( const LoKi::Types::GCuts& cut, int range_idx );
       /** constructor from the criteria and "range"
        *  @param range search region
        *  @param cut the criteria
        *  @see const HepMC3::Relatives &
        */
       Has( const HepMC3::Relatives & range, const LoKi::Types::GCuts& cut );
+      Has( int range_idx, const LoKi::Types::GCuts& cut );
       // ======================================================================
       /// MANDATORY: clone method ("virtual contructor")
       Has* clone() const override;
diff --git a/Gen/LoKiGen/src/GenHybridEngine.cpp b/Gen/LoKiGen/src/GenHybridEngine.cpp
index ac9ea91b7..61a828c4a 100644
--- a/Gen/LoKiGen/src/GenHybridEngine.cpp
+++ b/Gen/LoKiGen/src/GenHybridEngine.cpp
@@ -132,7 +132,13 @@ StatusCode LoKi::Hybrid::GenEngine::process( const std::string& name, const LoKi
   return _process( name, cut );
 }
 // ============================================================================
-
+// get the current context
+// ============================================================================
+const LoKi::Context* LoKi::Hybrid::GenEngine::context() const {
+  const LoKi::Hybrid::GenEngineActor& actor = LoKi::Hybrid::GenEngineActor::instance();
+  return actor.context();
+}
+// ============================================================================
 // ============================================================================
 // The END
 // ============================================================================
diff --git a/Gen/LoKiGen/src/GenParticles.cpp b/Gen/LoKiGen/src/GenParticles.cpp
index 6f4305bc3..b0d2a72ca 100644
--- a/Gen/LoKiGen/src/GenParticles.cpp
+++ b/Gen/LoKiGen/src/GenParticles.cpp
@@ -51,6 +51,7 @@
 #include "boost/format.hpp"
 // ============================================================================
 #include "HepMCUtils/HepMCUtils.h"
+#include "HepMCUtils/Relatives.h"
 /** @file
  *
  *  Implementation of the functions form namespace LoKi::GenParticles
@@ -637,6 +638,8 @@ namespace LoKi {
     // ============================================================================
     NInTree::NInTree( const LoKi::GenTypes::GCuts& cut, const HepMC3::Relatives & range )
         : LoKi::AuxFunBase( std::tie( cut, range ) ), m_cut( cut ), m_range( range ) {}
+    NInTree::NInTree( const LoKi::GenTypes::GCuts& cut, int idx )
+        : NInTree(cut, HepMCUtils::RelativesFromID(idx)) {}
     // ============================================================================
     //  MANDATORY: clone function ("virtual constructor")
     // ============================================================================
@@ -687,6 +690,8 @@ namespace LoKi {
     // ============================================================================
     MaxTree::MaxTree( const LoKi::GenTypes::GFunc& fun, const LoKi::GenTypes::GCuts& cut, const HepMC3::Relatives & range )
         : LoKi::AuxFunBase( std::tie( fun, cut, range ) ), NInTree( cut, range ), m_fun( fun ) {}
+    MaxTree::MaxTree( const LoKi::GenTypes::GFunc& fun, const LoKi::GenTypes::GCuts& cut, int idx)
+        : MaxTree(fun, cut, HepMCUtils::RelativesFromID(idx)) {}
     // ============================================================================
     // MANDATORY: clone function ("virtual constructor")
     // ============================================================================
@@ -735,6 +740,8 @@ namespace LoKi {
     // ============================================================================
     MinTree::MinTree( const LoKi::GenTypes::GFunc& fun, const LoKi::GenTypes::GCuts& cut,  const HepMC3::Relatives & range )
         : LoKi::AuxFunBase( std::tie( fun, cut, range ) ), MaxTree( fun, cut, range ) {}
+    MinTree::MinTree( const LoKi::GenTypes::GFunc& fun, const LoKi::GenTypes::GCuts& cut, int idx )
+        : MinTree(fun, cut, HepMCUtils::RelativesFromID(idx)) {}
     // ============================================================================
     // MANDATORY: clone function ("virtual constructor")
     // ============================================================================
@@ -781,6 +788,8 @@ namespace LoKi {
     // ============================================================================
     SumTree::SumTree( const LoKi::GenTypes::GFunc& fun, const LoKi::GenTypes::GCuts& cut, const HepMC3::Relatives & range )
         : LoKi::AuxFunBase( std::tie( fun, cut, range ) ), MinTree( fun, cut, range ) {}
+    SumTree::SumTree( const LoKi::GenTypes::GFunc& fun, const LoKi::GenTypes::GCuts& cut, int idx )
+        : SumTree(fun, cut, HepMCUtils::RelativesFromID(idx)) {}
     // ============================================================================
     // MANDATORY: clone function ("virtual constructor")
     // ============================================================================
@@ -828,6 +837,8 @@ namespace LoKi {
     // ============================================================================
     MultTree::MultTree( const LoKi::GenTypes::GFunc& fun, const LoKi::GenTypes::GCuts& cut, const HepMC3::Relatives & range )
         : LoKi::AuxFunBase( std::tie( fun, cut, range ) ), SumTree( fun, cut, range ) {}
+    MultTree::MultTree( const LoKi::GenTypes::GFunc& fun, const LoKi::GenTypes::GCuts& cut, int idx )
+        : MultTree(fun, cut, HepMCUtils::RelativesFromID(idx)) {}
     // ============================================================================
     // MANDATORY: clone function ("virtual constructor")
     // ============================================================================
diff --git a/Gen/LoKiGen/src/GenParticles3.cpp b/Gen/LoKiGen/src/GenParticles3.cpp
index 15193225d..9e6d8a623 100644
--- a/Gen/LoKiGen/src/GenParticles3.cpp
+++ b/Gen/LoKiGen/src/GenParticles3.cpp
@@ -21,6 +21,7 @@
 #include "LoKi/GenExtract.h"
 #include "LoKi/GenParticles3.h"
 #include "HepMCUtils/HepMCUtils.h"
+#include "HepMCUtils/Relatives.h"
 // ============================================================================
 /** @file
  *
@@ -61,6 +62,7 @@ namespace LoKi {
      */
     // ============================================================================
     Count::Count( const LoKi::Types::GCuts& cut, const HepMC3::Relatives & range ) : m_cut( cut ), m_range( range ) {}
+    Count::Count( const LoKi::Types::GCuts& cut, int range_idx ) : Count(cut, HepMCUtils::RelativesFromID(range_idx)) {}
     // ============================================================================
     /*  constructor from the criteria and "range"
      *  @param cut the criteria
@@ -69,6 +71,7 @@ namespace LoKi {
      */
     // ============================================================================
     Count::Count( const HepMC3::Relatives & range, const LoKi::Types::GCuts& cut ) : m_cut( cut ), m_range( range ) {}
+    Count::Count( int range_idx, const LoKi::Types::GCuts& cut ) : Count(HepMCUtils::RelativesFromID(range_idx), cut) {}
     // ============================================================================
     // MANDATORY: clone method ("virtual contructor")
     // ============================================================================
@@ -103,6 +106,7 @@ namespace LoKi {
      */
     // ============================================================================
     Has::Has( const LoKi::Types::GCuts& cut, const HepMC3::Relatives & range ) : m_cut( cut ), m_range( range ) {}
+    Has::Has( const LoKi::Types::GCuts& cut, int range_idx ) : Has(cut, HepMCUtils::RelativesFromID(range_idx)) {}
     // ============================================================================
     /*  constructor from the criteria and "range"
      *  @param cut the criteria
@@ -111,6 +115,7 @@ namespace LoKi {
      */
     // ============================================================================
     Has::Has( const HepMC3::Relatives & range, const LoKi::Types::GCuts& cut ) : m_cut( cut ), m_range( range ) {}
+    Has::Has( int range_idx, const LoKi::Types::GCuts& cut ) : Has(HepMCUtils::RelativesFromID(range_idx), cut) {}
     // ============================================================================
     // MANDATORY: clone method ("virtual contructor")
     // ============================================================================
-- 
GitLab


From 6dcd3a2fd67518d56766e0b74af517451de0cdea Mon Sep 17 00:00:00 2001
From: Dominik Muller <dominik.muller@cern.ch>
Date: Wed, 25 Mar 2020 15:02:15 +0100
Subject: [PATCH 46/90] StatusCode ignores for gencuts

---
 Gen/GenCuts/src_future/GenericGenCutTool.cpp  | 10 +--
 .../src_future/GenericGenCutToolWithDecay.cpp |  4 +-
 Gen/LoKiGen/LoKi/GenDecayChain.h              |  4 +-
 Gen/LoKiGen/src/Components/DumpHepMC.cpp      |  2 +-
 Gen/LoKiGen/src/Components/GenDecay.cpp       |  6 +-
 Gen/LoKiGen/src/Components/GenFilter.cpp      |  2 +-
 Gen/LoKiGen/src/GenChildSelector.cpp          | 10 +--
 Gen/LoKiGen/src/GenHybridEngineActor.cpp      |  2 +-
 Gen/LoKiGen/src/GenKinematics.cpp             | 20 +++---
 Gen/LoKiGen/src/GenParticles.cpp              |  4 +-
 Gen/LoKiGen/src/GenParticles2.cpp             | 64 +++++++++----------
 Gen/LoKiGen/src/GenParticles3.cpp             |  4 +-
 Gen/LoKiGen/src/GenParticles4.cpp             | 44 ++++++-------
 Gen/LoKiGen/src/GenParticles5.cpp             | 10 +--
 Gen/LoKiGen/src/GenVertices.cpp               | 16 ++---
 Gen/LoKiGen/src/PrintHepMCDecay.cpp           |  4 +-
 16 files changed, 103 insertions(+), 103 deletions(-)

diff --git a/Gen/GenCuts/src_future/GenericGenCutTool.cpp b/Gen/GenCuts/src_future/GenericGenCutTool.cpp
index 07524fda2..3d79a46ad 100644
--- a/Gen/GenCuts/src_future/GenericGenCutTool.cpp
+++ b/Gen/GenCuts/src_future/GenericGenCutTool.cpp
@@ -236,7 +236,7 @@ StatusCode LoKi::GenCutTool::decodeDescriptor ()  const
   //
   m_update_decay = false ;
   //
-  release ( factory ) ;
+  release ( factory ).ignore();
   //
   return StatusCode::SUCCESS ;
 } 
@@ -274,8 +274,8 @@ StatusCode LoKi::GenCutTool::decodeCuts ()  const
   //
   m_update_cuts = false ;
   //
-  release ( nodes   ) ;
-  release ( factory ) ;
+  release ( nodes   ).ignore() ;
+  release ( factory ).ignore() ;
   // 
   return StatusCode::SUCCESS ;
 }
@@ -349,7 +349,7 @@ StatusCode LoKi::GenCutTool::decodeHistos ()  const
   }
   // ==========================================================================
   m_update_histos = false ;
-  release ( factory ) ;
+  release ( factory ).ignore() ;
   // 
   return StatusCode::SUCCESS ;
 }
@@ -395,7 +395,7 @@ StatusCode LoKi::GenCutTool::initialize()
 StatusCode LoKi::GenCutTool::finalize () 
 {
   /// calculate the efficiency 
-  getEfficiency() ;
+  getEfficiency().ignore() ;
   /// check errors/problems 
   if  ( m_fill_counters ) 
   {
diff --git a/Gen/GenCuts/src_future/GenericGenCutToolWithDecay.cpp b/Gen/GenCuts/src_future/GenericGenCutToolWithDecay.cpp
index bccedaafb..af2f8ddde 100644
--- a/Gen/GenCuts/src_future/GenericGenCutToolWithDecay.cpp
+++ b/Gen/GenCuts/src_future/GenericGenCutToolWithDecay.cpp
@@ -234,7 +234,7 @@ StatusCode LoKi::GenCutToolWithDecay::initialize ()
 // ============================================================================
 StatusCode LoKi::GenCutToolWithDecay::finalize () 
 {
-  if ( 0 != m_decayTool ) { releaseTool ( m_decayTool ) ; m_decayTool = 0 ; }
+  if ( 0 != m_decayTool ) { releaseTool ( m_decayTool ).ignore() ; m_decayTool = 0 ; }
   //
   typedef std::pair<unsigned long long, std::string> Item  ;
   typedef std::vector<Item>                          Items ;
@@ -320,7 +320,7 @@ bool LoKi::GenCutToolWithDecay::applyCut
     { 
       if ( nullptr == p )  { continue ; }
       const LHCb::ParticleID pid{ p->pdg_id() } ; 
-      m_decayTool -> generateDecayWithLimit ( std::const_pointer_cast<HepMC3::GenParticle>(p) , m_particle.pid(), ThreadLocalEngine::GetPtr() ) ; 
+      m_decayTool -> generateDecayWithLimit ( std::const_pointer_cast<HepMC3::GenParticle>(p) , m_particle.pid(), ThreadLocalEngine::GetPtr() ).ignore() ; 
       if ( UNLIKELY ( msgLevel ( MSG::DEBUG ) ) )
       { ++m_decays[ LoKi::Particles::nameFromPID ( pid )  ] ; }
     }
diff --git a/Gen/LoKiGen/LoKi/GenDecayChain.h b/Gen/LoKiGen/LoKi/GenDecayChain.h
index ab3206b97..d9953703d 100644
--- a/Gen/LoKiGen/LoKi/GenDecayChain.h
+++ b/Gen/LoKiGen/LoKi/GenDecayChain.h
@@ -115,7 +115,7 @@ namespace LoKi {
                    const MARK& mark, const std::string& prefix = " ", const size_t depth = 0 ) const {
       // invalid particle
       if ( 0 == particle ) {
-        Error( " HepMC3::GenParticlePtr points to NULL" );
+        Error( " HepMC3::GenParticlePtr points to NULL" ).ignore();
         return stream; // RETURN
       }
       //
@@ -217,7 +217,7 @@ namespace LoKi {
                    const MARK& mark, const std::string& prefix = " ", const size_t depth = 0 ) const {
       // invalid event
       if ( !event ) {
-        Error( " HepMC3::GenEvent* points to NULL" );
+        Error( " HepMC3::GenEvent* points to NULL" ).ignore();
         return stream;
       }
       // select the trees
diff --git a/Gen/LoKiGen/src/Components/DumpHepMC.cpp b/Gen/LoKiGen/src/Components/DumpHepMC.cpp
index 3d41ab8c0..dc8ad2719 100644
--- a/Gen/LoKiGen/src/Components/DumpHepMC.cpp
+++ b/Gen/LoKiGen/src/Components/DumpHepMC.cpp
@@ -76,7 +76,7 @@ namespace LoKi {
     /// printout mode  ( @see LoKi::DecayChainBase::Mode )
     unsigned short m_mode; // printout mode
     // ========================================================================
-    mutable AnyDataHandle<std::vector<HepMC3::GenEvent>> m_handle{this, Gaudi::DataHandle::Writer, "Location", Gaussino::HepMCEventLocation::Default};
+    mutable DataObjectWriteHandle<std::vector<HepMC3::GenEvent>> m_handle{this, "Location", Gaussino::HepMCEventLocation::Default};
   };
   // ==========================================================================
 } // end of namespace LoKi
diff --git a/Gen/LoKiGen/src/Components/GenDecay.cpp b/Gen/LoKiGen/src/Components/GenDecay.cpp
index 490db2fa6..c2f457f5f 100644
--- a/Gen/LoKiGen/src/Components/GenDecay.cpp
+++ b/Gen/LoKiGen/src/Components/GenDecay.cpp
@@ -88,7 +88,7 @@ Decays::IGenDecay::Tree LoKi::GenDecay::tree( const std::string& decay ) const {
   Decays::Parsers::Tree ptree;
   StatusCode            sc = _parse( ptree, decay );
   if ( sc.isFailure() ) {
-    Error( "Error from _parse('" + decay + "')", sc );
+    Error( "Error from _parse('" + decay + "')", sc ).ignore();
     return Invalid(); // RETURN
   }
   // 2) convert parsed tree into reasonable decay tree
@@ -96,14 +96,14 @@ Decays::IGenDecay::Tree LoKi::GenDecay::tree( const std::string& decay ) const {
   sc        = Decays::Trees::factory( tree, ptree, err.stream() );
   if ( sc.isFailure() ) {
     err << endmsg;
-    Error( "Unable to create the tree from '" + ptree.toString() + "'", sc );
+    Error( "Unable to create the tree from '" + ptree.toString() + "'", sc ).ignore();
     return Invalid(); // RETURN
   }
   // 3) validate the tree
   if ( !tree ) {
     sc = tree.validate( ppSvc() );
     if ( sc.isFailure() ) {
-      Error( "Unable to validate the tree '" + tree.toString() + "'", sc );
+      Error( "Unable to validate the tree '" + tree.toString() + "'", sc ).ignore();
       return Invalid(); // RETURN
     }
   }
diff --git a/Gen/LoKiGen/src/Components/GenFilter.cpp b/Gen/LoKiGen/src/Components/GenFilter.cpp
index 9ce90b893..4cb400682 100644
--- a/Gen/LoKiGen/src/Components/GenFilter.cpp
+++ b/Gen/LoKiGen/src/Components/GenFilter.cpp
@@ -81,7 +81,7 @@ namespace LoKi {
     /// the functor itself
     LoKi::Types::GCutVal m_cut; // the functor itself
     /// TES location of LHCb::HepMC3Event::Container object
-    mutable AnyDataHandle<std::vector<HepMC3::GenEvent>> m_handle{this, Gaudi::DataHandle::Writer, "Location", Gaussino::HepMCEventLocation::Default};
+    mutable DataObjectWriteHandle<std::vector<HepMC3::GenEvent>> m_handle{this, "Location", Gaussino::HepMCEventLocation::Default};
     // ========================================================================
   };
   // ==========================================================================
diff --git a/Gen/LoKiGen/src/GenChildSelector.cpp b/Gen/LoKiGen/src/GenChildSelector.cpp
index 03b8a39d3..94fa5d985 100644
--- a/Gen/LoKiGen/src/GenChildSelector.cpp
+++ b/Gen/LoKiGen/src/GenChildSelector.cpp
@@ -163,10 +163,10 @@ StatusCode LoKi::GenChild::Selector::buildTree( const std::string& descriptor, c
   //
   m_finder = tool->tree( descriptor );
   //
-  toolSvc->releaseTool( tool ); // do not need the tool anymore
+  toolSvc->releaseTool( tool ).ignore(); // do not need the tool anymore
   //
   if ( !m_finder ) { return Error( "getTree: the tree is invalid:  '" + descriptor + "'" ); }
-  if ( !m_finder.marked() ) { Warning( "getTree: the tree is unmarked: '" + descriptor + "'" ); }
+  if ( !m_finder.marked() ) { Warning( "getTree: the tree is unmarked: '" + descriptor + "'" ).ignore(); }
   //
   return StatusCode::SUCCESS;
 }
@@ -208,7 +208,7 @@ std::ostream& LoKi::GenChild::Selector::fillStream( std::ostream& s ) const {
 unsigned int LoKi::GenChild::Selector::children( const HepMC3::ConstGenParticlePtr &    head,
                                                  LoKi::GenTypes::ConstVector& daughters ) const {
   if ( 0 == head ) {
-    Error( "children: HepMC3::GenParticlePtr points to NULL" );
+    Error( "children: HepMC3::GenParticlePtr points to NULL" ).ignore();
     return 0; // RETURN
   }
   //
@@ -237,7 +237,7 @@ unsigned int LoKi::GenChild::Selector::children( const HepMC3::ConstGenParticleP
 HepMC3::ConstGenParticlePtr LoKi::GenChild::Selector::child( const HepMC3::ConstGenParticlePtr & head ) const {
   //
   if ( 0 == head ) {
-    Error( "child: HepMC3::GenParticle points to NULL" );
+    Error( "child: HepMC3::GenParticle points to NULL" ).ignore();
     return 0;
   }
   //
@@ -254,7 +254,7 @@ HepMC3::ConstGenParticlePtr LoKi::GenChild::Selector::child( const HepMC3::Const
   //
   if ( daughters.empty() ) { return 0; } // REUTRN
   //
-  if ( 1 < daughters.size() ) { Warning( "child: >1 daughter particles are found, return the first" ); }
+  if ( 1 < daughters.size() ) { Warning( "child: >1 daughter particles are found, return the first" ).ignore(); }
   //
   return daughters[0];
 }
diff --git a/Gen/LoKiGen/src/GenHybridEngineActor.cpp b/Gen/LoKiGen/src/GenHybridEngineActor.cpp
index da6c225ff..a4bd9f6ca 100644
--- a/Gen/LoKiGen/src/GenHybridEngineActor.cpp
+++ b/Gen/LoKiGen/src/GenHybridEngineActor.cpp
@@ -95,7 +95,7 @@ StatusCode LoKi::Hybrid::GenEngineActor::connect( const LoKi::IGenHybridTool* fa
 // ============================================================================
 const LoKi::Context* LoKi::Hybrid::GenEngineActor::context() const {
   if ( m_stack.empty() ) {
-    LoKi::Report::Error( "LoKi::Hybrid::GenEngineActor::context: empty stack" );
+    LoKi::Report::Error( "LoKi::Hybrid::GenEngineActor::context: empty stack" ).ignore();
     return nullptr;
   }
   const Entry& last = m_stack.top();
diff --git a/Gen/LoKiGen/src/GenKinematics.cpp b/Gen/LoKiGen/src/GenKinematics.cpp
index ca1b1a092..5bf3d078b 100644
--- a/Gen/LoKiGen/src/GenKinematics.cpp
+++ b/Gen/LoKiGen/src/GenKinematics.cpp
@@ -46,7 +46,7 @@
 // ============================================================================
 double LoKi::GenKinematics::mass( const HepMC3::ConstGenParticlePtr & p ) {
   if ( !p ) {
-    LoKi::Report::Error( "mass(HepMC3::GenParticlePtr),invaild argument,return 'InvalidMass'" );
+    LoKi::Report::Error( "mass(HepMC3::GenParticlePtr),invaild argument,return 'InvalidMass'" ).ignore();
     return LoKi::Constants::InvalidMass;
   }
   return LoKi::Kinematics::mass( LoKi::LorentzVector( p->momentum() ) );
@@ -63,11 +63,11 @@ double LoKi::GenKinematics::mass( const HepMC3::ConstGenParticlePtr & p ) {
 // ============================================================================
 double LoKi::GenKinematics::mass( const HepMC3::ConstGenParticlePtr & p1, HepMC3::ConstGenParticlePtr p2 ) {
   if ( !p1 ) {
-    LoKi::Report::Error( "mass(2*HepMC3::GenParticlePtr),invaild argument 1,return 'InvalidMass'" );
+    LoKi::Report::Error( "mass(2*HepMC3::GenParticlePtr),invaild argument 1,return 'InvalidMass'" ).ignore();
     return LoKi::Constants::InvalidMass;
   }
   if ( !p2 ) {
-    LoKi::Report::Error( "mass(2*HepMC3::GenParticlePtr),invaild argument 2,return'InvalidMass'" );
+    LoKi::Report::Error( "mass(2*HepMC3::GenParticlePtr),invaild argument 2,return'InvalidMass'" ).ignore();
     return LoKi::Constants::InvalidMass;
   }
   //
@@ -87,15 +87,15 @@ double LoKi::GenKinematics::mass( const HepMC3::ConstGenParticlePtr & p1, HepMC3
 double LoKi::GenKinematics::mass( const HepMC3::ConstGenParticlePtr & p1, HepMC3::ConstGenParticlePtr p2,
                                   HepMC3::ConstGenParticlePtr p3 ) {
   if ( !p1 ) {
-    LoKi::Report::Error( "mass(3*HepMC3::GenParticlePtr),invaild argument 1,return 'InvalidMass'" );
+    LoKi::Report::Error( "mass(3*HepMC3::GenParticlePtr),invaild argument 1,return 'InvalidMass'" ).ignore();
     return LoKi::Constants::InvalidMass;
   }
   if ( !p2 ) {
-    LoKi::Report::Error( "mass(3*HepMC3::GenParticlePtr),invaild argument 2,return 'InvalidMass'" );
+    LoKi::Report::Error( "mass(3*HepMC3::GenParticlePtr),invaild argument 2,return 'InvalidMass'" ).ignore();
     return LoKi::Constants::InvalidMass;
   }
   if ( !p3 ) {
-    LoKi::Report::Error( "mass(3*HepMC3::GenParticlePtr),invaild argument 3,return 'InvalidMass'" );
+    LoKi::Report::Error( "mass(3*HepMC3::GenParticlePtr),invaild argument 3,return 'InvalidMass'" ).ignore();
     return LoKi::Constants::InvalidMass;
   }
   //
@@ -117,19 +117,19 @@ double LoKi::GenKinematics::mass( const HepMC3::ConstGenParticlePtr & p1, HepMC3
 double LoKi::GenKinematics::mass( const HepMC3::ConstGenParticlePtr & p1, HepMC3::ConstGenParticlePtr p2,
                                   HepMC3::ConstGenParticlePtr p3, HepMC3::ConstGenParticlePtr p4 ) {
   if ( !p1 ) {
-    LoKi::Report::Error( "mass(4*HepMC3::GenParticlePtr),invaild argument 1,return 'InvalidMass'" );
+    LoKi::Report::Error( "mass(4*HepMC3::GenParticlePtr),invaild argument 1,return 'InvalidMass'" ).ignore();
     return LoKi::Constants::InvalidMass;
   }
   if ( !p2 ) {
-    LoKi::Report::Error( "mass(4*HepMC3::GenParticlePtr),invaild argument 2,return 'InvalidMass'" );
+    LoKi::Report::Error( "mass(4*HepMC3::GenParticlePtr),invaild argument 2,return 'InvalidMass'" ).ignore();
     return LoKi::Constants::InvalidMass;
   }
   if ( !p3 ) {
-    LoKi::Report::Error( "mass(4*HepMC3::GenParticlePtr),invaild argument 3,return 'InvalidMass'" );
+    LoKi::Report::Error( "mass(4*HepMC3::GenParticlePtr),invaild argument 3,return 'InvalidMass'" ).ignore();
     return LoKi::Constants::InvalidMass;
   }
   if ( !p4 ) {
-    LoKi::Report::Error( "mass(4*HepMC3::GenParticlePtr),invaild argument 4,return 'InvalidMass'" );
+    LoKi::Report::Error( "mass(4*HepMC3::GenParticlePtr),invaild argument 4,return 'InvalidMass'" ).ignore();
     return LoKi::Constants::InvalidMass;
   }
   //
diff --git a/Gen/LoKiGen/src/GenParticles.cpp b/Gen/LoKiGen/src/GenParticles.cpp
index b0d2a72ca..409c5c54e 100644
--- a/Gen/LoKiGen/src/GenParticles.cpp
+++ b/Gen/LoKiGen/src/GenParticles.cpp
@@ -891,7 +891,7 @@ namespace LoKi {
     // MANDATORY: the only one essential method
     // ============================================================================
     bool InTree::operator()( const HepMC3::ConstGenParticlePtr & p ) const {
-      if ( 0 == p ) { Warning( "HepMC3::ConstGenParticlePtr & points to NULL" ); }
+      if ( 0 == p ) { Warning( "HepMC3::ConstGenParticlePtr & points to NULL" ).ignore(); }
       return LoKi::GenAlgs::found( p, m_cut );
     }
     // ============================================================================
@@ -1021,7 +1021,7 @@ namespace LoKi {
       Assert( 0 != tool, "Decays::IGenDecay* points to NULL" );
       //
       m_tree = tool->tree( descriptor );
-      toolSvc->releaseTool( tool ); // do not need the tool anymore
+      toolSvc->releaseTool( tool ).ignore(); // do not need the tool anymore
       //
       Assert( !( !m_tree ), "The tree is invalid : '" + descriptor + "'" );
       Assert( !m_tree.marked(), "The tree is marked  : '" + descriptor + "'" );
diff --git a/Gen/LoKiGen/src/GenParticles2.cpp b/Gen/LoKiGen/src/GenParticles2.cpp
index 66cb5538c..f49b42d48 100644
--- a/Gen/LoKiGen/src/GenParticles2.cpp
+++ b/Gen/LoKiGen/src/GenParticles2.cpp
@@ -103,7 +103,7 @@ namespace LoKi {
                                                    Decays::IGenDecay::iTree::Collection& vct ) const {
       //
       if ( 0 == p ) {
-        Error( "HepMC3::GenParticlePtr points to NULL" );
+        Error( "HepMC3::GenParticlePtr points to NULL" ).ignore();
         return StatusCode::FAILURE; //                                 RETURN
       }
       //
@@ -112,14 +112,14 @@ namespace LoKi {
       //
       HepMC3::ConstGenParticlePtr c1 = m_first.child( p );
       if ( 0 == c1 ) {
-        Error( "Invalid first  child : '" + m_first.printOut() + "'" );
+        Error( "Invalid first  child : '" + m_first.printOut() + "'" ).ignore();
         return StatusCode::FAILURE;
       }
       vct.push_back( c1 );
       //
       HepMC3::ConstGenParticlePtr c2 = m_second.child( p );
       if ( 0 == c2 ) {
-        Error( "Invalid second child : '" + m_second.printOut() + "'" );
+        Error( "Invalid second child : '" + m_second.printOut() + "'" ).ignore();
         return StatusCode::FAILURE;
       }
       vct.push_back( c2 );
@@ -131,7 +131,7 @@ namespace LoKi {
     // ==========================================================================
     double PolarizationAngle::operator()( const HepMC3::ConstGenParticlePtr & p ) const {
       if ( 0 == p ) {
-        Error( "HepMC3::GenParticlePtr points to NULL" );
+        Error( "HepMC3::GenParticlePtr points to NULL" ).ignore();
         return 1.0; //                                 RETURN
       }
       //
@@ -140,11 +140,11 @@ namespace LoKi {
       StatusCode sc = getComponents12( p, vct );
 
       if ( sc.isFailure() ) {
-        Error( "Unable to get proper decay components (1), return 'InvalidAngle'", sc );
+        Error( "Unable to get proper decay components (1), return 'InvalidAngle'", sc ).ignore();
         return LoKi::Constants::InvalidAngle;
       }
       if ( 2 != vct.size() ) {
-        Error( "Unable to get proper decay components (1), return 'InvalidAngle'", sc );
+        Error( "Unable to get proper decay components (1), return 'InvalidAngle'", sc ).ignore();
         return LoKi::Constants::InvalidAngle;
       }
       //
@@ -233,7 +233,7 @@ namespace LoKi {
     StatusCode SinChi::getComponents34( const HepMC3::ConstGenParticlePtr & p, Decays::IGenDecay::iTree::Collection& vct ) const {
       //
       if ( 0 == p ) {
-        Error( "LHCb::GenParticlePtr points to NULL" );
+        Error( "LHCb::GenParticlePtr points to NULL" ).ignore();
         return StatusCode::FAILURE; //                                 RETURN
       }
       //
@@ -242,14 +242,14 @@ namespace LoKi {
       //
       HepMC3::ConstGenParticlePtr c1 = m_tree3.child( p );
       if ( 0 == c1 ) {
-        Error( "Invalid third  child : '" + m_tree3.printOut() + "'" );
+        Error( "Invalid third  child : '" + m_tree3.printOut() + "'" ).ignore();
         return StatusCode::FAILURE;
       }
       vct.push_back( c1 );
       //
       HepMC3::ConstGenParticlePtr c2 = m_tree4.child( p );
       if ( 0 == c2 ) {
-        Error( "Invalid fourth child : '" + m_tree4.printOut() + "'" );
+        Error( "Invalid fourth child : '" + m_tree4.printOut() + "'" ).ignore();
         return StatusCode::FAILURE;
       }
       vct.push_back( c2 );
@@ -263,13 +263,13 @@ namespace LoKi {
       vct.clear();
       StatusCode sc1 = getComponents12( p, vct );
       if ( sc1.isFailure() ) {
-        Error( "Unable to pickup 12-components", sc1 );
+        Error( "Unable to pickup 12-components", sc1 ).ignore();
         return sc1;
       }
       //
       StatusCode sc2 = getComponents34( p, vct );
       if ( sc2.isFailure() ) {
-        Error( "Unable to pickup 34-components", sc2 );
+        Error( "Unable to pickup 34-components", sc2 ).ignore();
         return sc2;
       }
       return StatusCode::SUCCESS;
@@ -283,7 +283,7 @@ namespace LoKi {
     // ============================================================================
     double SinChi::operator()( const HepMC3::ConstGenParticlePtr & p ) const {
       if ( 0 == p ) {
-        Error( "HepMC3::GenParticlePtr points to NULL, return 'Invaild Angle'" );
+        Error( "HepMC3::GenParticlePtr points to NULL, return 'Invaild Angle'" ).ignore();
         return LoKi::Constants::InvalidAngle;
       }
       //
@@ -293,11 +293,11 @@ namespace LoKi {
       StatusCode sc = getComponents( p, daughters );
       //
       if ( sc.isFailure() ) {
-        Error( "Unable to get proper decay components (1), return 'InvalidAngle'" );
+        Error( "Unable to get proper decay components (1), return 'InvalidAngle'" ).ignore();
         return LoKi::Constants::InvalidAngle;
       }
       if ( 4 != daughters.size() ) {
-        Error( "Unable to get proper decay components (2) , return 'InvalidAngle'" );
+        Error( "Unable to get proper decay components (2) , return 'InvalidAngle'" ).ignore();
         return LoKi::Constants::InvalidAngle;
       }
       // finally evaluate the angle chi:
@@ -355,7 +355,7 @@ namespace LoKi {
     // ============================================================================
     double CosChi::operator()( const HepMC3::ConstGenParticlePtr & p ) const {
       if ( 0 == p ) {
-        Error( "HepMC3::GenParticlePtr points to NULL, return 'Invaild Angle'" );
+        Error( "HepMC3::GenParticlePtr points to NULL, return 'Invaild Angle'" ).ignore();
         return LoKi::Constants::InvalidAngle;
       }
       //
@@ -365,11 +365,11 @@ namespace LoKi {
       StatusCode sc = getComponents( p, daughters );
       //
       if ( sc.isFailure() ) {
-        Error( "Unable to get proper decay components (1), return 'InvalidAngle'" );
+        Error( "Unable to get proper decay components (1), return 'InvalidAngle'" ).ignore();
         return LoKi::Constants::InvalidAngle;
       }
       if ( 4 != daughters.size() ) {
-        Error( "Unable to get proper decay components (2) , return 'InvalidAngle'" );
+        Error( "Unable to get proper decay components (2) , return 'InvalidAngle'" ).ignore();
         return LoKi::Constants::InvalidAngle;
       }
       // finally evaluate the angle chi:
@@ -427,7 +427,7 @@ namespace LoKi {
     // ============================================================================
     double AngleChi::operator()( const HepMC3::ConstGenParticlePtr & p ) const {
       if ( 0 == p ) {
-        Error( "HepMC3::GenParticlePtr points to NULL, return 'Invaild Angle'" );
+        Error( "HepMC3::GenParticlePtr points to NULL, return 'Invaild Angle'" ).ignore();
         return LoKi::Constants::InvalidAngle;
       }
       //
@@ -437,11 +437,11 @@ namespace LoKi {
       StatusCode sc = getComponents( p, daughters );
       //
       if ( sc.isFailure() ) {
-        Error( "Unable to get proper decay components (1), return 'InvalidAngle'" );
+        Error( "Unable to get proper decay components (1), return 'InvalidAngle'" ).ignore();
         return LoKi::Constants::InvalidAngle;
       }
       if ( 4 != daughters.size() ) {
-        Error( "Unable to get proper decay components (2) , return 'InvalidAngle'" );
+        Error( "Unable to get proper decay components (2) , return 'InvalidAngle'" ).ignore();
         return LoKi::Constants::InvalidAngle;
       }
       // finally evaluate the angle chi:
@@ -499,7 +499,7 @@ namespace LoKi {
     // ============================================================================
     double CosThetaTr::operator()( const HepMC3::ConstGenParticlePtr & p ) const {
       if ( 0 == p ) {
-        Error( "HepMC3::GenParticlePtr points to NULL, return 'Invaild Angle'" );
+        Error( "HepMC3::GenParticlePtr points to NULL, return 'Invaild Angle'" ).ignore();
         return LoKi::Constants::InvalidAngle;
       }
       //
@@ -509,11 +509,11 @@ namespace LoKi {
       StatusCode sc = getComponents( p, daughters );
       //
       if ( sc.isFailure() ) {
-        Error( "Unable to get proper decay components (1), return 'InvalidAngle'" );
+        Error( "Unable to get proper decay components (1), return 'InvalidAngle'" ).ignore();
         return LoKi::Constants::InvalidAngle;
       }
       if ( 4 != daughters.size() ) {
-        Error( "Unable to get proper decay components (2) , return 'InvalidAngle'" );
+        Error( "Unable to get proper decay components (2) , return 'InvalidAngle'" ).ignore();
         return LoKi::Constants::InvalidAngle;
       }
       // finally evaluate the angle chi:
@@ -571,7 +571,7 @@ namespace LoKi {
     // ============================================================================
     double SinPhiTr::operator()( const HepMC3::ConstGenParticlePtr & p ) const {
       if ( 0 == p ) {
-        Error( "HepMC3::GenParticlePtr points to NULL, return 'Invaild Angle'" );
+        Error( "HepMC3::GenParticlePtr points to NULL, return 'Invaild Angle'" ).ignore();
         return LoKi::Constants::InvalidAngle;
       }
       //
@@ -581,11 +581,11 @@ namespace LoKi {
       StatusCode sc = getComponents( p, daughters );
       //
       if ( sc.isFailure() ) {
-        Error( "Unable to get proper decay components (1), return 'InvalidAngle'" );
+        Error( "Unable to get proper decay components (1), return 'InvalidAngle'" ).ignore();
         return LoKi::Constants::InvalidAngle;
       }
       if ( 4 != daughters.size() ) {
-        Error( "Unable to get proper decay components (2) , return 'InvalidAngle'" );
+        Error( "Unable to get proper decay components (2) , return 'InvalidAngle'" ).ignore();
         return LoKi::Constants::InvalidAngle;
       }
       // finally evaluate the angle chi:
@@ -643,7 +643,7 @@ namespace LoKi {
     // ============================================================================
     double CosPhiTr::operator()( const HepMC3::ConstGenParticlePtr & p ) const {
       if ( 0 == p ) {
-        Error( "HepMC3::GenParticlePtr points to NULL, return 'Invaild Angle'" );
+        Error( "HepMC3::GenParticlePtr points to NULL, return 'Invaild Angle'" ).ignore();
         return LoKi::Constants::InvalidAngle;
       }
       //
@@ -653,11 +653,11 @@ namespace LoKi {
       StatusCode sc = getComponents( p, daughters );
       //
       if ( sc.isFailure() ) {
-        Error( "Unable to get proper decay components (1), return 'InvalidAngle'" );
+        Error( "Unable to get proper decay components (1), return 'InvalidAngle'" ).ignore();
         return LoKi::Constants::InvalidAngle;
       }
       if ( 4 != daughters.size() ) {
-        Error( "Unable to get proper decay components (2) , return 'InvalidAngle'" );
+        Error( "Unable to get proper decay components (2) , return 'InvalidAngle'" ).ignore();
         return LoKi::Constants::InvalidAngle;
       }
       // finally evaluate the cos(phi_tr)
@@ -715,7 +715,7 @@ namespace LoKi {
     // ============================================================================
     double AnglePhiTr::operator()( const HepMC3::ConstGenParticlePtr & p ) const {
       if ( 0 == p ) {
-        Error( "HepMC3::GenParticlePtr points to NULL, return 'Invaild Angle'" );
+        Error( "HepMC3::GenParticlePtr points to NULL, return 'Invaild Angle'" ).ignore();
         return LoKi::Constants::InvalidAngle;
       }
       //
@@ -725,11 +725,11 @@ namespace LoKi {
       StatusCode sc = getComponents( p, daughters );
       //
       if ( sc.isFailure() ) {
-        Error( "Unable to get proper decay components (1), return 'InvalidAngle'" );
+        Error( "Unable to get proper decay components (1), return 'InvalidAngle'" ).ignore();
         return LoKi::Constants::InvalidAngle;
       }
       if ( 4 != daughters.size() ) {
-        Error( "Unable to get proper decay components (2) , return 'InvalidAngle'" );
+        Error( "Unable to get proper decay components (2) , return 'InvalidAngle'" ).ignore();
         return LoKi::Constants::InvalidAngle;
       }
       // finally evaluate the phi_tr
diff --git a/Gen/LoKiGen/src/GenParticles3.cpp b/Gen/LoKiGen/src/GenParticles3.cpp
index 9e6d8a623..54bf673fe 100644
--- a/Gen/LoKiGen/src/GenParticles3.cpp
+++ b/Gen/LoKiGen/src/GenParticles3.cpp
@@ -82,7 +82,7 @@ namespace LoKi {
     double Count::operator()( const HepMC3::ConstGenParticlePtr & p ) const {
       //
       if ( !p ) {
-        Error( "HepMC3::GenParticlePtr points to NULL, return -1000 " );
+        Error( "HepMC3::GenParticlePtr points to NULL, return -1000 " ).ignore();
         return -1000;
       }
       // This should now automatically select the correct vertex
@@ -126,7 +126,7 @@ namespace LoKi {
     bool Has::operator()( const HepMC3::ConstGenParticlePtr & p ) const {
       //
       if ( !p ) {
-        Error( "HepMC3::GenParticlePtr points to NULL, return false" );
+        Error( "HepMC3::GenParticlePtr points to NULL, return false" ).ignore();
         return false;
       }
       return has_parts( p->production_vertex(), m_range, m_cut ); // RETURN
diff --git a/Gen/LoKiGen/src/GenParticles4.cpp b/Gen/LoKiGen/src/GenParticles4.cpp
index 5e97a6629..0ce4ad312 100644
--- a/Gen/LoKiGen/src/GenParticles4.cpp
+++ b/Gen/LoKiGen/src/GenParticles4.cpp
@@ -140,7 +140,7 @@ namespace LoKi {
     // ============================================================================
     LoKi::LorentzVector FourMomentum::momentum( const HepMC3::ConstGenParticlePtr & p ) const {
       if ( UNLIKELY( !p ) ) {
-        Error( "HepMC3::ConstGenParticlePtr & points to NULL, return empty 4-momentum" );
+        Error( "HepMC3::ConstGenParticlePtr & points to NULL, return empty 4-momentum" ).ignore();
         return LoKi::LorentzVector();
       }
       //
@@ -151,7 +151,7 @@ namespace LoKi {
       for ( auto ii = m_children.begin(); m_children.end() != ii; ++ii ) {
         HepMC3::ConstGenParticlePtr c = ii->child( p );
         if ( !c ) {
-          Error( "daughter HepMC3::ConstGenParticlePtr & points to NULL, skip it" );
+          Error( "daughter HepMC3::ConstGenParticlePtr & points to NULL, skip it" ).ignore();
           continue;
         }
         result += LoKi::LorentzVector( c->momentum() );
@@ -216,7 +216,7 @@ namespace LoKi {
     double Mass::operator()( const HepMC3::ConstGenParticlePtr & p ) const {
       //
       if ( UNLIKELY( !p ) ) {
-        Error( "HepMC3::ConstGenParticlePtr & points to NULL, return Invalid Mass" );
+        Error( "HepMC3::ConstGenParticlePtr & points to NULL, return Invalid Mass" ).ignore();
         return LoKi::Constants::InvalidMass;
       }
       //
@@ -238,7 +238,7 @@ namespace LoKi {
     double Energy::operator()( const HepMC3::ConstGenParticlePtr & p ) const {
       //
       if ( UNLIKELY( !p ) ) {
-        Error( "HepMC3::ConstGenParticlePtr & points to NULL, return Invalid Energy" );
+        Error( "HepMC3::ConstGenParticlePtr & points to NULL, return Invalid Energy" ).ignore();
         return LoKi::Constants::InvalidEnergy;
       }
       //
@@ -259,7 +259,7 @@ namespace LoKi {
     double Momentum::operator()( const HepMC3::ConstGenParticlePtr & p ) const {
       //
       if ( UNLIKELY( !p ) ) {
-        Error( "HepMC3::ConstGenParticlePtr & points to NULL, return Invalid Momentum" );
+        Error( "HepMC3::ConstGenParticlePtr & points to NULL, return Invalid Momentum" ).ignore();
         return LoKi::Constants::InvalidMomentum;
       }
       //
@@ -280,7 +280,7 @@ namespace LoKi {
     double MomentumX::operator()( const HepMC3::ConstGenParticlePtr & p ) const {
       //
       if ( UNLIKELY( !p ) ) {
-        Error( "HepMC3::ConstGenParticlePtr & points to NULL, return Invalid Momentum" );
+        Error( "HepMC3::ConstGenParticlePtr & points to NULL, return Invalid Momentum" ).ignore();
         return LoKi::Constants::InvalidMomentum;
       }
       //
@@ -301,7 +301,7 @@ namespace LoKi {
     double MomentumY::operator()( const HepMC3::ConstGenParticlePtr & p ) const {
       //
       if ( UNLIKELY( !p ) ) {
-        Error( "HepMC3::ConstGenParticlePtr & points to NULL, return Invalid Momentum" );
+        Error( "HepMC3::ConstGenParticlePtr & points to NULL, return Invalid Momentum" ).ignore();
         return LoKi::Constants::InvalidMomentum;
       }
       //
@@ -322,7 +322,7 @@ namespace LoKi {
     double MomentumZ::operator()( const HepMC3::ConstGenParticlePtr & p ) const {
       //
       if ( UNLIKELY( !p ) ) {
-        Error( "HepMC3::ConstGenParticlePtr & points to NULL, return Invalid Momentum" );
+        Error( "HepMC3::ConstGenParticlePtr & points to NULL, return Invalid Momentum" ).ignore();
         return LoKi::Constants::InvalidMomentum;
       }
       //
@@ -343,7 +343,7 @@ namespace LoKi {
     double TransverseMomentum::operator()( const HepMC3::ConstGenParticlePtr & p ) const {
       //
       if ( UNLIKELY( !p ) ) {
-        Error( "HepMC3::ConstGenParticlePtr & points to NULL, return Invalid Momentum" );
+        Error( "HepMC3::ConstGenParticlePtr & points to NULL, return Invalid Momentum" ).ignore();
         return LoKi::Constants::InvalidMomentum;
       }
       //
@@ -364,7 +364,7 @@ namespace LoKi {
     double PseudoRapidity::operator()( const HepMC3::ConstGenParticlePtr & p ) const {
       //
       if ( UNLIKELY( !p ) ) {
-        Error( "HepMC3::ConstGenParticlePtr & points to NULL, return NegativeInfinity" );
+        Error( "HepMC3::ConstGenParticlePtr & points to NULL, return NegativeInfinity" ).ignore();
         return LoKi::Constants::NegativeInfinity;
       }
       //
@@ -385,7 +385,7 @@ namespace LoKi {
     double Rapidity::operator()( const HepMC3::ConstGenParticlePtr & p ) const {
       //
       if ( UNLIKELY( !p ) ) {
-        Error( "HepMC3::ConstGenParticlePtr & points to NULL, return NegativeInfinity" );
+        Error( "HepMC3::ConstGenParticlePtr & points to NULL, return NegativeInfinity" ).ignore();
         return LoKi::Constants::NegativeInfinity;
       }
       //
@@ -407,7 +407,7 @@ namespace LoKi {
     double Rapidity0::operator()( const HepMC3::ConstGenParticlePtr & p ) const {
       //
       if ( UNLIKELY( !p ) ) {
-        Error( "HepMC3::ConstGenParticlePtr & points to NULL, return NegativeInfinity" );
+        Error( "HepMC3::ConstGenParticlePtr & points to NULL, return NegativeInfinity" ).ignore();
         return LoKi::Constants::NegativeInfinity;
       }
       //
@@ -429,7 +429,7 @@ namespace LoKi {
     double Phi::operator()( const HepMC3::ConstGenParticlePtr & p ) const {
       //
       if ( UNLIKELY( !p ) ) {
-        Error( "HepMC3::ConstGenParticlePtr & points to NULL, return -100 " );
+        Error( "HepMC3::ConstGenParticlePtr & points to NULL, return -100 " ).ignore();
         return -100;
       }
       //
@@ -452,7 +452,7 @@ namespace LoKi {
     double Theta::operator()( const HepMC3::ConstGenParticlePtr & p ) const {
       //
       if ( 0 == p ) {
-        Error( "HepMC3::ConstGenParticlePtr & points to NULL, return -100 " );
+        Error( "HepMC3::ConstGenParticlePtr & points to NULL, return -100 " ).ignore();
         return -100;
       }
       //
@@ -473,7 +473,7 @@ namespace LoKi {
     // ============================================================================
     double Beta::beta( const HepMC3::ConstGenParticlePtr & p ) const {
       if ( 0 == p ) {
-        Error( "HepMC3::ConstGenParticlePtr & points to NULL, return -1 " );
+        Error( "HepMC3::ConstGenParticlePtr & points to NULL, return -1 " ).ignore();
         return -1;
       }
       //
@@ -485,7 +485,7 @@ namespace LoKi {
     // ============================================================================
     double Beta::gamma( const HepMC3::ConstGenParticlePtr & p ) const {
       if ( 0 == p ) {
-        Error( "HepMC3::ConstGenParticlePtr & points to NULL, return -1 " );
+        Error( "HepMC3::ConstGenParticlePtr & points to NULL, return -1 " ).ignore();
         return -1;
       }
       //
@@ -499,7 +499,7 @@ namespace LoKi {
       if ( UNLIKELY( s_equal( m, 0 ) ) ) {
         //
         //
-        Error( "Light-like particle, return +infinity" );
+        Error( "Light-like particle, return +infinity" ).ignore();
         return LoKi::Constants::PositiveInfinity;
       }
       //
@@ -511,7 +511,7 @@ namespace LoKi {
     // ============================================================================
     double Beta::betagamma( const HepMC3::ConstGenParticlePtr & p ) const {
       if ( UNLIKELY( !p ) ) {
-        Error( "HepMC3::ConstGenParticlePtr & points to NULL, return -1 " );
+        Error( "HepMC3::ConstGenParticlePtr & points to NULL, return -1 " ).ignore();
         return -1;
       }
       //
@@ -522,7 +522,7 @@ namespace LoKi {
       const double m = lv.M();
       if ( s_equal( m, 0 ) ) {
         //
-        Error( "Light-like particle, return +infinity" );
+        Error( "Light-like particle, return +infinity" ).ignore();
         return LoKi::Constants::PositiveInfinity;
       }
       //
@@ -593,7 +593,7 @@ namespace LoKi {
     // ============================================================================
     double DeltaPhi::operator()( const HepMC3::ConstGenParticlePtr & p ) const {
       if ( 0 == p ) {
-        Error( "HepMC3::ConstGenParticlePtr & points to NULL, return 'InvalidAngle'" );
+        Error( "HepMC3::ConstGenParticlePtr & points to NULL, return 'InvalidAngle'" ).ignore();
         return LoKi::Constants::InvalidAngle;
       }
       return dphi( p );
@@ -632,7 +632,7 @@ namespace LoKi {
     // ============================================================================
     double DeltaEta::operator()( const HepMC3::ConstGenParticlePtr & p ) const {
       if ( UNLIKELY( !p ) ) {
-        Error( "HepMC3::ConstGenParticlePtr & points to NULL, return 'InvalidAngle'" );
+        Error( "HepMC3::ConstGenParticlePtr & points to NULL, return 'InvalidAngle'" ).ignore();
         return LoKi::Constants::InvalidAngle;
       }
       return deta( p );
@@ -668,7 +668,7 @@ namespace LoKi {
     // ============================================================================
     double DeltaR2::operator()( const HepMC3::ConstGenParticlePtr & p ) const {
       if ( 0 == p ) {
-        Error( "HepMC3::ConstGenParticlePtr & points to NULL, return 'InvalidDustance'" );
+        Error( "HepMC3::ConstGenParticlePtr & points to NULL, return 'InvalidDustance'" ).ignore();
         return LoKi::Constants::InvalidDistance;
       }
       //
diff --git a/Gen/LoKiGen/src/GenParticles5.cpp b/Gen/LoKiGen/src/GenParticles5.cpp
index 071846369..ede37cb2b 100644
--- a/Gen/LoKiGen/src/GenParticles5.cpp
+++ b/Gen/LoKiGen/src/GenParticles5.cpp
@@ -59,14 +59,14 @@ namespace LoKi {
     double Flight::operator()( const HepMC3::ConstGenParticlePtr & p ) const {
       //
       if ( !p ) {
-        Error( "HepMC3::GenParticlePtr points to NULL, return -1*km " );
+        Error( "HepMC3::GenParticlePtr points to NULL, return -1*km " ).ignore();
         return -1 * Gaudi::Units::km;
       }
       // end vertex
       HepMC3::ConstGenVertexPtr ev = p->end_vertex();
       //
       if ( !ev ) {
-        Error( "HepMC3::GenParticle::end_vertex points to NULL, return +1*km " );
+        Error( "HepMC3::GenParticle::end_vertex points to NULL, return +1*km " ).ignore();
         return Gaudi::Units::km;
       }
       //
@@ -75,13 +75,13 @@ namespace LoKi {
         //
         const HepMC3::GenEvent* evt = p->parent_event();
         if ( !evt ) {
-          Error( "HepMC3::GenParticle::parent_event points to NULL, return -1*km " );
+          Error( "HepMC3::GenParticle::parent_event points to NULL, return -1*km " ).ignore();
           return -1 * Gaudi::Units::km;
         }
         //
         v0 = evt->attribute<HepMC3::VertexAttribute>( Gaussino::HepMC::Attributes::SignalProcessVertex )->value();
         if ( !v0 ) {
-          Error( "HepMC3::GenEvent::signal_process_vertex points to NULL, return -1*km " );
+          Error( "HepMC3::GenEvent::signal_process_vertex points to NULL, return -1*km " ).ignore();
           return -1 * Gaudi::Units::km;
         }
         //
@@ -89,7 +89,7 @@ namespace LoKi {
         //
         v0 = p->production_vertex();
         if ( !v0 ) {
-          Error( "HepMC3::GenParticle::production_vertex points to NULL, return -1*km " );
+          Error( "HepMC3::GenParticle::production_vertex points to NULL, return -1*km " ).ignore();
           return -1 * Gaudi::Units::km;
         }
         //
diff --git a/Gen/LoKiGen/src/GenVertices.cpp b/Gen/LoKiGen/src/GenVertices.cpp
index 6d78220b9..3d63716f9 100644
--- a/Gen/LoKiGen/src/GenVertices.cpp
+++ b/Gen/LoKiGen/src/GenVertices.cpp
@@ -48,7 +48,7 @@ LoKi::GenVertices::BarCode* LoKi::GenVertices::BarCode::clone() const {
 // ============================================================================
 double LoKi::GenVertices::BarCode::operator()( const HepMC3::ConstGenVertexPtr & v ) const {
   if ( UNLIKELY( !v ) ) {
-    Error( "HepMC3::GenVertexPtr points to NULL; return 0" );
+    Error( "HepMC3::GenVertexPtr points to NULL; return 0" ).ignore();
     return 0;
   }
   return v->id();
@@ -66,7 +66,7 @@ LoKi::GenVertices::PositionX* LoKi::GenVertices::PositionX::clone() const { retu
 // ============================================================================
 double LoKi::GenVertices::PositionX::operator()( const HepMC3::ConstGenVertexPtr & v ) const {
   if ( UNLIKELY( !v ) ) {
-    Error( "HepMC3::GenVertexPtr points to NULL; return 'InvalidDistance'" );
+    Error( "HepMC3::GenVertexPtr points to NULL; return 'InvalidDistance'" ).ignore();
     return LoKi::Constants::InvalidDistance;
   }
   return v->position().x();
@@ -84,7 +84,7 @@ LoKi::GenVertices::PositionY* LoKi::GenVertices::PositionY::clone() const { retu
 // ============================================================================
 double LoKi::GenVertices::PositionY::operator()( const HepMC3::ConstGenVertexPtr & v ) const {
   if ( UNLIKELY( !v ) ) {
-    Error( "HepMC3::GenVertexPtr points to NULL; return 'InvalidDistance'" );
+    Error( "HepMC3::GenVertexPtr points to NULL; return 'InvalidDistance'" ).ignore();
     return LoKi::Constants::InvalidDistance;
   }
   return v->position().y();
@@ -102,7 +102,7 @@ LoKi::GenVertices::PositionZ* LoKi::GenVertices::PositionZ::clone() const { retu
 // ============================================================================
 double LoKi::GenVertices::PositionZ::operator()( const HepMC3::ConstGenVertexPtr & v ) const {
   if ( UNLIKELY( !v ) ) {
-    Error( "HepMC3::GenVertexPtr points to NULL; return 'InvalidDistance'" );
+    Error( "HepMC3::GenVertexPtr points to NULL; return 'InvalidDistance'" ).ignore();
     return LoKi::Constants::InvalidDistance;
   }
   return v->position().z();
@@ -120,7 +120,7 @@ LoKi::GenVertices::PositionT* LoKi::GenVertices::PositionT::clone() const { retu
 // ============================================================================
 double LoKi::GenVertices::PositionT::operator()( const HepMC3::ConstGenVertexPtr & v ) const {
   if ( UNLIKELY( !v ) ) {
-    Error( "HepMC3::GenVertexPtr points to NULL; return 'InvalidTime'" );
+    Error( "HepMC3::GenVertexPtr points to NULL; return 'InvalidTime'" ).ignore();
     return LoKi::Constants::InvalidTime;
   }
   return v->position().t();
@@ -139,7 +139,7 @@ LoKi::GenVertices::Rho* LoKi::GenVertices::Rho::clone() const { return new Rho(
 // ============================================================================
 double LoKi::GenVertices::Rho::operator()( const HepMC3::ConstGenVertexPtr & v ) const {
   if ( UNLIKELY( !v ) ) {
-    Error( "HepMC3::GenVertexPtr points to NULL; return 'InvalidDistance'" );
+    Error( "HepMC3::GenVertexPtr points to NULL; return 'InvalidDistance'" ).ignore();
     return LoKi::Constants::InvalidDistance;
   }
   return v->position().perp();
@@ -248,7 +248,7 @@ LoKi::GenVertices::SumIF* LoKi::GenVertices::SumIF::clone() const { return new S
 // ============================================================================
 double LoKi::GenVertices::SumIF::operator()( const HepMC3::ConstGenVertexPtr & v ) const {
   if ( UNLIKELY( !v ) ) {
-    Error( "HepMC3::GenVertexPtr poitns to NULL, return 0 " );
+    Error( "HepMC3::GenVertexPtr poitns to NULL, return 0 " ).ignore();
     return 0;
   }
   auto particles = m_range(v);
@@ -256,7 +256,7 @@ double LoKi::GenVertices::SumIF::operator()( const HepMC3::ConstGenVertexPtr & v
   return std::accumulate( std::begin(particles), std::end(particles), 0.,
                           [&]( double r, HepMC3::ConstGenParticlePtr p ) {
                             if ( UNLIKELY( !p ) ) {
-                              Warning( "HepMC3::GenParticlePtr points to 0; skip it" );
+                              Warning( "HepMC3::GenParticlePtr points to 0; skip it" ).ignore();
                             } else if ( m_cut( p ) ) {
                               r += m_fun( p );
                             }
diff --git a/Gen/LoKiGen/src/PrintHepMCDecay.cpp b/Gen/LoKiGen/src/PrintHepMCDecay.cpp
index a3180bbb1..1d6062626 100644
--- a/Gen/LoKiGen/src/PrintHepMCDecay.cpp
+++ b/Gen/LoKiGen/src/PrintHepMCDecay.cpp
@@ -93,7 +93,7 @@ std::ostream& LoKi::PrintHepMC::printDecay( const HepMC3::ConstGenParticlePtr &
                                             const LoKi::GenTypes::GCuts& cut, const int level,
                                             const std::string& blank ) {
   if ( !particle ) {
-    LoKi::Report::Warning( "LoKi::printDecay, invalid particle" );
+    LoKi::Report::Warning( "LoKi::printDecay, invalid particle" ).ignore();
     return stream << " <NULL> "; // RETURN
   }
   //
@@ -116,7 +116,7 @@ std::ostream& LoKi::PrintHepMC::printDecay( const HepMC3::ConstGenParticlePtr &
   //      osc1 != 0 , osc2 != 0
   //      invalid case
   if ( osc1 && osc2 ) {
-    LoKi::Report::Error( "LoKi::printDecay, invalid oscillation pattern" );
+    LoKi::Report::Error( "LoKi::printDecay, invalid oscillation pattern" ).ignore();
     return stream << " <INVALID OSCILLATION PATTERN> "; // RETURN
   }
   HepMC3::ConstGenParticlePtr self   = particle;
-- 
GitLab


From 90c2ed3ca7e10c144ed8a7a613d4937e35b926c8 Mon Sep 17 00:00:00 2001
From: Dominik Muller <dominik.muller@cern.ch>
Date: Fri, 27 Mar 2020 15:21:43 +0100
Subject: [PATCH 47/90] Added missing header to GenericGenCutToolWithDecay

---
 Gen/GenCuts/src_future/GenericGenCutToolWithDecay.cpp | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/Gen/GenCuts/src_future/GenericGenCutToolWithDecay.cpp b/Gen/GenCuts/src_future/GenericGenCutToolWithDecay.cpp
index af2f8ddde..e78515f86 100644
--- a/Gen/GenCuts/src_future/GenericGenCutToolWithDecay.cpp
+++ b/Gen/GenCuts/src_future/GenericGenCutToolWithDecay.cpp
@@ -40,6 +40,8 @@
 #include "HepMC3/GenVertex.h"
 #include "HepMC3/Relatives.h"
 #include "NewRnd/RndGlobal.h"
+#include "HepMCUser/VertexAttribute.h"
+#include "Defaults/HepMCAttributes.h"
 //=============================================================================
 namespace LoKi 
 {
-- 
GitLab


From 14a5e16590890a5a515f8b7b39dc19379f87fc5e Mon Sep 17 00:00:00 2001
From: Dominik Muller <dominik.muller@cern.ch>
Date: Thu, 4 Jun 2020 15:07:52 +0200
Subject: [PATCH 48/90] Set Gaussino to use particle properties from git

---
 Sim/Gauss/python/Gauss/Configuration.py | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/Sim/Gauss/python/Gauss/Configuration.py b/Sim/Gauss/python/Gauss/Configuration.py
index c0b8d103f..4b9858017 100755
--- a/Sim/Gauss/python/Gauss/Configuration.py
+++ b/Sim/Gauss/python/Gauss/Configuration.py
@@ -225,6 +225,8 @@ class Gauss(LHCbConfigurableUser):
         self.setOtherProps(LHCbApp(), [
             "EvtMax", "EnableHive", "ThreadPoolSize", "DataType"])
 
+        Gaussino().ParticleTable = 'git:///param/ParticleTable.txt'
+
         # Propagate beam settings for compatibility with existing option files
         from Gaussino.Generation import GenPhase
         self.setOtherProps(GenPhase(), [
-- 
GitLab


From 713cbbfdfc346586cfc5c8aa642dd638a3195cef Mon Sep 17 00:00:00 2001
From: Dominik Muller <dominik.muller@cern.ch>
Date: Fri, 5 Jun 2020 14:40:08 +0200
Subject: [PATCH 49/90] Always set ConvertEDM flag in Gaussino

---
 Sim/Gauss/python/Gauss/Configuration.py | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Sim/Gauss/python/Gauss/Configuration.py b/Sim/Gauss/python/Gauss/Configuration.py
index 4b9858017..61c14206f 100755
--- a/Sim/Gauss/python/Gauss/Configuration.py
+++ b/Sim/Gauss/python/Gauss/Configuration.py
@@ -226,6 +226,7 @@ class Gauss(LHCbConfigurableUser):
             "EvtMax", "EnableHive", "ThreadPoolSize", "DataType"])
 
         Gaussino().ParticleTable = 'git:///param/ParticleTable.txt'
+        Gaussino().ConvertEDM = True
 
         # Propagate beam settings for compatibility with existing option files
         from Gaussino.Generation import GenPhase
-- 
GitLab


From 8fbee54bd1d37e6bbc589a46ad65c5d4578b976e Mon Sep 17 00:00:00 2001
From: Dominik Muller <dominik.muller@cern.ch>
Date: Fri, 3 Jul 2020 16:36:15 +0200
Subject: [PATCH 50/90] Use relatives wrapper in LoKiGen everywhere to avoid
 thread-safety issues

---
 Gen/LoKiGen/CMakeLists.txt          |  2 +-
 Gen/LoKiGen/LoKi/GenAlgs.h          | 15 ++++++++-------
 Gen/LoKiGen/LoKi/GenAlgsDicts.h     | 14 +++++++-------
 Gen/LoKiGen/LoKi/GenChild.h         |  5 +++--
 Gen/LoKiGen/LoKi/GenExtract.h       |  3 ++-
 Gen/LoKiGen/LoKi/GenExtractDicts.h  |  4 ++--
 Gen/LoKiGen/LoKi/GenParticles.h     | 11 ++++++-----
 Gen/LoKiGen/src/GenExtractDicts.cpp |  1 +
 Gen/LoKiGen/src/GenParticles.cpp    |  4 ++--
 9 files changed, 32 insertions(+), 27 deletions(-)

diff --git a/Gen/LoKiGen/CMakeLists.txt b/Gen/LoKiGen/CMakeLists.txt
index 9b77bbe1f..749b0ce12 100644
--- a/Gen/LoKiGen/CMakeLists.txt
+++ b/Gen/LoKiGen/CMakeLists.txt
@@ -17,7 +17,7 @@ find_package(Graphviz)
 gaudi_depends_on_subdirs(Phys/LoKiCore
                          Phys/LoKiNumbers
                          Gen/Generators
-                         HepMCUtils)
+                         HepMCUser)
 
 include_directories(SYSTEM ${Boost_INCLUDE_DIRS} ${ROOT_INCLUDE_DIRS})
 
diff --git a/Gen/LoKiGen/LoKi/GenAlgs.h b/Gen/LoKiGen/LoKi/GenAlgs.h
index aa4b41125..f79fd3fa8 100644
--- a/Gen/LoKiGen/LoKi/GenAlgs.h
+++ b/Gen/LoKiGen/LoKi/GenAlgs.h
@@ -27,6 +27,7 @@
 #include "HepMC3/GenParticle.h"
 #include "HepMC3/GenVertex.h"
 #include "HepMC3/Relatives.h"
+#include "HepMCUtils/Relatives.h"
 /** @file
  *
  *  This file is a part of LoKi project -
@@ -114,7 +115,7 @@ namespace LoKi {
     template <class PREDICATE>
     inline size_t count_if( const HepMC3::ConstGenParticlePtr & particle, const PREDICATE& cut ) {
       size_t result = 0;
-      if ( 0 != particle ) { result = LoKi::GenAlgs::count_if( particle->end_vertex(), cut, HepMC3::Relatives::DESCENDANTS ); }
+      if ( 0 != particle ) { result = LoKi::GenAlgs::count_if( particle->end_vertex(), cut, HepMCUtils::WrapperRelatives::DESCENDANTS ); }
       if ( cut( particle ) ) { ++result; }
       // check the particle itself
       return result;
@@ -212,7 +213,7 @@ namespace LoKi {
      */
     template <class PREDICATE>
     inline bool found( const HepMC3::ConstGenParticlePtr & particle, const PREDICATE& cut ) {
-      return cut( particle ) || ( particle && LoKi::GenAlgs::found( particle->end_vertex(), cut, HepMC3::Relatives::DESCENDANTS ) );
+      return cut( particle ) || ( particle && LoKi::GenAlgs::found( particle->end_vertex(), cut, HepMCUtils::WrapperRelatives::DESCENDANTS ) );
     }
     // =====================================================================
     template <class PREDICATE>
@@ -377,7 +378,7 @@ namespace LoKi {
                               RESULT result, OPERATION binop ) {
       if ( particle ) {
         result =
-            LoKi::GenAlgs::accumulate( particle->end_vertex(), functor, predicate, result, HepMC3::Relatives::DESCENDANTS, binop );
+            LoKi::GenAlgs::accumulate( particle->end_vertex(), functor, predicate, result, HepMCUtils::WrapperRelatives::DESCENDANTS, binop );
       }
       if ( predicate( particle ) ) { result = binop( result, functor( particle ) ); }
       return result;
@@ -432,7 +433,7 @@ namespace LoKi {
       // (1) traverse the tree if possible
       if ( particle ) {
         // check all end-vertices :
-        minval = LoKi::GenAlgs::min_value( particle->end_vertex(), fun, cut, HepMC3::Relatives::DESCENDANTS, minval ); // RECURSION!
+        minval = LoKi::GenAlgs::min_value( particle->end_vertex(), fun, cut, HepMCUtils::WrapperRelatives::DESCENDANTS, minval ); // RECURSION!
       }
       // (2) check itself
       if ( cut( particle ) ) { minval = std::min( minval, fun( particle ) ); }
@@ -481,7 +482,7 @@ namespace LoKi {
       // (1) traverse the tree if possible
       if ( particle ) {
         // check for endvertices
-        maxval = LoKi::GenAlgs::max_value( particle->end_vertex(), fun, cut, HepMC3::Relatives::DESCENDANTS, maxval ); // RECURSION!
+        maxval = LoKi::GenAlgs::max_value( particle->end_vertex(), fun, cut, HepMCUtils::WrapperRelatives::DESCENDANTS, maxval ); // RECURSION!
       }
       // (2) check itself
       return cut( particle ) ? std::max( maxval, fun( particle ) ) : maxval;
@@ -568,7 +569,7 @@ namespace LoKi {
                                                   const PREDICATE& cut ) {
       if ( !particle ) { return nullptr; } // RETURN
       const HepMC3::ConstGenParticlePtr & tmp =
-          LoKi::GenAlgs::min_element( particle->end_vertex(), fun, cut, HepMC3::Relatives::DESCENDANTS);
+          LoKi::GenAlgs::min_element( particle->end_vertex(), fun, cut, HepMCUtils::WrapperRelatives::DESCENDANTS);
       if ( !tmp && cut( particle ) ) { return particle; } // RETURN
       if ( !tmp ) { return nullptr; }                     // RETURN
       return fun( tmp ) < fun( particle ) ? tmp : particle;
@@ -622,7 +623,7 @@ namespace LoKi {
     inline const HepMC3::ConstGenParticlePtr max_element( const HepMC3::ConstGenParticlePtr & particle, const FUNCTION& fun,
                                                   const PREDICATE& cut ) {
       if ( 0 == particle ) { return 0; } // RETURN
-      auto tmp = LoKi::GenAlgs::max_element( particle->end_vertex(), fun, cut, HepMC3::Relatives::DESCENDANTS );
+      auto tmp = LoKi::GenAlgs::max_element( particle->end_vertex(), fun, cut, HepMCUtils::WrapperRelatives::DESCENDANTS );
       if ( 0 == tmp && cut( particle ) ) { return particle; } // RETURN
       if ( 0 == tmp ) { return 0; }                           // RETURN
       return fun( tmp ) < fun( particle ) ? tmp : particle;
diff --git a/Gen/LoKiGen/LoKi/GenAlgsDicts.h b/Gen/LoKiGen/LoKi/GenAlgsDicts.h
index 6d57e76a2..e0be1d8f4 100644
--- a/Gen/LoKiGen/LoKi/GenAlgsDicts.h
+++ b/Gen/LoKiGen/LoKi/GenAlgsDicts.h
@@ -34,7 +34,7 @@ namespace LoKi {
       // ======================================================================
       /// count the particles in the tree
       std::size_t count_if( const HepMC3::ConstGenVertexPtr & vertex, const LoKi::GenTypes::GCuts& cuts,
-                            const HepMC3::Relatives & range = HepMC3::Relatives::DESCENDANTS);
+                            const HepMC3::Relatives & range = HepMCUtils::WrapperRelatives::DESCENDANTS);
       // ======================================================================
       /// check the presence in the event
       bool found( const HepMC3::GenEvent* event, const LoKi::GenTypes::GCuts& cuts );
@@ -44,7 +44,7 @@ namespace LoKi {
       // ======================================================================
       /// check the presence in the tree
       bool found( const HepMC3::ConstGenVertexPtr & vertex, const LoKi::GenTypes::GCuts& cuts,
-                  const HepMC3::Relatives & range = HepMC3::Relatives::DESCENDANTS);
+                  const HepMC3::Relatives & range = HepMCUtils::WrapperRelatives::DESCENDANTS);
       // ======================================================================
       /// accumulate through the addition
       double accumulate( const HepMC3::GenEvent* event, const LoKi::GenTypes::GFunc& fun,
@@ -52,7 +52,7 @@ namespace LoKi {
       // ======================================================================
       /// accumulate through the addition
       double accumulate( const HepMC3::ConstGenVertexPtr & vertex, const LoKi::GenTypes::GFunc& fun,
-                         const LoKi::GenTypes::GCuts& cut, const HepMC3::Relatives & range = HepMC3::Relatives::DESCENDANTS,
+                         const LoKi::GenTypes::GCuts& cut, const HepMC3::Relatives & range = HepMCUtils::WrapperRelatives::DESCENDANTS,
                          double res = 0.0 );
       // ======================================================================
       /// accumulate through the addition
@@ -69,7 +69,7 @@ namespace LoKi {
       // ======================================================================
       /// find minimal value over the tree:
       double min_value( const HepMC3::ConstGenVertexPtr & veretx, const LoKi::GenTypes::GFunc& fun,
-                        const LoKi::GenTypes::GCuts& cut, const HepMC3::Relatives & range = HepMC3::Relatives::DESCENDANTS,
+                        const LoKi::GenTypes::GCuts& cut, const HepMC3::Relatives & range = HepMCUtils::WrapperRelatives::DESCENDANTS,
                         double res = LoKi::Constants::PositiveInfinity );
       // ======================================================================
       /// find maximum value over the event
@@ -82,7 +82,7 @@ namespace LoKi {
       // ======================================================================
       /// find maximum value over the tree
       double max_value( const HepMC3::ConstGenVertexPtr & vertex, const LoKi::GenTypes::GFunc& fun,
-                        const LoKi::GenTypes::GCuts& cut, const HepMC3::Relatives & range = HepMC3::Relatives::DESCENDANTS,
+                        const LoKi::GenTypes::GCuts& cut, const HepMC3::Relatives & range = HepMCUtils::WrapperRelatives::DESCENDANTS,
                         double res = LoKi::Constants::NegativeInfinity );
       // ======================================================================
       /// find the minimum element through the event
@@ -95,7 +95,7 @@ namespace LoKi {
       /// find the minimum element through the tree
       HepMC3::ConstGenParticlePtr min_element( const HepMC3::ConstGenVertexPtr & veretx, const LoKi::GenTypes::GFunc& fun,
                                              const LoKi::GenTypes::GCuts& cut,
-                                             const HepMC3::Relatives &         range = HepMC3::Relatives::DESCENDANTS );
+                                             const HepMC3::Relatives &         range = HepMCUtils::WrapperRelatives::DESCENDANTS );
       // ======================================================================
       /// find the maximal element through the event
       HepMC3::ConstGenParticlePtr max_element( const HepMC3::GenEvent* event, const LoKi::GenTypes::GFunc& fun,
@@ -108,7 +108,7 @@ namespace LoKi {
       /// find the minimum element through the tree
       HepMC3::ConstGenParticlePtr max_element( const HepMC3::ConstGenVertexPtr & veretx, const LoKi::GenTypes::GFunc& fun,
                                              const LoKi::GenTypes::GCuts& cut,
-                                             const HepMC3::Relatives &         range = HepMC3::Relatives::DESCENDANTS );
+                                             const HepMC3::Relatives &         range = HepMCUtils::WrapperRelatives::DESCENDANTS );
       // ======================================================================
     } // namespace GenAlgs
   }   // namespace Dicts
diff --git a/Gen/LoKiGen/LoKi/GenChild.h b/Gen/LoKiGen/LoKi/GenChild.h
index d0c945e3e..7815f1962 100644
--- a/Gen/LoKiGen/LoKi/GenChild.h
+++ b/Gen/LoKiGen/LoKi/GenChild.h
@@ -25,6 +25,7 @@
 #include "HepMC3/GenParticle.h"
 #include "HepMC3/GenVertex.h"
 #include "HepMC3/Relatives.h"
+#include "HepMCUtils/Relatives.h"
 #ifdef __INTEL_COMPILER
 #  pragma warning( pop )
 #endif
@@ -272,7 +273,7 @@ namespace LoKi {
      *  @date   2007-05-26
      */
     inline std::vector<HepMC3::ConstGenParticlePtr> ancestors( const HepMC3::ConstGenVertexPtr & vertex ) {
-      return particles( vertex, HepMC3::Relatives::ANCESTORS);
+      return particles( vertex, HepMCUtils::WrapperRelatives::ANCESTORS);
     }
     // ========================================================================
     /** get all "ancestors" particles form the givel particlle
@@ -286,7 +287,7 @@ namespace LoKi {
      *  @date   2007-05-26
      */
     inline std::vector<HepMC3::ConstGenParticlePtr> descendants( const HepMC3::ConstGenVertexPtr & vertex ) {
-      return particles( vertex, HepMC3::Relatives::DESCENDANTS);
+      return particles( vertex, HepMCUtils::WrapperRelatives::DESCENDANTS);
     }
     // ========================================================================
     /** get all "descendant" particles form the given particle
diff --git a/Gen/LoKiGen/LoKi/GenExtract.h b/Gen/LoKiGen/LoKi/GenExtract.h
index 4cd47f03d..c5a914b18 100644
--- a/Gen/LoKiGen/LoKi/GenExtract.h
+++ b/Gen/LoKiGen/LoKi/GenExtract.h
@@ -24,6 +24,7 @@
 #include "HepMC3/GenParticle.h"
 #include "HepMC3/GenVertex.h"
 #include "HepMC3/Relatives.h"
+#include "HepMCUtils/Relatives.h"
 #include "LoKi/GenTypes.h"
 // ============================================================================
 #include <algorithm>
@@ -159,7 +160,7 @@ namespace LoKi {
     template <class OUTPUT, class PREDICATE>
     inline OUTPUT getGenParticles( const HepMC3::ConstGenParticlePtr & particle, OUTPUT output, const PREDICATE& predicate ) {
       if ( particle ) {
-        output = genParticles( particle->end_vertex(), HepMC3::Relatives::DESCENDANTS, output, predicate ); // RECURSION
+        output = genParticles( particle->end_vertex(), HepMCUtils::WrapperRelatives::DESCENDANTS, output, predicate ); // RECURSION
       }
       /// check the particle
       if ( predicate( particle ) ) {
diff --git a/Gen/LoKiGen/LoKi/GenExtractDicts.h b/Gen/LoKiGen/LoKi/GenExtractDicts.h
index 7c14a30ca..dc40a2538 100644
--- a/Gen/LoKiGen/LoKi/GenExtractDicts.h
+++ b/Gen/LoKiGen/LoKi/GenExtractDicts.h
@@ -29,11 +29,11 @@ namespace LoKi {
     /// extract the particles from the vertex
     std::vector<HepMC3::ConstGenParticlePtr> genParticles( const HepMC3::ConstGenVertexPtr &      veretx,
                                                          const LoKi::GenTypes::GCuts& cuts,
-                                                         const HepMC3::Relatives & range = HepMC3::Relatives::DESCENDANTS);
+                                                         const HepMC3::Relatives & range = HepMCUtils::WrapperRelatives::DESCENDANTS);
     // ======================================================================
     /// extract the particles from the vertex
     std::vector<HepMC3::ConstGenParticlePtr> genParticles( const HepMC3::ConstGenVertexPtr & veretx,
-                                                         const HepMC3::Relatives &    range = HepMC3::Relatives::DESCENDANTS);
+                                                         const HepMC3::Relatives &    range = HepMCUtils::WrapperRelatives::DESCENDANTS);
     // ======================================================================
     /// extract the particles from the particle
     std::vector<HepMC3::ConstGenParticlePtr> genParticles( const HepMC3::ConstGenParticlePtr &    particle,
diff --git a/Gen/LoKiGen/LoKi/GenParticles.h b/Gen/LoKiGen/LoKi/GenParticles.h
index 40f8703c3..c89d7593b 100644
--- a/Gen/LoKiGen/LoKi/GenParticles.h
+++ b/Gen/LoKiGen/LoKi/GenParticles.h
@@ -36,6 +36,7 @@
 #include "HepMC3/GenVertex.h"
 #include "HepMC3/GenEvent.h"
 #include "HepMC3/Relatives.h"
+#include "HepMCUtils/Relatives.h"
 // ============================================================================
 /** @file
  *
@@ -802,7 +803,7 @@ namespace LoKi {
        *  @param range  "iterator range", see const HepMC3::Relatives &
        *  @see const HepMC3::Relatives &
        */
-      NInTree( const LoKi::GenTypes::GCuts& cut, const HepMC3::Relatives & range = HepMC3::Relatives::DESCENDANTS );
+      NInTree( const LoKi::GenTypes::GCuts& cut, const HepMC3::Relatives & range = HepMCUtils::WrapperRelatives::DESCENDANTS );
       // Same as above but access range via index as in HepMC2
       NInTree( const LoKi::GenTypes::GCuts& cut, int idx );
       /// MANDATORY: clone function ("virtual constructor")
@@ -857,7 +858,7 @@ namespace LoKi {
        *  @see const HepMC3::Relatives &
        */
       MaxTree( const LoKi::GenTypes::GFunc& fun, const LoKi::GenTypes::GCuts& cut,
-          const HepMC3::Relatives & range = HepMC3::Relatives::DESCENDANTS);
+          const HepMC3::Relatives & range = HepMCUtils::WrapperRelatives::DESCENDANTS);
       MaxTree( const LoKi::GenTypes::GFunc& fun, const LoKi::GenTypes::GCuts& cut,
           int idx);
       /// MANDATORY: clone function ("virtual constructor")
@@ -900,7 +901,7 @@ namespace LoKi {
        *  @see const HepMC3::Relatives &
        */
       MinTree( const LoKi::GenTypes::GFunc& fun, const LoKi::GenTypes::GCuts& cut,
-               const HepMC3::Relatives & range = HepMC3::Relatives::DESCENDANTS);
+               const HepMC3::Relatives & range = HepMCUtils::WrapperRelatives::DESCENDANTS);
       MinTree( const LoKi::GenTypes::GFunc& fun, const LoKi::GenTypes::GCuts& cut,
                int idx);
       /// MANDATORY: clone function ("virtual constructor")
@@ -939,7 +940,7 @@ namespace LoKi {
        *  @see const HepMC3::Relatives &
        */
       SumTree( const LoKi::GenTypes::GFunc& fun, const LoKi::GenTypes::GCuts& cut,
-               const HepMC3::Relatives & range = HepMC3::Relatives::DESCENDANTS);
+               const HepMC3::Relatives & range = HepMCUtils::WrapperRelatives::DESCENDANTS);
       SumTree( const LoKi::GenTypes::GFunc& fun, const LoKi::GenTypes::GCuts& cut,
                int idx);
 
@@ -979,7 +980,7 @@ namespace LoKi {
        *  @see const HepMC3::Relatives &
        */
       MultTree( const LoKi::GenTypes::GFunc& fun, const LoKi::GenTypes::GCuts& cut,
-                const HepMC3::Relatives & range = HepMC3::Relatives::DESCENDANTS);
+                const HepMC3::Relatives & range = HepMCUtils::WrapperRelatives::DESCENDANTS);
       MultTree( const LoKi::GenTypes::GFunc& fun, const LoKi::GenTypes::GCuts& cut,
                 int idx);
       /// MANDATORY: clone function ("virtual constructor")
diff --git a/Gen/LoKiGen/src/GenExtractDicts.cpp b/Gen/LoKiGen/src/GenExtractDicts.cpp
index 269156be6..c34021fc5 100644
--- a/Gen/LoKiGen/src/GenExtractDicts.cpp
+++ b/Gen/LoKiGen/src/GenExtractDicts.cpp
@@ -20,6 +20,7 @@
 #include "HepMC3/GenEvent.h"
 #include "HepMC3/GenParticle.h"
 #include "HepMC3/GenVertex.h"
+#include "HepMCUtils/Relatives.h"
 #ifdef __INTEL_COMPILER
 #  pragma warning( pop )
 #endif
diff --git a/Gen/LoKiGen/src/GenParticles.cpp b/Gen/LoKiGen/src/GenParticles.cpp
index 409c5c54e..cfbdffcb9 100644
--- a/Gen/LoKiGen/src/GenParticles.cpp
+++ b/Gen/LoKiGen/src/GenParticles.cpp
@@ -326,7 +326,7 @@ namespace LoKi {
           continue;
         }
         // explict loop over all descendants
-        auto particles = HepMC3::Relatives::DESCENDANTS(vertex);
+        auto particles = HepMCUtils::WrapperRelatives::DESCENDANTS(vertex);
         auto begin = std::begin(particles);
         auto end   = std::end(particles);
         if ( std::find( begin, end, p ) != end ) { return true; } // RETURN
@@ -359,7 +359,7 @@ namespace LoKi {
       auto vertex = p->end_vertex();
       if ( 0 == vertex ) { return false; } // RETURN
       // explict loop over all descendants
-      auto particles = HepMC3::Relatives::DESCENDANTS(vertex);
+      auto particles = HepMCUtils::WrapperRelatives::DESCENDANTS(vertex);
       for ( auto dp : particles ) {
         if ( m_particle == ( dp ) ) { return true; }
       } // RETURN
-- 
GitLab


From f897ed7f7cc7123d45e714b05377cf49394a4232 Mon Sep 17 00:00:00 2001
From: Dominik Muller <dominik.muller@cern.ch>
Date: Fri, 3 Jul 2020 16:38:57 +0200
Subject: [PATCH 51/90] Added VP monitoring and updated VP/Velo monitoring
 histogram ranges

---
 VP/.gaudi_project_ignore           |   0
 VP/VPMoniSim/src/VPGaussMoni.cpp   | 258 +++++++++++++++++------------
 VP/VPMoniSim/src/VPGaussMoni.h     |  47 ------
 Velo/VeloGauss/src/VeloGaussMoni.h |   4 -
 4 files changed, 152 insertions(+), 157 deletions(-)
 delete mode 100644 VP/.gaudi_project_ignore
 delete mode 100644 VP/VPMoniSim/src/VPGaussMoni.h

diff --git a/VP/.gaudi_project_ignore b/VP/.gaudi_project_ignore
deleted file mode 100644
index e69de29bb..000000000
diff --git a/VP/VPMoniSim/src/VPGaussMoni.cpp b/VP/VPMoniSim/src/VPGaussMoni.cpp
index 09e7d19f2..1982f9e9a 100644
--- a/VP/VPMoniSim/src/VPGaussMoni.cpp
+++ b/VP/VPMoniSim/src/VPGaussMoni.cpp
@@ -1,12 +1,72 @@
 // Gaudi
+#include "GaudiAlg/Consumer.h"
 #include "GaudiAlg/Tuples.h"
 #include "GaudiKernel/Vector4DTypes.h"
 
 // LHCb
 #include "Event/MCParticle.h"
 
-// Local
-#include "VPGaussMoni.h"
+// Gaudi
+#include "GaudiAlg/GaudiTupleAlg.h"
+// LHCb
+#include "Event/MCHit.h"
+
+// from AIDA
+#include "AIDA/IHistogram1D.h"
+#include "AIDA/IHistogram2D.h"
+
+/** @class VPGaussMoni VPGaussMoni.h
+ *  Algorithm run in Gauss for monitoring VP MCHits.
+ *
+ *  @author Victor Coco based on VeloGaussMoni
+ *  @date   2009-06-05
+ */
+
+class VPGaussMoni : public Gaudi::Functional::Consumer<
+                        void(const LHCb::MCHits&),
+                        Gaudi::Functional::Traits::BaseClass_t<GaudiHistoAlg>> {
+  // public GaudiTupleAlg {
+ public:
+  /// Standard constructor
+  VPGaussMoni(const std::string& name, ISvcLocator* pSvcLocator)
+      : Consumer(name, pSvcLocator,
+                 {KeyValue{"VeloMCHits", LHCb::MCHitLocation::VP}}){};
+
+  virtual ~VPGaussMoni() = default;  ///< Destructor
+  StatusCode initialize() override;  ///< Algorithm initialization
+  StatusCode finalize() override;    ///< Algorithm finalization
+  void operator()(const LHCb::MCHits&) const override;
+
+ private:
+  Gaudi::Property<bool> m_printInfo{this, "PrintInfo", false};
+  Gaudi::Property<bool> m_detailedMonitor{this, "DetailedMonitor", true};
+
+  /// Create monitoring plots
+  void monitor(const LHCb::MCHits&) const;
+  void bookHistograms();
+
+  mutable std::atomic_ulong m_nMCH{0};
+  mutable std::atomic_ulong m_nMCH2{0};
+  mutable std::atomic_uint m_nEvent{0};
+
+  mutable std::mutex m_lazy_lock;
+
+  AIDA::IHistogram1D* m_hist_nMCHits{nullptr};
+  AIDA::IHistogram1D* m_hist_eDepSi{nullptr};
+  AIDA::IHistogram1D* m_hist_TOF{nullptr};
+  AIDA::IHistogram1D* m_hist_dist{nullptr};
+
+  AIDA::IHistogram2D* m_hist_entryZX{nullptr};
+  AIDA::IHistogram2D* m_hist_entryXY{nullptr};
+  AIDA::IHistogram2D* m_hist_exitZX{nullptr};
+  AIDA::IHistogram2D* m_hist_exitXY{nullptr};
+
+  AIDA::IHistogram2D* m_hist_vertexXY{nullptr};
+  AIDA::IHistogram2D* m_hist_vertexZX{nullptr};
+  AIDA::IHistogram2D* m_hist_vertexZY{nullptr};
+
+  AIDA::IHistogram1D* m_hist_eMCPart{nullptr};
+};
 
 //-----------------------------------------------------------------------------
 // Implementation file for class : VPGaussMoni
@@ -14,29 +74,7 @@
 // 2009-06-05 : Victor Coco, based on VeloGaussMoni
 //-----------------------------------------------------------------------------
 
-DECLARE_COMPONENT( VPGaussMoni )
-
-//=============================================================================
-// Standard constructor, initializes variables
-//=============================================================================
-VPGaussMoni::VPGaussMoni(const std::string& name,
-                         ISvcLocator* pSvcLocator) :
-    GaudiTupleAlg(name, pSvcLocator),
-    m_hits(),
-    m_nMCH(0.),
-    m_nMCH2(0.),
-    m_nEvent(0) {
-
-  declareProperty("PrintInfo", m_printInfo = false);
-  declareProperty("DetailedMonitor", m_detailedMonitor = true);
-  declareProperty("HitLocation", m_hitsLocation = LHCb::MCHitLocation::VP);
-
-}
-
-//=============================================================================
-// Destructor
-//=============================================================================
-VPGaussMoni::~VPGaussMoni() {}
+DECLARE_COMPONENT(VPGaussMoni)
 
 //=============================================================================
 // Initialization
@@ -45,39 +83,32 @@ StatusCode VPGaussMoni::initialize() {
   StatusCode sc = GaudiAlgorithm::initialize();
   if (sc.isFailure()) return sc;
   setHistoTopDir("VP/");
+  bookHistograms();
   return StatusCode::SUCCESS;
 }
 
 //=============================================================================
 // Main execution
 //=============================================================================
-StatusCode VPGaussMoni::execute() {
-
+void VPGaussMoni::operator()(const LHCb::MCHits& hits) const {
   ++m_nEvent;
+  std::lock_guard<std::mutex> guard_lock(m_lazy_lock);
   // Get data.
-  m_hits = getIfExists<LHCb::MCHits>(m_hitsLocation);
-  if (!m_hits) {
-    error() << "No MCHits at " << m_hitsLocation << endmsg;
-  } else {
-    if (m_printInfo) {
-      info() << "--------------------------------------------------" << endmsg;
-      info() << " ==> Found " << m_hits->size() << " VP MCHits" << endmsg;
-      info() << "--------------------------------------------------" << endmsg;
-    }
-    monitor();
+  if (m_printInfo) {
+    info() << "--------------------------------------------------" << endmsg;
+    info() << " ==> Found " << hits.size() << " VP MCHits" << endmsg;
+    info() << "--------------------------------------------------" << endmsg;
   }
-  return StatusCode::SUCCESS;
-
+  monitor(hits);
 }
 
 //=============================================================================
 //  Finalize
 //=============================================================================
 StatusCode VPGaussMoni::finalize() {
-
-  m_nMCH /= m_nEvent;
-  m_nMCH2 /= m_nEvent;
-  const double err = sqrt((m_nMCH2 - (m_nMCH * m_nMCH)) / m_nEvent);
+  double ave_nMCH = (double)m_nMCH / m_nEvent;
+  double ave_nMCH2 = (double)m_nMCH2 / m_nEvent;
+  double err = sqrt((ave_nMCH2 - (ave_nMCH * ave_nMCH)) / m_nEvent);
 
   info() << "------------------------------------------------------" << endmsg;
   info() << "                - VPGaussMoni table -                 " << endmsg;
@@ -94,91 +125,106 @@ StatusCode VPGaussMoni::finalize() {
 //=============================================================================
 // Create monitoring plots
 //=============================================================================
-void VPGaussMoni::monitor() {
-
-  const double size = m_hits->size();
+void VPGaussMoni::monitor(const LHCb::MCHits& hits) const {
+  const double size = hits.size();
   m_nMCH += size;
   m_nMCH2 += size * size;
 
-  plot(size, "nMCHits", 
-       "Number of hits in VP per event",
-       0., 3000., 100);
+  m_hist_nMCHits->fill(size);
   if (!m_detailedMonitor) return;
   // Loop over all MCHits in the container.
-  LHCb::MCHits::iterator it;
-  for (it = m_hits->begin(); it != m_hits->end(); ++it) {
+  for (auto& hit : hits) {
     if (m_printInfo) {
       info() << " ==> Test MCHit:\n"
-             << " sensor: " << ((*it)->sensDetID())
-             << "\nentry: x= " << ((*it)->entry()).x()/Gaudi::Units::mm << " mm"
-             << "\nentry: y= " << ((*it)->entry()).y()/Gaudi::Units::mm << " mm"
-             << "\nentry: z= " << ((*it)->entry()).z()/Gaudi::Units::mm << " mm"
-             << "\nexit: x= " << ((*it)->exit()).x()/Gaudi::Units::mm << " mm"
-             << "\nexit: y= " << ((*it)->exit()).y()/Gaudi::Units::mm << " mm"
-             << "\nexit: z= " << ((*it)->exit()).z()/Gaudi::Units::mm << " mm"
-             << "energy: " << ((*it)->energy())/Gaudi::Units::eV << " eV"
-             << "TOF: " << ((*it)->time())/Gaudi::Units::ns << " ns"
-             << endmsg;
+             << " sensor: " << (hit->sensDetID())
+             << "\nentry: x= " << (hit->entry()).x() / Gaudi::Units::mm << " mm"
+             << "\nentry: y= " << (hit->entry()).y() / Gaudi::Units::mm << " mm"
+             << "\nentry: z= " << (hit->entry()).z() / Gaudi::Units::mm << " mm"
+             << "\nexit: x= " << (hit->exit()).x() / Gaudi::Units::mm << " mm"
+             << "\nexit: y= " << (hit->exit()).y() / Gaudi::Units::mm << " mm"
+             << "\nexit: z= " << (hit->exit()).z() / Gaudi::Units::mm << " mm"
+             << "energy: " << (hit->energy()) / Gaudi::Units::eV << " eV"
+             << "TOF: " << (hit->time()) / Gaudi::Units::ns << " ns" << endmsg;
     }
-    plot((*it)->energy() / Gaudi::Units::eV, "eDepSi",
-         "Energy deposited in Si [eV]",
-         0., 300000., 100);
-    double x = (*it)->entry().x() / Gaudi::Units::cm;
-    double y = (*it)->entry().y() / Gaudi::Units::cm;
-    double z = (*it)->entry().z() / Gaudi::Units::cm;
-    plot2D(z, x, "entryZX",
-           "Particle entry point in Si [cm] - ZX plane",
-           -30., 80., -5., 5., 1100, 50);
-    plot2D(x, y, "entryXY",
-           "Particle entry point in Si [cm] - XY plane",
-           -5., 5., -5., 5., 500, 500);
-    x = (*it)->exit().x() / Gaudi::Units::cm;
-    y = (*it)->exit().y() / Gaudi::Units::cm;
-    z = (*it)->exit().z() / Gaudi::Units::cm;
-    plot2D(z, x, "exitZX",
-           "Particle exit point in Si [cm] - ZX plane",
-           -30., 80., -5., 5., 1100, 50);
-    plot2D(x, y, "exitXY",
-           "Particle exit point in Si [cm] - XY plane",
-           -5., 5., -5., 5., 500, 500);
-    plot((*it)->time() / Gaudi::Units::ns, "TOF",
-         "Time Of Flight [ns]", 
-         0., 50., 100);
+    m_hist_eDepSi->fill(hit->energy() / Gaudi::Units::eV);
+    double x = hit->entry().x() / Gaudi::Units::cm;
+    double y = hit->entry().y() / Gaudi::Units::cm;
+    double z = hit->entry().z() / Gaudi::Units::cm;
+    m_hist_entryXY->fill(x, y);
+    m_hist_entryZX->fill(z, x);
+
+    x = hit->exit().x() / Gaudi::Units::cm;
+    y = hit->exit().y() / Gaudi::Units::cm;
+    z = hit->exit().z() / Gaudi::Units::cm;
+
+    m_hist_exitZX->fill(z, x);
+    m_hist_exitXY->fill(x, y);
+    m_hist_TOF->fill(hit->time() / Gaudi::Units::ns);
     // Get access to the MCParticle which made the hit, and write out 4-mom
-    const LHCb::MCParticle* particle = (*it)->mcParticle();
+    const LHCb::MCParticle* particle = hit->mcParticle();
     if (!particle) continue;
     Gaudi::LorentzVector fMom = particle->momentum();
-    plot(fMom.e() /Gaudi::Units::GeV, "eMCPart",
-         "Particle energy [GeV]",
-         0., 50., 100);       
+    m_hist_eMCPart->fill(fMom.e() / Gaudi::Units::GeV);
     // Get the production vertex position
     const LHCb::MCVertex* vert = particle->originVertex();
     x = vert->position().x() / Gaudi::Units::cm;
     y = vert->position().y() / Gaudi::Units::cm;
     z = vert->position().z() / Gaudi::Units::cm;
-    plot2D(x, y, "MCVertexPosXY",
-           "Position of production MC Vertex of MCParticles giving hits - XY [cm]",
-           -5., 5., -5., 5., 500, 500);      
-    plot2D(z, x, "MCVertexPosZX",
-           "Position of production MC Vertex of MCParticles giving hits - ZX [cm]",
-           -30., 80., -5., 5., 500, 500); 
-    plot2D(z, y, "MCVertexPosZY",
-           "Position of production MC Vertex of MCParticles giving hits - ZY [cm]",
-           -30., 80., -5., 5., 500, 500);
-    
+    m_hist_vertexXY->fill(x, y);
+    m_hist_vertexZX->fill(z, x);
+    m_hist_vertexZY->fill(z, y);
+
     // Get the distance traversed through silicon for each particle
-    double xdist2 = pow((*it)->entry().x()-(*it)->exit().x(),2);
-    double ydist2 = pow((*it)->entry().y()-(*it)->exit().y(),2);
-    double zdist2 = pow((*it)->entry().z()-(*it)->exit().z(),2);
-    double dist = sqrt(xdist2+ydist2+zdist2) / Gaudi::Units::cm;
-    plot(dist, "SiDist", "Distance traversed through silicon by particle [cm]", 0., .05, 500.);
+    double xdist2 = pow(hit->entry().x() - hit->exit().x(), 2);
+    double ydist2 = pow(hit->entry().y() - hit->exit().y(), 2);
+    double zdist2 = pow(hit->entry().z() - hit->exit().z(), 2);
+    double dist = sqrt(xdist2 + ydist2 + zdist2) / Gaudi::Units::cm;
+    plot(dist, "SiDist", "Distance traversed through silicon by particle [cm]",
+         0., .05, 500.);
 
     if (m_printInfo) {
       info() << " ==> MCHit - MCParticle: "
              << "\np_x = " << fMom.px() / Gaudi::Units::GeV
              << "\np_y = " << fMom.py() / Gaudi::Units::GeV
-             << "\np_z = " << fMom.pz() / Gaudi::Units::GeV
-             << endmsg;
+             << "\np_z = " << fMom.pz() / Gaudi::Units::GeV << endmsg;
     }
   }
 }
+
+void VPGaussMoni::bookHistograms() {
+  m_hist_nMCHits =
+      book1D("nMCHits", "Number of hits in Velo per event", 0., 10000., 100);
+  if (!m_detailedMonitor) return;
+  m_hist_eDepSi =
+      book("eDepSi", "Energy deposited in Si [eV]", 0., 300000., 100);
+  m_hist_TOF = book("TOF", "Time Of Flight [ns]", 0., 5., 100);
+  m_hist_entryZX =
+      book2D("entryZX", "Particle entry point in Si [cm] - ZX plane", -30., 80.,
+             1100, -5., 5., 50);
+  m_hist_entryXY =
+      book2D("entryXY", "Particle entry point in Si [cm] - XY plane", -5., 5.,
+             50, -5., 5., 50);
+  m_hist_exitZX = book2D("exitZX", "Particle exit point in Si [cm] - ZX plane",
+                         -30., 80., 1100, -5., 5., 50);
+  m_hist_exitXY = book2D("exitXY", "Particle exit point in Si [cm] - XY plane",
+                         -5., 5., 50, -5., 5., 50);
+
+  m_hist_eMCPart = book("eMCPart", "Particle energy [GeV]", 0., 50., 100);
+
+  m_hist_vertexXY = book2D(
+      "MCVertexPosXY",
+      "Position of production MC Vertex of MCParticles giving hits - XY [cm]",
+      -5., 5., 500, -5., 5., 500);
+  m_hist_vertexZX = book2D(
+      "MCVertexPosZX",
+      "Position of production MC Vertex of MCParticles giving hits - ZX [cm]",
+      -5., 5., 500, -5., 5., 500);
+  m_hist_vertexZY = book2D(
+      "MCVertexPosZY",
+      "Position of production MC Vertex of MCParticles giving hits - ZY [cm]",
+      -5., 5., 500, -5., 5., 500);
+
+  m_hist_dist =
+      book1D("SiDist", "Distance traversed through silicon by particle [cm]",
+             0.015, .03, 200.);
+}
diff --git a/VP/VPMoniSim/src/VPGaussMoni.h b/VP/VPMoniSim/src/VPGaussMoni.h
deleted file mode 100644
index 62f3236c3..000000000
--- a/VP/VPMoniSim/src/VPGaussMoni.h
+++ /dev/null
@@ -1,47 +0,0 @@
-#ifndef VPGAUSSMONI_H
-#define VPGAUSSMONI_H 1
-
-// Gaudi
-#include "GaudiAlg/GaudiTupleAlg.h"
-// LHCb
-#include "Event/MCHit.h"
-
-/** @class VPGaussMoni VPGaussMoni.h
- *  Algorithm run in Gauss for monitoring VP MCHits.
- *
- *  @author Victor Coco based on VeloGaussMoni
- *  @date   2009-06-05
- */
-
-class VPGaussMoni : public GaudiTupleAlg {
-public:
-  /// Standard constructor
-  VPGaussMoni(const std::string& name, ISvcLocator* pSvcLocator);
-  virtual ~VPGaussMoni(); ///< Destructor
-
-  StatusCode initialize() override;    ///< Algorithm initialization
-  StatusCode execute() override;       ///< Algorithm execution
-  StatusCode finalize() override;      ///< Algorithm finalization
-
-private:
-
-  /// Create monitoring plots
-  void monitor();
-
-  /// TES location of VP MCHits container
-  std::string m_hitsLocation;
-  /// Container of VP MCHits
-  LHCb::MCHits* m_hits;
-  /// Flag to activate printout of each hit
-  bool m_printInfo;
-  /// Flag to activate additional set of histograms
-  bool m_detailedMonitor;
-  /// Total number of MC hits
-  double m_nMCH;
-  /// Total number of MC hits squared
-  double m_nMCH2;
-  /// Number of events
-  unsigned int m_nEvent;
-
-};
-#endif // VPGAUSSMONI_H
diff --git a/Velo/VeloGauss/src/VeloGaussMoni.h b/Velo/VeloGauss/src/VeloGaussMoni.h
index 758baf24d..ba7ed2b4c 100755
--- a/Velo/VeloGauss/src/VeloGaussMoni.h
+++ b/Velo/VeloGauss/src/VeloGaussMoni.h
@@ -59,10 +59,6 @@ private:
   mutable std::atomic_ulong m_nPUMCH{0};
   mutable std::atomic_ulong m_nPUMCH2{0};
   mutable std::atomic_uint m_nEvent{0};
-  /// Location of Velo MCHits
-  std::string m_veloMCHitsLocation ;
-  /// Location of PuVeto MCHits
-  std::string m_puVetoMCHitsLocation ;
   mutable std::mutex m_lazy_lock;
 
   AIDA::IHistogram1D* m_hist_nMCHits{nullptr};
-- 
GitLab


From b39b5a36402cdeb46c1007ca8690e919142213dd Mon Sep 17 00:00:00 2001
From: Dominik Muller <dominik.muller@cern.ch>
Date: Fri, 3 Jul 2020 16:40:32 +0200
Subject: [PATCH 52/90] Added dd4hep conversion service and basic changes to
 configuration of geometry

---
 CMakeLists.txt                                |  28 ++++
 Example/LHCbLumi/CMakeLists.txt               |   2 +-
 Gen/EvtGen/CMakeLists.txt                     |   7 +-
 Gen/GENSER/CMakeLists.txt                     |   6 +
 Sim/DD4hepCnv/CMakeLists.txt                  |  38 +++++
 Sim/DD4hepCnv/DD4hepCnv/IGaussGeo.h           |  21 +++
 Sim/DD4hepCnv/doc/release.notes               |  12 ++
 Sim/DD4hepCnv/src/component/DD4hepCnvSvc.cpp  | 132 ++++++++++++++++++
 Sim/DD4hepCnv/src/component/DD4hepCnvSvc.h    |   0
 Sim/Gauss/python/Gauss/Configuration.py       |   3 +-
 Sim/Gauss/python/Gauss/Geometry/BCM.py        |   2 +-
 Sim/Gauss/python/Gauss/Geometry/BLS.py        |   2 +-
 Sim/Gauss/python/Gauss/Geometry/BeamPipe.py   |   2 +-
 Sim/Gauss/python/Gauss/Geometry/CALO.py       |   8 +-
 .../python/Gauss/Geometry/Configuration.py    |  43 ++++--
 Sim/Gauss/python/Gauss/Geometry/FT.py         |   2 +-
 Sim/Gauss/python/Gauss/Geometry/HC.py         |   2 +-
 Sim/Gauss/python/Gauss/Geometry/IT.py         |   2 +-
 Sim/Gauss/python/Gauss/Geometry/Magnet.py     |   2 +-
 Sim/Gauss/python/Gauss/Geometry/Muon.py       |   2 +-
 Sim/Gauss/python/Gauss/Geometry/OT.py         |   2 +-
 Sim/Gauss/python/Gauss/Geometry/PuVeto.py     |   2 +-
 Sim/Gauss/python/Gauss/Geometry/RICH.py       |   8 +-
 Sim/Gauss/python/Gauss/Geometry/SL.py         |   2 +-
 Sim/Gauss/python/Gauss/Geometry/TT.py         |   2 +-
 Sim/Gauss/python/Gauss/Geometry/UT.py         |   2 +-
 Sim/Gauss/python/Gauss/Geometry/VP.py         |   8 +-
 Sim/Gauss/python/Gauss/Geometry/Velo.py       |   2 +-
 Sim/Gauss/python/Gauss/Geometry/det_base.py   |  10 ++
 Sim/GaussGeo/CMakeLists.txt                   |   5 +
 cmake/FindPhotos++.cmake                      |   5 +-
 toolchain.cmake                               |  66 +++++++++
 32 files changed, 385 insertions(+), 45 deletions(-)
 create mode 100644 Sim/DD4hepCnv/CMakeLists.txt
 create mode 100644 Sim/DD4hepCnv/DD4hepCnv/IGaussGeo.h
 create mode 100644 Sim/DD4hepCnv/doc/release.notes
 create mode 100644 Sim/DD4hepCnv/src/component/DD4hepCnvSvc.cpp
 create mode 100644 Sim/DD4hepCnv/src/component/DD4hepCnvSvc.h

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 7af042366..ab610c8fc 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -3,6 +3,17 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8.5)
 #---------------------------------------------------------------
 # Load macros and functions for Gaudi-based projects
 find_package(GaudiProject)
+
+# Set the CMP0074 policy that dictates how the packages are looked up
+# this should allow overriding the LCG versions of package XXX,
+# provided, XXX_ROOT is set
+if (POLICY CMP0074)
+  cmake_policy(SET CMP0074 NEW)
+  message(STATUS "Setting the policy CMP0074 to NEW")
+else()
+  message(STATUS "Policy CMP0074 not available: LCG packages NOT overriden by _ROOT environment variable")
+endif()
+
 set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
 #---------------------------------------------------------------
 
@@ -25,6 +36,23 @@ macro(AddHepMC3)
     link_directories(${Gaussino_DIR}/lib)
 endmacro()
 
+macro(AddDD4hepDDG4)
+    include_directories(SYSTEM ${Gaussino_DIR}/include)
+    link_directories(${Gaussino_DIR}/lib)
+
+    set(DD4hepDDG4_LIBRARIES
+          -lDDG4LCIO
+          -lDDG4Legacy  
+          -lDDG4Plugins  
+          -lDDG4Python  
+          -lDDG4  
+          -lDDPython)
+endmacro()
+
+# make sure pkg-config looks for packages on CMAKE_PREFIX_PATH and system
+set(PKG_CONFIG_USE_CMAKE_PREFIX_PATH ON)
+list(APPEND CMAKE_PREFIX_PATH /usr)
+
 # Declare project name and version
 gaudi_project(Gauss v60r0
               FORTRAN
diff --git a/Example/LHCbLumi/CMakeLists.txt b/Example/LHCbLumi/CMakeLists.txt
index 969959df4..ec6ebab4f 100644
--- a/Example/LHCbLumi/CMakeLists.txt
+++ b/Example/LHCbLumi/CMakeLists.txt
@@ -11,7 +11,7 @@ gaudi_depends_on_subdirs(GaudiAlg
 
 find_package(Boost)
 find_package(ROOT COMPONENTS Tree TreePlayer RIO REQUIRED)
-find_package(CLHEP)
+find_package(CLHEP CONFIG)
 AddHepMC3()
 include_directories(SYSTEM ${Boost_INCLUDE_DIRS} ${ROOT_INCLUDE_DIRS} ${CLHEP_INCLUDE_DIRS} ${Geant4_INCLUDE_DIRS} ${HEPMC3_INCLUDE_DIR})
 
diff --git a/Gen/EvtGen/CMakeLists.txt b/Gen/EvtGen/CMakeLists.txt
index 2fe7bc2a9..a228a4756 100644
--- a/Gen/EvtGen/CMakeLists.txt
+++ b/Gen/EvtGen/CMakeLists.txt
@@ -3,9 +3,12 @@
 ################################################################################
 gaudi_subdir(EvtGen v14r7)
 
-gaudi_depends_on_subdirs(Gen/GENSER)
+#gaudi_depends_on_subdirs(Gen/GENSER)
+gaudi_depends_on_subdirs(Gen/GENSER
+                         GaudiAlg
+                         HepMC3)
 
-find_package(CLHEP)
+find_package(CLHEP CONFIG) 
 find_package(HepMC)
 
 find_package(Pythia8)
diff --git a/Gen/GENSER/CMakeLists.txt b/Gen/GENSER/CMakeLists.txt
index bd8772f89..dc87c839f 100644
--- a/Gen/GENSER/CMakeLists.txt
+++ b/Gen/GENSER/CMakeLists.txt
@@ -2,9 +2,13 @@
 # Package: GENSER
 ################################################################################
 gaudi_subdir(GENSER v16r4)
+message(STATUS "CLHEP_INCLUDE_DIRS: ${CLHEP_INCLUDE_DIRS}")
+message(STATUS "CLHEP_LIBRARIES: ${CLHEP_LIBRARIES}")
 
 find_package(LHAPDF)
 find_package(Pythia6)
+message(STATUS "CLHEP_INCLUDE_DIRS: ${CLHEP_INCLUDE_DIRS}")
+message(STATUS "CLHEP_LIBRARIES: ${CLHEP_LIBRARIES}")
 
 message(WARNING "FIXME: the Pythia6 headers in GENSER must be installed")
 
@@ -21,5 +25,7 @@ set_property(TARGET pythia6forgauss
              APPEND PROPERTY LINK_FLAGS ${PYTHIA6_LIBRARY_DIRS}/pydata.o)
 
 gaudi_install_cmake_modules()
+message(STATUS "CLHEP_INCLUDE_DIRS: ${CLHEP_INCLUDE_DIRS}")
+message(STATUS "CLHEP_LIBRARIES: ${CLHEP_LIBRARIES}")
 #gaudi_env(SET PYTHIA8DATA ${PYTHIA8_XML})
 
diff --git a/Sim/DD4hepCnv/CMakeLists.txt b/Sim/DD4hepCnv/CMakeLists.txt
new file mode 100644
index 000000000..d4c62fa7a
--- /dev/null
+++ b/Sim/DD4hepCnv/CMakeLists.txt
@@ -0,0 +1,38 @@
+################################################################################
+# Package: DD4hepCnv
+################################################################################
+gaudi_subdir(DD4hepCnv v1r0)
+
+gaudi_depends_on_subdirs(Sim/GiGaMTFactories
+                         Sim/GiGaMTCore
+                         Sim/SimInterfaces
+                         Sim/GiGaMTGeo
+                         DD4hepDDG4Ext
+                         Sim/GiGaMTDD4hep
+                         Det/LbDD4hep)
+
+find_package(Boost)
+find_package(CLHEP)
+
+AddHepMC3()
+AddDD4hepDDG4()
+
+if(${Geant4_config_version} VERSION_LESS "10.06")
+  add_definitions(-DG4MULTITHREADED)
+  add_definitions(-DG4USE_STD11)
+endif()
+
+find_package(DD4hep REQUIRED CONFIG COMPONENTS DDCore)
+
+include_directories(SYSTEM ${Boost_INCLUDE_DIRS} ${CLHEP_INCLUDE_DIRS} ${Geant4_INCLUDE_DIRS})
+
+FindG4libs(digits_hits event geometry global graphics_reps materials
+           particles processes run tracking track)
+
+message(STATUS "DD4hepDDG4_INCLUDE_DIRS: ${DD4hepDDG4_INCLUDE_DIRS}")
+message(STATUS "DD4hepDDG4_LIBRARIES: ${DD4hepDDG4_LIBRARIES}")
+
+gaudi_add_module(DD4hepCnv
+        src/component/*.cpp
+        INCLUDE_DIRS Tools/ClhepTools GiGaMTGeo LbDD4hep DD4hep
+        LINK_LIBRARIES ${GEANT4_LIBS} DD4hep ${DD4hep_COMPONENT_LIBRARIES} ROOT GiGaMTCoreRunLib GiGaMTDD4hepLib) 
diff --git a/Sim/DD4hepCnv/DD4hepCnv/IGaussGeo.h b/Sim/DD4hepCnv/DD4hepCnv/IGaussGeo.h
new file mode 100644
index 000000000..65a9a3e64
--- /dev/null
+++ b/Sim/DD4hepCnv/DD4hepCnv/IGaussGeo.h
@@ -0,0 +1,21 @@
+#pragma once
+
+// GaudiKernel
+#include "GaudiKernel/IInterface.h"
+
+class G4VPhysicalVolume;
+
+// ============================================================================
+// Minimal geometry source interface to GaussGeo
+//
+// 2015-11-11 : Dmitry Popov
+// ============================================================================
+
+class IGaussGeo : virtual public IInterface {
+ public:
+  // Retrieve unique interface ID
+  static const InterfaceID& interfaceID();
+
+  // Retrieve the pointer to the G4 geometry tree root
+  virtual G4VPhysicalVolume* world() = 0;
+};
diff --git a/Sim/DD4hepCnv/doc/release.notes b/Sim/DD4hepCnv/doc/release.notes
new file mode 100644
index 000000000..d45972bea
--- /dev/null
+++ b/Sim/DD4hepCnv/doc/release.notes
@@ -0,0 +1,12 @@
+!-----------------------------------------------------------------------------
+! Package     : Sim/GaussGeo
+! Responsible : Gloria CORTI, Dmitry POPOV
+! Purpose     : LHCb to GEANT4 geometry convertion service
+!-----------------------------------------------------------------------------
+
+!========================= GaussGeo v1r0 2016-03-08 ==========================
+! 2016-03-08 - Dmitry Popov
+ - Initial release, providing the basic geometry conversion functionality,
+   based on GiGaCnv conversion service.
+
+!=============================================================================
diff --git a/Sim/DD4hepCnv/src/component/DD4hepCnvSvc.cpp b/Sim/DD4hepCnv/src/component/DD4hepCnvSvc.cpp
new file mode 100644
index 000000000..63e8d59d9
--- /dev/null
+++ b/Sim/DD4hepCnv/src/component/DD4hepCnvSvc.cpp
@@ -0,0 +1,132 @@
+// Gaudi includes
+#include "GaudiKernel/IToolSvc.h"
+#include "GaudiKernel/SmartDataPtr.h"
+#include "GaudiKernel/IRegistry.h"
+#include "GaudiKernel/IDataManagerSvc.h"
+#include "GaudiKernel/SmartIF.h"
+
+// GiGa
+// FIXME: Need to integrate this
+//#include "GiGaMTFactories/GiGaMTG4SensDetFactory.h"
+//#include "GiGa/IGiGaMagField.h"
+//#include "GiGa/IGiGaFieldMgr.h"
+//#include "GiGa/IGDMLReader.h"
+
+
+#include "Kernel/IPropertyConfigSvc.h"
+
+// Gaudi includes
+#include "GaudiKernel/Service.h"
+#include "GaudiKernel/IIncidentSvc.h"
+#include "GiGaMTFactories/GiGaFactoryBase.h"
+#include "Geant4/G4VSensitiveDetector.hh"
+#include "GaudiKernel/Transform3DTypes.h"
+
+#include "GiGaMTGeo/IGiGaMTGeoSvc.h"
+#include "LbDD4hep/IDD4hepSvc.h"
+
+// DD4hep
+#include "DD4hep/Detector.h"
+#include "DDG4/Geant4Converter.h"
+#include "DDG4/Geant4Mapping.h"
+#include "GiGaMTDD4hep/Utilities.h"
+
+// ============================================================================
+// Conversion service for convertion DD4hep geometry from LHCb to Geant4
+//
+// 2020-6-15 : Dominik Muller
+// ============================================================================
+
+class DD4hepCnvSvc: public extends<Service, IGiGaMTGeoSvc> {
+ public:
+   using extends::extends;
+  virtual ~DD4hepCnvSvc() = default;
+
+  // Service pure member functions
+  StatusCode initialize() override;
+  StatusCode finalize() override;
+
+  // Pointer to the root of G4 geometry tree
+  G4VPhysicalVolume* constructWorld() override;
+  void constructSDandField() override;
+
+ private:
+
+  // G4 geometry variables
+  G4VPhysicalVolume* m_world_root{nullptr};
+  dd4hep::sim::Geant4GeometryInfo* geoinfo{nullptr};
+  std::string m_world_material;
+  std::string m_world_pv_name;
+  std::string m_world_lv_name;
+
+  Gaudi::Property<bool> m_debugMaterials  {this, "DebugMaterials", false};
+  Gaudi::Property<bool> m_debugElements   {this, "DebugElements", false};
+  Gaudi::Property<bool> m_debugShapes     {this, "DebugShapes", false};
+  Gaudi::Property<bool> m_debugVolumes    {this, "DebugVolumes", false};
+  Gaudi::Property<bool> m_debugPlacements {this, "DebugPlacements", false};
+  Gaudi::Property<bool> m_debugRegions    {this, "DebugRegions", false};
+  ServiceHandle<LHCb::Det::LbDD4hep::IDD4hepSvc> m_dd4Svc{this, "DD4hepSvc", "LHCb::Det::LbDD4hep::DD4hepSvc"};
+
+  // Services accessors
+  inline ISvcLocator * svcLocator() const { return serviceLocator(); }
+
+  // Extract the object type name
+  template <class T>
+  inline const std::string objectTypeName(T object) {
+    return object ? std::string(System::typeinfoName(typeid(*object))) : std::string("'UNKNOWN_type'");
+  }
+
+  // Tabulated properties
+  template<class T>
+  StatusCode copyTableProperties(const T& src_table, G4MaterialPropertiesTable* dst_table);
+};
+// ============================================================================
+// Implementation file for class : GaussGeo
+//
+// 2015-11-11 : Dmitry Popov
+// ============================================================================
+
+DECLARE_COMPONENT( DD4hepCnvSvc )
+
+StatusCode DD4hepCnvSvc::initialize() {
+  auto sc = extends::initialize();
+  auto& g4map = dd4hep::sim::Geant4Mapping::instance();
+  dd4hep::setPrintLevel(DD4hepGaudiMessaging::Convert(msgLevel()));
+  dd4hep::DetElement world = m_dd4Svc->getDetector().world();
+  dd4hep::sim::Geant4Converter conv(dd4hep::Detector::getInstance(), DD4hepGaudiMessaging::Convert(msgLevel()));
+  conv.debugMaterials = m_debugMaterials.value();
+  conv.debugElements = m_debugElements.value();
+  conv.debugShapes = m_debugShapes.value();
+  conv.debugVolumes = m_debugVolumes.value();
+  conv.debugPlacements = m_debugPlacements.value();
+  conv.debugRegions = m_debugRegions.value();
+
+  dd4hep::sim::Geant4GeometryInfo* geoinfo = conv.create(world).detach();
+  geoinfo->printLevel = DD4hepGaudiMessaging::Convert(msgLevel());
+
+  g4map.attach(geoinfo);
+  m_world_root = geoinfo->world();
+  // Create Geant4 volume manager only if not yet available
+  g4map.volumeManager();
+
+  return sc;
+}
+
+StatusCode DD4hepCnvSvc::finalize() {
+  return extends::finalize();
+}
+
+
+//=============================================================================
+// Retrieve the pointer to G4 geometry tree root
+//=============================================================================
+G4VPhysicalVolume* DD4hepCnvSvc::constructWorld() {
+
+  if(m_world_root) return m_world_root;
+
+  return m_world_root;
+}
+
+
+void DD4hepCnvSvc::constructSDandField() {
+}
diff --git a/Sim/DD4hepCnv/src/component/DD4hepCnvSvc.h b/Sim/DD4hepCnv/src/component/DD4hepCnvSvc.h
new file mode 100644
index 000000000..e69de29bb
diff --git a/Sim/Gauss/python/Gauss/Configuration.py b/Sim/Gauss/python/Gauss/Configuration.py
index 61c14206f..52d347f66 100755
--- a/Sim/Gauss/python/Gauss/Configuration.py
+++ b/Sim/Gauss/python/Gauss/Configuration.py
@@ -218,7 +218,7 @@ class Gauss(LHCbConfigurableUser):
 
         self.setOtherProps(Gaussino(), [
             "Histograms", "DatasetName", "Phases", "SpilloverPaths", "EvtMax",
-            "EnableHive", "ThreadPoolSize", "EventSlots", 
+            "EnableHive", "ThreadPoolSize", "EventSlots",
             "ReDecay"])
 
         LHCbApp().Simulation = True
@@ -235,6 +235,7 @@ class Gauss(LHCbConfigurableUser):
             "BeamEmittance", "BeamBetaStar", "BeamLineAngles",
             "InteractionPosition", "BunchRMS", "Luminosity",
             "TotalCrossSection", "B2Momentum", "B1Particle", "B2Particle"])
+        GenPhase().GenMonitor = True
 
         # Propagates and sets up SimConf to be able to configure the
         # OutputStream during its apply_configuration
diff --git a/Sim/Gauss/python/Gauss/Geometry/BCM.py b/Sim/Gauss/python/Gauss/Geometry/BCM.py
index 2e63d1594..ce50bc779 100644
--- a/Sim/Gauss/python/Gauss/Geometry/BCM.py
+++ b/Sim/Gauss/python/Gauss/Geometry/BCM.py
@@ -7,7 +7,7 @@ class BCM(det_base):
 
     __slots__ = {}
 
-    def ApplyDetector(self, basePieces, detPieces):
+    def ApplyDetectorDetDesc(self, basePieces, detPieces):
         from Gauss.Geometry import LHCbGeo
         # Add the non-standard pieces of the BeforeMagnet region.
         region = 'BeforeMagnetRegion'
diff --git a/Sim/Gauss/python/Gauss/Geometry/BLS.py b/Sim/Gauss/python/Gauss/Geometry/BLS.py
index e5c66dd10..f46bdd564 100644
--- a/Sim/Gauss/python/Gauss/Geometry/BLS.py
+++ b/Sim/Gauss/python/Gauss/Geometry/BLS.py
@@ -8,7 +8,7 @@ class BCM(det_base):
 
     __slots__ = {}
 
-    def ApplyDetector(self, basePieces, detPieces):
+    def ApplyDetectorDetDesc(self, basePieces, detPieces):
         from Gauss.Geometry import LHCbGeo
         # Add the non-standard pieces of the BeforeMagnet region.
         region = 'BeforeMagnetRegion'
diff --git a/Sim/Gauss/python/Gauss/Geometry/BeamPipe.py b/Sim/Gauss/python/Gauss/Geometry/BeamPipe.py
index 1a9d2b04f..a80491f3e 100644
--- a/Sim/Gauss/python/Gauss/Geometry/BeamPipe.py
+++ b/Sim/Gauss/python/Gauss/Geometry/BeamPipe.py
@@ -71,7 +71,7 @@ class BeamPipe(det_base):
         super(det_base, self).__init__(*(), **kwargs)
         self.initialize()
 
-    def ApplyDetector(self, basePieces, detPieces):
+    def ApplyDetectorDetDesc(self, basePieces, detPieces):
         # This function is only executed if BeamPipe was set to Active
         self.validateBeamPipeSwitch()
 
diff --git a/Sim/Gauss/python/Gauss/Geometry/CALO.py b/Sim/Gauss/python/Gauss/Geometry/CALO.py
index 3d160e555..1567676ef 100644
--- a/Sim/Gauss/python/Gauss/Geometry/CALO.py
+++ b/Sim/Gauss/python/Gauss/Geometry/CALO.py
@@ -18,7 +18,7 @@ class SPD(det_base):
 
     __slots__ = {}
 
-    def ApplyDetector(self, basePieces, detPieces):
+    def ApplyDetectorDetDesc(self, basePieces, detPieces):
         BeamPipe.removeBeamPipeElements("calo")
         region = 'DownstreamRegion'
         detPieces[region] += ['Spd']
@@ -63,7 +63,7 @@ class PRS(det_base):
 
     __slots__ = {}
 
-    def ApplyDetector(self, basePieces, detPieces):
+    def ApplyDetectorDetDesc(self, basePieces, detPieces):
         region = 'DownstreamRegion'
         detPieces[region] += ['Prs']
 
@@ -106,7 +106,7 @@ class ECAL(det_base):
 
     __slots__ = {}
 
-    def ApplyDetector(self, basePieces, detPieces):
+    def ApplyDetectorDetDesc(self, basePieces, detPieces):
         region = 'DownstreamRegion'
         detPieces[region] += ['Ecal']
 
@@ -149,7 +149,7 @@ class HCAL(det_base):
 
     __slots__ = {}
 
-    def ApplyDetector(self, basePieces, detPieces):
+    def ApplyDetectorDetDesc(self, basePieces, detPieces):
         region = 'DownstreamRegion'
         detPieces[region] += ['Hcal']
 
diff --git a/Sim/Gauss/python/Gauss/Geometry/Configuration.py b/Sim/Gauss/python/Gauss/Geometry/Configuration.py
index a4d46fae4..a36741323 100644
--- a/Sim/Gauss/python/Gauss/Geometry/Configuration.py
+++ b/Sim/Gauss/python/Gauss/Geometry/Configuration.py
@@ -29,6 +29,8 @@ class LHCbGeo(LHCbConfigurableUser):
             "Detectors": ['PuVeto', 'Velo', 'TT', 'IT', 'OT', 'Rich1', 'Rich2',
                           'Spd', 'Prs', 'Ecal', 'Hcal', 'Muon']},
         "Debug": False,
+        "DD4hep": False,
+        "SaveGDMLFile": "",
         "SensDetMap":{},
         "ExtraGeoTools":[]
         }
@@ -73,9 +75,15 @@ class LHCbGeo(LHCbConfigurableUser):
         pass
 
     def apply(self):
-        from Configurables import GaussGeo
+
         if self.getProp('Debug'):
-            GaussGeo.OutputLevel = -10
+            from Gaudi.Configuration import DEBUG
+            if self.getProp('DD4hep'):
+                from Configurables import GaussGeo
+                GaussGeo().OutputLevel = DEBUG
+            else:
+                from Configurables import DD4hepCnvSvc
+                DD4hepCnvSvc().OutputLevel = DEBUG
 
         detPieces = {'BeforeUpstreamRegion': [],
                      'UpstreamRegion': [],
@@ -89,12 +97,6 @@ class LHCbGeo(LHCbConfigurableUser):
         checkIncompatibleDetectors()
         defineGeoBasePieces(basePieces)
 
-        gaussgeo = GaussGeo()
-
-        # Use information from SIMCOND and GeometryInfo
-        # Allows to be set to False by RichXPmt
-        gaussgeo.UseAlignment = True
-        gaussgeo.AlignAllDetectors = True
 
         from Gauss.Geometry.Helpers import getsubdetector
         detectors_geo = self.getProp("DetectorGeo")["Detectors"]
@@ -109,7 +111,7 @@ class LHCbGeo(LHCbConfigurableUser):
             getsubdetector(det).Monitor = True
 
         # BeamPipe
-        getsubdetector('BeamPipe').ApplyDetector(basePieces, detPieces)
+        # getsubdetector('BeamPipe').ApplyDetector(basePieces, detPieces)
 
         for det in detectors_geo:
             getsubdetector(det).ApplyDetector(basePieces, detPieces)
@@ -122,7 +124,7 @@ class LHCbGeo(LHCbConfigurableUser):
         for det in detectors_geo:
             getsubdetector(det).ApplyStream()
 
-        getsubdetector("Magnet").defineMagnetGeoField()
+        # getsubdetector("Magnet").defineMagnetGeoField()
 
         # FIXME: those calo option files
         # Seperate Calo opts
@@ -145,8 +147,16 @@ class LHCbGeo(LHCbConfigurableUser):
 
         # Populate the list of geometry elements
         # in the requested conversion service
-        for el in self._listOfGeoObjects_:
-            gaussgeo.GeoItemsNames.append(el)
+        if self.getProp('DD4hep') is False:
+            from Configurables import GaussGeo
+            gaussgeo = GaussGeo()
+
+            # Use information from SIMCOND and GeometryInfo
+            # Allows to be set to False by RichXPmt
+            gaussgeo.UseAlignment = True
+            gaussgeo.AlignAllDetectors = True
+            for el in self._listOfGeoObjects_:
+                gaussgeo.GeoItemsNames.append(el)
 
         self.MakeItTalkToGaussino()
 
@@ -164,7 +174,10 @@ class LHCbGeo(LHCbConfigurableUser):
         giga.DetectorConstruction = "GiGaMTDetectorConstructionFAC"
         dettool = giga.addTool(GiGaMTDetectorConstructionFAC,
                                "GiGaMTDetectorConstructionFAC")
-        dettool.GiGaMTGeoSvc = "GaussGeo"
+        if self.getProp('DD4hep') is False:
+            dettool.GiGaMTGeoSvc = "GaussGeo"
+        else:
+            dettool.GiGaMTGeoSvc = "DD4hepCnvSvc"
         dettool.SensDetVolumeMap = self.getProp('SensDetMap')
 
         dettool.AfterGeoConstructionTools = self.getProp('ExtraGeoTools')
@@ -180,6 +193,8 @@ class LHCbGeo(LHCbConfigurableUser):
         from Configurables import GiGaRegionsTool
         dettool.addTool(GiGaRegionsTool(), name="GiGaRegionsTool")
         dettool.GiGaRegionsTool.OutputLevel = 4
+        if self.getProp('SaveGDMLFile') != "":
+            dettool.Output = self.getProp('SaveGDMLFile')
         # FIXME: This is all just temporary, especially the provided xml is only
         # for Run1+2 MC
         from Configurables import RegionsDefinitionSvc
@@ -193,7 +208,7 @@ class LHCbGeo(LHCbConfigurableUser):
             print "\nkey : detPieces[key]"
             for key in detPieces.keys():
                 print "%s : %s" % (key, detPieces[key])
-            print "\nkey : detPieces[key]"
+            print "\nkey : Sorted detPieces[key]"
 
             for key in sorted(detPieces.keys()):
                 print "%s : %s" % (key, detPieces[key])
diff --git a/Sim/Gauss/python/Gauss/Geometry/FT.py b/Sim/Gauss/python/Gauss/Geometry/FT.py
index c59eb9a7f..4f0f0c2ec 100644
--- a/Sim/Gauss/python/Gauss/Geometry/FT.py
+++ b/Sim/Gauss/python/Gauss/Geometry/FT.py
@@ -8,7 +8,7 @@ class FT(det_base):
 
     __slots__ = {}
 
-    def ApplyDetector(self, basePieces, detPieces):
+    def ApplyDetectorDetDesc(self, basePieces, detPieces):
         BeamPipe.removeBeamPipeElements("t")
         region = "AfterMagnetRegion"
         if 'T' not in detPieces[region]:
diff --git a/Sim/Gauss/python/Gauss/Geometry/HC.py b/Sim/Gauss/python/Gauss/Geometry/HC.py
index ce875bc73..78b2f4f8c 100644
--- a/Sim/Gauss/python/Gauss/Geometry/HC.py
+++ b/Sim/Gauss/python/Gauss/Geometry/HC.py
@@ -9,7 +9,7 @@ class HC(det_base):
 
     __slots__ = {}
 
-    def ApplyDetector(self, basePieces, detPieces):
+    def ApplyDetectorDetDesc(self, basePieces, detPieces):
         from Gauss.Geometry import LHCbGeo
         from Configurables import LHCbApp
         year = LHCbApp().getProp("DataType")
diff --git a/Sim/Gauss/python/Gauss/Geometry/IT.py b/Sim/Gauss/python/Gauss/Geometry/IT.py
index 26bf6d8b6..b21207e50 100644
--- a/Sim/Gauss/python/Gauss/Geometry/IT.py
+++ b/Sim/Gauss/python/Gauss/Geometry/IT.py
@@ -8,7 +8,7 @@ class IT(det_base):
 
     __slots__ = {}
 
-    def ApplyDetector(self, basePieces, detPieces):
+    def ApplyDetectorDetDesc(self, basePieces, detPieces):
         BeamPipe.removeBeamPipeElements("t")
         region = "AfterMagnetRegion"
         if 'T' not in detPieces[region]:
diff --git a/Sim/Gauss/python/Gauss/Geometry/Magnet.py b/Sim/Gauss/python/Gauss/Geometry/Magnet.py
index 7be7dc264..230601130 100644
--- a/Sim/Gauss/python/Gauss/Geometry/Magnet.py
+++ b/Sim/Gauss/python/Gauss/Geometry/Magnet.py
@@ -7,7 +7,7 @@ class Magnet(det_base):
 
     __slots__ = {}
 
-    def ApplyDetector(self, basePieces, detPieces):
+    def ApplyDetectorDetDesc(self, basePieces, detPieces):
         detPieces["MagnetRegion"] = ['Magnet', 'BcmDown']
 
     def defineMagnetGeoField(self):
diff --git a/Sim/Gauss/python/Gauss/Geometry/Muon.py b/Sim/Gauss/python/Gauss/Geometry/Muon.py
index 5091ba609..188cfed93 100644
--- a/Sim/Gauss/python/Gauss/Geometry/Muon.py
+++ b/Sim/Gauss/python/Gauss/Geometry/Muon.py
@@ -7,7 +7,7 @@ class Muon(det_base):
 
     __slots__ = {}
 
-    def ApplyDetector(self, basePieces, detPieces):
+    def ApplyDetectorDetDesc(self, basePieces, detPieces):
         region = 'DownstreamRegion'
         detPieces[region] += ['Muon']
 
diff --git a/Sim/Gauss/python/Gauss/Geometry/OT.py b/Sim/Gauss/python/Gauss/Geometry/OT.py
index f35efce00..eb983fc81 100644
--- a/Sim/Gauss/python/Gauss/Geometry/OT.py
+++ b/Sim/Gauss/python/Gauss/Geometry/OT.py
@@ -8,7 +8,7 @@ class OT(det_base):
 
     __slots__ = {}
 
-    def ApplyDetector(self, basePieces, detPieces):
+    def ApplyDetectorDetDesc(self, basePieces, detPieces):
         BeamPipe.removeBeamPipeElements("t")
         region = "AfterMagnetRegion"
         if 'T' not in detPieces[region]:
diff --git a/Sim/Gauss/python/Gauss/Geometry/PuVeto.py b/Sim/Gauss/python/Gauss/Geometry/PuVeto.py
index 6842c675e..89a57e411 100644
--- a/Sim/Gauss/python/Gauss/Geometry/PuVeto.py
+++ b/Sim/Gauss/python/Gauss/Geometry/PuVeto.py
@@ -7,7 +7,7 @@ class PuVeto(det_base):
 
     __slots__ = {}
 
-    def ApplyDetector(self, basePieces, detPieces):
+    def ApplyDetectorDetDesc(self, basePieces, detPieces):
         pass
 
     def SetupExtractionImpl(self, slot=''):
diff --git a/Sim/Gauss/python/Gauss/Geometry/RICH.py b/Sim/Gauss/python/Gauss/Geometry/RICH.py
index 8beee2e76..3b602c5ee 100644
--- a/Sim/Gauss/python/Gauss/Geometry/RICH.py
+++ b/Sim/Gauss/python/Gauss/Geometry/RICH.py
@@ -8,7 +8,7 @@ class RICH1(det_base):
 
     __slots__ = {}
 
-    def ApplyDetector(self, basePieces, detPieces):
+    def ApplyDetectorDetDesc(self, basePieces, detPieces):
         BeamPipe.removeBeamPipeElements("rich1")
         detPieces['BeforeMagnetRegion'] += ['Rich1']
 
@@ -25,7 +25,7 @@ class RICH2(det_base):
 
     __slots__ = {}
 
-    def ApplyDetector(self, basePieces, detPieces):
+    def ApplyDetectorDetDesc(self, basePieces, detPieces):
         BeamPipe.removeBeamPipeElements("rich2")
         detPieces['AfterMagnetRegion'] += ['Rich2']
 
@@ -40,7 +40,7 @@ class RICH1PMT(det_base):
 
     __slots__ = {}
 
-    def ApplyDetector(self, basePieces, detPieces):
+    def ApplyDetectorDetDesc(self, basePieces, detPieces):
         BeamPipe.removeBeamPipeElements("rich1")
         detPieces['BeforeMagnetRegion'] += ['Rich1']
 
@@ -60,7 +60,7 @@ class RICH2PMT(det_base):
 
     __slots__ = {}
 
-    def ApplyDetector(self, basePieces, detPieces):
+    def ApplyDetectorDetDesc(self, basePieces, detPieces):
         BeamPipe.removeBeamPipeElements("rich2")
         detPieces['AfterMagnetRegion'] += ['Rich2']
 
diff --git a/Sim/Gauss/python/Gauss/Geometry/SL.py b/Sim/Gauss/python/Gauss/Geometry/SL.py
index 5a1b02950..6bb705ce8 100644
--- a/Sim/Gauss/python/Gauss/Geometry/SL.py
+++ b/Sim/Gauss/python/Gauss/Geometry/SL.py
@@ -6,7 +6,7 @@ from Gauss.Geometry.BeamPipe import BeamPipe
 @subdetector
 class SL(det_base):
 
-    def ApplyDetector(self, basePieces, detPieces):
+    def ApplyDetectorDetDesc(self, basePieces, detPieces):
         BeamPipe.removeBeamPipeElements("t")
         region = "AfterMagnetRegion"
         if 'T' not in detPieces[region]:
diff --git a/Sim/Gauss/python/Gauss/Geometry/TT.py b/Sim/Gauss/python/Gauss/Geometry/TT.py
index d9c955561..5a53c6d32 100644
--- a/Sim/Gauss/python/Gauss/Geometry/TT.py
+++ b/Sim/Gauss/python/Gauss/Geometry/TT.py
@@ -8,7 +8,7 @@ class TT(det_base):
 
     __slots__ = {}
 
-    def ApplyDetector(self, basePieces, detPieces):
+    def ApplyDetectorDetDesc(self, basePieces, detPieces):
         BeamPipe.removeBeamPipeElements("tt")
         if 'TT' not in detPieces['BeforeMagnetRegion']:
             detPieces['BeforeMagnetRegion'] += ['TT']
diff --git a/Sim/Gauss/python/Gauss/Geometry/UT.py b/Sim/Gauss/python/Gauss/Geometry/UT.py
index 229edd8af..f1035d05a 100644
--- a/Sim/Gauss/python/Gauss/Geometry/UT.py
+++ b/Sim/Gauss/python/Gauss/Geometry/UT.py
@@ -6,7 +6,7 @@ from Gauss.Geometry.BeamPipe import BeamPipe
 @subdetector
 class UT(det_base):
 
-    def ApplyDetector(self, basePieces, detPieces):
+    def ApplyDetectorDetDesc(self, basePieces, detPieces):
         BeamPipe.removeBeamPipeElements("ut")
         if 'UT' not in detPieces['BeforeMagnetRegion']:
             detPieces['BeforeMagnetRegion'] += ['UT']
diff --git a/Sim/Gauss/python/Gauss/Geometry/VP.py b/Sim/Gauss/python/Gauss/Geometry/VP.py
index e9689d68b..19761f5cd 100644
--- a/Sim/Gauss/python/Gauss/Geometry/VP.py
+++ b/Sim/Gauss/python/Gauss/Geometry/VP.py
@@ -8,7 +8,7 @@ class VP(det_base):
 
     __slots__ = {}
 
-    def ApplyDetector(self, basePieces, detPieces):
+    def ApplyDetectorDetDesc(self, basePieces, detPieces):
         BeamPipe.removeBeamPipeElements("velo")
         if 'BeforeMagnetRegion' in detPieces:
             detPieces['BeforeMagnetRegion'] += ['VP']
@@ -28,5 +28,7 @@ class VP(det_base):
         ApplicationMgr().TopAlg += [alg]
 
     def SetupMonitor(self, slot=''):
-        from Gaudi.Configuration import log
-        log.warning("Monitoring for VP not available yet")
+        from Configurables import VPGaussMoni
+        moni = VPGaussMoni("VPGaussMoni"+slot)
+        from Configurables import ApplicationMgr
+        ApplicationMgr().TopAlg += [moni]
diff --git a/Sim/Gauss/python/Gauss/Geometry/Velo.py b/Sim/Gauss/python/Gauss/Geometry/Velo.py
index fb153ccce..d7178c937 100644
--- a/Sim/Gauss/python/Gauss/Geometry/Velo.py
+++ b/Sim/Gauss/python/Gauss/Geometry/Velo.py
@@ -131,7 +131,7 @@ class Velo(det_base):
         go += ["/dd/Structure/LHCb/BeforeMagnetRegion/Velo/VeloRight/RFFoilRight"]  # NOQA
         go += ["/dd/Structure/LHCb/BeforeMagnetRegion/Velo/VeloLeft/RFFoilLeft"]
 
-    def ApplyDetector(self, basePieces, detPieces):
+    def ApplyDetectorDetDesc(self, basePieces, detPieces):
         VeloP = Velo.checkVeloDDDB()
         if VeloP == 1 or VeloP == 2:
             basePieces['BeforeMagnetRegion'] = []
diff --git a/Sim/Gauss/python/Gauss/Geometry/det_base.py b/Sim/Gauss/python/Gauss/Geometry/det_base.py
index d6dc291e0..54854300c 100644
--- a/Sim/Gauss/python/Gauss/Geometry/det_base.py
+++ b/Sim/Gauss/python/Gauss/Geometry/det_base.py
@@ -12,6 +12,7 @@ class det_base(LHCbConfigurableUser):
         "active": False,
         "simulate": False,
         "monitor": False,
+        "UseDD4hep": False,
         "simconf_name": 'NONE',
     }
 
@@ -59,6 +60,15 @@ class det_base(LHCbConfigurableUser):
         pass
 
     def ApplyDetector(self, basePieces, detPieces):
+        if self.getProp('UseDD4hep'):
+            return self.ApplyDetectorDD4hep(basePieces, detPieces)
+        else:
+            return self.ApplyDetectorDetDesc(basePieces, detPieces)
+
+    def ApplyDetectorDetDesc(self, basePieces, detPieces):
+        pass
+
+    def ApplyDetectorDD4hep(self, basePieces, detPieces):
         pass
 
     def ApplyStream(self):
diff --git a/Sim/GaussGeo/CMakeLists.txt b/Sim/GaussGeo/CMakeLists.txt
index 2f1c1b360..2fc8e9b52 100644
--- a/Sim/GaussGeo/CMakeLists.txt
+++ b/Sim/GaussGeo/CMakeLists.txt
@@ -6,6 +6,11 @@ gaudi_subdir(GaussGeo v1r0)
 gaudi_depends_on_subdirs(Det/DetDesc
                          Sim/GiGaMTGeo)
 
+if(${Geant4_config_version} VERSION_LESS "10.06")
+  add_definitions(-DG4MULTITHREADED)
+  add_definitions(-DG4USE_STD11)
+endif()
+
 find_package(Boost)
 find_package(CLHEP)
 include_directories(SYSTEM ${Boost_INCLUDE_DIRS} ${CLHEP_INCLUDE_DIRS} ${Geant4_INCLUDE_DIRS})
diff --git a/cmake/FindPhotos++.cmake b/cmake/FindPhotos++.cmake
index 81044ac92..088fd12ba 100644
--- a/cmake/FindPhotos++.cmake
+++ b/cmake/FindPhotos++.cmake
@@ -11,11 +11,11 @@
 
 # Enforce a minimal list if none is explicitly requested
 if(NOT PHOTOS++_FIND_COMPONENTS)
-  set(PHOTOS++_FIND_COMPONENTS Fortran CxxInterface)
+  set(PHOTOS++_FIND_COMPONENTS Photospp PhotosppHEPEVT PhotosppHepMC)
 endif()
 
 foreach(component ${PHOTOS++_FIND_COMPONENTS})
-  find_library(PHOTOS++_${component}_LIBRARY NAMES Photos${component}
+  find_library(PHOTOS++_${component}_LIBRARY NAMES ${component}
                HINTS ${PHOTOS++_ROOT_DIR}/lib
                      $ENV{PHOTOSPP_ROOT_DIR}/lib
                      ${PHOTOSPP_ROOT_DIR}/lib)
@@ -39,6 +39,7 @@ find_path(PHOTOS++_INCLUDE_DIR Photos/Photos.h
           HINTS ${PHOTOS++_ROOT_DIR}/include
                 $ENV{PHOTOSPP_ROOT_DIR}/include
                 ${PHOTOSPP_ROOT_DIR}/include)
+
 set(PHOTOS++_INCLUDE_DIRS ${PHOTOS++_INCLUDE_DIR})
 mark_as_advanced(PHOTOS++_INCLUDE_DIR)
 
diff --git a/toolchain.cmake b/toolchain.cmake
index 6ab1c3e11..2d56f7d32 100644
--- a/toolchain.cmake
+++ b/toolchain.cmake
@@ -3,6 +3,72 @@
 
 cmake_minimum_required(VERSION 3.6)
 
+if(NOT DEFINED GAUDI_OLD_STYLE_PROJECT)
+  file(STRINGS "${PROJECT_SOURCE_DIR}/CMakeLists.txt" _top_cmakelists)
+  set(GAUDI_OLD_STYLE_PROJECT NO)
+  foreach(_line IN LISTS _top_cmakelists)
+    if(_line MATCHES "^[^#]*gaudi_project")
+      set(GAUDI_OLD_STYLE_PROJECT YES)
+      break()
+    endif()
+  endforeach()
+  set(GAUDI_OLD_STYLE_PROJECT ${GAUDI_OLD_STYLE_PROJECT} CACHE BOOL "true if the top level CMakeLists file contains a call to gaudi_project")
+endif()
+
+if(NOT GAUDI_OLD_STYLE_PROJECT)
+  # for new style CMake projects, or vanilla CMake projects
+  if("$ENV{BINARY_TAG}" STREQUAL "" OR "$ENV{LCG_VERSION}" STREQUAL "")
+    message(FATAL_ERROR "The environment variables BINARY_TAG and LCG_VERSION mut be set for new style CMake projects")
+  endif()
+  find_file(LCG_TOOLCHAIN NAMES $ENV{BINARY_TAG}.cmake PATH_SUFFIXES lcg-toolchains/LCG_$ENV{LCG_VERSION})
+  if(LCG_TOOLCHAIN)
+    include(${LCG_TOOLCHAIN})
+    # after including the toolchain, set some LHCb defaults
+    find_program(CCACHE_COMMAND NAMES ccache)
+    if(CCACHE_COMMAND)
+      set(CMAKE_C_COMPILER_LAUNCHER "${CCACHE_COMMAND}" CACHE PATH "...")
+      set(CMAKE_CXX_COMPILER_LAUNCHER "${CCACHE_COMMAND}" CACHE PATH "...")
+    endif()
+    if(NOT DEFINED GAUDI_USE_INTELAMPLIFIER)
+      set(GAUDI_USE_INTELAMPLIFIER "YES" CACHE BOOL "...")
+    endif()
+    if(NOT DEFINED GAUDI_LEGACY_CMAKE_SUPPORT)
+      set(GAUDI_LEGACY_CMAKE_SUPPORT "YES" CACHE BOOL "...")
+    endif()
+    if(NOT DEFINED CMAKE_INSTALL_PREFIX OR CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
+      set(CMAKE_INSTALL_PREFIX "${PROJECT_SOURCE_DIR}/InstallArea/$ENV{BINARY_TAG}" CACHE BOOL "...")
+    endif()
+  else()
+    message(FATAL_ERROR "Cannot find LCG $ENV{LCG_VERSION} $ENV{BINARY_TAG} toolchain")
+  endif()
+else()
+
+# this check is needed because the toolchain is called when checking the
+# compiler (without the proper cache)
+if(NOT CMAKE_SOURCE_DIR MATCHES "CMakeTmp")
+
+  find_file(default_toolchain NAMES GaudiDefaultToolchain.cmake
+            HINTS ${CMAKE_SOURCE_DIR}/cmake
+                  ${CMAKE_CURRENT_LIST_DIR}/cmake)
+  if(default_toolchain)
+    include(${default_toolchain})
+    if(NOT DEFINED CMAKE_USE_CCACHE)
+      set(CMAKE_USE_CCACHE "YES" CACHE BOOL "...")
+    endif()
+  else()
+    message(FATAL_ERROR "Cannot find GaudiDefaultToolchain.cmake")
+  endif()
+
+  # FIXME: make sure we do not pick up unwanted/problematic projects from LCG
+  if(CMAKE_PREFIX_PATH)
+    # - ninja (it requires LD_LIBRARY_PATH set to run)
+    # - Gaudi (we do not want to use it from LCG)
+    # - xenv (conflicts with the version in the build environment)
+    list(FILTER CMAKE_PREFIX_PATH EXCLUDE REGEX "(LCG_|lcg/nightlies).*(ninja|Gaudi|xenv)")
+  endif()
+endif()
+endif()
+
 find_file(inherit_heptools_module InheritHEPTools.cmake)
 
 # Process the lines of LCG_generators_*.txt file to extract the
-- 
GitLab


From d223787e4e4c089a55c99b243549d9b7b9d173c7 Mon Sep 17 00:00:00 2001
From: Dominik Muller <dominik.muller@cern.ch>
Date: Thu, 9 Jul 2020 16:11:50 +0200
Subject: [PATCH 53/90] More debug output for dd4hep conversion service

---
 CMakeLists.txt                               |  2 +-
 Sim/DD4hepCnv/src/component/DD4hepCnvSvc.cpp | 15 +++++++++++++++
 2 files changed, 16 insertions(+), 1 deletion(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index ab610c8fc..4252be5f8 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -41,7 +41,7 @@ macro(AddDD4hepDDG4)
     link_directories(${Gaussino_DIR}/lib)
 
     set(DD4hepDDG4_LIBRARIES
-          -lDDG4LCIO
+          #-lDDG4LCIO
           -lDDG4Legacy  
           -lDDG4Plugins  
           -lDDG4Python  
diff --git a/Sim/DD4hepCnv/src/component/DD4hepCnvSvc.cpp b/Sim/DD4hepCnv/src/component/DD4hepCnvSvc.cpp
index 63e8d59d9..43e9b86e9 100644
--- a/Sim/DD4hepCnv/src/component/DD4hepCnvSvc.cpp
+++ b/Sim/DD4hepCnv/src/component/DD4hepCnvSvc.cpp
@@ -93,6 +93,13 @@ StatusCode DD4hepCnvSvc::initialize() {
   auto& g4map = dd4hep::sim::Geant4Mapping::instance();
   dd4hep::setPrintLevel(DD4hepGaudiMessaging::Convert(msgLevel()));
   dd4hep::DetElement world = m_dd4Svc->getDetector().world();
+  if ( msgLevel( MSG::DEBUG ) ) {
+    auto & children =world.children();
+    debug() << "Children of DD4hep world DetElement:" << endmsg;
+    for(auto & child: children){
+      debug() << " --- " << child.first  << " ::: " << child.second.name() << endmsg;
+    }
+  }
   dd4hep::sim::Geant4Converter conv(dd4hep::Detector::getInstance(), DD4hepGaudiMessaging::Convert(msgLevel()));
   conv.debugMaterials = m_debugMaterials.value();
   conv.debugElements = m_debugElements.value();
@@ -101,6 +108,7 @@ StatusCode DD4hepCnvSvc::initialize() {
   conv.debugPlacements = m_debugPlacements.value();
   conv.debugRegions = m_debugRegions.value();
 
+
   dd4hep::sim::Geant4GeometryInfo* geoinfo = conv.create(world).detach();
   geoinfo->printLevel = DD4hepGaudiMessaging::Convert(msgLevel());
 
@@ -108,6 +116,13 @@ StatusCode DD4hepCnvSvc::initialize() {
   m_world_root = geoinfo->world();
   // Create Geant4 volume manager only if not yet available
   g4map.volumeManager();
+  if (msgLevel(MSG::DEBUG)) {
+    debug() << "Placements in Geant4Mapping:" << endmsg;
+    for (auto& data : g4map.data().g4Placements) {
+      debug() << " --- " << data.first.name()
+              << " ::: " << data.second->GetName() << endmsg;
+    }
+  }
 
   return sc;
 }
-- 
GitLab


From c8ec08fe4991ee14cc77e5e040a607c49e70cf3c Mon Sep 17 00:00:00 2001
From: Dominik Muller <dominik.muller@cern.ch>
Date: Thu, 16 Jul 2020 09:46:26 +0200
Subject: [PATCH 54/90] Added missing generator version file for LCG97

---
 generators_versions_LCG97.txt | 13 +++++++++++++
 1 file changed, 13 insertions(+)
 create mode 100644 generators_versions_LCG97.txt

diff --git a/generators_versions_LCG97.txt b/generators_versions_LCG97.txt
new file mode 100644
index 000000000..9732b86f1
--- /dev/null
+++ b/generators_versions_LCG97.txt
@@ -0,0 +1,13 @@
+alpgen         2.1.4
+hijing         1.383bs.2
+powheg-box-v2  r3043.lhcb
+pythia6        429.2
+rivet          3.0.1
+tauola++       1.1.6
+thepeg         2.2.0
+crmc           1.6.0
+yoda           1.8.0
+starlight      r313
+pythia8        244
+lhapdf         6.2.3
+photos++       3.61
-- 
GitLab


From c768442afe77579e55329a582b2622637d6f7a09 Mon Sep 17 00:00:00 2001
From: Dominik Muller <dominik.muller@cern.ch>
Date: Tue, 21 Jul 2020 16:37:47 +0200
Subject: [PATCH 55/90] Support for SensDet assignment extracted from the
 DD4hep description

---
 Sim/DD4hepCnv/src/component/DD4hepCnvSvc.cpp | 128 +++++++++++++++++--
 Sim/Gauss/python/Gauss/Geometry/Helpers.py   |   2 +-
 Sim/Gauss/python/Gauss/Geometry/VP.py        |   6 +
 3 files changed, 125 insertions(+), 11 deletions(-)

diff --git a/Sim/DD4hepCnv/src/component/DD4hepCnvSvc.cpp b/Sim/DD4hepCnv/src/component/DD4hepCnvSvc.cpp
index 43e9b86e9..c3d307242 100644
--- a/Sim/DD4hepCnv/src/component/DD4hepCnvSvc.cpp
+++ b/Sim/DD4hepCnv/src/component/DD4hepCnvSvc.cpp
@@ -31,6 +31,9 @@
 #include "DDG4/Geant4Mapping.h"
 #include "GiGaMTDD4hep/Utilities.h"
 
+// Geant4
+#include "Geant4/G4SDManager.hh"
+
 // ============================================================================
 // Conversion service for convertion DD4hep geometry from LHCb to Geant4
 //
@@ -65,6 +68,7 @@ class DD4hepCnvSvc: public extends<Service, IGiGaMTGeoSvc> {
   Gaudi::Property<bool> m_debugVolumes    {this, "DebugVolumes", false};
   Gaudi::Property<bool> m_debugPlacements {this, "DebugPlacements", false};
   Gaudi::Property<bool> m_debugRegions    {this, "DebugRegions", false};
+  Gaudi::Property<std::map<std::string, std::string>> m_sensdetmappings    {this, "SensDetMappings", {}};
   ServiceHandle<LHCb::Det::LbDD4hep::IDD4hepSvc> m_dd4Svc{this, "DD4hepSvc", "LHCb::Det::LbDD4hep::DD4hepSvc"};
 
   // Services accessors
@@ -79,6 +83,17 @@ class DD4hepCnvSvc: public extends<Service, IGiGaMTGeoSvc> {
   // Tabulated properties
   template<class T>
   StatusCode copyTableProperties(const T& src_table, G4MaterialPropertiesTable* dst_table);
+
+  // Storage maps to manage assignment of sensdet factories to volumes
+  std::map<GiGaFactoryBase<G4VSensitiveDetector>*, std::set<G4LogicalVolume*>> mmap_sensdet_to_lvols;
+  std::map<std::string, GiGaFactoryBase<G4VSensitiveDetector>*> mmap_name_to_sensdetfac;
+
+  // Methods to simplify tools retrieval
+  template<class T>
+  T* getTool(const std::string& type, const std::string& name, T*& tool, const IInterface* parent = 0, bool create = true) const;
+  template<class T>
+  T* getTool(const std::string& type, T*& tool, const IInterface* parent = 0, bool create = true) const;
+  IToolSvc * m_tool_svc{nullptr};
 };
 // ============================================================================
 // Implementation file for class : GaussGeo
@@ -89,7 +104,9 @@ class DD4hepCnvSvc: public extends<Service, IGiGaMTGeoSvc> {
 DECLARE_COMPONENT( DD4hepCnvSvc )
 
 StatusCode DD4hepCnvSvc::initialize() {
-  auto sc = extends::initialize();
+
+  auto sc = svcLocator()->service("ToolSvc", m_tool_svc, true);
+  sc &= extends::initialize();
   auto& g4map = dd4hep::sim::Geant4Mapping::instance();
   dd4hep::setPrintLevel(DD4hepGaudiMessaging::Convert(msgLevel()));
   dd4hep::DetElement world = m_dd4Svc->getDetector().world();
@@ -116,14 +133,48 @@ StatusCode DD4hepCnvSvc::initialize() {
   m_world_root = geoinfo->world();
   // Create Geant4 volume manager only if not yet available
   g4map.volumeManager();
-  if (msgLevel(MSG::DEBUG)) {
-    debug() << "Placements in Geant4Mapping:" << endmsg;
-    for (auto& data : g4map.data().g4Placements) {
-      debug() << " --- " << data.first.name()
-              << " ::: " << data.second->GetName() << endmsg;
+
+  // We now loop over the existing logical volume mappings and extract the sensitive detector knowledge
+  // from the DD4hep volumes and map them to the requested Gaussino factories
+  if(m_sensdetmappings.size() > 0){
+    for (auto& [dd4hep_volume, g4_volume]: g4map.data().g4Volumes) {
+      if(!dd4hep_volume.isValid()){
+        continue;
+      }
+      if(dd4hep_volume.isSensitive()){
+        auto dd4hep_sensdet_name = dd4hep_volume.sensitiveDetector().name();
+        // Now only continue if the sensitive volume information is present in the factory mappings provided
+        if(m_sensdetmappings.find(dd4hep_sensdet_name) != std::end(m_sensdetmappings)){
+          auto tool_name = m_sensdetmappings[dd4hep_sensdet_name];
+          // Following code is taken from the corresponding GaussGeo functionality 
+          // 1. Get a dictionary mapping tool name to tool instance in case multiple volumes need same sensitive detector
+          auto it = mmap_name_to_sensdetfac.find(tool_name);
+          if(it == std::end(mmap_name_to_sensdetfac)){
+            mmap_name_to_sensdetfac[tool_name] = nullptr;
+            getTool(tool_name, mmap_name_to_sensdetfac[tool_name], this);
+            // Check if successful
+            if(!mmap_name_to_sensdetfac[tool_name]){
+              warning() << "Could not retrieve sensitive detector " << tool_name << "." << endmsg;
+              warning() << "What do we say to the geo service? Not today ..." << endmsg;
+            } else {
+              debug() << "Mapping DD4hep sensitive detector '" << dd4hep_sensdet_name << "' to factory '" << tool_name << "'" << endmsg;
+            }
+          }
+
+          // 2. Now fill the map of identified sensitive detectors to volumes
+          if(auto & sensdet = mmap_name_to_sensdetfac[tool_name]; sensdet){
+            if(mmap_sensdet_to_lvols.find(sensdet) == std::end(mmap_sensdet_to_lvols)){
+              mmap_sensdet_to_lvols[sensdet] = {};
+            }
+            mmap_sensdet_to_lvols[sensdet].insert(g4_volume);
+            if(g4_volume){
+              debug() << "Asked to use sens det " << tool_name << " for " << g4_volume->GetName() << "" << endmsg;
+            }
+          }
+        }
+      }
     }
   }
-
   return sc;
 }
 
@@ -136,12 +187,69 @@ StatusCode DD4hepCnvSvc::finalize() {
 // Retrieve the pointer to G4 geometry tree root
 //=============================================================================
 G4VPhysicalVolume* DD4hepCnvSvc::constructWorld() {
-
-  if(m_world_root) return m_world_root;
-
+  // Simply return the world root volume. It was populated during the initialisation
   return m_world_root;
 }
 
 
 void DD4hepCnvSvc::constructSDandField() {
+  auto sdmanager = G4SDManager::GetSDMpointer();
+  for(auto & [sensdetfac, vols]:  mmap_sensdet_to_lvols){
+    debug() << "Assigning " << sensdetfac->name() << " to " << vols.size() << " logical volumes" << endmsg;
+    auto sensdet = sensdetfac->construct();
+    sdmanager->AddNewDetector(sensdet);
+    for(auto * vol: vols){
+      vol->SetSensitiveDetector(sensdet);
+    }
+  }
+}
+
+//=============================================================================
+// Retrieve a tool by type and name
+//=============================================================================
+template<class T>
+T* DD4hepCnvSvc::getTool(const std::string& type, const std::string& name, T*& tool, const IInterface* parent,
+                     bool create) const {
+  if (m_tool_svc == nullptr) {
+    fatal() << "ToolService is invalid!" << endmsg;
+    return nullptr;
+  }
+
+  if (name.empty()) {
+    return getTool(type, tool, parent, create);
+  }
+
+  StatusCode sc = m_tool_svc->retrieveTool(type, name, tool, parent, create);
+  if (sc.isFailure() || tool == nullptr) {
+    fatal() << "Failed to retrieve tool '" << type << "'/'" << name << "'" << endmsg;
+  }
+
+  return tool;
+}
+
+//=============================================================================
+// Retrieve a tool by type
+//=============================================================================
+template<class T>
+T* DD4hepCnvSvc::getTool(const std::string& type, T*& tool, const IInterface* parent, bool create) const {
+  if (m_tool_svc == nullptr) {
+    fatal() << "ToolService is invalid!" << endmsg;
+    return nullptr;
+  }
+
+  // Check if it is "type" or "type/name"
+  const auto iter = std::find(type.begin(), type.end(), '/');
+  if (iter != type.end()) {
+    std::string::size_type position = iter - type.begin();
+    const std::string new_type(type, 0, position);
+    const std::string new_name(type, position + 1, std::string::npos);
+    return getTool(new_type, new_name, tool, parent, create);
+  }
+
+  StatusCode sc = m_tool_svc->retrieveTool(type, tool, parent, create);
+  if (sc.isFailure() || tool == nullptr) {
+    fatal() << "Failed to retrieve tool '" << type << "'" << endmsg;
+  }
+
+  return tool;
 }
diff --git a/Sim/Gauss/python/Gauss/Geometry/Helpers.py b/Sim/Gauss/python/Gauss/Geometry/Helpers.py
index f29b746c9..e49f56094 100644
--- a/Sim/Gauss/python/Gauss/Geometry/Helpers.py
+++ b/Sim/Gauss/python/Gauss/Geometry/Helpers.py
@@ -6,7 +6,7 @@ def subdetector(obj):
     if lname in __subdetector_configurables:
         raise RuntimeError("Class definition conflict found")
     __subdetector_configurables[lname] = obj
-    obj.name = lname
+    obj.lname = lname
     return obj
 
 
diff --git a/Sim/Gauss/python/Gauss/Geometry/VP.py b/Sim/Gauss/python/Gauss/Geometry/VP.py
index 19761f5cd..3a4b5ef65 100644
--- a/Sim/Gauss/python/Gauss/Geometry/VP.py
+++ b/Sim/Gauss/python/Gauss/Geometry/VP.py
@@ -8,6 +8,12 @@ class VP(det_base):
 
     __slots__ = {}
 
+    def ApplyDetectorDD4hep(self, basePieces, detPieces):
+        from Configurables import DD4hepCnvSvc
+        mappings = DD4hepCnvSvc().getProp('SensDetMappings')
+        mappings['VP'] = 'GiGaSensDetTracker/VPSDet'
+        DD4hepCnvSvc().SensDetMappings = mappings
+
     def ApplyDetectorDetDesc(self, basePieces, detPieces):
         BeamPipe.removeBeamPipeElements("velo")
         if 'BeforeMagnetRegion' in detPieces:
-- 
GitLab


From ac4f5952616f4a6bb3e1ee345ddd9b146e6483fe Mon Sep 17 00:00:00 2001
From: Dominik Muller <dominik.muller@cern.ch>
Date: Thu, 23 Jul 2020 18:39:49 +0200
Subject: [PATCH 56/90] Reworked tracker sens det to support volume ID from
 DD4hep if used

---
 Sim/DD4hepCnv/src/component/DD4hepCnvSvc.h    |  0
 .../component/GiGaSensDetTrackerDD4hepFAC.cpp | 29 +++++++++++++++++
 Sim/GaussTracker/CMakeLists.txt               | 15 ++++++---
 .../GiGaSensDetTracker.h                      | 31 +++++++++++++++++--
 .../{src => GaussTracker}/TrackerHit.h        |  0
 .../{src => GaussTracker}/TrackerHit.icc      |  0
 .../src/GiGaSensDetTrackerFAC.cpp             | 25 ---------------
 .../{ => components}/GetTrackerHitsAlg.cpp    | 16 +++++-----
 .../src/{ => components}/GetTrackerHitsAlg.h  |  7 -----
 .../src/components/GiGaSensDetTrackerFAC.cpp  |  8 +++++
 .../src/{ => lib}/GiGaSensDetTracker.cpp      |  9 ++++--
 Sim/GaussTracker/src/{ => lib}/TrackerHit.cpp |  2 +-
 12 files changed, 93 insertions(+), 49 deletions(-)
 delete mode 100644 Sim/DD4hepCnv/src/component/DD4hepCnvSvc.h
 create mode 100644 Sim/DD4hepCnv/src/component/GiGaSensDetTrackerDD4hepFAC.cpp
 rename Sim/GaussTracker/{src => GaussTracker}/GiGaSensDetTracker.h (74%)
 rename Sim/GaussTracker/{src => GaussTracker}/TrackerHit.h (100%)
 rename Sim/GaussTracker/{src => GaussTracker}/TrackerHit.icc (100%)
 delete mode 100644 Sim/GaussTracker/src/GiGaSensDetTrackerFAC.cpp
 rename Sim/GaussTracker/src/{ => components}/GetTrackerHitsAlg.cpp (92%)
 rename Sim/GaussTracker/src/{ => components}/GetTrackerHitsAlg.h (85%)
 create mode 100644 Sim/GaussTracker/src/components/GiGaSensDetTrackerFAC.cpp
 rename Sim/GaussTracker/src/{ => lib}/GiGaSensDetTracker.cpp (89%)
 rename Sim/GaussTracker/src/{ => lib}/TrackerHit.cpp (98%)

diff --git a/Sim/DD4hepCnv/src/component/DD4hepCnvSvc.h b/Sim/DD4hepCnv/src/component/DD4hepCnvSvc.h
deleted file mode 100644
index e69de29bb..000000000
diff --git a/Sim/DD4hepCnv/src/component/GiGaSensDetTrackerDD4hepFAC.cpp b/Sim/DD4hepCnv/src/component/GiGaSensDetTrackerDD4hepFAC.cpp
new file mode 100644
index 000000000..66580fbfd
--- /dev/null
+++ b/Sim/DD4hepCnv/src/component/GiGaSensDetTrackerDD4hepFAC.cpp
@@ -0,0 +1,29 @@
+// Include files
+
+#include "GiGaMTFactories/GiGaMTG4SensDetFactory.h"
+
+// Geant4 physics lists
+#include "GaussTracker/GiGaSensDetTracker.h"
+
+#include "DDG4/Geant4Mapping.h"
+#include "DDG4/Geant4TouchableHandler.h"
+
+class GiGaSensDetTrackerDD4hep : public GiGaSensDetTracker {
+ public:
+  using GiGaSensDetTracker::GiGaSensDetTracker;
+
+ protected:
+  virtual int GetDetectorID(G4Step*, G4TouchableHistory*) const override final;
+};
+
+int GiGaSensDetTrackerDD4hep::GetDetectorID(G4Step* step,
+                                            G4TouchableHistory*) const {
+  auto& g4map = dd4hep::sim::Geant4Mapping::instance();
+  dd4hep::sim::Geant4TouchableHandler touch{step};
+  auto paths = touch.placementPath();
+  auto id = g4map.volumeManager().volumeID(paths);
+  return id;
+}
+
+DECLARE_COMPONENT_WITH_ID(GiGaSensDetTrackerFAC<GiGaSensDetTrackerDD4hep>,
+                          "GiGaSensDetTrackerDD4hep")
diff --git a/Sim/GaussTracker/CMakeLists.txt b/Sim/GaussTracker/CMakeLists.txt
index 2e4a9b593..3bf963034 100644
--- a/Sim/GaussTracker/CMakeLists.txt
+++ b/Sim/GaussTracker/CMakeLists.txt
@@ -14,12 +14,19 @@ find_package(CLHEP)
 AddHepMC3()
 include_directories(SYSTEM ${Boost_INCLUDE_DIRS} ${CLHEP_INCLUDE_DIRS} ${Geant4_INCLUDE_DIRS} ${HEPMC3_INCLUDE_DIR})
 
-add_definitions(-DG4MULTITHREADED)
-add_definitions(-DG4USE_STD11)
+if(${Geant4_config_version} VERSION_LESS "10.06")
+  add_definitions(-DG4MULTITHREADED)
+  add_definitions(-DG4USE_STD11)
+endif()
+
+gaudi_add_library(GaussTrackerLib
+                 src/lib/*.cpp
+                 PUBLIC_HEADERS GaussTracker
+                 LINK_LIBRARIES Geant4 GiGaMTCoreTruthLib GaudiAlgLib)
 
 gaudi_add_module(GaussTracker
-                 src/*.cpp
-                 LINK_LIBRARIES DetDescLib Geant4 GiGaMTCoreTruthLib GaudiAlgLib)
+                 src/components/*.cpp
+                 LINK_LIBRARIES DetDescLib GaussTrackerLib)
 
 gaudi_env(SET GAUSSTRACKEROPTS \${GAUSSTRACKERROOT}/options)
 
diff --git a/Sim/GaussTracker/src/GiGaSensDetTracker.h b/Sim/GaussTracker/GaussTracker/GiGaSensDetTracker.h
similarity index 74%
rename from Sim/GaussTracker/src/GiGaSensDetTracker.h
rename to Sim/GaussTracker/GaussTracker/GiGaSensDetTracker.h
index afabcfb8f..f0ebc241b 100755
--- a/Sim/GaussTracker/src/GiGaSensDetTracker.h
+++ b/Sim/GaussTracker/GaussTracker/GiGaSensDetTracker.h
@@ -4,7 +4,7 @@
 #include "GiGaMTCoreTruth/GaussinoTrackInformation.h"
 #include "GiGaMTCoreMessage/IGiGaMessage.h"
 #include "Geant4/G4VSensitiveDetector.hh"
-#include "TrackerHit.h"
+#include "GaussTracker/TrackerHit.h"
 
 // Forward declarations
 class G4Step;
@@ -25,6 +25,7 @@ class G4TouchableHistory;
 class GiGaSensDetTracker : public G4VSensitiveDetector, public virtual GiGaMessage {
   public:
   GiGaSensDetTracker(const std::string& name);
+  virtual ~GiGaSensDetTracker() = default;
 
   /** Initialize method (Geant4).
    *  Called at the beginning of each event
@@ -47,11 +48,13 @@ class GiGaSensDetTracker : public G4VSensitiveDetector, public virtual GiGaMessa
    *  @param step     pointer to current Geant4 step
    *  @param history  pointer to touchable history
    */
-  bool ProcessHits(G4Step* step, G4TouchableHistory* history) override;
+  bool ProcessHits(G4Step* step, G4TouchableHistory* history) override final;
 
   // Flag to control storing of hits if track deposited energy or not
   void SetRequireEDep(bool val = true) { m_requireEDep = val; }
 
+  protected:
+  virtual int GetDetectorID(G4Step*, G4TouchableHistory*) const {return -1;}
   private:
   GiGaSensDetTracker();                           ///< no default constructor
   GiGaSensDetTracker(const GiGaSensDetTracker&);  ///< no copy constructor
@@ -64,3 +67,27 @@ class GiGaSensDetTracker : public G4VSensitiveDetector, public virtual GiGaMessa
   /// switching it off for special studies (like with geantinos)
   bool m_requireEDep = true;
 };
+
+#include "GiGaMTFactories/GiGaMTG4SensDetFactory.h"
+
+template <typename T>
+using TrackerBaseFAC = GiGaMTG4SensDetFactory<T>;
+
+template<typename T>
+class GiGaSensDetTrackerFAC: public TrackerBaseFAC<T>
+{
+  static_assert(std::is_base_of<GiGaSensDetTracker, T>::value);
+
+  Gaudi::Property<bool> m_requireEDep{this, "RequireEDep", true,
+                                      "Hits must have non-zero Energy deposition"};
+
+public:
+  using base_class = TrackerBaseFAC<T>;
+  using base_class::base_class;
+  T* construct() const override
+  {
+    auto tmp = base_class::construct();
+    tmp->SetRequireEDep(m_requireEDep);
+    return tmp;
+  }
+};
diff --git a/Sim/GaussTracker/src/TrackerHit.h b/Sim/GaussTracker/GaussTracker/TrackerHit.h
similarity index 100%
rename from Sim/GaussTracker/src/TrackerHit.h
rename to Sim/GaussTracker/GaussTracker/TrackerHit.h
diff --git a/Sim/GaussTracker/src/TrackerHit.icc b/Sim/GaussTracker/GaussTracker/TrackerHit.icc
similarity index 100%
rename from Sim/GaussTracker/src/TrackerHit.icc
rename to Sim/GaussTracker/GaussTracker/TrackerHit.icc
diff --git a/Sim/GaussTracker/src/GiGaSensDetTrackerFAC.cpp b/Sim/GaussTracker/src/GiGaSensDetTrackerFAC.cpp
deleted file mode 100644
index 66b2bbed5..000000000
--- a/Sim/GaussTracker/src/GiGaSensDetTrackerFAC.cpp
+++ /dev/null
@@ -1,25 +0,0 @@
-// Include files
-
-#include "GiGaMTFactories/GiGaMTG4SensDetFactory.h"
-
-// Geant4 physics lists
-#include "GiGaSensDetTracker.h"
-
-typedef GiGaMTG4SensDetFactory<GiGaSensDetTracker> TrackerBaseFAC;
-
-class GiGaSensDetTrackerFAC: public TrackerBaseFAC
-{
-  Gaudi::Property<bool> m_requireEDep{this, "RequireEDep", true,
-                                      "Hits must have non-zero Energy deposition"};
-
-public:
-  using TrackerBaseFAC::TrackerBaseFAC;
-  GiGaSensDetTracker* construct() const override
-  {
-    auto tmp = TrackerBaseFAC::construct();
-    tmp->SetRequireEDep(m_requireEDep);
-    return tmp;
-  }
-};
-
-DECLARE_COMPONENT_WITH_ID( GiGaSensDetTrackerFAC, "GiGaSensDetTracker" )
diff --git a/Sim/GaussTracker/src/GetTrackerHitsAlg.cpp b/Sim/GaussTracker/src/components/GetTrackerHitsAlg.cpp
similarity index 92%
rename from Sim/GaussTracker/src/GetTrackerHitsAlg.cpp
rename to Sim/GaussTracker/src/components/GetTrackerHitsAlg.cpp
index b33eefebc..c1b114233 100755
--- a/Sim/GaussTracker/src/GetTrackerHitsAlg.cpp
+++ b/Sim/GaussTracker/src/components/GetTrackerHitsAlg.cpp
@@ -8,7 +8,7 @@
 
 // local
 #include "GetTrackerHitsAlg.h"
-#include "TrackerHit.h"
+#include "GaussTracker/TrackerHit.h"
 
 //-----------------------------------------------------------------------------
 // Implementation file for class : GetTrackerHitsAlg
@@ -40,9 +40,10 @@ StatusCode GetTrackerHitsAlg::initialize() {
     debug() << " will be taken from G4 collection " << m_colName << endmsg;
     debug() << endmsg;
 
-    // FIXME: Should become a tool
-    // get the detector element
-  debug() << " for detector(s) ";
+    debug() << " for detector(s) ";
+    // Get the DetDesc detectors specified to search for detector ID. If the
+    // list is empty, no search is performed and the ID is taken from the geant4 hit
+    // directly (latter needs DD4hep)
     for (itDet = m_detName.begin(); itDet != m_detName.end(); itDet++) {
         debug() << *itDet << " ";
         m_detector.push_back(getDet<DetectorElement>(*itDet));
@@ -123,10 +124,9 @@ void GetTrackerHitsAlg::fillHit(
     mcHit->setTime(g4Hit->GetTimeOfFlight());
     mcHit->setP(g4Hit->GetMomentum().mag());
 
-    // get sensitive detector identifier using mid point
-    // FIXME: This needs to be added once geometry has been worked in
-    int detID = -1;
-    // FIXME: put this into a tool so it can be configured when using DD4hep
+    // get sensitive detector from the TrackerHit
+    int detID = g4Hit->GetDetectorID();
+    // If DetDesc detectors were specified, search the list of detectors
     for (auto itDet = m_detector.begin(); itDet != m_detector.end(); itDet++) {
         if ((*itDet)->isInside(mcHit->midPoint())) {
             detID = (*itDet)->sensitiveVolumeID(mcHit->midPoint());
diff --git a/Sim/GaussTracker/src/GetTrackerHitsAlg.h b/Sim/GaussTracker/src/components/GetTrackerHitsAlg.h
similarity index 85%
rename from Sim/GaussTracker/src/GetTrackerHitsAlg.h
rename to Sim/GaussTracker/src/components/GetTrackerHitsAlg.h
index 39657950e..ba28216a9 100755
--- a/Sim/GaussTracker/src/GetTrackerHitsAlg.h
+++ b/Sim/GaussTracker/src/components/GetTrackerHitsAlg.h
@@ -44,11 +44,6 @@ class GetTrackerHitsAlg
   virtual StatusCode initialize() override;  ///< Algorithm initialization
   virtual StatusCode finalize() override;    ///< Algorithm finalization
 
-  // declareProperty( "GiGaService",    m_gigaSvcName  = "GiGa",
-  //"The service handling the intreface to Geant4" );
-  // declareProperty( "KineCnvService", m_kineSvcName  =
-  // IGiGaCnvSvcLocation::Kine, "The service keeping the relation between Geant4
-  // kinematic and MCTruth" );
   Gaudi::Property<bool> m_extendedInfo{this, "ExtendedInfo", false,
                                        "Flag to control filling of "
                                        "MCExtendedHits instead of MCHits (def "
@@ -62,8 +57,6 @@ class GetTrackerHitsAlg
       {},
       "List of detector paths in TDS for which to retrieve the hits (most of "
       "the time one"};
-  // declareProperty( "MCParticles",    m_mcParticles =
-  // LHCb::MCParticleLocation::Default, "Location of MCParticles" ) ;
 
   protected:
   void fillHit(TrackerHit* g4Hit, LHCb::MCHit* mcHit,const Gaussino::MCTruth* mctruth, const LinkedParticleMCParticleLinks& mcplinks) const;
diff --git a/Sim/GaussTracker/src/components/GiGaSensDetTrackerFAC.cpp b/Sim/GaussTracker/src/components/GiGaSensDetTrackerFAC.cpp
new file mode 100644
index 000000000..ea8938c1c
--- /dev/null
+++ b/Sim/GaussTracker/src/components/GiGaSensDetTrackerFAC.cpp
@@ -0,0 +1,8 @@
+// Include files
+
+#include "GiGaMTFactories/GiGaMTG4SensDetFactory.h"
+
+// Geant4 physics lists
+#include "GaussTracker/GiGaSensDetTracker.h"
+
+DECLARE_COMPONENT_WITH_ID( GiGaSensDetTrackerFAC<GiGaSensDetTracker>, "GiGaSensDetTracker" )
diff --git a/Sim/GaussTracker/src/GiGaSensDetTracker.cpp b/Sim/GaussTracker/src/lib/GiGaSensDetTracker.cpp
similarity index 89%
rename from Sim/GaussTracker/src/GiGaSensDetTracker.cpp
rename to Sim/GaussTracker/src/lib/GiGaSensDetTracker.cpp
index 4aec95363..7f2e81a4a 100755
--- a/Sim/GaussTracker/src/GiGaSensDetTracker.cpp
+++ b/Sim/GaussTracker/src/lib/GiGaSensDetTracker.cpp
@@ -18,7 +18,8 @@
 #include "Geant4/G4ios.hh"
 
 // local
-#include "GiGaSensDetTracker.h"
+#include "GaussTracker/GiGaSensDetTracker.h"
+#include "GaussTracker/TrackerHit.h"
 
 //-----------------------------------------------------------------------------
 // Implementation file for class : GiGaSensDetTracker
@@ -44,7 +45,7 @@ void GiGaSensDetTracker::Initialize(G4HCofThisEvent* HCE) {
 }
 
 bool GiGaSensDetTracker::ProcessHits(G4Step* step,
-                                     G4TouchableHistory* /* history */) {
+                                     G4TouchableHistory* history) {
     if (0 == step) {
         return false;
     }
@@ -84,6 +85,10 @@ bool GiGaSensDetTracker::ProcessHits(G4Step* step,
         int trid = track->GetTrackID();
         newHit->SetTrackID(trid);
 
+        // Get the hit ID. Default implementation just sets it to -1
+        // but derived classes can overwrite this behaviour
+        newHit->SetDetectorID(GetDetectorID(step, history));
+
         auto gi = GaussinoTrackInformation::Get(track);
         gi->setCreatedHit(true);
         gi->setToStoreTruth(true);
diff --git a/Sim/GaussTracker/src/TrackerHit.cpp b/Sim/GaussTracker/src/lib/TrackerHit.cpp
similarity index 98%
rename from Sim/GaussTracker/src/TrackerHit.cpp
rename to Sim/GaussTracker/src/lib/TrackerHit.cpp
index f4b6f029b..d00816455 100755
--- a/Sim/GaussTracker/src/TrackerHit.cpp
+++ b/Sim/GaussTracker/src/lib/TrackerHit.cpp
@@ -14,7 +14,7 @@
 #include "Geant4/G4VisAttributes.hh"
 
 // local
-#include "TrackerHit.h"
+#include "GaussTracker/TrackerHit.h"
 
 G4ThreadLocal G4Allocator<TrackerHit> *aTrackerHitAllocator = nullptr;
 
-- 
GitLab


From c42eac04f38c46427875ebb4c4ca83de9ccfa6ee Mon Sep 17 00:00:00 2001
From: Dominik Muller <dominik.muller@cern.ch>
Date: Thu, 23 Jul 2020 18:40:48 +0200
Subject: [PATCH 57/90] Dynamic writing of main DD4hep xml, sensitive detector
 from DD4hep, Bls support from dd4hep and monitor

---
 Bls/.gaudi_project_ignore                     |   0
 Bls/BlsMoniSim/src/BlsHitChecker.cpp          | 583 ++++++++----------
 Bls/BlsMoniSim/src/BlsHitChecker.h            |  74 +--
 Sim/DD4hepCnv/CMakeLists.txt                  |   3 +-
 Sim/DD4hepCnv/src/component/DD4hepCnvSvc.cpp  |  28 +-
 Sim/Gauss/python/Gauss/Geometry/BLS.py        |  87 ++-
 .../python/Gauss/Geometry/Configuration.py    |  30 +-
 Sim/Gauss/python/Gauss/Geometry/VP.py         |  23 +-
 Sim/Gauss/python/Gauss/Geometry/__init__.py   |   2 +
 Sim/Gauss/python/Gauss/Geometry/xml_writer.py |  71 +++
 Sim/Gauss/python/Gauss/Physics.py             |   6 +-
 11 files changed, 490 insertions(+), 417 deletions(-)
 delete mode 100644 Bls/.gaudi_project_ignore
 create mode 100644 Sim/Gauss/python/Gauss/Geometry/xml_writer.py

diff --git a/Bls/.gaudi_project_ignore b/Bls/.gaudi_project_ignore
deleted file mode 100644
index e69de29bb..000000000
diff --git a/Bls/BlsMoniSim/src/BlsHitChecker.cpp b/Bls/BlsMoniSim/src/BlsHitChecker.cpp
index 0c518bebf..f03f9e57e 100644
--- a/Bls/BlsMoniSim/src/BlsHitChecker.cpp
+++ b/Bls/BlsMoniSim/src/BlsHitChecker.cpp
@@ -1,17 +1,127 @@
 // $Id: BlsHitChecker.cpp,v 1.1.1.2 2010-03-10 17:38:47 vtalanov Exp $
-// Include files 
+// Include files
 
 // from Gaudi
-#include "GaudiAlg/Tuples.h"
-#include "Event/MCParticle.h"
 #include "Event/MCHeader.h"
+#include "Event/MCParticle.h"
+#include "GaudiAlg/Tuples.h"
 
 // from STL
 #include <map>
 #include <string>
 
-// local
-#include "BlsHitChecker.h"
+// Include files
+
+// from Gaudi
+#include "Event/MCHit.h"
+#include "GaudiAlg/Consumer.h"
+#include "GaudiAlg/GaudiTupleAlg.h"
+#include "GaudiKernel/Stat.h"
+
+// from STL
+#include <map>
+
+// from AIDA
+#include "AIDA/IHistogram1D.h"
+#include "AIDA/IHistogram2D.h"
+
+/** @class BlsHitChecker BlsHitChecker.h
+ *
+ *
+ *  @author Vadim Talanov
+ *  @date   2010-02-06
+ *
+ *  MT modifications
+ *  @author Dominik Muller
+ *  @date   2020-07-23
+ */
+
+class BlsHitChecker
+    : public Gaudi::Functional::Consumer<
+          void(const LHCb::MCHits&, const LHCb::MCHeader&),
+          Gaudi::Functional::Traits::BaseClass_t<GaudiHistoAlg>> {
+ public:
+  /// Standard constructor
+  BlsHitChecker(const std::string& name, ISvcLocator* pSvcLocator)
+      : Consumer(name, pSvcLocator,
+                 {
+                     KeyValue{"HitsLocation", "MC/Bls/Hits"},
+                     KeyValue{"MCHeader", LHCb::MCHeaderLocation::Default},
+                 }){};
+
+  StatusCode initialize() override;  ///< Algorithm initialization
+  void operator()(const LHCb::MCHits&, const LHCb::MCHeader&) const override;
+
+ protected:
+ private:
+  void bookHistograms();
+  Gaudi::Property<bool> m_blsAOn{this, "BlsAOn", false};
+  Gaudi::Property<bool> m_blsCOn{this, "BlsCOn", false};
+  Gaudi::Property<std::string> m_blsHTitlePrefix{this, "HistogramTitlePrefix",
+                                                 "BLS: "};
+  Gaudi::Property<double> m_blsHEntryXMin{this, "EntryXMin",
+                                          -150.0 * Gaudi::Units::mm};
+  Gaudi::Property<double> m_blsHEntryXMax{this, "EntryXMax",
+                                          +150.0 * Gaudi::Units::mm};
+  Gaudi::Property<unsigned long> m_blsHEntryXNbins{this, "EntryXNbins", 300};
+  Gaudi::Property<double> m_blsHEntryYMin{this, "EntryYMin",
+                                          -150.0 * Gaudi::Units::mm};
+  Gaudi::Property<double> m_blsHEntryYMax{this, "EntryYMax",
+                                          +150.0 * Gaudi::Units::mm};
+  Gaudi::Property<unsigned long> m_blsHEntryYNbins{this, "EntryYNbins", 300};
+  Gaudi::Property<double> m_blsHEntryZMin{this, "EntryZMin",
+                                          -2200.0 * Gaudi::Units::mm};
+  Gaudi::Property<double> m_blsHEntryZMax{this, "EntryZMax",
+                                          -1900.0 * Gaudi::Units::mm};
+  Gaudi::Property<unsigned long> m_blsHEntryZNbins{this, "EntryZNbins", 300};
+  Gaudi::Property<double> m_blsHEntryTimeOffset{this, "EntryTimeOffset",
+                                                0.0 * Gaudi::Units::ns};
+  Gaudi::Property<double> m_blsHEntryTimeMin{this, "EntryTimeMin",
+                                             -50.0 * Gaudi::Units::ns};
+  Gaudi::Property<double> m_blsHEntryTimeMax{this, "EntryTimeMax",
+                                             +50.0 * Gaudi::Units::ns};
+  Gaudi::Property<unsigned long> m_blsHEntryTimeNbins{this, "EntryTimeNbins",
+                                                      100};
+  Gaudi::Property<double> m_blsHTrackEnDepMin{this, "TrackEnDepMin", 0.0};
+  Gaudi::Property<double> m_blsHTrackEnDepMax{this, "TrackEnDepMax", 50.0};
+  Gaudi::Property<unsigned long> m_blsHTrackEnDepNbins{this, "TrackEnDepNbins",
+                                                       500};
+  Gaudi::Property<double> m_blsHTrackLengthMin{this, "TrackLengthMin", 0.0};
+  Gaudi::Property<double> m_blsHTrackLengthMax{this, "TrackLengthMax", 7.0};
+  Gaudi::Property<unsigned long> m_blsHTrackLengthNbins{this,
+                                                        "TrackLengthNbins", 70};
+  Gaudi::Property<double> m_blsHEventNumTracksMin{this, "EventNumTracksMin",
+                                                  0.0};
+  Gaudi::Property<double> m_blsHEventNumTracksMax{this, "EventNumTracksMax",
+                                                  50.0};
+  Gaudi::Property<unsigned long> m_blsHEventNumTracksNbins{
+      this, "EventNumTracksNbins", 50};
+  Gaudi::Property<double> m_blsHEventNumMin{this, "EventNumMin", 0.0};
+  Gaudi::Property<double> m_blsHEventNumMax{this, "EventNumMax", 1000.0};
+  Gaudi::Property<unsigned long> m_blsHEventNumNbins{this, "EventNumNbins",
+                                                     1000};
+  mutable Gaudi::Accumulators::SummingCounter<size_t> m_blsHits{this,
+                                                                "BlsHits"};
+  mutable Gaudi::Accumulators::SummingCounter<size_t> m_blsTracks{this,
+                                                                  "BlsTracks"};
+
+  typedef std::multimap<const LHCb::MCParticle*, LHCb::MCHit*>
+      t_blsMCParticle2MCHitMultimap;
+
+  AIDA::IHistogram2D* h_HitEntryXY{nullptr};
+  AIDA::IHistogram2D* h_HitEntryZX{nullptr};
+  AIDA::IHistogram2D* h_HitEntryZY{nullptr};
+  AIDA::IHistogram1D* h_HitEnDepTime{nullptr};
+  AIDA::IHistogram1D* h_TrackEnDep{nullptr};
+  AIDA::IHistogram1D* h_TrackLength{nullptr};
+  AIDA::IHistogram1D* h_TrackEnDepPerUnitLength{nullptr};
+  AIDA::IHistogram1D* h_EventNumHits{nullptr};
+  AIDA::IHistogram1D* h_EventNumTracks{nullptr};
+  AIDA::IHistogram1D* h_EventEnDep{nullptr};
+  AIDA::IHistogram1D* h_RunNumHits{nullptr};
+  AIDA::IHistogram1D* h_RunNumTracks{nullptr};
+  AIDA::IHistogram1D* h_RunEnDep{nullptr};
+};
 
 //-----------------------------------------------------------------------------
 // Implementation file for class : BlsHitChecker
@@ -20,178 +130,75 @@
 //-----------------------------------------------------------------------------
 
 // Declaration of the Algorithm Factory
-DECLARE_COMPONENT( BlsHitChecker )
-
-//=============================================================================
-// Standard constructor, initializes variables
-//=============================================================================
-
-BlsHitChecker::BlsHitChecker( const std::string& name,
-                              ISvcLocator* pSvcLocator)
-  : GaudiTupleAlg ( name , pSvcLocator ),
-                     m_blsMCHits ( ),
-               m_blsHitsLocation ( "MC/Bls/Hits" ),
-                        m_blsAOn ( false ),
-                        m_blsCOn ( false ),
-               m_blsHTitlePrefix ( "BLS: " ),
-                 m_blsHEntryXMin ( -150.0 * Gaudi::Units::mm),
-                 m_blsHEntryXMax ( +150.0 * Gaudi::Units::mm),
-               m_blsHEntryXNbins ( 300 ),
-                 m_blsHEntryYMin ( -150.0 * Gaudi::Units::mm),
-                 m_blsHEntryYMax ( +150.0 * Gaudi::Units::mm),
-               m_blsHEntryYNbins ( 300 ),
-                 m_blsHEntryZMin ( -2200.0 * Gaudi::Units::mm),
-                 m_blsHEntryZMax ( -1900.0 * Gaudi::Units::mm),
-               m_blsHEntryZNbins ( 300 ),
-           m_blsHEntryTimeOffset ( 0.0 * Gaudi::Units::ns ),
-              m_blsHEntryTimeMin ( -50.0 * Gaudi::Units::ns ),
-              m_blsHEntryTimeMax ( +50.0 * Gaudi::Units::ns ),
-            m_blsHEntryTimeNbins ( 100 ),
-             m_blsHTrackEnDepMin ( 0.0 ),
-             m_blsHTrackEnDepMax ( 50.0 ),
-           m_blsHTrackEnDepNbins ( 500 ),
-            m_blsHTrackLengthMin ( 0.0 ),
-            m_blsHTrackLengthMax ( 7.0 ),
-          m_blsHTrackLengthNbins ( 70 ),
-         m_blsHEventNumTracksMin ( 0.0 ),
-         m_blsHEventNumTracksMax ( 50.0 ),
-       m_blsHEventNumTracksNbins ( 50 ),
-               m_blsHEventNumMin ( 0.0 ),
-               m_blsHEventNumMax ( 1000.0 ),
-             m_blsHEventNumNbins ( 1000 ),
-                       m_blsHits ( 0 ),
-                     m_blsTracks ( 0 )
-{
-  declareProperty( "HitsLocation", m_blsHitsLocation );
-  declareProperty( "BlsAOn", m_blsAOn );
-  declareProperty( "BlsCOn", m_blsCOn );
-  declareProperty( "HistogramTitlePrefix", m_blsHTitlePrefix );
-  declareProperty( "EntryXMin", m_blsHEntryXMin );
-  declareProperty( "EntryXMax", m_blsHEntryXMax );
-  declareProperty( "EntryXNbins", m_blsHEntryXNbins );
-  declareProperty( "EntryYMin", m_blsHEntryYMin );
-  declareProperty( "EntryYMax", m_blsHEntryYMax );
-  declareProperty( "EntryYNbins", m_blsHEntryYNbins );
-  declareProperty( "EntryZMin", m_blsHEntryZMin );
-  declareProperty( "EntryZMax", m_blsHEntryZMax );
-  declareProperty( "EntryZNbins", m_blsHEntryZNbins );
-  declareProperty( "EntryTimeOffset", m_blsHEntryTimeOffset );
-  declareProperty( "EntryTimeMin", m_blsHEntryTimeMin );
-  declareProperty( "EntryTimeMax", m_blsHEntryTimeMax );
-  declareProperty( "EntryTimeNbins", m_blsHEntryTimeNbins );
-  declareProperty( "TrackEnDepMin", m_blsHTrackEnDepMin );
-  declareProperty( "TrackEnDepMax", m_blsHTrackEnDepMax );
-  declareProperty( "TrackEnDepNbins", m_blsHTrackEnDepNbins );
-  declareProperty( "TrackLengthMin", m_blsHTrackLengthMin );
-  declareProperty( "TrackLengthMax", m_blsHTrackLengthMax );
-  declareProperty( "TrackLengthNbins", m_blsHTrackLengthNbins );
-  declareProperty( "EventNumTracksMin", m_blsHEventNumTracksMin );
-  declareProperty( "EventNumTracksMax", m_blsHEventNumTracksMax );
-  declareProperty( "EventNumTracksNbins", m_blsHEventNumTracksNbins );
-  declareProperty( "EventNumMin", m_blsHEventNumMin );
-  declareProperty( "EventNumMax", m_blsHEventNumMax );
-  declareProperty( "EventNumNbins", m_blsHEventNumNbins );
- }
-
-//=============================================================================
-// Destructor
-//=============================================================================
-
-BlsHitChecker::~BlsHitChecker() {} 
+DECLARE_COMPONENT(BlsHitChecker)
 
 //=============================================================================
 // Initialization
 //=============================================================================
 
 StatusCode BlsHitChecker::initialize() {
-  StatusCode sc = GaudiAlgorithm::initialize(); // must be executed first
-  if ( sc.isFailure() ) return sc;  // error printed already by GaudiAlgorithm
-  if ( msgLevel(MSG::DEBUG) )
-    debug() << "BlsHitChecker::initialize()" << endmsg;
+  StatusCode sc = GaudiAlgorithm::initialize();  // must be executed first
+  if (sc.isFailure()) return sc;  // error printed already by GaudiAlgorithm
+  if (msgLevel(MSG::DEBUG)) debug() << "BlsHitChecker::initialize()" << endmsg;
+  bookHistograms();
   return StatusCode::SUCCESS;
-} // end of: BlsHitChecker::initialize() {
+}  // end of: BlsHitChecker::initialize() {
 
 //=============================================================================
 // Main execution
 //=============================================================================
 
-StatusCode BlsHitChecker::execute() {
-  if ( msgLevel(MSG::DEBUG) )
-    debug() << "BlsHitChecker::execute()" << endmsg;
-  if ( ! exist < LHCb::MCHits > ( m_blsHitsLocation ) ) {
-    // Something happened - m_blsHitsLocation points to nowhere?...
-    error() << "There are no MCHits at "
-            << m_blsHitsLocation
-            << " in TES!" << endmsg;
-    // This is critical - tell the world about this error
-    return StatusCode::FAILURE;
-  } // end of: if ( ! exist < LHCb::MCHits > ( m_blsHitsLocation ) )
-  // Get MC hits in the scintillator volume of BLSs
-  m_blsMCHits = get < LHCb::MCHits > ( m_blsHitsLocation );
+void BlsHitChecker::operator()(const LHCb::MCHits& blsMCHits,
+                               const LHCb::MCHeader& myMCHeader) const {
+  if (msgLevel(MSG::DEBUG)) debug() << "BlsHitChecker::execute()" << endmsg;
   // Just return if the number of hits in all BLSs is zero
-  if ( 0 == m_blsMCHits->size() )
-    return StatusCode::SUCCESS;
-  // Get event header for event number (also used much later)
-  const LHCb::MCHeader* myMCHeader =
-    get < LHCb::MCHeader > ( LHCb::MCHeaderLocation::Default );
-  if ( msgLevel(MSG::DEBUG) )
-    debug() << "m_blsHitsLocation: "
-            << m_blsMCHits->size()
-            << " hit(s) found at event no. "
-            << myMCHeader->evtNumber() << endmsg;
+  if (0 == blsMCHits.size()) return;
+  if (msgLevel(MSG::DEBUG))
+    debug() << "m_blsHitsLocation: " << blsMCHits.size()
+            << " hit(s) found at event no. " << myMCHeader.evtNumber()
+            << endmsg;
   // Define a multimap for Particle/Hit pairs
   t_blsMCParticle2MCHitMultimap myMultimap;
   // Loop over all hits got from m_blsHitsLocation
-  for ( LHCb::MCHits::iterator It = m_blsMCHits->begin();
-        It != m_blsMCHits->end();
-        It++ ) {
+  for (auto& hit : blsMCHits) {
     // Get MC Particle that created this hit
-    const LHCb::MCParticle* myMCParticle = (*It)->mcParticle();
+    const LHCb::MCParticle* myMCParticle = hit->mcParticle();
     // If DEBUG is switched on
-    if ( msgLevel(MSG::DEBUG) ) {
+    if (msgLevel(MSG::DEBUG)) {
       // Print some data for hit and particle
       LHCb::ParticleID myParticleId = myMCParticle->particleID();
       Gaudi::LorentzVector myParticleMomentum = myMCParticle->momentum();
       const LHCb::MCVertex* myMCVertex = myMCParticle->originVertex();
-      debug () << "Particle ID and momentum: "
-               << myParticleId.pid() << " "
-               << myParticleMomentum.e()/Gaudi::Units::GeV << " "
-               << myMCParticle << " "
-               << (*It) << " "
-               << endmsg;
-      debug () << "Entry point: "
-               << (*It)->entry().x()/Gaudi::Units::mm << " "
-               << (*It)->entry().y()/Gaudi::Units::mm << " "
-               << (*It)->entry().z()/Gaudi::Units::mm
-               << endmsg;
-      debug () << "Exit point: "
-               << (*It)->exit().x()/Gaudi::Units::mm << " "
-               << (*It)->exit().y()/Gaudi::Units::mm << " "
-               << (*It)->exit().z()/Gaudi::Units::mm
-               << endmsg;
-      debug () << "Vertex position: "
-               << myMCVertex->position().x()/Gaudi::Units::mm << " " 
-               << myMCVertex->position().y()/Gaudi::Units::mm << " " 
-               << myMCVertex->position().z()/Gaudi::Units::mm << " " 
-               << myMCVertex->type()
-               << endmsg;
-    } // end of: if ( msgLevel(MSG::DEBUG) )
+      debug() << "Particle ID and momentum: " << myParticleId.pid() << " "
+              << myParticleMomentum.e() / Gaudi::Units::GeV << " "
+              << myMCParticle << " " << hit << " " << endmsg;
+      debug() << "Entry point: " << hit->entry().x() / Gaudi::Units::mm << " "
+              << hit->entry().y() / Gaudi::Units::mm << " "
+              << hit->entry().z() / Gaudi::Units::mm << endmsg;
+      debug() << "Exit point: " << hit->exit().x() / Gaudi::Units::mm << " "
+              << hit->exit().y() / Gaudi::Units::mm << " "
+              << hit->exit().z() / Gaudi::Units::mm << endmsg;
+      debug() << "Vertex position: "
+              << myMCVertex->position().x() / Gaudi::Units::mm << " "
+              << myMCVertex->position().y() / Gaudi::Units::mm << " "
+              << myMCVertex->position().z() / Gaudi::Units::mm << " "
+              << myMCVertex->type() << endmsg;
+    }  // end of: if ( msgLevel(MSG::DEBUG) )
     // Positive X goes to positive BLS and negative X to negative BLS
-    if ( ( (*It)->entry().x() > 0 && m_blsCOn ) ||
-         ( (*It)->entry().x() < 0 && m_blsAOn ) ) {
+    if ((hit->entry().x() > 0 && m_blsCOn) ||
+        (hit->entry().x() < 0 && m_blsAOn)) {
       // Insert a pair of Particle-Hit into the map
-      myMultimap.insert
-        ( t_blsMCParticle2MCHitMultimap::value_type ( myMCParticle, *It ) );
-    } // end of: if ( ( (*It)->entry().x() > 0 && m_blsCOn ) ||
-  } // end of: for ( LHCb::MCHits::iterator It = m_blsMCHits->begin();
+      myMultimap.insert(
+          t_blsMCParticle2MCHitMultimap::value_type(myMCParticle, hit));
+    }  // end of: if ( ( (*It)->entry().x() > 0 && m_blsCOn ) ||
+  }    // end of: for ( LHCb::MCHits::iterator It = m_blsMCHits->begin();
   // Just return if no hits were found in a particular BLS
-  if ( myMultimap.empty() ) {
-    if ( msgLevel(MSG::DEBUG) )
+  if (myMultimap.empty()) {
+    if (msgLevel(MSG::DEBUG))
       debug() << "No hits in this BLS found at event no. "
-              << myMCHeader->evtNumber()
-              << endmsg;
-    return StatusCode::SUCCESS;
-  } // end of: if ( myMultimap.empty() ) {
+              << myMCHeader.evtNumber() << endmsg;
+    return;
+  }  // end of: if ( myMultimap.empty() ) {
   // Calculate hits/tracks and energy deposited in event
   unsigned short myEventNumHits = 0;
   unsigned short myEventNumTracks = 0;
@@ -199,9 +206,8 @@ StatusCode BlsHitChecker::execute() {
   // String for histogram titles
   std::string myTitle;
   // Scan Particle<->Hit map to get quantities per single track
-  for ( t_blsMCParticle2MCHitMultimap::iterator anIt = myMultimap.begin();
-        anIt != myMultimap.end();
-        ) {
+  for (t_blsMCParticle2MCHitMultimap::iterator anIt = myMultimap.begin();
+       anIt != myMultimap.end();) {
     // Count new track
     myEventNumTracks++;
     // Calculate energy deposited by a single track and this track length
@@ -209,187 +215,138 @@ StatusCode BlsHitChecker::execute() {
     double myTrackLength = 0.0;
     // For each unique key (== MCParticle) in a map collect hits it has created
     const LHCb::MCParticle* myKey = (*anIt).first;
-    for ( t_blsMCParticle2MCHitMultimap::iterator oneMoreIt =
-            myMultimap.lower_bound ( myKey );
-          oneMoreIt != myMultimap.upper_bound ( myKey );
-          oneMoreIt++ ) {
+    for (t_blsMCParticle2MCHitMultimap::iterator oneMoreIt =
+             myMultimap.lower_bound(myKey);
+         oneMoreIt != myMultimap.upper_bound(myKey); oneMoreIt++) {
       // Count new hit
       myEventNumHits++;
       const LHCb::MCParticle* myMCParticle = (*oneMoreIt).first;
       LHCb::MCHit* myMCHit = (*oneMoreIt).second;
       // If DEBUG is switched on
-      if ( msgLevel(MSG::DEBUG) ) {
-        debug() << "Particle2Hit map: "
-                << myMCParticle << " "
-                << myMCHit << " "
-                << myMCHit->energy()/Gaudi::Units::MeV << " "
-                << myMCHit->time()/Gaudi::Units::ns
-                << endmsg;
-      } // end of: if ( msgLevel(MSG::DEBUG) )
+      if (msgLevel(MSG::DEBUG)) {
+        debug() << "Particle2Hit map: " << myMCParticle << " " << myMCHit << " "
+                << myMCHit->energy() / Gaudi::Units::MeV << " "
+                << myMCHit->time() / Gaudi::Units::ns << endmsg;
+      }  // end of: if ( msgLevel(MSG::DEBUG) )
       // Add properties for current hit (== step) to track
       myTrackEnDep += myMCHit->energy();
       myTrackLength += myMCHit->pathLength();
       // Make histograms for a per hit quantities
-      myTitle = m_blsHTitlePrefix
-        + "Hit entry point in scintillator [mm], XY plane";
-      plot2D( myMCHit->entry().x()/Gaudi::Units::mm,
-              myMCHit->entry().y()/Gaudi::Units::mm,
-              "HitEntryXY",
-              myTitle,
-              m_blsHEntryXMin/Gaudi::Units::mm,
-              m_blsHEntryXMax/Gaudi::Units::mm,
-              m_blsHEntryYMin/Gaudi::Units::mm,
-              m_blsHEntryYMax/Gaudi::Units::mm,
-              m_blsHEntryXNbins,
-              m_blsHEntryYNbins );
-      myTitle = m_blsHTitlePrefix
-        + "Hit entry point in scintillator [mm], ZX plane";
-      plot2D( myMCHit->entry().z()/Gaudi::Units::mm,
-              myMCHit->entry().x()/Gaudi::Units::mm,
-              "HitEntryZX",
-              myTitle,
-              m_blsHEntryZMin/Gaudi::Units::mm,
-              m_blsHEntryZMax/Gaudi::Units::mm,
-              m_blsHEntryXMin/Gaudi::Units::mm,
-              m_blsHEntryXMax/Gaudi::Units::mm,
-              m_blsHEntryZNbins,
-              m_blsHEntryXNbins );
-      myTitle = m_blsHTitlePrefix
-        + "Hit entry point in scintillator [mm], ZY plane";
-      plot2D( myMCHit->entry().z()/Gaudi::Units::mm,
-              myMCHit->entry().y()/Gaudi::Units::mm,
-              "HitEntryZY",
-              myTitle,
-              m_blsHEntryZMin/Gaudi::Units::mm,
-              m_blsHEntryZMax/Gaudi::Units::mm,
-              m_blsHEntryYMin/Gaudi::Units::mm,
-              m_blsHEntryYMax/Gaudi::Units::mm,
-              m_blsHEntryZNbins,
-              m_blsHEntryYNbins );
-      myTitle = m_blsHTitlePrefix
-        + "Hit energy deposited in scintillator [MeV]";
-      plot( ( myMCHit->time() + m_blsHEntryTimeOffset )/Gaudi::Units::ns,
-            "HitEnDepTime",
-            myTitle,
-            m_blsHEntryTimeMin,
-            m_blsHEntryTimeMax,
-            m_blsHEntryTimeNbins,
-            myMCHit->energy()/Gaudi::Units::MeV);
+      myTitle =
+          m_blsHTitlePrefix + "Hit entry point in scintillator [mm], XY plane";
+      h_HitEntryXY->fill(myMCHit->entry().x() / Gaudi::Units::mm,
+                         myMCHit->entry().y() / Gaudi::Units::mm);
+      myTitle =
+          m_blsHTitlePrefix + "Hit entry point in scintillator [mm], ZX plane";
+      h_HitEntryZX->fill(myMCHit->entry().z() / Gaudi::Units::mm,
+                         myMCHit->entry().x() / Gaudi::Units::mm);
+      myTitle =
+          m_blsHTitlePrefix + "Hit entry point in scintillator [mm], ZY plane";
+      h_HitEntryZY->fill(myMCHit->entry().z() / Gaudi::Units::mm,
+                         myMCHit->entry().y() / Gaudi::Units::mm);
+      myTitle =
+          m_blsHTitlePrefix + "Hit energy deposited in scintillator [MeV]";
+      h_HitEnDepTime->fill(
+          (myMCHit->time() + m_blsHEntryTimeOffset) / Gaudi::Units::ns,
+          myMCHit->energy() / Gaudi::Units::MeV);
       // This can as well be: anIt = upper_bound(myKey)
       anIt++;
-    } // end of: for ( t_blsMCParticle2MCHitMultimap::iterator oneMoreIt
+    }  // end of: for ( t_blsMCParticle2MCHitMultimap::iterator oneMoreIt
     // Add energy deposited by a single track to total energy deposited in event
     myEventEnDep += myTrackEnDep;
     // Make histograms for a per track quantities
-    myTitle = m_blsHTitlePrefix
-      + "Energy deposited per track [MeV]";
-    plot( myTrackEnDep/Gaudi::Units::MeV,
-          "TrackEnDep",
-          myTitle,
-          m_blsHTrackEnDepMin,
-          m_blsHTrackEnDepMax,
-          m_blsHTrackEnDepNbins);
-    myTitle = m_blsHTitlePrefix
-      + "Track length [cm]";
-    plot( myTrackLength/Gaudi::Units::cm,
-          "TrackLength",
-          myTitle,
-          m_blsHTrackLengthMin,
-          m_blsHTrackLengthMax,
-          m_blsHTrackLengthNbins);
-    myTitle = m_blsHTitlePrefix
-      + "Energy deposited per track unit length [MeV/cm]";
-    plot( (myTrackEnDep/Gaudi::Units::MeV)/(myTrackLength/Gaudi::Units::cm),
-          "TrackEnDepPerUnitLength",
-          myTitle,
-          m_blsHTrackEnDepMin,
-          m_blsHTrackEnDepMax,
-          m_blsHTrackEnDepNbins);
-  } // end of: for ( t_blsMCParticle2MCHitMultimap::iterator anIt
+    myTitle = m_blsHTitlePrefix + "Energy deposited per track [MeV]";
+    h_TrackEnDep->fill(myTrackEnDep / Gaudi::Units::MeV);
+    myTitle = m_blsHTitlePrefix + "Track length [cm]";
+    h_TrackLength->fill(myTrackLength / Gaudi::Units::cm);
+    myTitle =
+        m_blsHTitlePrefix + "Energy deposited per track unit length [MeV/cm]";
+    h_TrackEnDepPerUnitLength->fill((myTrackEnDep / Gaudi::Units::MeV) /
+                                    (myTrackLength / Gaudi::Units::cm));
+  }  // end of: for ( t_blsMCParticle2MCHitMultimap::iterator anIt
   // If DEBUG is switched on
-  if ( msgLevel(MSG::DEBUG) ) {
-    debug() << "Event no. "
-            << myMCHeader->evtNumber()
-            << ": Hits/Tracks = "
-            << myEventNumHits
-            << "/"
-            << myEventNumTracks
-            << ", EnDep = "
-            << myEventEnDep/Gaudi::Units::MeV
-            << endmsg;
-  } // end of: if ( msgLevel(MSG::DEBUG) )
+  if (msgLevel(MSG::DEBUG)) {
+    debug() << "Event no. " << myMCHeader.evtNumber()
+            << ": Hits/Tracks = " << myEventNumHits << "/" << myEventNumTracks
+            << ", EnDep = " << myEventEnDep / Gaudi::Units::MeV << endmsg;
+  }  // end of: if ( msgLevel(MSG::DEBUG) )
   // Make histograms for a per event quantities
-  myTitle = m_blsHTitlePrefix
-    + "Number of hits per event ";
-  plot( myEventNumHits,
-        "EventNumHits",
-        myTitle,
-        m_blsHEventNumTracksMin,
-        m_blsHEventNumTracksMax,
-        m_blsHEventNumTracksNbins );
-  myTitle = m_blsHTitlePrefix
-      + "Number of tracks per event ";
-  plot( myEventNumTracks,
-        "EventNumTracks",
-        myTitle,
-        m_blsHEventNumTracksMin,
-        m_blsHEventNumTracksMax,
-        m_blsHEventNumTracksNbins );
-  myTitle = m_blsHTitlePrefix
-    + "Energy deposited per event [MeV]";
-  plot( myEventEnDep/Gaudi::Units::MeV,
-        "EventEnDep",
-        myTitle,
-        m_blsHTrackEnDepMin,
-        m_blsHTrackEnDepMax,
-        m_blsHTrackEnDepNbins);
+  myTitle = m_blsHTitlePrefix + "Number of hits per event ";
+  h_EventNumHits->fill(myEventNumHits);
+  myTitle = m_blsHTitlePrefix + "Number of tracks per event ";
+  h_EventNumTracks->fill(myEventNumTracks);
+  myTitle = m_blsHTitlePrefix + "Energy deposited per event [MeV]";
+  h_EventEnDep->fill(myEventEnDep / Gaudi::Units::MeV);
   // Count number of hits/tracks per run
   m_blsHits += myEventNumHits;
   m_blsTracks += myEventNumTracks;
   // Plot global per run quantities
-  myTitle = m_blsHTitlePrefix
-      + "Number of hits in event";
-  plot( myMCHeader->evtNumber(),
-        "RunNumHits",
-        myTitle,
-        m_blsHEventNumMin,
-        m_blsHEventNumMax,
-        m_blsHEventNumNbins,
-        myEventNumHits);
-  myTitle = m_blsHTitlePrefix
-      + "Number of tracks in event";
-  plot( myMCHeader->evtNumber(),
-        "RunNumTracks",
-        myTitle,
-        m_blsHEventNumMin,
-        m_blsHEventNumMax,
-        m_blsHEventNumNbins,
-        myEventNumTracks);
-  myTitle = m_blsHTitlePrefix
-    + "Energy deposited in event [MeV]";
-  plot( myMCHeader->evtNumber(),
-        "RunEnDep",
-        myTitle,
-        m_blsHEventNumMin,
-        m_blsHEventNumMax,
-        m_blsHEventNumNbins,
-        myEventEnDep/Gaudi::Units::MeV);
-  // Final global return
-  return StatusCode::SUCCESS;
-} // end of: BlsHitChecker::execute()
+  myTitle = m_blsHTitlePrefix + "Number of hits in event";
+  h_RunNumHits->fill(myMCHeader.evtNumber(), myEventNumHits);
+  myTitle = m_blsHTitlePrefix + "Number of tracks in event";
+  h_RunNumTracks->fill(myMCHeader.evtNumber(), myEventNumTracks);
+  myTitle = m_blsHTitlePrefix + "Energy deposited in event [MeV]";
+  h_RunEnDep->fill(myMCHeader.evtNumber(), myEventEnDep / Gaudi::Units::MeV);
+}
 
 //=============================================================================
 //  Finalize
 //=============================================================================
 
-StatusCode BlsHitChecker::finalize() {
-  if ( msgLevel(MSG::INFO) )
-    // Print numbers for Hits and Tracks to the common output
-    info() << "Hits/Tracks: "
-           << m_blsHits
-           << "/"
-           << m_blsTracks << endmsg; 
-  return GaudiAlgorithm::finalize();  // must be called after all other actions
-} // end of: BlsHitChecker::finalize()
-
-//=============================================================================
+void BlsHitChecker::bookHistograms() {
+  std::string myTitle;
+  myTitle =
+      m_blsHTitlePrefix + "Hit entry point in scintillator [mm], XY plane";
+  h_HitEntryXY =
+      book2D("HitEntryXY", myTitle, m_blsHEntryXMin / Gaudi::Units::mm,
+             m_blsHEntryXMax / Gaudi::Units::mm, m_blsHEntryXNbins,
+             m_blsHEntryYMin / Gaudi::Units::mm,
+             m_blsHEntryYMax / Gaudi::Units::mm, m_blsHEntryYNbins);
+  myTitle =
+      m_blsHTitlePrefix + "Hit entry point in scintillator [mm], ZX plane";
+  h_HitEntryZX =
+      book2D("HitEntryZX", myTitle, m_blsHEntryZMin / Gaudi::Units::mm,
+             m_blsHEntryZMax / Gaudi::Units::mm, m_blsHEntryZNbins,
+             m_blsHEntryXMin / Gaudi::Units::mm,
+             m_blsHEntryXMax / Gaudi::Units::mm, m_blsHEntryXNbins);
+  myTitle =
+      m_blsHTitlePrefix + "Hit entry point in scintillator [mm], ZY plane";
+  h_HitEntryZY =
+      book2D("HitEntryZY", myTitle, m_blsHEntryZMin / Gaudi::Units::mm,
+             m_blsHEntryZMax / Gaudi::Units::mm, m_blsHEntryZNbins,
+             m_blsHEntryYMin / Gaudi::Units::mm,
+             m_blsHEntryYMax / Gaudi::Units::mm, m_blsHEntryYNbins);
+  myTitle = m_blsHTitlePrefix + "Hit energy deposited in scintillator [MeV]";
+  h_HitEnDepTime = book("HitEnDepTime", myTitle, m_blsHEntryTimeMin,
+                        m_blsHEntryTimeMax, m_blsHEntryTimeNbins);
+  myTitle = m_blsHTitlePrefix + "Energy deposited per track [MeV]";
+  h_TrackEnDep = book("TrackEnDep", myTitle, m_blsHTrackEnDepMin,
+                      m_blsHTrackEnDepMax, m_blsHTrackEnDepNbins);
+  myTitle = m_blsHTitlePrefix + "Track length [cm]";
+  h_TrackLength = book("TrackLength", myTitle, m_blsHTrackLengthMin,
+                       m_blsHTrackLengthMax, m_blsHTrackLengthNbins);
+  myTitle =
+      m_blsHTitlePrefix + "Energy deposited per track unit length [MeV/cm]";
+  h_TrackEnDepPerUnitLength =
+      book("TrackEnDepPerUnitLength", myTitle, m_blsHTrackEnDepMin,
+           m_blsHTrackEnDepMax, m_blsHTrackEnDepNbins);
+  myTitle = m_blsHTitlePrefix + "Number of hits per event ";
+  h_EventNumHits = book("EventNumHits", myTitle, m_blsHEventNumTracksMin,
+                        m_blsHEventNumTracksMax, m_blsHEventNumTracksNbins);
+  myTitle = m_blsHTitlePrefix + "Number of tracks per event ";
+  h_EventNumTracks = book("EventNumTracks", myTitle, m_blsHEventNumTracksMin,
+                          m_blsHEventNumTracksMax, m_blsHEventNumTracksNbins);
+  myTitle = m_blsHTitlePrefix + "Energy deposited per event [MeV]";
+  h_EventEnDep = book("EventEnDep", myTitle, m_blsHTrackEnDepMin,
+                      m_blsHTrackEnDepMax, m_blsHTrackEnDepNbins);
+  // Plot global per run quantities
+  myTitle = m_blsHTitlePrefix + "Number of hits in event";
+  h_RunNumHits = book("RunNumHits", myTitle, m_blsHEventNumMin,
+                      m_blsHEventNumMax, m_blsHEventNumNbins);
+  myTitle = m_blsHTitlePrefix + "Number of tracks in event";
+  h_RunNumTracks = book("RunNumTracks", myTitle, m_blsHEventNumMin,
+                        m_blsHEventNumMax, m_blsHEventNumNbins);
+  myTitle = m_blsHTitlePrefix + "Energy deposited in event [MeV]";
+  h_RunEnDep = book("RunEnDep", myTitle, m_blsHEventNumMin, m_blsHEventNumMax,
+                    m_blsHEventNumNbins);
+}
diff --git a/Bls/BlsMoniSim/src/BlsHitChecker.h b/Bls/BlsMoniSim/src/BlsHitChecker.h
index 11ac2f9f2..41027650e 100644
--- a/Bls/BlsMoniSim/src/BlsHitChecker.h
+++ b/Bls/BlsMoniSim/src/BlsHitChecker.h
@@ -1,76 +1,4 @@
 // $Id: BlsHitChecker.h,v 1.1.1.2 2010-03-10 17:38:47 vtalanov Exp $
 #ifndef BLSHITCHECKER_H
 #define BLSHITCHECKER_H 1
-
-// Include files
-
-// from Gaudi
-#include "GaudiAlg/GaudiTupleAlg.h"
-#include "Event/MCHit.h"
-
-// from STL
-#include <map>
-
-/** @class BlsHitChecker BlsHitChecker.h
- *
- *
- *  @author Vadim Talanov
- *  @date   2010-02-06
- */
-
-class BlsHitChecker : public GaudiTupleAlg {
-public:
-  /// Standard constructor
-  BlsHitChecker( const std::string& name, ISvcLocator* pSvcLocator );
-
-  virtual ~BlsHitChecker( ); ///< Destructor
-
-  StatusCode initialize() override;    ///< Algorithm initialization
-  StatusCode execute   () override;    ///< Algorithm execution
-  StatusCode finalize  () override;    ///< Algorithm finalization
-
-protected:
-
-private:
-
-  LHCb::MCHits* m_blsMCHits;
-    std::string m_blsHitsLocation;
-           bool m_blsAOn;
-           bool m_blsCOn;
-    std::string m_blsHTitlePrefix;
-
-         double m_blsHEntryXMin;
-         double m_blsHEntryXMax;
-  unsigned long m_blsHEntryXNbins;
-         double m_blsHEntryYMin;
-         double m_blsHEntryYMax;
-  unsigned long m_blsHEntryYNbins;
-         double m_blsHEntryZMin;
-         double m_blsHEntryZMax;
-  unsigned long m_blsHEntryZNbins;
-         double m_blsHEntryTimeOffset;
-         double m_blsHEntryTimeMin;
-         double m_blsHEntryTimeMax;
-  unsigned long m_blsHEntryTimeNbins;
-         double m_blsHTrackEnDepMin;
-         double m_blsHTrackEnDepMax;
-  unsigned long m_blsHTrackEnDepNbins;
-         double m_blsHTrackLengthMin;
-         double m_blsHTrackLengthMax;
-  unsigned long m_blsHTrackLengthNbins;
-         double m_blsHEventNumTracksMin;
-         double m_blsHEventNumTracksMax;
-  unsigned long m_blsHEventNumTracksNbins;
-         double m_blsHEventNumMin;
-         double m_blsHEventNumMax;
-  unsigned long m_blsHEventNumNbins;
-
-  unsigned long m_blsHits;
-  unsigned long m_blsTracks;
-
-   typedef std::multimap < const LHCb::MCParticle*,
-                            LHCb::MCHit* >
-                            t_blsMCParticle2MCHitMultimap;
-
-};
-#endif // BLSHITCHECKER_H
+#endif  // BLSHITCHECKER_H
diff --git a/Sim/DD4hepCnv/CMakeLists.txt b/Sim/DD4hepCnv/CMakeLists.txt
index d4c62fa7a..7361749b8 100644
--- a/Sim/DD4hepCnv/CMakeLists.txt
+++ b/Sim/DD4hepCnv/CMakeLists.txt
@@ -9,6 +9,7 @@ gaudi_depends_on_subdirs(Sim/GiGaMTFactories
                          Sim/GiGaMTGeo
                          DD4hepDDG4Ext
                          Sim/GiGaMTDD4hep
+                         Sim/GaussTracker
                          Det/LbDD4hep)
 
 find_package(Boost)
@@ -35,4 +36,4 @@ message(STATUS "DD4hepDDG4_LIBRARIES: ${DD4hepDDG4_LIBRARIES}")
 gaudi_add_module(DD4hepCnv
         src/component/*.cpp
         INCLUDE_DIRS Tools/ClhepTools GiGaMTGeo LbDD4hep DD4hep
-        LINK_LIBRARIES ${GEANT4_LIBS} DD4hep ${DD4hep_COMPONENT_LIBRARIES} ROOT GiGaMTCoreRunLib GiGaMTDD4hepLib) 
+        LINK_LIBRARIES ${GEANT4_LIBS} DD4hep ${DD4hep_COMPONENT_LIBRARIES} ROOT GiGaMTCoreRunLib GiGaMTDD4hepLib GaussTrackerLib) 
diff --git a/Sim/DD4hepCnv/src/component/DD4hepCnvSvc.cpp b/Sim/DD4hepCnv/src/component/DD4hepCnvSvc.cpp
index c3d307242..8c432e4ff 100644
--- a/Sim/DD4hepCnv/src/component/DD4hepCnvSvc.cpp
+++ b/Sim/DD4hepCnv/src/component/DD4hepCnvSvc.cpp
@@ -110,13 +110,6 @@ StatusCode DD4hepCnvSvc::initialize() {
   auto& g4map = dd4hep::sim::Geant4Mapping::instance();
   dd4hep::setPrintLevel(DD4hepGaudiMessaging::Convert(msgLevel()));
   dd4hep::DetElement world = m_dd4Svc->getDetector().world();
-  if ( msgLevel( MSG::DEBUG ) ) {
-    auto & children =world.children();
-    debug() << "Children of DD4hep world DetElement:" << endmsg;
-    for(auto & child: children){
-      debug() << " --- " << child.first  << " ::: " << child.second.name() << endmsg;
-    }
-  }
   dd4hep::sim::Geant4Converter conv(dd4hep::Detector::getInstance(), DD4hepGaudiMessaging::Convert(msgLevel()));
   conv.debugMaterials = m_debugMaterials.value();
   conv.debugElements = m_debugElements.value();
@@ -133,6 +126,27 @@ StatusCode DD4hepCnvSvc::initialize() {
   m_world_root = geoinfo->world();
   // Create Geant4 volume manager only if not yet available
   g4map.volumeManager();
+  // Printout all active volumes and assigned sensitive detectors from dd4hep
+  if (msgLevel(MSG::DEBUG)) {
+      debug() << "Stored paths in volume manager: " << endmsg;
+      for(auto & pp: g4map.volumeManager()->g4Paths){
+        debug() << "/";
+        for(auto & pv:pp.first){
+          debug() << pv->GetName() << "/";
+        }
+        debug() << " ID:" << pp.second << endmsg;
+      }
+      for (auto& [dd4hep_volume, g4_volume] : g4map.data().g4Volumes) {
+          if (!dd4hep_volume.isValid() || !dd4hep_volume.isSensitive()) {
+              continue;
+          }
+          auto dd4hep_sensdet_name = dd4hep_volume.sensitiveDetector().name();
+          debug() << "Active volume '" << dd4hep_volume.name() << "' SensDet: '"
+                  << dd4hep_sensdet_name << "'" << endmsg;
+          if (dd4hep_volume.isSensitive()) {
+          }
+      }
+  }
 
   // We now loop over the existing logical volume mappings and extract the sensitive detector knowledge
   // from the DD4hep volumes and map them to the requested Gaussino factories
diff --git a/Sim/Gauss/python/Gauss/Geometry/BLS.py b/Sim/Gauss/python/Gauss/Geometry/BLS.py
index f46bdd564..0418c198e 100644
--- a/Sim/Gauss/python/Gauss/Geometry/BLS.py
+++ b/Sim/Gauss/python/Gauss/Geometry/BLS.py
@@ -4,10 +4,30 @@ from Gauss.Geometry.Helpers import subdetector
 
 
 @subdetector
-class BCM(det_base):
+class BLS(det_base):
 
     __slots__ = {}
 
+    def ApplyDetectorDD4hep(self, basePieces, detPieces):
+        # Configuring the DD4hep detector conversion.
+        # 1. Add the mapping to have the DD4hepCnvSvc instrument
+        # the G4 volume with the correct sensdet factory if marked with a
+        # dd4hep sensitive detector named VP
+        from Configurables import DD4hepCnvSvc
+        mappings = DD4hepCnvSvc().getProp('SensDetMappings')
+        mappings['Bls'] = 'GiGaSensDetTrackerDD4hep/BlsSDet'
+        DD4hepCnvSvc().SensDetMappings = mappings
+
+        # Add the necessary dd4hep includes for the VP. Also added all the
+        # dependencies for material definitions that were identified using
+        # trial and error. As the list is made unique before being added to
+        # the xml this should be fine if they appear in multiple places
+        from Gauss.Geometry import LHCbGeo
+        go = LHCbGeo._listOfXMLIncludes_
+
+        go += ["Bls/parameters.xml"]
+        go += ["Bls/detector.xml"]
+
     def ApplyDetectorDetDesc(self, basePieces, detPieces):
         from Gauss.Geometry import LHCbGeo
         # Add the non-standard pieces of the BeforeMagnet region.
@@ -28,3 +48,68 @@ class BCM(det_base):
                 if piece in detPieces[region]:
                     continue
                 detPieces[region] += [piece]
+
+    def SetupExtractionImpl(self, slot=''):
+        from Configurables import GetTrackerHitsAlg
+        self.simconf_name = 'Bls'
+        region = "BeforeMagnetRegion"
+        det = "Bls"
+        alg = GetTrackerHitsAlg(
+            'Get'+det+'Hits'+slot,
+            MCHitsLocation='MC/'+det+'/Hits',
+            CollectionName=det + 'SDet/Hits',
+        )
+        # Only add the detectors if we are not using DD4hep so that the ID is
+        # looked up using DetDesc
+        if not self.getProp('UseDD4hep'):
+            alg.Detectors = ['/dd/Structure/LHCb/' + region + '/' + det]
+        from Configurables import ApplicationMgr
+        ApplicationMgr().TopAlg += [alg]
+
+    def SetupMonitor(self, slot=''):
+        from GaudiKernel import SystemOfUnits
+        from Configurables import BlsHitChecker
+        moni = BlsHitChecker("BlsHitCheckerAll"+slot)
+        from Configurables import ApplicationMgr
+        moni.HistoDir = "BlsHitChecker/BlsHitCheckerAll"
+        moni.BlsAOn = True
+        moni.BlsCOn = True
+        moni.HistogramTitlePrefix = "BlsA+C: "
+        moni.EntryXMin = -150.0 * SystemOfUnits.mm
+        moni.EntryXMax = +150.0 * SystemOfUnits.mm
+        moni.EntryXNbins = 300
+        moni.EntryYMin = -150.0 * SystemOfUnits.mm
+        moni.EntryYMax = +150.0 * SystemOfUnits.mm
+        moni.EntryYNbins = 300
+        moni.EntryZMin = -2200.0 * SystemOfUnits.mm
+        moni.EntryZMax = -1900.0 * SystemOfUnits.mm
+        moni.EntryZNbins = 300
+        moni.EntryTimeOffset = +0.0 * SystemOfUnits.ns
+        moni.EntryTimeMin = -50.0 * SystemOfUnits.ns
+        moni.EntryTimeMax = +50.0 * SystemOfUnits.ns
+        moni.EntryTimeNbins = 100
+        moni.EventNumMin = 0.0
+        moni.EventNumMax = 1000.0
+        moni.EventNumNbins = 1000
+        moni.EventNumTracksMin = 0.0
+        moni.EventNumTracksMax = 50.0
+        moni.EventNumTracksNbins = 50
+        moni.TrackEnDepMin = 0.0
+        moni.TrackEnDepMax = 50.0
+        moni.TrackEnDepNbins = 50
+        moni.TrackLengthMin = 0.0
+        moni.TrackLengthMax = 7.0
+        moni.TrackLengthNbins = 70
+        ApplicationMgr().TopAlg += [moni]
+
+        moni = BlsHitChecker("BlsHitCheckerBlsA"+slot)
+        moni.HistoDir = "BlsHitChecker/BlsHitCheckerBlsA"
+        moni.BlsAOn = True
+        moni.HistogramTitlePrefix = "BlsA: "
+        ApplicationMgr().TopAlg += [moni]
+
+        moni = BlsHitChecker("BlsHitCheckerBlsC"+slot)
+        moni.HistoDir = "BlsHitChecker/BlsHitCheckerBlsC"
+        moni.BlsCOn = True
+        moni.HistogramTitlePrefix = "BlsC: "
+        ApplicationMgr().TopAlg += [moni]
diff --git a/Sim/Gauss/python/Gauss/Geometry/Configuration.py b/Sim/Gauss/python/Gauss/Geometry/Configuration.py
index a36741323..2fca3d942 100644
--- a/Sim/Gauss/python/Gauss/Geometry/Configuration.py
+++ b/Sim/Gauss/python/Gauss/Geometry/Configuration.py
@@ -31,8 +31,8 @@ class LHCbGeo(LHCbConfigurableUser):
         "Debug": False,
         "DD4hep": False,
         "SaveGDMLFile": "",
-        "SensDetMap":{},
-        "ExtraGeoTools":[]
+        "SensDetMap": {},
+        "ExtraGeoTools": []
         }
 
     _detectorsDefaults = {
@@ -54,6 +54,8 @@ class LHCbGeo(LHCbConfigurableUser):
     # List of geometry objects which will be converted, it's content is used in
     # GaussGeo or in GiGaInputStream if GiGaGeo is used for conversion
     _listOfGeoObjects_ = []
+    # List of DD4hep XML includes
+    _listOfXMLIncludes_ = []
 
     def __init__(self, name=Configurable.DefaultName, **kwargs):
         kwargs["name"] = name
@@ -97,7 +99,6 @@ class LHCbGeo(LHCbConfigurableUser):
         checkIncompatibleDetectors()
         defineGeoBasePieces(basePieces)
 
-
         from Gauss.Geometry.Helpers import getsubdetector
         detectors_geo = self.getProp("DetectorGeo")["Detectors"]
         detectors_sim = self.getProp("DetectorSim")["Detectors"]
@@ -111,7 +112,7 @@ class LHCbGeo(LHCbConfigurableUser):
             getsubdetector(det).Monitor = True
 
         # BeamPipe
-        # getsubdetector('BeamPipe').ApplyDetector(basePieces, detPieces)
+        getsubdetector('BeamPipe').ApplyDetector(basePieces, detPieces)
 
         for det in detectors_geo:
             getsubdetector(det).ApplyDetector(basePieces, detPieces)
@@ -124,19 +125,7 @@ class LHCbGeo(LHCbConfigurableUser):
         for det in detectors_geo:
             getsubdetector(det).ApplyStream()
 
-        # getsubdetector("Magnet").defineMagnetGeoField()
-
-        # FIXME: those calo option files
-        # Seperate Calo opts
-        # Returns a list containing all the elments common to both lists
-        # if self.getProp('UseGaussGeo'):
-        # if [det for det in ['Spd', 'Prs', 'Ecal', 'Hcal'] if det in
-        # self.getProp('DetectorGeo')['Detectors']]:  # NOQA
-        # importOptions("$GAUSSCALOROOT/options/GaussGeo-Calo.py")
-        # else:
-        # if [det for det in ['Spd', 'Prs', 'Ecal', 'Hcal'] if det in
-        # self.getProp('DetectorGeo')['Detectors']]:  # NOQA
-        # importOptions("$GAUSSCALOROOT/options/Calo.opts")
+        getsubdetector("Magnet").defineMagnetGeoField()
 
         self.PrintDebugDump(detPieces, basePieces)
 
@@ -157,6 +146,11 @@ class LHCbGeo(LHCbConfigurableUser):
             gaussgeo.AlignAllDetectors = True
             for el in self._listOfGeoObjects_:
                 gaussgeo.GeoItemsNames.append(el)
+        else:
+            from Gauss.Geometry import xml_writer
+            from Configurables import LHCb__Det__LbDD4hep__DD4hepSvc
+            LHCb__Det__LbDD4hep__DD4hepSvc().DescriptionLocation = \
+                xml_writer.create_xml(self._listOfXMLIncludes_)
 
         self.MakeItTalkToGaussino()
 
@@ -203,7 +197,7 @@ class LHCbGeo(LHCbConfigurableUser):
         svc.RegionsDefinitionDbLocation = xmlfile
 
     def PrintDebugDump(self, detPieces, basePieces):
-        if self.getProp("Debug"):
+        if self.getProp("Debug") and not self.getProp("DD4hep"):
             print "\nDEBUG Detector Geometry Elements:"
             print "\nkey : detPieces[key]"
             for key in detPieces.keys():
diff --git a/Sim/Gauss/python/Gauss/Geometry/VP.py b/Sim/Gauss/python/Gauss/Geometry/VP.py
index 3a4b5ef65..5b3b11a95 100644
--- a/Sim/Gauss/python/Gauss/Geometry/VP.py
+++ b/Sim/Gauss/python/Gauss/Geometry/VP.py
@@ -9,11 +9,29 @@ class VP(det_base):
     __slots__ = {}
 
     def ApplyDetectorDD4hep(self, basePieces, detPieces):
+        # Configuring the DD4hep detector conversion.
+        # 1. Add the mapping to have the DD4hepCnvSvc instrument
+        # the G4 volume with the correct sensdet factory if marked with a
+        # dd4hep sensitive detector named VP
         from Configurables import DD4hepCnvSvc
         mappings = DD4hepCnvSvc().getProp('SensDetMappings')
-        mappings['VP'] = 'GiGaSensDetTracker/VPSDet'
+        mappings['VP'] = 'GiGaSensDetTrackerDD4hep/VPSDet'
         DD4hepCnvSvc().SensDetMappings = mappings
 
+        # Add the necessary dd4hep includes for the VP. Also added all the
+        # dependencies for material definitions that were identified using
+        # trial and error. As the list is made unique before being added to
+        # the xml this should be fine if they appear in multiple places
+        from Gauss.Geometry import LHCbGeo
+        go = LHCbGeo._listOfXMLIncludes_
+
+        go += ["Pipe/parameters.xml"]
+        go += ["Rich1/materials.xml"]
+        go += ["VP/parameters.xml"]
+        go += ["VP/visualization.xml"]
+        go += ["VP/detector.xml"]
+        go += ["VP/conditions.xml"]
+
     def ApplyDetectorDetDesc(self, basePieces, detPieces):
         BeamPipe.removeBeamPipeElements("velo")
         if 'BeforeMagnetRegion' in detPieces:
@@ -28,8 +46,9 @@ class VP(det_base):
             'Get'+det+'Hits'+slot,
             MCHitsLocation='MC/'+det+'/Hits',
             CollectionName=det + 'SDet/Hits',
-            Detectors=['/dd/Structure/LHCb/' + region + '/' + det]
         )
+        if not self.getProp('UseDD4hep'):
+            alg.Detectors = ['/dd/Structure/LHCb/' + region + '/' + det]
         from Configurables import ApplicationMgr
         ApplicationMgr().TopAlg += [alg]
 
diff --git a/Sim/Gauss/python/Gauss/Geometry/__init__.py b/Sim/Gauss/python/Gauss/Geometry/__init__.py
index 4d1ef0029..24dc43f26 100644
--- a/Sim/Gauss/python/Gauss/Geometry/__init__.py
+++ b/Sim/Gauss/python/Gauss/Geometry/__init__.py
@@ -14,6 +14,8 @@ from Gauss.Geometry.UT import *
 from Gauss.Geometry.Magnet import *
 from Gauss.Geometry.Muon import *
 from Gauss.Geometry.HC import *
+from Gauss.Geometry.BLS import *
+from Gauss.Geometry.BCM import *
 
 __all__ = [
     'LHCbGeo', 'BeamPipe'
diff --git a/Sim/Gauss/python/Gauss/Geometry/xml_writer.py b/Sim/Gauss/python/Gauss/Geometry/xml_writer.py
new file mode 100644
index 000000000..137b41501
--- /dev/null
+++ b/Sim/Gauss/python/Gauss/Geometry/xml_writer.py
@@ -0,0 +1,71 @@
+import xml.etree.ElementTree as ET
+from xml.dom import minidom
+from collections import OrderedDict
+from Gaudi.Configuration import log
+import tempfile
+import os
+
+
+# Combine the includes into a valid LHCb DD4hep xml and return name of temporary
+# file
+def create_xml(includesfiles):
+    unique_includes = list(OrderedDict.fromkeys(includesfiles))
+    detectorroot = os.path.join(os.environ['DETECTOR_PROJECT_ROOT'], 'compact/')
+
+    def addroot(p):
+        if p[0] != '.' and p[0] != '/':
+            return detectorroot + p
+        return p
+
+    root = ET.Element("lccdd")
+    ET.SubElement(root, "std_conditions", type="STP")
+    debug = ET.SubElement(root, "debug")
+    ET.SubElement(debug, "type", name="includes", value="0")
+    ET.SubElement(debug, "type", name="materials", value="0")
+    includes = ET.SubElement(root, "includes")
+    ET.SubElement(includes, "gdmlFile", ref=addroot("defaults.xml"))
+    define = ET.SubElement(root, "define")
+    ET.SubElement(define, "constant", name="Bls:parent",
+                  value="/world/BeforeMagnetRegion/BeforeVelo", type="string")
+    ET.SubElement(define, "constant", name="BcmUp:parent",
+                  value="/world/BeforeMagnetRegion/BeforeVelo", type="string")
+    ET.SubElement(define, "constant", name="BcmDown:parent",
+                  value="/world/DownstreamRegion/AfterMuon", type="string")
+    ET.SubElement(define, "constant", name="GValve:parent",
+                  value="/world/BeforeMagnetRegion/BeforeVelo", type="string")
+    ET.SubElement(define, "constant", name="MBXWUp:parent",
+                  value="/world/UpstreamRegion", type="string")
+    ET.SubElement(define, "constant", name="Cavern:parent",
+                  value="/world/Infrastructure", type="string")
+    ET.SubElement(define, "constant", name="Tunnel:parent",
+                  value="/world/Infrastructure", type="string")
+    ET.SubElement(define, "constant", name="Bunker:parent",
+                  value="/world/Infrastructure", type="string")
+    ET.SubElement(define, "constant", name="VP:parent",
+                  value="/world/BeforeMagnetRegion", type="string")
+    ET.SubElement(define, "constant", name="UT:parent",
+                  value="/world/BeforeMagnetRegion", type="string")
+    ET.SubElement(define, "constant", name="FT:parent",
+                  value="/world/AfterMagnetRegion/T", type="string")
+    ET.SubElement(define, "constant", name="Magnet:ignore", value="0")
+    ET.SubElement(define, "constant", name="UpstreamRegion:ignore", value="0")
+    ET.SubElement(define, "constant", name="BeforeMagnetRegion:ignore", value="0")  # NOQA
+    ET.SubElement(define, "constant", name="MagnetRegion:ignore", value="0")
+    ET.SubElement(define, "constant", name="AfterMagnetRegion:ignore", value="0")  # NOQA
+    ET.SubElement(define, "constant", name="DownstreamRegion:ignore", value="0")
+
+    ET.SubElement(root, "include", ref=addroot("global/conditions.xml"))
+
+    # FIXME: Regions need something from this file
+    ET.SubElement(root, "include", ref=addroot("T/parameters.xml"))
+    ET.SubElement(root, "include", ref=addroot("Regions/detector.xml"))
+
+    for inc in unique_includes:
+        ET.SubElement(root, "include", ref=addroot(inc))
+
+    _, tmpfile = tempfile.mkstemp('.xml')
+    xmlstr = minidom.parseString(ET.tostring(root)).toprettyxml(indent="   ")
+    with open(tmpfile, "w") as f:
+        f.write(xmlstr)
+    log.info('Wrote xml file to {}'.format(tmpfile))
+    return tmpfile
diff --git a/Sim/Gauss/python/Gauss/Physics.py b/Sim/Gauss/python/Gauss/Physics.py
index da653039a..1f45f3a88 100644
--- a/Sim/Gauss/python/Gauss/Physics.py
+++ b/Sim/Gauss/python/Gauss/Physics.py
@@ -163,6 +163,8 @@ class G4Physics(LHCbConfigurableUser):
             for hp in _all[hadronPhys]:
                 addConstructor(pl, *hp)
             return True
+        elif hadronPhys == '':
+            log.warning("No hadron physics list")
         else:
             raise RuntimeError("Unknown Hadron PhysicsList "
                                "chosen ('%s')" % hadronPhys)
@@ -178,8 +180,8 @@ class G4Physics(LHCbConfigurableUser):
             else:
                 self.defineRichPhys(pl)
         else:
-            log.warning("The lhcb-related physics (RICH processed,"
-                        "UnknownParticles) is disabled")
+            log.warning("The lhcb-related physics (RICH processed)"
+                        "is disabled")
 
     def AddOtherPhysics(self, pl):
         otherPhys = self.getProp('Other')
-- 
GitLab


From ef2e8ca3c709d2fd9433b2a443f72a2f5e0a915d Mon Sep 17 00:00:00 2001
From: Dominik Muller <dominik.muller@cern.ch>
Date: Fri, 24 Jul 2020 15:49:39 +0200
Subject: [PATCH 58/90] Support for global magnetic field and simplified tool
 handling in dd4hep svc

---
 Sim/DD4hepCnv/src/component/DD4hepCnvSvc.cpp  | 294 ++++++++++--------
 .../python/Gauss/Geometry/Configuration.py    |   2 +-
 Sim/Gauss/python/Gauss/Geometry/Magnet.py     |  35 ++-
 3 files changed, 192 insertions(+), 139 deletions(-)

diff --git a/Sim/DD4hepCnv/src/component/DD4hepCnvSvc.cpp b/Sim/DD4hepCnv/src/component/DD4hepCnvSvc.cpp
index 8c432e4ff..96571808b 100644
--- a/Sim/DD4hepCnv/src/component/DD4hepCnvSvc.cpp
+++ b/Sim/DD4hepCnv/src/component/DD4hepCnvSvc.cpp
@@ -1,8 +1,8 @@
 // Gaudi includes
+#include "GaudiKernel/IDataManagerSvc.h"
+#include "GaudiKernel/IRegistry.h"
 #include "GaudiKernel/IToolSvc.h"
 #include "GaudiKernel/SmartDataPtr.h"
-#include "GaudiKernel/IRegistry.h"
-#include "GaudiKernel/IDataManagerSvc.h"
 #include "GaudiKernel/SmartIF.h"
 
 // GiGa
@@ -12,15 +12,14 @@
 //#include "GiGa/IGiGaFieldMgr.h"
 //#include "GiGa/IGDMLReader.h"
 
-
 #include "Kernel/IPropertyConfigSvc.h"
 
 // Gaudi includes
-#include "GaudiKernel/Service.h"
 #include "GaudiKernel/IIncidentSvc.h"
-#include "GiGaMTFactories/GiGaFactoryBase.h"
-#include "Geant4/G4VSensitiveDetector.hh"
+#include "GaudiKernel/Service.h"
 #include "GaudiKernel/Transform3DTypes.h"
+#include "Geant4/G4VSensitiveDetector.hh"
+#include "GiGaMTFactories/GiGaFactoryBase.h"
 
 #include "GiGaMTGeo/IGiGaMTGeoSvc.h"
 #include "LbDD4hep/IDD4hepSvc.h"
@@ -40,9 +39,9 @@
 // 2020-6-15 : Dominik Muller
 // ============================================================================
 
-class DD4hepCnvSvc: public extends<Service, IGiGaMTGeoSvc> {
+class DD4hepCnvSvc : public extends<Service, IGiGaMTGeoSvc> {
  public:
-   using extends::extends;
+  using extends::extends;
   virtual ~DD4hepCnvSvc() = default;
 
   // Service pure member functions
@@ -54,7 +53,6 @@ class DD4hepCnvSvc: public extends<Service, IGiGaMTGeoSvc> {
   void constructSDandField() override;
 
  private:
-
   // G4 geometry variables
   G4VPhysicalVolume* m_world_root{nullptr};
   dd4hep::sim::Geant4GeometryInfo* geoinfo{nullptr};
@@ -62,38 +60,47 @@ class DD4hepCnvSvc: public extends<Service, IGiGaMTGeoSvc> {
   std::string m_world_pv_name;
   std::string m_world_lv_name;
 
-  Gaudi::Property<bool> m_debugMaterials  {this, "DebugMaterials", false};
-  Gaudi::Property<bool> m_debugElements   {this, "DebugElements", false};
-  Gaudi::Property<bool> m_debugShapes     {this, "DebugShapes", false};
-  Gaudi::Property<bool> m_debugVolumes    {this, "DebugVolumes", false};
-  Gaudi::Property<bool> m_debugPlacements {this, "DebugPlacements", false};
-  Gaudi::Property<bool> m_debugRegions    {this, "DebugRegions", false};
-  Gaudi::Property<std::map<std::string, std::string>> m_sensdetmappings    {this, "SensDetMappings", {}};
-  ServiceHandle<LHCb::Det::LbDD4hep::IDD4hepSvc> m_dd4Svc{this, "DD4hepSvc", "LHCb::Det::LbDD4hep::DD4hepSvc"};
+  Gaudi::Property<bool> m_debugMaterials{this, "DebugMaterials", false};
+  Gaudi::Property<bool> m_debugElements{this, "DebugElements", false};
+  Gaudi::Property<bool> m_debugShapes{this, "DebugShapes", false};
+  Gaudi::Property<bool> m_debugVolumes{this, "DebugVolumes", false};
+  Gaudi::Property<bool> m_debugPlacements{this, "DebugPlacements", false};
+  Gaudi::Property<bool> m_debugRegions{this, "DebugRegions", false};
+  Gaudi::Property<std::map<std::string, std::string>> m_sensdetmappings{
+      this, "SensDetMappings", {}};
+  ServiceHandle<LHCb::Det::LbDD4hep::IDD4hepSvc> m_dd4Svc{
+      this, "DD4hepSvc", "LHCb::Det::LbDD4hep::DD4hepSvc"};
+
+  Gaudi::Property<std::string> m_mag_field_mgr{this, "FieldManager", ""};
 
   // Services accessors
-  inline ISvcLocator * svcLocator() const { return serviceLocator(); }
+  inline ISvcLocator* svcLocator() const { return serviceLocator(); }
+  StatusCode register_mag_field(const std::string& name, G4LogicalVolume*);
+  StatusCode register_sensitive(const std::string& name, G4LogicalVolume*);
 
   // Extract the object type name
   template <class T>
   inline const std::string objectTypeName(T object) {
-    return object ? std::string(System::typeinfoName(typeid(*object))) : std::string("'UNKNOWN_type'");
+    return object ? std::string(System::typeinfoName(typeid(*object)))
+                  : std::string("'UNKNOWN_type'");
   }
 
   // Tabulated properties
-  template<class T>
-  StatusCode copyTableProperties(const T& src_table, G4MaterialPropertiesTable* dst_table);
+  template <class T>
+  StatusCode copyTableProperties(const T& src_table,
+                                 G4MaterialPropertiesTable* dst_table);
 
   // Storage maps to manage assignment of sensdet factories to volumes
-  std::map<GiGaFactoryBase<G4VSensitiveDetector>*, std::set<G4LogicalVolume*>> mmap_sensdet_to_lvols;
-  std::map<std::string, GiGaFactoryBase<G4VSensitiveDetector>*> mmap_name_to_sensdetfac;
-
-  // Methods to simplify tools retrieval
-  template<class T>
-  T* getTool(const std::string& type, const std::string& name, T*& tool, const IInterface* parent = 0, bool create = true) const;
-  template<class T>
-  T* getTool(const std::string& type, T*& tool, const IInterface* parent = 0, bool create = true) const;
-  IToolSvc * m_tool_svc{nullptr};
+  std::map<GiGaFactoryBase<G4VSensitiveDetector>*, std::set<G4LogicalVolume*>>
+      mmap_sensdet_to_lvols;
+  std::map<std::string, ToolHandle<GiGaFactoryBase<G4VSensitiveDetector>>>
+      mmap_name_to_sensdetfac;
+
+  std::atomic_bool m_found_global_fieldmgr{false};
+  std::map<GiGaFactoryBase<G4FieldManager, bool>*, std::set<G4LogicalVolume*>>
+      mmap_fieldmgr_to_lvols;
+  std::map<std::string, ToolHandle<GiGaFactoryBase<G4FieldManager, bool>>>
+      mmap_name_to_fieldmgrfac;
 };
 // ============================================================================
 // Implementation file for class : GaussGeo
@@ -101,16 +108,15 @@ class DD4hepCnvSvc: public extends<Service, IGiGaMTGeoSvc> {
 // 2015-11-11 : Dmitry Popov
 // ============================================================================
 
-DECLARE_COMPONENT( DD4hepCnvSvc )
+DECLARE_COMPONENT(DD4hepCnvSvc)
 
 StatusCode DD4hepCnvSvc::initialize() {
-
-  auto sc = svcLocator()->service("ToolSvc", m_tool_svc, true);
-  sc &= extends::initialize();
+  auto sc = extends::initialize();
   auto& g4map = dd4hep::sim::Geant4Mapping::instance();
   dd4hep::setPrintLevel(DD4hepGaudiMessaging::Convert(msgLevel()));
   dd4hep::DetElement world = m_dd4Svc->getDetector().world();
-  dd4hep::sim::Geant4Converter conv(dd4hep::Detector::getInstance(), DD4hepGaudiMessaging::Convert(msgLevel()));
+  dd4hep::sim::Geant4Converter conv(dd4hep::Detector::getInstance(),
+                                    DD4hepGaudiMessaging::Convert(msgLevel()));
   conv.debugMaterials = m_debugMaterials.value();
   conv.debugElements = m_debugElements.value();
   conv.debugShapes = m_debugShapes.value();
@@ -118,7 +124,6 @@ StatusCode DD4hepCnvSvc::initialize() {
   conv.debugPlacements = m_debugPlacements.value();
   conv.debugRegions = m_debugRegions.value();
 
-
   dd4hep::sim::Geant4GeometryInfo* geoinfo = conv.create(world).detach();
   geoinfo->printLevel = DD4hepGaudiMessaging::Convert(msgLevel());
 
@@ -128,142 +133,173 @@ StatusCode DD4hepCnvSvc::initialize() {
   g4map.volumeManager();
   // Printout all active volumes and assigned sensitive detectors from dd4hep
   if (msgLevel(MSG::DEBUG)) {
-      debug() << "Stored paths in volume manager: " << endmsg;
-      for(auto & pp: g4map.volumeManager()->g4Paths){
-        debug() << "/";
-        for(auto & pv:pp.first){
-          debug() << pv->GetName() << "/";
-        }
-        debug() << " ID:" << pp.second << endmsg;
+    debug() << "Stored paths in volume manager: " << endmsg;
+    for (auto& pp : g4map.volumeManager()->g4Paths) {
+      debug() << "/";
+      for (auto& pv : pp.first) {
+        debug() << pv->GetName() << "/";
       }
-      for (auto& [dd4hep_volume, g4_volume] : g4map.data().g4Volumes) {
-          if (!dd4hep_volume.isValid() || !dd4hep_volume.isSensitive()) {
-              continue;
-          }
-          auto dd4hep_sensdet_name = dd4hep_volume.sensitiveDetector().name();
-          debug() << "Active volume '" << dd4hep_volume.name() << "' SensDet: '"
-                  << dd4hep_sensdet_name << "'" << endmsg;
-          if (dd4hep_volume.isSensitive()) {
-          }
+      debug() << " ID:" << pp.second << endmsg;
+    }
+    for (auto& [dd4hep_volume, g4_volume] : g4map.data().g4Volumes) {
+      if (!dd4hep_volume.isValid() || !dd4hep_volume.isSensitive()) {
+        continue;
       }
+      auto dd4hep_sensdet_name = dd4hep_volume.sensitiveDetector().name();
+      debug() << "Active volume '" << dd4hep_volume.name() << "' SensDet: '"
+              << dd4hep_sensdet_name << "'" << endmsg;
+      if (dd4hep_volume.isSensitive()) {
+      }
+    }
   }
 
-  // We now loop over the existing logical volume mappings and extract the sensitive detector knowledge
-  // from the DD4hep volumes and map them to the requested Gaussino factories
-  if(m_sensdetmappings.size() > 0){
-    for (auto& [dd4hep_volume, g4_volume]: g4map.data().g4Volumes) {
-      if(!dd4hep_volume.isValid()){
+  // We now loop over the existing logical volume mappings and extract the
+  // sensitive detector knowledge from the DD4hep volumes and map them to the
+  // requested Gaussino factories
+  if (m_sensdetmappings.size() > 0) {
+    for (auto& [dd4hep_volume, g4_volume] : g4map.data().g4Volumes) {
+      if (!dd4hep_volume.isValid()) {
         continue;
       }
-      if(dd4hep_volume.isSensitive()){
+      if (dd4hep_volume.isSensitive()) {
         auto dd4hep_sensdet_name = dd4hep_volume.sensitiveDetector().name();
-        // Now only continue if the sensitive volume information is present in the factory mappings provided
-        if(m_sensdetmappings.find(dd4hep_sensdet_name) != std::end(m_sensdetmappings)){
+        // Now only continue if the sensitive volume information is present in
+        // the factory mappings provided
+        if (m_sensdetmappings.find(dd4hep_sensdet_name) !=
+            std::end(m_sensdetmappings)) {
           auto tool_name = m_sensdetmappings[dd4hep_sensdet_name];
-          // Following code is taken from the corresponding GaussGeo functionality 
-          // 1. Get a dictionary mapping tool name to tool instance in case multiple volumes need same sensitive detector
-          auto it = mmap_name_to_sensdetfac.find(tool_name);
-          if(it == std::end(mmap_name_to_sensdetfac)){
-            mmap_name_to_sensdetfac[tool_name] = nullptr;
-            getTool(tool_name, mmap_name_to_sensdetfac[tool_name], this);
-            // Check if successful
-            if(!mmap_name_to_sensdetfac[tool_name]){
-              warning() << "Could not retrieve sensitive detector " << tool_name << "." << endmsg;
-              warning() << "What do we say to the geo service? Not today ..." << endmsg;
-            } else {
-              debug() << "Mapping DD4hep sensitive detector '" << dd4hep_sensdet_name << "' to factory '" << tool_name << "'" << endmsg;
-            }
-          }
-
-          // 2. Now fill the map of identified sensitive detectors to volumes
-          if(auto & sensdet = mmap_name_to_sensdetfac[tool_name]; sensdet){
-            if(mmap_sensdet_to_lvols.find(sensdet) == std::end(mmap_sensdet_to_lvols)){
-              mmap_sensdet_to_lvols[sensdet] = {};
-            }
-            mmap_sensdet_to_lvols[sensdet].insert(g4_volume);
-            if(g4_volume){
-              debug() << "Asked to use sens det " << tool_name << " for " << g4_volume->GetName() << "" << endmsg;
-            }
-          }
+          sc &= register_sensitive(tool_name, g4_volume);
         }
       }
     }
   }
-  return sc;
-}
 
-StatusCode DD4hepCnvSvc::finalize() {
-  return extends::finalize();
+  // Register the factory for the global magnetic field
+  if (!m_mag_field_mgr.empty()) {
+    sc &= register_mag_field(m_mag_field_mgr, nullptr);
+  } else {
+    warning() << "Global magnetic Field was not requested to be loaded"
+              << endmsg;
+  }
+  return sc;
 }
 
+StatusCode DD4hepCnvSvc::finalize() { return extends::finalize(); }
 
 //=============================================================================
 // Retrieve the pointer to G4 geometry tree root
 //=============================================================================
 G4VPhysicalVolume* DD4hepCnvSvc::constructWorld() {
-  // Simply return the world root volume. It was populated during the initialisation
+  // Simply return the world root volume. It was populated during the
+  // initialisation
   return m_world_root;
 }
 
-
 void DD4hepCnvSvc::constructSDandField() {
   auto sdmanager = G4SDManager::GetSDMpointer();
-  for(auto & [sensdetfac, vols]:  mmap_sensdet_to_lvols){
-    debug() << "Assigning " << sensdetfac->name() << " to " << vols.size() << " logical volumes" << endmsg;
+  for (auto& [sensdetfac, vols] : mmap_sensdet_to_lvols) {
+    debug() << "Assigning " << sensdetfac->name() << " to " << vols.size()
+            << " logical volumes" << endmsg;
     auto sensdet = sensdetfac->construct();
     sdmanager->AddNewDetector(sensdet);
-    for(auto * vol: vols){
+    for (auto* vol : vols) {
       vol->SetSensitiveDetector(sensdet);
     }
   }
+
+  for (auto& [fieldmgrfac, vols] : mmap_fieldmgr_to_lvols) {
+    // Catch the global field manager
+    if (vols.size() == 1 && *std::begin(vols) == nullptr) {
+      debug() << "Constructing global " << fieldmgrfac->name() << "." << endmsg;
+      fieldmgrfac->construct(true);
+    } else {
+      auto fieldmgr = fieldmgrfac->construct(false);
+      debug() << "Assigning " << fieldmgrfac->name() << " to " << vols.size()
+              << " logical volumes" << endmsg;
+      for (auto* vol : vols) {
+        vol->SetFieldManager(fieldmgr, false);
+      }
+    }
+  }
 }
 
 //=============================================================================
-// Retrieve a tool by type and name
+// Instantiate a Magnetic Field Factories
 //=============================================================================
-template<class T>
-T* DD4hepCnvSvc::getTool(const std::string& type, const std::string& name, T*& tool, const IInterface* parent,
-                     bool create) const {
-  if (m_tool_svc == nullptr) {
-    fatal() << "ToolService is invalid!" << endmsg;
-    return nullptr;
+StatusCode DD4hepCnvSvc::register_mag_field(const std::string& name,
+                                            G4LogicalVolume* vol) {
+  // First check if we have already obtained the magnetic field factory for the
+  // provided name.
+  if (!vol && m_found_global_fieldmgr) {
+    error() << "Tried to register second global magnetic field manager"
+            << endmsg;
+    return StatusCode::FAILURE;
   }
-
-  if (name.empty()) {
-    return getTool(type, tool, parent, create);
+  auto it = mmap_name_to_fieldmgrfac.find(name);
+  if (it == std::end(mmap_name_to_fieldmgrfac)) {
+    mmap_name_to_fieldmgrfac.emplace(std::piecewise_construct,
+                                     std::forward_as_tuple(name),
+                                     std::forward_as_tuple(name, this));
+
+    if (!mmap_name_to_fieldmgrfac[name].retrieve().isSuccess()) {
+      warning() << "Could not field manager " << name << "." << endmsg;
+      warning() << "What do we say to the geo service? Not today ..." << endmsg;
+    }
   }
 
-  StatusCode sc = m_tool_svc->retrieveTool(type, name, tool, parent, create);
-  if (sc.isFailure() || tool == nullptr) {
-    fatal() << "Failed to retrieve tool '" << type << "'/'" << name << "'" << endmsg;
+  // Now fill the map of field managers to volumes
+  if (auto& fieldmgr = mmap_name_to_fieldmgrfac[name]; fieldmgr) {
+    if (mmap_fieldmgr_to_lvols.find(fieldmgr.get()) ==
+        std::end(mmap_fieldmgr_to_lvols)) {
+      mmap_fieldmgr_to_lvols[fieldmgr.get()] = {};
+    }
+    mmap_fieldmgr_to_lvols[fieldmgr.get()].insert(vol);
+    if (vol) {
+      debug() << "Asked to use field " << name << " for " << vol->GetName()
+              << "" << endmsg;
+    }
+  }
+  if (!vol) {
+    auto giga_fmanager = mmap_name_to_fieldmgrfac[name];
+    info() << "Global 'Field Manager' is set to '"
+           << objectTypeName(giga_fmanager) << "/" << giga_fmanager->name()
+           << "'" << endmsg;
+    m_found_global_fieldmgr = true;
   }
 
-  return tool;
+  return StatusCode::SUCCESS;
 }
 
 //=============================================================================
-// Retrieve a tool by type
+// Instantiate a Sensitive Detector object
 //=============================================================================
-template<class T>
-T* DD4hepCnvSvc::getTool(const std::string& type, T*& tool, const IInterface* parent, bool create) const {
-  if (m_tool_svc == nullptr) {
-    fatal() << "ToolService is invalid!" << endmsg;
-    return nullptr;
-  }
-
-  // Check if it is "type" or "type/name"
-  const auto iter = std::find(type.begin(), type.end(), '/');
-  if (iter != type.end()) {
-    std::string::size_type position = iter - type.begin();
-    const std::string new_type(type, 0, position);
-    const std::string new_name(type, position + 1, std::string::npos);
-    return getTool(new_type, new_name, tool, parent, create);
+StatusCode DD4hepCnvSvc::register_sensitive(const std::string& name, G4LogicalVolume* vol) {
+  // First check if we have already obtained the sensitive detector factory for the
+  // provided name.
+  auto it = mmap_name_to_sensdetfac.find(name);
+  if(it == std::end(mmap_name_to_sensdetfac)){
+    mmap_name_to_sensdetfac.emplace(std::piecewise_construct,
+                                     std::forward_as_tuple(name),
+                                     std::forward_as_tuple(name, this));
+
+    if (!mmap_name_to_sensdetfac[name].retrieve().isSuccess()) {
+    //mmap_name_to_sensdetfac[name] = nullptr;
+    //getTool(name, mmap_name_to_sensdetfac[name], this);
+    // Check if successful
+    //if(!mmap_name_to_sensdetfac[name]){
+      warning() << "Could not retrieve sensitive detector " << name << "." << endmsg;
+      warning() << "What do we say to the geo service? Not today ..." << endmsg;
+    }
   }
-
-  StatusCode sc = m_tool_svc->retrieveTool(type, tool, parent, create);
-  if (sc.isFailure() || tool == nullptr) {
-    fatal() << "Failed to retrieve tool '" << type << "'" << endmsg;
+  // Now fill the map of identified sensitive detectors to volumes
+  if(auto sensdet = mmap_name_to_sensdetfac[name]; sensdet){
+    if(mmap_sensdet_to_lvols.find(sensdet.get()) == std::end(mmap_sensdet_to_lvols)){
+      mmap_sensdet_to_lvols[sensdet.get()] = {};
+    }
+    mmap_sensdet_to_lvols[sensdet.get()].insert(vol);
+    if(vol){
+      debug() << "Asked to use sens det " << name << " for " << vol->GetName() << "" << endmsg;
+    }
   }
-
-  return tool;
+  return StatusCode::SUCCESS;
 }
diff --git a/Sim/Gauss/python/Gauss/Geometry/Configuration.py b/Sim/Gauss/python/Gauss/Geometry/Configuration.py
index 2fca3d942..45b793180 100644
--- a/Sim/Gauss/python/Gauss/Geometry/Configuration.py
+++ b/Sim/Gauss/python/Gauss/Geometry/Configuration.py
@@ -125,7 +125,7 @@ class LHCbGeo(LHCbConfigurableUser):
         for det in detectors_geo:
             getsubdetector(det).ApplyStream()
 
-        getsubdetector("Magnet").defineMagnetGeoField()
+        getsubdetector("Magnet").defineMagnetGeoField(self.getProp('DD4hep'))
 
         self.PrintDebugDump(detPieces, basePieces)
 
diff --git a/Sim/Gauss/python/Gauss/Geometry/Magnet.py b/Sim/Gauss/python/Gauss/Geometry/Magnet.py
index 230601130..b27751f5c 100644
--- a/Sim/Gauss/python/Gauss/Geometry/Magnet.py
+++ b/Sim/Gauss/python/Gauss/Geometry/Magnet.py
@@ -7,25 +7,42 @@ class Magnet(det_base):
 
     __slots__ = {}
 
+    def ApplyDetectorDD4hep(self, basePieces, detPieces):
+        # Add the necessary dd4hep includes for the VP. Also added all the
+        # dependencies for material definitions that were identified using
+        # trial and error. As the list is made unique before being added to
+        # the xml this should be fine if they appear in multiple places
+        from Gauss.Geometry import LHCbGeo
+        go = LHCbGeo._listOfXMLIncludes_
+        go += ["Magnet/parameters.xml"]
+        go += ["Magnet/detector.xml"]
+
     def ApplyDetectorDetDesc(self, basePieces, detPieces):
         detPieces["MagnetRegion"] = ['Magnet', 'BcmDown']
 
-    def defineMagnetGeoField(self):
-        from Configurables import GaussGeo, ToolFieldMgr, MagFieldFromSvc
+    def defineMagnetGeoField(self, use_dd4hep_svc=False):
+        from Configurables import ToolFieldMgr, MagFieldFromSvc
         from Gauss.Geometry.Helpers import getsubdetector
         # Only bother with the FIELD Geometry if simulated.
+        if use_dd4hep_svc:
+            from Configurables import DD4hepCnvSvc
+            geosvc = DD4hepCnvSvc()
+        else:
+            from Configurables import GaussGeo
+            geosvc = GaussGeo()
+
         if getsubdetector("Magnet").Simulate or getsubdetector("HC").Simulate:
-            GaussGeo().FieldManager = "ToolFieldMgr/FieldMgr"
-            GaussGeo().addTool(ToolFieldMgr("FieldMgr"), name="FieldMgr")
-            GaussGeo().FieldMgr.Stepper = "G4ClassicalRK4"
-            GaussGeo().FieldMgr.MagneticField = "MagFieldFromSvc/LHCbField"
-            GaussGeo().FieldMgr.addTool(MagFieldFromSvc("LHCbField"), name="LHCbField")  # NOQA
-            GaussGeo().FieldMgr.LHCbField.MagneticFieldService = "MagneticFieldSvc"  # NOQA
+            geosvc.FieldManager = "ToolFieldMgr/FieldMgr"
+            geosvc.addTool(ToolFieldMgr("FieldMgr"), name="FieldMgr")
+            geosvc.FieldMgr.Stepper = "G4ClassicalRK4"
+            geosvc.FieldMgr.MagneticField = "MagFieldFromSvc/LHCbField"
+            geosvc.FieldMgr.addTool(MagFieldFromSvc("LHCbField"), name="LHCbField")  # NOQA
+            geosvc.FieldMgr.LHCbField.MagneticFieldService = "MagneticFieldSvc"  # NOQA
 
         if getsubdetector("HC").Simulate:
             from Configurables import MagneticFieldSvc, MultipleMagneticFieldSvc
             # Use MultipleMagneticFieldSvc instead of default MagneticFieldSvc.
-            GaussGeo().FieldMgr.LHCbField.MagneticFieldService = "MultipleMagneticFieldSvc"  # NOQA
+            geosvc.FieldMgr.LHCbField.MagneticFieldService = "MultipleMagneticFieldSvc"  # NOQA
             # Add LHCb dipole magnet and compensators.
             if getsubdetector("Magnet").Simulate:
               MultipleMagneticFieldSvc().MagneticFieldServices += ["MagneticFieldSvc"]
-- 
GitLab


From a853235279fd95bfbb406d0b41223c36d0747c5d Mon Sep 17 00:00:00 2001
From: Dominik Muller <dominik.muller@cern.ch>
Date: Fri, 24 Jul 2020 15:53:09 +0200
Subject: [PATCH 59/90] generator versions for 97a

---
 generators_versions_LCG97a.txt | 13 +++++++++++++
 1 file changed, 13 insertions(+)
 create mode 100644 generators_versions_LCG97a.txt

diff --git a/generators_versions_LCG97a.txt b/generators_versions_LCG97a.txt
new file mode 100644
index 000000000..9732b86f1
--- /dev/null
+++ b/generators_versions_LCG97a.txt
@@ -0,0 +1,13 @@
+alpgen         2.1.4
+hijing         1.383bs.2
+powheg-box-v2  r3043.lhcb
+pythia6        429.2
+rivet          3.0.1
+tauola++       1.1.6
+thepeg         2.2.0
+crmc           1.6.0
+yoda           1.8.0
+starlight      r313
+pythia8        244
+lhapdf         6.2.3
+photos++       3.61
-- 
GitLab


From 553d45e036ed9d4f2b3012eba0988a362fe71257 Mon Sep 17 00:00:00 2001
From: Dominik Muller <dominik.muller@cern.ch>
Date: Wed, 19 Aug 2020 17:05:06 +0200
Subject: [PATCH 60/90] Refactored Calo sensdet code to allow DD4hep support.
 Dummy DD4hep specialisation added as well

---
 Sim/GaussCalo/CMakeLists.txt        |   5 +-
 Sim/GaussCalo/src/CaloSensDet.h     |  70 ++----------
 Sim/GaussCalo/src/CaloSensDet.icpp  | 100 ++----------------
 Sim/GaussCalo/src/CaloSensDetFAC.h  |  33 ------
 Sim/GaussCalo/src/CellFromDD4hep.h  |  39 +++++++
 Sim/GaussCalo/src/CellFromLHCbGeo.h | 158 ++++++++++++++++++++++++++++
 Sim/GaussCalo/src/EcalSensDet.cpp   |   5 +
 Sim/GaussCalo/src/HcalSensDet.cpp   |   5 +
 Sim/GaussCalo/src/SpdPrsSensDet.cpp |   5 +
 9 files changed, 234 insertions(+), 186 deletions(-)
 create mode 100644 Sim/GaussCalo/src/CellFromDD4hep.h
 create mode 100644 Sim/GaussCalo/src/CellFromLHCbGeo.h

diff --git a/Sim/GaussCalo/CMakeLists.txt b/Sim/GaussCalo/CMakeLists.txt
index 3695eba48..8f9b86db9 100644
--- a/Sim/GaussCalo/CMakeLists.txt
+++ b/Sim/GaussCalo/CMakeLists.txt
@@ -12,6 +12,7 @@ gaudi_depends_on_subdirs(Det/CaloDet
 
 find_package(AIDA)
 AddHepMC3()
+AddDD4hepDDG4()
 find_package(Boost)
 find_package(CLHEP)
 include_directories(SYSTEM ${Boost_INCLUDE_DIRS} ${CLHEP_INCLUDE_DIRS} ${Geant4_INCLUDE_DIRS})
@@ -21,7 +22,7 @@ add_definitions(-DG4USE_STD11)
 
 gaudi_add_module(GaussCalo
                  src/*.cpp
-                 INCLUDE_DIRS AIDA GiGaMTFactories
-                 LINK_LIBRARIES CaloDetLib MCEvent LHCbKernel GiGaMTCoreTruthLib GaudiAlgLib)
+                 INCLUDE_DIRS AIDA GiGaMTFactories DD4hep
+                 LINK_LIBRARIES CaloDetLib MCEvent LHCbKernel GiGaMTCoreTruthLib GaudiAlgLib ${DD4hepDDG4_LIBRARIES})
 
 gaudi_env(SET GAUSSCALOOPTS \${GAUSSCALOROOT}/options)
diff --git a/Sim/GaussCalo/src/CaloSensDet.h b/Sim/GaussCalo/src/CaloSensDet.h
index 243b073b6..cee10742c 100755
--- a/Sim/GaussCalo/src/CaloSensDet.h
+++ b/Sim/GaussCalo/src/CaloSensDet.h
@@ -4,7 +4,7 @@
 #include "GaudiKernel/HashMap.h"
 
 // from Gaudi
-#include "GaudiKernel/Counters.h"
+#include "Gaudi/Accumulators.h"
 #include "GaudiKernel/Point3DTypes.h"
 
 // GiGa
@@ -27,9 +27,19 @@
 #include "CLHEP/Geometry/Transform3D.h"
 
 /** @class CaloSensDet CaloSensDet.h CaloSensDet.h
+ *  Base class for all calo sensitive detectors.
+ *  Templated in the CELLGETTER that provides information
+ *  from the geometry description to avoid vtable calls.
+ *  This base class must provide
+ *  inline double cellX(const LHCb::CaloCellID& id) const
+ *  inline double cellY(const LHCb::CaloCellID& id) const
+ *  inline double cellSize(const LHCb::CaloCellID& id) const
+ *  inline LHCb::CaloCellID cell(const G4Step* point) const
+ *  inline void GeoBaseInitialize()
  *
  *
  *  @author  Vanya Belyaev
+ *  @author  Dominik Muller
  *  @date    23/01/2001
  */
 
@@ -38,12 +48,7 @@ class CaloSensDet : public G4VSensitiveDetector,
                     public virtual CELLGETTER,
                     public virtual GiGaMessage {
   public:
-  /// useful type for list of names
-  typedef std::vector<std::string> Names;
-  /// useful type for list of logical volumes
-  typedef std::vector<const G4LogicalVolume*> Volumes;
   /// translator from Path to CellID
-  typedef GaudiUtils::HashMap<CaloSim::Path, LHCb::CaloCellID> Table;
   typedef GaudiUtils::HashMap<LHCb::CaloCellID, CaloHit*> HitMap;
   /// type for all histograms
   typedef std::vector<AIDA::IHistogram1D*> Histos;
@@ -74,15 +79,6 @@ class CaloSensDet : public G4VSensitiveDetector,
    */
   bool ProcessHits(G4Step* step, G4TouchableHistory* history) override;
 
-  // ============================================================================
-  /** helper method to locate the Calorimeter cell to which
-   *  G4 point belongs to
-   *  @param point G4 point
-   *  @retuen calorimeter cell identifier
-   */
-  // ============================================================================
-  inline LHCb::CaloCellID cell(const G4StepPoint* point) const;
-
   /** method from G4
    *  (Called at the begin of each event)
    *  @see G4VSensitiveDetector
@@ -109,9 +105,6 @@ class CaloSensDet : public G4VSensitiveDetector,
   /// access to hit collection
   inline CaloHitsCollection* hits() const { return m_collection; }
 
-  /// access to translation table
-  inline Table& table() { return m_table; }
-
   /// access to hit map
   inline HitMap& hitmap() { return m_hitmap; }
 
@@ -221,25 +214,14 @@ class CaloSensDet : public G4VSensitiveDetector,
                                const double density) const;
 
   private:
-  const G4LogicalVolume* m_end;
 
-  // definition logical volumes where will be analysed signal
-  Volumes m_start;
-
-  // translation table
-  mutable Table m_table;
   HitMap m_hitmap;
 
   CaloHitsCollection* m_collection;
 
-  bool m_geoBaseInitialized{false};
-  void GeoBaseInitialize();
-
   public:
   /// all histograms
   Histos m_histos;
-  std::string m_endVolumeName{};
-  Names m_startVolumeNames{};
 
   // the first coefficient of Birk's law                    (c1)
   double m_birk_c1{0.013 * CLHEP::g / CLHEP::MeV / CLHEP::cm2};
@@ -260,34 +242,4 @@ class CaloSensDet : public G4VSensitiveDetector,
   Gaudi::Accumulators::SummingCounter<double>* m_energy{nullptr};
 };
 
-
-// CaloDet
-#include "CaloDet/DeCalorimeter.h"
-class CellFromLHCbGeo : public virtual GiGaMessage {
-  protected:
-  CellFromLHCbGeo() = default;
-  virtual ~CellFromLHCbGeo() = default;
-  inline double cellTime(const LHCb::CaloCellID& cellID) const {
-    return m_calo->cellTime(cellID);
-  };
-
-  inline double cellX(const LHCb::CaloCellID& id) const {return m_calo->cellX( id);};
-  inline double cellY(const LHCb::CaloCellID& id) const {return m_calo->cellY( id);};
-  inline double cellSize(const LHCb::CaloCellID& id) const {return m_calo->cellSize(id);}
-
-  inline LHCb::CaloCellID cellID(const Gaudi::XYZPoint& position) const {
-    const CellParam* par = m_calo->Cell_(position);
-    if (0 == par || !par->valid()) {
-      return LHCb::CaloCellID();  // RETURN
-    }
-    return par->cellID();
-  }
-
-  public:
-  // Need to be set by the corresponding factory that has access to
-  // the Gaudi based functionality
-  const DeCalorimeter* m_calo{nullptr};
-  int m_caloID{0};
-};
-
 #include "CaloSensDet.icpp"
diff --git a/Sim/GaussCalo/src/CaloSensDet.icpp b/Sim/GaussCalo/src/CaloSensDet.icpp
index 5a00112da..ec8d8b05b 100755
--- a/Sim/GaussCalo/src/CaloSensDet.icpp
+++ b/Sim/GaussCalo/src/CaloSensDet.icpp
@@ -22,7 +22,6 @@
 
 // Geant4
 #include "Geant4/G4LogicalVolume.hh"
-#include "Geant4/G4LogicalVolumeStore.hh"
 #include "Geant4/G4Material.hh"
 #include "Geant4/G4MaterialCutsCouple.hh"
 #include "Geant4/G4SDManager.hh"
@@ -32,7 +31,6 @@
 
 // local
 #include "CaloHit.h"
-#include "CaloSensDet.h"
 #include "CaloSimHash.h"
 
 // AIDA
@@ -90,12 +88,7 @@ double CaloSensDet<CELLGETTER>::birkCorrection(const double charge,
 template <typename CELLGETTER>
 void CaloSensDet<CELLGETTER>::Initialize(G4HCofThisEvent* HCE) {
   //
-  if (!this->m_geoBaseInitialized) {
-    this->GeoBaseInitialize();
-  }
-  if (!this->m_geoBaseInitialized) {
-    std::runtime_error("Could not locate volumes!");
-  }
+  this->GeoBaseInitialize();
   //
   m_collection =
       new CaloHitsCollection(SensitiveDetectorName, collectionName[0]);
@@ -189,60 +182,6 @@ double CaloSensDet<CELLGETTER>::birkCorrection(const G4Step* step) const {
                         track->GetMaterialCutsCouple());
 }
 
-template <typename CELLGETTER>
-LHCb::CaloCellID CaloSensDet<CELLGETTER>::cell(const G4StepPoint* point) const {
-  G4TouchableHistory* tHist = (G4TouchableHistory*)point->GetTouchable();
-
-  const int nLevel = tHist->GetHistoryDepth();
-  CaloSim::Path path;
-  path.reserve(nLevel);
-
-  for (int level = 0; level < nLevel; ++level) {
-    const G4VPhysicalVolume* pv = tHist->GetVolume(level);
-    if (0 == pv) {
-      continue;
-    }  // CONTINUE
-    const G4LogicalVolume* lv = pv->GetLogicalVolume();
-    if (0 == lv) {
-      continue;
-    }  // CONTINUE
-    // start volume ??
-    if (m_end == lv) {
-      break;
-    }  // BREAK
-    // useful volume ?
-    if (!path.empty()) {
-      path.push_back(pv);
-    } else if (m_start.end() != std::find(m_start.begin(), m_start.end(), lv)) {
-      path.push_back(pv);
-    }
-  }
-
-  if (path.empty()) {
-    error("Volume path is invalid(empty) ");
-    return LHCb::CaloCellID();
-  }
-
-  // find the appropriate ID
-  Table::iterator ifound = m_table.find(path);
-  // already in the table ?
-  if (m_table.end() != ifound) {
-    return ifound->second;
-  }  // RETURN
-
-  // if not: add it into the table!
-  // CLHEP -> ROOT
-  HepGeom::Transform3D mtrx(*(tHist->GetRotation()), tHist->GetTranslation());
-  auto heppoint = mtrx * HepGeom::Point3D<double>{};
-  const Gaudi::XYZPoint p(heppoint.x(), heppoint.y(), heppoint.z());
-
-  // get the right cell id
-  auto id = this->cellID(p);
-  m_table.insert(Table::value_type(path, id));
-
-  return id;
-}
-
 // ============================================================================
 /** method from G4
  *  (Called at the end of each event)
@@ -329,7 +268,7 @@ bool CaloSensDet<CELLGETTER>::ProcessHits(G4Step* step,
   const double time = preStep->GetGlobalTime();
   const G4MaterialCutsCouple* const material = preStep->GetMaterialCutsCouple();
 
-  const LHCb::CaloCellID cellID = cell(preStep);
+  const LHCb::CaloCellID cellID = this->cell(step);
   if (LHCb::CaloCellID() == cellID) {
     return false;
   }
@@ -354,7 +293,10 @@ bool CaloSensDet<CELLGETTER>::ProcessHits(G4Step* step,
   int sTrackID = track->GetParentID();
 
   // already marked to be stored:
-  if (info->storeTruth()) {
+  // Use preliminary here as well. If it turns out that the track is
+  // not to be stored after all, the TruthFlaggingTrackAction will
+  // fix the IDs assigned to the hits of this track.
+  if (info->storeTruth() || info->prelStoreTruth()) {
     sTrackID = trackID;
   } else {
     // z-position of production vertex
@@ -365,6 +307,8 @@ bool CaloSensDet<CELLGETTER>::ProcessHits(G4Step* step,
     }
   }
 
+  sTrackID = trackID;
+
   // Does the hit exist for the given track?
   CaloSubHit*& sub = hit->hit(sTrackID);  // ATTENTION
   // create new subhit if needed
@@ -387,31 +331,3 @@ bool CaloSensDet<CELLGETTER>::ProcessHits(G4Step* step,
   return true;
 }
 
-// ============================================================================
-/** helpful method to locate start and end volumes
- *  @return status code
- */
-// ============================================================================
-template <typename CELLGETTER>
-void CaloSensDet<CELLGETTER>::GeoBaseInitialize() {
-  // locate start volumes
-  for (auto& vol : m_startVolumeNames) {
-    // look through converted volumes
-    const G4LogicalVolume* lv =
-        G4LogicalVolumeStore::GetInstance()->GetVolume(vol);
-    if (0 == lv) {
-      throw std::runtime_error(std::string(__PRETTY_FUNCTION__) + "G4LogicalVolume* points to 0 for " + (vol));
-    }
-    m_start.push_back(lv);
-  }
-  if (m_start.empty()) {
-    throw std::runtime_error(std::string(__PRETTY_FUNCTION__) + "Size of 'StartVolumes' is 0 ");
-  }
-  // locate end volume : look through converted volumes
-  m_end = G4LogicalVolumeStore::GetInstance()->GetVolume(m_endVolumeName);
-  if (0 == m_end) {
-    throw std::runtime_error(std::string(__PRETTY_FUNCTION__) + "G4LogicalVolume* points to 0 for '" +
-                             m_endVolumeName + "'");
-  }
-  m_geoBaseInitialized = true;
-}
diff --git a/Sim/GaussCalo/src/CaloSensDetFAC.h b/Sim/GaussCalo/src/CaloSensDetFAC.h
index 5171b1872..f4341308c 100755
--- a/Sim/GaussCalo/src/CaloSensDetFAC.h
+++ b/Sim/GaussCalo/src/CaloSensDetFAC.h
@@ -12,9 +12,6 @@
 
 template <typename CALO>
 class CaloSensDetBaseFAC : public GiGaMTG4SensDetFactory<CALO> {
-  Gaudi::Property<std::string> m_endVolumeName{this, "EndVolume", ""};
-  Gaudi::Property<std::vector<std::string>> m_startVolumeNames{
-      this, "StartVolumes", {}};
 
   // the first coefficient of Birk's law                    (c1)
   Gaudi::Property<double> m_birk_c1{this, "BirkC1",
@@ -49,8 +46,6 @@ class CaloSensDetBaseFAC : public GiGaMTG4SensDetFactory<CALO> {
   using typename gaussino_base_class::GiGaMTG4SensDetFactory;
   virtual CALO* construct() const override {
     auto tmp = gaussino_base_class::construct();
-    tmp->m_endVolumeName = m_endVolumeName;
-    tmp->m_startVolumeNames = m_startVolumeNames;
     tmp->m_birk_c1 = m_birk_c1;
     tmp->m_birk_c2 = m_birk_c2;
     tmp->m_birk_c1correction = m_birk_c1correction;
@@ -100,31 +95,3 @@ class CaloSensDetFAC : public CaloSensDetBaseFAC<CALO> {
   virtual CALO* construct() const override { return base_class::construct(); }
 };
 
-template <typename T>
-using usesLHCbGeo =
-    typename std::enable_if<std::is_base_of<CellFromLHCbGeo, T>::value>::type;
-
-template <typename CALO>
-class CaloSensDetFAC<CALO, usesLHCbGeo<CALO>>
-    : public CaloSensDetBaseFAC<CALO> {
-  Gaudi::Property<std::string> m_caloName{this, "Detector",
-                                          DeCalorimeterLocation::Ecal};
-
-  public:
-  virtual ~CaloSensDetFAC() = default;
-  using base_class = CaloSensDetBaseFAC<CALO>;
-  using base_class::CaloSensDetBaseFAC;
-  virtual CALO* construct() const override {
-    auto tmp = base_class::construct();
-    tmp->m_calo = this->template getDet<DeCalorimeter>(m_caloName);
-    if (0 == tmp->m_calo) {
-      throw std::runtime_error("Could not locate CALO " + m_caloName);
-    }
-    tmp->m_caloID = CaloCellCode::CaloNumFromName(m_caloName);
-
-    if (0 > tmp->m_caloID) {
-      throw std::runtime_error("Invalid detector name/number!");
-    }
-    return tmp;
-  }
-};
diff --git a/Sim/GaussCalo/src/CellFromDD4hep.h b/Sim/GaussCalo/src/CellFromDD4hep.h
new file mode 100644
index 000000000..09d35d0ee
--- /dev/null
+++ b/Sim/GaussCalo/src/CellFromDD4hep.h
@@ -0,0 +1,39 @@
+// CaloDet
+#include "CaloSensDetFAC.h"
+#include "GiGaMTFactories/GiGaMTG4SensDetFactory.h"
+
+#include "DDG4/Geant4Mapping.h"
+#include "DDG4/Geant4TouchableHandler.h"
+
+
+class CellFromDD4hep : public virtual GiGaMessage {
+  protected:
+  CellFromDD4hep() = default;
+  virtual ~CellFromDD4hep() = default;
+  inline double cellTime(const LHCb::CaloCellID&) const {
+    warning("CellTime not implemented for DD4hep", 10);
+    return -1;
+  };
+
+  inline double cellX(const LHCb::CaloCellID&) const {
+    warning("cellX not implemented for DD4hep", 10);
+    return -1;};
+  inline double cellY(const LHCb::CaloCellID&) const {
+    warning("cellY not implemented for DD4hep", 10);
+    return -1;};
+  inline double cellSize(const LHCb::CaloCellID&) const {
+    warning("cellSize not implemented for DD4hep", 10);
+    return -1;}
+  inline LHCb::CaloCellID cell(const G4Step* step) const {
+
+    auto& g4map = dd4hep::sim::Geant4Mapping::instance();
+    dd4hep::sim::Geant4TouchableHandler touch{step};
+    auto paths = touch.placementPath();
+    g4map.volumeManager().volumeID(paths);
+    warning("no conversion of DD4hep ID to LHCb::Calo::CellID yet", 10);
+    LHCb::CaloCellID id;
+    return id;
+  }
+
+  inline void GeoBaseInitialize() { }
+};
diff --git a/Sim/GaussCalo/src/CellFromLHCbGeo.h b/Sim/GaussCalo/src/CellFromLHCbGeo.h
new file mode 100644
index 000000000..2ee3ad7ea
--- /dev/null
+++ b/Sim/GaussCalo/src/CellFromLHCbGeo.h
@@ -0,0 +1,158 @@
+// CaloDet
+#include "CaloDet/DeCalorimeter.h"
+#include "Geant4/G4LogicalVolumeStore.hh"
+#include "CaloSensDetFAC.h"
+
+class CellFromLHCbGeo : public virtual GiGaMessage {
+  protected:
+  CellFromLHCbGeo() = default;
+  virtual ~CellFromLHCbGeo() = default;
+  inline double cellTime(const LHCb::CaloCellID& cellID) const {
+    return m_calo->cellTime(cellID);
+  };
+
+  inline double cellX(const LHCb::CaloCellID& id) const {return m_calo->cellX( id);};
+  inline double cellY(const LHCb::CaloCellID& id) const {return m_calo->cellY( id);};
+  inline double cellSize(const LHCb::CaloCellID& id) const {return m_calo->cellSize(id);}
+  inline LHCb::CaloCellID cell(const G4Step* step) const {
+
+    const G4StepPoint* const point = step->GetPreStepPoint();
+    G4TouchableHistory* tHist = (G4TouchableHistory*)point->GetTouchable();
+
+    const int nLevel = tHist->GetHistoryDepth();
+    CaloSim::Path path;
+    path.reserve(nLevel);
+
+    for (int level = 0; level < nLevel; ++level) {
+      const G4VPhysicalVolume* pv = tHist->GetVolume(level);
+      if (0 == pv) {
+        continue;
+      }  // CONTINUE
+      const G4LogicalVolume* lv = pv->GetLogicalVolume();
+      if (0 == lv) {
+        continue;
+      }  // CONTINUE
+      // start volume ??
+      if (m_end == lv) {
+        break;
+      }  // BREAK
+      // useful volume ?
+      if (!path.empty()) {
+        path.push_back(pv);
+      } else if (m_start.end() != std::find(m_start.begin(), m_start.end(), lv)) {
+        path.push_back(pv);
+      }
+    }
+
+    if (path.empty()) {
+      error("Volume path is invalid(empty) ");
+      return LHCb::CaloCellID();
+    }
+
+    // find the appropriate ID
+    Table::iterator ifound = m_table.find(path);
+    // already in the table ?
+    if (m_table.end() != ifound) {
+      return ifound->second;
+    }  // RETURN
+
+    // if not: add it into the table!
+    // CLHEP -> ROOT
+    HepGeom::Transform3D mtrx(*(tHist->GetRotation()), tHist->GetTranslation());
+    auto heppoint = mtrx * HepGeom::Point3D<double>{};
+    const Gaudi::XYZPoint p(heppoint.x(), heppoint.y(), heppoint.z());
+
+    // get the right cell id
+    LHCb::Calo::CellID id;
+    const CellParam* par = m_calo->Cell_(p);
+    if (0 == par || !par->valid()) {
+      id = LHCb::CaloCellID();  // RETURN
+    }
+    id = par->cellID();
+    m_table.insert(Table::value_type(path, id));
+
+    return id;
+  }
+
+  // ============================================================================
+  /** helpful method to locate start and end volumes
+  *  @return status code
+  */
+  // ============================================================================
+  inline void GeoBaseInitialize() {
+    // locate start volumes
+    for (auto& vol : m_startVolumeNames) {
+      // look through converted volumes
+      const G4LogicalVolume* lv =
+          G4LogicalVolumeStore::GetInstance()->GetVolume(vol);
+      if (0 == lv) {
+        throw std::runtime_error(std::string(__PRETTY_FUNCTION__) + "G4LogicalVolume* points to 0 for " + (vol));
+      }
+      m_start.push_back(lv);
+    }
+    if (m_start.empty()) {
+      throw std::runtime_error(std::string(__PRETTY_FUNCTION__) + "Size of 'StartVolumes' is 0 ");
+    }
+    // locate end volume : look through converted volumes
+    m_end = G4LogicalVolumeStore::GetInstance()->GetVolume(m_endVolumeName);
+    if (0 == m_end) {
+      throw std::runtime_error(std::string(__PRETTY_FUNCTION__) + "G4LogicalVolume* points to 0 for '" +
+                              m_endVolumeName + "'");
+    }
+  }
+
+  public:
+    // Need to be set by the corresponding factory that has access to
+    // the Gaudi based functionality
+    const DeCalorimeter* m_calo{nullptr};
+    int m_caloID{0};
+
+    /// useful type for list of names
+    typedef std::vector<std::string> Names;
+    std::string m_endVolumeName{};
+    Names m_startVolumeNames{};
+  private:
+    /// useful type for list of logical volumes
+    typedef std::vector<const G4LogicalVolume*> Volumes;
+    typedef GaudiUtils::HashMap<CaloSim::Path, LHCb::CaloCellID> Table;
+    const G4LogicalVolume* m_end{nullptr};
+    // definition logical volumes where will be analysed signal
+    Volumes m_start;
+    // translation table
+    mutable Table m_table;
+};
+
+
+template <typename T>
+using usesLHCbGeo =
+    typename std::enable_if<std::is_base_of<CellFromLHCbGeo, T>::value>::type;
+
+template <typename CALO>
+class CaloSensDetFAC<CALO, usesLHCbGeo<CALO>>
+    : public CaloSensDetBaseFAC<CALO> {
+  Gaudi::Property<std::string> m_caloName{this, "Detector",
+                                          DeCalorimeterLocation::Ecal};
+  Gaudi::Property<std::string> m_endVolumeName{this, "EndVolume", ""};
+  Gaudi::Property<std::vector<std::string>> m_startVolumeNames{
+      this, "StartVolumes", {}};
+
+  public:
+  virtual ~CaloSensDetFAC() = default;
+  using base_class = CaloSensDetBaseFAC<CALO>;
+  using base_class::CaloSensDetBaseFAC;
+  virtual CALO* construct() const override {
+    auto tmp = base_class::construct();
+    tmp->m_calo = this->template getDet<DeCalorimeter>(m_caloName);
+    if (!tmp->m_calo) {
+      throw std::runtime_error("Could not locate CALO " + m_caloName);
+    }
+    tmp->m_caloID = CaloCellCode::CaloNumFromName(m_caloName);
+    tmp->m_endVolumeName = m_endVolumeName;
+    tmp->m_startVolumeNames = m_startVolumeNames;
+
+    if (0 > tmp->m_caloID) {
+      throw std::runtime_error("Invalid detector name/number!");
+    }
+    return tmp;
+  }
+};
diff --git a/Sim/GaussCalo/src/EcalSensDet.cpp b/Sim/GaussCalo/src/EcalSensDet.cpp
index d1ff75b8d..fd7e64e7e 100755
--- a/Sim/GaussCalo/src/EcalSensDet.cpp
+++ b/Sim/GaussCalo/src/EcalSensDet.cpp
@@ -144,6 +144,8 @@ bool EcalSensDet<CELLGETTER>::timing(
 }
 
 #include "CaloSensDetFAC.h"
+#include "CellFromLHCbGeo.h"
+#include "CellFromDD4hep.h"
 
 template <typename CELLGETTER>
 class EcalSensDetFAC : public CaloSensDetFAC<EcalSensDet<CELLGETTER>> {
@@ -185,3 +187,6 @@ class EcalSensDetFAC : public CaloSensDetFAC<EcalSensDet<CELLGETTER>> {
 // Declaration of the Tool Factory
 typedef EcalSensDetFAC<CellFromLHCbGeo> EcalSensDetLHCbGeoFAC;
 DECLARE_COMPONENT_WITH_ID(EcalSensDetLHCbGeoFAC, "EcalSensDet")
+
+typedef EcalSensDetFAC<CellFromDD4hep> EcalSensDetDD4hepFAC;
+DECLARE_COMPONENT_WITH_ID(EcalSensDetDD4hepFAC, "EcalSensDetDD4hep")
diff --git a/Sim/GaussCalo/src/HcalSensDet.cpp b/Sim/GaussCalo/src/HcalSensDet.cpp
index f4e883208..41e48877d 100755
--- a/Sim/GaussCalo/src/HcalSensDet.cpp
+++ b/Sim/GaussCalo/src/HcalSensDet.cpp
@@ -133,6 +133,8 @@ bool HcalSensDet<CELLGETTER>::timing(
 }
 
 #include "CaloSensDetFAC.h"
+#include "CellFromLHCbGeo.h"
+#include "CellFromDD4hep.h"
 
 template <typename CELLGETTER>
 class HcalSensDetFAC : public CaloSensDetFAC<HcalSensDet<CELLGETTER>> {
@@ -152,3 +154,6 @@ class HcalSensDetFAC : public CaloSensDetFAC<HcalSensDet<CELLGETTER>> {
 // Declaration of the Tool Factory
 typedef HcalSensDetFAC<CellFromLHCbGeo> HcalSensDetLHCbGeoFAC;
 DECLARE_COMPONENT_WITH_ID(HcalSensDetLHCbGeoFAC, "HcalSensDet")
+
+typedef HcalSensDetFAC<CellFromDD4hep> HcalSensDetDD4hepFAC;
+DECLARE_COMPONENT_WITH_ID(HcalSensDetDD4hepFAC, "HcalSensDetDD4hep")
diff --git a/Sim/GaussCalo/src/SpdPrsSensDet.cpp b/Sim/GaussCalo/src/SpdPrsSensDet.cpp
index 77933f7cb..72950879a 100755
--- a/Sim/GaussCalo/src/SpdPrsSensDet.cpp
+++ b/Sim/GaussCalo/src/SpdPrsSensDet.cpp
@@ -157,6 +157,8 @@ bool SpdPrsSensDet<CELLGETTER>::timing
 }
 
 #include "CaloSensDetFAC.h"
+#include "CellFromLHCbGeo.h"
+#include "CellFromDD4hep.h"
 
 template <typename CELLGETTER>
 class SpdPrsSensDetFAC
@@ -185,3 +187,6 @@ class SpdPrsSensDetFAC
 // Declaration of the Tool Factory
 typedef SpdPrsSensDetFAC<CellFromLHCbGeo> SpdPrsSensDetLHCbGeoFAC;
 DECLARE_COMPONENT_WITH_ID( SpdPrsSensDetLHCbGeoFAC, "SpdPrsSensDet" )
+
+typedef SpdPrsSensDetFAC<CellFromDD4hep> SpdPrsSensDetDD4hepFAC;
+DECLARE_COMPONENT_WITH_ID( SpdPrsSensDetDD4hepFAC, "SpdPrsSensDetDD4hep" )
-- 
GitLab


From 9980ec5f1787e968c347da3020ce209baad3962c Mon Sep 17 00:00:00 2001
From: Dominik Muller <dominik.muller@cern.ch>
Date: Tue, 1 Sep 2020 16:52:46 +0200
Subject: [PATCH 61/90] Cleaned up DD4hepCnvSvc for LHCb specific parts; using
 general implementation from Gaussino

---
 Sim/DD4hepCnv/src/component/DD4hepCnvSvc.cpp  | 305 ------------------
 .../src/component/LHCbDD4hepCnvSvc.cpp        |  21 ++
 Sim/Gauss/python/Gauss/Configuration.py       |   9 +-
 Sim/Gauss/python/Gauss/Geometry/BLS.py        |   6 +-
 .../python/Gauss/Geometry/Configuration.py    |   6 +-
 Sim/Gauss/python/Gauss/Geometry/Magnet.py     |   4 +-
 Sim/Gauss/python/Gauss/Geometry/VP.py         |   8 +-
 7 files changed, 39 insertions(+), 320 deletions(-)
 delete mode 100644 Sim/DD4hepCnv/src/component/DD4hepCnvSvc.cpp
 create mode 100644 Sim/DD4hepCnv/src/component/LHCbDD4hepCnvSvc.cpp

diff --git a/Sim/DD4hepCnv/src/component/DD4hepCnvSvc.cpp b/Sim/DD4hepCnv/src/component/DD4hepCnvSvc.cpp
deleted file mode 100644
index 96571808b..000000000
--- a/Sim/DD4hepCnv/src/component/DD4hepCnvSvc.cpp
+++ /dev/null
@@ -1,305 +0,0 @@
-// Gaudi includes
-#include "GaudiKernel/IDataManagerSvc.h"
-#include "GaudiKernel/IRegistry.h"
-#include "GaudiKernel/IToolSvc.h"
-#include "GaudiKernel/SmartDataPtr.h"
-#include "GaudiKernel/SmartIF.h"
-
-// GiGa
-// FIXME: Need to integrate this
-//#include "GiGaMTFactories/GiGaMTG4SensDetFactory.h"
-//#include "GiGa/IGiGaMagField.h"
-//#include "GiGa/IGiGaFieldMgr.h"
-//#include "GiGa/IGDMLReader.h"
-
-#include "Kernel/IPropertyConfigSvc.h"
-
-// Gaudi includes
-#include "GaudiKernel/IIncidentSvc.h"
-#include "GaudiKernel/Service.h"
-#include "GaudiKernel/Transform3DTypes.h"
-#include "Geant4/G4VSensitiveDetector.hh"
-#include "GiGaMTFactories/GiGaFactoryBase.h"
-
-#include "GiGaMTGeo/IGiGaMTGeoSvc.h"
-#include "LbDD4hep/IDD4hepSvc.h"
-
-// DD4hep
-#include "DD4hep/Detector.h"
-#include "DDG4/Geant4Converter.h"
-#include "DDG4/Geant4Mapping.h"
-#include "GiGaMTDD4hep/Utilities.h"
-
-// Geant4
-#include "Geant4/G4SDManager.hh"
-
-// ============================================================================
-// Conversion service for convertion DD4hep geometry from LHCb to Geant4
-//
-// 2020-6-15 : Dominik Muller
-// ============================================================================
-
-class DD4hepCnvSvc : public extends<Service, IGiGaMTGeoSvc> {
- public:
-  using extends::extends;
-  virtual ~DD4hepCnvSvc() = default;
-
-  // Service pure member functions
-  StatusCode initialize() override;
-  StatusCode finalize() override;
-
-  // Pointer to the root of G4 geometry tree
-  G4VPhysicalVolume* constructWorld() override;
-  void constructSDandField() override;
-
- private:
-  // G4 geometry variables
-  G4VPhysicalVolume* m_world_root{nullptr};
-  dd4hep::sim::Geant4GeometryInfo* geoinfo{nullptr};
-  std::string m_world_material;
-  std::string m_world_pv_name;
-  std::string m_world_lv_name;
-
-  Gaudi::Property<bool> m_debugMaterials{this, "DebugMaterials", false};
-  Gaudi::Property<bool> m_debugElements{this, "DebugElements", false};
-  Gaudi::Property<bool> m_debugShapes{this, "DebugShapes", false};
-  Gaudi::Property<bool> m_debugVolumes{this, "DebugVolumes", false};
-  Gaudi::Property<bool> m_debugPlacements{this, "DebugPlacements", false};
-  Gaudi::Property<bool> m_debugRegions{this, "DebugRegions", false};
-  Gaudi::Property<std::map<std::string, std::string>> m_sensdetmappings{
-      this, "SensDetMappings", {}};
-  ServiceHandle<LHCb::Det::LbDD4hep::IDD4hepSvc> m_dd4Svc{
-      this, "DD4hepSvc", "LHCb::Det::LbDD4hep::DD4hepSvc"};
-
-  Gaudi::Property<std::string> m_mag_field_mgr{this, "FieldManager", ""};
-
-  // Services accessors
-  inline ISvcLocator* svcLocator() const { return serviceLocator(); }
-  StatusCode register_mag_field(const std::string& name, G4LogicalVolume*);
-  StatusCode register_sensitive(const std::string& name, G4LogicalVolume*);
-
-  // Extract the object type name
-  template <class T>
-  inline const std::string objectTypeName(T object) {
-    return object ? std::string(System::typeinfoName(typeid(*object)))
-                  : std::string("'UNKNOWN_type'");
-  }
-
-  // Tabulated properties
-  template <class T>
-  StatusCode copyTableProperties(const T& src_table,
-                                 G4MaterialPropertiesTable* dst_table);
-
-  // Storage maps to manage assignment of sensdet factories to volumes
-  std::map<GiGaFactoryBase<G4VSensitiveDetector>*, std::set<G4LogicalVolume*>>
-      mmap_sensdet_to_lvols;
-  std::map<std::string, ToolHandle<GiGaFactoryBase<G4VSensitiveDetector>>>
-      mmap_name_to_sensdetfac;
-
-  std::atomic_bool m_found_global_fieldmgr{false};
-  std::map<GiGaFactoryBase<G4FieldManager, bool>*, std::set<G4LogicalVolume*>>
-      mmap_fieldmgr_to_lvols;
-  std::map<std::string, ToolHandle<GiGaFactoryBase<G4FieldManager, bool>>>
-      mmap_name_to_fieldmgrfac;
-};
-// ============================================================================
-// Implementation file for class : GaussGeo
-//
-// 2015-11-11 : Dmitry Popov
-// ============================================================================
-
-DECLARE_COMPONENT(DD4hepCnvSvc)
-
-StatusCode DD4hepCnvSvc::initialize() {
-  auto sc = extends::initialize();
-  auto& g4map = dd4hep::sim::Geant4Mapping::instance();
-  dd4hep::setPrintLevel(DD4hepGaudiMessaging::Convert(msgLevel()));
-  dd4hep::DetElement world = m_dd4Svc->getDetector().world();
-  dd4hep::sim::Geant4Converter conv(dd4hep::Detector::getInstance(),
-                                    DD4hepGaudiMessaging::Convert(msgLevel()));
-  conv.debugMaterials = m_debugMaterials.value();
-  conv.debugElements = m_debugElements.value();
-  conv.debugShapes = m_debugShapes.value();
-  conv.debugVolumes = m_debugVolumes.value();
-  conv.debugPlacements = m_debugPlacements.value();
-  conv.debugRegions = m_debugRegions.value();
-
-  dd4hep::sim::Geant4GeometryInfo* geoinfo = conv.create(world).detach();
-  geoinfo->printLevel = DD4hepGaudiMessaging::Convert(msgLevel());
-
-  g4map.attach(geoinfo);
-  m_world_root = geoinfo->world();
-  // Create Geant4 volume manager only if not yet available
-  g4map.volumeManager();
-  // Printout all active volumes and assigned sensitive detectors from dd4hep
-  if (msgLevel(MSG::DEBUG)) {
-    debug() << "Stored paths in volume manager: " << endmsg;
-    for (auto& pp : g4map.volumeManager()->g4Paths) {
-      debug() << "/";
-      for (auto& pv : pp.first) {
-        debug() << pv->GetName() << "/";
-      }
-      debug() << " ID:" << pp.second << endmsg;
-    }
-    for (auto& [dd4hep_volume, g4_volume] : g4map.data().g4Volumes) {
-      if (!dd4hep_volume.isValid() || !dd4hep_volume.isSensitive()) {
-        continue;
-      }
-      auto dd4hep_sensdet_name = dd4hep_volume.sensitiveDetector().name();
-      debug() << "Active volume '" << dd4hep_volume.name() << "' SensDet: '"
-              << dd4hep_sensdet_name << "'" << endmsg;
-      if (dd4hep_volume.isSensitive()) {
-      }
-    }
-  }
-
-  // We now loop over the existing logical volume mappings and extract the
-  // sensitive detector knowledge from the DD4hep volumes and map them to the
-  // requested Gaussino factories
-  if (m_sensdetmappings.size() > 0) {
-    for (auto& [dd4hep_volume, g4_volume] : g4map.data().g4Volumes) {
-      if (!dd4hep_volume.isValid()) {
-        continue;
-      }
-      if (dd4hep_volume.isSensitive()) {
-        auto dd4hep_sensdet_name = dd4hep_volume.sensitiveDetector().name();
-        // Now only continue if the sensitive volume information is present in
-        // the factory mappings provided
-        if (m_sensdetmappings.find(dd4hep_sensdet_name) !=
-            std::end(m_sensdetmappings)) {
-          auto tool_name = m_sensdetmappings[dd4hep_sensdet_name];
-          sc &= register_sensitive(tool_name, g4_volume);
-        }
-      }
-    }
-  }
-
-  // Register the factory for the global magnetic field
-  if (!m_mag_field_mgr.empty()) {
-    sc &= register_mag_field(m_mag_field_mgr, nullptr);
-  } else {
-    warning() << "Global magnetic Field was not requested to be loaded"
-              << endmsg;
-  }
-  return sc;
-}
-
-StatusCode DD4hepCnvSvc::finalize() { return extends::finalize(); }
-
-//=============================================================================
-// Retrieve the pointer to G4 geometry tree root
-//=============================================================================
-G4VPhysicalVolume* DD4hepCnvSvc::constructWorld() {
-  // Simply return the world root volume. It was populated during the
-  // initialisation
-  return m_world_root;
-}
-
-void DD4hepCnvSvc::constructSDandField() {
-  auto sdmanager = G4SDManager::GetSDMpointer();
-  for (auto& [sensdetfac, vols] : mmap_sensdet_to_lvols) {
-    debug() << "Assigning " << sensdetfac->name() << " to " << vols.size()
-            << " logical volumes" << endmsg;
-    auto sensdet = sensdetfac->construct();
-    sdmanager->AddNewDetector(sensdet);
-    for (auto* vol : vols) {
-      vol->SetSensitiveDetector(sensdet);
-    }
-  }
-
-  for (auto& [fieldmgrfac, vols] : mmap_fieldmgr_to_lvols) {
-    // Catch the global field manager
-    if (vols.size() == 1 && *std::begin(vols) == nullptr) {
-      debug() << "Constructing global " << fieldmgrfac->name() << "." << endmsg;
-      fieldmgrfac->construct(true);
-    } else {
-      auto fieldmgr = fieldmgrfac->construct(false);
-      debug() << "Assigning " << fieldmgrfac->name() << " to " << vols.size()
-              << " logical volumes" << endmsg;
-      for (auto* vol : vols) {
-        vol->SetFieldManager(fieldmgr, false);
-      }
-    }
-  }
-}
-
-//=============================================================================
-// Instantiate a Magnetic Field Factories
-//=============================================================================
-StatusCode DD4hepCnvSvc::register_mag_field(const std::string& name,
-                                            G4LogicalVolume* vol) {
-  // First check if we have already obtained the magnetic field factory for the
-  // provided name.
-  if (!vol && m_found_global_fieldmgr) {
-    error() << "Tried to register second global magnetic field manager"
-            << endmsg;
-    return StatusCode::FAILURE;
-  }
-  auto it = mmap_name_to_fieldmgrfac.find(name);
-  if (it == std::end(mmap_name_to_fieldmgrfac)) {
-    mmap_name_to_fieldmgrfac.emplace(std::piecewise_construct,
-                                     std::forward_as_tuple(name),
-                                     std::forward_as_tuple(name, this));
-
-    if (!mmap_name_to_fieldmgrfac[name].retrieve().isSuccess()) {
-      warning() << "Could not field manager " << name << "." << endmsg;
-      warning() << "What do we say to the geo service? Not today ..." << endmsg;
-    }
-  }
-
-  // Now fill the map of field managers to volumes
-  if (auto& fieldmgr = mmap_name_to_fieldmgrfac[name]; fieldmgr) {
-    if (mmap_fieldmgr_to_lvols.find(fieldmgr.get()) ==
-        std::end(mmap_fieldmgr_to_lvols)) {
-      mmap_fieldmgr_to_lvols[fieldmgr.get()] = {};
-    }
-    mmap_fieldmgr_to_lvols[fieldmgr.get()].insert(vol);
-    if (vol) {
-      debug() << "Asked to use field " << name << " for " << vol->GetName()
-              << "" << endmsg;
-    }
-  }
-  if (!vol) {
-    auto giga_fmanager = mmap_name_to_fieldmgrfac[name];
-    info() << "Global 'Field Manager' is set to '"
-           << objectTypeName(giga_fmanager) << "/" << giga_fmanager->name()
-           << "'" << endmsg;
-    m_found_global_fieldmgr = true;
-  }
-
-  return StatusCode::SUCCESS;
-}
-
-//=============================================================================
-// Instantiate a Sensitive Detector object
-//=============================================================================
-StatusCode DD4hepCnvSvc::register_sensitive(const std::string& name, G4LogicalVolume* vol) {
-  // First check if we have already obtained the sensitive detector factory for the
-  // provided name.
-  auto it = mmap_name_to_sensdetfac.find(name);
-  if(it == std::end(mmap_name_to_sensdetfac)){
-    mmap_name_to_sensdetfac.emplace(std::piecewise_construct,
-                                     std::forward_as_tuple(name),
-                                     std::forward_as_tuple(name, this));
-
-    if (!mmap_name_to_sensdetfac[name].retrieve().isSuccess()) {
-    //mmap_name_to_sensdetfac[name] = nullptr;
-    //getTool(name, mmap_name_to_sensdetfac[name], this);
-    // Check if successful
-    //if(!mmap_name_to_sensdetfac[name]){
-      warning() << "Could not retrieve sensitive detector " << name << "." << endmsg;
-      warning() << "What do we say to the geo service? Not today ..." << endmsg;
-    }
-  }
-  // Now fill the map of identified sensitive detectors to volumes
-  if(auto sensdet = mmap_name_to_sensdetfac[name]; sensdet){
-    if(mmap_sensdet_to_lvols.find(sensdet.get()) == std::end(mmap_sensdet_to_lvols)){
-      mmap_sensdet_to_lvols[sensdet.get()] = {};
-    }
-    mmap_sensdet_to_lvols[sensdet.get()].insert(vol);
-    if(vol){
-      debug() << "Asked to use sens det " << name << " for " << vol->GetName() << "" << endmsg;
-    }
-  }
-  return StatusCode::SUCCESS;
-}
diff --git a/Sim/DD4hepCnv/src/component/LHCbDD4hepCnvSvc.cpp b/Sim/DD4hepCnv/src/component/LHCbDD4hepCnvSvc.cpp
new file mode 100644
index 000000000..a6d46edc3
--- /dev/null
+++ b/Sim/DD4hepCnv/src/component/LHCbDD4hepCnvSvc.cpp
@@ -0,0 +1,21 @@
+#include "GiGaMTDD4hep/DD4hepCnvSvc.h"
+#include "LbDD4hep/IDD4hepSvc.h"
+
+// ============================================================================
+// Conversion service for convertion DD4hep geometry from LHCb to Geant4
+//
+// 2020-6-15 : Dominik Muller
+// ============================================================================
+
+class LHCbDD4hepCnvSvc : public DD4hepCnvSvc {
+private:
+  using DD4hepCnvSvc::DD4hepCnvSvc;
+  ServiceHandle<LHCb::Det::LbDD4hep::IDD4hepSvc> m_dd4Svc{this, "DD4hepSvc", "LHCb::Det::LbDD4hep::DD4hepSvc"};
+
+protected:
+  virtual const dd4hep::Detector& getDetector() const override;
+};
+
+DECLARE_COMPONENT( LHCbDD4hepCnvSvc )
+
+const dd4hep::Detector& LHCbDD4hepCnvSvc::getDetector() const { return m_dd4Svc->getDetector(); }
diff --git a/Sim/Gauss/python/Gauss/Configuration.py b/Sim/Gauss/python/Gauss/Configuration.py
index 52d347f66..991622c4d 100755
--- a/Sim/Gauss/python/Gauss/Configuration.py
+++ b/Sim/Gauss/python/Gauss/Configuration.py
@@ -32,6 +32,7 @@ class Gauss(LHCbConfigurableUser):
         "MergeGenFSR": False,
         "Debug": False,
         "ReDecay": False,
+        "UseLHCbGeo": True,
         "ForceRandomEngine": 'NONE',
         "Phases": ["Generator", "Simulation"],
         "BeamMomentum": 3.5 * SystemOfUnits.TeV,  # NOQA
@@ -65,6 +66,7 @@ class Gauss(LHCbConfigurableUser):
        , 'EnablePack'     : """ Flag to turn on or off the packing of the SIM data """  # NOQA
        , 'DataPackingChecks' : """ Flag to turn on or off the running of some test algorithms to check the quality of the data packing """  # NOQA
        , "ForceRandomEngine"   : """Force the random number generator for all AlgSeeders"""  # NOQA
+       , "UseLHCbGeo": """Flag to redirect configuration of geometry construction to LHCbGeo()""",
        }
     KnownHistOptions = ['NONE', 'DEFAULT']
     TrackingSystem = ['VELO', 'TT', 'IT', 'OT']
@@ -246,9 +248,10 @@ class Gauss(LHCbConfigurableUser):
         if "Simulation" in Gaussino().getProp("Phases"):
             from Gauss import G4Physics
             G4Physics().apply()
-            from Gauss.Geometry import LHCbGeo
-            LHCbGeo().setOtherProps(LHCbApp(), ['DetectorGeo'])
-            LHCbGeo().apply()
+            if self.getProp("UseLHCbGeo"):
+                from Gauss.Geometry import LHCbGeo
+                LHCbGeo().setOtherProps(LHCbApp(), ['DetectorGeo'])
+                LHCbGeo().apply()
 
         crossingList = self.defineCrossingList()
 
diff --git a/Sim/Gauss/python/Gauss/Geometry/BLS.py b/Sim/Gauss/python/Gauss/Geometry/BLS.py
index 0418c198e..988391447 100644
--- a/Sim/Gauss/python/Gauss/Geometry/BLS.py
+++ b/Sim/Gauss/python/Gauss/Geometry/BLS.py
@@ -13,10 +13,10 @@ class BLS(det_base):
         # 1. Add the mapping to have the DD4hepCnvSvc instrument
         # the G4 volume with the correct sensdet factory if marked with a
         # dd4hep sensitive detector named VP
-        from Configurables import DD4hepCnvSvc
-        mappings = DD4hepCnvSvc().getProp('SensDetMappings')
+        from Configurables import LHCbDD4hepCnvSvc
+        mappings = LHCbDD4hepCnvSvc().getProp('SensDetMappings')
         mappings['Bls'] = 'GiGaSensDetTrackerDD4hep/BlsSDet'
-        DD4hepCnvSvc().SensDetMappings = mappings
+        LHCbDD4hepCnvSvc().SensDetMappings = mappings
 
         # Add the necessary dd4hep includes for the VP. Also added all the
         # dependencies for material definitions that were identified using
diff --git a/Sim/Gauss/python/Gauss/Geometry/Configuration.py b/Sim/Gauss/python/Gauss/Geometry/Configuration.py
index 45b793180..2586fe9f1 100644
--- a/Sim/Gauss/python/Gauss/Geometry/Configuration.py
+++ b/Sim/Gauss/python/Gauss/Geometry/Configuration.py
@@ -84,8 +84,8 @@ class LHCbGeo(LHCbConfigurableUser):
                 from Configurables import GaussGeo
                 GaussGeo().OutputLevel = DEBUG
             else:
-                from Configurables import DD4hepCnvSvc
-                DD4hepCnvSvc().OutputLevel = DEBUG
+                from Configurables import LHCbDD4hepCnvSvc
+                LHCbDD4hepCnvSvc().OutputLevel = DEBUG
 
         detPieces = {'BeforeUpstreamRegion': [],
                      'UpstreamRegion': [],
@@ -171,7 +171,7 @@ class LHCbGeo(LHCbConfigurableUser):
         if self.getProp('DD4hep') is False:
             dettool.GiGaMTGeoSvc = "GaussGeo"
         else:
-            dettool.GiGaMTGeoSvc = "DD4hepCnvSvc"
+            dettool.GiGaMTGeoSvc = "LHCbDD4hepCnvSvc"
         dettool.SensDetVolumeMap = self.getProp('SensDetMap')
 
         dettool.AfterGeoConstructionTools = self.getProp('ExtraGeoTools')
diff --git a/Sim/Gauss/python/Gauss/Geometry/Magnet.py b/Sim/Gauss/python/Gauss/Geometry/Magnet.py
index b27751f5c..1698620af 100644
--- a/Sim/Gauss/python/Gauss/Geometry/Magnet.py
+++ b/Sim/Gauss/python/Gauss/Geometry/Magnet.py
@@ -25,8 +25,8 @@ class Magnet(det_base):
         from Gauss.Geometry.Helpers import getsubdetector
         # Only bother with the FIELD Geometry if simulated.
         if use_dd4hep_svc:
-            from Configurables import DD4hepCnvSvc
-            geosvc = DD4hepCnvSvc()
+            from Configurables import LHCbDD4hepCnvSvc
+            geosvc = LHCbDD4hepCnvSvc()
         else:
             from Configurables import GaussGeo
             geosvc = GaussGeo()
diff --git a/Sim/Gauss/python/Gauss/Geometry/VP.py b/Sim/Gauss/python/Gauss/Geometry/VP.py
index 5b3b11a95..1012e612a 100644
--- a/Sim/Gauss/python/Gauss/Geometry/VP.py
+++ b/Sim/Gauss/python/Gauss/Geometry/VP.py
@@ -10,13 +10,13 @@ class VP(det_base):
 
     def ApplyDetectorDD4hep(self, basePieces, detPieces):
         # Configuring the DD4hep detector conversion.
-        # 1. Add the mapping to have the DD4hepCnvSvc instrument
+        # 1. Add the mapping to have the LHCbDD4hepCnvSvc instrument
         # the G4 volume with the correct sensdet factory if marked with a
         # dd4hep sensitive detector named VP
-        from Configurables import DD4hepCnvSvc
-        mappings = DD4hepCnvSvc().getProp('SensDetMappings')
+        from Configurables import LHCbDD4hepCnvSvc
+        mappings = LHCbDD4hepCnvSvc().getProp('SensDetMappings')
         mappings['VP'] = 'GiGaSensDetTrackerDD4hep/VPSDet'
-        DD4hepCnvSvc().SensDetMappings = mappings
+        LHCbDD4hepCnvSvc().SensDetMappings = mappings
 
         # Add the necessary dd4hep includes for the VP. Also added all the
         # dependencies for material definitions that were identified using
-- 
GitLab


From 3d344282b3fff0d7a47fffae4b68d632a633455c Mon Sep 17 00:00:00 2001
From: Dominik Muller <dominik.muller@cern.ch>
Date: Mon, 14 Sep 2020 18:13:28 +0200
Subject: [PATCH 62/90] Fix compilation errors due to changes to Property in
 Gaudi

---
 Gen/GenCuts/src_future/GenericGenCutTool.cpp          | 6 +++---
 Gen/GenCuts/src_future/GenericGenCutTool.h            | 6 +++---
 Gen/GenCuts/src_future/GenericGenCutToolWithDecay.cpp | 4 ++--
 3 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/Gen/GenCuts/src_future/GenericGenCutTool.cpp b/Gen/GenCuts/src_future/GenericGenCutTool.cpp
index 3d79a46ad..9558c4f2f 100644
--- a/Gen/GenCuts/src_future/GenericGenCutTool.cpp
+++ b/Gen/GenCuts/src_future/GenericGenCutTool.cpp
@@ -188,7 +188,7 @@ LoKi::GenCutTool::~GenCutTool() {}
 // =============================================================================
 // update-handler for the property "DecayDescriptor" 
 // =============================================================================
-void LoKi::GenCutTool::updateDescriptor ( Property& /* p */ ) 
+void LoKi::GenCutTool::updateDescriptor ( Gaudi::Details::PropertyBase& /* p */ ) 
 {
   // no action if not yet initialized 
   if ( Gaudi::StateMachine::INITIALIZED > FSMState() ) { return ; }
@@ -198,7 +198,7 @@ void LoKi::GenCutTool::updateDescriptor ( Property& /* p */ )
 // =============================================================================
 // update-handler for the properties "Cuts","Preambulo","Factory" 
 // =============================================================================
-void LoKi::GenCutTool::updateCuts       ( Property& /* p */ ) 
+void LoKi::GenCutTool::updateCuts       ( Gaudi::Details::PropertyBase& /* p */ ) 
 {
   // no action if not yet initialized 
   if ( Gaudi::StateMachine::INITIALIZED > FSMState() ) { return ; }
@@ -209,7 +209,7 @@ void LoKi::GenCutTool::updateCuts       ( Property& /* p */ )
 // =============================================================================
 // update-handler for the properties "XAxis","YAxis"
 // =============================================================================
-void LoKi::GenCutTool::updateHistos     ( Property& /* p */ ) 
+void LoKi::GenCutTool::updateHistos     ( Gaudi::Details::PropertyBase& /* p */ ) 
 {
   // no action if not yet initialized 
   if ( Gaudi::StateMachine::INITIALIZED > FSMState() ) { return ; }
diff --git a/Gen/GenCuts/src_future/GenericGenCutTool.h b/Gen/GenCuts/src_future/GenericGenCutTool.h
index c65379e37..b4943b439 100644
--- a/Gen/GenCuts/src_future/GenericGenCutTool.h
+++ b/Gen/GenCuts/src_future/GenericGenCutTool.h
@@ -130,11 +130,11 @@ namespace LoKi
   protected:
     // =========================================================================
     /// update-handler for the property "Decay" 
-    void updateDescriptor ( Property& /* p */ ) ;
+    void updateDescriptor ( Gaudi::Details::PropertyBase& /* p */ ) ;
     /// update-handler for the properties "Cuts","Preambulo","Factory" 
-    void updateCuts       ( Property& /* p */ ) ;
+    void updateCuts       ( Gaudi::Details::PropertyBase& /* p */ ) ;
     /// update-handler for the properties "XAxis","YAxis"
-    void updateHistos     ( Property& /* p */ ) ;
+    void updateHistos     ( Gaudi::Details::PropertyBase& /* p */ ) ;
     // =========================================================================
   private:
     // =========================================================================
diff --git a/Gen/GenCuts/src_future/GenericGenCutToolWithDecay.cpp b/Gen/GenCuts/src_future/GenericGenCutToolWithDecay.cpp
index e78515f86..52d3fac3d 100644
--- a/Gen/GenCuts/src_future/GenericGenCutToolWithDecay.cpp
+++ b/Gen/GenCuts/src_future/GenericGenCutToolWithDecay.cpp
@@ -127,7 +127,7 @@ namespace LoKi
     // ========================================================================
   public:
     // ========================================================================
-    void updateSignal ( Property& /* p */ ) ;
+    void updateSignal ( Gaudi::Details::PropertyBase& /* p */ ) ;
     // ========================================================================
   private:
     // ========================================================================
@@ -382,7 +382,7 @@ bool LoKi::GenCutToolWithDecay::applyCut
 // ============================================================================
 // update-handler for the property "SignalPID" 
 // =============================================================================
-void LoKi::GenCutToolWithDecay::updateSignal  ( Property& /* p */ ) 
+void LoKi::GenCutToolWithDecay::updateSignal  ( Gaudi::Details::PropertyBase& /* p */ ) 
 {
   // no action if not yet initialized 
   if ( Gaudi::StateMachine::INITIALIZED > FSMState() ) { return ; }
-- 
GitLab


From ddf55fd64a7687c6ee02ded4dac29e0805ad0e37 Mon Sep 17 00:00:00 2001
From: Dominik Muller <dominik.muller@cern.ch>
Date: Fri, 16 Oct 2020 16:35:25 +0200
Subject: [PATCH 63/90] Fixes to tracking cuts and HCal sensitive detector code

---
 Sim/Gauss/python/Gauss/Geometry/det_base.py   |  5 +-
 Sim/GaussCalo/src/CaloSensDet.icpp            |  1 +
 Sim/GaussCalo/src/CellFromLHCbGeo.h           |  6 ++
 Sim/GaussCalo/src/HcalSensDet.cpp             |  3 +-
 Sim/GaussPhysics/src/cuts/TrCutsRunAction.cpp | 56 +++++++++----------
 5 files changed, 40 insertions(+), 31 deletions(-)

diff --git a/Sim/Gauss/python/Gauss/Geometry/det_base.py b/Sim/Gauss/python/Gauss/Geometry/det_base.py
index 54854300c..0a60198dd 100644
--- a/Sim/Gauss/python/Gauss/Geometry/det_base.py
+++ b/Sim/Gauss/python/Gauss/Geometry/det_base.py
@@ -1,5 +1,6 @@
 from Configurables import LHCbConfigurableUser
 from Gaudi.Configuration import Configurable
+from Gaudi.Configuration import log
 
 
 class det_base(LHCbConfigurableUser):
@@ -35,14 +36,14 @@ class det_base(LHCbConfigurableUser):
     @Simulate.setter
     def Simulate(self, value):
         if not self.Active:
-            raise RuntimeError(
+            log.warning(
                 "Setting {} to be simulated but not active".format(self.name()))
         self.simulate = value
 
     @Monitor.setter
     def Monitor(self, value):
         if not self.Active or not self.Simulate:
-            raise RuntimeError(
+            log.warning(
                 "Setting {} to be monitored but not active"
                 "or simulated".format(self.name()))
         self.monitor = value
diff --git a/Sim/GaussCalo/src/CaloSensDet.icpp b/Sim/GaussCalo/src/CaloSensDet.icpp
index ec8d8b05b..588b43bac 100755
--- a/Sim/GaussCalo/src/CaloSensDet.icpp
+++ b/Sim/GaussCalo/src/CaloSensDet.icpp
@@ -270,6 +270,7 @@ bool CaloSensDet<CELLGETTER>::ProcessHits(G4Step* step,
 
   const LHCb::CaloCellID cellID = this->cell(step);
   if (LHCb::CaloCellID() == cellID) {
+    warning("Could not find LHCb::CaloCellID");
     return false;
   }
 
diff --git a/Sim/GaussCalo/src/CellFromLHCbGeo.h b/Sim/GaussCalo/src/CellFromLHCbGeo.h
index 2ee3ad7ea..8fabded56 100644
--- a/Sim/GaussCalo/src/CellFromLHCbGeo.h
+++ b/Sim/GaussCalo/src/CellFromLHCbGeo.h
@@ -80,6 +80,9 @@ class CellFromLHCbGeo : public virtual GiGaMessage {
   */
   // ============================================================================
   inline void GeoBaseInitialize() {
+      if(m_initialized){
+          return;
+      }
     // locate start volumes
     for (auto& vol : m_startVolumeNames) {
       // look through converted volumes
@@ -99,6 +102,7 @@ class CellFromLHCbGeo : public virtual GiGaMessage {
       throw std::runtime_error(std::string(__PRETTY_FUNCTION__) + "G4LogicalVolume* points to 0 for '" +
                               m_endVolumeName + "'");
     }
+    m_initialized = true;
   }
 
   public:
@@ -120,6 +124,8 @@ class CellFromLHCbGeo : public virtual GiGaMessage {
     Volumes m_start;
     // translation table
     mutable Table m_table;
+  private:
+    bool m_initialized{false};
 };
 
 
diff --git a/Sim/GaussCalo/src/HcalSensDet.cpp b/Sim/GaussCalo/src/HcalSensDet.cpp
index 41e48877d..f23902fd0 100755
--- a/Sim/GaussCalo/src/HcalSensDet.cpp
+++ b/Sim/GaussCalo/src/HcalSensDet.cpp
@@ -93,6 +93,7 @@ bool HcalSensDet<CELLGETTER>::fillHitInfo(
     if (fr > 1.e-5) {
       hit->add(slot, energy * fr).ignore();
     }
+    ++slot;
   }
 
   return true;
@@ -146,7 +147,7 @@ class HcalSensDetFAC : public CaloSensDetFAC<HcalSensDet<CELLGETTER>> {
   using typename base::CaloSensDetFAC;
   virtual calotype* construct() const override {
     auto tmp = base::construct();
-    tmp->m_slotWidth = m_slotWidth;
+    tmp->m_slotWidth = m_slotWidth.value();
     return tmp;
   }
 };
diff --git a/Sim/GaussPhysics/src/cuts/TrCutsRunAction.cpp b/Sim/GaussPhysics/src/cuts/TrCutsRunAction.cpp
index f75fbefc9..99c12386e 100755
--- a/Sim/GaussPhysics/src/cuts/TrCutsRunAction.cpp
+++ b/Sim/GaussPhysics/src/cuts/TrCutsRunAction.cpp
@@ -108,32 +108,32 @@ class TrCutsRunActionFAC
   G4VPhysicsConstructor* construct() const override {
     auto ret = new TrCutsRunAction{};
     ret->SetMessageInterface(message_interface());
-    ret->m_ecut = m_ecut;
-    ret->m_phcut = m_phcut;
-    ret->m_pKpicut = m_pKpicut;
-    ret->m_ocut = m_ocut;
-    ret->m_ncut = m_ncut;
-    ret->m_nucut = m_nucut;
-    ret->m_mcut = m_mcut;
-    ret->m_killloops = m_killloops;
-    ret->m_maxsteps = m_maxsteps;
-    ret->m_minstep = m_minstep;
-    ret->m_minx = m_minx;
-    ret->m_miny = m_miny;
-    ret->m_minz = m_minz;
-    ret->m_maxx = m_maxx;
-    ret->m_maxy = m_maxy;
-    ret->m_maxz = m_maxz;
-    ret->m_killPingPong = m_killPingPong;
-    ret->m_nMaxForPingPong = m_nMaxForPingPong;
-    ret->m_nMaxOfPingPong = m_nMaxOfPingPong;
-    ret->m_stepLenghtPingPong = m_stepLenghtPingPong;
-    ret->m_killAtOrigin = m_killAtOrigin;
-    ret->m_killZeroSteps = m_killZeroSteps;
-    ret->m_nStepsForZero = m_nStepsForZero;
-    ret->m_zeroMaxLenght = m_zeroMaxLenght;
-    ret->m_maxNZeroSteps = m_maxNZeroSteps;
-    ret->m_world = m_world;
+    ret->m_ecut = m_ecut.value();
+    ret->m_phcut = m_phcut.value();
+    ret->m_pKpicut = m_pKpicut.value();
+    ret->m_ocut = m_ocut.value();
+    ret->m_ncut = m_ncut.value();
+    ret->m_nucut = m_nucut.value();
+    ret->m_mcut = m_mcut.value();
+    ret->m_killloops = m_killloops.value();
+    ret->m_maxsteps = m_maxsteps.value();
+    ret->m_minstep = m_minstep.value();
+    ret->m_minx = m_minx.value();
+    ret->m_miny = m_miny.value();
+    ret->m_minz = m_minz.value();
+    ret->m_maxx = m_maxx.value();
+    ret->m_maxy = m_maxy.value();
+    ret->m_maxz = m_maxz.value();
+    ret->m_killPingPong = m_killPingPong.value();
+    ret->m_nMaxForPingPong = m_nMaxForPingPong.value();
+    ret->m_nMaxOfPingPong = m_nMaxOfPingPong.value();
+    ret->m_stepLenghtPingPong = m_stepLenghtPingPong.value();
+    ret->m_killAtOrigin = m_killAtOrigin.value();
+    ret->m_killZeroSteps = m_killZeroSteps.value();
+    ret->m_nStepsForZero = m_nStepsForZero.value();
+    ret->m_zeroMaxLenght = m_zeroMaxLenght.value();
+    ret->m_maxNZeroSteps = m_maxNZeroSteps.value();
+    ret->m_world = m_world.value();
     return ret;
   }
   Gaudi::Property<double> m_ecut{this, "ElectronTrCut", 1.0 * CLHEP::MeV};
@@ -147,8 +147,8 @@ class TrCutsRunActionFAC
   Gaudi::Property<int> m_maxsteps{this, "MaxNumberSteps", 100};
   Gaudi::Property<double> m_minstep{this, "MininumStep", 0.001};
   Gaudi::Property<double> m_minx{this, "MinX", -10000 * CLHEP::mm};
-  Gaudi::Property<double> m_miny{this, "MinY", -5000 * CLHEP::mm};
-  Gaudi::Property<double> m_minz{this, "MinZ", -10000 * CLHEP::mm};
+  Gaudi::Property<double> m_miny{this, "MinY", -10000 * CLHEP::mm};
+  Gaudi::Property<double> m_minz{this, "MinZ", -5000 * CLHEP::mm};
   Gaudi::Property<double> m_maxx{this, "MaxX", 10000 * CLHEP::mm};
   Gaudi::Property<double> m_maxy{this, "MaxY", 10000 * CLHEP::mm};
   Gaudi::Property<double> m_maxz{this, "MaxZ", 25000 * CLHEP::mm};
-- 
GitLab


From f603fb9203158eb821f776baf36788852826ee2c Mon Sep 17 00:00:00 2001
From: Dominik Muller <dominik.muller@cern.ch>
Date: Fri, 16 Oct 2020 21:35:23 +0200
Subject: [PATCH 64/90] Removed statPrint for new monitoring compatibility

---
 Gen/GenCuts/src_future/GenericGenCutTool.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Gen/GenCuts/src_future/GenericGenCutTool.cpp b/Gen/GenCuts/src_future/GenericGenCutTool.cpp
index 9558c4f2f..415e29104 100644
--- a/Gen/GenCuts/src_future/GenericGenCutTool.cpp
+++ b/Gen/GenCuts/src_future/GenericGenCutTool.cpp
@@ -375,7 +375,7 @@ StatusCode LoKi::GenCutTool::initialize()
   sc = decodeHistos     () ;
   if ( sc.isFailure() ) { return Error ( "Unable to decode histos" , sc ) ; }
   //
-  if ( ( statPrint() || msgLevel ( MSG::DEBUG ) ) && !m_fill_counters )
+  if (  msgLevel ( MSG::DEBUG )  && !m_fill_counters )
   { m_fill_counters = true ; }
   //
   if ( m_fill_counters )
-- 
GitLab


From a5022ab3f50b3221c808ee0a8aa8f54937f4219d Mon Sep 17 00:00:00 2001
From: Dominik Muller <dominik.muller@cern.ch>
Date: Mon, 26 Oct 2020 17:25:45 +0100
Subject: [PATCH 65/90] Removed testing logic for calohit track assignment to
 fix disagreement of Gauss on Gaussino wrt to Sim10

---
 Sim/GaussCalo/src/CaloSensDet.icpp | 2 --
 1 file changed, 2 deletions(-)

diff --git a/Sim/GaussCalo/src/CaloSensDet.icpp b/Sim/GaussCalo/src/CaloSensDet.icpp
index 588b43bac..e02ab3b27 100755
--- a/Sim/GaussCalo/src/CaloSensDet.icpp
+++ b/Sim/GaussCalo/src/CaloSensDet.icpp
@@ -308,8 +308,6 @@ bool CaloSensDet<CELLGETTER>::ProcessHits(G4Step* step,
     }
   }
 
-  sTrackID = trackID;
-
   // Does the hit exist for the given track?
   CaloSubHit*& sub = hit->hit(sTrackID);  // ATTENTION
   // create new subhit if needed
-- 
GitLab


From 3f19be15b8ffdb089e6552ef520260e92a637b66 Mon Sep 17 00:00:00 2001
From: Michal Mazurek <michal.mazurek@cern.ch>
Date: Sun, 29 Nov 2020 19:42:20 +0100
Subject: [PATCH 66/90] fix toolchain behaviour for old-style CMake projects

---
 toolchain.cmake | 19 ++++++++++++++++++-
 1 file changed, 18 insertions(+), 1 deletion(-)

diff --git a/toolchain.cmake b/toolchain.cmake
index 2d56f7d32..556d8a3ac 100644
--- a/toolchain.cmake
+++ b/toolchain.cmake
@@ -15,7 +15,7 @@ if(NOT DEFINED GAUDI_OLD_STYLE_PROJECT)
   set(GAUDI_OLD_STYLE_PROJECT ${GAUDI_OLD_STYLE_PROJECT} CACHE BOOL "true if the top level CMakeLists file contains a call to gaudi_project")
 endif()
 
-if(NOT GAUDI_OLD_STYLE_PROJECT)
+if(NOT GAUDI_OLD_STYLE_PROJECT AND "$ENV{GAUDI_OLD_STYLE_PROJECT}" STREQUAL "")
   # for new style CMake projects, or vanilla CMake projects
   if("$ENV{BINARY_TAG}" STREQUAL "" OR "$ENV{LCG_VERSION}" STREQUAL "")
     message(FATAL_ERROR "The environment variables BINARY_TAG and LCG_VERSION mut be set for new style CMake projects")
@@ -46,6 +46,20 @@ else()
 # this check is needed because the toolchain is called when checking the
 # compiler (without the proper cache)
 if(NOT CMAKE_SOURCE_DIR MATCHES "CMakeTmp")
+  # Avoid using Gaudi's get_host_binary_tag.py script as it doesn't support Python 3.8
+  # https://gitlab.cern.ch/gaudi/Gaudi/-/issues/123
+  execute_process(COMMAND "lb-host-binary-tag"
+                  OUTPUT_VARIABLE HOST_BINARY_TAG
+                  RESULT_VARIABLE HOST_BINARY_RETURN
+                  ERROR_VARIABLE  HOST_BINARY_ERROR
+                  OUTPUT_STRIP_TRAILING_WHITESPACE)
+  set(HOST_BINARY_TAG ${HOST_BINARY_TAG} CACHE STRING "BINARY_TAG of the host")
+  if(HOST_BINARY_RETURN OR NOT HOST_BINARY_TAG)
+    message(FATAL_ERROR "Error getting host binary tag\nFailed to execute ${HOST_BINARY_TAG_COMMAND}\n"
+                        "HOST_BINARY_TAG value: ${HOST_BINARY_TAG}\n"
+                        "Program Return Value: ${HOST_BINARY_RETURN}\n"
+                        "Error Message: ${HOST_BINARY_ERROR}\n")
+  endif()
 
   find_file(default_toolchain NAMES GaudiDefaultToolchain.cmake
             HINTS ${CMAKE_SOURCE_DIR}/cmake
@@ -66,6 +80,9 @@ if(NOT CMAKE_SOURCE_DIR MATCHES "CMakeTmp")
     # - xenv (conflicts with the version in the build environment)
     list(FILTER CMAKE_PREFIX_PATH EXCLUDE REGEX "(LCG_|lcg/nightlies).*(ninja|Gaudi|xenv)")
   endif()
+
+  # Make sure that when the toolchain is invoked again it uses this branch
+  set(ENV{GAUDI_OLD_STYLE_PROJECT} "${CMAKE_SOURCE_DIR}")
 endif()
 endif()
 
-- 
GitLab


From c372ef722e3406addcf6f98bf9dd188c59103af6 Mon Sep 17 00:00:00 2001
From: Michal Mazurek <michal.mazurek@cern.ch>
Date: Tue, 8 Dec 2020 17:09:28 +0100
Subject: [PATCH 67/90] Fix failing test no. 1 GaussSys.gausssys

---
 GaussSys/tests/options/testGaussSys-30000000.py |  9 +++++++++
 GaussSys/tests/options/testGaussSys-defaults.py | 13 ++++++-------
 GaussSys/tests/qmtest/gausssys.qms/gausssys.qmt |  9 ++++++---
 3 files changed, 21 insertions(+), 10 deletions(-)
 create mode 100644 GaussSys/tests/options/testGaussSys-30000000.py

diff --git a/GaussSys/tests/options/testGaussSys-30000000.py b/GaussSys/tests/options/testGaussSys-30000000.py
new file mode 100644
index 000000000..158088017
--- /dev/null
+++ b/GaussSys/tests/options/testGaussSys-30000000.py
@@ -0,0 +1,9 @@
+from Configurables import Generation
+Generation().EventType = 30000000
+from Gaussino.Generation import GenPhase
+GenPhase().SampleGenerationTool = "MinimumBias"
+GenPhase().ProductionTool = "Pythia8Production"
+from Configurables import ToolSvc
+from Configurables import EvtGenDecay
+ToolSvc().addTool( EvtGenDecay )
+ToolSvc().EvtGenDecay.UserDecayFile = "$DECFILESROOT/dkfiles/minbias.dec"
diff --git a/GaussSys/tests/options/testGaussSys-defaults.py b/GaussSys/tests/options/testGaussSys-defaults.py
index f106b75b1..ded53d20a 100755
--- a/GaussSys/tests/options/testGaussSys-defaults.py
+++ b/GaussSys/tests/options/testGaussSys-defaults.py
@@ -3,16 +3,15 @@
 # ie. setting of random number seed and name of output files
 #
 
-from Gauss.Configuration import *
-
 #--Generator phase, set random numbers
-GaussGen = GenInit("GaussGen")
-GaussGen.FirstEventNumber = 1
-GaussGen.RunNumber        = 1082
+from Configurables import GenRndInit
+GenRndInit().FirstEventNumber = 1
+GenRndInit().RunNumber        = 1082
 
 #--Number of events
-nEvts = 1
-LHCbApp().EvtMax = nEvts
+from Configurables import Gauss
+Gauss().EvtMax = 1
+Gauss().EnableHive = True
 
 #--Set name of output files for given job (uncomment the lines)
 #  Note that if you do not set it Gauss will make a name based on event type,
diff --git a/GaussSys/tests/qmtest/gausssys.qms/gausssys.qmt b/GaussSys/tests/qmtest/gausssys.qms/gausssys.qmt
index beff50609..d9c94bf03 100755
--- a/GaussSys/tests/qmtest/gausssys.qms/gausssys.qmt
+++ b/GaussSys/tests/qmtest/gausssys.qms/gausssys.qmt
@@ -2,9 +2,12 @@
 <extension class="GaudiTest.GaudiExeTest" kind="test">
 <argument name="program"><text>gaudirun.py</text></argument>
 <argument name="args"><set>
-    <text>$GAUSSOPTS/Gauss-DEV.py</text>
-    <text>$DECFILESROOT/options/30000000.py</text>
-    <text>$LBPYTHIAROOT/options/Pythia.py</text> 
+    <text>$GAUSSROOT/options/Gauss-DEV.py</text>
+    <!-- <text>$DECFILESROOT/options/30000000.py</text> -->
+    <!-- TODO: Temporary fix in order to make it working on Gaussino -->
+    <text>$GAUSSSYSROOT/tests/options/testGaussSys-30000000.py</text>
+    <!-- -->
+    <text>$LBPYTHIA8ROOT/options/Pythia8.py</text>
     <text>$GAUSSSYSROOT/tests/options/testGaussSys-defaults.py</text>
 </set></argument>
 <argument name="timeout"><integer>1800</integer></argument>
-- 
GitLab


From 939823ae4b112a7f3c6fdba5eb5746e434306497 Mon Sep 17 00:00:00 2001
From: Michal Mazurek <michal.mazurek@cern.ch>
Date: Wed, 9 Dec 2020 14:35:39 +0100
Subject: [PATCH 68/90] Fix problem with std.vector & GenParticle

---
 Gen/LoKiGen/python/LoKiGen/tests.py     | 2 +-
 Gen/LoKiGen/tests/tst_JIRA_LBCORE461.py | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/Gen/LoKiGen/python/LoKiGen/tests.py b/Gen/LoKiGen/python/LoKiGen/tests.py
index f9699adb0..5bdc0b45c 100755
--- a/Gen/LoKiGen/python/LoKiGen/tests.py
+++ b/Gen/LoKiGen/python/LoKiGen/tests.py
@@ -63,7 +63,7 @@ def test1():
     print 'particle: ( p>>GID , p>>cos(GE) )=(%s,%s)' % (p >> GID,
                                                          p >> cos(GE))
 
-    gpv = std.vector('HepMC3::ConstGenParticlePtr')
+    gpv = std.vector('HepMC3::GenParticle')
     v = gpv()
 
     v.push_back(p)
diff --git a/Gen/LoKiGen/tests/tst_JIRA_LBCORE461.py b/Gen/LoKiGen/tests/tst_JIRA_LBCORE461.py
index 3be1923e4..702ecc917 100755
--- a/Gen/LoKiGen/tests/tst_JIRA_LBCORE461.py
+++ b/Gen/LoKiGen/tests/tst_JIRA_LBCORE461.py
@@ -12,7 +12,7 @@
 # =====================================================================================
 from LoKiGen.decorators import *
 
-GPV = std.vector('HepMC3::ConstGenParticlePtr')
+GPV = std.vector('HepMC3::GenParticle')
 v = GPV()
 
 p = HepMC.GenParticle()
-- 
GitLab


From 4f14ea8fbb92c9e309ac64bf163101b21069a619 Mon Sep 17 00:00:00 2001
From: Michal Mazurek <michal.mazurek@cern.ch>
Date: Wed, 13 Jan 2021 18:35:39 +0100
Subject: [PATCH 69/90] Prepare Gauss-on-Gaussino for the changes in the
 location of XML files

---
 Sim/Gauss/python/Gauss/Geometry/Configuration.py | 9 +++++++--
 Sim/Gauss/python/Gauss/Geometry/xml_writer.py    | 4 ++--
 2 files changed, 9 insertions(+), 4 deletions(-)

diff --git a/Sim/Gauss/python/Gauss/Geometry/Configuration.py b/Sim/Gauss/python/Gauss/Geometry/Configuration.py
index 2586fe9f1..de806bf6c 100644
--- a/Sim/Gauss/python/Gauss/Geometry/Configuration.py
+++ b/Sim/Gauss/python/Gauss/Geometry/Configuration.py
@@ -148,9 +148,14 @@ class LHCbGeo(LHCbConfigurableUser):
                 gaussgeo.GeoItemsNames.append(el)
         else:
             from Gauss.Geometry import xml_writer
-            from Configurables import LHCb__Det__LbDD4hep__DD4hepSvc
-            LHCb__Det__LbDD4hep__DD4hepSvc().DescriptionLocation = \
+            from Configurables import LHCb__Det__LbDD4hep__DD4hepSvc as DD4hepSvc
+            from Configurables import DDDBConf
+            desc_loc, desc_file = \
                 xml_writer.create_xml(self._listOfXMLIncludes_)
+            dddbconf = DDDBConf()
+            DD4hepSvc().DescriptionLocation = desc_loc
+            dddbconf.GeometryMain = desc_file
+            dddbconf.GeometryVersion = ''
 
         self.MakeItTalkToGaussino()
 
diff --git a/Sim/Gauss/python/Gauss/Geometry/xml_writer.py b/Sim/Gauss/python/Gauss/Geometry/xml_writer.py
index 137b41501..d7a921fed 100644
--- a/Sim/Gauss/python/Gauss/Geometry/xml_writer.py
+++ b/Sim/Gauss/python/Gauss/Geometry/xml_writer.py
@@ -10,7 +10,7 @@ import os
 # file
 def create_xml(includesfiles):
     unique_includes = list(OrderedDict.fromkeys(includesfiles))
-    detectorroot = os.path.join(os.environ['DETECTOR_PROJECT_ROOT'], 'compact/')
+    detectorroot = os.path.join(os.environ['DETECTOR_PROJECT_ROOT'], 'compact/trunk/')
 
     def addroot(p):
         if p[0] != '.' and p[0] != '/':
@@ -68,4 +68,4 @@ def create_xml(includesfiles):
     with open(tmpfile, "w") as f:
         f.write(xmlstr)
     log.info('Wrote xml file to {}'.format(tmpfile))
-    return tmpfile
+    return tempfile.tempdir, tmpfile.replace(tempfile.tempdir + '/', '')
-- 
GitLab


From a7d9bb55faa7aa671c2201b2adc40838e70e27da Mon Sep 17 00:00:00 2001
From: Michal Mazurek <michal.mazurek@cern.ch>
Date: Mon, 8 Feb 2021 16:29:02 +0100
Subject: [PATCH 70/90] Adapt sensdet_name_shortening test to Gaussino
 configuration

---
 .../tests/options/sensdet_name_shortening.py  | 58 +++++++++++++++----
 .../shortened_sensdet_name.qmt                |  7 +--
 2 files changed, 50 insertions(+), 15 deletions(-)

diff --git a/Sim/GaussTracker/tests/options/sensdet_name_shortening.py b/Sim/GaussTracker/tests/options/sensdet_name_shortening.py
index 237317fe1..acc3f0888 100755
--- a/Sim/GaussTracker/tests/options/sensdet_name_shortening.py
+++ b/Sim/GaussTracker/tests/options/sensdet_name_shortening.py
@@ -1,13 +1,49 @@
 #!env python
-from Gaudi.Configuration import *
+# This is a very specific configuration in order to trigger a debug message
+# with a shortened name of the sensitive detector. In order to do so, in
+# Gauss-on-Gaussino it will only be triggered by running construct() on the
+# GiGaSensDetTracker. This happens usually in Geo services or directly in the
+# detector construction factory in Gaussino, so the configuration had to be
+# extended.
+
+from Configurables import GiGaMT
+from multiprocessing import cpu_count
+giga = GiGaMT()
+
+# choose default detector construction factory
+from Configurables import GiGaMTDetectorConstructionFAC
+giga.DetectorConstruction = "GiGaMTDetectorConstructionFAC"
+dettool = giga.addTool(GiGaMTDetectorConstructionFAC,
+                       "GiGaMTDetectorConstructionFAC")
+# in order to print a debug message
+from Gaudi.Configuration import DEBUG
+dettool.OutputLevel = DEBUG
+
+# Add the test tracker factory with an empty list of volumes
+# just to invoke the debug message
 from Configurables import GiGaSensDetTracker
-from GaudiPython.Bindings import AppMgr
-import cppyy
-sensdet = GiGaSensDetTracker( 'ToolSvc.Hello', OutputLevel = -10)
-bye = sensdet.addTool(GiGaSensDetTracker, 'Bye')
-bye.OutputLevel = -10
-
-gaudi = AppMgr()
-blub = gaudi.toolSvc().create('GiGaSensDetTracker', 'Hello')
-blub = gaudi.toolSvc().create('GiGaSensDetTracker', 'Hello.Bye')
-gaudi.initialize()
+dettool.SensDetVolumeMap = {'GiGaSensDetTracker/Hello': [] }
+dettool.addTool(GiGaSensDetTracker, 'Hello')
+
+# All the rest provides a minimum, the fastest working example
+# for this test
+
+from Configurables import GiGaMT
+giga = GiGaMT()
+giga.NumberOfWorkerThreads = cpu_count()
+
+from Configurables import Gaussino
+Gaussino().EvtMax = 1
+
+# select a simple Geo service from Gaussino
+# not relevant for the test, but needed for detector FAC
+from Configurables import IronBoxGeo
+dettool.GiGaMTGeoSvc = "IronBoxGeo"
+from Configurables import ApplicationMgr
+ApplicationMgr().ExtSvc += [IronBoxGeo()]
+
+from Gaussino.Generation import GenPhase
+GenPhase().ParticleGun = True
+
+from GaudiPython import AppMgr
+AppMgr().initialize()
diff --git a/Sim/GaussTracker/tests/qmtest/gausstracker.qms/shortened_sensdet_name.qmt b/Sim/GaussTracker/tests/qmtest/gausstracker.qms/shortened_sensdet_name.qmt
index 3b16a1c3f..40f748ed2 100644
--- a/Sim/GaussTracker/tests/qmtest/gausstracker.qms/shortened_sensdet_name.qmt
+++ b/Sim/GaussTracker/tests/qmtest/gausstracker.qms/shortened_sensdet_name.qmt
@@ -8,12 +8,11 @@
 	<text>$GAUSSTRACKERROOT/tests/options/sensdet_name_shortening.py</text>
 </set></argument>
 <argument name="validator"><text>
-names = [&quot;ToolSvc.Hello&quot;, &quot;ToolSvc.Hello.Bye&quot;]
+name = &quot;GiGaMT.GiGaMTDetectorConstructionFAC.Hello&quot;
 search = &quot;Sens det shortened name {} -&gt; {}&quot;
 
 print stdout
-for name in names:
-    if stdout.find(search.format(name, name.split(&quot;.&quot;)[-1])) == -1:
-        causes.append(&quot;Name not correctly shortened&quot;)  
+if stdout.find(search.format(name, name.split(&quot;.&quot;)[-1])) == -1:
+    causes.append(&quot;Name not correctly shortened&quot;)  
 </text></argument>
 </extension>
-- 
GitLab


From 6a2a483e6e988f4c35503a828fd34cbeb89783cd Mon Sep 17 00:00:00 2001
From: Michal Mazurek <michal.mazurek@cern.ch>
Date: Fri, 12 Feb 2021 14:06:29 +0100
Subject: [PATCH 71/90] Remove explicit lists of generators

---
 generators_versions_LCG95.txt  | 13 -------------
 generators_versions_LCG96.txt  | 14 --------------
 generators_versions_LCG96b.txt | 14 --------------
 generators_versions_LCG97.txt  | 13 -------------
 generators_versions_LCG97a.txt | 13 -------------
 5 files changed, 67 deletions(-)
 delete mode 100644 generators_versions_LCG95.txt
 delete mode 100644 generators_versions_LCG96.txt
 delete mode 100644 generators_versions_LCG96b.txt
 delete mode 100644 generators_versions_LCG97.txt
 delete mode 100644 generators_versions_LCG97a.txt

diff --git a/generators_versions_LCG95.txt b/generators_versions_LCG95.txt
deleted file mode 100644
index 3365cb382..000000000
--- a/generators_versions_LCG95.txt
+++ /dev/null
@@ -1,13 +0,0 @@
-alpgen         2.1.4
-herwig++       2.7.1
-hijing         1.383bs.2
-lhapdf         6.2.3
-photos++       3.56.lhcb1
-pythia6        427.2.lhcb
-pythia8        240.lhcb4
-rivet          2.7.2b
-tauola++       1.1.6b.lhcb
-thepeg         2.1.5
-crmc           1.5.6
-yoda           1.7.7
-starlight      r300
diff --git a/generators_versions_LCG96.txt b/generators_versions_LCG96.txt
deleted file mode 100644
index be3003968..000000000
--- a/generators_versions_LCG96.txt
+++ /dev/null
@@ -1,14 +0,0 @@
-alpgen         2.1.4
-herwig++       2.7.1
-hijing         1.383bs.2
-lhapdf         6.2.3
-photos++       3.56
-powheg-box-v2  r3043.lhcb
-pythia6        427.2
-pythia8        240
-rivet          2.7.2b
-tauola++       1.1.6b.lhcb
-thepeg         2.1.5
-crmc           1.5.6
-yoda           1.7.5
-starlight      r300
diff --git a/generators_versions_LCG96b.txt b/generators_versions_LCG96b.txt
deleted file mode 100644
index 9b6459b47..000000000
--- a/generators_versions_LCG96b.txt
+++ /dev/null
@@ -1,14 +0,0 @@
-alpgen         2.1.4
-herwig++       2.7.1
-hijing         1.383bs.2
-lhapdf         6.2.3
-photos++       3.56
-powheg-box-v2  r3043.lhcb
-pythia6        427.2
-pythia8        240
-rivet          2.7.2b
-tauola++       1.1.6b.lhcb
-thepeg         2.1.5
-crmc           1.5.6
-yoda           1.7.7
-starlight      r300
diff --git a/generators_versions_LCG97.txt b/generators_versions_LCG97.txt
deleted file mode 100644
index 9732b86f1..000000000
--- a/generators_versions_LCG97.txt
+++ /dev/null
@@ -1,13 +0,0 @@
-alpgen         2.1.4
-hijing         1.383bs.2
-powheg-box-v2  r3043.lhcb
-pythia6        429.2
-rivet          3.0.1
-tauola++       1.1.6
-thepeg         2.2.0
-crmc           1.6.0
-yoda           1.8.0
-starlight      r313
-pythia8        244
-lhapdf         6.2.3
-photos++       3.61
diff --git a/generators_versions_LCG97a.txt b/generators_versions_LCG97a.txt
deleted file mode 100644
index 9732b86f1..000000000
--- a/generators_versions_LCG97a.txt
+++ /dev/null
@@ -1,13 +0,0 @@
-alpgen         2.1.4
-hijing         1.383bs.2
-powheg-box-v2  r3043.lhcb
-pythia6        429.2
-rivet          3.0.1
-tauola++       1.1.6
-thepeg         2.2.0
-crmc           1.6.0
-yoda           1.8.0
-starlight      r313
-pythia8        244
-lhapdf         6.2.3
-photos++       3.61
-- 
GitLab


From 41c9544f47c94c43f7164214ade110940a4a1c1a Mon Sep 17 00:00:00 2001
From: Michal Mazurek <michal.mazurek@cern.ch>
Date: Fri, 12 Feb 2021 15:29:48 +0100
Subject: [PATCH 72/90] Introduce lcg layers

---
 toolchain.cmake | 134 ++----------------------------------------------
 1 file changed, 5 insertions(+), 129 deletions(-)

diff --git a/toolchain.cmake b/toolchain.cmake
index 556d8a3ac..516168842 100644
--- a/toolchain.cmake
+++ b/toolchain.cmake
@@ -1,8 +1,10 @@
 # Special toolchain file that inherits the same heptools version as the
 # used projects.
-
 cmake_minimum_required(VERSION 3.6)
 
+set(LCG_LAYER LHCB_4 CACHE STRING "Specific set of version to use")
+option(LCG_USE_GENERATORS "enable/disable use of LCG generators" ON)
+
 if(NOT DEFINED GAUDI_OLD_STYLE_PROJECT)
   file(STRINGS "${PROJECT_SOURCE_DIR}/CMakeLists.txt" _top_cmakelists)
   set(GAUDI_OLD_STYLE_PROJECT NO)
@@ -77,8 +79,9 @@ if(NOT CMAKE_SOURCE_DIR MATCHES "CMakeTmp")
   if(CMAKE_PREFIX_PATH)
     # - ninja (it requires LD_LIBRARY_PATH set to run)
     # - Gaudi (we do not want to use it from LCG)
+    # - Geant4 (we do not want to use it from LCG)
     # - xenv (conflicts with the version in the build environment)
-    list(FILTER CMAKE_PREFIX_PATH EXCLUDE REGEX "(LCG_|lcg/nightlies).*(ninja|Gaudi|xenv)")
+    list(FILTER CMAKE_PREFIX_PATH EXCLUDE REGEX "(LCG_|lcg/nightlies).*(ninja|Gaudi|Geant4|xenv)")
   endif()
 
   # Make sure that when the toolchain is invoked again it uses this branch
@@ -86,131 +89,4 @@ if(NOT CMAKE_SOURCE_DIR MATCHES "CMakeTmp")
 endif()
 endif()
 
-find_file(inherit_heptools_module InheritHEPTools.cmake)
-
-# Process the lines of LCG_generators_*.txt file to extract the
-# needed generators (variable generators_versions)
-macro(lcg_set_generator root name hash version dir)
-  #message(STATUS "Processing ${name} ${version} (${dir})")
-  list(FIND generators_versions ${name} _gen_idx)
-  list(FIND found_generators ${name} _found_idx)
-  if(NOT _gen_idx EQUAL -1 AND _found_idx EQUAL -1)
-    math(EXPR _gen_vers_idx "${_gen_idx} + 1")
-    list(GET generators_versions ${_gen_vers_idx} _gen_vers)
-    #message(STATUS "  required ${_gen_vers}")
-    if("${version}" STREQUAL "${_gen_vers}")
-      set(${name}_native_version ${${name}_config_version})
-      if(NOT IS_ABSOLUTE ${dir})
-        set(${name}_home ${root}/${dir})
-      else()
-        set(${name}_home ${dir})
-      endif()
-      if(EXISTS ${${name}_home})
-        get_filename_component(${name}_home "${${name}_home}" ABSOLUTE)
-        set(${name}_config_version ${version} CACHE STRING "Version of ${name}")
-        mark_as_advanced(${name}_config_version)
-        #message(STATUS "Using ${name} ${version} from ${${name}_home}")
-        list(INSERT CMAKE_PREFIX_PATH 0 ${${name}_home})
-        list(APPEND found_generators ${name})
-      endif()
-    #else()
-    #  message(STATUS "  wrong version (${name} ${version})")
-    endif()
-  #else()
-  #  if(_found_idx EQUAL -1)
-  #    message(STATUS "  ${name} not required")
-  #  else()
-  #    message(STATUS "  ${name} already found")
-  #  endif()
-  endif()
-endmacro()
-
-# Check that all the generators in generators_versions are found in the
-# LCG_generators_*.txt file.
-macro(check_generators)
-  set(_idx 0)
-  set(_missing_generators)
-  list(LENGTH generators_versions _length)
-  while(_idx LESS _length)
-    list(GET generators_versions ${_idx} _gen_name)
-    list(FIND found_generators ${_gen_name} _found_idx)
-    if(_found_idx EQUAL -1)
-      math(EXPR _gen_vers_idx "${_idx} + 1")
-      list(GET generators_versions ${_gen_vers_idx} _gen_ver)
-      set(_missing_generators "${_missing_generators} ${_gen_name}(${_gen_ver})")
-    endif()
-    math(EXPR _idx "${_idx} + 2")
-  endwhile()
-  if(_missing_generators)
-    message(WARNING "Missing generators: ${_missing_generators}")
-  endif()
-endmacro()
 
-# this check is needed because the toolchain seem to be called a second time
-# without the proper cache
-if(inherit_heptools_module)
-  include(${inherit_heptools_module})
-  inherit_heptools()
-
-  if(EXISTS ${CMAKE_SOURCE_DIR}/generators_versions_LCG${heptools_version}.txt)
-    file(READ ${CMAKE_SOURCE_DIR}/generators_versions_LCG${heptools_version}.txt generators_versions)
-    string(REGEX REPLACE "[ \t\n]+" ";" generators_versions "${generators_versions}")
-    set(generators_versions ${generators_versions})
-  endif()
-
-  if(LCG_TOOLCHAIN_INFO)
-    # prepare list of toolchain info files for generators
-    get_filename_component(_info_name ${LCG_TOOLCHAIN_INFO} NAME CACHE)
-    string(REPLACE "_externals_" "_generators_" _info_name "${_info_name}")
-    # look for alternative info files
-    file(TO_CMAKE_PATH "$ENV{CMAKE_PREFIX_PATH}" _a)
-    file(TO_CMAKE_PATH "$ENV{CMTPROJECTPATH}" _b)
-    set(_search_path ${LCG_releases} ${_a} ${_b} ${CMAKE_PREFIX_PATH})
-    foreach(_d ${_search_path})
-      foreach(_suff "LCG_${heptools_version}" ".")
-        foreach(_f "${_d}/${_suff}/${_info_name}.installed"
-                   "${_d}/${_suff}/${_info_name}")
-          if(EXISTS "${_f}")
-            get_filename_component(_f "${_f}" ABSOLUTE)
-            list(APPEND LCG_GENERATOR_INFOS "${_f}")
-            break()
-          endif()
-        endforeach()
-      endforeach()
-    endforeach()
-    if(NOT LCG_GENERATOR_INFOS)
-      message(FATAL_ERROR "Generators infos not found for ${heptools_version}")
-    endif()
-    message(STATUS "Using generators infos from:")
-    list(REMOVE_DUPLICATES LCG_GENERATOR_INFOS)
-    foreach(_i ${LCG_GENERATOR_INFOS})
-      message(STATUS "  * ${_i}")
-    endforeach()
-
-    set(found_generators)
-    foreach(_i ${LCG_GENERATOR_INFOS})
-      get_filename_component(_info_dir "${_i}" PATH)
-      file(STRINGS "${_i}" _lcg_infos)
-      foreach(_l ${_lcg_infos})
-        if(NOT _l MATCHES "^(PLATFORM|VERSION|COMPILER):")
-          string(REGEX REPLACE "; *" ";" _l "${_l}")
-          lcg_set_generator(${_info_dir} ${_l})
-        endif()
-      endforeach()
-    endforeach()
-    check_generators()
-  else()
-    # This check is to handle the special case of test builds internal to CMake
-    if(NOT CMAKE_SOURCE_DIR MATCHES "CMakeTmp")
-      message(FATAL_ERROR "Only LCG >= 68 is supported")
-    endif()
-  endif()
-endif()
-
-# FIXME: make sure we do not pick up unwanted/problematic projects from LCG
-if(CMAKE_PREFIX_PATH)
-  # - ninja (it requires LD_LIBRARY_PATH set to run)
-  # - Gaudi (we do not want to use it from LCG)
-  # - Geant4 (we do not want to use it from LCG)
-  list(FILTER CMAKE_PREFIX_PATH EXCLUDE REGEX "(LCG_|lcg/nightlies).*(ninja|Gaudi|Geant4)")
-endif()
-- 
GitLab


From ed36b0c585834e0eb850b8df265fc50ddb1bf64e Mon Sep 17 00:00:00 2001
From: Rosen Matev <rosen.matev@cern.ch>
Date: Tue, 9 Mar 2021 10:19:13 +0100
Subject: [PATCH 73/90] Support both 3.56 (LHCB_5) and newer versions of
 Photos++

---
 cmake/FindPhotos++.cmake | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/cmake/FindPhotos++.cmake b/cmake/FindPhotos++.cmake
index 088fd12ba..a8d6cf248 100644
--- a/cmake/FindPhotos++.cmake
+++ b/cmake/FindPhotos++.cmake
@@ -11,11 +11,12 @@
 
 # Enforce a minimal list if none is explicitly requested
 if(NOT PHOTOS++_FIND_COMPONENTS)
-  set(PHOTOS++_FIND_COMPONENTS Photospp PhotosppHEPEVT PhotosppHepMC)
+  set(PHOTOS++_FIND_COMPONENTS Fortran CxxInterface  # versions <3.58
+                               pp HEPEVT ppHepMC)    # versions >=3.58
 endif()
 
 foreach(component ${PHOTOS++_FIND_COMPONENTS})
-  find_library(PHOTOS++_${component}_LIBRARY NAMES ${component}
+  find_library(PHOTOS++_${component}_LIBRARY NAMES Photos${component}
                HINTS ${PHOTOS++_ROOT_DIR}/lib
                      $ENV{PHOTOSPP_ROOT_DIR}/lib
                      ${PHOTOSPP_ROOT_DIR}/lib)
-- 
GitLab


From 404a51268ce7240c6d445862fef0cad45febed79 Mon Sep 17 00:00:00 2001
From: Rosen Matev <rosen.matev@cern.ch>
Date: Wed, 24 Mar 2021 18:50:39 +0100
Subject: [PATCH 74/90] Fix copy-paste bug with EvtGenDecay.ImHelOne

EvtGenDecay.ImHelOne was wrongly named RealHelOne causing a collision.
As a result the property `m_imHelOne` had a value of 1 instead of 0.
---
 Gen/LbEvtGen/src/EvtGenDecay.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Gen/LbEvtGen/src/EvtGenDecay.h b/Gen/LbEvtGen/src/EvtGenDecay.h
index 7aab87f1b..0904339f0 100755
--- a/Gen/LbEvtGen/src/EvtGenDecay.h
+++ b/Gen/LbEvtGen/src/EvtGenDecay.h
@@ -243,7 +243,7 @@ private:
   Gaudi::Property<double> m_realHelOne{this, "RealHelOne", 1.};
 
   /// Imaginary part of spin matrix for helicity 1 for charmonium polarization
-  Gaudi::Property<double> m_imHelOne{this, "RealHelOne", 1.};
+  Gaudi::Property<double> m_imHelOne{this, "ImHelOne", 0.};
 };
 
 //#include "EvtGenBase/EvtIncoherentMixing.hh"
-- 
GitLab


From c5fbab1ecadca42866c0de0612b623806d40ce56 Mon Sep 17 00:00:00 2001
From: Rosen Matev <rosen.matev@cern.ch>
Date: Wed, 24 Mar 2021 18:56:51 +0100
Subject: [PATCH 75/90] Fix list of XML includes for VP (follow
 lhcb/Detector!76)

---
 Sim/Gauss/python/Gauss/Geometry/VP.py | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/Sim/Gauss/python/Gauss/Geometry/VP.py b/Sim/Gauss/python/Gauss/Geometry/VP.py
index 1012e612a..c33bafd80 100644
--- a/Sim/Gauss/python/Gauss/Geometry/VP.py
+++ b/Sim/Gauss/python/Gauss/Geometry/VP.py
@@ -26,7 +26,8 @@ class VP(det_base):
         go = LHCbGeo._listOfXMLIncludes_
 
         go += ["Pipe/parameters.xml"]
-        go += ["Rich1/materials.xml"]
+        go += ["Rich1/DetElem/RichRun3PropertySpecParam.xml"]
+        go += ["Rich1/RichMatDir/RichMaterials.xml"]
         go += ["VP/parameters.xml"]
         go += ["VP/visualization.xml"]
         go += ["VP/detector.xml"]
-- 
GitLab


From bf79a11c3fa257df575ba56c4e6c951cf9925c7e Mon Sep 17 00:00:00 2001
From: Rosen Matev <rosen.matev@cern.ch>
Date: Wed, 24 Mar 2021 19:00:01 +0100
Subject: [PATCH 76/90] Fix configuration for output file writing

Until this change, the writer GaussTape was run too early by the
AvalancheScheduler because its dependencies are not declared.

Here the GaussTape writer and the packers are now wrapped into
GaudiSequencer-s which tells the AvalancheScheduler that GaussTape
must run after the packing. Similarly, MCTruthToEDM is explicitly
scheduled before the packers (which also don't delcare their inputs).
With these changes, one can write out a .sim file as long as a single
thread is used.
---
 Sim/Gauss/python/Gauss/Configuration.py | 33 ++++++++++---------------
 1 file changed, 13 insertions(+), 20 deletions(-)

diff --git a/Sim/Gauss/python/Gauss/Configuration.py b/Sim/Gauss/python/Gauss/Configuration.py
index 991622c4d..6b0374176 100755
--- a/Sim/Gauss/python/Gauss/Configuration.py
+++ b/Sim/Gauss/python/Gauss/Configuration.py
@@ -10,6 +10,7 @@ from Gaudi.Configuration import ApplicationMgr
 from Configurables import LHCbConfigurableUser, LHCbApp, SimConf
 from Configurables import Gaussino
 from GaudiKernel import SystemOfUnits
+from Gaussino.Utilities import configure_edm_conversion
 
 
 class Gauss(LHCbConfigurableUser):
@@ -101,7 +102,7 @@ class Gauss(LHCbConfigurableUser):
             evtType = str(Generation("Generation").EventType)
         return evtType
 
-    def propagateSimConf(self):
+    def propagateSimConf(self, packing):
         # Propagate properties to SimConf
         SimConf().setProp("Writer", "GaussTape")
         self.setOtherProps(
@@ -118,24 +119,10 @@ class Gauss(LHCbConfigurableUser):
         # Don't want SIM data unpacking enabled in DoD service
         SimConf().EnableUnpack = False
 
-        class dummy:
-            def __init__(self):
-                self.Members = []
-
-        packing = dummy()
-        # Need this dummy sequence to later extract all the algorithm that
-        # need to be given to the scheduler.
         if "GenToMCTree" in Gaussino().getProp('Phases') or "Simulation" in Gauss().getProp("Phases"):
             for so in self.defineCrossingList():
                 SimConf().PackingSequencers[so] = packing
 
-        from Gaudi.Configuration import appendPostConfigAction
-
-        def runit():
-            for a in packing.Members:
-                ApplicationMgr().TopAlg += [a]
-
-        appendPostConfigAction(runit)
         SimConf().SaveHepMC = False
 
     def defineCrossingList(self):
@@ -146,7 +133,7 @@ class Gauss(LHCbConfigurableUser):
         crossingList += spillOverList
         return crossingList
 
-    def defineOutput(self, SpillOverSlots):
+    def defineOutput(self, SpillOverSlots, prerequisites):
         """
         Set up output stream according to phase processed,
         the spill-over slots and the type of output
@@ -212,8 +199,11 @@ class Gauss(LHCbConfigurableUser):
         if not FileCatalog().isPropertySet("Catalogs"):
             FileCatalog().Catalogs = ["xmlcatalog_file:NewCatalog.xml"]
 
-        from Configurables import ApplicationMgr
-        ApplicationMgr().TopAlg += [simWriter]
+        output_seq = GaudiSequencer(
+            "OutputSeq",
+            Members=prerequisites + [SimConf().writer()],
+            Sequential=True)
+        ApplicationMgr().TopAlg += [output_seq]
 
     # Apply the configuration
     def __apply_configuration__(self):
@@ -230,6 +220,9 @@ class Gauss(LHCbConfigurableUser):
         Gaussino().ParticleTable = 'git:///param/ParticleTable.txt'
         Gaussino().ConvertEDM = True
 
+        edm = configure_edm_conversion(self.getProp("ReDecay"))
+        packing = GaudiSequencer("PackingSeq",  Sequential=True, IgnoreFilterPassed=True)
+
         # Propagate beam settings for compatibility with existing option files
         from Gaussino.Generation import GenPhase
         self.setOtherProps(GenPhase(), [
@@ -241,7 +234,7 @@ class Gauss(LHCbConfigurableUser):
 
         # Propagates and sets up SimConf to be able to configure the
         # OutputStream during its apply_configuration
-        self.propagateSimConf()
+        self.propagateSimConf(packing)
 
         # Trigger the simulation related configuration if simulation is in
         # phases
@@ -258,4 +251,4 @@ class Gauss(LHCbConfigurableUser):
         from Configurables import EvtGenDecay
         EvtGenDecay().DecayFile = "$DECFILESROOT/dkfiles/DECAY.DEC"
 
-        self.defineOutput(crossingList)
+        self.defineOutput(crossingList, prerequisites=edm + [packing])
-- 
GitLab


From 6b568cc1aad4d27e3bb1fdfb836a6cf0fe5f796c Mon Sep 17 00:00:00 2001
From: Rosen Matev <rosen.matev@cern.ch>
Date: Wed, 24 Mar 2021 19:10:18 +0100
Subject: [PATCH 77/90] Add a test for running Gauss with DD4hep geometry

The test is based on the example at
https://gitlab.cern.ch/Gaussino/futuregaussexamples/-/blob/854f8978601a669342101901aa74927a2730c6fb/dd4hep/main.md

The test is placed in a temporary new package (Sim/FutureTests) since
the tests in Sim/Gauss are disabled.
---
 Sim/FutureTests/CMakeLists.txt          | 14 +++++
 Sim/FutureTests/options/dd4hep.py       | 83 +++++++++++++++++++++++++
 Sim/FutureTests/tests/qmtest/dd4hep.qmt | 44 +++++++++++++
 3 files changed, 141 insertions(+)
 create mode 100644 Sim/FutureTests/CMakeLists.txt
 create mode 100644 Sim/FutureTests/options/dd4hep.py
 create mode 100755 Sim/FutureTests/tests/qmtest/dd4hep.qmt

diff --git a/Sim/FutureTests/CMakeLists.txt b/Sim/FutureTests/CMakeLists.txt
new file mode 100644
index 000000000..7516a4990
--- /dev/null
+++ b/Sim/FutureTests/CMakeLists.txt
@@ -0,0 +1,14 @@
+###############################################################################
+# (c) Copyright 2021 CERN for the benefit of the LHCb Collaboration           #
+#                                                                             #
+# This software is distributed under the terms of the GNU General Public      #
+# Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   #
+#                                                                             #
+# In applying this licence, CERN does not waive the privileges and immunities #
+# granted to it by virtue of its status as an Intergovernmental Organization  #
+# or submit itself to any jurisdiction.                                       #
+###############################################################################
+# Temporary package holding tests for Gauss-on-Gaussino
+gaudi_subdir(FutureTests)
+
+gaudi_add_test(QMTest QMTEST)
diff --git a/Sim/FutureTests/options/dd4hep.py b/Sim/FutureTests/options/dd4hep.py
new file mode 100644
index 000000000..0b30823f2
--- /dev/null
+++ b/Sim/FutureTests/options/dd4hep.py
@@ -0,0 +1,83 @@
+###############################################################################
+# (c) Copyright 2021 CERN for the benefit of the LHCb Collaboration           #
+#                                                                             #
+# This software is distributed under the terms of the GNU General Public      #
+# Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   #
+#                                                                             #
+# In applying this licence, CERN does not waive the privileges and immunities #
+# granted to it by virtue of its status as an Intergovernmental Organization  #
+# or submit itself to any jurisdiction.                                       #
+###############################################################################
+from Gaudi.Configuration import importOptions
+from Gaussino.Generation import GenPhase
+from Configurables import GiGaMT
+from Configurables import Generation, ToolSvc, EvtGenDecay, GenRndInit
+from Configurables import Gauss, Gaussino
+from Configurables import LHCbApp, CondDB
+from Gauss.Geometry import LHCbGeo
+from Gauss.Geometry.Helpers import getsubdetector
+
+# Beam options as in Beam6500GeV-md100-2016-nu1.6.py
+importOptions("$APPCONFIGOPTS/Gauss/Beam7000GeV-mu100-nu7.6-HorExtAngle.py")
+
+# Add also the DDDB tag for now
+LHCbApp().DDDBtag = "dddb-20210218"
+LHCbApp().CondDBtag = "sim-20180530-vc-mu100"
+LHCbApp().DataType = "Upgrade"
+CondDB().Upgrade = True
+
+# Configure the generation phase as usual
+Generation().EventType = 30000000
+GenPhase().SampleGenerationTool = "MinimumBias"
+GenPhase().ProductionTool = "Pythia8ProductionMT"
+GenPhase().DecayTool = "EvtGenDecay"
+ToolSvc().addTool(
+    EvtGenDecay(
+        UserDecayFile="$DECFILESROOT/dkfiles/Dsst_ppbarpi=TightCut.dec",
+        DecayFile="$DECFILESROOT/dkfiles/DECAY.DEC"))
+
+# Configure number of events and parallelism
+nthreads = 1  # cannot use many threads when writing output
+GiGaMT().NumberOfWorkerThreads = nthreads
+Gauss().EnableHive = True
+Gauss().ThreadPoolSize = nthreads
+Gauss().EventSlots = nthreads
+GenRndInit().FirstEventNumber = 3000
+Gauss().EvtMax = 10
+Gauss().DatasetName = "gaussino-dd4hep"
+Gaussino().DatasetNameForced = True  # no time or EvtMax in output filenames
+
+# Activate global DD4hep flag, this results in the use of the DD4hep conversion service
+# instead of GaussGeo
+LHCbGeo().DD4hep = True
+# Set the list of detectors / detector elements
+LHCbGeo().DetectorGeo = {"Detectors": ['VP', 'Magnet', 'Bls']}
+LHCbGeo().DetectorSim = {"Detectors": ['VP', 'Magnet', 'Bls']}
+LHCbGeo().DetectorMoni = {"Detectors": ['VP', 'Magnet', 'Bls']}
+# LHCbGeo().SaveGDMLFile = "detector.gdml"
+# Optional mapping of a sensitive detector factory to a G4 logical volume
+# LHCbGeo().SensDetMap = {'GiGaSensDetTracker/VPSDet': ["lvDet"] }
+# LHCbGeo().Debug = True  # Comment this in if you want a lot of debug output
+
+# Select and activate DD4hep for the subdetectors you want to.
+# This needs to be for the future functionalities where DetDesc and
+# DD4hep can be mixed but is already needed now.
+getsubdetector('VP').UseDD4hep = True
+getsubdetector('BeamPipe').UseDD4hep = True
+getsubdetector('Magnet').UseDD4hep = True
+getsubdetector('Bls').UseDD4hep = True
+
+# Comment in below to trigger a more verbose printout of the conversion service
+# from Configurables import DD4hepCnvSvc
+# from Gaudi.Configuration import VERBOSE
+# DD4hepCnvSvc().OutputLevel = VERBOSE
+# DD4hepCnvSvc().DebugMaterials = True
+# DD4hepCnvSvc().DebugElements = True
+# DD4hepCnvSvc().DebugShapes = True
+# DD4hepCnvSvc().DebugVolumes = True
+# DD4hepCnvSvc().DebugPlacements = True
+# DD4hepCnvSvc().DebugRegions = True
+
+# Print some debugging information from the scheduler
+from Configurables import AvalancheSchedulerSvc
+AvalancheSchedulerSvc(ShowControlFlow=True, ShowDataFlow=True)
diff --git a/Sim/FutureTests/tests/qmtest/dd4hep.qmt b/Sim/FutureTests/tests/qmtest/dd4hep.qmt
new file mode 100755
index 000000000..cd3164d21
--- /dev/null
+++ b/Sim/FutureTests/tests/qmtest/dd4hep.qmt
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE extension  PUBLIC '-//QM/2.3/Extension//EN'  'http://www.codesourcery.com/qm/dtds/2.3/-//qm/2.3/extension//en.dtd'>
+<!--
+    (c) Copyright 2021 CERN for the benefit of the LHCb Collaboration
+
+    This software is distributed under the terms of the GNU General Public
+    Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".
+
+    In applying this licence, CERN does not waive the privileges and immunities
+    granted to it by virtue of its status as an Intergovernmental Organization
+    or submit itself to any jurisdiction.
+-->
+<!--
+Check that Gauss on Gaussino can run with a DD4hep geometry and save output.
+-->
+<extension class="GaudiTest.GaudiExeTest" kind="test">
+<argument name="program"><text>gaudirun.py</text></argument>
+<argument name="timeout"><integer>600</integer></argument>
+<argument name="args"><set>
+  <text>../../options/dd4hep.py</text>
+</set></argument>
+<argument name="use_temp_dir"><enumeral>true</enumeral></argument>
+<!--<argument name="reference"><text>../refs/dd4hep.ref</text></argument>
+<argument name="error_reference"><text>../refs/dd4hep.err.ref</text></argument> -->
+<argument name="validator"><text>
+
+# from GaudiConf.QMTest.LHCbExclusions import preprocessor
+# validateWithReference(preproc=preprocessor)
+
+countErrorLines({"FATAL": 0, "ERROR": 0, "WARNING": 0})
+
+# check we processed the expected number of events
+findReferenceBlock("GenRndInit           INFO 10 events processed", id="processed")
+
+# check if some MCHits were produced (different message otherwise)
+expected = "VPGaussMoni          INFO  Number of MCHits/Event:"
+if expected not in stdout:
+    causes.append('missing string')
+    result['GaudiTest.expected_string'] = result.Quote(expected)
+
+# check we persisted the expected number of events
+findReferenceBlock("GaussTape            INFO Events output: 10", id="output")
+
+</text></argument>
+</extension>
\ No newline at end of file
-- 
GitLab


From 5d0d133baa26ceaaa243b2dc4dbba0f188fd2e8a Mon Sep 17 00:00:00 2001
From: Michal Mazurek <michal.mazurek@cern.ch>
Date: Mon, 29 Mar 2021 14:52:56 +0200
Subject: [PATCH 78/90] Drop including manually lcg toolchain for non gaudi
 projects

---
 toolchain.cmake | 45 ---------------------------------------------
 1 file changed, 45 deletions(-)

diff --git a/toolchain.cmake b/toolchain.cmake
index 516168842..f5e5c2edf 100644
--- a/toolchain.cmake
+++ b/toolchain.cmake
@@ -5,45 +5,6 @@ cmake_minimum_required(VERSION 3.6)
 set(LCG_LAYER LHCB_4 CACHE STRING "Specific set of version to use")
 option(LCG_USE_GENERATORS "enable/disable use of LCG generators" ON)
 
-if(NOT DEFINED GAUDI_OLD_STYLE_PROJECT)
-  file(STRINGS "${PROJECT_SOURCE_DIR}/CMakeLists.txt" _top_cmakelists)
-  set(GAUDI_OLD_STYLE_PROJECT NO)
-  foreach(_line IN LISTS _top_cmakelists)
-    if(_line MATCHES "^[^#]*gaudi_project")
-      set(GAUDI_OLD_STYLE_PROJECT YES)
-      break()
-    endif()
-  endforeach()
-  set(GAUDI_OLD_STYLE_PROJECT ${GAUDI_OLD_STYLE_PROJECT} CACHE BOOL "true if the top level CMakeLists file contains a call to gaudi_project")
-endif()
-
-if(NOT GAUDI_OLD_STYLE_PROJECT AND "$ENV{GAUDI_OLD_STYLE_PROJECT}" STREQUAL "")
-  # for new style CMake projects, or vanilla CMake projects
-  if("$ENV{BINARY_TAG}" STREQUAL "" OR "$ENV{LCG_VERSION}" STREQUAL "")
-    message(FATAL_ERROR "The environment variables BINARY_TAG and LCG_VERSION mut be set for new style CMake projects")
-  endif()
-  find_file(LCG_TOOLCHAIN NAMES $ENV{BINARY_TAG}.cmake PATH_SUFFIXES lcg-toolchains/LCG_$ENV{LCG_VERSION})
-  if(LCG_TOOLCHAIN)
-    include(${LCG_TOOLCHAIN})
-    # after including the toolchain, set some LHCb defaults
-    find_program(CCACHE_COMMAND NAMES ccache)
-    if(CCACHE_COMMAND)
-      set(CMAKE_C_COMPILER_LAUNCHER "${CCACHE_COMMAND}" CACHE PATH "...")
-      set(CMAKE_CXX_COMPILER_LAUNCHER "${CCACHE_COMMAND}" CACHE PATH "...")
-    endif()
-    if(NOT DEFINED GAUDI_USE_INTELAMPLIFIER)
-      set(GAUDI_USE_INTELAMPLIFIER "YES" CACHE BOOL "...")
-    endif()
-    if(NOT DEFINED GAUDI_LEGACY_CMAKE_SUPPORT)
-      set(GAUDI_LEGACY_CMAKE_SUPPORT "YES" CACHE BOOL "...")
-    endif()
-    if(NOT DEFINED CMAKE_INSTALL_PREFIX OR CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
-      set(CMAKE_INSTALL_PREFIX "${PROJECT_SOURCE_DIR}/InstallArea/$ENV{BINARY_TAG}" CACHE BOOL "...")
-    endif()
-  else()
-    message(FATAL_ERROR "Cannot find LCG $ENV{LCG_VERSION} $ENV{BINARY_TAG} toolchain")
-  endif()
-else()
 
 # this check is needed because the toolchain is called when checking the
 # compiler (without the proper cache)
@@ -83,10 +44,4 @@ if(NOT CMAKE_SOURCE_DIR MATCHES "CMakeTmp")
     # - xenv (conflicts with the version in the build environment)
     list(FILTER CMAKE_PREFIX_PATH EXCLUDE REGEX "(LCG_|lcg/nightlies).*(ninja|Gaudi|Geant4|xenv)")
   endif()
-
-  # Make sure that when the toolchain is invoked again it uses this branch
-  set(ENV{GAUDI_OLD_STYLE_PROJECT} "${CMAKE_SOURCE_DIR}")
 endif()
-endif()
-
-
-- 
GitLab


From 032d6ed218caf4c2fa8a455c001cb06feb972aee Mon Sep 17 00:00:00 2001
From: Michal Mazurek <michal.mazurek@cern.ch>
Date: Mon, 29 Mar 2021 14:53:51 +0200
Subject: [PATCH 79/90] Introduce LCG_97a_LHCB_5

---
 toolchain.cmake | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/toolchain.cmake b/toolchain.cmake
index f5e5c2edf..ea67f82e8 100644
--- a/toolchain.cmake
+++ b/toolchain.cmake
@@ -2,9 +2,11 @@
 # used projects.
 cmake_minimum_required(VERSION 3.6)
 
-set(LCG_LAYER LHCB_4 CACHE STRING "Specific set of version to use")
+set(LCG_LAYER LHCB_5 CACHE STRING "Specific set of version to use")
 option(LCG_USE_GENERATORS "enable/disable use of LCG generators" ON)
 
+#FIXME: very bad, LCIO has to be in LCG_LAYER
+set(CMAKE_PREFIX_PATH "/cvmfs/lhcb.cern.ch/lib/lcg/releases/LCG_97a/LCIO/02.13.03/x86_64-centos7-gcc9-opt" ${CMAKE_PREFIX_PATH})
 
 # this check is needed because the toolchain is called when checking the
 # compiler (without the proper cache)
-- 
GitLab


From 677dc1041f5220df6c6423ca0d1fa5f13646da9e Mon Sep 17 00:00:00 2001
From: Michal Mazurek <michal.mazurek@cern.ch>
Date: Mon, 29 Mar 2021 14:57:35 +0200
Subject: [PATCH 80/90] Propagate changes in Rich1 geometry from Detector.

---
 Sim/Gauss/python/Gauss/Geometry/VP.py | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/Sim/Gauss/python/Gauss/Geometry/VP.py b/Sim/Gauss/python/Gauss/Geometry/VP.py
index 1012e612a..c33bafd80 100644
--- a/Sim/Gauss/python/Gauss/Geometry/VP.py
+++ b/Sim/Gauss/python/Gauss/Geometry/VP.py
@@ -26,7 +26,8 @@ class VP(det_base):
         go = LHCbGeo._listOfXMLIncludes_
 
         go += ["Pipe/parameters.xml"]
-        go += ["Rich1/materials.xml"]
+        go += ["Rich1/DetElem/RichRun3PropertySpecParam.xml"]
+        go += ["Rich1/RichMatDir/RichMaterials.xml"]
         go += ["VP/parameters.xml"]
         go += ["VP/visualization.xml"]
         go += ["VP/detector.xml"]
-- 
GitLab


From 86ea6317ee8f8c89f2fbb2a5d45fd96002c62a30 Mon Sep 17 00:00:00 2001
From: Michal Mazurek <michal.mazurek@cern.ch>
Date: Tue, 20 Apr 2021 19:42:07 +0200
Subject: [PATCH 81/90] Propagate the removal of
 LHCb::Det::LbDD4hep::DD4hepSvc::getDetector()

---
 Sim/DD4hepCnv/src/component/LHCbDD4hepCnvSvc.cpp | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/Sim/DD4hepCnv/src/component/LHCbDD4hepCnvSvc.cpp b/Sim/DD4hepCnv/src/component/LHCbDD4hepCnvSvc.cpp
index a6d46edc3..6d9272aa2 100644
--- a/Sim/DD4hepCnv/src/component/LHCbDD4hepCnvSvc.cpp
+++ b/Sim/DD4hepCnv/src/component/LHCbDD4hepCnvSvc.cpp
@@ -14,8 +14,17 @@ private:
 
 protected:
   virtual const dd4hep::Detector& getDetector() const override;
+
+public:
+  virtual StatusCode initialize() override;
 };
 
 DECLARE_COMPONENT( LHCbDD4hepCnvSvc )
 
-const dd4hep::Detector& LHCbDD4hepCnvSvc::getDetector() const { return m_dd4Svc->getDetector(); }
+StatusCode LHCbDD4hepCnvSvc::initialize() {
+  auto sc = m_dd4Svc.retrieve();
+  sc &= DD4hepCnvSvc::initialize();
+  return sc;
+}
+
+const dd4hep::Detector& LHCbDD4hepCnvSvc::getDetector() const { return dd4hep::Detector::getInstance(); }
-- 
GitLab


From 4cafa05e96a2516215428c3acb1197b1b7e3acb9 Mon Sep 17 00:00:00 2001
From: Michal Mazurek <michal.mazurek@cern.ch>
Date: Sat, 1 May 2021 16:42:29 +0000
Subject: [PATCH 82/90] Do not get git from LCG

---
 toolchain.cmake | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/toolchain.cmake b/toolchain.cmake
index ea67f82e8..e3f583646 100644
--- a/toolchain.cmake
+++ b/toolchain.cmake
@@ -44,6 +44,6 @@ if(NOT CMAKE_SOURCE_DIR MATCHES "CMakeTmp")
     # - Gaudi (we do not want to use it from LCG)
     # - Geant4 (we do not want to use it from LCG)
     # - xenv (conflicts with the version in the build environment)
-    list(FILTER CMAKE_PREFIX_PATH EXCLUDE REGEX "(LCG_|lcg/nightlies).*(ninja|Gaudi|Geant4|xenv)")
+    list(FILTER CMAKE_PREFIX_PATH EXCLUDE REGEX "(LCG_|lcg/nightlies).*(ninja|Gaudi|Geant4|xenv|git)")
   endif()
 endif()
-- 
GitLab


From 2ccaaac051188c48a364a57ddcbd1667cea46b11 Mon Sep 17 00:00:00 2001
From: Michal Mazurek <michal.mazurek@cern.ch>
Date: Thu, 6 May 2021 10:51:39 +0000
Subject: [PATCH 83/90] Move to LAYER_6

---
 toolchain.cmake | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/toolchain.cmake b/toolchain.cmake
index e3f583646..d6d5b182d 100644
--- a/toolchain.cmake
+++ b/toolchain.cmake
@@ -2,7 +2,7 @@
 # used projects.
 cmake_minimum_required(VERSION 3.6)
 
-set(LCG_LAYER LHCB_5 CACHE STRING "Specific set of version to use")
+set(LCG_LAYER LHCB_6 CACHE STRING "Specific set of version to use")
 option(LCG_USE_GENERATORS "enable/disable use of LCG generators" ON)
 
 #FIXME: very bad, LCIO has to be in LCG_LAYER
-- 
GitLab


From e1e4e8a93a808d4aabcb35387dd4faab59e4d378 Mon Sep 17 00:00:00 2001
From: Michal Mazurek <michal.mazurek@cern.ch>
Date: Sun, 9 May 2021 22:30:46 +0200
Subject: [PATCH 84/90] Temporary fix for misssing DD4hep and LCIO in
 LCG_100_LAYER_6

---
 toolchain.cmake | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/toolchain.cmake b/toolchain.cmake
index d6d5b182d..f64c88ab2 100644
--- a/toolchain.cmake
+++ b/toolchain.cmake
@@ -6,7 +6,8 @@ set(LCG_LAYER LHCB_6 CACHE STRING "Specific set of version to use")
 option(LCG_USE_GENERATORS "enable/disable use of LCG generators" ON)
 
 #FIXME: very bad, LCIO has to be in LCG_LAYER
-set(CMAKE_PREFIX_PATH "/cvmfs/lhcb.cern.ch/lib/lcg/releases/LCG_97a/LCIO/02.13.03/x86_64-centos7-gcc9-opt" ${CMAKE_PREFIX_PATH})
+set(CMAKE_PREFIX_PATH "/cvmfs/lhcb.cern.ch/lib/lcg/releases/LCG_100/LCIO/02.16.01/x86_64-centos7-gcc10-opt" ${CMAKE_PREFIX_PATH})
+set(CMAKE_PREFIX_PATH "/cvmfs/lhcb.cern.ch/lib/lcg/releases/LCG_100/DD4hep/01.16.01/x86_64-centos7-gcc10-opt" ${CMAKE_PREFIX_PATH})
 
 # this check is needed because the toolchain is called when checking the
 # compiler (without the proper cache)
-- 
GitLab


From 0917f2b3c3183333f91571cb3773260bdaed9664 Mon Sep 17 00:00:00 2001
From: Michal Mazurek <michal.mazurek@cern.ch>
Date: Sun, 9 May 2021 23:00:00 +0200
Subject: [PATCH 85/90] Stage 1 of futurize: only packages with no
 .gaudi_project_ignore

futurize -w --stage1 --nobackups --nofix libfuturize.fixes.fix_absolute_import $(find . -name '*.py' | egrep -v "$(echo $(find . -name'.gaudi_project_ignore' | sed -e 's/\.gaudi_project_ignore//g' | sed -e 's/\.\///g') | sed -e 's/\/\s/|/g')|InstallArea|build|Sim/Gauss/tests")  -w
---
 GaussSys/scripts/project_manifest.py          |   5 +-
 Gen/LoKiGen/python/LoKiGen/HepMC.py           |  15 +-
 Gen/LoKiGen/python/LoKiGen/decorators.py      |  17 +--
 Gen/LoKiGen/python/LoKiGen/functions.py       |  15 +-
 Gen/LoKiGen/python/LoKiGen/graph.py           |  17 +--
 Gen/LoKiGen/python/LoKiGen/tests.py           |  55 ++++----
 Gen/LoKiGen/tests/tst_JIRA_LBCORE461.py       |   5 +-
 .../ModelBuilderGridSubmission/GangaSubmit.py |   7 +-
 .../ModelSubmission.py                        |  25 ++--
 .../ModelSubmission_simple.py                 |  35 ++---
 .../SetupUpModelBuilder.py                    |  11 +-
 Sim/Gauss/options/GaussRead.py                |   3 +-
 Sim/Gauss/python/Gauss/Configuration.py       |  13 +-
 .../python/Gauss/Geometry/Configuration.py    |  27 ++--
 Sim/Gauss/python/Gauss/Geometry/Magnet.py     |   3 +-
 Sim/Gauss/python/Gauss/Geometry/det_base.py   |   2 +-
 Sim/Gauss/scripts/GaussStat.py                | 131 +++++++++---------
 17 files changed, 201 insertions(+), 185 deletions(-)

diff --git a/GaussSys/scripts/project_manifest.py b/GaussSys/scripts/project_manifest.py
index 15dd7964a..d4abd641c 100644
--- a/GaussSys/scripts/project_manifest.py
+++ b/GaussSys/scripts/project_manifest.py
@@ -1,6 +1,7 @@
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
 
+from __future__ import print_function
 import sys
 import os
 from xml.etree import ElementTree as ET
@@ -95,7 +96,7 @@ if __name__ == '__main__':
 
     # look for the CMake configuration file
     if not os.path.exists(cmake_lists):
-        print 'The project does not have a CMake configuration, I cannot produce a manifest.xml'
+        print('The project does not have a CMake configuration, I cannot produce a manifest.xml')
         sys.exit(0)
 
     project_args = []
@@ -104,7 +105,7 @@ if __name__ == '__main__':
     if m:
         project_args = m.group(1).split()
     if len(project_args) < 2:
-        print 'error: invalid content of CMakeLists.txt'
+        print('error: invalid content of CMakeLists.txt')
         sys.exit(1)
 
     # parse gaudi_project arguments
diff --git a/Gen/LoKiGen/python/LoKiGen/HepMC.py b/Gen/LoKiGen/python/LoKiGen/HepMC.py
index 863550993..e2646b644 100755
--- a/Gen/LoKiGen/python/LoKiGen/HepMC.py
+++ b/Gen/LoKiGen/python/LoKiGen/HepMC.py
@@ -37,6 +37,7 @@ A.Golutvin, P.Koppenburg have been used in the design.
 
 
 """
+from __future__ import print_function
 # =============================================================================
 __author__ = 'Vanya BELYAEV ibelyaev@physics.syr.edu'
 __date__ = "2007-08-11"
@@ -645,14 +646,14 @@ for t in (HepMC.GenParticle, HepMC.GenParticle.Range,
 # =============================================================================
 if '__main__' == __name__:
 
-    print 80 * '*'
-    print __doc__
-    print ' Author  : ', __author__
-    print ' Version : ', __version__
-    print ' Date    : ', __date__
-    print 80 * '*'
+    print(80 * '*')
+    print(__doc__)
+    print(' Author  : ', __author__)
+    print(' Version : ', __version__)
+    print(' Date    : ', __date__)
+    print(80 * '*')
     for i in dir():
-        print i
+        print(i)
 
 # =============================================================================
 # The END
diff --git a/Gen/LoKiGen/python/LoKiGen/decorators.py b/Gen/LoKiGen/python/LoKiGen/decorators.py
index 3c4100004..0c3a320b3 100755
--- a/Gen/LoKiGen/python/LoKiGen/decorators.py
+++ b/Gen/LoKiGen/python/LoKiGen/decorators.py
@@ -35,6 +35,7 @@ contributions and advices from G.Raven, J.van Tilburg,
 A.Golutvin, P.Koppenburg have been used in the design.
 
 """
+from __future__ import print_function
 # =============================================================================
 __author__ = "Vanya BELYAEV ibelyaev@physics.syr.edu"
 __date__ = "????-??-??"
@@ -192,15 +193,15 @@ GSTABLEINDECAYGEN = GSTATUS == LHCb.HepMCEvent.StableInDecayGen
 
 # =============================================================================
 if '__main__' == __name__:
-    print 80 * '*'
-    print __doc__
-    print ' Author    :  ', __author__
-    print ' Version   :  ', __version__
-    print ' Date      :  ', __date__
-    print ' Decorated : #', len(_decorated)
-    print 80 * '*'
+    print(80 * '*')
+    print(__doc__)
+    print(' Author    :  ', __author__)
+    print(' Version   :  ', __version__)
+    print(' Date      :  ', __date__)
+    print(' Decorated : #', len(_decorated))
+    print(80 * '*')
     for i in dir():
-        print i
+        print(i)
 
 # =============================================================================
 # The END
diff --git a/Gen/LoKiGen/python/LoKiGen/functions.py b/Gen/LoKiGen/python/LoKiGen/functions.py
index 6ed985e46..6870aefb1 100755
--- a/Gen/LoKiGen/python/LoKiGen/functions.py
+++ b/Gen/LoKiGen/python/LoKiGen/functions.py
@@ -36,6 +36,7 @@ contributions and advices from G.Raven, J.van Tilburg,
 A.Golutvin, P.Koppenburg have been used in the design.
 
 """
+from __future__ import print_function
 # =============================================================================
 __author__ = "Vanya BELYAEV <ibelyaev@physics.syr.edu>"
 __date__ = "2007-12-01"
@@ -396,14 +397,14 @@ GVSIZE = LoKi.Functors.Size(_GV)()
 
 # =============================================================================
 if '__main__' == __name__:
-    print 80 * '*'
-    print __doc__
-    print ' Author  : ', __author__
-    print ' Version : ', __version__
-    print ' Date    : ', __date__
-    print 80 * '*'
+    print(80 * '*')
+    print(__doc__)
+    print(' Author  : ', __author__)
+    print(' Version : ', __version__)
+    print(' Date    : ', __date__)
+    print(80 * '*')
     for i in dir():
-        print i
+        print(i)
 
 # =============================================================================
 # The END
diff --git a/Gen/LoKiGen/python/LoKiGen/graph.py b/Gen/LoKiGen/python/LoKiGen/graph.py
index d3fc1a909..6c4028d68 100644
--- a/Gen/LoKiGen/python/LoKiGen/graph.py
+++ b/Gen/LoKiGen/python/LoKiGen/graph.py
@@ -34,6 +34,7 @@ Galina PAKHLOVA and Sergey BARSUK.  Many bright ideas,
 contributions and advices from G.Raven, J.van Tilburg,
 A.Golutvin, P.Koppenburg have been used in the design.
 """
+from __future__ import print_function
 # =============================================================================
 __author__ = "Vanya BELYAEV Ivan.Belyaev@itep.ru"
 __date__ = "2015-01-16"
@@ -185,7 +186,7 @@ def view(particle, command=None, format='png'):
     with _TmpName_(format) as ofile:
 
         if not graph(particle, format, filename=ofile):
-            print 'Error producing the graph for %s ' % particle.decay()
+            print('Error producing the graph for %s ' % particle.decay())
             return
 
         if not command:
@@ -196,7 +197,7 @@ def view(particle, command=None, format='png'):
                 if command: break
 
         if not command:
-            print 'No valid command is found!'
+            print('No valid command is found!')
             return
 
         import subprocess
@@ -214,12 +215,12 @@ for t in (PARTICLE, PARTICLE.Range, PARTICLE.ConstVector, HEPMCEVENT,
 # =============================================================================
 if '__main__' == __name__:
 
-    print 80 * '*'
-    print __doc__
-    print ' Author  : ', __author__
-    print ' Version : ', __version__
-    print ' Date    : ', __date__
-    print 80 * '*'
+    print(80 * '*')
+    print(__doc__)
+    print(' Author  : ', __author__)
+    print(' Version : ', __version__)
+    print(' Date    : ', __date__)
+    print(80 * '*')
 
 # =============================================================================
 # The END
diff --git a/Gen/LoKiGen/python/LoKiGen/tests.py b/Gen/LoKiGen/python/LoKiGen/tests.py
index f9699adb0..18de3b81f 100755
--- a/Gen/LoKiGen/python/LoKiGen/tests.py
+++ b/Gen/LoKiGen/python/LoKiGen/tests.py
@@ -35,6 +35,7 @@ contributions and advices from G.Raven, J.van Tilburg,
 A.Golutvin, P.Koppenburg have been used in the design.
 
 """
+from __future__ import print_function
 # =============================================================================
 __author__ = "Vanya BELYAEV ibelyaev@physics.syr.edu"
 __date__ = "2007-05-29"
@@ -57,11 +58,11 @@ def test1():
     p = HepMC.GenParticle()
     p.set_pdg_id(11)
 
-    print 'particle: %s/%s ' % (p.name(), pname(p))
-    print 'particle: (GPX,GPY,GPZ,GM)=(%s,%s,%s,%s)' % (GPX(p), GPY(p), GPZ(p),
-                                                        GM(p))
-    print 'particle: ( p>>GID , p>>cos(GE) )=(%s,%s)' % (p >> GID,
-                                                         p >> cos(GE))
+    print('particle: %s/%s ' % (p.name(), pname(p)))
+    print('particle: (GPX,GPY,GPZ,GM)=(%s,%s,%s,%s)' % (GPX(p), GPY(p), GPZ(p),
+                                                        GM(p)))
+    print('particle: ( p>>GID , p>>cos(GE) )=(%s,%s)' % (p >> GID,
+                                                         p >> cos(GE)))
 
     gpv = std.vector('HepMC3::ConstGenParticlePtr')
     v = gpv()
@@ -74,24 +75,24 @@ def test1():
     p2.set_pdg_id(22)
     v.push_back(p2)
 
-    print ' v>>GID                           : %s' % (v >> GID)
-    print ' v>>yields(GID)                   : %s' % (v >> yields(GID))
-    print ' v>>process(GID)>>min_value(GP)   : %s' % (
-        v >> process(GID) >> min_value(GP))
-    print '(v>>min_element(GID))[0].name()   : %s' % (
-        v >> min_element(GID))[0].name()
-    print ' v>>min_value(GID)                : %s' % (v >> min_value(GID))
-    print ' v>>("e+"!=GABSID)>>GSIZE         : %s' % (
-        v >> ('e+' != GABSID) >> GSIZE)
-    print ' v>>select("mu+"!=GABSID)>>GEMPTY : %s' % (
-        v >> select('mu+' != GABSID) >> GEMPTY)
+    print(' v>>GID                           : %s' % (v >> GID))
+    print(' v>>yields(GID)                   : %s' % (v >> yields(GID)))
+    print(' v>>process(GID)>>min_value(GP)   : %s' % (
+        v >> process(GID) >> min_value(GP)))
+    print('(v>>min_element(GID))[0].name()   : %s' % (
+        v >> min_element(GID))[0].name())
+    print(' v>>min_value(GID)                : %s' % (v >> min_value(GID)))
+    print(' v>>("e+"!=GABSID)>>GSIZE         : %s' % (
+        v >> ('e+' != GABSID) >> GSIZE))
+    print(' v>>select("mu+"!=GABSID)>>GEMPTY : %s' % (
+        v >> select('mu+' != GABSID) >> GEMPTY))
 
     f1 = in_list(GID, ["e+", "e-", 'mu+', 'mu-'])
     f2 = in_list(GABSID, ["e+", "e-", 'mu+', 'mu-'])
-    print ' in_list ( GID    , [ "e+" , "e-" , "mu+" , "mu-"] ) : %s %s ' % (
-        f1, f1(p1))
-    print ' in_list ( GABSID , [ "e+" , "e-" , "mu+" , "mu-"] ) : %s %s ' % (
-        f2, f2(p1))
+    print(' in_list ( GID    , [ "e+" , "e-" , "mu+" , "mu-"] ) : %s %s ' % (
+        f1, f1(p1)))
+    print(' in_list ( GABSID , [ "e+" , "e-" , "mu+" , "mu-"] ) : %s %s ' % (
+        f2, f2(p1)))
 
 
 # =============================================================================
@@ -102,14 +103,14 @@ def testAll():
 # =============================================================================
 if '__main__' == __name__:
 
-    print 80 * '*'
-    print __doc__
-    print ' Author  : ', __author__
-    print ' Version : ', __version__
-    print ' Date    : ', __date__
-    print 80 * '*'
+    print(80 * '*')
+    print(__doc__)
+    print(' Author  : ', __author__)
+    print(' Version : ', __version__)
+    print(' Date    : ', __date__)
+    print(80 * '*')
     for i in dir():
-        print i
+        print(i)
 
     testAll()
 
diff --git a/Gen/LoKiGen/tests/tst_JIRA_LBCORE461.py b/Gen/LoKiGen/tests/tst_JIRA_LBCORE461.py
index 3be1923e4..6a112a989 100755
--- a/Gen/LoKiGen/tests/tst_JIRA_LBCORE461.py
+++ b/Gen/LoKiGen/tests/tst_JIRA_LBCORE461.py
@@ -10,6 +10,7 @@
 # or submit itself to any jurisdiction.                                       #
 ###############################################################################
 # =====================================================================================
+from __future__ import print_function
 from LoKiGen.decorators import *
 
 GPV = std.vector('HepMC3::ConstGenParticlePtr')
@@ -30,11 +31,11 @@ v.push_back(p2)
 
 ## THIS IS OK
 for i in v:
-    print i.pdg_id()
+    print(i.pdg_id())
 
 ## make a range from vector
 r = GRange(v)
 
 ## THIS MAKES SEGMENTATION FAULT FOR ROOT6
 for i in r:
-    print i.pdg_id()
+    print(i.pdg_id())
diff --git a/Gen/Mint/src/Users/Matt/ModelBuilderGridSubmission/GangaSubmit.py b/Gen/Mint/src/Users/Matt/ModelBuilderGridSubmission/GangaSubmit.py
index fc3352dd9..fe9009a43 100644
--- a/Gen/Mint/src/Users/Matt/ModelBuilderGridSubmission/GangaSubmit.py
+++ b/Gen/Mint/src/Users/Matt/ModelBuilderGridSubmission/GangaSubmit.py
@@ -1,14 +1,15 @@
+from __future__ import print_function
 import os, sys, time
 import subprocess
 
 os.system('echo $ROOTSYS')
 
-print "ROOT environment configured"
+print("ROOT environment configured")
 
 fileout = 'out_'+sys.argv[1]+'.txt'
 
-print fileout
+print(fileout)
 
-print sys.argv[2]
+print(sys.argv[2])
 
 os.system('./ampFit ' + sys.argv[1] + ' < '+ sys.argv[2] +' > ' + fileout)
diff --git a/Gen/Mint/src/Users/Matt/ModelBuilderGridSubmission/ModelSubmission.py b/Gen/Mint/src/Users/Matt/ModelBuilderGridSubmission/ModelSubmission.py
index 56fb85837..d033581a9 100644
--- a/Gen/Mint/src/Users/Matt/ModelBuilderGridSubmission/ModelSubmission.py
+++ b/Gen/Mint/src/Users/Matt/ModelBuilderGridSubmission/ModelSubmission.py
@@ -1,3 +1,4 @@
+from __future__ import print_function
 
 import os
 import time
@@ -106,12 +107,12 @@ class ModelFinderJob:
         MyModels = Models('InputModels.txt')
         models = MyModels.GetModels()
         for model in models:
-            print model
+            print(model)
             model = model.replace('\n','')
             self.inputs.append(model)
             modelName = model.split('/')
             inputargs.append([str(1),modelName[1]])
-            print modelName[1]
+            print(modelName[1])
         return inputargs
     
     def InputLFNs(self,inputLFNs):
@@ -126,11 +127,11 @@ class ModelFinderJob:
         input_parts=self.ParticleProp+"MintDalitzSpecialParticles.cvs"
         self.j.application.script = [script]
         inputargs = self.makeSubjobs()
-        print inputargs
+        print(inputargs)
         s = ArgSplitter(args=inputargs)
         bckend = Dirac()
         bckend.settings['CPUTime']=60*60*18
-        print script, exe
+        print(script, exe)
         self.j.name= self.name
         self.j.inputsandbox = [exe, input_mass, input_parts]
         self.j.outputsandbox = ['*.eps','*.pdf','*.png','*.txt']
@@ -141,10 +142,10 @@ class ModelFinderJob:
 #        self.j.backend.inputSandboxLFNs = ['LFN:/lhcb/user/m/mcoombes/FourPiModelFit/BinningFile_D0.root',
 #                                           'LFN:/lhcb/user/m/mcoombes/FourPiModelFit/NocutsMC.root']
         self.inputs.append('BG4piModel.txt')
-        print self.inputs
+        print(self.inputs)
         self.j.inputsandbox.extend(self.inputs)
         for entry in self.j.inputsandbox:
-            print entry
+            print(entry)
     #    j.do_auto_resubmit = True
         self.j.submit()
         
@@ -200,10 +201,10 @@ def RunModelFinder(MintDir,UserArea,inputLFNs,modelTextFile,ModelBuilderExe,max_
     for i in range (start_iteration,max_iterations):
         directory = "it"+str(i)
 
-        print i 
+        print(i) 
         if (i == 0):
-            print "Run jacks code first iteration"
-            print "Will create an empty file to feed to Jack for iteration 0"
+            print("Run jacks code first iteration")
+            print("Will create an empty file to feed to Jack for iteration 0")
             modelsForIt = open(modelTextFile,"w")
             if (useModelCreator):
                 decs = ModelCreator()
@@ -216,8 +217,8 @@ def RunModelFinder(MintDir,UserArea,inputLFNs,modelTextFile,ModelBuilderExe,max_
             modelsForIt.close()
             os.system('./'+ModelBuilderExe+' '+str(modelTextFile)+' > modelbuilder.txt') # Ask Jack about iteration 0
         else:
-            print "Run iteration ", i, " of Jacks code"
-            print "Input ", modelTextFile
+            print("Run iteration ", i, " of Jacks code")
+            print("Input ", modelTextFile)
             os.system('./'+ModelBuilderExe+' '+directory+'/'+str(modelTextFile)+' > modelbuilder.txt')
     
         """Get output from Jacks code"""
@@ -242,7 +243,7 @@ def RunModelFinder(MintDir,UserArea,inputLFNs,modelTextFile,ModelBuilderExe,max_
         job.InputLFNs(inputLFNs) #Where is the data.
         job.SubmitJob()
         jid = job.JobID()
-        print jid
+        print(jid)
         j = job.Job()# Get the ganga job.
         
         job.WaitTillfinished() #Wait till the job is finished
diff --git a/Gen/Mint/src/Users/Matt/ModelBuilderGridSubmission/ModelSubmission_simple.py b/Gen/Mint/src/Users/Matt/ModelBuilderGridSubmission/ModelSubmission_simple.py
index b950fa72c..f4a85db11 100644
--- a/Gen/Mint/src/Users/Matt/ModelBuilderGridSubmission/ModelSubmission_simple.py
+++ b/Gen/Mint/src/Users/Matt/ModelBuilderGridSubmission/ModelSubmission_simple.py
@@ -1,3 +1,4 @@
+from __future__ import print_function
 
 import os
 import time
@@ -32,12 +33,12 @@ class ModelFinderJob:
         MyModels = Models('InputModels.txt')
         models = MyModels.GetModels()
         for model in models:
-            print model
+            print(model)
             model = model.replace('\n','')
             self.inputs.append(model)
             modelName = model.split('/')
             inputargs.append([str(1),modelName[1]])
-            print modelName[1]
+            print(modelName[1])
         return inputargs
     
     def InputLFNs(self,inputLFNs):
@@ -52,11 +53,11 @@ class ModelFinderJob:
         input_parts=self.ParticleProp+"MintDalitzSpecialParticles.cvs"
         self.j.application.script = [script]
         inputargs = self.makeSubjobs()
-        print inputargs
+        print(inputargs)
         s = ArgSplitter(args=inputargs)
         bckend = Dirac()
         bckend.settings['CPUTime']=60*60*18
-        print script, exe
+        print(script, exe)
         self.j.name= self.name
         self.j.inputsandbox = [exe, input_mass, input_parts]
         self.j.outputsandbox = ['*.eps','*.pdf','*.png','*.txt']
@@ -67,10 +68,10 @@ class ModelFinderJob:
 #        self.j.backend.inputSandboxLFNs = ['LFN:/lhcb/user/m/mcoombes/FourPiModelFit/BinningFile_D0.root',
 #                                           'LFN:/lhcb/user/m/mcoombes/FourPiModelFit/NocutsMC.root']
         self.inputs.append('BG4piModel.txt')
-        print self.inputs
+        print(self.inputs)
         self.j.inputsandbox.extend(self.inputs)
         for entry in self.j.inputsandbox:
-            print entry
+            print(entry)
     #    j.do_auto_resubmit = True
         self.j.submit()
         
@@ -125,16 +126,16 @@ def RunModelFinder(MintDir,UserArea,inputLFNs,modelTextFile,ModelBuilderExe,max_
     for i in range (start_iteration,max_iterations):
         directory = "it"+str(i)
 
-        print i 
+        print(i) 
         if (i == 0):
-            print "Run jacks code first iteration"
-            print "Will create an empty file to feed to Jack for iteration 0"
+            print("Run jacks code first iteration")
+            print("Will create an empty file to feed to Jack for iteration 0")
             modelsForIt = open(modelTextFile,"w")
             modelsForIt.close()
             os.system('./'+ModelBuilderExe+' '+str(modelTextFile)+' > modelbuilder.txt') # Ask Jack about iteration 0
         else:
-            print "Run iteration ", i, " of Jacks code"
-            print "Input ", modelTextFile
+            print("Run iteration ", i, " of Jacks code")
+            print("Input ", modelTextFile)
             os.system('./'+ModelBuilderExe+' '+directory+'/'+str(modelTextFile)+' > modelbuilder.txt')
     
         """Get output from Jacks code"""
@@ -166,18 +167,18 @@ def RunModelFinder(MintDir,UserArea,inputLFNs,modelTextFile,ModelBuilderExe,max_
         MyModels = Models('InputModels.txt')
         models = MyModels.GetModels()
         for model in models:
-            print model
+            print(model)
             model = model.replace('\n','')
             self.inputs.append(model)
             modelName = model.split('/')
             inputargs.append([str(1),modelName[1]])
-            print modelName[1]
+            print(modelName[1])
         return inputargs
         
         s = ArgSplitter(args=inputargs)
         bckend = Dirac()
         bckend.settings['CPUTime']=60*60*18
-        print script, exe
+        print(script, exe)
         j.name= "FourPiModelBuilder_It"+str(i)
         j.inputsandbox = [exe, input_mass, input_parts]
         j.outputsandbox = ['*.eps','*.pdf','*.png','*.txt']
@@ -187,14 +188,14 @@ def RunModelFinder(MintDir,UserArea,inputLFNs,modelTextFile,ModelBuilderExe,max_
         j.backend.inputSandboxLFNs.extend(inputLFNs)
         inputs = []
         inputs.append('BG4piModel.txt')
-        print inputs
+        print(inputs)
         j.inputsandbox.extend(inputs)
         for entry in j.inputsandbox:
-            print entry
+            print(entry)
     #    j.do_auto_resubmit = True
         j.submit()
 
-        print j.id()
+        print(j.id())
 
         jobrunning = True
         while jobrunning:
diff --git a/Gen/Mint/src/Users/Matt/ModelBuilderGridSubmission/SetupUpModelBuilder.py b/Gen/Mint/src/Users/Matt/ModelBuilderGridSubmission/SetupUpModelBuilder.py
index 84976bfea..64ba037b3 100644
--- a/Gen/Mint/src/Users/Matt/ModelBuilderGridSubmission/SetupUpModelBuilder.py
+++ b/Gen/Mint/src/Users/Matt/ModelBuilderGridSubmission/SetupUpModelBuilder.py
@@ -1,3 +1,4 @@
+from __future__ import print_function
 import os
 #from ModelFinder import *
 #gangaArea = "/afs/cern.ch/work/m/mcoombes/Ganga/ganga_workspace1/workspace/mcoombes/LocalXML"
@@ -22,11 +23,11 @@ ModelBuilderExe = MintDir+"Users/Matt/ModelCreator/ModelBuilder"
 SubmitModelBuilder = MintDir+'Users/Matt/ModelBuilderGridSubmission/ModelSubmission_simple.py'
 
 
-print "Before submitting make sure you have compiled ampFit with DaVinci v29r2 in order to get the correct ROOT version"
-print "\n"
+print("Before submitting make sure you have compiled ampFit with DaVinci v29r2 in order to get the correct ROOT version")
+print("\n")
 
 if ( not( os.path.exists("BG4piModel.txt") ) ) :
-    print "ERROR: file ", MintDir+UserArea+"BG4piModel.txt does not exist"
-    print "You must have the background model file BG4piModel.txt in userarea\n\n"
+    print("ERROR: file ", MintDir+UserArea+"BG4piModel.txt does not exist")
+    print("You must have the background model file BG4piModel.txt in userarea\n\n")
     
-print "To run type in the Ganga prompt execfile(SubmitModelBuilder)"
+print("To run type in the Ganga prompt execfile(SubmitModelBuilder)")
diff --git a/Sim/Gauss/options/GaussRead.py b/Sim/Gauss/options/GaussRead.py
index 887006ee6..b7c45ae9c 100644
--- a/Sim/Gauss/options/GaussRead.py
+++ b/Sim/Gauss/options/GaussRead.py
@@ -1,3 +1,4 @@
+from __future__ import print_function
 #
 # Example options to run Gauss in a pure reading mode with generator
 # and MCtruth.
@@ -39,7 +40,7 @@ def readOnly():
     if alg in moni.Members:
         moni.Members.remove(alg)
     
-    print "before", moni.Members
+    print("before", moni.Members)
  
 #-- Do the readOnly as a postconfig action for Gauss
 #
diff --git a/Sim/Gauss/python/Gauss/Configuration.py b/Sim/Gauss/python/Gauss/Configuration.py
index 991622c4d..82ef7f0e3 100755
--- a/Sim/Gauss/python/Gauss/Configuration.py
+++ b/Sim/Gauss/python/Gauss/Configuration.py
@@ -2,6 +2,7 @@
 High level configuration tools for Gauss
 Beampipe configuration added.
 """
+from __future__ import print_function
 __version__ = "$Id: Configuration.py,v 1.30 2010/05/09 18:14:28 gcorti Exp $"
 __author__ = "Gloria Corti <Gloria.Corti@cern.ch>"
 
@@ -175,18 +176,18 @@ class Gauss(LHCbConfigurableUser):
         # choose the file extension from the one selected compatibly with the
         # phase run
         if output not in knownOptions:
-            print "WARNING: OutputType not supported." \
-                  "Use default for chosen phases : %s" % (fileDefaultExtension)
+            print("WARNING: OutputType not supported." \
+                  "Use default for chosen phases : %s" % (fileDefaultExtension))
         fileExtension = "." + output.lower()
         if fileExtension not in fileAllowedExtension:
             fileExtension = fileDefaultExtension
-            print "WARNING: OutputType not supported" \
-                  " for this phase. Use default : %s" % (fileExtension)
+            print("WARNING: OutputType not supported" \
+                  " for this phase. Use default : %s" % (fileExtension))
 
         # set saving or not of HepMC depending on chosen file extension
         if SimConf().isPropertySet("SaveHepMC"):
-            print "WARNING: SimConf().SaveHepMC will" \
-                  " be ignored. Value set by Gauss()"
+            print("WARNING: SimConf().SaveHepMC will" \
+                  " be ignored. Value set by Gauss()")
         saveHepMC = False
         if fileExtension in ['.gen', '.xgen', '.xsim']:
             saveHepMC = True
diff --git a/Sim/Gauss/python/Gauss/Geometry/Configuration.py b/Sim/Gauss/python/Gauss/Geometry/Configuration.py
index de806bf6c..3b23dee3f 100644
--- a/Sim/Gauss/python/Gauss/Geometry/Configuration.py
+++ b/Sim/Gauss/python/Gauss/Geometry/Configuration.py
@@ -1,3 +1,4 @@
+from __future__ import print_function
 from Configurables import LHCbConfigurableUser
 from Gaudi.Configuration import Configurable
 from Gauss.Geometry.Helpers import checkIncompatibleDetectors
@@ -203,29 +204,29 @@ class LHCbGeo(LHCbConfigurableUser):
 
     def PrintDebugDump(self, detPieces, basePieces):
         if self.getProp("Debug") and not self.getProp("DD4hep"):
-            print "\nDEBUG Detector Geometry Elements:"
-            print "\nkey : detPieces[key]"
+            print("\nDEBUG Detector Geometry Elements:")
+            print("\nkey : detPieces[key]")
             for key in detPieces.keys():
-                print "%s : %s" % (key, detPieces[key])
-            print "\nkey : Sorted detPieces[key]"
+                print("%s : %s" % (key, detPieces[key]))
+            print("\nkey : Sorted detPieces[key]")
 
             for key in sorted(detPieces.keys()):
-                print "%s : %s" % (key, detPieces[key])
+                print("%s : %s" % (key, detPieces[key]))
 
-            print "\nkey : basePieces[key]"
+            print("\nkey : basePieces[key]")
             for key in basePieces.keys():
-                print "%s : %s" % (key, basePieces[key])
+                print("%s : %s" % (key, basePieces[key]))
 
-            print "\nkey : Sorted basePieces[key]"
+            print("\nkey : Sorted basePieces[key]")
             for key in sorted(basePieces.keys()):
-                print "%s : %s" % (key, basePieces[key])
+                print("%s : %s" % (key, basePieces[key]))
 
-            print "\ngeo items:"
+            print("\ngeo items:")
             for item in self._listOfGeoObjects_:
-                print "%s" % (item)
+                print("%s" % (item))
 
-            print "\ngeo items SORTED:"
+            print("\ngeo items SORTED:")
             mySortedGeoStream = self._listOfGeoObjects_[:]
             mySortedGeoStream.sort()
             for item in mySortedGeoStream:
-                print "%s" % (item)
+                print("%s" % (item))
diff --git a/Sim/Gauss/python/Gauss/Geometry/Magnet.py b/Sim/Gauss/python/Gauss/Geometry/Magnet.py
index 1698620af..734c3f68c 100644
--- a/Sim/Gauss/python/Gauss/Geometry/Magnet.py
+++ b/Sim/Gauss/python/Gauss/Geometry/Magnet.py
@@ -1,3 +1,4 @@
+from __future__ import print_function
 from Gauss.Geometry.det_base import det_base
 from Gauss.Geometry.Helpers import subdetector
 
@@ -57,4 +58,4 @@ class Magnet(det_base):
             for magnet in magnets:
               if any(m in magnet for m in scalableMagnets):
                  MagneticFieldSvc(magnet).ForcedSignedCurrentScaling = scale
-                 print "Scaling", magnet, "by", scale
+                 print("Scaling", magnet, "by", scale)
diff --git a/Sim/Gauss/python/Gauss/Geometry/det_base.py b/Sim/Gauss/python/Gauss/Geometry/det_base.py
index 0a60198dd..7543655bd 100644
--- a/Sim/Gauss/python/Gauss/Geometry/det_base.py
+++ b/Sim/Gauss/python/Gauss/Geometry/det_base.py
@@ -50,7 +50,7 @@ class det_base(LHCbConfigurableUser):
 
     def __init__(self, name=Configurable.DefaultName, **kwargs):
         kwargs["name"] = name
-        apply(super(LHCbConfigurableUser, self).__init__, (), kwargs)
+        super(LHCbConfigurableUser, self).__init__(*(), **kwargs)
         self.initialize()
 
     def __apply_configuration__(self):
diff --git a/Sim/Gauss/scripts/GaussStat.py b/Sim/Gauss/scripts/GaussStat.py
index 49cb41fc1..471df691e 100755
--- a/Sim/Gauss/scripts/GaussStat.py
+++ b/Sim/Gauss/scripts/GaussStat.py
@@ -3,6 +3,7 @@
 
 #==============================================================================================
 #==============================================================================================
+from __future__ import print_function
 global script_version
 script_version = '20120105'
 
@@ -29,52 +30,52 @@ def operations(result):
     calculations = ''
     # Computation of Pile-Up interations
     
-    if result.has_key('N2'):
-        if result.has_key('L1'):
+    if 'N2' in result:
+        if 'L1' in result:
             calculations += '\nMean Number of generated Pile-Up interactions: %.4f +- %.6f' % ( result['N2']/result['L1'], (result['N2']/result['L1'])*math.sqrt( (1/result['N2']) + (1/result['L1']) ) )
-    if result.has_key('N1'):
+    if 'N1' in result:
         calculations += '\nMean Number of non-empty generated Pile-Up interactions: %.4f +- %.6f' % ( result['N2']/result['N1'], (result['N2']/result['N1'])*math.sqrt( (1/result['N2']) + (1/result['N1']) )  )
                                                                                                                              
-    if result.has_key('N3') and result.has_key('N4'):
+    if 'N3' in result and 'N4' in result:
         calculations += '\nMean Number of accepted Pile-Up interactions: %.4f +- %.6f\n' % ( result['N4']/result['N3'], (result['N4']/result['N3'])*math.sqrt( (1/result['N4']) + (1/result['N3']) ) )
                                                                                                                              
     #  Computation of cut efficiencies
                                                                                                                              
-    if result.has_key('I2') and result.has_key('I1'):
+    if 'I2' in result and 'I1' in result:
         calculations += '\nGenerator level cut efficiency: %.4f +- %.6f\n' % ( result['I2']/result['I1'], math.sqrt(result['I2']*(result['I1']-result['I2'])/result['I1']**3) )
                                                                                                                              
-    if result.has_key('N20') and result.has_key('N19'):
+    if 'N20' in result and 'N19' in result:
         calculations += '\nFull level cut efficiency: %.4f +- %.6f\n' % ( result['N20']/result['N19'], math.sqrt(result['N20']*(result['N19']-result['N20'])/result['N19']**3) )
                                                                                                                              
     #  Computation of cross-sections
                                                                                                                              
-    if result.has_key('C1') and result.has_key('N2'):
+    if 'C1' in result and 'N2' in result:
         C1 = result['C1N2']/result['N2']
-        if result.has_key('N5'):
+        if 'N5' in result:
             calculations += '\nb cross-section: %.5f +- %.6f' % ( C1*result['N5']/result['N2'], C1*math.sqrt(result['N5']*(result['N2']-result['N5'])/result['N2']**3) )
-        if result.has_key('N6'):
+        if 'N6' in result:
             calculations += '\nDouble b cross-section: %.5f +- %.6f' % ( C1*result['N6']/result['N2'], C1*math.sqrt(result['N6']*(result['N2']-result['N6'])/result['N2']**3) )
-        if result.has_key('N7'):
+        if 'N7' in result:
             calculations += '\nPrompt B cross-section: %.5f +- %.6f' % ( C1*result['N7']/result['N2'], C1*math.sqrt(result['N7']*(result['N2']-result['N7'])/result['N2']**3) )
-        if result.has_key('N8'):
+        if 'N8' in result:
             calculations += '\nc cross-section: %.4f +- %.5f' % ( C1*result['N8']/result['N2'], C1*math.sqrt(result['N8']*(result['N2']-result['N8'])/result['N2']**3) )
-        if result.has_key('N9'):
+        if 'N9' in result:
             calculations += '\nDouble c cross-section: %.5f +- %.6f' % ( C1*result['N9']/result['N2'], C1*math.sqrt(result['N9']*(result['N2']-result['N9'])/result['N2']**3) )
-        if result.has_key('N10'):
+        if 'N10' in result:
             calculations += '\nPrompt D cross-section: %.5f +- %.6f' % ( C1*result['N10']/result['N2'], C1*math.sqrt(result['N10']*(result['N2']-result['N10'])/result['N2']**3) )
-        if result.has_key('N11'):
+        if 'N11' in result:
             calculations += '\nb and c cross-section: %.5f +- %.6f\n' % ( C1*result['N11']/result['N2'], C1*math.sqrt(result['N11']*(result['N2']-result['N11'])/result['N2']**3) )
                                                                                                                              
         #  Computation of B Hadron fraction
         
-        if result.has_key('I3') and result.has_key('I5') and result.has_key('I7') and result.has_key('I9'):
+        if 'I3' in result and 'I5' in result and 'I7' in result and 'I9' in result:
             sum = result['I3']+result['I5']+result['I7']+result['I9']
             calculations += '\nFraction of generated B0: %.4f +- %.6f' % ( result['I3']/sum, math.sqrt(result['I3']*(sum - result['I3'])/sum**3) )
             calculations += '\nFraction of generated B+: %.4f +- %.6f' % ( result['I5']/sum, math.sqrt(result['I5']*(sum - result['I5'])/sum**3) )
             calculations += '\nFraction of generated Bs0: %.4f +- %.6f' % ( result['I7']/sum, math.sqrt(result['I7']*(sum - result['I7'])/sum**3) )
             calculations += '\nFraction of generated b-Baryon: %.4f +- %.6f\n' % ( result['I9']/sum, math.sqrt(result['I7']*(sum - result['I9'])/sum**3) )
 
-        if result.has_key('I14') and result.has_key('I16') and result.has_key('I18') and result.has_key('I20'):
+        if 'I14' in result and 'I16' in result and 'I18' in result and 'I20' in result:
             sum = result['I14']+result['I16']+result['I18']+result['I20']
             if sum != 0:
                 calculations += '\nFraction of accepted B0: %.4f +- %.6f' % ( result['I14']/sum, math.sqrt(result['I14']*(sum - result['I14'])/sum**3) )
@@ -89,14 +90,14 @@ def operations(result):
                 
         #  Computation of D Hadron fraction
                                                                                                                              
-        if result.has_key('I25') and result.has_key('I27') and result.has_key('I29') and result.has_key('I31'):
+        if 'I25' in result and 'I27' in result and 'I29' in result and 'I31' in result:
             sum = result['I25']+result['I27']+result['I29']+result['I31']
             calculations += '\nFraction of generated D0: %.4f +- %.6f' % ( result['I25']/sum, math.sqrt(result['I25']*(sum - result['I25'])/sum**3) )
             calculations += '\nFraction of generated D+: %.4f +- %.6f' % ( result['I27']/sum, math.sqrt(result['I27']*(sum - result['I27'])/sum**3) )
             calculations += '\nFraction of generated Ds+: %.4f +- %.6f' % ( result['I29']/sum, math.sqrt(result['I29']*(sum - result['I29'])/sum**3) )
             calculations += '\nFraction of generated c-Baryon: %.4f +- %.6f\n' % ( result['I31']/sum, math.sqrt(result['I31']*(sum - result['I31'])/sum**3) )
                                                                                                                              
-        if result.has_key('I34') and result.has_key('I36') and result.has_key('I38') and result.has_key('I40'):
+        if 'I34' in result and 'I36' in result and 'I38' in result and 'I40' in result:
             sum = result['I34']+result['I36']+result['I38']+result['I40']
             if sum != 0:
                 calculations += '\nFraction of accepted D0: %.4f +- %.6f' % ( result['I34']/sum, math.sqrt(result['I34']*(sum - result['I34'])/sum**3) )
@@ -112,13 +113,13 @@ def operations(result):
                 
             #  Computation of B** fraction
 
-            if result.has_key('I43') and result.has_key('I44') and result.has_key('I45'):
+            if 'I43' in result and 'I44' in result and 'I45' in result:
                 sum = result['I43']+result['I44']+result['I45']
                 calculations += '\nFraction of generated B: %.4f +- %.6f' % ( result['I43']/sum, math.sqrt(result['I43']*(sum - result['I43'])/sum**3) )
                 calculations += '\nFraction of generated B*: %.4f +- %.6f' % ( result['I44']/sum, math.sqrt(result['I44']*(sum - result['I44'])/sum**3) )
                 calculations += '\nFraction of generated B**: %.4f +- %.6f' % ( result['I45']/sum, math.sqrt(result['I45']*(sum - result['I45'])/sum**3) )
                 
-                if result.has_key('I46') and result.has_key('I47') and result.has_key('I48'):
+                if 'I46' in result and 'I47' in result and 'I48' in result:
                     sum = result['I46']+result['I47']+result['I48']
                     if sum != 0:
                         calculations += '\nFraction of accepted B: %.4f +- %.6f' % ( result['I46']/sum, math.sqrt(result['I46']*(sum - result['I46'])/sum**3) )
@@ -131,7 +132,7 @@ def operations(result):
                                                                                                                              
             #  Computation of D** fraction
             
-            if result.has_key('I49') and result.has_key('I50') and result.has_key('I51'):
+            if 'I49' in result and 'I50' in result and 'I51' in result:
                 sum = result['I49']+result['I50']+result['I51']
                 if sum != 0:
                     calculations += '\nFraction of generated D: %.4f +- %.6f' % ( result['I49']/sum, math.sqrt(result['I49']*(sum - result['I49'])/sum**3) )
@@ -142,7 +143,7 @@ def operations(result):
                     calculations += '\nFraction of generated D*: 0 +- 0'
                     calculations += '\nFraction of generated D**: 0 +- 0'
 
-            if result.has_key('I52') and result.has_key('I53') and result.has_key('I54'):
+            if 'I52' in result and 'I53' in result and 'I54' in result:
                 sum = result['I52']+result['I53']+result['I54']
                 if sum != 0:
                     calculations += '\nFraction of accepted D: %.4f +- %.6f' % ( result['I52']/sum, math.sqrt(result['I52']*(sum - result['I52'])/sum**3) )
@@ -155,10 +156,10 @@ def operations(result):
 
             #  Computation of signal level cut efficiencies
 
-            if result.has_key('S1') and result.has_key('S2'):
+            if 'S1' in result and 'S2' in result:
                 calculations += '\nparticle cut efficiency: %.4f +- %.6f\n' % ( result['S2']/result['S1'], math.sqrt(result['S2']*(result['S1']-result['S2'])/result['S1']**3) )
 
-            if result.has_key('S3') and result.has_key('S4'):
+            if 'S3' in result and 'S4' in result:
                 calculations += '\nanti-particle cut efficiency: %.4f +- %.6f\n' % ( result['S4']/result['S3'], math.sqrt(result['S4']*(result['S3']-result['S4'])/result['S3']**3) )
                 
                 
@@ -181,7 +182,7 @@ def search_general_info(info):
       if test != -1:
           gaussvertmp = info[test:test+100].split(' ')[4].strip().split(' ')[0]
           if str(gaussvertmp) != str(gaussversion):
-              print 'INFO: inside the same PRODID, the gauss version you are currently analyzing: %s is different from the previously analyzed log files gauss version %s '%(gaussversion,gaussvertmp)
+              print('INFO: inside the same PRODID, the gauss version you are currently analyzing: %s is different from the previously analyzed log files gauss version %s '%(gaussversion,gaussvertmp))
               
   # search DDDB version
   DDDB = 'dummy'
@@ -242,7 +243,7 @@ def search_lines(info):
     if check != -1:
         ParamFiles = info[test:test+20].split('/')[1]
     else:
-      print 'Problem with ParamFiles ', info[test:test+100]
+      print('Problem with ParamFiles ', info[test:test+100])
 ##      return result
   result['ParamFiles'] = ParamFiles
 
@@ -457,7 +458,7 @@ def search_lines(info):
     if gaussversion == 'v25r8': S4 = S4/2
     result['S3'] = S3
     result['S4'] = S4
-  if result.has_key('N2') and result.has_key('C1'):
+  if 'N2' in result and 'C1' in result:
     result['C1N2'] = result['C1']*result['N2']
 
   return result
@@ -603,7 +604,7 @@ def gen_store_results(jobgen):
   web_comments = Warning + '<p>Number of accepted events/generated events: %i / %i = %f<br>Number of interactions in accepted events/generated interactions: %i / %i = %f' % ( result['N3'], result['N1'], result['N3']/result['N1'], result['N4'], result['N2'], result['N4']/result['N2'] )
 
 #  web_comments += '<p>Statistics done (script version %s) with %i jobs from the following ProdIDs: </p>\n<p>' %(script_version,jobgen)
-  if result.has_key('L0'):
+  if 'L0' in result:
       web_comments += '<p><font color="#0000FF">Branching fraction of the signal decay mode:</font> %s' % ( str(result['L0']) )
 
   web_comments += '<p>Statistics done (script version %s) with %i jobs from the following ProdIDs:<font color="#0000FF">' %(script_version,jobgen)
@@ -621,7 +622,7 @@ def gen_store_results(jobgen):
 #  file = os.path.join(LocationPath, generation+"_%s_%s.html" % ( wrkflw,evntp))
   file = os.path.join(LocationPath, generation+"_%s.html" % ( APPCONFIG))
   if os.path.exists(file):
-    print '%s exists '%file  
+    print('%s exists '%file)  
     f = open(file,'r')
     lines = f.read()
     f.close()
@@ -646,7 +647,7 @@ def gen_store_results(jobgen):
   else:
   # the file does not exist
   # the file does not exist, create it
-    print '%s does not exist, creating it now'%file
+    print('%s does not exist, creating it now'%file)
     webheader += '<p>Event Type : <a href="%s_%s.html#%s">%s</a> </p>\n' % ( generation, APPCONFIG, str(evntp), str(evntp) )
     webn = webheader + link + table + web_comments + '</body>\n'
 
@@ -777,7 +778,7 @@ def sim_store_results(jobsim, gevents, averageResults, veloResults, richResults,
 
   # Number Of Events written
   if gevents != {}:
-      if gevents.has_key('N1'):
+      if 'N1' in gevents:
           web += '<p>Event written / requested: %i / %i = %s </p>\n' % ( int(gevents['N2']), int(gevents['N1']), str(gevents['N2']/gevents['N1']) )
   else:
       web += '<p><font color="#FF0000">Warning: Impossible to find the Events counters</font></p>'
@@ -801,20 +802,20 @@ def sim_store_results(jobsim, gevents, averageResults, veloResults, richResults,
   file = os.path.join(LocationPath, simulation+"_%s.html" % (APPCONFIG))
  
   if os.path.exists(file):
-    print '%s exists '%file  
+    print('%s exists '%file)  
     f = open(file,'r')
     lines = f.read()
     f.close()
     test = lines.find(str(evntp))
     if test == -1:
-      print '%s event type does not exist - include it'%(str(evntp))
+      print('%s event type does not exist - include it'%(str(evntp)))
       # this event type does not exist
       pos_list = lines.find('</p>\n<a name=')
       pos_table = lines.find('</body>')
       webn = lines[:pos_list] + ' <a href="%s_%s.html#%s">%s</a>' % ( simulation, APPCONFIG, str(evntp), str(evntp) ) + lines[pos_list:pos_table] + web + lines[pos_table:]
     else:
     # This event type exist
-      print '%s event type exists - do not update'%(str(evntp))
+      print('%s event type exists - do not update'%(str(evntp)))
     # just nothing
       pos_table = lines.find('<a name=%s> </a>' % ( str(evntp) ))
       pos_next = lines.find('<a name=', pos_table+1)
@@ -824,7 +825,7 @@ def sim_store_results(jobsim, gevents, averageResults, veloResults, richResults,
 
   else:
   # the file does not exist, create it
-    print '%s does not exist, creating it now'%file
+    print('%s does not exist, creating it now'%file)
 
     webheader = '<html>\n'
     webheader += '<HEAD>\n'
@@ -1084,7 +1085,7 @@ def process_one_file(file):
             if pos > -1:
                 evntp = evntp.replace(';','')
             # The eventtype given and this one found in the log file should be equal
-            if debug_flag == 1: print 'evntp %s eventtype %s '%(evntp,eventtype)
+            if debug_flag == 1: print('evntp %s eventtype %s '%(evntp,eventtype))
             if eventtype != evntp and eventtype != '30000000':
                 sys.exit('something is wrong with logfile format:evntp %s eventtype %s '%(evntp,eventtype))
                 pass
@@ -1092,11 +1093,11 @@ def process_one_file(file):
                 # the data are correct, begin the process
                 # /////////// GENERATION STATISTICS ///////////
                 # results in generationResults
-                if debug_flag == 1: print 'execution=',execution
+                if debug_flag == 1: print('execution=',execution)
                 if execution == 'both' or execution == 'generation':
                     search_general_info(info)
                     numg= Generators(info)
-                    if debug_flag == 1: print 'numg=',numg
+                    if debug_flag == 1: print('numg=',numg)
 #                    print 'File ',file,'has ',numg,' events'
                             
                 # /////////// SIMULATION TABLES  ///////////
@@ -1104,7 +1105,7 @@ def process_one_file(file):
                 if execution == 'both' or execution =='simulation':
                     search_general_info(info)
                     nums = Simulation(info)
-                    if debug_flag == 1: print 'nums=',nums
+                    if debug_flag == 1: print('nums=',nums)
                     
     return numg,nums
 
@@ -1134,7 +1135,7 @@ def Generators(info):
 #                  if index == 'DecFiles' or index == 'ParamFiles':
                   if index == 'DecFiles' or index == 'ParamFiles' or  index == 'L0':
                       if aux[index] != grAux[index]:
-                          if debug_flag == 1: print 'Warning: Different %s version/value found in the logfiles belonging the same production' % index
+                          if debug_flag == 1: print('Warning: Different %s version/value found in the logfiles belonging the same production' % index)
                           generationResults = aux
                       else:
                           generationResults[index] = grAux[index]
@@ -1226,7 +1227,7 @@ def SummaryTable(Data,Results):
 def take_info(file):
     import urllib, tempfile, os, gzip, bz2
     
-    print file
+    print(file)
     log_file = ''
     
     tmpfile = tempfile.mktemp()
@@ -1234,7 +1235,7 @@ def take_info(file):
     try:
       urllib.urlretrieve(file,tmpfile)
     except IOError:
-      print "Error: \tThe url %s is not available or doesn't exist.\n" % file
+      print("Error: \tThe url %s is not available or doesn't exist.\n" % file)
       exit()
       return log_file
 
@@ -1243,13 +1244,13 @@ def take_info(file):
     try:
       fc = gzip.open(tmpfile)
       log_file = fc.read()
-    except IOError, e:
+    except IOError as e:
       # Close the gzip opened file and reopen it as bz2.
       fc.close()
       try:
         fc = bz2.BZ2File(tmpfile)
         log_file = fc.read()
-      except IOError, e:
+      except IOError as e:
 #        print "Error: %s could not be opened as a bz2 or gzip file. Unknown compression or file could not be found on server." %file
 #        print e
 # sm
@@ -1257,9 +1258,9 @@ def take_info(file):
         try:
             fc = open(tmpfile)
             log_file = fc.read()
-        except IOError, e:
-            print "Error: %s could not be opened as uncompressed or a bz2 or gzip file. Unknown compression or file could not be found on server." %file
-            print e
+        except IOError as e:
+            print("Error: %s could not be opened as uncompressed or a bz2 or gzip file. Unknown compression or file could not be found on server." %file)
+            print(e)
 
 
     if fc:
@@ -1279,7 +1280,7 @@ def install(file):
         os.mkdir( dstDir )
     dstFile = os.path.join(dstDir,os.path.basename(file))
     if os.path.exists(dstFile):
-        print 'The file you are trying to move existed already: moving existing file to .old!' 
+        print('The file you are trying to move existed already: moving existing file to .old!') 
         shutil.move( dstFile , dstFile+'.old')
 #    shutil.move( file , dstFile )
     shutil.copy( file , dstFile )
@@ -1328,7 +1329,7 @@ def addToIndex(file):
 
 #################################################################
 def getHTML(url):
-        print ">>> URL -> ", url
+        print(">>> URL -> ", url)
         usock = urllib.urlopen(url)
         htmlSource = usock.read()
         usock.close()
@@ -1369,19 +1370,19 @@ def readErrorDesc(evntp):
 # ========================================================================
 def usage():
     import sys
-    print "Usage: \tpython GaussStat.py -e EVENTTYPE -f filename.log.gz"
-    print "Usage: \tpython GaussStat.py -e EVENTTYPE -v GaussVersion -f filename.log.gz"
-    print "Usage: \tpython GaussStat.py -e EVENTTYPE -v GaussVersion --path directory_with_logs"
-    print "\t                              [--simulation/--generation]"
-    print "\t                              [-h/--help]\n"
-    print "\t                              [-d/--debug]\n"
-    print "\t                              [-i/--install]\n"
-    print "\t                              [-a/--addToIndex]\n"
+    print("Usage: \tpython GaussStat.py -e EVENTTYPE -f filename.log.gz")
+    print("Usage: \tpython GaussStat.py -e EVENTTYPE -v GaussVersion -f filename.log.gz")
+    print("Usage: \tpython GaussStat.py -e EVENTTYPE -v GaussVersion --path directory_with_logs")
+    print("\t                              [--simulation/--generation]")
+    print("\t                              [-h/--help]\n")
+    print("\t                              [-d/--debug]\n")
+    print("\t                              [-i/--install]\n")
+    print("\t                              [-a/--addToIndex]\n")
  
-    print "Ex: python GaussStat.py -e 13104011 --path /afs/cern.ch/lhcb/group/gauss/LogChecks/testLog.dir/Gauss_logs_12345/"
-    print "    python GaussStat.py -e 13104011 -v v37r3p1 --path /afs/cern.ch/lhcb/group/gauss/LogChecks/testLog.dir/Gauss_logs_12345/"
-    print "    python GaussStat.py -e 13104011 -v v37r3p1 -f /afs/cern.ch/lhcb/group/gauss/LogChecks/testLog.dir/Gauss_logs_12345/Gauss_00012345_00012345_1.log.gz"
-    print "    python GaussStat.py -e 13104011 --simulation --path /afs/cern.ch/lhcb/group/gauss/LogChecks/testLog.dir/Gauss_logs_12345/"
+    print("Ex: python GaussStat.py -e 13104011 --path /afs/cern.ch/lhcb/group/gauss/LogChecks/testLog.dir/Gauss_logs_12345/")
+    print("    python GaussStat.py -e 13104011 -v v37r3p1 --path /afs/cern.ch/lhcb/group/gauss/LogChecks/testLog.dir/Gauss_logs_12345/")
+    print("    python GaussStat.py -e 13104011 -v v37r3p1 -f /afs/cern.ch/lhcb/group/gauss/LogChecks/testLog.dir/Gauss_logs_12345/Gauss_00012345_00012345_1.log.gz")
+    print("    python GaussStat.py -e 13104011 --simulation --path /afs/cern.ch/lhcb/group/gauss/LogChecks/testLog.dir/Gauss_logs_12345/")
 
     sys.exit()
 
@@ -1455,7 +1456,7 @@ if __name__ == "__main__":
         if key in ('--path', ''):
             filelist = [os.path.join(value, f) for f in os.listdir(value)]
     if execution == '': execution = 'both'
-    print 'debug_flag %s  eventtype %s gaussversion %s  execution %s install_flag %s add_flag %s'%(debug_flag,eventtype,gaussversion,execution,install_flag,add_flag)
+    print('debug_flag %s  eventtype %s gaussversion %s  execution %s install_flag %s add_flag %s'%(debug_flag,eventtype,gaussversion,execution,install_flag,add_flag))
 
     #-------------------------------------------------------------------------
     # analize only one file if filename is provided with -f options
@@ -1487,14 +1488,14 @@ if __name__ == "__main__":
 
         # compute average and create tables
         if execution == 'both' or execution == 'generation':
-            print 'Creating Generation Statistics Tables.... ', eventtype,gaussversion
+            print('Creating Generation Statistics Tables.... ', eventtype,gaussversion)
             # store the results in a file RESULTS_<eventtype>.html
             rc = gen_store_results(numg)
             if rc == 'KO':
-                print 'No results for generation statistics %s Gauss %s eventtype %s' %(this_lumi,gaussversion,eventtype)
+                print('No results for generation statistics %s Gauss %s eventtype %s' %(this_lumi,gaussversion,eventtype))
 
         if execution == 'both' or execution =='simulation':
-            print 'Creating Simulation  Statistics Tables.... ', eventtype,gaussversion
+            print('Creating Simulation  Statistics Tables.... ', eventtype,gaussversion)
             # store the results in a file RESULTS_<eventtype>.html
             muonResults = [m1, m2, m3, m4, m5, m6]
             rc = sim_store_results(nums,gevents,averageResults,veloResults,richResults,muonResults)
-- 
GitLab


From a23d863ebbcac916cb60fe325ac212af2ee19d70 Mon Sep 17 00:00:00 2001
From: Michal Mazurek <michal.mazurek@cern.ch>
Date: Sun, 9 May 2021 23:04:02 +0200
Subject: [PATCH 86/90] Use absolute paths

---
 Sim/Gauss/python/Gauss/__init__.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Sim/Gauss/python/Gauss/__init__.py b/Sim/Gauss/python/Gauss/__init__.py
index a17e4b6aa..d6d293022 100644
--- a/Sim/Gauss/python/Gauss/__init__.py
+++ b/Sim/Gauss/python/Gauss/__init__.py
@@ -1,5 +1,5 @@
 # entry point for the Python module
-from Physics import G4Physics
+from Gauss.Physics import G4Physics
 
 __all__ = [
     G4Physics
-- 
GitLab


From 3ece6bd51b30d2856d4f629d6a64f96fbbbbb797 Mon Sep 17 00:00:00 2001
From: Michal Mazurek <michal.mazurek@cern.ch>
Date: Sun, 9 May 2021 23:05:34 +0200
Subject: [PATCH 87/90] Stage 2 of futurize: only packages with no
 .gaudi_project_ignore

futurize -w --stage2 --nobackups $(find . -name '*.py' | egrep -v "$(echo $(find . -name'.gaudi_project_ignore' | sed -e 's/\.gaudi_project_ignore//g' | sed -e 's/\.\///g') | sed -e 's/\/\s/|/g')|InstallArea|build|Sim/Gauss/tests")  -w
---
 GaussSys/scripts/project_manifest.py          |   4 +-
 Gen/LoKiGen/python/LoKiGen/graph.py           |   1 +
 .../ModelCreator.py                           |   3 +-
 .../ModelSubmission.py                        |   9 +-
 .../ModelSubmission_simple.py                 |   7 +-
 Sim/Gauss/options/SimVeloGeometry.py          |   2 +
 Sim/Gauss/python/Gauss/Configuration.py       |   5 +-
 Sim/Gauss/python/Gauss/Geometry/BeamPipe.py   |   6 +-
 .../python/Gauss/Geometry/Configuration.py    |   6 +-
 Sim/Gauss/python/Gauss/Geometry/Helpers.py    |   2 +-
 Sim/Gauss/python/Gauss/Geometry/Magnet.py     |   4 +-
 Sim/Gauss/python/Gauss/Geometry/Velo.py       |   2 +
 Sim/Gauss/python/Gauss/Utilities.py           |   4 +-
 Sim/Gauss/scripts/GaussStat.py                | 136 +++++++++---------
 14 files changed, 109 insertions(+), 82 deletions(-)

diff --git a/GaussSys/scripts/project_manifest.py b/GaussSys/scripts/project_manifest.py
index d4abd641c..c033b5fa6 100644
--- a/GaussSys/scripts/project_manifest.py
+++ b/GaussSys/scripts/project_manifest.py
@@ -2,6 +2,8 @@
 # -*- coding: utf-8 -*-
 
 from __future__ import print_function
+from builtins import filter
+from builtins import zip
 import sys
 import os
 from xml.etree import ElementTree as ET
@@ -187,7 +189,7 @@ if __name__ == '__main__':
 
     # Hack alert: tcmalloc LCG_interface corresponds to gperftools
     # as from LCG 84. We rename the external in that case...
-    if int(filter(str.isdigit, lcg_version)) >= 84:
+    if int(list(filter(str.isdigit, lcg_version))) >= 84:
         rpm_names['tcmalloc'] = 'gperftools'
         
     fix_rpm_name = lambda n: rpm_names.get(n, n)
diff --git a/Gen/LoKiGen/python/LoKiGen/graph.py b/Gen/LoKiGen/python/LoKiGen/graph.py
index 6c4028d68..ef45dcfc2 100644
--- a/Gen/LoKiGen/python/LoKiGen/graph.py
+++ b/Gen/LoKiGen/python/LoKiGen/graph.py
@@ -36,6 +36,7 @@ A.Golutvin, P.Koppenburg have been used in the design.
 """
 from __future__ import print_function
 # =============================================================================
+from builtins import object
 __author__ = "Vanya BELYAEV Ivan.Belyaev@itep.ru"
 __date__ = "2015-01-16"
 __version__ = ""
diff --git a/Gen/Mint/src/Users/Matt/ModelBuilderGridSubmission/ModelCreator.py b/Gen/Mint/src/Users/Matt/ModelBuilderGridSubmission/ModelCreator.py
index 71c4422e6..20608d9e2 100644
--- a/Gen/Mint/src/Users/Matt/ModelBuilderGridSubmission/ModelCreator.py
+++ b/Gen/Mint/src/Users/Matt/ModelBuilderGridSubmission/ModelCreator.py
@@ -1,6 +1,7 @@
+from builtins import object
 import os
 
-class ModelCreator:
+class ModelCreator(object):
     constDecays = ['D0->a(1)(1260)+[D](->rho(770)0(->pi+,pi-),pi+),pi-',
                   'D0->a(1)(1260)+(->sigma10(->pi+,pi-),pi+),pi-',
                   'D0->rho(770)0(->pi+,pi-),rho(770)0(->pi+,pi-)',
diff --git a/Gen/Mint/src/Users/Matt/ModelBuilderGridSubmission/ModelSubmission.py b/Gen/Mint/src/Users/Matt/ModelBuilderGridSubmission/ModelSubmission.py
index d033581a9..516980458 100644
--- a/Gen/Mint/src/Users/Matt/ModelBuilderGridSubmission/ModelSubmission.py
+++ b/Gen/Mint/src/Users/Matt/ModelBuilderGridSubmission/ModelSubmission.py
@@ -1,9 +1,12 @@
 from __future__ import print_function
 
+from builtins import str
+from builtins import range
+from builtins import object
 import os
 import time
 
-class ModelCreator:
+class ModelCreator(object):
     constDecays = ['D0->a(1)(1260)+[D](->rho(770)0(->pi+,pi-),pi+),pi-',
                   'D0->a(1)(1260)+(->sigma10(->pi+,pi-),pi+),pi-',
                   'D0->rho(770)0(->pi+,pi-),rho(770)0(->pi+,pi-)',
@@ -77,7 +80,7 @@ for j in range(0,len(optionalDecays)):
 modelsForIt.close()
 
 """
-class Models:
+class Models(object):
     inputfile = ''
     def __init__(self,file='FileOfModels.txt'):
         self.inputfile = file
@@ -87,7 +90,7 @@ class Models:
         return models
     
 #Create Ganga Job
-class ModelFinderJob:
+class ModelFinderJob(object):
     basedir=""
     userarea = ""
     ParticleProp = ""
diff --git a/Gen/Mint/src/Users/Matt/ModelBuilderGridSubmission/ModelSubmission_simple.py b/Gen/Mint/src/Users/Matt/ModelBuilderGridSubmission/ModelSubmission_simple.py
index f4a85db11..8953e8bb9 100644
--- a/Gen/Mint/src/Users/Matt/ModelBuilderGridSubmission/ModelSubmission_simple.py
+++ b/Gen/Mint/src/Users/Matt/ModelBuilderGridSubmission/ModelSubmission_simple.py
@@ -1,9 +1,12 @@
 from __future__ import print_function
 
+from builtins import str
+from builtins import range
+from builtins import object
 import os
 import time
 
-class Models:
+class Models(object):
     inputfile = ''
     def __init__(self,file='FileOfModels.txt'):
         self.inputfile = file
@@ -13,7 +16,7 @@ class Models:
         return models
     
 #Create Ganga Job
-class ModelFinderJob:
+class ModelFinderJob(object):
     basedir=""
     userarea = ""
     ParticleProp = ""
diff --git a/Sim/Gauss/options/SimVeloGeometry.py b/Sim/Gauss/options/SimVeloGeometry.py
index 8791404c0..4bb42dc20 100755
--- a/Sim/Gauss/options/SimVeloGeometry.py
+++ b/Sim/Gauss/options/SimVeloGeometry.py
@@ -17,6 +17,8 @@
 # *  @date 2006-02-14
 #  modified for python, T.Ruf 18.11.2008
 
+from builtins import str
+from builtins import range
 from Gaudi.Configuration import *
 from Configurables import GiGaInputStream
 
diff --git a/Sim/Gauss/python/Gauss/Configuration.py b/Sim/Gauss/python/Gauss/Configuration.py
index 82ef7f0e3..9c18f18d8 100755
--- a/Sim/Gauss/python/Gauss/Configuration.py
+++ b/Sim/Gauss/python/Gauss/Configuration.py
@@ -3,6 +3,9 @@ High level configuration tools for Gauss
 Beampipe configuration added.
 """
 from __future__ import print_function
+from __future__ import division
+from builtins import str
+from past.utils import old_div
 __version__ = "$Id: Configuration.py,v 1.30 2010/05/09 18:14:28 gcorti Exp $"
 __author__ = "Gloria Corti <Gloria.Corti@cern.ch>"
 
@@ -44,7 +47,7 @@ class Gauss(LHCbConfigurableUser):
         "BeamLineAngles": [-0.075 * SystemOfUnits.mrad, 0.035 * SystemOfUnits.mrad],  # NOQA
         "InteractionPosition" : [0.459 * SystemOfUnits.mm, -0.015 * SystemOfUnits.mm, 0.5 * SystemOfUnits.mm],  # NOQA
         "BunchRMS": 82.03 * SystemOfUnits.mm,  # NOQA
-        "Luminosity": 0.247 * (10 ** 30) / (SystemOfUnits.cm2 * SystemOfUnits.s),  # NOQA
+        "Luminosity": old_div(0.247 * (10 ** 30), (SystemOfUnits.cm2 * SystemOfUnits.s)),  # NOQA
         "TotalCrossSection": 91.1 * SystemOfUnits.millibarn,  # NOQA
         "B2Momentum": 3.5 * SystemOfUnits.TeV,  # NOQA
         "B1Particle": 'p',  # NOQA
diff --git a/Sim/Gauss/python/Gauss/Geometry/BeamPipe.py b/Sim/Gauss/python/Gauss/Geometry/BeamPipe.py
index a80491f3e..9b8752419 100644
--- a/Sim/Gauss/python/Gauss/Geometry/BeamPipe.py
+++ b/Sim/Gauss/python/Gauss/Geometry/BeamPipe.py
@@ -43,7 +43,7 @@ class BeamPipe(det_base):
     def removeBeamPipeElements(det):
         det = det.lower()
         # Remove beampipe elements in <det> - will be included automatically
-        if det in BeamPipe._beamPipeElements.keys():
+        if det in list(BeamPipe._beamPipeElements.keys()):
             for element in BeamPipe._beamPipeElements[det]:
                 # remove all instances of the element
                 while element in LHCbGeo._listOfGeoObjects_:
@@ -52,7 +52,7 @@ class BeamPipe(det_base):
     @staticmethod
     def removeAllBeamPipeElements():
         # Remove all beampipe elements
-        for det in BeamPipe._beamPipeElements.keys():
+        for det in list(BeamPipe._beamPipeElements.keys()):
             for element in BeamPipe._beamPipeElements[det]:
                 # remove all instances of the element
                 while element in LHCbGeo._listOfGeoObjects_:
@@ -91,7 +91,7 @@ class BeamPipe(det_base):
                 det
                 for det in ignoreList if det not in ttDetectorList]
 
-        for region in self._beamPipeElements.keys():
+        for region in list(self._beamPipeElements.keys()):
             if region in ignoreList:
                 continue
             for element in self._beamPipeElements[region]:
diff --git a/Sim/Gauss/python/Gauss/Geometry/Configuration.py b/Sim/Gauss/python/Gauss/Geometry/Configuration.py
index 3b23dee3f..e22ddfca7 100644
--- a/Sim/Gauss/python/Gauss/Geometry/Configuration.py
+++ b/Sim/Gauss/python/Gauss/Geometry/Configuration.py
@@ -64,7 +64,7 @@ class LHCbGeo(LHCbConfigurableUser):
         self.initialize()
 
     def defineStreamItemsGeo(self, basePieces, detPieces):
-        for region in basePieces.keys():
+        for region in list(basePieces.keys()):
             path = "/dd/Structure/LHCb/"+region+"/"
             if len(detPieces[region]) == 0:
                 continue
@@ -206,7 +206,7 @@ class LHCbGeo(LHCbConfigurableUser):
         if self.getProp("Debug") and not self.getProp("DD4hep"):
             print("\nDEBUG Detector Geometry Elements:")
             print("\nkey : detPieces[key]")
-            for key in detPieces.keys():
+            for key in list(detPieces.keys()):
                 print("%s : %s" % (key, detPieces[key]))
             print("\nkey : Sorted detPieces[key]")
 
@@ -214,7 +214,7 @@ class LHCbGeo(LHCbConfigurableUser):
                 print("%s : %s" % (key, detPieces[key]))
 
             print("\nkey : basePieces[key]")
-            for key in basePieces.keys():
+            for key in list(basePieces.keys()):
                 print("%s : %s" % (key, basePieces[key]))
 
             print("\nkey : Sorted basePieces[key]")
diff --git a/Sim/Gauss/python/Gauss/Geometry/Helpers.py b/Sim/Gauss/python/Gauss/Geometry/Helpers.py
index e49f56094..b81e26d63 100644
--- a/Sim/Gauss/python/Gauss/Geometry/Helpers.py
+++ b/Sim/Gauss/python/Gauss/Geometry/Helpers.py
@@ -26,7 +26,7 @@ def checkIncompatibleDetectors():
         "Muon": ["Muon", "MuonNoM1"],
         "MuonTorch": ["Muon", "Torch"]
     }
-    for section in _incompatibleDetectors.keys():
+    for section in list(_incompatibleDetectors.keys()):
         incompatList = _incompatibleDetectors[section]
         used_dets = LHCbGeo().getProp("DetectorGeo")['Detectors']
         myList = [det for det in used_dets if det in incompatList]
diff --git a/Sim/Gauss/python/Gauss/Geometry/Magnet.py b/Sim/Gauss/python/Gauss/Geometry/Magnet.py
index 734c3f68c..b7aa7ce1f 100644
--- a/Sim/Gauss/python/Gauss/Geometry/Magnet.py
+++ b/Sim/Gauss/python/Gauss/Geometry/Magnet.py
@@ -1,4 +1,6 @@
 from __future__ import print_function
+from __future__ import division
+from past.utils import old_div
 from Gauss.Geometry.det_base import det_base
 from Gauss.Geometry.Helpers import subdetector
 
@@ -54,7 +56,7 @@ class Magnet(det_base):
             # Scale dipoles and quadrupoles.
             scalableMagnets = ["Q1", "Q2", "Q3", "D1", "MCBX"]
             magnets = MultipleMagneticFieldSvc().getProp("MagneticFieldServices")
-            scale =  self.getProp("BeamMomentum") / (3.5 * SystemOfUnits.TeV )
+            scale =  old_div(self.getProp("BeamMomentum"), (3.5 * SystemOfUnits.TeV ))
             for magnet in magnets:
               if any(m in magnet for m in scalableMagnets):
                  MagneticFieldSvc(magnet).ForcedSignedCurrentScaling = scale
diff --git a/Sim/Gauss/python/Gauss/Geometry/Velo.py b/Sim/Gauss/python/Gauss/Geometry/Velo.py
index d7178c937..6ca715e47 100644
--- a/Sim/Gauss/python/Gauss/Geometry/Velo.py
+++ b/Sim/Gauss/python/Gauss/Geometry/Velo.py
@@ -1,3 +1,5 @@
+from builtins import str
+from builtins import range
 from Gauss.Geometry.det_base import det_base
 from Gaudi.Configuration import log
 from Gaudi.Configuration import Configurable
diff --git a/Sim/Gauss/python/Gauss/Utilities.py b/Sim/Gauss/python/Gauss/Utilities.py
index 66dff20b2..3c838ac0d 100644
--- a/Sim/Gauss/python/Gauss/Utilities.py
+++ b/Sim/Gauss/python/Gauss/Utilities.py
@@ -1,3 +1,5 @@
+from builtins import str
+from builtins import object
 from Gaudi.Configuration import importOptions
 from Gaussino.Utilities import run_once
 
@@ -12,7 +14,7 @@ def GaussImportOptions(options):
     importOptions(options)
 
 
-class HelperBase:
+class HelperBase(object):
 
     def slotName(self, slot):
         name = slot
diff --git a/Sim/Gauss/scripts/GaussStat.py b/Sim/Gauss/scripts/GaussStat.py
index 471df691e..ceb17900b 100755
--- a/Sim/Gauss/scripts/GaussStat.py
+++ b/Sim/Gauss/scripts/GaussStat.py
@@ -4,6 +4,12 @@
 #==============================================================================================
 #==============================================================================================
 from __future__ import print_function
+from __future__ import division
+from future import standard_library
+standard_library.install_aliases()
+from builtins import str
+from builtins import range
+from past.utils import old_div
 global script_version
 script_version = '20120105'
 
@@ -11,7 +17,7 @@ script_version = '20120105'
 def float__(s):
     """emulate the behaviour of python float, but makes it valid oalso on
     FORTRAN scientific notation with Double.  1.2D+03 """ 
-    from __builtin__ import float
+    from builtins import float
     try:
         return float(s)
     except ValueError:
@@ -32,56 +38,56 @@ def operations(result):
     
     if 'N2' in result:
         if 'L1' in result:
-            calculations += '\nMean Number of generated Pile-Up interactions: %.4f +- %.6f' % ( result['N2']/result['L1'], (result['N2']/result['L1'])*math.sqrt( (1/result['N2']) + (1/result['L1']) ) )
+            calculations += '\nMean Number of generated Pile-Up interactions: %.4f +- %.6f' % ( old_div(result['N2'],result['L1']), (old_div(result['N2'],result['L1']))*math.sqrt( (old_div(1,result['N2'])) + (old_div(1,result['L1'])) ) )
     if 'N1' in result:
-        calculations += '\nMean Number of non-empty generated Pile-Up interactions: %.4f +- %.6f' % ( result['N2']/result['N1'], (result['N2']/result['N1'])*math.sqrt( (1/result['N2']) + (1/result['N1']) )  )
+        calculations += '\nMean Number of non-empty generated Pile-Up interactions: %.4f +- %.6f' % ( old_div(result['N2'],result['N1']), (old_div(result['N2'],result['N1']))*math.sqrt( (old_div(1,result['N2'])) + (old_div(1,result['N1'])) )  )
                                                                                                                              
     if 'N3' in result and 'N4' in result:
-        calculations += '\nMean Number of accepted Pile-Up interactions: %.4f +- %.6f\n' % ( result['N4']/result['N3'], (result['N4']/result['N3'])*math.sqrt( (1/result['N4']) + (1/result['N3']) ) )
+        calculations += '\nMean Number of accepted Pile-Up interactions: %.4f +- %.6f\n' % ( old_div(result['N4'],result['N3']), (old_div(result['N4'],result['N3']))*math.sqrt( (old_div(1,result['N4'])) + (old_div(1,result['N3'])) ) )
                                                                                                                              
     #  Computation of cut efficiencies
                                                                                                                              
     if 'I2' in result and 'I1' in result:
-        calculations += '\nGenerator level cut efficiency: %.4f +- %.6f\n' % ( result['I2']/result['I1'], math.sqrt(result['I2']*(result['I1']-result['I2'])/result['I1']**3) )
+        calculations += '\nGenerator level cut efficiency: %.4f +- %.6f\n' % ( old_div(result['I2'],result['I1']), math.sqrt(old_div(result['I2']*(result['I1']-result['I2']),result['I1']**3)) )
                                                                                                                              
     if 'N20' in result and 'N19' in result:
-        calculations += '\nFull level cut efficiency: %.4f +- %.6f\n' % ( result['N20']/result['N19'], math.sqrt(result['N20']*(result['N19']-result['N20'])/result['N19']**3) )
+        calculations += '\nFull level cut efficiency: %.4f +- %.6f\n' % ( old_div(result['N20'],result['N19']), math.sqrt(old_div(result['N20']*(result['N19']-result['N20']),result['N19']**3)) )
                                                                                                                              
     #  Computation of cross-sections
                                                                                                                              
     if 'C1' in result and 'N2' in result:
-        C1 = result['C1N2']/result['N2']
+        C1 = old_div(result['C1N2'],result['N2'])
         if 'N5' in result:
-            calculations += '\nb cross-section: %.5f +- %.6f' % ( C1*result['N5']/result['N2'], C1*math.sqrt(result['N5']*(result['N2']-result['N5'])/result['N2']**3) )
+            calculations += '\nb cross-section: %.5f +- %.6f' % ( old_div(C1*result['N5'],result['N2']), C1*math.sqrt(old_div(result['N5']*(result['N2']-result['N5']),result['N2']**3)) )
         if 'N6' in result:
-            calculations += '\nDouble b cross-section: %.5f +- %.6f' % ( C1*result['N6']/result['N2'], C1*math.sqrt(result['N6']*(result['N2']-result['N6'])/result['N2']**3) )
+            calculations += '\nDouble b cross-section: %.5f +- %.6f' % ( old_div(C1*result['N6'],result['N2']), C1*math.sqrt(old_div(result['N6']*(result['N2']-result['N6']),result['N2']**3)) )
         if 'N7' in result:
-            calculations += '\nPrompt B cross-section: %.5f +- %.6f' % ( C1*result['N7']/result['N2'], C1*math.sqrt(result['N7']*(result['N2']-result['N7'])/result['N2']**3) )
+            calculations += '\nPrompt B cross-section: %.5f +- %.6f' % ( old_div(C1*result['N7'],result['N2']), C1*math.sqrt(old_div(result['N7']*(result['N2']-result['N7']),result['N2']**3)) )
         if 'N8' in result:
-            calculations += '\nc cross-section: %.4f +- %.5f' % ( C1*result['N8']/result['N2'], C1*math.sqrt(result['N8']*(result['N2']-result['N8'])/result['N2']**3) )
+            calculations += '\nc cross-section: %.4f +- %.5f' % ( old_div(C1*result['N8'],result['N2']), C1*math.sqrt(old_div(result['N8']*(result['N2']-result['N8']),result['N2']**3)) )
         if 'N9' in result:
-            calculations += '\nDouble c cross-section: %.5f +- %.6f' % ( C1*result['N9']/result['N2'], C1*math.sqrt(result['N9']*(result['N2']-result['N9'])/result['N2']**3) )
+            calculations += '\nDouble c cross-section: %.5f +- %.6f' % ( old_div(C1*result['N9'],result['N2']), C1*math.sqrt(old_div(result['N9']*(result['N2']-result['N9']),result['N2']**3)) )
         if 'N10' in result:
-            calculations += '\nPrompt D cross-section: %.5f +- %.6f' % ( C1*result['N10']/result['N2'], C1*math.sqrt(result['N10']*(result['N2']-result['N10'])/result['N2']**3) )
+            calculations += '\nPrompt D cross-section: %.5f +- %.6f' % ( old_div(C1*result['N10'],result['N2']), C1*math.sqrt(old_div(result['N10']*(result['N2']-result['N10']),result['N2']**3)) )
         if 'N11' in result:
-            calculations += '\nb and c cross-section: %.5f +- %.6f\n' % ( C1*result['N11']/result['N2'], C1*math.sqrt(result['N11']*(result['N2']-result['N11'])/result['N2']**3) )
+            calculations += '\nb and c cross-section: %.5f +- %.6f\n' % ( old_div(C1*result['N11'],result['N2']), C1*math.sqrt(old_div(result['N11']*(result['N2']-result['N11']),result['N2']**3)) )
                                                                                                                              
         #  Computation of B Hadron fraction
         
         if 'I3' in result and 'I5' in result and 'I7' in result and 'I9' in result:
             sum = result['I3']+result['I5']+result['I7']+result['I9']
-            calculations += '\nFraction of generated B0: %.4f +- %.6f' % ( result['I3']/sum, math.sqrt(result['I3']*(sum - result['I3'])/sum**3) )
-            calculations += '\nFraction of generated B+: %.4f +- %.6f' % ( result['I5']/sum, math.sqrt(result['I5']*(sum - result['I5'])/sum**3) )
-            calculations += '\nFraction of generated Bs0: %.4f +- %.6f' % ( result['I7']/sum, math.sqrt(result['I7']*(sum - result['I7'])/sum**3) )
-            calculations += '\nFraction of generated b-Baryon: %.4f +- %.6f\n' % ( result['I9']/sum, math.sqrt(result['I7']*(sum - result['I9'])/sum**3) )
+            calculations += '\nFraction of generated B0: %.4f +- %.6f' % ( old_div(result['I3'],sum), math.sqrt(old_div(result['I3']*(sum - result['I3']),sum**3)) )
+            calculations += '\nFraction of generated B+: %.4f +- %.6f' % ( old_div(result['I5'],sum), math.sqrt(old_div(result['I5']*(sum - result['I5']),sum**3)) )
+            calculations += '\nFraction of generated Bs0: %.4f +- %.6f' % ( old_div(result['I7'],sum), math.sqrt(old_div(result['I7']*(sum - result['I7']),sum**3)) )
+            calculations += '\nFraction of generated b-Baryon: %.4f +- %.6f\n' % ( old_div(result['I9'],sum), math.sqrt(old_div(result['I7']*(sum - result['I9']),sum**3)) )
 
         if 'I14' in result and 'I16' in result and 'I18' in result and 'I20' in result:
             sum = result['I14']+result['I16']+result['I18']+result['I20']
             if sum != 0:
-                calculations += '\nFraction of accepted B0: %.4f +- %.6f' % ( result['I14']/sum, math.sqrt(result['I14']*(sum - result['I14'])/sum**3) )
-                calculations += '\nFraction of accepted B+: %.4f +- %.6f' % ( result['I16']/sum, math.sqrt(result['I16']*(sum - result['I16'])/sum**3) )
-                calculations += '\nFraction of accepted Bs0: %.4f +- %.6f' % ( result['I18']/sum, math.sqrt(result['I18']*(sum - result['I18'])/sum**3) )
-                calculations += '\nFraction of accepted b-Baryon: %.4f +- %.6f\n' % ( result['I20']/sum, math.sqrt(result['I20']*(sum - result['I20'])/sum**3) )
+                calculations += '\nFraction of accepted B0: %.4f +- %.6f' % ( old_div(result['I14'],sum), math.sqrt(old_div(result['I14']*(sum - result['I14']),sum**3)) )
+                calculations += '\nFraction of accepted B+: %.4f +- %.6f' % ( old_div(result['I16'],sum), math.sqrt(old_div(result['I16']*(sum - result['I16']),sum**3)) )
+                calculations += '\nFraction of accepted Bs0: %.4f +- %.6f' % ( old_div(result['I18'],sum), math.sqrt(old_div(result['I18']*(sum - result['I18']),sum**3)) )
+                calculations += '\nFraction of accepted b-Baryon: %.4f +- %.6f\n' % ( old_div(result['I20'],sum), math.sqrt(old_div(result['I20']*(sum - result['I20']),sum**3)) )
             else:
                 calculations += '\nFraction of accepted B0: 0 +- 0'
                 calculations += '\nFraction of accepted B+: 0 +- 0'
@@ -92,19 +98,19 @@ def operations(result):
                                                                                                                              
         if 'I25' in result and 'I27' in result and 'I29' in result and 'I31' in result:
             sum = result['I25']+result['I27']+result['I29']+result['I31']
-            calculations += '\nFraction of generated D0: %.4f +- %.6f' % ( result['I25']/sum, math.sqrt(result['I25']*(sum - result['I25'])/sum**3) )
-            calculations += '\nFraction of generated D+: %.4f +- %.6f' % ( result['I27']/sum, math.sqrt(result['I27']*(sum - result['I27'])/sum**3) )
-            calculations += '\nFraction of generated Ds+: %.4f +- %.6f' % ( result['I29']/sum, math.sqrt(result['I29']*(sum - result['I29'])/sum**3) )
-            calculations += '\nFraction of generated c-Baryon: %.4f +- %.6f\n' % ( result['I31']/sum, math.sqrt(result['I31']*(sum - result['I31'])/sum**3) )
+            calculations += '\nFraction of generated D0: %.4f +- %.6f' % ( old_div(result['I25'],sum), math.sqrt(old_div(result['I25']*(sum - result['I25']),sum**3)) )
+            calculations += '\nFraction of generated D+: %.4f +- %.6f' % ( old_div(result['I27'],sum), math.sqrt(old_div(result['I27']*(sum - result['I27']),sum**3)) )
+            calculations += '\nFraction of generated Ds+: %.4f +- %.6f' % ( old_div(result['I29'],sum), math.sqrt(old_div(result['I29']*(sum - result['I29']),sum**3)) )
+            calculations += '\nFraction of generated c-Baryon: %.4f +- %.6f\n' % ( old_div(result['I31'],sum), math.sqrt(old_div(result['I31']*(sum - result['I31']),sum**3)) )
                                                                                                                              
         if 'I34' in result and 'I36' in result and 'I38' in result and 'I40' in result:
             sum = result['I34']+result['I36']+result['I38']+result['I40']
             if sum != 0:
-                calculations += '\nFraction of accepted D0: %.4f +- %.6f' % ( result['I34']/sum, math.sqrt(result['I34']*(sum - result['I34'])/sum**3) )
-                calculations += '\nFraction of accepted D+: %.4f +- %.6f' % ( result['I36']/sum, math.sqrt(result['I36']*(sum - result['I36'])/sum**3) )
-                calculations += '\nFraction of accepted Ds+: %.4f +- %.6f' % ( result['I38']/sum, math.sqrt(result['I38']*(sum - result['I38'])/sum**3) )
-                calculations += '\nFraction of accepted c-Baryon: %.4f +- %.6f\n' % ( result['I40']/sum, math.sqrt(result['I40']*(sum -
-                                                                                                                                  result['I40'])/sum**3) )
+                calculations += '\nFraction of accepted D0: %.4f +- %.6f' % ( old_div(result['I34'],sum), math.sqrt(old_div(result['I34']*(sum - result['I34']),sum**3)) )
+                calculations += '\nFraction of accepted D+: %.4f +- %.6f' % ( old_div(result['I36'],sum), math.sqrt(old_div(result['I36']*(sum - result['I36']),sum**3)) )
+                calculations += '\nFraction of accepted Ds+: %.4f +- %.6f' % ( old_div(result['I38'],sum), math.sqrt(old_div(result['I38']*(sum - result['I38']),sum**3)) )
+                calculations += '\nFraction of accepted c-Baryon: %.4f +- %.6f\n' % ( old_div(result['I40'],sum), math.sqrt(old_div(result['I40']*(sum -
+                                                                                                                                  result['I40']),sum**3)) )
             else:
                 calculations += '\nFraction of accepted D0: 0 +- 0'
                 calculations += '\nFraction of accepted D+: 0 +- 0'
@@ -115,16 +121,16 @@ def operations(result):
 
             if 'I43' in result and 'I44' in result and 'I45' in result:
                 sum = result['I43']+result['I44']+result['I45']
-                calculations += '\nFraction of generated B: %.4f +- %.6f' % ( result['I43']/sum, math.sqrt(result['I43']*(sum - result['I43'])/sum**3) )
-                calculations += '\nFraction of generated B*: %.4f +- %.6f' % ( result['I44']/sum, math.sqrt(result['I44']*(sum - result['I44'])/sum**3) )
-                calculations += '\nFraction of generated B**: %.4f +- %.6f' % ( result['I45']/sum, math.sqrt(result['I45']*(sum - result['I45'])/sum**3) )
+                calculations += '\nFraction of generated B: %.4f +- %.6f' % ( old_div(result['I43'],sum), math.sqrt(old_div(result['I43']*(sum - result['I43']),sum**3)) )
+                calculations += '\nFraction of generated B*: %.4f +- %.6f' % ( old_div(result['I44'],sum), math.sqrt(old_div(result['I44']*(sum - result['I44']),sum**3)) )
+                calculations += '\nFraction of generated B**: %.4f +- %.6f' % ( old_div(result['I45'],sum), math.sqrt(old_div(result['I45']*(sum - result['I45']),sum**3)) )
                 
                 if 'I46' in result and 'I47' in result and 'I48' in result:
                     sum = result['I46']+result['I47']+result['I48']
                     if sum != 0:
-                        calculations += '\nFraction of accepted B: %.4f +- %.6f' % ( result['I46']/sum, math.sqrt(result['I46']*(sum - result['I46'])/sum**3) )
-                        calculations += '\nFraction of accepted B*: %.4f +- %.6f' % ( result['I47']/sum, math.sqrt(result['I47']*(sum - result['I47'])/sum**3) )
-                        calculations += '\nFraction of accepted B**: %.4f +- %.6f' % ( result['I48']/sum, math.sqrt(result['I48']*(sum - result['I48'])/sum**3) )
+                        calculations += '\nFraction of accepted B: %.4f +- %.6f' % ( old_div(result['I46'],sum), math.sqrt(old_div(result['I46']*(sum - result['I46']),sum**3)) )
+                        calculations += '\nFraction of accepted B*: %.4f +- %.6f' % ( old_div(result['I47'],sum), math.sqrt(old_div(result['I47']*(sum - result['I47']),sum**3)) )
+                        calculations += '\nFraction of accepted B**: %.4f +- %.6f' % ( old_div(result['I48'],sum), math.sqrt(old_div(result['I48']*(sum - result['I48']),sum**3)) )
                     else:
                         calculations += '\nFraction of accepted B: 0 +- 0'
                         calculations += '\nFraction of accepted B*: 0 +- 0'
@@ -135,9 +141,9 @@ def operations(result):
             if 'I49' in result and 'I50' in result and 'I51' in result:
                 sum = result['I49']+result['I50']+result['I51']
                 if sum != 0:
-                    calculations += '\nFraction of generated D: %.4f +- %.6f' % ( result['I49']/sum, math.sqrt(result['I49']*(sum - result['I49'])/sum**3) )
-                    calculations += '\nFraction of generated D*: %.4f +- %.6f' % ( result['I50']/sum, math.sqrt(result['I50']*(sum - result['I50'])/sum**3) )
-                    calculations += '\nFraction of generated D**: %.4f +- %.6f' % ( result['I51']/sum, math.sqrt(result['I51']*(sum - result['I51'])/sum**3) )
+                    calculations += '\nFraction of generated D: %.4f +- %.6f' % ( old_div(result['I49'],sum), math.sqrt(old_div(result['I49']*(sum - result['I49']),sum**3)) )
+                    calculations += '\nFraction of generated D*: %.4f +- %.6f' % ( old_div(result['I50'],sum), math.sqrt(old_div(result['I50']*(sum - result['I50']),sum**3)) )
+                    calculations += '\nFraction of generated D**: %.4f +- %.6f' % ( old_div(result['I51'],sum), math.sqrt(old_div(result['I51']*(sum - result['I51']),sum**3)) )
                 else:
                     calculations += '\nFraction of generated D: 0 +- 0'
                     calculations += '\nFraction of generated D*: 0 +- 0'
@@ -146,9 +152,9 @@ def operations(result):
             if 'I52' in result and 'I53' in result and 'I54' in result:
                 sum = result['I52']+result['I53']+result['I54']
                 if sum != 0:
-                    calculations += '\nFraction of accepted D: %.4f +- %.6f' % ( result['I52']/sum, math.sqrt(result['I52']*(sum - result['I52'])/sum**3) )
-                    calculations += '\nFraction of accepted D*: %.4f +- %.6f' % ( result['I53']/sum, math.sqrt(result['I53']*(sum - result['I53'])/sum**3) )
-                    calculations += '\nFraction of accepted D**: %.4f +- %.6f' % ( result['I54']/sum, math.sqrt(result['I54']*(sum - result['I54'])/sum**3) )
+                    calculations += '\nFraction of accepted D: %.4f +- %.6f' % ( old_div(result['I52'],sum), math.sqrt(old_div(result['I52']*(sum - result['I52']),sum**3)) )
+                    calculations += '\nFraction of accepted D*: %.4f +- %.6f' % ( old_div(result['I53'],sum), math.sqrt(old_div(result['I53']*(sum - result['I53']),sum**3)) )
+                    calculations += '\nFraction of accepted D**: %.4f +- %.6f' % ( old_div(result['I54'],sum), math.sqrt(old_div(result['I54']*(sum - result['I54']),sum**3)) )
                 else:
                     calculations += '\nFraction of accepted D: 0 +- 0'
                     calculations += '\nFraction of accepted D*: 0 +- 0'
@@ -157,10 +163,10 @@ def operations(result):
             #  Computation of signal level cut efficiencies
 
             if 'S1' in result and 'S2' in result:
-                calculations += '\nparticle cut efficiency: %.4f +- %.6f\n' % ( result['S2']/result['S1'], math.sqrt(result['S2']*(result['S1']-result['S2'])/result['S1']**3) )
+                calculations += '\nparticle cut efficiency: %.4f +- %.6f\n' % ( old_div(result['S2'],result['S1']), math.sqrt(old_div(result['S2']*(result['S1']-result['S2']),result['S1']**3)) )
 
             if 'S3' in result and 'S4' in result:
-                calculations += '\nanti-particle cut efficiency: %.4f +- %.6f\n' % ( result['S4']/result['S3'], math.sqrt(result['S4']*(result['S3']-result['S4'])/result['S3']**3) )
+                calculations += '\nanti-particle cut efficiency: %.4f +- %.6f\n' % ( old_div(result['S4'],result['S3']), math.sqrt(old_div(result['S4']*(result['S3']-result['S4']),result['S3']**3)) )
                 
                 
     return calculations
@@ -446,7 +452,7 @@ def search_lines(info):
     S1 = float(string.strip(info[test:test+80].split(':')[1].split(',')[0]))
   # after
     S2 = float(string.strip(info[test:test+90].split(':')[2].split()[0]))
-    if gaussversion == 'v25r8': S2 = S2/2
+    if gaussversion == 'v25r8': S2 = old_div(S2,2)
     result['S1'] = S1
     result['S2'] = S2
   test = info.find('Number of events for generator anti-particle level cut')
@@ -455,7 +461,7 @@ def search_lines(info):
     S3 = float(string.strip(info[test:test+80].split(':')[1].split(',')[0]))
   # after
     S4 = float(string.strip(info[test:test+90].split(':')[2].split()[0]))
-    if gaussversion == 'v25r8': S4 = S4/2
+    if gaussversion == 'v25r8': S4 = old_div(S4,2)
     result['S3'] = S3
     result['S4'] = S4
   if 'N2' in result and 'C1' in result:
@@ -601,7 +607,7 @@ def gen_store_results(jobgen):
   table += table1 + table2 + table3 + '</table>\n'
 
 
-  web_comments = Warning + '<p>Number of accepted events/generated events: %i / %i = %f<br>Number of interactions in accepted events/generated interactions: %i / %i = %f' % ( result['N3'], result['N1'], result['N3']/result['N1'], result['N4'], result['N2'], result['N4']/result['N2'] )
+  web_comments = Warning + '<p>Number of accepted events/generated events: %i / %i = %f<br>Number of interactions in accepted events/generated interactions: %i / %i = %f' % ( result['N3'], result['N1'], old_div(result['N3'],result['N1']), result['N4'], result['N2'], old_div(result['N4'],result['N2']) )
 
 #  web_comments += '<p>Statistics done (script version %s) with %i jobs from the following ProdIDs: </p>\n<p>' %(script_version,jobgen)
   if 'L0' in result:
@@ -691,14 +697,14 @@ def sim_store_results(jobsim, gevents, averageResults, veloResults, richResults,
       tr21 += '<td></td>\n'
       tr31 += '<td></td>\n'
       tr11 += '<td><div class=firstcell>MCParticles</div></td>\n'
-      tr21 += '<td>%.4f</td>\n' % (float(averageResults['MCParticles']/count))
+      tr21 += '<td>%.4f</td>\n' % (float(old_div(averageResults['MCParticles'],count)))
       tr31 += '<td>&plusmn; %.4f</td>\n' % (math.sqrt(float(averageResults['MCPError'])/count))
       tr11 += '<td><div class=firstcell>MCHits</div></td>\n'
       tr21 += '<td></td>\n'
       tr31 += '<td></td>\n'
       for type in ('TT', 'IT', 'OT', 'Spd', 'Prs', 'Ecal', 'Hcal'):
           tr11 += '<td><center><div class=firstcell>%s</div></center></td>\n' % (type)
-          tr21 += '<td>%.4f</td>\n' % (float(averageResults[type]/count))
+          tr21 += '<td>%.4f</td>\n' % (float(old_div(averageResults[type],count)))
           tr31 += '<td>&plusmn; %.4f</td>\n' % (math.sqrt(float(averageResults[type+'Error'])/count))
       tr11 += '</tr>\n'
       tr21 += '</tr>\n'
@@ -743,7 +749,7 @@ def sim_store_results(jobsim, gevents, averageResults, veloResults, richResults,
   # Summary table for the Velo
   if veloResults != {}:
       web += '<table border=1>\n<th colspan=3><div class=firstcell>Velo Monitoring Table:</div></th>\n'
-      web += '<tr>\n<td>Number of MCHits/Event</td>\n<td>%.4f</td>\n<td>&plusmn; %.4f</td>\n</tr>\n' % ( float(veloResults['MCHits'])/count, math.sqrt(veloResults['MCHitsError']/count))
+      web += '<tr>\n<td>Number of MCHits/Event</td>\n<td>%.4f</td>\n<td>&plusmn; %.4f</td>\n</tr>\n' % ( float(veloResults['MCHits'])/count, math.sqrt(old_div(veloResults['MCHitsError'],count)))
       web += '<tr>\n<td>Number of PileUpMCHits</td>\n<td>%.4f</td>\n<td>&plusmn; %.4f</td>\n</tr>\n' % ( float(veloResults['PileUpMCHits'])/count, math.sqrt(float(veloResults['PileUpMCHitsError'])/count))
       web += '</table>\n'
   else:
@@ -759,13 +765,13 @@ def sim_store_results(jobsim, gevents, averageResults, veloResults, richResults,
       for index in range(4):
           web += '<tr>\n'
           for index2 in range(5):
-              web += '<td>%.4f</td>\n' % ( ( float(muonResults[index2][index]) )/count )
+              web += '<td>%.4f</td>\n' % ( old_div(( float(muonResults[index2][index]) ),count) )
           web += '<td>%s</td>\n' % muonResults[5][index]
           web += '</tr>\n'
       web += '<tr>\n<td colspan=6>Integrated over regions</td>\n</tr>\n'
       web += '<tr>\n'
       for index in range(5):
-          web += '<td>%.3f</td>\n' % ( ( float(muonResults[index][4]) )/count )
+          web += '<td>%.3f</td>\n' % ( old_div(( float(muonResults[index][4]) ),count) )
       web += '<td>'+str(muonResults[5][4])+'</td>\n'
       web += '</tr>\n'
       web += '</table>\n'
@@ -779,7 +785,7 @@ def sim_store_results(jobsim, gevents, averageResults, veloResults, richResults,
   # Number Of Events written
   if gevents != {}:
       if 'N1' in gevents:
-          web += '<p>Event written / requested: %i / %i = %s </p>\n' % ( int(gevents['N2']), int(gevents['N1']), str(gevents['N2']/gevents['N1']) )
+          web += '<p>Event written / requested: %i / %i = %s </p>\n' % ( int(gevents['N2']), int(gevents['N1']), str(old_div(gevents['N2'],gevents['N1'])) )
   else:
       web += '<p><font color="#FF0000">Warning: Impossible to find the Events counters</font></p>'
                                                                                                                              
@@ -1120,7 +1126,7 @@ def Generators(info):
   grAux = search_lines(info)
 
   if generationResults == {}:
-      for index in grAux.keys():
+      for index in list(grAux.keys()):
           generationResults[index] = grAux[index]
               
 #MY_DEBYG: next line added
@@ -1128,10 +1134,10 @@ def Generators(info):
   else:
       if grAux != None:
           # if some counters are missing the values are not counted
-          if len(grAux.keys()) >= len(generationResults.keys()):
+          if len(list(grAux.keys())) >= len(list(generationResults.keys())):
               aux = generationResults
 #              Generationresults = {}
-              for index in grAux.keys():
+              for index in list(grAux.keys()):
 #                  if index == 'DecFiles' or index == 'ParamFiles':
                   if index == 'DecFiles' or index == 'ParamFiles' or  index == 'L0':
                       if aux[index] != grAux[index]:
@@ -1205,14 +1211,14 @@ def SummaryTable(Data,Results):
 
    # Summary
   if Results == {}:
-      for index in Data.keys():
+      for index in list(Data.keys()):
           Results[index] = Data[index]
       valid = 1
   else:
-      if len(Data.keys()) >= len(Results.keys()):
+      if len(list(Data.keys())) >= len(list(Results.keys())):
           aux = Results
           Results = {}
-          for index in Data.keys():
+          for index in list(Data.keys()):
               Results[index] = Data[index] + aux[index]
           valid = 1
 
@@ -1225,7 +1231,7 @@ def SummaryTable(Data,Results):
 # Retrieve info from the .txt.gz or .log.bz2 logfile.
 # ========================================================================
 def take_info(file):
-    import urllib, tempfile, os, gzip, bz2
+    import urllib.request, urllib.parse, urllib.error, tempfile, os, gzip, bz2
     
     print(file)
     log_file = ''
@@ -1233,7 +1239,7 @@ def take_info(file):
     tmpfile = tempfile.mktemp()
     
     try:
-      urllib.urlretrieve(file,tmpfile)
+      urllib.request.urlretrieve(file,tmpfile)
     except IOError:
       print("Error: \tThe url %s is not available or doesn't exist.\n" % file)
       exit()
@@ -1330,7 +1336,7 @@ def addToIndex(file):
 #################################################################
 def getHTML(url):
         print(">>> URL -> ", url)
-        usock = urllib.urlopen(url)
+        usock = urllib.request.urlopen(url)
         htmlSource = usock.read()
         usock.close()
         return htmlSource
@@ -1341,7 +1347,7 @@ def getHTMLlines(url):
 # --- get url content (line by line) ---
 
 #  print ">>> URL -> ", url
-  usock = urllib.urlopen(url)
+  usock = urllib.request.urlopen(url)
   htmlSource = usock.readlines()
   usock.close()
   return htmlSource
@@ -1390,7 +1396,7 @@ def usage():
 # Main
 # ========================================================================
 if __name__ == "__main__":
-    import urllib, gzip, string, sys, math, time, getopt, tempfile, os, shutil
+    import urllib.request, urllib.parse, urllib.error, gzip, string, sys, math, time, getopt, tempfile, os, shutil
 
     global eventtype, gaussversion, execution, debug_flag, publish
     global url
-- 
GitLab


From d37b1446ae13fe7da276b70c292497f44a84df73 Mon Sep 17 00:00:00 2001
From: Michal Mazurek <michal.mazurek@cern.ch>
Date: Mon, 10 May 2021 15:38:07 +0200
Subject: [PATCH 88/90] Make GaussTracker.shortened_sensdet_name compatible
 with python3

---
 .../tests/qmtest/gausstracker.qms/shortened_sensdet_name.qmt    | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Sim/GaussTracker/tests/qmtest/gausstracker.qms/shortened_sensdet_name.qmt b/Sim/GaussTracker/tests/qmtest/gausstracker.qms/shortened_sensdet_name.qmt
index 40f748ed2..b456b1506 100644
--- a/Sim/GaussTracker/tests/qmtest/gausstracker.qms/shortened_sensdet_name.qmt
+++ b/Sim/GaussTracker/tests/qmtest/gausstracker.qms/shortened_sensdet_name.qmt
@@ -11,7 +11,7 @@
 name = &quot;GiGaMT.GiGaMTDetectorConstructionFAC.Hello&quot;
 search = &quot;Sens det shortened name {} -&gt; {}&quot;
 
-print stdout
+print(stdout)
 if stdout.find(search.format(name, name.split(&quot;.&quot;)[-1])) == -1:
     causes.append(&quot;Name not correctly shortened&quot;)  
 </text></argument>
-- 
GitLab


From a68b603a071ad34e3639a87a2eb51a42fcf66358 Mon Sep 17 00:00:00 2001
From: Michal Mazurek <michal.mazurek@cern.ch>
Date: Mon, 24 May 2021 18:13:26 +0200
Subject: [PATCH 89/90] Fix missing libgit2

---
 toolchain.cmake | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/toolchain.cmake b/toolchain.cmake
index f64c88ab2..484b1902a 100644
--- a/toolchain.cmake
+++ b/toolchain.cmake
@@ -45,6 +45,6 @@ if(NOT CMAKE_SOURCE_DIR MATCHES "CMakeTmp")
     # - Gaudi (we do not want to use it from LCG)
     # - Geant4 (we do not want to use it from LCG)
     # - xenv (conflicts with the version in the build environment)
-    list(FILTER CMAKE_PREFIX_PATH EXCLUDE REGEX "(LCG_|lcg/nightlies).*(ninja|Gaudi|Geant4|xenv|git)")
+    list(FILTER CMAKE_PREFIX_PATH EXCLUDE REGEX "(LCG_|lcg/nightlies).*(ninja|Gaudi|Geant4|xenv|git)/")
   endif()
 endif()
-- 
GitLab


From c029ff6d2a5a9d41ab1d053b74acd4dd4fd62959 Mon Sep 17 00:00:00 2001
From: Sajan Easo <Sajan.Easo@cern.ch>
Date: Sun, 20 Feb 2022 14:38:53 +0100
Subject: [PATCH 90/90] First Version of RICH simulation with GaussPhotonics

---
 CMakeLists.txt                                |    1 +
 .../options/ParticleGunRich12FullMuon.py      |   85 +
 Gen/LbPGuns/options/ParticleGunRich1Muon.py   |   83 +
 .../options/ParticleGunRich2FullMuon.py       |   85 +
 Gen/LbPGuns/options/ParticleGunRich2Muon.py   |   83 +
 Sim/Gauss/python/Gauss/Configuration.py       |   35 +-
 Sim/Gauss/python/Gauss/Geometry/RICH.py       |   64 +
 Sim/Gauss/python/Gauss/Geometry/xml_writer.py |    5 +
 Sim/Gauss/python/Gauss/Physics.py             |   21 +-
 Sim/GaussPhotonics/CMakeLists.txt             |   42 +
 .../GaussCkvOpticalPhysicsList.h              |   62 +
 .../GaussPhotonics/GaussCkvPhysics.h          |   24 +
 .../GaussPhotonics/RhCkvG4Cerenkov.h          |  243 +++
 .../GaussPhotonics/RhCkvG4OpBoundaryProcess.h |  391 ++++
 .../GaussPhotonics/RichCkvCommonSensDet.h     |   68 +
 .../GaussPhotonics/RichCkvG4Hit.h             |  136 ++
 .../GaussPhotonics/RichCkvG4HitCollName.h     |  123 ++
 .../GaussPhotonics/RichCkvG4SvcLocator.h      |   43 +
 .../GaussPhotonics/RichCkvGrandSensDet.h      |   82 +
 .../GaussPhotonics/RichCkvStdSensDet.h        |   83 +
 .../RichG4PhotonicsCkvProdTag.h               |   11 +
 .../GaussPhotonics/RichG4PhotonicsGeomProp.h  |   59 +
 .../RichMapmtPhotoElectricProc-test-h         |   53 +
 .../GaussPhotonics/RichPDProperties.h         |   51 +
 .../GaussPhotonics/RichPmtQuantEff.h          |   36 +
 .../python/GaussPhotonics/Configuration.py    |  111 +
 .../PhotonicsG4EventAction.cpp                |   88 +
 .../PhotonicsAction/PhotonicsG4EventAction.h  |   76 +
 .../PhotonicsG4HitHistoSet5.cpp               |  245 +++
 .../PhotonicsG4HitHistoSet5.h                 |   80 +
 .../PhotonicsAnalysis/PhotonicsG4HitRecon.cpp |   27 +
 .../PhotonicsAnalysis/PhotonicsG4HitRecon.h   |   36 +
 .../PhotonicsStepAnalysis10.cpp               |  119 ++
 .../PhotonicsStepAnalysis10.h                 |   81 +
 .../PhotonicsMisc/RichCkvG4HitCollName.cpp    |   42 +
 .../src/PhotonicsMisc/RichCkvG4SvcLocator.cpp |  152 ++
 .../RichG4PhotonicsCkvProdTag.cpp             |   24 +
 .../RichMapmtPhotoElectricProc-test-cpp       |   34 +
 .../PhotonicsPhysPDet/RichPDProperties.cpp    |   83 +
 .../src/PhotonicsPhysPDet/RichPmtQuantEff.cpp |   46 +
 .../GaussCkvOpticalPhysicsList.cpp            |  156 ++
 .../PhotonicsSensDet/RhCkvGrandSensDet.cpp    |  116 ++
 .../PhotonicsSensDet/RichCkvCommonSensDet.cpp |  164 ++
 .../src/PhotonicsSensDet/RichCkvG4Hit.cpp     |   90 +
 .../RichCkvGrandSensDetFAC.cpp                |   19 +
 .../PhotonicsSensDet/RichCkvStdSensDet.cpp    |  120 ++
 .../PhotonicsSensDet/RichCkvStdSensDetFAC.cpp |   19 +
 .../RichG4PhotonicsGeomProp.cpp               |   46 +
 .../src/srcG4Photonics/RhCkvG4Cerenkov.cpp    |  794 +++++++
 .../RhCkvG4OpBoundaryProcess.cpp              | 1819 +++++++++++++++++
 50 files changed, 6547 insertions(+), 9 deletions(-)
 create mode 100755 Gen/LbPGuns/options/ParticleGunRich12FullMuon.py
 create mode 100755 Gen/LbPGuns/options/ParticleGunRich1Muon.py
 create mode 100755 Gen/LbPGuns/options/ParticleGunRich2FullMuon.py
 create mode 100755 Gen/LbPGuns/options/ParticleGunRich2Muon.py
 create mode 100644 Sim/GaussPhotonics/CMakeLists.txt
 create mode 100644 Sim/GaussPhotonics/GaussPhotonics/GaussCkvOpticalPhysicsList.h
 create mode 100644 Sim/GaussPhotonics/GaussPhotonics/GaussCkvPhysics.h
 create mode 100644 Sim/GaussPhotonics/GaussPhotonics/RhCkvG4Cerenkov.h
 create mode 100644 Sim/GaussPhotonics/GaussPhotonics/RhCkvG4OpBoundaryProcess.h
 create mode 100644 Sim/GaussPhotonics/GaussPhotonics/RichCkvCommonSensDet.h
 create mode 100644 Sim/GaussPhotonics/GaussPhotonics/RichCkvG4Hit.h
 create mode 100644 Sim/GaussPhotonics/GaussPhotonics/RichCkvG4HitCollName.h
 create mode 100755 Sim/GaussPhotonics/GaussPhotonics/RichCkvG4SvcLocator.h
 create mode 100644 Sim/GaussPhotonics/GaussPhotonics/RichCkvGrandSensDet.h
 create mode 100644 Sim/GaussPhotonics/GaussPhotonics/RichCkvStdSensDet.h
 create mode 100644 Sim/GaussPhotonics/GaussPhotonics/RichG4PhotonicsCkvProdTag.h
 create mode 100644 Sim/GaussPhotonics/GaussPhotonics/RichG4PhotonicsGeomProp.h
 create mode 100644 Sim/GaussPhotonics/GaussPhotonics/RichMapmtPhotoElectricProc-test-h
 create mode 100644 Sim/GaussPhotonics/GaussPhotonics/RichPDProperties.h
 create mode 100644 Sim/GaussPhotonics/GaussPhotonics/RichPmtQuantEff.h
 create mode 100644 Sim/GaussPhotonics/python/GaussPhotonics/Configuration.py
 create mode 100644 Sim/GaussPhotonics/src/PhotonicsAction/PhotonicsG4EventAction.cpp
 create mode 100644 Sim/GaussPhotonics/src/PhotonicsAction/PhotonicsG4EventAction.h
 create mode 100644 Sim/GaussPhotonics/src/PhotonicsAnalysis/PhotonicsG4HitHistoSet5.cpp
 create mode 100644 Sim/GaussPhotonics/src/PhotonicsAnalysis/PhotonicsG4HitHistoSet5.h
 create mode 100644 Sim/GaussPhotonics/src/PhotonicsAnalysis/PhotonicsG4HitRecon.cpp
 create mode 100644 Sim/GaussPhotonics/src/PhotonicsAnalysis/PhotonicsG4HitRecon.h
 create mode 100644 Sim/GaussPhotonics/src/PhotonicsAnalysis/PhotonicsStepAnalysis10.cpp
 create mode 100644 Sim/GaussPhotonics/src/PhotonicsAnalysis/PhotonicsStepAnalysis10.h
 create mode 100644 Sim/GaussPhotonics/src/PhotonicsMisc/RichCkvG4HitCollName.cpp
 create mode 100755 Sim/GaussPhotonics/src/PhotonicsMisc/RichCkvG4SvcLocator.cpp
 create mode 100644 Sim/GaussPhotonics/src/PhotonicsMisc/RichG4PhotonicsCkvProdTag.cpp
 create mode 100644 Sim/GaussPhotonics/src/PhotonicsPhysPDet/RichMapmtPhotoElectricProc-test-cpp
 create mode 100644 Sim/GaussPhotonics/src/PhotonicsPhysPDet/RichPDProperties.cpp
 create mode 100644 Sim/GaussPhotonics/src/PhotonicsPhysPDet/RichPmtQuantEff.cpp
 create mode 100644 Sim/GaussPhotonics/src/PhotonicsPhysProcess/GaussCkvOpticalPhysicsList.cpp
 create mode 100644 Sim/GaussPhotonics/src/PhotonicsSensDet/RhCkvGrandSensDet.cpp
 create mode 100644 Sim/GaussPhotonics/src/PhotonicsSensDet/RichCkvCommonSensDet.cpp
 create mode 100644 Sim/GaussPhotonics/src/PhotonicsSensDet/RichCkvG4Hit.cpp
 create mode 100644 Sim/GaussPhotonics/src/PhotonicsSensDet/RichCkvGrandSensDetFAC.cpp
 create mode 100644 Sim/GaussPhotonics/src/PhotonicsSensDet/RichCkvStdSensDet.cpp
 create mode 100644 Sim/GaussPhotonics/src/PhotonicsSensDet/RichCkvStdSensDetFAC.cpp
 create mode 100644 Sim/GaussPhotonics/src/PhotonicsSensDet/RichG4PhotonicsGeomProp.cpp
 create mode 100644 Sim/GaussPhotonics/src/srcG4Photonics/RhCkvG4Cerenkov.cpp
 create mode 100644 Sim/GaussPhotonics/src/srcG4Photonics/RhCkvG4OpBoundaryProcess.cpp

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 4252be5f8..d3693820c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -57,6 +57,7 @@ list(APPEND CMAKE_PREFIX_PATH /usr)
 gaudi_project(Gauss v60r0
               FORTRAN
               USE Gaussino v1r0
+              USE Detector v1r0
               DATA AppConfig VERSION v3r*
                    BcVegPyData VERSION v3r*
                    Det/GDMLData VERSION v1r*
diff --git a/Gen/LbPGuns/options/ParticleGunRich12FullMuon.py b/Gen/LbPGuns/options/ParticleGunRich12FullMuon.py
new file mode 100755
index 000000000..cefe32b8b
--- /dev/null
+++ b/Gen/LbPGuns/options/ParticleGunRich12FullMuon.py
@@ -0,0 +1,85 @@
+##############################################################################
+# Example options to generate particle guns with flat random distribution in
+# momentum, theta and phi originating from a flat vertx distribution.
+##############################################################################
+#
+#  This example will generate one pi+ or pi- per event originating at
+#  (0,0,0) in the LHCb reference system, with 1 GeV < abs(P) < 100 GeV,
+#  0.15 mrad < theta < 0.300 mrad and 0 < phi < 2pi
+#    
+#  Include this file instead of the EVENTTYPE.opts after all you other 
+#  options.
+#
+#  @author : G.Corti
+#  @date   : last modified on 2009-11-04
+##############################################################################
+ 
+from Gaudi.Configuration import *
+from Configurables import ParticleGun
+from GaudiKernel.SystemOfUnits import *
+
+# Set up ParticleGun
+ParticleGun = ParticleGun("ParticleGun")
+
+# Control of the ParticleGun
+# Event type is set as described in LHCb-2005-034 : G=5! (Def = 0)
+ParticleGun.EventType = 53210205;
+
+# GunMode flag:
+#   if = MomentumRange uses parameters below within random values generated
+#   if = FixedMomentum need to set fix values of px, py, pz via specific properties
+from Configurables import MomentumRange
+ParticleGun.addTool(MomentumRange, name="MomentumRange")
+ParticleGun.ParticleGunTool = "MomentumRange"
+
+#from Configurables import FixedMomentum
+#ParticleGun.addTool(FixedMomentum, name="FixedMomentum")
+#ParticleGun.ParticleGunTool = "FixedMomentum"
+
+# Set min and max number of particles to produce in an event
+# defaults are = 1, i.e. always one particle
+from Configurables import FlatNParticles
+ParticleGun.addTool(FlatNParticles, name="FlatNParticles")
+ParticleGun.NumberOfParticlesTool = "FlatNParticles"
+#ParticleGun.FlatNParticles.MinNParticles = 1
+#ParticleGun.FlatNParticles.MaxNParticles = 1
+
+# PDG code of a list of possible particles to be generated, default = {-211})
+#ParticleGun.MomentumRange.PdgCodes = [-211, 211]
+#ParticleGun.MomentumRange.PdgCodes = [-2212, 2212]
+ParticleGun.MomentumRange.PdgCodes = [-13, 13]
+#ParticleGun.FixedMomentum.PdgCodes = [-211, 211]
+
+# The vertex of each particle gun is randomly generated in a flat
+# distributionwithin the given limits, when min=max the vertex is in the
+# given point. Default is 0.0*mm for all.
+#from Configurables import FlatSmearVertex
+#ParticleGun.addTool(FlatSmearVertex, name="FlatSmearVertex")
+#ParticleGun.VertexSmearingTool = "FlatSmearVertex"
+#ParticleGun.FlatSmearVertex.xVertexMin = 0.0*mm;  
+#ParticleGun.FlatSmearVertex.xVertexMax = 0.0*mm
+#ParticleGun.FlatSmearVertex.yVertexMin = 0.0*mm
+#ParticleGun.FlatSmearVertex.yVertexMax = 0.0*mm
+#ParticleGun.FlatSmearVertex.zVertexMin = 0.0*mm
+#ParticleGun.FlatSmearVertex.zVertexMax = 0.0*mm
+
+# The momentum of the particle is derived from randomly generated value
+# of abs(P) (default for both min and max = 100 GeV), theta (default 
+# min = 0.1*rad and max = 0.4*rad) and phi (default min = 0, max = twopi*rad)
+ParticleGun.MomentumRange.MomentumMin = 80.0*GeV
+ParticleGun.MomentumRange.MomentumMax = 80.0*GeV
+ParticleGun.MomentumRange.ThetaMin    = 0.03*rad #rich1 full acceptance
+ParticleGun.MomentumRange.ThetaMax    = 0.22*rad #rich1 almost full acceptance
+#ParticleGun.MomentumRange.ThetaMin    = 0.09*rad #rich1 good acceptance
+#ParticleGun.MomentumRange.ThetaMax    = 0.18*rad #rich1 good acceptance
+#ParticleGun.MomentumRange.ThetaMin    = 0.04*rad #rich2 good acceptance
+#ParticleGun.MomentumRange.ThetaMax    = 0.09*rad #rich2 good acceptance
+#ParticleGun.MomentumRange.PhiMin     =   0.0*rad
+#ParticleGun.MomentumRange.PhiMax     =  6.28*rad
+
+# When GunMode = FixedMomentum, the specific options for setting px, py and pz are
+# the following with default values listed
+#ParticleGun.FixedMomentum.px = 1.0*GeV
+#ParticleGun.FixedMomentum.py = 1.0*GeV
+#ParticleGun.FixedMomentum.pz = 1.0*GeV
+
diff --git a/Gen/LbPGuns/options/ParticleGunRich1Muon.py b/Gen/LbPGuns/options/ParticleGunRich1Muon.py
new file mode 100755
index 000000000..e8661e628
--- /dev/null
+++ b/Gen/LbPGuns/options/ParticleGunRich1Muon.py
@@ -0,0 +1,83 @@
+##############################################################################
+# Example options to generate particle guns with flat random distribution in
+# momentum, theta and phi originating from a flat vertx distribution.
+##############################################################################
+#
+#  This example will generate one pi+ or pi- per event originating at
+#  (0,0,0) in the LHCb reference system, with 1 GeV < abs(P) < 100 GeV,
+#  0.15 mrad < theta < 0.300 mrad and 0 < phi < 2pi
+#    
+#  Include this file instead of the EVENTTYPE.opts after all you other 
+#  options.
+#
+#  @author : G.Corti
+#  @date   : last modified on 2009-11-04
+##############################################################################
+ 
+from Gaudi.Configuration import *
+from Configurables import ParticleGun
+from GaudiKernel.SystemOfUnits import *
+
+# Set up ParticleGun
+ParticleGun = ParticleGun("ParticleGun")
+
+# Control of the ParticleGun
+# Event type is set as described in LHCb-2005-034 : G=5! (Def = 0)
+ParticleGun.EventType = 53210205;
+
+# GunMode flag:
+#   if = MomentumRange uses parameters below within random values generated
+#   if = FixedMomentum need to set fix values of px, py, pz via specific properties
+from Configurables import MomentumRange
+ParticleGun.addTool(MomentumRange, name="MomentumRange")
+ParticleGun.ParticleGunTool = "MomentumRange"
+
+#from Configurables import FixedMomentum
+#ParticleGun.addTool(FixedMomentum, name="FixedMomentum")
+#ParticleGun.ParticleGunTool = "FixedMomentum"
+
+# Set min and max number of particles to produce in an event
+# defaults are = 1, i.e. always one particle
+from Configurables import FlatNParticles
+ParticleGun.addTool(FlatNParticles, name="FlatNParticles")
+ParticleGun.NumberOfParticlesTool = "FlatNParticles"
+#ParticleGun.FlatNParticles.MinNParticles = 1
+#ParticleGun.FlatNParticles.MaxNParticles = 1
+
+# PDG code of a list of possible particles to be generated, default = {-211})
+#ParticleGun.MomentumRange.PdgCodes = [-211, 211]
+#ParticleGun.MomentumRange.PdgCodes = [-2212, 2212]
+ParticleGun.MomentumRange.PdgCodes = [-13, 13]
+#ParticleGun.FixedMomentum.PdgCodes = [-211, 211]
+
+# The vertex of each particle gun is randomly generated in a flat
+# distributionwithin the given limits, when min=max the vertex is in the
+# given point. Default is 0.0*mm for all.
+#from Configurables import FlatSmearVertex
+#ParticleGun.addTool(FlatSmearVertex, name="FlatSmearVertex")
+#ParticleGun.VertexSmearingTool = "FlatSmearVertex"
+#ParticleGun.FlatSmearVertex.xVertexMin = 0.0*mm;  
+#ParticleGun.FlatSmearVertex.xVertexMax = 0.0*mm
+#ParticleGun.FlatSmearVertex.yVertexMin = 0.0*mm
+#ParticleGun.FlatSmearVertex.yVertexMax = 0.0*mm
+#ParticleGun.FlatSmearVertex.zVertexMin = 0.0*mm
+#ParticleGun.FlatSmearVertex.zVertexMax = 0.0*mm
+
+# The momentum of the particle is derived from randomly generated value
+# of abs(P) (default for both min and max = 100 GeV), theta (default 
+# min = 0.1*rad and max = 0.4*rad) and phi (default min = 0, max = twopi*rad)
+ParticleGun.MomentumRange.MomentumMin = 80.0*GeV
+ParticleGun.MomentumRange.MomentumMax = 80.0*GeV
+ParticleGun.MomentumRange.ThetaMin    = 0.09*rad #rich1 good acceptance
+ParticleGun.MomentumRange.ThetaMax    = 0.18*rad #rich1 good acceptance
+#ParticleGun.MomentumRange.ThetaMin    = 0.04*rad #rich2 good acceptance
+#ParticleGun.MomentumRange.ThetaMax    = 0.09*rad #rich2 good acceptance
+#ParticleGun.MomentumRange.PhiMin     =   0.0*rad
+#ParticleGun.MomentumRange.PhiMax     =  6.28*rad
+
+# When GunMode = FixedMomentum, the specific options for setting px, py and pz are
+# the following with default values listed
+#ParticleGun.FixedMomentum.px = 1.0*GeV
+#ParticleGun.FixedMomentum.py = 1.0*GeV
+#ParticleGun.FixedMomentum.pz = 1.0*GeV
+
diff --git a/Gen/LbPGuns/options/ParticleGunRich2FullMuon.py b/Gen/LbPGuns/options/ParticleGunRich2FullMuon.py
new file mode 100755
index 000000000..555256d99
--- /dev/null
+++ b/Gen/LbPGuns/options/ParticleGunRich2FullMuon.py
@@ -0,0 +1,85 @@
+##############################################################################
+# Example options to generate particle guns with flat random distribution in
+# momentum, theta and phi originating from a flat vertx distribution.
+##############################################################################
+#
+#  This example will generate one pi+ or pi- per event originating at
+#  (0,0,0) in the LHCb reference system, with 1 GeV < abs(P) < 100 GeV,
+#  0.15 mrad < theta < 0.300 mrad and 0 < phi < 2pi
+#    
+#  Include this file instead of the EVENTTYPE.opts after all you other 
+#  options.
+#
+#  @author : G.Corti
+#  @date   : last modified on 2009-11-04
+##############################################################################
+ 
+from Gaudi.Configuration import *
+from Configurables import ParticleGun
+from GaudiKernel.SystemOfUnits import *
+
+# Set up ParticleGun
+ParticleGun = ParticleGun("ParticleGun")
+
+# Control of the ParticleGun
+# Event type is set as described in LHCb-2005-034 : G=5! (Def = 0)
+ParticleGun.EventType = 53210205;
+
+# GunMode flag:
+#   if = MomentumRange uses parameters below within random values generated
+#   if = FixedMomentum need to set fix values of px, py, pz via specific properties
+from Configurables import MomentumRange
+ParticleGun.addTool(MomentumRange, name="MomentumRange")
+ParticleGun.ParticleGunTool = "MomentumRange"
+
+#from Configurables import FixedMomentum
+#ParticleGun.addTool(FixedMomentum, name="FixedMomentum")
+#ParticleGun.ParticleGunTool = "FixedMomentum"
+
+# Set min and max number of particles to produce in an event
+# defaults are = 1, i.e. always one particle
+from Configurables import FlatNParticles
+ParticleGun.addTool(FlatNParticles, name="FlatNParticles")
+ParticleGun.NumberOfParticlesTool = "FlatNParticles"
+#ParticleGun.FlatNParticles.MinNParticles = 1
+#ParticleGun.FlatNParticles.MaxNParticles = 1
+
+# PDG code of a list of possible particles to be generated, default = {-211})
+#ParticleGun.MomentumRange.PdgCodes = [-211, 211]
+#ParticleGun.MomentumRange.PdgCodes = [-2212, 2212]
+ParticleGun.MomentumRange.PdgCodes = [-13, 13]
+#ParticleGun.FixedMomentum.PdgCodes = [-211, 211]
+
+# The vertex of each particle gun is randomly generated in a flat
+# distributionwithin the given limits, when min=max the vertex is in the
+# given point. Default is 0.0*mm for all.
+#from Configurables import FlatSmearVertex
+#ParticleGun.addTool(FlatSmearVertex, name="FlatSmearVertex")
+#ParticleGun.VertexSmearingTool = "FlatSmearVertex"
+#ParticleGun.FlatSmearVertex.xVertexMin = 0.0*mm;  
+#ParticleGun.FlatSmearVertex.xVertexMax = 0.0*mm
+#ParticleGun.FlatSmearVertex.yVertexMin = 0.0*mm
+#ParticleGun.FlatSmearVertex.yVertexMax = 0.0*mm
+#ParticleGun.FlatSmearVertex.zVertexMin = 0.0*mm
+#ParticleGun.FlatSmearVertex.zVertexMax = 0.0*mm
+
+# The momentum of the particle is derived from randomly generated value
+# of abs(P) (default for both min and max = 100 GeV), theta (default 
+# min = 0.1*rad and max = 0.4*rad) and phi (default min = 0, max = twopi*rad)
+ParticleGun.MomentumRange.MomentumMin = 80.0*GeV
+ParticleGun.MomentumRange.MomentumMax = 80.0*GeV
+#ParticleGun.MomentumRange.ThetaMin    = 0.09*rad #rich1 good acceptance
+#ParticleGun.MomentumRange.ThetaMax    = 0.18*rad #rich1 good acceptance
+#ParticleGun.MomentumRange.ThetaMin    = 0.04*rad #rich2 good acceptance
+#ParticleGun.MomentumRange.ThetaMax    = 0.09*rad #rich2 good acceptance
+ParticleGun.MomentumRange.ThetaMin    = 0.02*rad #rich2 full acceptance
+ParticleGun.MomentumRange.ThetaMax    = 0.10*rad #rich2 full acceptance
+#ParticleGun.MomentumRange.PhiMin     =   0.0*rad
+#ParticleGun.MomentumRange.PhiMax     =  6.28*rad
+
+# When GunMode = FixedMomentum, the specific options for setting px, py and pz are
+# the following with default values listed
+#ParticleGun.FixedMomentum.px = 1.0*GeV
+#ParticleGun.FixedMomentum.py = 1.0*GeV
+#ParticleGun.FixedMomentum.pz = 1.0*GeV
+
diff --git a/Gen/LbPGuns/options/ParticleGunRich2Muon.py b/Gen/LbPGuns/options/ParticleGunRich2Muon.py
new file mode 100755
index 000000000..a99586522
--- /dev/null
+++ b/Gen/LbPGuns/options/ParticleGunRich2Muon.py
@@ -0,0 +1,83 @@
+##############################################################################
+# Example options to generate particle guns with flat random distribution in
+# momentum, theta and phi originating from a flat vertx distribution.
+##############################################################################
+#
+#  This example will generate one pi+ or pi- per event originating at
+#  (0,0,0) in the LHCb reference system, with 1 GeV < abs(P) < 100 GeV,
+#  0.15 mrad < theta < 0.300 mrad and 0 < phi < 2pi
+#    
+#  Include this file instead of the EVENTTYPE.opts after all you other 
+#  options.
+#
+#  @author : G.Corti
+#  @date   : last modified on 2009-11-04
+##############################################################################
+ 
+from Gaudi.Configuration import *
+from Configurables import ParticleGun
+from GaudiKernel.SystemOfUnits import *
+
+# Set up ParticleGun
+ParticleGun = ParticleGun("ParticleGun")
+
+# Control of the ParticleGun
+# Event type is set as described in LHCb-2005-034 : G=5! (Def = 0)
+ParticleGun.EventType = 53210205;
+
+# GunMode flag:
+#   if = MomentumRange uses parameters below within random values generated
+#   if = FixedMomentum need to set fix values of px, py, pz via specific properties
+from Configurables import MomentumRange
+ParticleGun.addTool(MomentumRange, name="MomentumRange")
+ParticleGun.ParticleGunTool = "MomentumRange"
+
+#from Configurables import FixedMomentum
+#ParticleGun.addTool(FixedMomentum, name="FixedMomentum")
+#ParticleGun.ParticleGunTool = "FixedMomentum"
+
+# Set min and max number of particles to produce in an event
+# defaults are = 1, i.e. always one particle
+from Configurables import FlatNParticles
+ParticleGun.addTool(FlatNParticles, name="FlatNParticles")
+ParticleGun.NumberOfParticlesTool = "FlatNParticles"
+#ParticleGun.FlatNParticles.MinNParticles = 1
+#ParticleGun.FlatNParticles.MaxNParticles = 1
+
+# PDG code of a list of possible particles to be generated, default = {-211})
+#ParticleGun.MomentumRange.PdgCodes = [-211, 211]
+#ParticleGun.MomentumRange.PdgCodes = [-2212, 2212]
+ParticleGun.MomentumRange.PdgCodes = [-13, 13]
+#ParticleGun.FixedMomentum.PdgCodes = [-211, 211]
+
+# The vertex of each particle gun is randomly generated in a flat
+# distributionwithin the given limits, when min=max the vertex is in the
+# given point. Default is 0.0*mm for all.
+#from Configurables import FlatSmearVertex
+#ParticleGun.addTool(FlatSmearVertex, name="FlatSmearVertex")
+#ParticleGun.VertexSmearingTool = "FlatSmearVertex"
+#ParticleGun.FlatSmearVertex.xVertexMin = 0.0*mm;  
+#ParticleGun.FlatSmearVertex.xVertexMax = 0.0*mm
+#ParticleGun.FlatSmearVertex.yVertexMin = 0.0*mm
+#ParticleGun.FlatSmearVertex.yVertexMax = 0.0*mm
+#ParticleGun.FlatSmearVertex.zVertexMin = 0.0*mm
+#ParticleGun.FlatSmearVertex.zVertexMax = 0.0*mm
+
+# The momentum of the particle is derived from randomly generated value
+# of abs(P) (default for both min and max = 100 GeV), theta (default 
+# min = 0.1*rad and max = 0.4*rad) and phi (default min = 0, max = twopi*rad)
+ParticleGun.MomentumRange.MomentumMin = 80.0*GeV
+ParticleGun.MomentumRange.MomentumMax = 80.0*GeV
+#ParticleGun.MomentumRange.ThetaMin    = 0.09*rad #rich1 good acceptance
+#ParticleGun.MomentumRange.ThetaMax    = 0.18*rad #rich1 good acceptance
+ParticleGun.MomentumRange.ThetaMin    = 0.04*rad #rich2 good acceptance
+ParticleGun.MomentumRange.ThetaMax    = 0.09*rad #rich2 good acceptance
+#ParticleGun.MomentumRange.PhiMin     =   0.0*rad
+#ParticleGun.MomentumRange.PhiMax     =  6.28*rad
+
+# When GunMode = FixedMomentum, the specific options for setting px, py and pz are
+# the following with default values listed
+#ParticleGun.FixedMomentum.px = 1.0*GeV
+#ParticleGun.FixedMomentum.py = 1.0*GeV
+#ParticleGun.FixedMomentum.pz = 1.0*GeV
+
diff --git a/Sim/Gauss/python/Gauss/Configuration.py b/Sim/Gauss/python/Gauss/Configuration.py
index 74d137363..ddc33b4c1 100755
--- a/Sim/Gauss/python/Gauss/Configuration.py
+++ b/Sim/Gauss/python/Gauss/Configuration.py
@@ -15,12 +15,14 @@ from Configurables import LHCbConfigurableUser, LHCbApp, SimConf
 from Configurables import Gaussino
 from GaudiKernel import SystemOfUnits
 from Gaussino.Utilities import configure_edm_conversion
-
+# Various options for the RICH
+from Configurables import (GaussPhotonicsConf)
 
 class Gauss(LHCbConfigurableUser):
 
     # Possible used Configurables
     __used_configurables__ = [LHCbApp, SimConf, Gaussino,
+                              (GaussPhotonicsConf,None)  
                               # (GaussRICHConf,None),
                               # (GaussCherenkovConf,None)
                               ]
@@ -129,6 +131,11 @@ class Gauss(LHCbConfigurableUser):
 
         SimConf().SaveHepMC = False
 
+        #add SimConf configuration for pGun settings
+        #if 'PGUN' in self.getProp('Production') and not "GenToMCTree" in Gaussino().getProp('Phases'):
+        #    SimConf().setProp("pGun",True)
+
+
     def defineCrossingList(self):
         crossingList = ['']
         spillOverList = self.getProp("SpilloverPaths")
@@ -243,12 +250,38 @@ class Gauss(LHCbConfigurableUser):
         # Trigger the simulation related configuration if simulation is in
         # phases
         if "Simulation" in Gaussino().getProp("Phases"):
+            #Sanity checks to be added to ensure RichPmt Detector is loaded.
+            richUpgradeConfig = False
+            UpgradeRichPmtDetector=False
+
+
+            if self.getProp("DataType") == "Upgrade" :
+                richUpgradeConfig=True
+            
+            if(richUpgradeConfig):
+                mGaussPhotonicsConf = GaussPhotonicsConf()
+                mGaussPhotonicsConf.InitializeGaussPhotonicsConfiguration()       
+    
             from Gauss import G4Physics
             G4Physics().apply()
             if self.getProp("UseLHCbGeo"):
                 from Gauss.Geometry import LHCbGeo
                 LHCbGeo().setOtherProps(LHCbApp(), ['DetectorGeo'])
                 LHCbGeo().apply()
+             
+            #Configure RICH 
+#            from Configurables import GiGaMT
+#            giga = GiGaMT()
+#            if [det for det in ['Rich1Pmt', 'Rich2Pmt'] if det in self.getProp('DetectorSim')['Detectors']]:
+#               UpgradeRichPmtDetector=True
+
+#            if(richUpgradeConfig):
+#                if(UpgradeRichPmtDetector):
+#                    mGaussPhotonicsConf = GaussPhotonicsConf()
+#                    mGaussPhotonicsConf.InitializeGaussPhotonicsConfiguration()
+#                    mGaussPhotonicsConf.setUpgradeRichDetExistFlag(UpgradeRichPmtDetector)
+#                    mGaussPhotonicsConf.setSkipUpgradeGeant4Flag(skipG4)
+#                    mGaussPhotonicsConf.ApplyGaussPhotonicsConfiguration(giga)
 
         crossingList = self.defineCrossingList()
 
diff --git a/Sim/Gauss/python/Gauss/Geometry/RICH.py b/Sim/Gauss/python/Gauss/Geometry/RICH.py
index 3b602c5ee..aeb05f464 100644
--- a/Sim/Gauss/python/Gauss/Geometry/RICH.py
+++ b/Sim/Gauss/python/Gauss/Geometry/RICH.py
@@ -40,6 +40,41 @@ class RICH1PMT(det_base):
 
     __slots__ = {}
 
+    def ApplyDetectorDD4hep(self, basePieces, detPieces):
+        # Configuring the DD4hep detector conversion.
+        # 1. Add the mapping to have the LHCbDD4hepCnvSvc instrument
+        # the G4 volume with the correct sensdet factory if marked with a
+        # dd4hep sensitive detector named Rich1
+        from Configurables import LHCbDD4hepCnvSvc
+        mappings = LHCbDD4hepCnvSvc().getProp('SensDetMappings')
+        mappings["lvRichPMTPhCathode"] = 'RichCkvStdSensDet/RichSDet'
+        LHCbDD4hepCnvSvc().SensDetMappings = mappings
+
+        # Add the necessary dd4hep includes for the Rich1. 
+        #Also added all the
+        # dependencies for material definitions that were identified using
+        # trial and error. As the list is made unique before being added to
+        # the xml this should be fine if they appear in multiple places
+        from Gauss.Geometry import LHCbGeo
+        go = LHCbGeo._listOfXMLIncludes_
+        go += ["Pipe/parameters.xml"]
+        go += ["PipeGeomParams.xml"]
+        go += ["PipeBeforeMagGeomParams.xml"]
+        go += ["Rich1/DetElem/RichRun3PropertySpecParam.xml"]
+        go += ["Rich1/RichMatDir/RichMaterialTabProperty.xml"]
+        go += ["Rich1/RichMatDir/RichMaterials.xml"]
+        go += ["Rich1/GeomParam/Rich1GeometryParameters.xml"]
+        go += ["Rich1/RichVisDir/Rich1VisAttrDef.xml"]
+        go += ["Rich1/Rich1SurfaceDir/RichSurfaceParam.xml"]
+        go += ["Rich1/Rich1SurfaceDir/Rich1SurfaceTabProperty.xml"]
+        go += ["Rich1/Rich1SurfaceDir/RichPMTSurfaceTabProperty.xml"]
+        go += ["Rich1/Rich1SurfaceDir/Rich1Surfaces.xml"]
+        go += ["Rich1/Rich1SurfaceDir/RichPMTSurfaces.xml"]
+        go += ["Rich1/detector.xml"]
+
+
+
+
     def ApplyDetectorDetDesc(self, basePieces, detPieces):
         BeamPipe.removeBeamPipeElements("rich1")
         detPieces['BeforeMagnetRegion'] += ['Rich1']
@@ -60,6 +95,35 @@ class RICH2PMT(det_base):
 
     __slots__ = {}
 
+    def ApplyDetectorDD4hep(self, basePieces, detPieces):
+
+
+        from Configurables import LHCbDD4hepCnvSvc
+        mappings = LHCbDD4hepCnvSvc().getProp('SensDetMappings')
+        mappings["lvRichPMTPhCathode"] = 'RichCkvStdSensDet/RichStdSDet'
+        mappings["lvRichGrandPMTPhCathode"] = 'RichCkvGrandSensDet/RichGrandSDet'
+        LHCbDD4hepCnvSvc().SensDetMappings = mappings
+
+        from Gauss.Geometry import LHCbGeo
+        go = LHCbGeo._listOfXMLIncludes_
+        go += ["Pipe/parameters.xml"]
+        go += ["PipeGeomParams.xml"]
+        go += ["PipeBeforeMagGeomParams.xml"]
+        go += ["Rich1/DetElem/RichRun3PropertySpecParam.xml"]
+        go += ["Rich1/RichMatDir/RichMaterialTabProperty.xml"]
+        go += ["Rich1/RichMatDir/RichMaterials.xml"]
+        go += ["Rich1/GeomParam/Rich1GeometryParameters.xml"]
+        go += ["Rich2/GeomParam/Rich2GeometryParameters.xml"]
+        go += ["Rich1/RichVisDir/Rich1VisAttrDef.xml"]
+        go += ["Rich1/RichVisDir/Rich2VisAttrDef.xml"]
+        go += ["Rich1/Rich1SurfaceDir/RichSurfaceParam.xml"]
+        go += ["Rich1/Rich1SurfaceDir/RichPMTSurfaceTabProperty.xml"]
+        go += ["Rich2/Rich2SurfaceDir/Rich2SurfaceTabProperty.xml"]
+        go += ["Rich1/Rich1SurfaceDir/RichPMTSurfaces.xml"]
+        go += ["Rich2/Rich2SurfaceDir/Rich2Surfaces.xml"]
+        go += ["Rich2/detector.xml"]
+
+
     def ApplyDetectorDetDesc(self, basePieces, detPieces):
         BeamPipe.removeBeamPipeElements("rich2")
         detPieces['AfterMagnetRegion'] += ['Rich2']
diff --git a/Sim/Gauss/python/Gauss/Geometry/xml_writer.py b/Sim/Gauss/python/Gauss/Geometry/xml_writer.py
index d7a921fed..bf2386518 100644
--- a/Sim/Gauss/python/Gauss/Geometry/xml_writer.py
+++ b/Sim/Gauss/python/Gauss/Geometry/xml_writer.py
@@ -47,7 +47,12 @@ def create_xml(includesfiles):
                   value="/world/BeforeMagnetRegion", type="string")
     ET.SubElement(define, "constant", name="FT:parent",
                   value="/world/AfterMagnetRegion/T", type="string")
+    ET.SubElement(define, "constant", name="Rich1:parent",
+                  value="/world/BeforeMagnetRegion", type="string")
+    ET.SubElement(define, "constant", name="Rich2:parent",
+                  value="/world/AfterMagnetRegion", type="string")
     ET.SubElement(define, "constant", name="Magnet:ignore", value="0")
+    ET.SubElement(define, "constant", name="Magnet:parent", value="/world/MagnetRegion", type="string")
     ET.SubElement(define, "constant", name="UpstreamRegion:ignore", value="0")
     ET.SubElement(define, "constant", name="BeforeMagnetRegion:ignore", value="0")  # NOQA
     ET.SubElement(define, "constant", name="MagnetRegion:ignore", value="0")
diff --git a/Sim/Gauss/python/Gauss/Physics.py b/Sim/Gauss/python/Gauss/Physics.py
index 1f45f3a88..ac27d56f1 100644
--- a/Sim/Gauss/python/Gauss/Physics.py
+++ b/Sim/Gauss/python/Gauss/Physics.py
@@ -19,10 +19,10 @@ class G4Physics(LHCbConfigurableUser):
         "Em": 'NoCuts',
         "Hadron": 'FTFP_BERT',
         "GeneralPhys": True,
-        "LHCbPhys": False,
+        "LHCbPhys": True,
         "Other": '',
         "DeltaRays": True,
-        "RichUpgradeConfig": False,
+        "RichUpgradePhysicsConfig": True,
         "AddPhysConstr": [],
     }
 
@@ -40,7 +40,7 @@ class G4Physics(LHCbConfigurableUser):
                        Choices: [True,False]""",
         'Other': """Anything else. Currently not used ['']""",
         "DeltaRays": """Simulation of delta rays enabled (default True)""",
-        "RichUpgradeConfig": """Use RICH upgrade (default True)"""
+        "RichUpgradePhysicsConfig": """Use RICH upgrade (default True)"""
     }
 
     def __apply_configuration__(self):
@@ -49,6 +49,11 @@ class G4Physics(LHCbConfigurableUser):
     def apply(self):
         from Configurables import GiGaMT
         giga = GiGaMT()
+        from Configurables import (GaussPhotonicsConf)
+        mGaussPhotonicsConf = GaussPhotonicsConf()
+        if(mGaussPhotonicsConf.getProp("ActivateCherenkovProcess") ) :
+            RichUpgradePhysicsConfig = True
+
 
         from Configurables import GiGaMTModularPhysListFAC
         gmpl = giga.addTool(GiGaMTModularPhysListFAC("ModularPL"),
@@ -171,14 +176,14 @@ class G4Physics(LHCbConfigurableUser):
 
     def AddLHCbPhysics(self, pl):
         lhcbPhys = self.getProp('LHCbPhys')
-        richUpgradeConfig = self.getProp('RichUpgradeConfig')
         pl.PhysicsConstructors.append("GiGaPhysUnknownParticles")
         if lhcbPhys:
             log.info("Applying LHCb specific physics.")
-            if richUpgradeConfig:
-                self.defineRichMaPmtPhys(pl)
-            else:
-                self.defineRichPhys(pl)
+            addConstructor(pl,"GaussCkvOpticalPhysicsList", "GaussCkvOpticalPhysicsList")
+            #if richUpgradeConfig:
+            #    self.defineRichMaPmtPhys(pl)
+            #else:
+            #    self.defineRichPhys(pl)
         else:
             log.warning("The lhcb-related physics (RICH processed)"
                         "is disabled")
diff --git a/Sim/GaussPhotonics/CMakeLists.txt b/Sim/GaussPhotonics/CMakeLists.txt
new file mode 100644
index 000000000..d47a85746
--- /dev/null
+++ b/Sim/GaussPhotonics/CMakeLists.txt
@@ -0,0 +1,42 @@
+################################################################################
+# Package: GaussPhotonics
+################################################################################
+gaudi_subdir(GaussPhotonics v1r0)
+
+
+gaudi_depends_on_subdirs(GaudiAlg
+                         Sim/GiGaMTCore
+                         HepMC3
+                         Sim/GiGaMTFactories  )
+
+find_package(AIDA)
+find_package(CLHEP)
+find_package(Boost)
+find_package(ROOT)
+find_package(Vc)
+find_package(Detector)
+AddHepMC3()
+
+
+include_directories(SYSTEM ${CLHEP_INCLUDE_DIRS} ${Boost_INCLUDE_DIR} ${ROOT_INCLUDE_DIRS} ${Geant4_INCLUDE_DIRS} ${Vc_INCLUDE_DIR} ${HEPMC3_INCLUDE_DIR} ${DD4hep_INCLUDE_DIRS})
+
+gaudi_add_module(GaussPhotonics
+                 src/PhotonicsPhysProcess/*.cpp 
+                 src/PhotonicsPhysPDet/*.cpp
+                 src/srcG4Photonics/*.cpp
+                 src/PhotonicsMisc/*.cpp
+                 src/PhotonicsSensDet/*.cpp
+                 src/PhotonicsAnalysis/*.cpp
+                 src/PhotonicsAction/*.cpp
+                 INCLUDE_DIRS AIDA
+                              DD4hep Detector DetectorPlugins 
+                              GiGaMTFactories 
+                              GaudiAlg
+                              src/PhotonicsAnalysis
+                              src/PhotonicsAction
+                              src/PhotonicsMisc     
+                 LINK_LIBRARIES LinkerEvent MCEvent RelationsLib
+                                RichKernelLib Geant4 GiGaMTCoreTruthLib Detector::DetectorLib DD4hep ${DD4hep_COMPONENT_LIBRARIES}
+                 GENCONF_PRELOAD GaussToolsGenConfHelperLib )
+
+gaudi_install_python_modules()
diff --git a/Sim/GaussPhotonics/GaussPhotonics/GaussCkvOpticalPhysicsList.h b/Sim/GaussPhotonics/GaussPhotonics/GaussCkvOpticalPhysicsList.h
new file mode 100644
index 000000000..fa53f6c12
--- /dev/null
+++ b/Sim/GaussPhotonics/GaussPhotonics/GaussCkvOpticalPhysicsList.h
@@ -0,0 +1,62 @@
+/*****************************************************************************\
+* (c) Copyright 2000-2020 CERN for the benefit of the LHCb Collaboration      *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                             *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+// ============================================================================
+#ifndef    GIGAMT_GaussCkvOpticalPhysicsList_H
+#define    GIGAMT_GaussCkvOpticalPhysicsList_H 1
+// ============================================================================
+
+// ============================================================================
+// include files
+
+//GaudiKernel
+
+// G4
+#include "GaudiAlg/GaudiTool.h"
+#include "GaudiKernel/ToolHandle.h"
+#include "Geant4/G4VPhysicsConstructor.hh"
+#include "Geant4/G4VUserPhysicsList.hh"
+
+#include "GiGaMTFactories/GiGaFactoryBase.h"
+#include "GiGaMTFactories/GiGaTool.h"
+
+#include "Geant4/globals.hh"
+
+//class GaussCkvOpticalPhysicsList:  public extends<GiGaTool, GiGaFactoryBase<G4VUserPhysicsList>>
+
+class GaussCkvOpticalPhysicsList: public G4VPhysicsConstructor  
+{
+ public:
+  GaussCkvOpticalPhysicsList() ; 
+
+//  using extends::extends;
+
+  virtual ~GaussCkvOpticalPhysicsList() {} ; 
+
+
+
+  void ConstructParticle() override;
+  void ConstructProcess() override;
+  void ConstructOpProc();
+
+
+ private:
+
+  
+  bool m_ActivateRICHOpticalPhysProc ;
+  int m_MaxPhotonsPerRichCherenkovStep;
+  bool m_RichActivateVerboseProcessInfoTag;
+  bool m_CherenkovAddBackgrRich2;
+  double m_CherenkovRich2BackgrProbFactor;
+  //bool m_ApplyMaxPhotCkvLimitPerRadiator;
+
+};
+
+#endif   ///< GIGAMT_GaussCkvOpticalPhysicsList_H >
diff --git a/Sim/GaussPhotonics/GaussPhotonics/GaussCkvPhysics.h b/Sim/GaussPhotonics/GaussPhotonics/GaussCkvPhysics.h
new file mode 100644
index 000000000..c6557c4a0
--- /dev/null
+++ b/Sim/GaussPhotonics/GaussPhotonics/GaussCkvPhysics.h
@@ -0,0 +1,24 @@
+/*****************************************************************************\
+* (c) Copyright 2000-2020 CERN for the benefit of the LHCb Collaboration      *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                             *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+// ============================================================================
+#ifndef    GIGAMT_GaussCkvPhysics_H
+#define    GIGAMT_GaussCkvPhysics_H 1
+// ============================================================================
+#include "GiGaMTFactories/GiGaMTG4PhysicsConstrFAC.h"
+
+#include "GaussPhotonics/GaussCkvOpticalPhysicsList.h"
+
+
+typedef GiGaMTG4PhysicsConstrFAC<GaussCkvOpticalPhysicsList> GiGaMT_GaussCkvOpticalPhysicsList;
+DECLARE_COMPONENT_WITH_ID( GiGaMT_GaussCkvOpticalPhysicsList, "GiGaMT_GaussCkvOpticalPhysicsList" )
+
+
+#endif ///< GIGAMT_GaussCkvPhysics_H >
diff --git a/Sim/GaussPhotonics/GaussPhotonics/RhCkvG4Cerenkov.h b/Sim/GaussPhotonics/GaussPhotonics/RhCkvG4Cerenkov.h
new file mode 100644
index 000000000..8948e4fbb
--- /dev/null
+++ b/Sim/GaussPhotonics/GaussPhotonics/RhCkvG4Cerenkov.h
@@ -0,0 +1,243 @@
+//
+// ********************************************************************
+// * License and Disclaimer                                           *
+// *                                                                  *
+// * The  Geant4 software  is  copyright of the Copyright Holders  of *
+// * the Geant4 Collaboration.  It is provided  under  the terms  and *
+// * conditions of the Geant4 Software License,  included in the file *
+// * LICENSE and available at  http://cern.ch/geant4/license .  These *
+// * include a list of copyright holders.                             *
+// *                                                                  *
+// * Neither the authors of this software system, nor their employing *
+// * institutes,nor the agencies providing financial support for this *
+// * work  make  any representation or  warranty, express or implied, *
+// * regarding  this  software system or assume any liability for its *
+// * use.  Please see the license in the file  LICENSE  and URL above *
+// * for the full disclaimer and the limitation of liability.         *
+// *                                                                  *
+// * This  code  implementation is the result of  the  scientific and *
+// * technical work of the GEANT4 collaboration.                      *
+// * By using,  copying,  modifying or  distributing the software (or *
+// * any work based  on the software)  you  agree  to acknowledge its *
+// * use  in  resulting  scientific  publications,  and indicate your *
+// * acceptance of all terms of the Geant4 Software license.          *
+// ********************************************************************
+//
+//
+//
+//
+////////////////////////////////////////////////////////////////////////
+// RICH Cerenkov Radiation Class Definition
+////////////////////////////////////////////////////////////////////////
+//
+// File:        RhCkvG4Cerenkov.hh
+// Description:	Discrete Process - Generation of Cerenkov Photons
+// Version:     2.0
+// Created:     1996-02-21
+// Author:      Juliet Armstrong
+// Updated:     2007-09-30 change inheritance to G4VDiscreteProcess
+//              2005-07-28 add G4ProcessType to constructor
+//              1999-10-29 add method and class descriptors
+//              1997-04-09 by Peter Gumplinger
+//              > G4MaterialPropertiesTable; new physics/tracking scheme
+// Updated  SE 2021-06-06
+////////////////////////////////////////////////////////////////////////
+
+#ifndef RhCkvG4Cerenkov_h
+#define RhCkvG4Cerenkov_h 1
+
+#include <CLHEP/Units/SystemOfUnits.h>
+
+#include "Geant4/globals.hh"
+#include "Geant4/templates.hh"
+#include "Geant4/Randomize.hh"
+#include "Geant4/G4ThreeVector.hh"
+#include "Geant4/G4ParticleMomentum.hh"
+#include "Geant4/G4Step.hh"
+#include "Geant4/G4VProcess.hh"
+#include "Geant4/G4OpticalPhoton.hh"
+#include "Geant4/G4DynamicParticle.hh"
+#include "Geant4/G4Material.hh"
+#include "Geant4/G4PhysicsTable.hh"
+#include "Geant4/G4MaterialPropertyVector.hh"
+#include "Geant4/G4MaterialPropertiesTable.hh"
+#include "Geant4/G4PhysicsOrderedFreeVector.hh"
+
+class RhCkvG4Cerenkov : public G4VProcess
+{
+ public:
+  explicit RhCkvG4Cerenkov(const G4String& processName = "RhCkvG4Cerenkov",
+                      G4ProcessType type          = fElectromagnetic);
+  ~RhCkvG4Cerenkov();
+
+  explicit RhCkvG4Cerenkov(const RhCkvG4Cerenkov& right);
+
+ private:
+  RhCkvG4Cerenkov& operator=(const RhCkvG4Cerenkov& right) = delete;
+
+ public:
+  G4bool IsApplicable(const G4ParticleDefinition& aParticleType) override;
+  // Returns true -> 'is applicable', for all charged particles
+  // except short-lived particles.
+
+  void BuildPhysicsTable(const G4ParticleDefinition& aParticleType) override;
+  // Build table at a right time
+
+  void PreparePhysicsTable(const G4ParticleDefinition& part) override;
+  void Initialise();
+ 
+  G4double GetMeanFreePath(const G4Track& aTrack, G4double, G4ForceCondition*);
+  // Returns the discrete step limit and sets the 'StronglyForced'
+  // condition for the DoIt to be invoked at every step.
+
+  G4double PostStepGetPhysicalInteractionLength(const G4Track& aTrack, G4double,
+                                                G4ForceCondition*) override;
+  // Returns the discrete step limit and sets the 'StronglyForced'
+  // condition for the DoIt to be invoked at every step.
+
+  G4VParticleChange* PostStepDoIt(const G4Track& aTrack,
+                                  const G4Step& aStep) override;
+  // This is the method implementing the Cerenkov process.
+
+  //  no operation in  AtRestDoIt and  AlongStepDoIt
+  virtual G4double AlongStepGetPhysicalInteractionLength(
+    const G4Track&, G4double, G4double, G4double&, G4GPILSelection*) override
+  {
+    return -1.0;
+  };
+
+  virtual G4double AtRestGetPhysicalInteractionLength(
+    const G4Track&, G4ForceCondition*) override
+  {
+    return -1.0;
+  };
+
+  //  no operation in  AtRestDoIt and  AlongStepDoIt
+  virtual G4VParticleChange* AtRestDoIt(const G4Track&, const G4Step&) override
+  {
+    return nullptr;
+  };
+
+  virtual G4VParticleChange* AlongStepDoIt(const G4Track&,
+                                           const G4Step&) override
+  {
+    return nullptr;
+  };
+
+  void SetTrackSecondariesFirst(const G4bool state);
+  // If set, the primary particle tracking is interrupted and any
+  // produced Cerenkov photons are tracked next. When all have
+  // been tracked, the tracking of the primary resumes.
+
+  G4bool GetTrackSecondariesFirst() const;
+  // Returns the boolean flag for tracking secondaries first.
+
+  void SetMaxBetaChangePerStep(const G4double d);
+  // Set the maximum allowed change in beta = v/c in % (perCent) per step.
+
+  G4double GetMaxBetaChangePerStep() const;
+  // Returns the maximum allowed change in beta = v/c in % (perCent)
+
+  void SetMaxNumPhotonsPerStep(const G4int NumPhotons);
+  // Set the maximum number of Cerenkov photons allowed to be generated during
+  // a tracking step. This is an average ONLY; the actual number will vary
+  // around this average. If invoked, the maximum photon stack will roughly be
+  // of the size set. If not called, the step is not limited by the number of
+  // photons generated.
+
+  G4int GetMaxNumPhotonsPerStep() const;
+  // Returns the maximum number of Cerenkov photons allowed to be
+  // generated during a tracking step.
+
+  void SetStackPhotons(const G4bool);
+  // Call by the user to set the flag for stacking the scint. photons
+
+  G4bool GetStackPhotons() const;
+  // Return the boolean for whether or not the scint. photons are stacked
+
+  G4int GetNumPhotons() const;
+  // Returns the current number of scint. photons (after PostStepDoIt)
+
+  G4PhysicsTable* GetPhysicsTable() const;
+  // Returns the address of the physics table.
+
+  void DumpPhysicsTable() const;
+  // Prints the physics table.
+
+  G4double GetAverageNumberOfPhotons(const G4double charge, const G4double beta,
+                                     const G4Material* aMaterial,
+                                     G4MaterialPropertyVector* Rindex) const;
+
+  //LHCb specific
+  void InitCkvMatList();
+  G4int FindG4CkvMatIndex (std::string aMatName, G4int aDummyIndex );
+
+  G4bool GetRichVerboseInfoTag(){return  fRichVerboseInfoTag;}
+  void SetRichVerboseInfoTag(G4bool aVTagValue)
+             {fRichVerboseInfoTag = aVTagValue;}
+  //void SetMaxPhotonPerRadiatorFlag(const G4bool aMaxNumPerStepRadiatorFlag)
+  //     {fMaxPhotonPerRadiatorFlag=aMaxNumPerStepRadiatorFlag;}
+  void setAddBackGrRich2(G4bool addbackgrFlag  )
+  {  m_AddBackGrRich2 = addbackgrFlag;}
+  void setRich2BackgrProb(G4double abackgrprob )
+  { m_Rich2BackgrProb = abackgrprob; }
+  void printBackgrRich2Param();
+
+  void setActivateRichG4CherenkovAnalysis(G4bool aFLA) {
+    m_ActivateRichG4CherenkovAnalysis = aFLA ;
+  }
+
+ protected:
+  G4PhysicsTable* thePhysicsTable;
+
+ private:
+  G4bool fTrackSecondariesFirst;
+  G4double fMaxBetaChange;
+  G4int fMaxPhotons;
+
+  G4bool fStackingFlag;
+
+  G4int fNumPhotons;
+
+  //Info specific for LHCb
+  G4bool fRichVerboseInfoTag;
+  // G4bool fMaxPhotonPerRadiatorFlag; To be activated later.
+
+  G4bool m_AddBackGrRich2;
+  G4double  m_Rich2BackgrProb;
+  G4bool  m_ActivateRichG4CherenkovAnalysis;
+  std::string m_Rich2GasVolName;
+  G4double m_R2Rnd_minCos;
+  G4double m_R2Rnd_maxCos;
+
+  std::vector<G4int> m_RichCkvProdMatIndex;
+
+};
+
+inline G4bool RhCkvG4Cerenkov::GetTrackSecondariesFirst() const
+{
+  return fTrackSecondariesFirst;
+}
+
+inline G4double RhCkvG4Cerenkov::GetMaxBetaChangePerStep() const
+{
+  return fMaxBetaChange;
+}
+
+inline G4int RhCkvG4Cerenkov::GetMaxNumPhotonsPerStep() const { return fMaxPhotons; }
+
+inline void RhCkvG4Cerenkov::SetStackPhotons(const G4bool stackingFlag)
+{
+  fStackingFlag = stackingFlag;
+}
+
+inline G4bool RhCkvG4Cerenkov::GetStackPhotons() const { return fStackingFlag; }
+
+inline G4int RhCkvG4Cerenkov::GetNumPhotons() const { return fNumPhotons; }
+
+inline G4PhysicsTable* RhCkvG4Cerenkov::GetPhysicsTable() const
+{
+  return thePhysicsTable;
+}
+
+#endif /* RhCkvG4Cerenkov_h */
diff --git a/Sim/GaussPhotonics/GaussPhotonics/RhCkvG4OpBoundaryProcess.h b/Sim/GaussPhotonics/GaussPhotonics/RhCkvG4OpBoundaryProcess.h
new file mode 100644
index 000000000..77d2eda1f
--- /dev/null
+++ b/Sim/GaussPhotonics/GaussPhotonics/RhCkvG4OpBoundaryProcess.h
@@ -0,0 +1,391 @@
+//
+// ********************************************************************
+// * License and Disclaimer                                           *
+// *                                                                  *
+// * The  Geant4 software  is  copyright of the Copyright Holders  of *
+// * the Geant4 Collaboration.  It is provided  under  the terms  and *
+// * conditions of the Geant4 Software License,  included in the file *
+// * LICENSE and available at  http://cern.ch/geant4/license .  These *
+// * include a list of copyright holders.                             *
+// *                                                                  *
+// * Neither the authors of this software system, nor their employing *
+// * institutes,nor the agencies providing financial support for this *
+// * work  make  any representation or  warranty, express or implied, *
+// * regarding  this  software system or assume any liability for its *
+// * use.  Please see the license in the file  LICENSE  and URL above *
+// * for the full disclaimer and the limitation of liability.         *
+// *                                                                  *
+// * This  code  implementation is the result of  the  scientific and *
+// * technical work of the GEANT4 collaboration.                      *
+// * By using,  copying,  modifying or  distributing the software (or *
+// * any work based  on the software)  you  agree  to acknowledge its *
+// * use  in  resulting  scientific  publications,  and indicate your *
+// * acceptance of all terms of the Geant4 Software license.          *
+// ********************************************************************
+//
+//
+//
+//
+////////////////////////////////////////////////////////////////////////
+// Optical Photon Boundary Process Class Definition
+// With modifications for LHCb usage
+////////////////////////////////////////////////////////////////////////
+//
+// File:        RhCkvG4OpBoundaryProcess.hh
+// Description: Discrete Process -- reflection/refraction at
+//                                  optical interfaces
+// Version:     1.1
+// Created:     1997-06-18
+// Modified:    2005-07-28 add G4ProcessType to constructor
+//              1999-10-29 add method and class descriptors
+//              1999-10-10 - Fill NewMomentum/NewPolarization in
+//                           DoAbsorption. These members need to be
+//                           filled since DoIt calls
+//                           aParticleChange.SetMomentumChange etc.
+//                           upon return (thanks to: Clark McGrew)
+//              2006-11-04 - add capability of calculating the reflectivity
+//                           off a metal surface by way of a complex index
+//                           of refraction - Thanks to Sehwook Lee and John
+//                           Hauptman (Dept. of Physics - Iowa State Univ.)
+//              2009-11-10 - add capability of simulating surface reflections
+//                           with Look-Up-Tables (LUT) containing measured
+//                           optical reflectance for a variety of surface
+//                           treatments - Thanks to Martin Janecek and
+//                           William Moses (Lawrence Berkeley National Lab.)
+//              2013-06-01 - add the capability of simulating the transmission
+//                           of a dichronic filter
+//              2017-02-24 - add capability of simulating surface reflections
+//                           with Look-Up-Tables (LUT) developed in DAVIS
+//
+// Author:      Peter Gumplinger
+//              adopted from work by Werner Keil - April 2/96
+//
+// Modified SE 01-09-2021
+////////////////////////////////////////////////////////////////////////
+
+#ifndef RhCkvG4OpBoundaryProcess_h
+#define RhCkvG4OpBoundaryProcess_h 1
+
+#include "Geant4/G4RandomTools.hh"
+#include "Geant4/G4VDiscreteProcess.hh"
+#include "Geant4/G4OpticalSurface.hh"
+#include "Geant4/G4OpticalPhoton.hh"
+#include "Geant4/G4Material.hh"
+#include "Geant4/G4LogicalBorderSurface.hh"
+#include "Geant4/G4LogicalSkinSurface.hh"
+#include "Geant4/G4TransportationManager.hh"
+#include "Geant4/G4Track.hh"
+#include "Geant4/G4Step.hh"
+#include <vector>
+#include <map>
+
+enum RhCkvG4OpBoundaryProcessStatus
+{
+  Undefined,
+  Transmission,
+  FresnelRefraction,
+  FresnelReflection,
+  TotalInternalReflection,
+  LambertianReflection,
+  LobeReflection,
+  SpikeReflection,
+  BackScattering,
+  Absorption,
+  Detection,
+  NotAtBoundary,
+  SameMaterial,
+  StepTooSmall,
+  NoRINDEX,
+  PolishedLumirrorAirReflection,
+  PolishedLumirrorGlueReflection,
+  PolishedAirReflection,
+  PolishedTeflonAirReflection,
+  PolishedTiOAirReflection,
+  PolishedTyvekAirReflection,
+  PolishedVM2000AirReflection,
+  PolishedVM2000GlueReflection,
+  EtchedLumirrorAirReflection,
+  EtchedLumirrorGlueReflection,
+  EtchedAirReflection,
+  EtchedTeflonAirReflection,
+  EtchedTiOAirReflection,
+  EtchedTyvekAirReflection,
+  EtchedVM2000AirReflection,
+  EtchedVM2000GlueReflection,
+  GroundLumirrorAirReflection,
+  GroundLumirrorGlueReflection,
+  GroundAirReflection,
+  GroundTeflonAirReflection,
+  GroundTiOAirReflection,
+  GroundTyvekAirReflection,
+  GroundVM2000AirReflection,
+  GroundVM2000GlueReflection,
+  Dichroic
+};
+
+class RhCkvG4OpBoundaryProcess : public G4VDiscreteProcess
+{
+ public:
+  explicit RhCkvG4OpBoundaryProcess(const G4String& processName = "OpBoundary",
+                               G4ProcessType type          = fOptical);
+  virtual ~RhCkvG4OpBoundaryProcess();
+
+  virtual G4bool IsApplicable(
+    const G4ParticleDefinition& aParticleType) override;
+  // Returns true -> 'is applicable' only for an optical photon.
+
+  virtual G4double GetMeanFreePath(const G4Track&, G4double,
+                                   G4ForceCondition* condition) override;
+  // Returns infinity; i. e. the process does not limit the step, but sets the
+  // 'Forced' condition for the DoIt to be invoked at every step. However, only
+  // at a boundary will any action be taken.
+
+  G4VParticleChange* PostStepDoIt(const G4Track& aTrack,
+                                  const G4Step& aStep) override;
+  // This is the method implementing boundary processes.
+
+  virtual RhCkvG4OpBoundaryProcessStatus GetStatus() const;
+  // Returns the current status.
+
+  virtual void SetInvokeSD(G4bool);
+  // Set flag for call to InvokeSD method.
+
+  virtual void PreparePhysicsTable(const G4ParticleDefinition&) override;
+
+  virtual void Initialise();
+
+  void SetRhCkvOptMatIndex();
+  G4int FindG4MatIndex (std::string aMatName, G4int aDummyIndex );
+
+
+
+ private:
+  RhCkvG4OpBoundaryProcess(const RhCkvG4OpBoundaryProcess& right) = delete;
+  RhCkvG4OpBoundaryProcess& operator=(const RhCkvG4OpBoundaryProcess& right) = delete;
+  
+
+  G4bool G4BooleanRand(const G4double prob) const;
+
+  G4ThreeVector GetFacetNormal(const G4ThreeVector& Momentum,
+                               const G4ThreeVector& Normal) const;
+
+  void DielectricMetal();
+  void DielectricDielectric();
+
+  void DielectricLUT();
+  void DielectricLUTDAVIS();
+
+  void DielectricDichroic();
+
+  void ChooseReflection();
+  void DoAbsorption();
+  void DoReflection();
+
+  G4double GetIncidentAngle();
+  // Returns the incident angle of optical photon
+
+  G4double GetReflectivity(G4double E1_perp, G4double E1_parl,
+                           G4double incidentangle, G4double RealRindex,
+                           G4double ImaginaryRindex);
+  // Returns the Reflectivity on a metalic surface
+
+  void CalculateReflectivity(void);
+
+  void BoundaryProcessVerbose(void) const;
+
+  // Invoke SD for post step point if the photon is 'detected'
+  G4bool InvokeSD(const G4Step* step);
+
+  G4double thePhotonMomentum;
+
+  G4ThreeVector OldMomentum;
+  G4ThreeVector OldPolarization;
+
+  G4ThreeVector NewMomentum;
+  G4ThreeVector NewPolarization;
+
+  G4ThreeVector theGlobalNormal;
+  G4ThreeVector theFacetNormal;
+
+  G4Material* Material1;
+  G4Material* Material2;
+
+  G4int CurPhotStepNum;
+  G4int theMaxPhotStepNumInBoundaryProc;
+
+
+  G4OpticalSurface* OpticalSurface;
+
+  G4MaterialPropertyVector* fRealRIndexMPV;
+  G4MaterialPropertyVector* fImagRIndexMPV;
+
+  G4double Rindex1;
+  G4double Rindex2;
+
+  G4double cost1, cost2, sint1, sint2;
+
+  RhCkvG4OpBoundaryProcessStatus theStatus;
+
+  G4OpticalSurfaceModel theModel;
+
+  G4OpticalSurfaceFinish theFinish;
+
+  G4double theReflectivity;
+  G4double theEfficiency;
+  G4double theTransmittance;
+
+  G4double theSurfaceRoughness;
+
+  G4double prob_sl, prob_ss, prob_bs;
+
+  G4int iTE, iTM;
+
+  G4double kCarTolerance;
+
+  size_t idx, idy;
+  G4Physics2DVector* DichroicVector;
+
+  G4bool fInvokeSD;
+
+  size_t idx_rindex1        = 0;
+  size_t idx_rindex_surface = 0;
+  size_t idx_reflect        = 0;
+  size_t idx_eff            = 0;
+  size_t idx_trans          = 0;
+  size_t idx_lobe           = 0;
+  size_t idx_spike          = 0;
+  size_t idx_back           = 0;
+  size_t idx_rindex2        = 0;
+  size_t idx_groupvel       = 0;
+  size_t idx_rrindex        = 0;
+  size_t idx_irindex        = 0;
+
+
+  G4int m_Material1Index;
+  G4int m_Material2Index;
+
+  G4int m_Rich1GasQWMatIndex;
+  G4int m_Rich2GasQWMatIndex;
+  G4int m_RichPmtQWMatIndex;
+
+  G4int m_RichAirMatIndex;
+  G4int m_Rich1NitrogenMatIndex;
+  G4int m_RichPmtPhCathMatIndex;
+  G4int m_RichPmtVacMatIndex;
+  G4int m_Rich1C4F10MatIndex;
+  G4int m_Rich1RadiatorGasMatIndex;
+  G4int m_Rich2NitrogenMatIndex;
+  G4int m_Rich2CF4MatIndex;
+  G4int m_Rich2RadiatorGasMatIndex;
+
+  std::vector<G4int> m_RichTotalIntReflCheckList;
+
+  std::map<G4int, G4int>m_RichTransCoefCheckPairList;
+  std::vector<G4int> m_RichTransCoefCheckSingleList;
+  std::map<G4int, G4int>m_RichReflSupCheckPairList;
+  std::map<G4int, G4int> m_RichARCoatCheckPairList;
+
+  
+
+
+};
+
+////////////////////
+// Inline methods
+////////////////////
+
+inline G4bool RhCkvG4OpBoundaryProcess::G4BooleanRand(const G4double prob) const
+{
+  /* Returns a random boolean variable with the specified probability */
+  return (G4UniformRand() < prob);
+}
+
+inline G4bool RhCkvG4OpBoundaryProcess::IsApplicable(
+  const G4ParticleDefinition& aParticleType)
+{
+  return (&aParticleType == G4OpticalPhoton::OpticalPhoton());
+}
+
+inline RhCkvG4OpBoundaryProcessStatus RhCkvG4OpBoundaryProcess::GetStatus() const
+{
+  return theStatus;
+}
+
+inline void RhCkvG4OpBoundaryProcess::SetInvokeSD(G4bool flag) { fInvokeSD = flag; }
+
+inline void RhCkvG4OpBoundaryProcess::ChooseReflection()
+{
+  G4double rand = G4UniformRand();
+  if(rand >= 0.0 && rand < prob_ss)
+  {
+    theStatus      = SpikeReflection;
+    theFacetNormal = theGlobalNormal;
+  }
+  else if(rand >= prob_ss && rand <= prob_ss + prob_sl)
+  {
+    theStatus = LobeReflection;
+  }
+  else if(rand > prob_ss + prob_sl && rand < prob_ss + prob_sl + prob_bs)
+  {
+    theStatus = BackScattering;
+  }
+  else
+  {
+    theStatus = LambertianReflection;
+  }
+}
+
+inline void RhCkvG4OpBoundaryProcess::DoAbsorption()
+{
+  theStatus = Absorption;
+
+  if(G4BooleanRand(theEfficiency))
+  {
+    // EnergyDeposited =/= 0 means: photon has been detected
+    theStatus = Detection;
+    aParticleChange.ProposeLocalEnergyDeposit(thePhotonMomentum);
+  }
+  else
+  {
+    aParticleChange.ProposeLocalEnergyDeposit(0.0);
+  }
+
+  NewMomentum     = OldMomentum;
+  NewPolarization = OldPolarization;
+
+  aParticleChange.ProposeTrackStatus(fStopAndKill);
+}
+
+inline void RhCkvG4OpBoundaryProcess::DoReflection()
+{
+  if(theStatus == LambertianReflection)
+  {
+    NewMomentum    = G4LambertianRand(theGlobalNormal);
+    theFacetNormal = (NewMomentum - OldMomentum).unit();
+  }
+  else if(theFinish == ground)
+  {
+    theStatus = LobeReflection;
+    if(fRealRIndexMPV && fImagRIndexMPV)
+    {
+      //
+    }
+    else
+    {
+      theFacetNormal = GetFacetNormal(OldMomentum, theGlobalNormal);
+    }
+    G4double PdotN = OldMomentum * theFacetNormal;
+    NewMomentum    = OldMomentum - (2. * PdotN) * theFacetNormal;
+  }
+  else
+  {
+    theStatus      = SpikeReflection;
+    theFacetNormal = theGlobalNormal;
+    G4double PdotN = OldMomentum * theFacetNormal;
+    NewMomentum    = OldMomentum - (2. * PdotN) * theFacetNormal;
+  }
+  G4double EdotN  = OldPolarization * theFacetNormal;
+  NewPolarization = -OldPolarization + (2. * EdotN) * theFacetNormal;
+}
+
+#endif /* RhCkvG4OpBoundaryProcess_h */
diff --git a/Sim/GaussPhotonics/GaussPhotonics/RichCkvCommonSensDet.h b/Sim/GaussPhotonics/GaussPhotonics/RichCkvCommonSensDet.h
new file mode 100644
index 000000000..7754e3171
--- /dev/null
+++ b/Sim/GaussPhotonics/GaussPhotonics/RichCkvCommonSensDet.h
@@ -0,0 +1,68 @@
+/*****************************************************************************\
+* (c) Copyright 2000-2020 CERN for the benefit of the LHCb Collaboration      *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                             *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+//  Author SE 20-11-2021
+//
+#ifndef GAUSSCHERENKOV_RICHCKVCOMMONSENSDET_H 
+#define GAUSSCHERENKOV_RICHCKVCOMMONSENSDET_H 1
+// Include files
+
+#include "GaussPhotonics/RichCkvStdSensDet.h"
+#include "GaussPhotonics/RichCkvG4HitCollName.h"
+#include "GaussPhotonics/RichG4PhotonicsGeomProp.h"
+
+#include "Geant4/G4Step.hh"
+#include "Geant4/G4TouchableHistory.hh"
+
+
+class RichCkvCommonSensDet {
+
+ public:
+
+  virtual ~RichCkvCommonSensDet(); ///< Destructor
+  static RichCkvCommonSensDet* getRichCkvCommonSensDetInstance();
+  bool ProcessRichPmtHits( G4Step* aStep , G4TouchableHistory* aTh);
+
+  void RichPmtAviodDuplicateHitsActivate(bool adupavoidfl ) 
+  {m_RichPmtAviodDuplicateHitsActivate =  adupavoidfl;}
+  void RichPmtFlagDuplicateHitsActivate (bool adupfl ) 
+  {m_RichPmtFlagDuplicateHitsActivate = adupfl;}
+  RichCkvG4Hit*  newHit()  {  return m_newHit;}
+  RichG4PhotonicsGeomProp * RichGeomProperty() {return   m_RichGeomProperty ; }
+  void InitGeomProp() ;
+  bool QESelected(G4Step* aStep, int aRDet );
+
+  G4double MaxZHitInRich1Detector() const
+  {return m_RichGeomProperty->MaxZHitInRich1Det(); }
+  G4double MaxZHitInRich2Detector() const
+  {return m_RichGeomProperty->MaxZHitInRich2Det(); }
+
+  RichCkvG4HitCollName* RichG4HitCollName() {return m_RichG4HitCollName ;}
+
+
+  
+
+ private:
+  /// Standard constructor
+  RichCkvCommonSensDet( );   
+  static RichCkvCommonSensDet* RichCkvCommonSensDetInstance;
+  bool m_RichPmtAviodDuplicateHitsActivate;
+  bool m_RichPmtFlagDuplicateHitsActivate;
+  bool m_GeomPropInitFlag ;
+  RichG4PhotonicsGeomProp * m_RichGeomProperty ;
+  int m_MaxTotalNumPmtsInRich;
+
+  RichCkvG4Hit * m_newHit;
+  RichCkvG4HitCollName* m_RichG4HitCollName;
+
+};
+
+
+#endif //end of GAUSSCHERENKOV_RICHCKVCOMMONSENSDET_H
diff --git a/Sim/GaussPhotonics/GaussPhotonics/RichCkvG4Hit.h b/Sim/GaussPhotonics/GaussPhotonics/RichCkvG4Hit.h
new file mode 100644
index 000000000..820801851
--- /dev/null
+++ b/Sim/GaussPhotonics/GaussPhotonics/RichCkvG4Hit.h
@@ -0,0 +1,136 @@
+/*****************************************************************************\
+* (c) Copyright 2000-2020 CERN for the benefit of the LHCb Collaboration      *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                             *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+// Author SE 10-11-2021
+//
+#ifndef GAUSSPHOTONICS_RICHCKVG4HIT_H
+#define GAUSSPHOTONICS_RICHCKVG4HIT_H 1
+
+#include "Geant4/G4VHit.hh"
+#include "Geant4/G4Allocator.hh"
+#include "Geant4/G4THitsCollection.hh"
+#include "Geant4/G4ThreeVector.hh"
+#include "GiGaMTCoreDet/GaussHitBase.h"
+
+class RichCkvG4Hit : public Gaussino::HitBase {
+ public:
+ 
+  RichCkvG4Hit() = default;
+
+  virtual ~RichCkvG4Hit() = default ; //destructor
+  
+  RichCkvG4Hit(const RichCkvG4Hit &right);
+
+  const RichCkvG4Hit& operator=(const RichCkvG4Hit &right);
+
+  int operator==(const RichCkvG4Hit  & /*right */) const {return 0; }
+
+ inline void * operator new(size_t);
+ inline void operator delete(void *aHit);
+
+  void Print() override;
+  void Draw() override;
+ 
+ private:
+
+  G4int m_CurModuleNum;  // Current PMT Module number .
+  G4int m_CurPmtNum;   // Current Pmt number.
+  G4double m_edep;           ///< energy deposited in the Si Det.
+  G4ThreeVector m_GlobalPos; ///<  Global coordinate in the LHCb system.
+  G4ThreeVector m_LocalPos;  ///< Local coordinate in the PMT System.
+  G4int m_CurRichNum;        ///< this is 0 for RICH1 and 1 for RICH2
+  G4int m_CurSectorNum;      ///< this is the Quadrant or Half of a RICH.
+  G4int m_CurPixelXNum;       ///< Pixel Column number (0-31) within an HPD.
+  G4int m_CurPixelYNum;       ///< Pixel Row number (0-31) within an HPD.
+
+ public:
+
+  inline void SetCurModuleNum(const G4int cm)
+  {m_CurModuleNum=cm;}
+  inline G4int GetCurModuleNum () const {return m_CurModuleNum ;}
+
+  inline void SetCurPmtNum (const G4int ap ) {
+   m_CurPmtNum = ap;
+  }
+
+  inline G4int GetCurPmtNum() const { return m_CurPmtNum ;  }
+
+
+ inline void SetEdep(const G4double de)
+  { m_edep = de; };
+  inline void AddEdep( const G4double addenergy )
+  { m_edep += addenergy; }
+
+  inline G4double GetEdep() const
+  { return m_edep; };
+
+  inline void SetGlobalPos( const G4ThreeVector & xyz)
+  { m_GlobalPos = xyz; };
+
+  inline const G4ThreeVector & GetGlobalPos() const
+  { return m_GlobalPos; };
+
+  inline void SetLocalPos(const G4ThreeVector & localxyz)
+  { m_LocalPos = localxyz; };
+
+  inline const G4ThreeVector & GetLocalPos() const
+  { return m_LocalPos; };
+
+
+  inline void SetCurRichDetNum( const G4int IRichNum )
+  { m_CurRichNum = IRichNum ; }
+
+  inline G4int GetCurRichDetNum() const
+  { return m_CurRichNum; }
+
+  inline void SetCurSectorNum ( const G4int isector )
+  { m_CurSectorNum = isector; } ;
+
+  inline G4int GetCurSectorNum() const
+  { return m_CurSectorNum ; };
+
+  inline void SetCurPixelXNum ( const G4int ipx )
+  { m_CurPixelXNum = ipx; };
+
+  inline G4int GetCurPixelXNum() const
+  { return m_CurPixelXNum; };
+
+  inline void SetCurPixelYNum ( const G4int ipy )
+  { m_CurPixelYNum = ipy; };
+
+  inline G4int GetCurPixelYNum() const
+  { return m_CurPixelYNum; };
+
+
+
+};
+//==============================================================================//
+ typedef   G4THitsCollection<RichCkvG4Hit> RichCkvG4HitsCollection;
+
+ extern  G4ThreadLocal G4Allocator<RichCkvG4Hit> * RichCkvG4HitAllocator;
+//===============================================================================//
+
+inline void* RichCkvG4Hit::operator new (size_t){
+
+  if(! RichCkvG4HitAllocator  ) {
+       RichCkvG4HitAllocator  = new G4Allocator<RichCkvG4Hit>;
+    }
+
+    return (void*) ( RichCkvG4HitAllocator ->MallocSingle()   );
+ }
+//=========================================================================//
+inline void  RichCkvG4Hit::operator delete (void * aHit )  {
+  RichCkvG4HitAllocator ->FreeSingle((RichCkvG4Hit* ) aHit);
+
+}
+
+
+//========================================================================//
+#endif // GAUSSPHOTONICS_RICHCKVG4HIT_H
diff --git a/Sim/GaussPhotonics/GaussPhotonics/RichCkvG4HitCollName.h b/Sim/GaussPhotonics/GaussPhotonics/RichCkvG4HitCollName.h
new file mode 100644
index 000000000..b58bc15a5
--- /dev/null
+++ b/Sim/GaussPhotonics/GaussPhotonics/RichCkvG4HitCollName.h
@@ -0,0 +1,123 @@
+/*****************************************************************************\
+* (c) Copyright 2000-2020 CERN for the benefit of the LHCb Collaboration      *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                             *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+// Author  Sajan Easo   20-10-2021
+#ifndef GaussPhotonics_RichCkvG4HitCollName_h
+#define GaussPhotonics_RichCkvG4HitCollName_h 1
+#include "Geant4/globals.hh"
+#include <vector>
+
+class RichCkvG4HitCollName {
+ 
+public:
+
+  RichCkvG4HitCollName();
+  virtual ~RichCkvG4HitCollName();
+
+  int NumberOfHCollectionInRICH() const
+  {
+    return m_NumberOfHCollectionInRICH; 
+  }
+  int NumberOfStdHCollectionInRICH() const
+  {
+    return m_NumberOfStdHCollectionInRICH; 
+  }
+  int NumberOfGrandHCollectionInRICH() const
+  {
+    return m_NumberOfGrandHCollectionInRICH; 
+  }
+   
+  G4String RichHCName(const int HCNum ) 
+  {
+    return m_RichHCName[HCNum]; 
+  }
+
+  const std::vector<G4String> & RichHCNameVect() const
+  {
+    return m_RichHCName;
+  }
+  
+  int RichHCSize() const
+  {
+    return static_cast<int>( m_RichHCName.size() ); 
+  }
+
+   int InitCollectListNumForOutput() 
+   {
+    return m_InitCollectListNumForOutput;
+   }
+   int FinalCollectListNumForOutput() 
+   {
+    return m_FinalCollectListNumForOutput;
+   }
+
+  //  void SetInitCollectListNumForOutput(int aInit) 
+  // {m_InitCollectListNumForOutput=aInit;}
+
+  // void SetFinalCollectListNumForOutput(int aFinal)
+  // {m_FinalCollectListNumForOutput= aFinal;}  
+
+  int InitCollectListNumForStdPmtOutput() 
+  {
+    return m_InitCollectListNumForStdPmtOutput;
+  }
+  int FinalCollectListNumForStdPmtOutput() 
+  {
+    return m_FinalCollectListNumForStdPmtOutput;
+  }
+
+  //  void SetInitCollectListNumForStdPmtOutput(int aInit) 
+  // {m_InitCollectListNumForStdPmtOutput=aInit;}
+  // void SetFinalCollectListNumForStdPmtOutput(int aFinal)
+  // {m_FinalCollectListNumForStdPmtOutput= aFinal;}  
+
+
+  int InitCollectListNumForGrandPmtOutput() 
+  {
+    return m_InitCollectListNumForGrandPmtOutput;
+  }
+  int FinalCollectListNumForGrandPmtOutput() 
+  {
+    return m_FinalCollectListNumForGrandPmtOutput;
+  }
+
+  //  void SetInitCollectListNumForGrandPmtOutput(int aInit) 
+  // {m_InitCollectListNumForGrandPmtOutput=aInit;}
+  // void SetFinalCollectListNumForGrandPmtOutput(int aFinal)
+  // {m_FinalCollectListNumForGrandPmtOutput= aFinal;}  
+
+
+  void UseGrandPmtFlag(bool aflag) 
+  {m_UseGrandPmtFlag = aflag;  }
+  bool getUseGrandPmtFlag() 
+  {  return m_UseGrandPmtFlag;}
+
+private:
+
+  int m_NumberOfHCollectionInRICH;
+  int m_NumberOfStdHCollectionInRICH;
+  int m_NumberOfGrandHCollectionInRICH;
+
+  std::vector<G4String> m_RichHCName;
+  int m_InitCollectListNumForOutput;
+  int m_FinalCollectListNumForOutput;
+
+  int m_InitCollectListNumForStdPmtOutput;
+  int m_FinalCollectListNumForStdPmtOutput;
+
+  int m_InitCollectListNumForGrandPmtOutput;
+  int m_FinalCollectListNumForGrandPmtOutput;
+  
+  bool m_UseGrandPmtFlag;
+  
+};  
+
+
+#endif //GaussPhotonics_RichCkvG4HitCollName
diff --git a/Sim/GaussPhotonics/GaussPhotonics/RichCkvG4SvcLocator.h b/Sim/GaussPhotonics/GaussPhotonics/RichCkvG4SvcLocator.h
new file mode 100755
index 000000000..8d16cabce
--- /dev/null
+++ b/Sim/GaussPhotonics/GaussPhotonics/RichCkvG4SvcLocator.h
@@ -0,0 +1,43 @@
+/*****************************************************************************\
+* (c) Copyright 2000-2020 CERN for the benefit of the LHCb Collaboration      *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                             *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+#ifndef Photonics_RichCkvG4SvcLocator_h 
+#define Photonics_RichCkvG4SvcLocator_h 1
+
+/// STD & STL 
+#include <string>
+/// GaudiKernel
+class IDataProviderSvc;
+class IMessageSvc;
+class IHistogramSvc;
+class INTupleSvc;
+
+namespace RichCkvG4SvcLocator
+{
+
+  static const std::string a_RichG4DataSvcName("DetectorDataSvc");
+  /// name of Message  Service 
+  static const std::string a_RichG4MessageSvcName("MessageSvc");
+  //
+  static const std::string a_RichG4HistoSvcName("HistogramDataSvc");
+
+  static const std::string a_RichG4NtupSvcName("NTupleSvc");
+
+  IDataProviderSvc*  RichG4detSvc ();
+
+  IMessageSvc*       RichG4MsgSvc ();
+
+  IHistogramSvc*     RichG4HistoSvc();
+
+  INTupleSvc *       RichG4NtupleSvc();
+}
+
+#endif //Photonics_RichCkvG4SvcLocator
+
diff --git a/Sim/GaussPhotonics/GaussPhotonics/RichCkvGrandSensDet.h b/Sim/GaussPhotonics/GaussPhotonics/RichCkvGrandSensDet.h
new file mode 100644
index 000000000..f06b4726f
--- /dev/null
+++ b/Sim/GaussPhotonics/GaussPhotonics/RichCkvGrandSensDet.h
@@ -0,0 +1,82 @@
+/*****************************************************************************\
+* (c) Copyright 2000-2020 CERN for the benefit of the LHCb Collaboration      *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                             *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+// Author SE 20-11-2021
+#ifndef GAUSSPhotonics_RICHCKVGRANDSENSDET_H
+#define GAUSSPhotonics_RICHCKVGRANDSENSDET_H 1
+
+#include "GiGaMTCoreMessage/IGiGaMessage.h"
+#include "Geant4/G4VSensitiveDetector.hh"
+//local
+#include "GaussPhotonics/RichCkvG4Hit.h"
+
+#include <map>
+
+// Forward declarations
+class G4Step;
+class G4HCofThisEvent;
+class G4TouchableHistory;
+class RichCkvGrandSensDet : public G4VSensitiveDetector, public virtual GiGaMessage {
+ public:
+  RichCkvGrandSensDet(const std::string& name);
+  virtual ~RichCkvGrandSensDet() = default; 
+ void Initialize(G4HCofThisEvent* HCE) override;
+ void initialize();
+ void ResetRichGrandCollListInEv();
+
+ bool ProcessHits(G4Step* aStep, G4TouchableHistory* history) override final;
+ G4int GetCurRichGrandCollSet (G4int aRSect);
+// Flag to control storing of hits if Rich photon or track deposited energy or not
+ inline void SetRequireEDep(bool val = true) { m_requireEDep = val; }
+
+
+ private:
+
+  bool m_RichGrandPmtAviodDuplicateHitsActivate;
+  bool m_RichGrandPmtFlagDuplicateHitsActivate;
+
+
+  G4int m_NumberOfHCInRICH;
+  std::vector<RichCkvG4HitsCollection*>  m_RichHC;
+  std::vector<G4int> m_PhdHCID;
+  G4int m_GrPmtBegin;
+  G4int m_GrPmtEnd;
+
+  bool m_requireEDep = true;
+
+};
+#include "GiGaMTFactories/GiGaMTG4SensDetFactory.h"
+
+template <typename T>
+using RichDetectorSensDetBaseFAC = GiGaMTG4SensDetFactory<T>;
+
+template<typename T>
+class RichCkvGrandSensDetFAC: public RichDetectorSensDetBaseFAC<T>
+{
+  static_assert(std::is_base_of<RichCkvGrandSensDet, T>::value);
+
+  Gaudi::Property<bool> m_requireEDep{this, "RequireEDep", true,
+                                      "Rich Grand sensdet hits must have non-zero Energy deposition"};
+
+public:
+  using base_class = RichDetectorSensDetBaseFAC<T>;
+  using base_class::base_class;
+  T* construct() const override
+  {
+    auto tmp = base_class::construct();
+    tmp->SetRequireEDep(m_requireEDep);
+    return tmp;
+  }
+};
+
+
+
+
+#endif //GAUSSPhotonics_RICHCKVGRANDSENSDET_H
diff --git a/Sim/GaussPhotonics/GaussPhotonics/RichCkvStdSensDet.h b/Sim/GaussPhotonics/GaussPhotonics/RichCkvStdSensDet.h
new file mode 100644
index 000000000..52c8a6cc7
--- /dev/null
+++ b/Sim/GaussPhotonics/GaussPhotonics/RichCkvStdSensDet.h
@@ -0,0 +1,83 @@
+/*****************************************************************************\
+* (c) Copyright 2000-2020 CERN for the benefit of the LHCb Collaboration      *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                             *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+// Author  Sajan Easo   20-10-2021
+//
+#ifndef RICHCKVSTDSENSDET_H
+#define RICHCKVSTDSENSDET_H 1
+#include "GiGaMTCoreMessage/IGiGaMessage.h"
+#include "Geant4/G4VSensitiveDetector.hh"
+//local
+#include "GaussPhotonics/RichCkvG4Hit.h"
+
+#include <map>
+
+// Forward declarations
+class G4Step;
+class G4HCofThisEvent;
+class G4TouchableHistory;
+class RichCkvStdSensDet : public G4VSensitiveDetector, public virtual GiGaMessage {
+
+ public:
+
+ RichCkvStdSensDet(const std::string& name);
+ virtual ~RichCkvStdSensDet() = default;
+
+ void Initialize(G4HCofThisEvent* HCE) override;
+ void initialize();
+ void ResetRichStdCollListInEv();
+
+ bool ProcessHits(G4Step* aStep, G4TouchableHistory* history) override final;
+ G4int GetCurRichCollSet (G4int aRDet, G4int aRSect);
+
+ // Flag to control storing of hits if Rich photon or track deposited energy or not
+ inline void SetRequireEDep(bool val = true) { m_requireEDep = val; }
+
+ private:
+
+  bool m_RichPmtAviodDuplicateHitsActivate;
+  bool m_RichPmtFlagDuplicateHitsActivate;
+
+  G4int m_NumberOfHCInRICH;
+  std::vector<RichCkvG4HitsCollection*>  m_RichHC;
+  std::vector<G4int> m_PhdHCID;
+  G4int m_StdPmtBegin;
+  G4int m_StdPmtEnd;
+
+  bool m_requireEDep = true;
+
+}; 
+#include "GiGaMTFactories/GiGaMTG4SensDetFactory.h"
+
+template <typename T>
+using RichDetectorSensDetBaseFAC = GiGaMTG4SensDetFactory<T>;
+
+template<typename T>
+class RichCkvStdSensDetFAC: public RichDetectorSensDetBaseFAC<T>
+{
+  static_assert(std::is_base_of<RichCkvStdSensDet, T>::value);
+
+  Gaudi::Property<bool> m_requireEDep{this, "RequireEDep", true,
+                                      "Rich Std sensdet hits must have non-zero Energy deposition"};
+
+public:
+  using base_class = RichDetectorSensDetBaseFAC<T>;
+  using base_class::base_class;
+  T* construct() const override
+  {
+    auto tmp = base_class::construct();
+    tmp->SetRequireEDep(m_requireEDep);
+    return tmp;
+  }
+};
+
+
+
+#endif //RICHCKVSTDSENSDET_H
diff --git a/Sim/GaussPhotonics/GaussPhotonics/RichG4PhotonicsCkvProdTag.h b/Sim/GaussPhotonics/GaussPhotonics/RichG4PhotonicsCkvProdTag.h
new file mode 100644
index 000000000..8ece3e578
--- /dev/null
+++ b/Sim/GaussPhotonics/GaussPhotonics/RichG4PhotonicsCkvProdTag.h
@@ -0,0 +1,11 @@
+#ifndef      GaussPhotonics_RichG4PhotonicsCkvPhotProdTag_h
+#define      GaussPhotonics_RichG4PhotonicsCkvPhotProdTag_h 1
+#include "Geant4/G4Track.hh"
+extern G4Track* RichG4PhotonicsCkvProdTag(const G4Track& aChTrack,
+                                  G4Track* aCkvPhotTrack,
+                                  const G4double CkvCosTheta,
+                                  const G4double CkvPhi,
+                                  const G4double CkvPhotEnergy,
+                                   const G4bool aVerboseTagFlag,
+                                   const G4int aPhotoProdTag  );
+#endif //GaussPhotonics_RichG4PhotonicsCkvProdTag_h
diff --git a/Sim/GaussPhotonics/GaussPhotonics/RichG4PhotonicsGeomProp.h b/Sim/GaussPhotonics/GaussPhotonics/RichG4PhotonicsGeomProp.h
new file mode 100644
index 000000000..b0942fb4e
--- /dev/null
+++ b/Sim/GaussPhotonics/GaussPhotonics/RichG4PhotonicsGeomProp.h
@@ -0,0 +1,59 @@
+/*****************************************************************************\
+* (c) Copyright 2000-2020 CERN for the benefit of the LHCb Collaboration      *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                             *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+// Author SE 20-11-2021
+//
+#ifndef GAUSSPHOTONICS_RICHG4PHOTONICSGEOMPROP_H
+#define GAUSSPHOTONICS_RICHG4PHOTONICSGEOMPROP_H 1
+
+
+
+
+class RichG4PhotonicsGeomProp {
+
+ public:
+
+  RichG4PhotonicsGeomProp();
+
+  virtual ~RichG4PhotonicsGeomProp() = default;
+
+
+ int NumberOfRichDet() const {return m_NumberOfRichDet ;}
+ int NumberOfDetSectionsInRich1() const {return m_NumberOfDetSectionsInRich1; }
+ int NumberOfDetSectionsInRich2() const {return m_NumberOfDetSectionsInRich2; }
+ int NumberOfPixelsInPMT() const {return m_NumberOfPixelsInPMT; }
+ int NumberOfPixelColInPMT() const { return m_NumberOfPixelColInPMT; }
+ int NumberOfPixelRowInPMT() const { return m_NumberOfPixelRowInPMT; }
+ double MaxZHitInRich1Det() const {return  m_MaxZHitInRich1Det; }
+ double MaxZHitInRich2Det() const {return  m_MaxZHitInRich2Det; }
+ int  MaxNumberOfPMTsInRich1() {return m_MaxNumberOfPMTsInRich1; }
+ int  MaxNumberOfPMTsInRich2() {return m_MaxNumberOfPMTsInRich2; }
+ int  MaxNumberOfPMTsInRich() {return m_MaxNumberOfPMTsInRich; }
+
+
+ private:
+ 
+ int m_NumberOfRichDet;
+ int m_NumberOfDetSectionsInRich1;
+ int m_NumberOfDetSectionsInRich2;
+ int m_NumberOfPixelsInPMT;
+ int m_NumberOfPixelColInPMT;
+ int m_NumberOfPixelRowInPMT;
+ double  m_MaxZHitInRich1Det;
+ double  m_MaxZHitInRich2Det;
+ int  m_MaxNumberOfPMTsInRich1;
+ int  m_MaxNumberOfPMTsInRich2;
+ int  m_MaxNumberOfPMTsInRich;
+
+
+};
+
+
+#endif // GAUSSPHOTONICS_RICHG4PHOTONICSGEOMPROP_H 
diff --git a/Sim/GaussPhotonics/GaussPhotonics/RichMapmtPhotoElectricProc-test-h b/Sim/GaussPhotonics/GaussPhotonics/RichMapmtPhotoElectricProc-test-h
new file mode 100644
index 000000000..7115590a9
--- /dev/null
+++ b/Sim/GaussPhotonics/GaussPhotonics/RichMapmtPhotoElectricProc-test-h
@@ -0,0 +1,53 @@
+/*****************************************************************************\
+* (c) Copyright 2000-2020 CERN for the benefit of the LHCb Collaboration      *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                             *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+// Author SE 2021-10-15
+//
+//============================================================================
+#ifndef RichMapmtPhotoElectricProc_h
+#define RichMapmtPhotoElectricProc_h 1
+
+
+class RichMapmtPhotoElectric : public G4VProcess 
+{
+ public:
+  explicit RichMapmtPhotoElectric(const G4String processName = "RhMapmtPhotoElectric",
+				  G4ProcessType type = fOptical );
+  ~RichMapmtPhotoElectric();
+  
+G4bool IsApplicable (const G4ParticleDefinition&  ) override;
+// is Applicable for optical photons created within the two rich detectors only.
+G4double GetMeanFreePath(const G4Track&, G4double, G4ForceCondition * condition ) override ;
+   
+
+G4VParticleChange* PostStepDoIt(const G4Track& aTrack, const G4Step&  aStep) override;
+
+double getCurrentPmtQE( double photonenergy);
+// interpolate QE for a pmt
+
+
+void setPmtPhElectronKE(double PmtPhElecKE );
+
+void setPmtPhElecParam();
+
+RichPDProperties* pdProperty() {return RichPDProperties::getRichPDPropertiesInstance() ; }
+
+
+
+private:
+
+
+int m_PmtQwMatIndex;
+int m_PmtPhCathMatIndex;
+
+double m_PmtPhElectronKE;
+};
+#endif /*End of RichMapmtPhotoElectricProc_h */
+
diff --git a/Sim/GaussPhotonics/GaussPhotonics/RichPDProperties.h b/Sim/GaussPhotonics/GaussPhotonics/RichPDProperties.h
new file mode 100644
index 000000000..7b257f759
--- /dev/null
+++ b/Sim/GaussPhotonics/GaussPhotonics/RichPDProperties.h
@@ -0,0 +1,51 @@
+/*****************************************************************************\
+* (c) Copyright 2000-2020 CERN for the benefit of the LHCb Collaboration      *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                             *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+#ifndef GAUSSPHOTONICS_RichPDProperties_h
+#define GAUSSPHOTONICS_RichPDProperties_h 1
+
+#include <vector>
+#include <map>
+#include <string>
+#include "GaussPhotonics/RichPmtQuantEff.h"
+
+
+class RichPDProperties {
+
+ public:
+
+  virtual ~RichPDProperties();
+  static RichPDProperties* getRichPDPropertiesInstance();
+  void InitializePDProperties();
+  void FillPmtQEAtInit();
+  RichPmtQuantEff *  RichPmtQEList() {return m_RichPmtQEList ; }
+  double PmtNominalDetectionEffFactor() {return m_PmtNominalDetectionEffFactor ;}
+  double R1GasQWARCoatingFactor() {return m_R1GasQWARCoatingFactor; }
+
+ private:
+
+  RichPDProperties();
+  static  RichPDProperties*  RichPDPropertiesInstance;
+
+  RichPmtQuantEff* m_RichPmtQEList; //This may be made into an array for different pmts
+
+  double m_PmtMaxQuantumEff;
+  double m_MinPhotonEnergyInRICH;
+  double m_MaxPhotonEnergyInRICH;
+  bool m_UseNominalPmtQE;
+  int m_CurQETableSourceOption; // 0 is the nominal which is UV glass from 2020
+                                
+  double  m_Rich1MaxZHitCoord ;
+  double m_PmtNominalDetectionEffFactor;
+  double m_R1GasQWARCoatingFactor;  // to be removed after the AR coating is implemented
+};
+
+
+#endif //end of GAUSSPHOTONICS_RichPDProperties_h
diff --git a/Sim/GaussPhotonics/GaussPhotonics/RichPmtQuantEff.h b/Sim/GaussPhotonics/GaussPhotonics/RichPmtQuantEff.h
new file mode 100644
index 000000000..17d0f845b
--- /dev/null
+++ b/Sim/GaussPhotonics/GaussPhotonics/RichPmtQuantEff.h
@@ -0,0 +1,36 @@
+/*****************************************************************************\
+* (c) Copyright 2000-2020 CERN for the benefit of the LHCb Collaboration      *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                             *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+#ifndef RichPmtQuantEff_h
+#define RichPmtQuantEff_h 1
+
+#include <map>
+
+
+class RichPmtQuantEff{
+ public:
+  RichPmtQuantEff();
+
+  // RichPmtQuantEff(int pmtnum, int richdetnum); //This line may be activated for having a table per pmt.
+
+  virtual ~RichPmtQuantEff() {};
+  void SetPmtQeTab(std::map<double,double> aTab) {m_PmtQeTab = aTab ;}
+  double getPmtQEffFromPhotEnergy(double  photonenergy );
+  void UpdatePmtQETable(double aEn, double aQE);
+
+ private:
+
+  std::map<double,double> m_PmtQeTab;
+
+
+
+};
+
+#endif //end of RichPmtQuantEff_h
diff --git a/Sim/GaussPhotonics/python/GaussPhotonics/Configuration.py b/Sim/GaussPhotonics/python/GaussPhotonics/Configuration.py
new file mode 100644
index 000000000..87309aee0
--- /dev/null
+++ b/Sim/GaussPhotonics/python/GaussPhotonics/Configuration.py
@@ -0,0 +1,111 @@
+###############################################################################
+# (c) Copyright 2000-2020 CERN for the benefit of the LHCb Collaboration      #
+#                                                                             #
+# This software is distributed under the terms of the GNU General Public      #
+# Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   #
+#                                                                             #
+# In applying this licence, CERN does not waive the privileges and immunities #
+# granted to it by virtue of its status as an Intergovernmental Organization  #
+# or submit itself to any jurisdiction.                                       #
+###############################################################################
+"""
+Configuration tools for GaussPhotonics
+
+"""
+from Gaudi.Configuration import log, GaudiSequencer, FileCatalog
+from Gaudi.Configuration import ApplicationMgr
+from Configurables import LHCbConfigurableUser, LHCbApp, SimConf
+from Configurables import Gaussino
+from GaudiKernel import SystemOfUnits
+from Gaussino.Utilities import configure_edm_conversion
+
+class GaussPhotonicsConf(LHCbConfigurableUser):
+     
+    #steering options
+    __slots__ ={
+         "RichUpgradeDataYear"                   : "2022"
+        ,"ActivateCherenkovProcess"              : True
+        ,"UpgradeRichPmtDetectorExist"           : True
+        ,"SkipGeant4RichCkvFlag"                 : False 
+       }
+    def InitializeGaussPhotonicsConfiguration(self):
+        from Configurables import Gauss
+        Gauss=Gauss()
+
+        # print "Gauss run option selected for Upgraded RICH  =  ", Gauss.getProp("UpgradeRICHSimRunOption")
+        self.RichUpgradeDataYearConfig()
+        #print "Upgrade RICH simulation for the data in year = ", self.getProp("RichUpgradeDataYear")
+        #log.info( "Upgrade RICH simulation for the data in year =  %s" %(self.getProp("RichUpgradeDataYear")))
+        
+        #avoid annoying printouts with warnings about non-existent aerogel 
+        from Configurables import SimulationSvc 
+        SimulationSvc().SimulationDbLocation = "$GAUSSROOT/xml/SimulationRICHAerogelOff.xml"
+
+    def setUpgradeRichDetExistFlag(self,UpgradeRichPmtDetectorExistFlag=True):
+        self.setProp("UpgradeRichPmtDetectorExist", UpgradeRichPmtDetectorExistFlag)
+
+    def setSkipUpgradeGeant4Flag(self, SkipUpgradeGeant4=False):
+        self.setProp("SkipGeant4RichCkvFlag",  SkipUpgradeGeant4)
+
+
+    def ApplyGaussPhotonicsConfiguration(self, GiGa ):
+        #Actual implementation of upgrade RICH simulation configuration
+        
+        if ( not ( self.getProp("UpgradeRichPmtDetectorExist"))) :
+            self.setProp("ActivateCherenkovProcess",False)
+
+        if ( self.getProp("SkipGeant4RichCkvFlag")):
+            self.setProp("ActivateCherenkovProcess",False)
+
+        # RICH Cherenkov Processes 
+        self.PhotonicsProcessActivate(GiGa)       
+        #print "Upgrade RICH simulation now configured"
+        #log.info("Upgrade RICH simulation now configured")
+    def RichUpgradeDataYearConfig(self):
+        # for now unchanged.    
+        self.setProp("RichUpgradeDataYear", "2022")
+        
+    def PhotonicsProcessActivate(self,GiGa):
+            
+        GiGa.ModularPL.addTool( GiGaPhysConstructorOpPhotonics,name="GiGaPhysConstructorOpPhotonics" )
+        GiGa.ModularPL.addTool( GiGaPhysConstructorPhotonicsDetector ,name="GiGaPhysConstructorPhotonicsDetector" )
+        
+        if  (self.getProp("ActivateCherenkovProcess")):            
+            GiGa.ModularPL.GiGaPhysConstructorOpCkv.RichOpticalPhysicsProcessActivate = True
+            GiGa.ModularPL.GiGaPhysConstructorPhotoDetector.RichPmtPhysicsProcessActivate = True
+
+            
+            self.PhotonicsGeneralPhysProcessOptions(GiGa)
+            
+            #self.CkvScintillationSetup(GiGa)        
+            
+            #self.CkvRandomHitsSetup(GiGa) # kept as place holder 
+
+            #if (self.getProp("CkvRichExtendedinfoClasses")):
+            #    self.CkvExtendedInfoClassesSetup()    
+              
+            #if (self.getProp("CkvRichExtendedInfo")):
+            #    self.CkvExtendedInfoSetup(GiGa)
+
+            #self.CkvGeneralStepActionSetup(GiGa)
+            #self.CkvGeneralTrackActionSetup(GiGa)
+
+            #self.CkvAnalysisSetup(GiGa)
+
+        else:
+            
+            GiGa.ModularPL.GiGaPhysConstructorOpPhotonics.RichOpticalPhysicsProcessActivate = False
+            GiGa.ModularPL.GiGaPhysConstructorPhotonicsDetector.RichPmtPhysicsProcessActivate = False
+
+
+    def PhotonicsGeneralPhysProcessOptions(self,GiGa):
+        
+        # When RichApplyMaxNumCkvPhotPerStepPerRadiator is False, the global value
+        # as given by RichMaxNumPhotPerCherenkovStep is used for all radiators.
+        # Otherwise the individual value as listed below for each radiator is used 
+        GiGa.ModularPL.GiGaPhysConstructorOpCkv.RichApplyMaxNumCkvPhotPerStepPerRadiator=False
+        GiGa.ModularPL.GiGaPhysConstructorOpCkv.RichMaxPhotonsPerCherenkovStepInRich1Gas=40
+        GiGa.ModularPL.GiGaPhysConstructorOpCkv.RichMaxPhotonsPerCherenkovStepInRich2Gas=40
+        GiGa.ModularPL.GiGaPhysConstructorOpCkv.RichMaxNumPhotPerCherenkovStep=40
+
+
diff --git a/Sim/GaussPhotonics/src/PhotonicsAction/PhotonicsG4EventAction.cpp b/Sim/GaussPhotonics/src/PhotonicsAction/PhotonicsG4EventAction.cpp
new file mode 100644
index 000000000..aebf425cf
--- /dev/null
+++ b/Sim/GaussPhotonics/src/PhotonicsAction/PhotonicsG4EventAction.cpp
@@ -0,0 +1,88 @@
+#include <math.h>
+#include "Geant4/G4Event.hh"
+#include "Geant4/G4EventManager.hh"
+#include "Geant4/G4TrajectoryContainer.hh"
+#include "Geant4/G4Trajectory.hh"
+#include "Geant4/G4HCofThisEvent.hh"
+#include "Geant4/G4VHitsCollection.hh"
+#include "Geant4/G4SDManager.hh"
+
+#include "PhotonicsG4EventAction.h"
+
+//========================================================
+// Implementation file for class : PhotonicsG4EventAction
+//
+// 2021-01-31 : Sajan Easo
+//--------------------------------------------------------
+using namespace PhotonicsG4EventActionSpace ;
+using CLHEP::GeV;
+using CLHEP::mm;
+
+using PhotonicsG4EventActionFactory = PhotonicsG4EventActionSpace::PhotonicsG4EventActionFactory;
+DECLARE_COMPONENT_WITH_ID(PhotonicsG4EventActionFactory,"PhotonicsG4EventActionFactory")
+PhotonicsG4EventActionSpace::PhotonicsG4EventAction::PhotonicsG4EventAction( ):
+       m_NumRichColl(0)
+    ,   m_RichG4CollectionID(std::vector<int> (0) )
+    ,   m_RichCkvHitCName(0)
+    ,   m_PhotonicsG4HitRecon( new PhotonicsG4HitRecon())
+   {
+ 
+
+
+
+  if(!m_RichCkvHitCName) m_RichCkvHitCName=  new RichCkvG4HitCollName();
+  m_NumRichColl  =  m_RichCkvHitCName->RichHCSize();
+  m_RichG4CollectionID.assign(m_NumRichColl,-1);
+
+}
+//====================================================================//
+PhotonicsG4EventActionSpace::PhotonicsG4EventAction::~PhotonicsG4EventAction( ) {
+
+  if(m_PhotonicsG4HitRecon) delete(m_PhotonicsG4HitRecon);
+  if(m_RichCkvHitCName) delete(m_RichCkvHitCName);
+
+
+}
+
+//====================================================================//
+void PhotonicsG4EventActionSpace::PhotonicsG4EventAction::BeginOfEventAction ( const G4Event* ) {
+   
+
+  G4SDManager * SDman = G4SDManager::GetSDMpointer();
+  G4String colNam;
+  for (int icol=0; icol<m_NumRichColl; ++icol ) {
+    if(m_RichG4CollectionID[icol]<0){
+      colNam=  m_RichCkvHitCName->RichHCName(icol);
+      m_RichG4CollectionID[icol] = SDman->GetCollectionID(colNam);
+
+    }
+  }
+
+
+
+
+}
+//=====================================================================//
+void PhotonicsG4EventActionSpace::PhotonicsG4EventAction::EndOfEventAction   ( const G4Event* aEvent ) {
+
+  m_PhotonicsG4HitRecon->RichG4GetOccupancies(aEvent,m_NumRichColl, m_RichG4CollectionID);
+  
+
+}
+//=========================================================================================================//
+G4UserEventAction*  PhotonicsG4EventActionSpace::PhotonicsG4EventActionFactory::construct() const {
+
+  auto tmp = new PhotonicsG4EventAction( );
+  return tmp;
+}
+//=================================================================================================//
+StatusCode PhotonicsG4EventActionSpace::PhotonicsG4EventActionFactory::initialize() {
+  return StatusCode::SUCCESS;
+
+}
+//===============================================================================================//
+StatusCode PhotonicsG4EventActionSpace::PhotonicsG4EventActionFactory::finalize() {
+  return StatusCode::SUCCESS;
+
+}
+//==============================================================================================//
diff --git a/Sim/GaussPhotonics/src/PhotonicsAction/PhotonicsG4EventAction.h b/Sim/GaussPhotonics/src/PhotonicsAction/PhotonicsG4EventAction.h
new file mode 100644
index 000000000..66b80cafd
--- /dev/null
+++ b/Sim/GaussPhotonics/src/PhotonicsAction/PhotonicsG4EventAction.h
@@ -0,0 +1,76 @@
+/*****************************************************************************\
+* (c) Copyright 2000-2020 CERN for the benefit of the LHCb Collaboration      *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                             *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+
+#ifndef GaussPhotonics_PhotonicsG4EventAction_h
+#define GaussPhotonics_PhotonicsG4EventAction_h 1
+#pragma once
+/** @class PhotonicsG4EventAction PhotonicsG4EventAction.h src/PhotonicsAction/PhotoncisG4EventAction.h
+ *
+ *
+ *  @author Sajan Easo
+ *  @date   2022-01-31
+ */
+//================================================================================================//
+#include "Geant4/G4UserEventAction.hh"
+#include "Geant4/globals.hh"
+#include "Geant4/G4Step.hh"
+#include "Geant4/G4ParticleTable.hh"
+#include "Geant4/G4VProcess.hh"
+
+#include "GaudiAlg/GaudiTool.h"
+#include "GiGaMTCoreMessage/IGiGaMessage.h"
+#include "GiGaMTFactories/GiGaFactoryBase.h"
+#include "GiGaMTFactories/GiGaTool.h"
+
+#include "PhotonicsG4HitRecon.h"
+#include "GaussPhotonics/RichCkvG4HitCollName.h"
+
+
+//=======================================================================================//
+
+namespace PhotonicsG4EventActionSpace {
+  class PhotonicsG4EventAction: public G4UserEventAction, public GiGaMessage {
+  
+  public:
+    using G4UserEventAction::G4UserEventAction;
+    /// Standard constructor
+    PhotonicsG4EventAction();
+    ~ PhotonicsG4EventAction() ; //destructor
+    void BeginOfEventAction ( const G4Event* ) override;
+    void EndOfEventAction   ( const G4Event* ) override;
+    int NumRichColl() {return m_NumRichColl; }
+    int  RichG4CollectionID(int CollNum ) {return m_RichG4CollectionID[CollNum]; }
+    RichCkvG4HitCollName* RichCkvHitCName() {return m_RichCkvHitCName; }
+
+  private:
+
+    int m_NumRichColl;
+    std::vector<int> m_RichG4CollectionID;
+
+    RichCkvG4HitCollName* m_RichCkvHitCName;
+
+    PhotonicsG4HitRecon* m_PhotonicsG4HitRecon;
+
+  };
+
+  class PhotonicsG4EventActionFactory: public extends <GiGaTool, GiGaFactoryBase<G4UserEventAction> >
+  {
+  public:
+     using extends::extends;
+
+    StatusCode  initialize() override ;
+    StatusCode  finalize()   override ;
+    virtual G4UserEventAction *  construct() const override;
+  };
+
+}
+
+#endif  //GaussPhotonics_PhotonicsG4EventAction_h
diff --git a/Sim/GaussPhotonics/src/PhotonicsAnalysis/PhotonicsG4HitHistoSet5.cpp b/Sim/GaussPhotonics/src/PhotonicsAnalysis/PhotonicsG4HitHistoSet5.cpp
new file mode 100644
index 000000000..ed69980cd
--- /dev/null
+++ b/Sim/GaussPhotonics/src/PhotonicsAnalysis/PhotonicsG4HitHistoSet5.cpp
@@ -0,0 +1,245 @@
+/*****************************************************************************\
+* (c) Copyright 2000-2020 CERN for the benefit of the LHCb Collaboration      *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                             *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+//-----------------------------------------------------------------------------
+// Implementation file for class : PhotonicsG4HitHistoSet5
+//
+// 2022-01-31 : Sajan Easo
+//-----------------------------------------------------------------------------
+#include "PhotonicsG4HitHistoSet5.h"
+//#include "GaudiKernel/IHistogramSvc.h"
+// Histogramming
+//#include "AIDA/IHistogram1D.h"
+//#include "AIDA/IHistogram2D.h"
+#include "Geant4/globals.hh"
+//#include "GaudiKernel/Kernel.h"
+//#include "GaudiKernel/ISvcLocator.h"
+//#include "GaudiKernel/IDataProviderSvc.h"
+//#include "GaudiKernel/IMessageSvc.h"
+//#include "GaudiKernel/IHistogramSvc.h"
+//#include "GaudiKernel/Bootstrap.h"
+//#include "GaudiKernel/GaudiException.h"
+//#include "GaudiKernel/DataObject.h"
+//#include "GaudiKernel/MsgStream.h"
+//#include "GaudiKernel/SmartDataPtr.h"
+//#include "GaudiKernel/IValidity.h"
+//#include "GaudiKernel/Time.h"
+//#include "GaudiKernel/IRegistry.h"
+//#include "GaudiKernel/INTupleSvc.h"
+#include "GaussPhotonics/RichCkvG4Hit.h"
+// Gaudi
+#include "GaudiKernel/ITHistSvc.h"
+// Geant4
+#include "Geant4/G4Event.hh"
+#include "Geant4/G4EventManager.hh"
+#include "Geant4/G4TrajectoryContainer.hh"
+#include "Geant4/G4Trajectory.hh"
+#include "Geant4/G4HCofThisEvent.hh"
+#include "Geant4/G4VHitsCollection.hh"
+#include "Geant4/G4SDManager.hh"
+
+
+
+
+DECLARE_COMPONENT( PhotonicsG4HitHistoSet5 )
+
+
+//#include "GaussPhotonics/RichCkvG4SvcLocator.h"
+//=============================================================================//
+
+StatusCode PhotonicsG4HitHistoSet5::initialize() {
+  // if ( extends::initialize().isFailure() ) {
+  //  return StatusCode::FAILURE;
+  //  }
+
+ m_PhotonicsG4HistoPathSet5="RICHG4HistoSet5/";
+ // m_RichG4Set5HistoBooked=false;
+
+ // bookCherenkovG4HistogramSet5(); 
+
+  if(!m_RichCkvHitCName) m_RichCkvHitCName=  new RichCkvG4HitCollName();
+  m_NumRichColl  =  m_RichCkvHitCName->RichHCSize();
+  m_RichG4CollectionID.clear();
+  m_RichG4CollectionID.assign(m_NumRichColl,-1);
+  info()<< " HistoSet5 Num Rich Coll "<< m_NumRichColl  <<endmsg;
+
+ 
+ return StatusCode::SUCCESS;
+}
+//=============================================================================//
+StatusCode PhotonicsG4HitHistoSet5::monitor( const G4Event& aEvent ) {
+
+ G4HCofThisEvent* collections = aEvent.GetHCofThisEvent();
+ G4VHitsCollection* collect;
+  
+ int nHitTotRich1=0;
+ int nHitTotRich2=0;
+ int nHitTotRich2SmallPmt = 0;
+ int nHitTotRich2LargePmt = 0;
+
+ //info()<<" Now in  PhotonicsG4HitHistoSet5 monitor NumRichHitColl   " <<m_NumRichColl << endmsg;
+ // info()<<"HistoSet5 There are "<<collections->GetNumberOfCollections()<<endmsg;
+ for (int icol =0 ; icol < collections->GetNumberOfCollections() ; icol++) {
+   collect = collections->GetHC(icol);
+   // info()<<"HistoSet5 collectName "<< icol<<"  "<<collect->GetName()<<endmsg;
+   // info()<<"HistoSet5 collectSize "<<icol <<"  "<<(int) collect->GetSize()<<endmsg;
+   for (int ircol=0; ircol<m_NumRichColl; ++ircol ) {
+     // info()<< "HistoSet5 ircol  Name "<< ircol<<"   "<<m_RichCkvHitCName->RichHCName(ircol)<<endmsg;
+
+     if(collect->GetName().find(m_RichCkvHitCName->RichHCName(ircol)) !=  std::string::npos ) {
+       G4int nHitInCurColl = (G4int) collect->GetSize();
+
+       //info() <<"HistoSet5 CollOverall RichColl ColName NhitInCol "<<icol<<"  "
+       //       <<ircol<<"  "<<collect->GetName()<<"  "<< nHitInCurColl  <<endmsg;
+       if(ircol ==0 || ircol ==1 ) {
+           nHitTotRich1 +=   nHitInCurColl;
+       }else if ( (ircol >=2 )  && ( ircol <=5) ) {
+           nHitTotRich2 +=   nHitInCurColl;
+           if( ircol ==2 || ircol ==3 ) {
+             nHitTotRich2SmallPmt += nHitInCurColl;
+           }else if ( ircol ==4 || ircol ==5 ) {
+             nHitTotRich2LargePmt  += nHitInCurColl;
+	   }
+       }
+
+       for (G4int iha=0; iha<nHitInCurColl ; iha++ ) {
+	 RichCkvG4Hit * aHit =  dynamic_cast< RichCkvG4Hit * > (collect->GetHit(iha));
+
+	     const G4ThreeVector& aGlobalCoord =    aHit ->  GetGlobalPos();
+             if(  (ircol ==0) || (ircol ==1 ) ) {        
+	       //Rich1 hits
+                  if(aGlobalCoord.y() > 0.0 ){ 
+                         plot2D(aGlobalCoord.x(),aGlobalCoord.y(),m_PhotonicsG4HistoPathSet5+"R1XYTop",
+                                       "Global XY Hit coord: RICH1 Top",
+                                      	-600.0,600.0, 1200.0,1600.0,400,135);
+	           } else {
+                         plot2D(aGlobalCoord.x(),aGlobalCoord.y(),m_PhotonicsG4HistoPathSet5+"R1XYBottom",
+                                       "Global XY Hit coord: RICH1 Bottom",
+                                      	-600.0,600.0,-1600.0,-1200.0,400,135);
+
+		  }
+	     }else if ( (ircol >=2) && (ircol <= 5)   ) { 
+ 
+                  if(aGlobalCoord.x() > 0.0 ){ 
+                         plot2D(aGlobalCoord.x(),aGlobalCoord.y(),m_PhotonicsG4HistoPathSet5+"R2XYLeft",
+                                       "Global XY Hit coord: RICH2 Left",
+				3700.0,4100.0, -700.0,700.0,135,500);
+	           } else {
+                         plot2D(aGlobalCoord.x(),aGlobalCoord.y(),m_PhotonicsG4HistoPathSet5+"R2XYRight",
+                                       "Global XY Hit coord: RICH2 Right",
+                                      	-4100.0,-3700.0,-700.0,-700.0,135,500);
+
+		  }
+
+
+
+
+
+	     }
+		       
+       }
+
+     }
+       
+
+   }
+
+ }
+
+
+ //double x=5;
+ // double y=100.0; 
+ // double z = 200.0;
+ /*  
+ G4SDManager * SDman = G4SDManager::GetSDMpointer();
+  G4String colNam;
+  for (int icol=0; icol<m_NumRichColl; ++icol ) {
+    if(m_RichG4CollectionID[icol]<0){
+      colNam=  m_RichCkvHitCName->RichHCName(icol);
+       
+          m_RichG4CollectionID[icol] = SDman->GetCollectionID(colNam);
+
+      info()<<"HistoSet5 icol collection name collID "<<icol<<"  "<<colNam<<"   "
+            <<m_RichG4CollectionID[icol]<<endmsg;
+    }
+  }
+
+  G4HCofThisEvent * HCE;
+  G4int nHitTotRich1=0;
+  for (int ihcol=0; ihcol<m_NumRichColl; ++ihcol ) {
+    if(m_RichG4CollectionID[ihcol] >=0 ) {
+       HCE = aEvent.GetHCofThisEvent();
+       info()<<" HistoSet5 HCE ID"<< ihcol <<"  "<< HCE <<"   "<< m_RichG4CollectionID[ihcol]<<endmsg;
+       RichCkvG4HitsCollection* RHC=NULL;
+       if(HCE){
+           RHC = (RichCkvG4HitsCollection*)(HCE->GetHC(m_RichG4CollectionID[ihcol]));
+       }
+       info()<<" HistoSet5 RHC"<< ihcol <<"  "<<RHC<<endmsg;
+
+       if(RHC){
+          G4int nHitInCurColl = RHC->entries();
+          info()<<" HistoSet5 NumHitInCol "<<ihcol <<"   "<<nHitInCurColl<<endmsg;
+
+          if(ihcol == 0 || ihcol == 1 ) {         
+            nHitTotRich1 += nHitInCurColl;
+            for (G4int iha=0; iha<nHitInCurColl ; iha++ ) {
+              RichCkvG4Hit * aHit =  (*RHC)[iha];
+	      const G4ThreeVector& aGlobalCoord =    aHit ->  GetGlobalPos();         
+              plot2D(aGlobalCoord.x(),aGlobalCoord.y(),m_PhotonicsG4HistoPathSet5+"R1XY","Global XY Hit coord: RICH1",
+                                      	-400.0,400.0,-400.0,400.0,100,100);
+
+
+	    }
+
+	  }
+       }
+    }
+
+  }
+  
+
+ */
+
+ // info()<<"Number of Hits in Rich1 "<<nHitTotRich1<<endmsg;
+
+ // plot1D( (nHitTotRich1*1.0) , m_PhotonicsG4HistoPathSet5+"R1NH","Number of hits in RICH1",0.0,250.0,250);
+  plot1D( (nHitTotRich1*1.0) , m_PhotonicsG4HistoPathSet5+"R1NH","Number of hits in RICH1",0.0,200.0,100);
+  plot1D( (nHitTotRich1*1.0) , m_PhotonicsG4HistoPathSet5+"R1NHA","Number of hits in RICH1: pgun events",0.0,150.0,50);
+  plot1D( (nHitTotRich1*1.0) , m_PhotonicsG4HistoPathSet5+"R1NHB","Number of hits in RICH1: pgun events",0.0,200.0,50);
+  plot1D( (nHitTotRich2*1.0) , m_PhotonicsG4HistoPathSet5+"R2NH","Number of hits in RICH2",0.0,200.0,100);
+  plot1D( (nHitTotRich2*1.0) , m_PhotonicsG4HistoPathSet5+"R2NHA","Number of hits in RICH2: pgun events",0.0,150.0,50);
+  plot1D( (nHitTotRich2*1.0) , m_PhotonicsG4HistoPathSet5+"R2NHB","Number of hits in RICH2: pgun events",0.0,200.0,50);
+  plot1D( (nHitTotRich2SmallPmt*1.0) , m_PhotonicsG4HistoPathSet5+"R2NHA","Number of hits in RICH2 smallPmts: pgun events",0.0,150.0,50);
+  plot1D( (nHitTotRich2LargePmt*1.0) , m_PhotonicsG4HistoPathSet5+"R2NHA","Number of hits in RICH2 largePmts: pgun events",0.0,150.0,50);
+
+
+ // plot2D(y,z,m_PhotonicsG4HistoPathSet5+"R1XY","Global XY Hit coord: RICH1",
+ //	-400.0,400.0,-400.0,400.0,100,100);
+
+ return StatusCode::SUCCESS;
+}
+//=============================================================================//
+/*
+void PhotonicsG4HitHistoSet5::bookCherenkovG4HistogramSet5() {
+  //  IHistogramSvc* CurHistoSvc = RichCkvG4SvcLocator::RichG4HistoSvc();
+  info() <<" Now book histograms in PhotonicsG4HitHistoSet5 "<<endmsg;
+
+  std::string title;
+  title = "Number of hits per event in RICH1";
+  m_hNumHitRich1 = book(m_PhotonicsG4HistoPathSet5+"R1NH",title, 100,0.0,30.0);
+
+  title="Global XY Hit coord: RICH1";
+  m_hXYHitLocationRich1 = book(m_PhotonicsG4HistoPathSet5+"R1XY",title, 200,-400.0,400.0,200,-400.0,400.0);
+  m_RichG4Set5HistoBooked=true;
+
+}
+*/
+
+//=============================================================================//
diff --git a/Sim/GaussPhotonics/src/PhotonicsAnalysis/PhotonicsG4HitHistoSet5.h b/Sim/GaussPhotonics/src/PhotonicsAnalysis/PhotonicsG4HitHistoSet5.h
new file mode 100644
index 000000000..0def7cb1d
--- /dev/null
+++ b/Sim/GaussPhotonics/src/PhotonicsAnalysis/PhotonicsG4HitHistoSet5.h
@@ -0,0 +1,80 @@
+/*****************************************************************************\
+ * (c) Copyright 2000-2020 CERN for the benefit of the LHCb Collaboration      *
+ *                                                                             *
+ * This software is distributed under the terms of the GNU General Public      *
+ * Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+ *                                                                             *
+ * In applying this licence, CERN does not waive the privileges and immunities *
+ * granted to it by virtue of its status as an Intergovernmental Organization  *
+ * or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+// $Id: $
+#ifndef PHOTONICSANALYSIS_PHOTONICSG4HITHISTOSET5_H
+#define PHOTONICSANALYSIS_PHOTONICSG4HITHISTOSET5_H 1
+#pragma once
+ /*
+  * Histograms for G4 hit locations
+  *  @author Sajan Easo
+  *  @date   2022-01-31
+  */
+
+//#include "GaudiKernel/IHistogramSvc.h"
+// Gaudi
+#include "GaudiAlg/GaudiHistoTool.h"
+
+#include "SimInterfaces/IG4MonitoringTool.h"
+#include "AIDA/IHistogram1D.h"
+#include "AIDA/IHistogram2D.h"
+#include "GaussPhotonics/RichCkvG4HitCollName.h"
+
+
+// Forward declarations
+//class IHistogram1D;
+//class IHistogram2D;
+#include <string>
+
+//=============================================================//
+class PhotonicsG4HitHistoSet5 : public extends<GaudiHistoTool, IG4MonitoringTool> {
+  Gaudi::Property<std::string> m_calType{this, "richType"}; 
+
+ public:
+
+  using extends::extends;
+ /**  Initialize.
+   *   @return status code
+   */
+  virtual StatusCode initialize() override;
+
+
+  /**  Save the data output.
+   *   @param[in] aEvent Event with data to save.
+   *   @return status code
+   */
+  virtual StatusCode monitor(const G4Event& aEvent) override;
+
+
+  // void bookCherenkovG4HistogramSet5();
+
+  // IHistogram2D * hXYHitLocationRich1() {return m_hXYHitLocationRich1; }
+  // IHistogram1D * hNumHitRich1() {return m_hNumHitRich1; }
+  //bool  RichG4Set5HistoBooked() {return  m_RichG4Set5HistoBooked; }
+  
+ 
+ private:
+
+  //AIDA::IHistogram2D * m_hXYHitLocationRich1=nullptr;
+  // AIDA::IHistogram1D * m_hNumHitRich1=nullptr;
+
+  std::string m_PhotonicsG4HistoPathSet5;
+  // bool m_RichG4Set5HistoBooked;
+
+  int m_NumRichColl;
+  std::vector<int> m_RichG4CollectionID;
+
+  RichCkvG4HitCollName* m_RichCkvHitCName; 
+
+   
+
+};
+
+#endif //PHOTONICSANALYSIS_PHOTONICSG4HITHISTOSET5_H
diff --git a/Sim/GaussPhotonics/src/PhotonicsAnalysis/PhotonicsG4HitRecon.cpp b/Sim/GaussPhotonics/src/PhotonicsAnalysis/PhotonicsG4HitRecon.cpp
new file mode 100644
index 000000000..a646d5186
--- /dev/null
+++ b/Sim/GaussPhotonics/src/PhotonicsAnalysis/PhotonicsG4HitRecon.cpp
@@ -0,0 +1,27 @@
+/*****************************************************************************\
+* (c) Copyright 2000-2020 CERN for the benefit of the LHCb Collaboration      *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                             *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+// SE 2022-01-31
+//
+#include "PhotonicsG4HitRecon.h"
+//==============================================================================//
+PhotonicsG4HitRecon::PhotonicsG4HitRecon() {
+
+
+}
+//==============================================================================//
+void PhotonicsG4HitRecon::RichG4GetOccupancies(const G4Event* anEvent, int NumRichColl,
+					       const std::vector<int> & RichG4CollectionID) {
+
+  std::cout<<"Now in RichG4GetOccupancies "<<std::endl;
+
+
+}
+//================================================================================//
diff --git a/Sim/GaussPhotonics/src/PhotonicsAnalysis/PhotonicsG4HitRecon.h b/Sim/GaussPhotonics/src/PhotonicsAnalysis/PhotonicsG4HitRecon.h
new file mode 100644
index 000000000..f6cf13493
--- /dev/null
+++ b/Sim/GaussPhotonics/src/PhotonicsAnalysis/PhotonicsG4HitRecon.h
@@ -0,0 +1,36 @@
+/*****************************************************************************\
+* (c) Copyright 2000-2020 CERN for the benefit of the LHCb Collaboration      *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                             *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+#ifndef PHOTONICSANALYSIS_PHOTONICSG4HITRECON_H
+#define PHOTONICSANALYSIS_PHOTONICSG4HITRECON_H 1
+// SE 2022-01-31  
+//
+#include "Geant4/G4Event.hh"
+
+//#include "PhotonicsG4HitHistoSet5.h"
+
+
+class PhotonicsG4HitRecon {
+ public:
+  PhotonicsG4HitRecon();
+  virtual ~PhotonicsG4HitRecon()= default; //Destructor
+
+  void RichG4GetOccupancies(const G4Event* anEvent, int NumRichColl,
+			    const std::vector<int> & RichG4CollectionID);
+
+  //void SetPhotonicsG4HitHistoSet5(PhotonicsG4HitHistoSet5* aSet) {
+  //  m_PhotonicsG4HitHistoSet5 = aSet ; }
+
+ private:
+  //  PhotonicsG4HitHistoSet5* m_PhotonicsG4HitHistoSet5;
+
+};
+
+#endif // End of PHOTONICSANALYSIS_PHOTONICSG4HITRECON_H
diff --git a/Sim/GaussPhotonics/src/PhotonicsAnalysis/PhotonicsStepAnalysis10.cpp b/Sim/GaussPhotonics/src/PhotonicsAnalysis/PhotonicsStepAnalysis10.cpp
new file mode 100644
index 000000000..47d6cea05
--- /dev/null
+++ b/Sim/GaussPhotonics/src/PhotonicsAnalysis/PhotonicsStepAnalysis10.cpp
@@ -0,0 +1,119 @@
+/*****************************************************************************\
+* (c) Copyright 2000-2020 CERN for the benefit of the LHCb Collaboration      *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                             *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+// Include files 
+#include "Geant4/G4Track.hh"
+#include "Geant4/G4ParticleDefinition.hh"
+#include "Geant4/G4DynamicParticle.hh"
+#include "Geant4/G4Material.hh"
+#include "Geant4/G4OpticalPhoton.hh"
+#include "Geant4/G4VPhysicalVolume.hh"
+#include "Geant4/G4LogicalVolume.hh"
+#include "Geant4/G4TransportationManager.hh"
+#include "Geant4/G4Navigator.hh"
+#include "Geant4/G4ProcessManager.hh"
+
+// GiGa
+#include <math.h>
+#include "PhotonicsStepAnalysis10.h"
+
+//========================================================
+// Implementation file for class : PhotonicsStepAnalysis10
+//
+// 2021-09-15 : Sajan Easo
+//--------------------------------------------------------
+using namespace PhotonicsStepAnalysis10Space ;
+using CLHEP::GeV;
+using CLHEP::mm;
+
+using PhotonicsStepAnalysis10Factory = PhotonicsStepAnalysis10Space::PhotonicsStepAnalysis10Factory;
+DECLARE_COMPONENT_WITH_ID(PhotonicsStepAnalysis10Factory,"PhotonicsStepAnalysis10Factory")
+
+
+PhotonicsStepAnalysis10Space::PhotonicsStepAnalysis10::PhotonicsStepAnalysis10( ) {
+  m_PhotonicsStepAnalysis10UpstrLimitZ= -1000.0  * mm;
+  m_PhotonicsStepAnalysis10DnstrLimitZ = 15000.0 * mm;
+  m_PhotonicsStepAnalysis10LimitX = 5000.0 *mm;
+  m_PhotonicsStepAnalysis10LimitY = 4000.0 *mm;
+
+}
+void PhotonicsStepAnalysis10Space::PhotonicsStepAnalysis10::UserSteppingAction(const G4Step* aStep) { 
+  G4cout<<" Now in PhotonicsStepAnalysis10 StepAction "<<G4endl;
+
+  const G4Track *aTrack = aStep->GetTrack();
+  const G4DynamicParticle* aParticle=aTrack->GetDynamicParticle();
+  G4StepPoint* aPreStepPoint = aStep->GetPreStepPoint();
+  G4StepPoint* aPostStepPoint = aStep->GetPostStepPoint();
+  const G4double  aParticleKE= aParticle->GetKineticEnergy();
+  const G4ThreeVector & prePos=aPreStepPoint->GetPosition();
+  const G4ThreeVector & postPos=aPostStepPoint->GetPosition();
+  if( ( prePos.z() > m_PhotonicsStepAnalysis10UpstrLimitZ && 
+        prePos.z() < m_PhotonicsStepAnalysis10DnstrLimitZ && 
+        prePos.x() > -1.0* m_PhotonicsStepAnalysis10LimitX &&
+        prePos.x() <  m_PhotonicsStepAnalysis10LimitX &&
+        prePos.y() > -1.0* m_PhotonicsStepAnalysis10LimitY &&
+        prePos.y() <  m_PhotonicsStepAnalysis10LimitY 
+	)
+      && ( postPos.z()  > m_PhotonicsStepAnalysis10UpstrLimitZ && 
+           postPos.z() <  m_PhotonicsStepAnalysis10DnstrLimitZ &&
+           postPos.x() > -1.0* m_PhotonicsStepAnalysis10LimitX &&
+           postPos.x() <  m_PhotonicsStepAnalysis10LimitX &&
+           postPos.y() > -1.0* m_PhotonicsStepAnalysis10LimitY &&
+	   postPos.y() <  m_PhotonicsStepAnalysis10LimitY )
+      ){
+      if(   aParticleKE > 0.0 ) {
+
+       G4String  apPreVolName=  aPreStepPoint->
+                    GetPhysicalVolume()->GetLogicalVolume()->GetName();
+       G4String  apPostVolName=  aPostStepPoint->
+                    GetPhysicalVolume()->GetLogicalVolume()->GetName();
+       const G4Material* aMaterial        = aTrack -> GetMaterial();
+       G4String aMaterialName= aMaterial->GetName();
+       const G4ParticleDefinition* aParticleDef = aParticle->GetParticleDefinition();
+       
+       G4cout<<" PSA10 A  PDGCode Name Step PreVol PostVol Materal PrePos PostPos KE "<<
+	 aParticle->GetPDGcode()<<"  "<<aParticleDef->GetParticleName()<<"  "<<
+         apPreVolName<<"  "<<apPostVolName<<"  "<<aMaterialName<<"  "
+	   << prePos<<"   "<<postPos<<"  "<< aParticleKE << G4endl;
+
+       G4cout<<" PSA10 B Dir charge ID "<<aTrack->GetMomentumDirection()<<"  "<<aParticle->GetCharge()
+             <<"   "<< aTrack->GetTrackID()<<  G4endl;
+
+       aParticleDef ->GetProcessManager()->DumpInfo();
+       G4cout<<" PSA10 C End StepInfo "<<G4endl;
+
+
+
+    //if(aPostStepPoint->GetStepStatus() == fGeomBoundary ) {
+
+     //if(aParticle->GetDefinition() == G4OpticalPhoton::OpticalPhoton() ) {
+
+     // }
+
+      }  
+  }
+  // }
+
+}
+G4UserSteppingAction*  PhotonicsStepAnalysis10Space::PhotonicsStepAnalysis10Factory::construct() const {
+
+  auto tmp = new PhotonicsStepAnalysis10( );
+  return tmp;
+}
+StatusCode PhotonicsStepAnalysis10Space::PhotonicsStepAnalysis10Factory::initialize() {
+  return StatusCode::SUCCESS;
+
+}
+StatusCode PhotonicsStepAnalysis10Space::PhotonicsStepAnalysis10Factory::finalize() {
+  return StatusCode::SUCCESS;
+
+}
+
+
diff --git a/Sim/GaussPhotonics/src/PhotonicsAnalysis/PhotonicsStepAnalysis10.h b/Sim/GaussPhotonics/src/PhotonicsAnalysis/PhotonicsStepAnalysis10.h
new file mode 100644
index 000000000..453ed5c76
--- /dev/null
+++ b/Sim/GaussPhotonics/src/PhotonicsAnalysis/PhotonicsStepAnalysis10.h
@@ -0,0 +1,81 @@
+/*****************************************************************************\
+ * (c) Copyright 2000-2020 CERN for the benefit of the LHCb Collaboration      *
+ *                                                                             *
+ * This software is distributed under the terms of the GNU General Public      *
+ * Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+ *                                                                             *
+ * In applying this licence, CERN does not waive the privileges and immunities *
+ * granted to it by virtue of its status as an Intergovernmental Organization  *
+ * or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+// $Id: $
+#ifndef PHOTONICSANALYSIS_PHOTONICSSTEPANALYSIS10_H
+#define PHOTONICSANALYSIS_PHOTONICSSTEPANALYSIS10_H 1
+#pragma once
+
+#include "Geant4/G4UserSteppingAction.hh"
+#include "Geant4/globals.hh"
+#include "Geant4/G4Step.hh"
+#include "Geant4/G4ParticleTable.hh"
+#include "Geant4/G4VProcess.hh"
+
+
+#include "GaudiAlg/GaudiTool.h"
+#include "GiGaMTCoreMessage/IGiGaMessage.h"
+#include "GiGaMTFactories/GiGaFactoryBase.h"
+#include "GiGaMTFactories/GiGaTool.h"
+
+
+
+//class IHistogram1D;
+/** @class PhotonicsStepAnalysis10 PhotonicsStepAnalysis10.h PhotonicsAnalysis/PhotonicsStepAnalysis10.h
+*
+ *
+ *  @author Sajan Easo
+ *  @date   2021-09-15
+ */
+
+namespace PhotonicsStepAnalysis10Space {
+
+
+class PhotonicsStepAnalysis10: public G4UserSteppingAction, public GiGaMessage {
+
+public:
+  using G4UserSteppingAction::G4UserSteppingAction;
+
+  /// Standard constructor
+  //  PhotonicsStepAnalysis10( ) = default ;
+   PhotonicsStepAnalysis10( ) ;
+
+  ~PhotonicsStepAnalysis10( ) = default; ///< Destructor
+
+  void UserSteppingAction( const G4Step* aStep ) override;
+
+protected:
+
+private:
+  G4double m_PhotonicsStepAnalysis10UpstrLimitZ;
+  G4double m_PhotonicsStepAnalysis10DnstrLimitZ;
+  G4double m_PhotonicsStepAnalysis10LimitX;
+  G4double m_PhotonicsStepAnalysis10LimitY;
+
+
+
+};
+class PhotonicsStepAnalysis10Factory :public extends <GiGaTool , GiGaFactoryBase<G4UserSteppingAction> > {
+
+ public:
+  using extends::extends;
+
+  StatusCode  initialize() override ;
+  StatusCode  finalize()   override ;
+  virtual G4UserSteppingAction * construct() const override;
+  
+
+
+};
+ 
+}
+
+
+#endif //PHOTONICSANALYSIS_PHOTONICSSTEPANALYSIS10_H
diff --git a/Sim/GaussPhotonics/src/PhotonicsMisc/RichCkvG4HitCollName.cpp b/Sim/GaussPhotonics/src/PhotonicsMisc/RichCkvG4HitCollName.cpp
new file mode 100644
index 000000000..6fae3cf19
--- /dev/null
+++ b/Sim/GaussPhotonics/src/PhotonicsMisc/RichCkvG4HitCollName.cpp
@@ -0,0 +1,42 @@
+/*****************************************************************************\
+* (c) Copyright 2000-2020 CERN for the benefit of the LHCb Collaboration      *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                             *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+// Author  Sajan Easo   20-10-2021
+
+#include "GaussPhotonics/RichCkvG4HitCollName.h"
+
+
+RichCkvG4HitCollName::RichCkvG4HitCollName() {
+  m_NumberOfHCollectionInRICH=6;
+  m_NumberOfStdHCollectionInRICH=4;
+  m_NumberOfGrandHCollectionInRICH=2;
+  m_RichHCName.clear();
+  m_RichHCName.reserve(m_NumberOfHCollectionInRICH);
+  m_RichHCName.push_back("Rich1TopHC");
+  m_RichHCName.push_back("Rich1BotHC");
+  m_RichHCName.push_back("Rich2LeftHC");
+  m_RichHCName.push_back("Rich2RightHC");
+
+  m_RichHCName.push_back("Rich2LeftGrandHC");
+  m_RichHCName.push_back("Rich2RightGrandHC");
+
+  m_InitCollectListNumForOutput=0;
+  m_FinalCollectListNumForOutput=m_NumberOfHCollectionInRICH-1; 
+  m_InitCollectListNumForStdPmtOutput=0;
+  m_FinalCollectListNumForStdPmtOutput=3;
+  m_InitCollectListNumForGrandPmtOutput=4;
+  m_FinalCollectListNumForGrandPmtOutput=5;
+  UseGrandPmtFlag(true);
+ 
+
+}
+
+
+RichCkvG4HitCollName::~RichCkvG4HitCollName() {  }
diff --git a/Sim/GaussPhotonics/src/PhotonicsMisc/RichCkvG4SvcLocator.cpp b/Sim/GaussPhotonics/src/PhotonicsMisc/RichCkvG4SvcLocator.cpp
new file mode 100755
index 000000000..50bebfa5b
--- /dev/null
+++ b/Sim/GaussPhotonics/src/PhotonicsMisc/RichCkvG4SvcLocator.cpp
@@ -0,0 +1,152 @@
+/*****************************************************************************\
+* (c) Copyright 2000-2020 CERN for the benefit of the LHCb Collaboration      *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                             *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+#include <string> 
+#include <stdio.h>
+// GaudiKernel includes 
+#include "GaudiKernel/Kernel.h"
+#include "GaudiKernel/ISvcLocator.h"
+#include "GaudiKernel/IDataProviderSvc.h"
+#include "GaudiKernel/IMessageSvc.h"
+#include "GaudiKernel/IHistogramSvc.h"
+#include "GaudiKernel/Bootstrap.h" 
+#include "GaudiKernel/GaudiException.h" 
+#include "GaudiKernel/DataObject.h"
+#include "GaudiKernel/MsgStream.h"
+#include "GaudiKernel/SmartDataPtr.h"
+#include "GaudiKernel/IValidity.h"
+#include "GaudiKernel/Time.h"
+#include "GaudiKernel/IRegistry.h"
+#include "GaudiKernel/INTupleSvc.h"
+
+//local
+#include "GaussPhotonics/RichCkvG4SvcLocator.h"
+
+IDataProviderSvc* RichCkvG4SvcLocator::RichG4detSvc()
+{ 
+  static IDataProviderSvc* a_detSvc = 0 ;
+
+    /// locate te service 
+  if( 0 == a_detSvc ) 
+    {
+      ISvcLocator* svcLoc = Gaudi::svcLocator();
+      if( 0 == svcLoc ) 
+        { throw GaudiException("RichCkvG4Svclocator::ISvcLocator* points to NULL!",
+                               "*RichG4Exception*" , 
+                               StatusCode::FAILURE  ); }
+      StatusCode sc = 
+        svcLoc->service(RichCkvG4SvcLocator::a_RichG4DataSvcName , a_detSvc, true );
+      if( sc.isFailure() ) 
+        { throw GaudiException("RichCkvG4SvcLocator::Could not locate IDataProviderSvc='" 
+                               + RichCkvG4SvcLocator::a_RichG4DataSvcName + "'",
+                               "*RichG4Exception*" , 
+                               StatusCode::FAILURE); }
+      if( 0 == a_detSvc ) 
+        { throw GaudiException("RichCkvG4SvcLocator::IDataProviderSvc*(" 
+                               +  RichCkvG4SvcLocator::a_RichG4DataSvcName + 
+                               "') points to NULL!" ,
+                               "*RichG4Exception*" , 
+                               StatusCode::FAILURE  ); }
+      a_detSvc->addRef();
+    }
+  ///
+  return a_detSvc ;
+}
+
+IMessageSvc* RichCkvG4SvcLocator::RichG4MsgSvc ()
+{
+  static IMessageSvc* a_msgSvc = 0 ;
+  //  locate the service 
+  if( 0 == a_msgSvc ) 
+    {
+      ISvcLocator* svcLoc = Gaudi::svcLocator();
+      if( 0 == svcLoc ) 
+        { throw GaudiException("RichCkvG4SvcLocator::ISvcLocator* points to NULL!",
+                               "*RichG4Exception*" , 
+                               StatusCode::FAILURE  ); }
+      StatusCode sc = 
+        svcLoc->service( RichCkvG4SvcLocator::a_RichG4MessageSvcName , a_msgSvc, true );
+      if( sc.isFailure() ) 
+        { throw GaudiException("RichCkvG4SvcLocator::Could not locate IMessageSvc='" 
+                               + RichCkvG4SvcLocator::a_RichG4MessageSvcName  + "'",
+                               "*RichG4Exception*" , 
+                               StatusCode::FAILURE); }
+      if( 0 == a_msgSvc ) 
+        { throw GaudiException("RichCkvG4SvcLocator::IMessageSvc*(" 
+                               +RichCkvG4SvcLocator::a_RichG4MessageSvcName + 
+                               "') points to NULL!" ,
+                               "*DetDescException*" , 
+                               StatusCode::FAILURE  ); }
+      a_msgSvc->addRef();
+    }
+  ///
+  return a_msgSvc ;
+}
+
+IHistogramSvc*   RichCkvG4SvcLocator::RichG4HistoSvc()
+{
+  static IHistogramSvc* a_HistoSvc = 0 ;
+  //  locate the service 
+  if( 0 == a_HistoSvc ) 
+    {
+      ISvcLocator* svcLoc = Gaudi::svcLocator();
+      if( 0 == svcLoc ) 
+        { throw GaudiException("RichCkvG4SvcLocator::ISvcLocator* points to NULL!",
+                               "*RichG4Exception*" , 
+                               StatusCode::FAILURE  ); }
+      StatusCode sc = 
+        svcLoc->service( RichCkvG4SvcLocator::a_RichG4HistoSvcName , a_HistoSvc,true  );
+      if( sc.isFailure() ) 
+        { throw GaudiException("RichCkvG4SvcLocator::Could not locate IHistogramSvc='" 
+                               + RichCkvG4SvcLocator::a_RichG4HistoSvcName  + "'",
+                               "*RichG4Exception*" , 
+                               StatusCode::FAILURE); }
+      if( 0 == a_HistoSvc ) 
+        { throw GaudiException("RichCkvG4SvcLocator::IHistogramSvc*(" 
+                               +RichCkvG4SvcLocator::a_RichG4HistoSvcName + 
+                               "') points to NULL!" ,
+                               "*DetDescException*" , 
+                               StatusCode::FAILURE  ); }
+      a_HistoSvc->addRef();
+    }
+  ///
+  return a_HistoSvc ;
+}
+
+
+INTupleSvc*   RichCkvG4SvcLocator::RichG4NtupleSvc()
+{
+  static INTupleSvc* a_NtupleSvc = 0 ;
+  //  locate the service 
+  if( 0 == a_NtupleSvc ) 
+    {
+      ISvcLocator* svcLoc = Gaudi::svcLocator();
+      if( 0 == svcLoc ) 
+        { throw GaudiException("RichCkvG4SvcLocator::ISvcLocator* points to NULL!",
+                               "*RichG4Exception*" , 
+                               StatusCode::FAILURE  ); }
+      StatusCode sc = 
+        svcLoc->service( RichCkvG4SvcLocator::a_RichG4NtupSvcName , a_NtupleSvc,true  );
+      if( sc.isFailure() ) 
+        { throw GaudiException("RichCkvG4SvcLocator::Could not locate INtupleSvc='" 
+                               + RichCkvG4SvcLocator::a_RichG4NtupSvcName  + "'",
+                               "*RichG4Exception*" , 
+                               StatusCode::FAILURE); }
+      if( 0 == a_NtupleSvc ) 
+        { throw GaudiException("RichCkvG4SvcLocator::INtupleSvc*(" 
+                               +RichCkvG4SvcLocator::a_RichG4NtupSvcName + 
+                               "') points to NULL!" ,
+                               "*DetDescException*" , 
+                               StatusCode::FAILURE  ); }
+      a_NtupleSvc->addRef();
+    }
+  ///
+  return a_NtupleSvc ;
+}
diff --git a/Sim/GaussPhotonics/src/PhotonicsMisc/RichG4PhotonicsCkvProdTag.cpp b/Sim/GaussPhotonics/src/PhotonicsMisc/RichG4PhotonicsCkvProdTag.cpp
new file mode 100644
index 000000000..497957bfa
--- /dev/null
+++ b/Sim/GaussPhotonics/src/PhotonicsMisc/RichG4PhotonicsCkvProdTag.cpp
@@ -0,0 +1,24 @@
+/*
+#include "GaussTools/GaussTrackInformation.h"
+#include "GaussRICH/RichInfo.h"
+#include "GaussRICH/RichPhotInfo.h"
+#include "GaussRICH/RichG4AnalysisConstGauss.h"
+#include "GaussRICH/RichG4GaussPathNames.h"
+#include "GaussRICH/RichG4MatRadIdentifier.h"
+#include <math.h>
+#include "Geant4/G4ThreeVector.hh"
+#include "Geant4/G4ParticleDefinition.hh"
+#include "Geant4/G4DynamicParticle.hh"
+*/
+#include "GaussPhotonics/RichG4PhotonicsCkvProdTag.h"
+
+G4Track* RichG4PhotonicsCkvProdTag(const G4Track& aChTrack,
+                                    G4Track* aCkvPhotTrack,
+                                    const G4double  CkvCosTheta,
+                                    const G4double CkvPhi,
+                                    const G4double CkvPhotEnergy,
+                                    const G4bool aVerboseTagFlag ,
+                                    const G4int aPhotoProdTag)
+{ 
+  return aCkvPhotTrack;
+}
diff --git a/Sim/GaussPhotonics/src/PhotonicsPhysPDet/RichMapmtPhotoElectricProc-test-cpp b/Sim/GaussPhotonics/src/PhotonicsPhysPDet/RichMapmtPhotoElectricProc-test-cpp
new file mode 100644
index 000000000..15a91b4f7
--- /dev/null
+++ b/Sim/GaussPhotonics/src/PhotonicsPhysPDet/RichMapmtPhotoElectricProc-test-cpp
@@ -0,0 +1,34 @@
+/*****************************************************************************\
+* (c) Copyright 2000-2020 CERN for the benefit of the LHCb Collaboration      *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                             *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+// include files
+#include "GaussPhotonics/RichPDProperties.h"
+
+//=======================================================================
+// Implementation file for class : RichMapmtPhotoElectricProc
+//
+// 2021-10-15 : Sajan Easo
+//-----------------------------------------------------------------------
+
+RichPmtPhotoElectricEffect::RichPmtPhotoElectricEffect(const G4String& processName, G4ProcessType type) 
+  :G4VProcess(processName, type)
+ {
+
+
+
+}
+RichPmtPhotoElectricEffect::~RichPmtPhotoElectricEffect() { }
+
+void RichPmtPhotoElectricEffect::setPmtPhElecParam() {
+
+  RichPmtProperties* aPmtProperty = pdProperty();
+    
+
+}
diff --git a/Sim/GaussPhotonics/src/PhotonicsPhysPDet/RichPDProperties.cpp b/Sim/GaussPhotonics/src/PhotonicsPhysPDet/RichPDProperties.cpp
new file mode 100644
index 000000000..1f7e4b9af
--- /dev/null
+++ b/Sim/GaussPhotonics/src/PhotonicsPhysPDet/RichPDProperties.cpp
@@ -0,0 +1,83 @@
+/*****************************************************************************\
+* (c) Copyright 2000-2020 CERN for the benefit of the LHCb Collaboration      *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                             *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+// Include files
+#include "GaussPhotonics/RichPDProperties.h"
+#include "DD4hep/DetectorData.h"
+#include "XML/Utilities.h"
+#include "DD4hep/DD4hepUnits.h"
+#include "CLHEP/Units/SystemOfUnits.h"
+#include "Detector/Rich1/RichMatOPD.h"
+#include "Detector/Rich1/RichDD4HepAccessUtil.h"
+
+
+//======================================================================================//
+RichPDProperties* RichPDProperties::RichPDPropertiesInstance =0;
+
+RichPDProperties::RichPDProperties(){ 
+  InitializePDProperties();
+
+}
+//=======================================================================================//
+void  RichPDProperties::InitializePDProperties() {
+
+   m_PmtMaxQuantumEff      = dd4hep::_toDouble("RhMapmtMaxQuantumEff"  );
+   m_MinPhotonEnergyInRICH = dd4hep::_toDouble("PhotonMinEnergyInRICH");
+   m_MaxPhotonEnergyInRICH = dd4hep::_toDouble( "PhotonMaxEnergyInRICH" );
+   m_UseNominalPmtQE       = true;   // This may be changed using options file in the future.
+   m_CurQETableSourceOption = 0;     // This may be changed using options file in the future.
+   m_Rich1MaxZHitCoord      = (dd4hep::_toDouble("RhZBeyondDownstreamOfRich1" ) )/(dd4hep::mm);
+   m_PmtNominalDetectionEffFactor = dd4hep::_toDouble("PMTSiHitDetectionEff");
+   m_R1GasQWARCoatingFactor = dd4hep::_toDouble("Rich1GasQWARCoatingEfficiencyFactor");  
+                                        // calculated from ad-hoc calculation until
+                                       // AR coating( anti reflection coating)  implementation is available.
+   // m_R1GasQWARCoatingFactor = 1.0308;  // Now getting this DB.
+
+   m_RichPmtQEList = new  RichPmtQuantEff();
+
+
+   FillPmtQEAtInit();
+
+}
+//=====================================================================================//
+void RichPDProperties::FillPmtQEAtInit() {
+
+RichMatOPD* aRichMatOpd = RichMatOPD::getRichMatOPDInstance();
+RichDD4HepAccessUtil* aRichDD4HepAccessUtil = RichDD4HepAccessUtil::getRichDD4HepAccessUtilInstance();
+
+std::string aQeTabName = aRichMatOpd->GetQEGeneralTableName( RichMatPropType::pmtQE, RichMatQE::qePmtNominal );
+std::map<double, double> aQeTab = aRichMatOpd-> GetARichGeneralGDMLMatrix(aRichDD4HepAccessUtil->GetGDMLTable(aQeTabName) );
+// Now convert units to those used in Geant4
+
+for ( std::map<double, double>::const_iterator itq= aQeTab.begin(); itq !=aQeTab.end(); ++itq ) {
+  // The following does not work, although advertised in the dd4hep user guide.
+  // Hence replaced by the line after.
+  // double aEnValH = (itq->first) / (CLHEP::MeV);  //convert from GeV in dde4hep to MeV used in Geant4.
+  double aEnValH = (itq->first) / (dd4hep::MeV);  //convert from GeV in dd4hep to MeV used in Geant4.
+  double aQeValH = (itq->second)/100.0 ;   // convert from percentage to absolute fraction
+
+  std::cout<< "RichPDProp eNVal QE "<< aEnValH<<"   "<<aQeValH<<std::endl;
+
+  m_RichPmtQEList->UpdatePmtQETable(aEnValH,aQeValH );
+
+ } 
+
+}
+//=====================================================================================//
+RichPDProperties* RichPDProperties::getRichPDPropertiesInstance() {
+  if (RichPDPropertiesInstance == 0 ) {
+    RichPDPropertiesInstance = new RichPDProperties();
+  }
+
+  return RichPDPropertiesInstance ;
+}
+//==========================================================
+RichPDProperties::~RichPDProperties() {}
+//===================================================
diff --git a/Sim/GaussPhotonics/src/PhotonicsPhysPDet/RichPmtQuantEff.cpp b/Sim/GaussPhotonics/src/PhotonicsPhysPDet/RichPmtQuantEff.cpp
new file mode 100644
index 000000000..d3d8819f5
--- /dev/null
+++ b/Sim/GaussPhotonics/src/PhotonicsPhysPDet/RichPmtQuantEff.cpp
@@ -0,0 +1,46 @@
+/*****************************************************************************\
+* (c) Copyright 2000-2020 CERN for the benefit of the LHCb Collaboration      *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                             *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+
+#include "GaussPhotonics/RichPmtQuantEff.h"
+#include "Geant4/G4ios.hh"
+
+RichPmtQuantEff::RichPmtQuantEff():m_PmtQeTab(std::map<double,double>() ) { }
+
+
+void RichPmtQuantEff::UpdatePmtQETable(double aEn, double aQE) {
+
+  m_PmtQeTab.insert({aEn,aQE } );
+
+}
+
+double RichPmtQuantEff::getPmtQEffFromPhotEnergy(double  photonenergy ){
+
+  //if the energy is between 2 bins, interpolate.
+  // assumes that energies are stored in increasing order in the class.
+  // this means in the db they should be in the increasing order.
+  //G4cout<< " RichPmtQuantEff photonE "<< photonenergy <<G4endl;
+
+    typedef std::map<double,double>::const_iterator i_t;
+
+    i_t i = m_PmtQeTab.upper_bound(photonenergy);
+    if(i == m_PmtQeTab.end() ) {
+      return (--i)->second;
+    }
+    if(i == m_PmtQeTab.begin() ) {
+      return i->second;
+    }
+    i_t k = i; 
+    --k;
+    const double delta = ((i->first) != (k->first)) ? ( photonenergy - (k->first) )/((i->first) - (k->first) ) : 0;
+
+    return (delta * (i->second) + (1-delta)* (k->second)) ;
+  
+}
diff --git a/Sim/GaussPhotonics/src/PhotonicsPhysProcess/GaussCkvOpticalPhysicsList.cpp b/Sim/GaussPhotonics/src/PhotonicsPhysProcess/GaussCkvOpticalPhysicsList.cpp
new file mode 100644
index 000000000..98a459808
--- /dev/null
+++ b/Sim/GaussPhotonics/src/PhotonicsPhysProcess/GaussCkvOpticalPhysicsList.cpp
@@ -0,0 +1,156 @@
+/*****************************************************************************\
+* (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration      *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                             *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+
+
+#include "GaudiKernel/MsgStream.h"
+//G4
+
+#include "Geant4/G4VPhysicsConstructor.hh"
+#include "Geant4/globals.hh"
+#include "Geant4/G4ParticleTypes.hh"
+#include "Geant4/G4ParticleDefinition.hh"
+#include "Geant4/G4ParticleWithCuts.hh"
+#include "Geant4/G4ProcessManager.hh"
+#include "Geant4/G4ProcessVector.hh"
+#include "Geant4/G4VProcess.hh"
+#include "Geant4/G4ParticleTable.hh"
+#include "Geant4/G4Material.hh"
+#include "Geant4/G4Decay.hh"
+#include "Geant4/G4MaterialTable.hh"
+
+#include "GaussPhotonics/GaussCkvOpticalPhysicsList.h"
+#include "GaussPhotonics/RhCkvG4Cerenkov.h"
+#include "GaussPhotonics/RhCkvG4OpBoundaryProcess.h"
+
+
+#include "Geant4/G4PhysicsConstructorFactory.hh"
+G4_DECLARE_PHYSCONSTR_FACTORY(GaussCkvOpticalPhysicsList);
+
+
+#include "GaussPhotonics/GaussCkvPhysics.h"
+
+//DECLARE_COMPONENT( GaussCkvOpticalPhysicsList )
+
+
+using CLHEP::GeV;
+using CLHEP::mm;
+//==============================================================================//
+GaussCkvOpticalPhysicsList::GaussCkvOpticalPhysicsList()
+  :G4VPhysicsConstructor("GaussCkvOpticalPhysicsList"),
+   m_ActivateRICHOpticalPhysProc(true),
+   m_MaxPhotonsPerRichCherenkovStep(40),
+   m_RichActivateVerboseProcessInfoTag(false),
+   m_CherenkovAddBackgrRich2(false),
+   m_CherenkovRich2BackgrProbFactor(0.5)
+   //m_MaxPhotonsPerRichCherenkovStepInRich1Gas(40),
+   //m_MaxPhotonsPerRichCherenkovStepInRich2Gas(40),
+   //m_MaxPhotonsPerRichCherenkovStepInRichQuartzLikeRadiator(5000),
+{
+  std::cout<<" Testing constructor of GaussCkvOpticalPhysicsList "<<std::endl;
+  
+
+  //declareProperty("RichOpticalPhysicsProcessActivate", m_ActivateRICHOpticalPhysProc);
+
+  //std::cout<<" GaussCkvOpticalPhysicsList Properties declared "<<std::endl;
+
+}
+
+//==============================================================================//
+
+void GaussCkvOpticalPhysicsList::ConstructParticle() { }
+//==============================================================================//
+void GaussCkvOpticalPhysicsList::ConstructProcess() {
+  // MsgStream msg(msgSvc(), name());
+  G4cout <<"RICH Optical Process activation status "<< m_ActivateRICHOpticalPhysProc<<G4endl;
+
+   if(m_ActivateRICHOpticalPhysProc) ConstructOpProc() ;
+
+}
+//==============================================================================//
+void GaussCkvOpticalPhysicsList::ConstructOpProc() {
+  // MsgStream msg(msgSvc(), name());
+  // RhCkvG4Cerenkov * theCerenkovProcess = new RhCkvG4Cerenkov("RhCkvG4Cerenkov",fElectromagnetic);
+  RhCkvG4Cerenkov * theCerenkovProcess = new RhCkvG4Cerenkov();
+
+  G4cout <<" RhCkvG4Cerenkov proc created "<< G4endl;
+
+  theCerenkovProcess->SetVerboseLevel(0);
+  theCerenkovProcess->SetMaxNumPhotonsPerStep((G4int) m_MaxPhotonsPerRichCherenkovStep);
+  theCerenkovProcess->SetTrackSecondariesFirst(false);
+  //LHCb specific 
+  theCerenkovProcess->SetRichVerboseInfoTag( (G4bool) m_RichActivateVerboseProcessInfoTag);
+  // The following for activating later.
+  //theCerenkovProcess->SetMaxPhotonPerRadiatorFlag((G4bool) m_ApplyMaxPhotCkvLimitPerRadiator);
+  theCerenkovProcess -> setAddBackGrRich2((G4bool) m_CherenkovAddBackgrRich2);
+  theCerenkovProcess -> setRich2BackgrProb((G4double) m_CherenkovRich2BackgrProbFactor);
+  theCerenkovProcess -> printBackgrRich2Param();
+  //theCerenkovProcess ->setActivateRichG4CherenkovAnalysis(false);
+
+  RhCkvG4OpBoundaryProcess * theBoundaryProcess = 
+    new  RhCkvG4OpBoundaryProcess("RhCkvG4OpBoundary", fOptical );
+  theBoundaryProcess -> SetVerboseLevel(0);
+
+
+  G4ProcessManager* photManager = G4OpticalPhoton::OpticalPhoton()->GetProcessManager();
+  if (!photManager) {
+     G4ExceptionDescription ed;
+     ed << "Optical Photon without a Process Manager";
+     G4Exception("G4OpticalPhysics::ConstructProcess()","",
+                  FatalException,ed);
+     return;
+  }
+  photManager->AddDiscreteProcess(theBoundaryProcess);
+  photManager->SetProcessOrderingToLast(theBoundaryProcess,idxPostStep);
+
+
+  auto theParticleIterator = GetParticleIterator();
+  theParticleIterator->reset();
+
+  while( (*theParticleIterator)() ){
+    G4ParticleDefinition* particle = theParticleIterator->value();
+    // Avoid the cherenkov and scintillation process for the photoelectron.
+    G4String particleName = particle->GetParticleName();
+
+    if(particleName != "pe-" )
+      {
+
+        G4ProcessManager* pmanager = particle->GetProcessManager();
+        if (theCerenkovProcess->IsApplicable(*particle)) 
+          {
+            pmanager->AddProcess(theCerenkovProcess);
+            pmanager->SetProcessOrdering(theCerenkovProcess,idxPostStep);
+
+
+	    G4cout <<"Activated Cherenkov Process in the proc manager   "<< particleName << G4endl;
+
+
+          }
+
+        //if(   m_activateRICHCF4Scintillation ) {
+          
+	//   if(theRichScintillationProcess->IsApplicable(*particle)){
+
+        //      pmanager->AddProcess(theRichScintillationProcess);
+        //      pmanager->SetProcessOrderingToLast(theRichScintillationProcess, idxAtRest);
+        //      pmanager->SetProcessOrderingToLast(theRichScintillationProcess, idxPostStep);
+
+	//         }
+	// }
+        
+        
+      }
+
+  } // end particle iterator loop
+
+
+
+}
+//==============================================================================//
diff --git a/Sim/GaussPhotonics/src/PhotonicsSensDet/RhCkvGrandSensDet.cpp b/Sim/GaussPhotonics/src/PhotonicsSensDet/RhCkvGrandSensDet.cpp
new file mode 100644
index 000000000..c3146badc
--- /dev/null
+++ b/Sim/GaussPhotonics/src/PhotonicsSensDet/RhCkvGrandSensDet.cpp
@@ -0,0 +1,116 @@
+/*****************************************************************************\
+* (c) Copyright 2000-2020 CERN for the benefit of the LHCb Collaboration      *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                              *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+// Author  Sajan Easo   20-10-2021
+// Geant4
+#include "Geant4/G4Step.hh"
+#include "Geant4/G4TouchableHistory.hh"
+#include "Geant4/G4HCofThisEvent.hh"
+#include "Geant4/G4SDManager.hh"
+#include "Geant4/G4TransportationManager.hh"
+#include "Geant4/G4Track.hh"
+#include "Geant4/G4VPhysicalVolume.hh"
+#include "Geant4/G4ios.hh"
+
+
+#include "GaussPhotonics/RichCkvGrandSensDet.h"
+#include "GaussPhotonics/RichCkvG4Hit.h"
+#include "GaussPhotonics/RichCkvCommonSensDet.h"
+
+//=======================================================================================//
+RichCkvGrandSensDet::RichCkvGrandSensDet(const std::string& name )
+  :G4VSensitiveDetector(name) ,
+   m_RichGrandPmtAviodDuplicateHitsActivate(false),
+  m_RichGrandPmtFlagDuplicateHitsActivate(false),
+  m_GrPmtBegin(-1) {
+
+  // G4cout<<" Now create RichGrandStdSensDet with "<< name <<std::endl;
+  initialize();
+
+
+}
+
+//============================================================================//
+bool RichCkvGrandSensDet::ProcessHits(G4Step* aStep, G4TouchableHistory* history) {
+
+  RichCkvCommonSensDet* aCkvCommonSensDet =  RichCkvCommonSensDet::getRichCkvCommonSensDetInstance();
+  bool SC = aCkvCommonSensDet->ProcessRichPmtHits(aStep,history );
+  if(SC) {
+  RichCkvG4Hit * anewHit = aCkvCommonSensDet->  newHit();
+  G4int curCollSet = GetCurRichGrandCollSet ( anewHit->GetCurSectorNum());
+  if( curCollSet >= 0 ) {
+  
+     int NumHitsInCurHC =m_RichHC[curCollSet- m_GrPmtBegin] ->insert( anewHit );  
+
+     //Verbose Print
+     //G4cout<<" RichCKV GrandSensDet Hit stored in RichDetNum CollSet NumHitsTally    "
+     //	   <<anewHit -> GetCurRichDetNum() <<"  "<< curCollSet <<"   "<<NumHitsInCurHC<<G4endl;
+
+
+  }
+  }
+  return SC;
+}
+
+//============================================================================//
+
+G4int RichCkvGrandSensDet::GetCurRichGrandCollSet(G4int aRSect) {
+  G4int aC = ( aRSect == 0 ) ? 4 : 5 ;
+
+  return aC;
+
+}
+
+//=============================================================================//
+void RichCkvGrandSensDet::initialize() { 
+
+ RichCkvCommonSensDet* aCkvCommonSensDet = RichCkvCommonSensDet::getRichCkvCommonSensDetInstance();
+ aCkvCommonSensDet -> InitGeomProp();
+ m_GrPmtBegin= aCkvCommonSensDet -> RichG4HitCollName() -> InitCollectListNumForGrandPmtOutput();
+ m_GrPmtEnd  = aCkvCommonSensDet -> RichG4HitCollName() -> FinalCollectListNumForGrandPmtOutput();
+  
+ collectionName.clear();
+ m_PhdHCID.clear();
+
+ m_NumberOfHCInRICH= aCkvCommonSensDet -> RichG4HitCollName() -> NumberOfGrandHCollectionInRICH();
+ m_PhdHCID.assign(m_NumberOfHCInRICH, -1);
+ collectionName.reserve(m_NumberOfHCInRICH);
+ ResetRichGrandCollListInEv();
+ for(int ihc=m_GrPmtBegin; ihc <=  m_GrPmtEnd   ; ++ihc ) {
+   collectionName.push_back((G4String) (aCkvCommonSensDet -> RichG4HitCollName() -> RichHCName(ihc) ) );
+           
+ }
+  
+}
+
+//=========================================================================//
+void RichCkvGrandSensDet::ResetRichGrandCollListInEv() {
+  m_RichHC.clear(); 
+  m_RichHC.reserve(m_NumberOfHCInRICH);
+  
+}
+//=============================================================================//
+void RichCkvGrandSensDet::Initialize(G4HCofThisEvent* HCE) {
+ 
+  ResetRichGrandCollListInEv(); 
+  
+
+  for(int ihhd= 0;  ihhd <= (m_GrPmtEnd-m_GrPmtBegin)  ;  ++ihhd ) {
+
+    RichCkvG4HitsCollection* CurColl =new  RichCkvG4HitsCollection(SensitiveDetectorName,collectionName[ihhd]);
+    m_RichHC.push_back(CurColl);
+    if(m_PhdHCID[ihhd] < 0  ){
+        m_PhdHCID[ihhd] = G4SDManager::GetSDMpointer()->GetCollectionID(collectionName[ihhd]);
+    }
+    HCE->AddHitsCollection( m_PhdHCID[ihhd] , m_RichHC[ihhd]  );
+
+   }
+
+}
diff --git a/Sim/GaussPhotonics/src/PhotonicsSensDet/RichCkvCommonSensDet.cpp b/Sim/GaussPhotonics/src/PhotonicsSensDet/RichCkvCommonSensDet.cpp
new file mode 100644
index 000000000..62e95bfde
--- /dev/null
+++ b/Sim/GaussPhotonics/src/PhotonicsSensDet/RichCkvCommonSensDet.cpp
@@ -0,0 +1,164 @@
+/*****************************************************************************\
+* (c) Copyright 2000-2020 CERN for the benefit of the LHCb Collaboration      *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                             *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+// Author SE 20-11-2021
+//
+// Include files 
+#include "GaussPhotonics/RichCkvCommonSensDet.h"
+#include "GaussPhotonics/RichPDProperties.h"
+#include "Geant4/G4HCofThisEvent.hh"
+#include "Geant4/G4SDManager.hh"
+#include "Geant4/G4TransportationManager.hh"
+
+#include "Geant4/G4Track.hh"
+#include "Geant4/G4ParticleDefinition.hh"
+#include "Geant4/G4DynamicParticle.hh"
+#include "Geant4/G4OpticalPhoton.hh"
+#include "Geant4/globals.hh"
+#include "Geant4/Randomize.hh"
+
+
+
+using namespace std;
+
+RichCkvCommonSensDet* RichCkvCommonSensDet::RichCkvCommonSensDetInstance=0;
+//============================================================================//
+
+RichCkvCommonSensDet::RichCkvCommonSensDet(  ):m_GeomPropInitFlag(true) {
+
+  m_RichG4HitCollName = new  RichCkvG4HitCollName();
+
+  InitGeomProp();
+
+ }
+
+//===========================================================================//
+void RichCkvCommonSensDet::InitGeomProp() {
+  if( m_GeomPropInitFlag  ) {
+      
+    m_RichGeomProperty = new RichG4PhotonicsGeomProp() ;
+    
+    m_MaxTotalNumPmtsInRich = m_RichGeomProperty->MaxNumberOfPMTsInRich();
+
+
+    m_GeomPropInitFlag = false;
+
+  }
+}
+//============================================================================//
+// Destructor
+//=============================================================================//
+RichCkvCommonSensDet::~RichCkvCommonSensDet() {
+
+  if(m_RichGeomProperty) delete m_RichGeomProperty;
+
+ }
+//============================================================================//
+RichCkvCommonSensDet* RichCkvCommonSensDet::getRichCkvCommonSensDetInstance() {
+
+  if(RichCkvCommonSensDetInstance == 0 )  { 
+    RichCkvCommonSensDetInstance = new RichCkvCommonSensDet();
+  }
+  return RichCkvCommonSensDetInstance;
+}
+//============================================================================//
+
+bool RichCkvCommonSensDet::ProcessRichPmtHits( G4Step* aStep , G4TouchableHistory* ) {
+  if( 0 == aStep ) {return false ;}
+
+
+  //  if( !QESelected(aStep )) {return false ; } 
+
+  double CurEdep = aStep->GetTotalEnergyDeposit();
+  G4StepPoint* prePosPoint =aStep->GetPreStepPoint();
+  const G4ThreeVector & CurGlobalPos  = prePosPoint->GetPosition();
+  const G4double CurGlobalPosZ = CurGlobalPos.z();
+
+  G4TouchableHistory* CurTT =
+    (G4TouchableHistory*)(prePosPoint->GetTouchable());
+  //  G4Track* aTrack = aStep->GetTrack();
+
+  G4int CurrentRichDetNumber = (CurGlobalPosZ < MaxZHitInRich1Detector()) ? 0 : 1 ;
+
+  if( !QESelected(aStep,CurrentRichDetNumber )) {return false ; } 
+
+  // Test for inadmissible values
+  if( (CurGlobalPosZ <= 0 ) || (CurGlobalPosZ >=  MaxZHitInRich2Detector() ) ) {
+    G4cout<<"RICH Common SensDet ERROR "<< " Inadmissible Rich Hit Z coordinate "
+	  << CurGlobalPosZ << "    "<< MaxZHitInRich1Detector()<<"  "
+          <<MaxZHitInRich2Detector() <<G4endl;
+    CurrentRichDetNumber =-1;
+  }
+  // end test  
+  G4int CurrentPmtNumber= CurTT -> GetReplicaNumber(2);
+  G4int CurrentPmtModuleNumber= CurTT -> GetReplicaNumber(4);
+  G4int CurrentRichDetSector = CurTT -> GetReplicaNumber(5);
+  // test print 
+
+  //G4cout<<"RichCkvCommonsensdet  Current richdet sector module pmt numbers GlobalPosXYZ  "
+  //     << CurrentRichDetNumber<<"    "
+  //	<<CurrentRichDetSector<<"  "<<CurrentPmtModuleNumber<<"   "
+  //      <<CurrentPmtNumber <<"     "<<  CurGlobalPos<<G4endl;
+
+  // end test print 
+
+  G4Navigator* theNavigator =
+    G4TransportationManager::GetTransportationManager()->GetNavigatorForTracking();
+  G4ThreeVector CurLocalPos = theNavigator->
+    GetGlobalToLocalTransform().TransformPoint(CurGlobalPos);
+  G4int CurrentPixelXNum = 0; // to be implemented
+  G4int CurrentPixelYNum = 0; // to be implemented
+
+  //if (m_newHit) delete m_newHit;
+
+  m_newHit = new RichCkvG4Hit();
+  m_newHit -> SetEdep( CurEdep);
+  m_newHit -> SetGlobalPos( CurGlobalPos );
+  m_newHit -> SetCurSectorNum(CurrentRichDetSector);
+  m_newHit -> SetCurRichDetNum(CurrentRichDetNumber);
+  m_newHit -> SetLocalPos( CurLocalPos );
+  m_newHit -> SetCurPixelXNum(CurrentPixelXNum);
+  m_newHit -> SetCurPixelYNum(CurrentPixelYNum);
+  m_newHit -> SetCurModuleNum(CurrentPmtModuleNumber );
+  m_newHit -> SetCurPmtNum (CurrentPmtNumber);
+
+  return true;
+}
+//=================================================================//
+bool RichCkvCommonSensDet::QESelected(G4Step* aStep , int CurRDet) {
+ bool aSelected= false; 
+ // std::cout<<" Now in RichCkvCommonSensDet QE selected "<<std::endl;
+
+ const G4DynamicParticle* aParticle=aStep->GetTrack()->GetDynamicParticle();
+ const G4double  aParticleKE= aParticle->GetKineticEnergy();
+ // std::cout<<" RichCkvCommonSensDet KE "<<aParticleKE<<std::endl;
+
+//const G4ParticleDefinition* aParticleDef = aParticle->GetParticleDefinition();
+ if( aParticleKE > 0.0 ) {
+   if(aParticle->GetDefinition() == G4OpticalPhoton::OpticalPhoton() ) {
+
+      RichPDProperties* aRichPDProperties = RichPDProperties::getRichPDPropertiesInstance();    
+      double aQEVal = aRichPDProperties->RichPmtQEList()-> getPmtQEffFromPhotEnergy(aParticleKE);
+      double aAnodeEff = aRichPDProperties->PmtNominalDetectionEffFactor();
+      double aR1QWARCoatingFactor = (CurRDet == 0) ?  aRichPDProperties-> R1GasQWARCoatingFactor() : 1.0 ;
+
+      G4double randomnum = G4UniformRand();
+      //   G4cout<<"CkvCommonSensDet QE randnum "<< aQEVal <<"   "<< randomnum<<G4endl;
+
+      if( (aQEVal > 0.0) && (aAnodeEff > 0.0 )  && (randomnum <  ( aQEVal*aAnodeEff*aR1QWARCoatingFactor ) )) {
+
+          aSelected= true; 
+
+      }
+   }
+ }
+ return aSelected;
+
+}
diff --git a/Sim/GaussPhotonics/src/PhotonicsSensDet/RichCkvG4Hit.cpp b/Sim/GaussPhotonics/src/PhotonicsSensDet/RichCkvG4Hit.cpp
new file mode 100644
index 000000000..a23cdd601
--- /dev/null
+++ b/Sim/GaussPhotonics/src/PhotonicsSensDet/RichCkvG4Hit.cpp
@@ -0,0 +1,90 @@
+/*****************************************************************************\
+* (c) Copyright 2000-2020 CERN for the benefit of the LHCb Collaboration      *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                             *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+// Auhtor SE 10-11-2021
+
+#include "Geant4/G4VVisManager.hh"
+#include "Geant4/G4Circle.hh"
+#include "Geant4/G4Colour.hh"
+#include "Geant4/G4VisAttributes.hh"
+
+#include "GaussPhotonics/RichCkvG4Hit.h"
+
+G4ThreadLocal G4Allocator<RichCkvG4Hit> * RichCkvG4HitAllocator = nullptr;
+//============================================================================//
+RichCkvG4Hit::RichCkvG4Hit(const RichCkvG4Hit & right  ) 
+  :Gaussino::HitBase(right) {
+  m_CurModuleNum = right.m_CurModuleNum;
+  m_CurPmtNum    = right.m_CurPmtNum;
+  m_edep         = right.m_edep;
+  m_GlobalPos    = right.m_GlobalPos;
+  m_LocalPos     = right.m_LocalPos;
+  m_CurRichNum   = right.m_CurRichNum;
+  m_CurSectorNum = right.m_CurSectorNum;
+  m_CurPixelXNum = right.m_CurPixelXNum;
+  m_CurPixelYNum = right.m_CurPixelYNum;
+}
+//============================================================================//
+const RichCkvG4Hit& RichCkvG4Hit::operator=(const RichCkvG4Hit &right)
+{
+  m_CurModuleNum=right.m_CurModuleNum;
+  m_CurPmtNum= right.m_CurPmtNum;
+  m_edep = right.m_edep;
+  m_GlobalPos = right.m_GlobalPos;
+  m_LocalPos = right.m_LocalPos;
+  m_CurRichNum = right.m_CurRichNum;
+  m_CurSectorNum = right.m_CurSectorNum;
+  m_CurPixelXNum = right.m_CurPixelXNum;
+  m_CurPixelYNum = right.m_CurPixelYNum;
+  return *this;
+}
+
+
+//============================================================================//
+void RichCkvG4Hit::Draw() {
+  G4VVisManager* pVVisManager = G4VVisManager::GetConcreteInstance();
+  if(pVVisManager)
+  {
+
+    G4Circle circle(m_GlobalPos);
+    circle.SetScreenSize(5.);
+    circle.SetFillStyle(G4Circle::filled);
+    G4Colour colour(0.0,0.5,0.8);
+    G4VisAttributes attribs(colour);
+    circle.SetVisAttributes(attribs);
+    pVVisManager->Draw(circle);
+  }
+
+}
+//============================================================//
+void RichCkvG4Hit::Print() {
+
+  G4cout<<" Now Printing the a RichCkvG4Hit Info "<<G4endl;
+
+
+
+}
+//=============================================================================//
+/*
+void* RichCkvG4Hit::operator new (size_t){
+    if(!RichCkvG4HitAllocator ) {
+      RichCkvG4HitAllocator = new G4Allocator<RichCkvG4Hit>;
+    }
+
+    return (void*) (RichCkvG4HitAllocator->MallocSingle()   );
+ }
+//=========================================================================//
+void  RichCkvG4Hit::operator delete (void * aHit )  {
+  RichCkvG4HitAllocator->FreeSingle((RichCkvG4Hit* ) aHit);
+
+}
+*/
+
+//========================================================================//
diff --git a/Sim/GaussPhotonics/src/PhotonicsSensDet/RichCkvGrandSensDetFAC.cpp b/Sim/GaussPhotonics/src/PhotonicsSensDet/RichCkvGrandSensDetFAC.cpp
new file mode 100644
index 000000000..acf8da9e6
--- /dev/null
+++ b/Sim/GaussPhotonics/src/PhotonicsSensDet/RichCkvGrandSensDetFAC.cpp
@@ -0,0 +1,19 @@
+/*****************************************************************************\
+* (c) Copyright 2000-2020 CERN for the benefit of the LHCb Collaboration      *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                              *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+// Author  Sajan Easo   20-10-2021
+
+// Include files
+
+#include "GiGaMTFactories/GiGaMTG4SensDetFactory.h"
+#include "GaussPhotonics/RichCkvGrandSensDet.h"
+
+DECLARE_COMPONENT_WITH_ID(RichCkvGrandSensDetFAC<RichCkvGrandSensDet>,"RichCkvGrandSensDet")
+
diff --git a/Sim/GaussPhotonics/src/PhotonicsSensDet/RichCkvStdSensDet.cpp b/Sim/GaussPhotonics/src/PhotonicsSensDet/RichCkvStdSensDet.cpp
new file mode 100644
index 000000000..d7f47ff26
--- /dev/null
+++ b/Sim/GaussPhotonics/src/PhotonicsSensDet/RichCkvStdSensDet.cpp
@@ -0,0 +1,120 @@
+/*****************************************************************************\
+* (c) Copyright 2000-2020 CERN for the benefit of the LHCb Collaboration      *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                              *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+// Author  Sajan Easo   20-10-2021
+// Geant4
+#include "Geant4/G4Step.hh"
+#include "Geant4/G4TouchableHistory.hh"
+#include "Geant4/G4HCofThisEvent.hh"
+#include "Geant4/G4SDManager.hh"
+#include "Geant4/G4TransportationManager.hh"
+#include "Geant4/G4Track.hh"
+#include "Geant4/G4VPhysicalVolume.hh"
+#include "Geant4/G4ios.hh"
+
+#include "GaussPhotonics/RichCkvStdSensDet.h"
+#include "GaussPhotonics/RichCkvG4Hit.h"
+#include "GaussPhotonics/RichCkvCommonSensDet.h"
+
+
+//========================================================================//
+RichCkvStdSensDet::RichCkvStdSensDet(const std::string& name )
+  :G4VSensitiveDetector(name) ,
+   m_RichPmtAviodDuplicateHitsActivate(false),
+   m_RichPmtFlagDuplicateHitsActivate(false) {
+
+  G4cout<<" Now create RichCkvStdSensDet with "<< name <<std::endl;
+  initialize();
+
+ }
+//============================================================================//
+bool RichCkvStdSensDet::ProcessHits(G4Step* aStep, G4TouchableHistory* history) {
+
+  //G4cout<<" Now in RichCkvStdSensDet ProcessHits "<<G4endl;
+
+  RichCkvCommonSensDet* aCkvCommonSensDet =  RichCkvCommonSensDet::getRichCkvCommonSensDetInstance();
+  bool SC = aCkvCommonSensDet->ProcessRichPmtHits(aStep,history );
+  if(SC ) {
+  RichCkvG4Hit * anewHit = aCkvCommonSensDet->  newHit();
+  G4int curCollSet = GetCurRichCollSet (anewHit->GetCurRichDetNum(), anewHit->GetCurSectorNum());
+  if( curCollSet >= 0 ) {
+     int NumHitsInCurHC = m_RichHC[curCollSet]->insert( anewHit );
+     //Verbose print
+     //    G4cout<<" RichCkvStdSensDet Hit stored in RichDet CollSet NumHitsTally " << anewHit->GetCurRichDetNum()<< "     " 
+     //      << curCollSet <<"    "<< NumHitsInCurHC<<G4endl;
+
+  }
+
+  }
+  return SC;
+}
+//============================================================================//
+G4int RichCkvStdSensDet::GetCurRichCollSet (G4int aRDet, G4int aRSect) {
+  G4int aC = -1;
+  if(aRDet == 0 ) {
+    aC = ( aRSect == 0 ) ? 0 : 1 ;
+  } else if ( aRDet == 1 ) {
+    aC = ( aRSect == 0 ) ? 2 : 3 ;
+  }
+  return aC;
+}
+
+//==============================================================================//
+void RichCkvStdSensDet::initialize() {
+
+  RichCkvCommonSensDet* aCkvCommonSensDet =  RichCkvCommonSensDet::getRichCkvCommonSensDetInstance();
+
+  collectionName.clear();
+  m_PhdHCID.clear();
+  m_StdPmtBegin = aCkvCommonSensDet ->RichG4HitCollName() ->InitCollectListNumForStdPmtOutput() ;
+  m_StdPmtEnd = aCkvCommonSensDet -> RichG4HitCollName() ->FinalCollectListNumForStdPmtOutput() ;
+  
+  m_NumberOfHCInRICH=aCkvCommonSensDet -> RichG4HitCollName()->NumberOfStdHCollectionInRICH();
+  m_PhdHCID.assign(m_NumberOfHCInRICH, -1);
+  collectionName.reserve(m_NumberOfHCInRICH);
+
+  ResetRichStdCollListInEv();
+
+
+  for(int ihc= m_StdPmtBegin ; ihc <=  m_StdPmtEnd   ; ++ihc ) {
+           collectionName.push_back((G4String)  aCkvCommonSensDet ->RichG4HitCollName()->RichHCName(ihc)  );
+  }
+  
+}
+//==============================================================================//
+void RichCkvStdSensDet::ResetRichStdCollListInEv() {
+  m_RichHC.clear(); 
+  m_RichHC.reserve(m_NumberOfHCInRICH);
+  
+
+}
+
+//================================================================//
+void RichCkvStdSensDet::Initialize(G4HCofThisEvent* HCE) {
+ 
+  ResetRichStdCollListInEv(); 
+    
+  for(int ihhc= m_StdPmtBegin; ihhc <= m_StdPmtEnd   ; ++ihhc ) {
+    RichCkvG4HitsCollection* CurColl =new  RichCkvG4HitsCollection(SensitiveDetectorName,collectionName[ihhc]);
+    m_RichHC.push_back(CurColl);
+    if(m_PhdHCID[ihhc] < 0  ){
+        m_PhdHCID[ihhc] = G4SDManager::GetSDMpointer()->GetCollectionID(collectionName[ihhc]);
+    }
+   HCE->AddHitsCollection( m_PhdHCID[ihhc] , m_RichHC[ihhc]  );
+   // test print 
+   // G4cout<<" RichCkvStdSensDet EventInit ihhc m_PhdHCID collectionName "<<ihhc<<"   "<<m_PhdHCID[ihhc]<<"   "
+   //      <<collectionName[ihhc] <<G4endl;
+
+   //end test print
+   }
+
+}
+//==================================================================//
+
diff --git a/Sim/GaussPhotonics/src/PhotonicsSensDet/RichCkvStdSensDetFAC.cpp b/Sim/GaussPhotonics/src/PhotonicsSensDet/RichCkvStdSensDetFAC.cpp
new file mode 100644
index 000000000..3d83a23fb
--- /dev/null
+++ b/Sim/GaussPhotonics/src/PhotonicsSensDet/RichCkvStdSensDetFAC.cpp
@@ -0,0 +1,19 @@
+/*****************************************************************************\
+* (c) Copyright 2000-2020 CERN for the benefit of the LHCb Collaboration      *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                              *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+// Author  Sajan Easo   20-10-2021
+
+// Include files
+
+#include "GiGaMTFactories/GiGaMTG4SensDetFactory.h"
+#include "GaussPhotonics/RichCkvStdSensDet.h"
+
+DECLARE_COMPONENT_WITH_ID(RichCkvStdSensDetFAC<RichCkvStdSensDet>,"RichCkvStdSensDet")
+
diff --git a/Sim/GaussPhotonics/src/PhotonicsSensDet/RichG4PhotonicsGeomProp.cpp b/Sim/GaussPhotonics/src/PhotonicsSensDet/RichG4PhotonicsGeomProp.cpp
new file mode 100644
index 000000000..52b0550aa
--- /dev/null
+++ b/Sim/GaussPhotonics/src/PhotonicsSensDet/RichG4PhotonicsGeomProp.cpp
@@ -0,0 +1,46 @@
+/*****************************************************************************\
+* (c) Copyright 2000-2020 CERN for the benefit of the LHCb Collaboration      *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                             *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+// Author SE 20-11-2021
+#ifndef RICHG4PHOTONICSGEOMPROP_H
+#define RICHG4PHOTONICSGEOMPROP_H 1
+
+#include "GaussPhotonics/RichG4PhotonicsGeomProp.h"
+#include "Geant4/G4ios.hh"
+#include "DD4hep/DetFactoryHelper.h"
+#include "XML/Utilities.h"
+#include "CLHEP/Units/SystemOfUnits.h"
+
+//=============================================================================//
+RichG4PhotonicsGeomProp::RichG4PhotonicsGeomProp() { 
+
+  m_NumberOfRichDet            = dd4hep::_toInt("RhNumDetInLHCb");
+  m_NumberOfDetSectionsInRich1 = dd4hep::_toInt("Rh1NumSides");
+  m_NumberOfDetSectionsInRich2 = dd4hep::_toInt("Rh2NumSides");
+  m_NumberOfPixelsInPMT        = dd4hep::_toInt("RichPmtTotalNumberofPixels");
+  m_NumberOfPixelColInPMT      = dd4hep::_toInt("RhPMTNumPixelsInRow");
+  m_NumberOfPixelRowInPMT      = dd4hep::_toInt("RhPMTNumPixelsInCol");
+  m_MaxZHitInRich1Det          = (dd4hep::_toDouble("RhZBeyondDownstreamOfRich1"  ))/(dd4hep::mm) ;
+  m_MaxZHitInRich2Det          = (dd4hep::_toDouble("RhZBeyondDownstreamOfRich2"  ))/(dd4hep::mm);
+  m_MaxNumberOfPMTsInRich1        = dd4hep::_toInt( "Rh1MaxNumberOfPMT"  );
+  m_MaxNumberOfPMTsInRich2        = dd4hep::_toInt("Rh2MaxNumberOfPMT"  );
+  m_MaxNumberOfPMTsInRich         = m_MaxNumberOfPMTsInRich1 + m_MaxNumberOfPMTsInRich2 ;
+
+  //test print 
+  // std::cout<<" RichG4PhotonicsGeomProp Max Z Rich1 Rich2  "<<m_MaxZHitInRich1Det <<"  "
+  //         <<m_MaxZHitInRich2Det <<std::endl;
+  // end test print
+}
+
+
+
+
+
+#endif // RICHG4PHOTONICSGEOMPROP_H 
diff --git a/Sim/GaussPhotonics/src/srcG4Photonics/RhCkvG4Cerenkov.cpp b/Sim/GaussPhotonics/src/srcG4Photonics/RhCkvG4Cerenkov.cpp
new file mode 100644
index 000000000..7673bae5e
--- /dev/null
+++ b/Sim/GaussPhotonics/src/srcG4Photonics/RhCkvG4Cerenkov.cpp
@@ -0,0 +1,794 @@
+//
+// ********************************************************************
+// * License and Disclaimer                                           *
+// *                                                                  *
+// * The  Geant4 software  is  copyright of the Copyright Holders  of *
+// * the Geant4 Collaboration.  It is provided  under  the terms  and *
+// * conditions of the Geant4 Software License,  included in the file *
+// * LICENSE and available at  http://cern.ch/geant4/license .  These *
+// * include a list of copyright holders.                             *
+// *                                                                  *
+// * Neither the authors of this software system, nor their employing *
+// * institutes,nor the agencies providing financial support for this *
+// * work  make  any representation or  warranty, express or implied, *
+// * regarding  this  software system or assume any liability for its *
+// * use.  Please see the license in the file  LICENSE  and URL above *
+// * for the full disclaimer and the limitation of liability.         *
+// *                                                                  *
+// * This  code  implementation is the result of  the  scientific and *
+// * technical work of the GEANT4 collaboration.                      *
+// * By using,  copying,  modifying or  distributing the software (or *
+// * any work based  on the software)  you  agree  to acknowledge its *
+// * use  in  resulting  scientific  publications,  and indicate your *
+// * acceptance of all terms of the Geant4 Software license.          *
+// ********************************************************************
+//
+//
+//
+////////////////////////////////////////////////////////////////////////
+// RICH Cerenkov Radiation Class Implementation
+////////////////////////////////////////////////////////////////////////
+//
+// File:        RichCkvG4Cerenkov.cc
+// Description: Discrete Process -- Generation of Cerenkov Photons
+// Version:     2.1
+// Created:     1996-02-21
+// Author:      Juliet Armstrong
+// Updated:     2007-09-30 by Peter Gumplinger
+//              > change inheritance to G4VDiscreteProcess
+//              GetContinuousStepLimit -> GetMeanFreePath (StronglyForced)
+//              AlongStepDoIt -> PostStepDoIt
+//              2005-08-17 by Peter Gumplinger
+//              > change variable name MeanNumPhotons -> MeanNumberOfPhotons
+//              2005-07-28 by Peter Gumplinger
+//              > add G4ProcessType to constructor
+//              2001-09-17, migration of Materials to pure STL (mma)
+//              2000-11-12 by Peter Gumplinger
+//              > add check on CerenkovAngleIntegrals->IsFilledVectorExist()
+//              in method GetAverageNumberOfPhotons
+//              > and a test for MeanNumberOfPhotons <= 0.0 in DoIt
+//              2000-09-18 by Peter Gumplinger
+//              > change: aSecondaryPosition=x0+rand*aStep.GetDeltaPosition();
+//                        aSecondaryTrack->SetTouchable(0);
+//              1999-10-29 by Peter Gumplinger
+//              > change: == into <= in GetContinuousStepLimit
+//              1997-08-08 by Peter Gumplinger
+//              > add protection against /0
+//              > G4MaterialPropertiesTable; new physics/tracking scheme
+//
+//  Mod SE , Aug02-2021 
+////////////////////////////////////////////////////////////////////////
+
+#include "Geant4/G4ios.hh"
+#include "Geant4/G4PhysicalConstants.hh"
+#include "Geant4/G4SystemOfUnits.hh"
+#include "Geant4/G4Poisson.hh"
+#include "Geant4/G4EmProcessSubType.hh"
+
+#include "Geant4/G4LossTableManager.hh"
+#include "Geant4/G4MaterialCutsCouple.hh"
+#include "Geant4/G4ParticleDefinition.hh"
+
+//#include "Geant4/G4OpticalParameters.hh"
+#include "GaussPhotonics/RhCkvG4Cerenkov.h"
+#include "GaussPhotonics/RichG4PhotonicsCkvProdTag.h"
+#include "Detector/Rich1/RichGeoUtil.h"
+#include "Detector/Rich2/Rich2GeoUtil.h"
+#include "Detector/Rich1/RichPmtGeoAux.h"
+
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+RhCkvG4Cerenkov::RhCkvG4Cerenkov(const G4String& processName, G4ProcessType type)
+  : G4VProcess(processName, type)
+  , fTrackSecondariesFirst(false)
+  , fMaxBetaChange(0)
+  , fMaxPhotons(0)
+  , fStackingFlag(true)
+  , fNumPhotons(0)
+  , fRichVerboseInfoTag(false)
+  , m_AddBackGrRich2(false)
+  , m_Rich2BackgrProb(0.0)
+  , m_ActivateRichG4CherenkovAnalysis(false)
+  , m_R2Rnd_minCos(1.0)
+  , m_R2Rnd_maxCos(0.0)
+{
+  SetProcessSubType(fCerenkov);
+
+  thePhysicsTable = nullptr;
+
+  if(verboseLevel > -1)
+    //  if(verboseLevel > 0)
+  {
+    G4cout << GetProcessName() << " is created." << G4endl;
+  }
+  Initialise();
+
+    Rich2GeoUtil*   aRich2GeoUtil = Rich2GeoUtil::getRich2GeoUtilInstance();
+    m_Rich2GasVolName =  aRich2GeoUtil->Rich2GasEnclosureLVName();
+
+    //G4cout <<"RhCkvG4Cerenkov process created "<<G4endl;
+  //  G4cout<<"RhG4Cerenkov Rich2GasVolName "<< m_Rich2GasVolName <<G4endl;
+
+    InitCkvMatList();
+
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+RhCkvG4Cerenkov::~RhCkvG4Cerenkov()
+{
+  if(thePhysicsTable != nullptr)
+  {
+    thePhysicsTable->clearAndDestroy();
+    delete thePhysicsTable;
+  }
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+G4bool RhCkvG4Cerenkov::IsApplicable(const G4ParticleDefinition& aParticleType)
+{
+  return (aParticleType.GetPDGCharge() != 0.0 &&
+          aParticleType.GetPDGMass() != 0.0 &&
+          aParticleType.GetParticleName() != "chargedgeantino" &&
+          !aParticleType.IsShortLived())
+           ? true
+           : false;
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+void RhCkvG4Cerenkov::Initialise()
+{
+  // The relevant parts of the following already set from 
+  //GaussCkvOpticalPhysicsList.cpp and hence 
+  // commented out here. This is so that they can be controlled from options files.
+
+  /*
+  G4OpticalParameters* params = G4OpticalParameters::Instance();
+  SetMaxBetaChangePerStep(params->GetCerenkovMaxBetaChange());
+  SetMaxNumPhotonsPerStep(params->GetCerenkovMaxPhotonsPerStep());
+  SetTrackSecondariesFirst(params->GetCerenkovTrackSecondariesFirst());
+  SetStackPhotons(params->GetCerenkovStackPhotons());
+  SetVerboseLevel(params->GetCerenkovVerboseLevel());
+  
+  */
+
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+void RhCkvG4Cerenkov::BuildPhysicsTable(const G4ParticleDefinition&)
+{
+  if(thePhysicsTable)
+    return;
+
+  const G4MaterialTable* theMaterialTable = G4Material::GetMaterialTable();
+  G4int numOfMaterials                    = G4Material::GetNumberOfMaterials();
+  
+  thePhysicsTable = new G4PhysicsTable(numOfMaterials);
+
+  // loop over materials
+
+  for(G4int i = 0; i < numOfMaterials; ++i)
+  {
+    G4PhysicsOrderedFreeVector* aPhysicsOrderedFreeVector = 0;
+
+    // Retrieve vector of refraction indices for the material
+    // from the material's optical properties table
+    G4Material* aMaterial = (*theMaterialTable)[i];
+
+        //Restrict the Cherenkov photon production to the materials selected.
+         // This is to save CPU time. SE 15-12-2021
+         if( std::find (m_RichCkvProdMatIndex.begin(),m_RichCkvProdMatIndex.end(),
+                 (aMaterial->GetIndex()))!= m_RichCkvProdMatIndex.end()) {
+
+         // test print 
+         //  G4cout<<" Selected for Ckv "<< aMaterial->GetIndex() << aMaterial->GetName()<<G4endl;
+        //end test print
+
+           G4MaterialPropertiesTable* aMaterialPropertiesTable =
+                   aMaterial->GetMaterialPropertiesTable();
+
+           if(aMaterialPropertiesTable){
+                aPhysicsOrderedFreeVector = new G4PhysicsOrderedFreeVector();
+
+               //Change to produce photons only within a limited range of RefIndex.
+               G4MaterialPropertyVector* theRefractionIndexVector =
+               aMaterialPropertiesTable->GetProperty(kRINDEX);
+               //
+
+               //G4MaterialPropertyVector* theRefractionIndexVector =
+              //  aMaterialPropertiesTable->GetProperty("CKVRNDX");
+
+              if(theRefractionIndexVector){
+                 // Retrieve the first refraction index in vector
+                 // of (photon energy, refraction index) pairs
+                 G4double currentRI = (*theRefractionIndexVector)[0];
+
+               if(currentRI > 1.0){
+                // Create first (photon energy, Cerenkov Integral) pair
+                 G4double currentPM  = theRefractionIndexVector->Energy(0);
+                 G4double currentCAI = 0.0;
+
+                  aPhysicsOrderedFreeVector->InsertValues(currentPM, currentCAI);
+
+
+                // Set previous values to current ones prior to loop
+                   G4double prevPM  = currentPM;
+                   G4double prevCAI = currentCAI;
+                   G4double prevRI  = currentRI;
+
+                   // loop over all (photon energy, refraction index)
+                   // pairs stored for this material
+                    for(size_t ii = 1; ii < theRefractionIndexVector->GetVectorLength();
+                       ++ii)
+                    {
+                      currentRI  = (*theRefractionIndexVector)[ii];
+                      currentPM  = theRefractionIndexVector->Energy(ii);
+                      currentCAI = prevCAI + (currentPM - prevPM) * 0.5 *
+                                     (1.0 / (prevRI * prevRI) +
+                                      1.0 / (currentRI * currentRI));
+
+                        aPhysicsOrderedFreeVector->InsertValues(currentPM, currentCAI);
+
+                        prevPM  = currentPM;
+                        prevCAI = currentCAI;
+                        prevRI  = currentRI;
+		    }
+		}
+	      }
+           }
+	 }
+    // The Cerenkov integral for a given material will be inserted in
+    // thePhysicsTable according to the position of the material in
+    // the material table.
+
+      thePhysicsTable->insertAt(i, aPhysicsOrderedFreeVector);
+
+  }
+  
+}
+
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+G4VParticleChange* RhCkvG4Cerenkov::PostStepDoIt(const G4Track& aTrack,
+                                            const G4Step& aStep)
+// This method is called for each tracking Step of a charged particle
+// in a radiator. A Poisson-distributed number of photons is generated
+// according to the Cerenkov formula, distributed evenly along the track
+// segment and uniformly azimuth w.r.t. the particle direction. The
+// parameters are then transformed into the Master Reference System, and
+// they are added to the particle change.
+
+{
+ 
+
+  aParticleChange.Initialize(aTrack);
+
+  const G4DynamicParticle* aParticle = aTrack.GetDynamicParticle();
+  const G4Material* aMaterial        = aTrack.GetMaterial();
+
+  G4StepPoint* pPreStepPoint  = aStep.GetPreStepPoint();
+  G4StepPoint* pPostStepPoint = aStep.GetPostStepPoint();
+
+  // test printout
+
+     G4String  apPreVolName=  pPreStepPoint->
+                GetPhysicalVolume()->GetLogicalVolume()->GetName();
+     G4String  apPostVolName=  pPostStepPoint->
+               GetPhysicalVolume()->GetLogicalVolume()->GetName();
+     G4String aMaterialName= aMaterial->GetName();
+     // G4cout<<"RhCkvG4Cerenkov: PreVol PostVol Material Names: "<<apPreVolName<<"    "
+     //    << apPostVolName<<"   "<< aMaterialName<< G4endl;
+
+     // G4cout<<"RhCkvG4Cerenkov: PreVol  Names: "<<apPreVolName<<"    "<<G4endl;
+  //end test printout
+
+     G4ThreeVector x0 = pPreStepPoint->GetPosition();
+     G4ThreeVector p0 = aStep.GetDeltaPosition().unit();
+     G4double t0      = pPreStepPoint->GetGlobalTime();
+
+     G4MaterialPropertiesTable* MPT = aMaterial->GetMaterialPropertiesTable();
+     if(!MPT)
+     return pParticleChange;
+    //Using ref index table with limited size
+     G4MaterialPropertyVector* Rindex = MPT->GetProperty(kRINDEX);
+
+  //G4MaterialPropertyVector* Rindex = MPT->GetProperty("CKVRNDX");
+  if(!Rindex)
+    return pParticleChange;
+
+  G4double charge = aParticle->GetDefinition()->GetPDGCharge();
+  G4double beta = (pPreStepPoint->GetBeta() + pPostStepPoint->GetBeta()) * 0.5;
+
+  // fNumPhotons = 0;  // in PostStepGetPhysicalInteractionLength()
+
+  G4double MeanNumberOfPhotons =
+    GetAverageNumberOfPhotons(charge, beta, aMaterial, Rindex);
+  // G4cout<<" RhCkvG4Cerenkov Mean Number of phot prod "<< MeanNumberOfPhotons <<G4endl;
+
+  if(MeanNumberOfPhotons <= 0.0)
+  {
+    // return unchanged particle and no secondaries
+    aParticleChange.SetNumberOfSecondaries(0);
+    return pParticleChange;
+  }
+
+  G4double step_length = aStep.GetStepLength();
+  MeanNumberOfPhotons  = MeanNumberOfPhotons * step_length;
+  fNumPhotons          = (G4int) G4Poisson(MeanNumberOfPhotons);
+  G4int nAddPhotRich2 = 0;
+  if( m_AddBackGrRich2 ) {
+    G4String  pPreVolName=  pPreStepPoint->
+                GetPhysicalVolume()->GetLogicalVolume()->GetName();
+
+    if( pPreVolName.find(m_Rich2GasVolName) != std::string::npos){ 
+      nAddPhotRich2 = (G4int ) (fNumPhotons*m_Rich2BackgrProb);
+      fNumPhotons += nAddPhotRich2;
+   
+    }
+    
+  }
+ // test print for Rich2backgr
+  // if( pPreVolName == LogVolCF4NameAnalysis){ 
+  //  
+      //  G4cout<<"RichG4Cerenkov Adddbackgr prob  nAddBackgr NumPhot "<<  m_AddBackGrRich2 <<
+      //  "  "<<m_Rich2BackgrProb <<"  "<<nAddPhotRich2 <<"  "<<fNumPhotons<<G4endl;
+  //    
+  //  }
+  //  
+  //end test print  
+
+
+
+  if(fNumPhotons <= 0 || !fStackingFlag)
+  {
+    // return unchanged particle and no secondaries
+    aParticleChange.SetNumberOfSecondaries(0);
+    return pParticleChange;
+  }
+
+  ////////////////////////////////////////////////////////////////
+  aParticleChange.SetNumberOfSecondaries(fNumPhotons);
+
+  if(fTrackSecondariesFirst)
+  {
+    if(aTrack.GetTrackStatus() == fAlive)
+      aParticleChange.ProposeTrackStatus(fSuspend);
+  }
+
+  ////////////////////////////////////////////////////////////////
+  G4double Pmin = Rindex->GetMinLowEdgeEnergy();
+  G4double Pmax = Rindex->GetMaxLowEdgeEnergy();
+  G4double dp   = Pmax - Pmin;
+
+  G4double nMax        = Rindex->GetMaxValue();
+  G4double BetaInverse = 1. / beta;
+
+  G4double maxCos  = BetaInverse / nMax;
+  G4double maxSin2 = (1.0 - maxCos) * (1.0 + maxCos);
+
+  G4double beta1 = pPreStepPoint->GetBeta();
+  G4double beta2 = pPostStepPoint->GetBeta();
+
+  G4double MeanNumberOfPhotons1 =
+    GetAverageNumberOfPhotons(charge, beta1, aMaterial, Rindex);
+  G4double MeanNumberOfPhotons2 =
+    GetAverageNumberOfPhotons(charge, beta2, aMaterial, Rindex);
+
+  // Now for adding background in RICH2
+  m_R2Rnd_maxCos =  1.0/nMax;
+  // end for adding background in RICH2
+
+
+
+  for(G4int i = 0; i < fNumPhotons; ++i)
+  {
+    // Determine photon energy
+    G4double rand;
+    G4double sampledEnergy, sampledRI;
+    G4double cosTheta, sin2Theta;
+
+    // sample an energy
+    do
+    {
+      rand          = G4UniformRand();
+      sampledEnergy = Pmin + rand * dp;
+      sampledRI     = Rindex->Value(sampledEnergy);
+      cosTheta      = BetaInverse / sampledRI;
+
+      sin2Theta = (1.0 - cosTheta) * (1.0 + cosTheta);
+      rand      = G4UniformRand();
+
+      // Loop checking, 07-Aug-2015, Vladimir Ivanchenko
+    } while(rand * maxSin2 > sin2Theta);
+
+    if( i >= (fNumPhotons - nAddPhotRich2) ){
+      // for adding background to RICH2 
+      // create a theta randomly in the Beta range       
+        rand = G4UniformRand();	
+        cosTheta = rand *(m_R2Rnd_minCos- m_R2Rnd_maxCos) + m_R2Rnd_maxCos ;
+	sin2Theta = (1.0 - cosTheta)*(1.0 + cosTheta);
+
+        // keep the theta values to physically allowed values.
+        if( cosTheta  > 1.0) { 
+          cosTheta=1.0;
+          sin2Theta=0.0;
+         }
+
+      // end adding background to RICH2
+      //  G4cout<<"test print: rich2 random hits energy costheta theta " 
+      //         <<i<<"  "<<sampledEnergy<<"   "
+      //         << cosTheta <<"  "<<acos(cosTheta)<<G4endl;        
+    }
+
+
+
+
+    // Create photon momentum direction vector. The momentum direction is still
+    // with respect to the coordinate system where the primary particle
+    // direction is aligned with the z axis
+    rand              = G4UniformRand();
+    G4double phi      = twopi * rand;
+    G4double sinPhi   = std::sin(phi);
+    G4double cosPhi   = std::cos(phi);
+    G4double sinTheta = std::sqrt(sin2Theta);
+    G4ParticleMomentum photonMomentum(sinTheta * cosPhi, sinTheta * sinPhi,
+                                      cosTheta);
+
+    // Rotate momentum direction back to global reference system
+    photonMomentum.rotateUz(p0);
+
+    // Determine polarization of new photon
+    G4ThreeVector photonPolarization(cosTheta * cosPhi, cosTheta * sinPhi,
+                                     -sinTheta);
+
+    // Rotate back to original coord system
+    photonPolarization.rotateUz(p0);
+
+    // Generate a new photon:
+    G4DynamicParticle* aCerenkovPhoton =
+      new G4DynamicParticle(G4OpticalPhoton::OpticalPhoton(), photonMomentum);
+
+    aCerenkovPhoton->SetPolarization(photonPolarization);
+    aCerenkovPhoton->SetKineticEnergy(sampledEnergy);
+    //To be reviewed : to avoid the following check, since the particle is 
+    // unlikely to loose any significant amount of energy during the Cherenkov step 
+    // in RICH radiators. Avoiding the test may improve a minor amount of cpu.
+
+    G4double NumberOfPhotons, N;
+
+    do
+    {
+      rand            = G4UniformRand();
+      NumberOfPhotons = MeanNumberOfPhotons1 -
+                        rand * (MeanNumberOfPhotons1 - MeanNumberOfPhotons2);
+      N =
+        G4UniformRand() * std::max(MeanNumberOfPhotons1, MeanNumberOfPhotons2);
+      // Loop checking, 07-Aug-2015, Vladimir Ivanchenko
+    } while(N > NumberOfPhotons);
+
+    // end of part of to be reviewed.
+
+    G4double delta = rand * aStep.GetStepLength();
+    G4double deltaTime =
+      delta /
+      (pPreStepPoint->GetVelocity() +
+       rand * (pPostStepPoint->GetVelocity() - pPreStepPoint->GetVelocity()) *
+         0.5);
+
+    G4double aSecondaryTime          = t0 + deltaTime;
+    G4ThreeVector aSecondaryPosition = x0 + rand * aStep.GetDeltaPosition();
+
+    // Generate new G4Track object:
+    G4Track* aSecondaryTrack =
+      new G4Track(aCerenkovPhoton, aSecondaryTime, aSecondaryPosition);
+
+    aSecondaryTrack->SetTouchableHandle(
+      aStep.GetPreStepPoint()->GetTouchableHandle());
+    aSecondaryTrack->SetParentID(aTrack.GetTrackID());
+
+    // LHCb modif for monitoring and extracting relevant info
+    //    aParticleChange.AddSecondary(aSecondaryTrack);
+    //aCkvSourceInfo : // 0 mean unknown, 1 mean cherenkov process , 2 mean scintillation process,
+                       // 4 means cherenkov process with random Cherenkov angle as correlated background
+                       //  as implemented for RICH2
+
+    G4int aCkvSourceInfo = ( i >= (fNumPhotons - nAddPhotRich2) ) ? 4 : 1 ;
+    G4Track* aTaggedSecondaryTrack = RichG4PhotonicsCkvProdTag(aTrack,aSecondaryTrack,
+		        cosTheta,phi,sampledEnergy,
+                        fRichVerboseInfoTag,aCkvSourceInfo );
+     aParticleChange.AddSecondary(aTaggedSecondaryTrack);
+     // G4cout<<" Ckv photon crteated  i Theta PhotonE "<< i <<"  "<<acos(cosTheta) <<"  "<< sampledEnergy <<G4endl;
+    //end LHCb modif
+  }
+
+  // if( m_ActivateRichG4CherenkovAnalysis ) {
+    
+     //RichG4PhotonicsQwAnalysis* aRichG4PhotonicsQwAnalysis = RichG4PhotonicsQwAnalysis::getRichG4PhotonicsQwAnalysisInstance();
+     //  if( aRichG4PhotonicsQwAnalysis->qwAnalysisNtupleBooked() ) {
+     // aRichG4PhotonicsQwAnalysis ->FillQwAnalysisHisto(aTrack);
+     //aRichG4PhotonicsQwAnalysis ->FillQwAnalysisHistoA(aTrack);
+     //}        
+  //  }
+
+  if(verboseLevel > 1)
+  // if(verboseLevel > -1)
+  {
+    G4cout << "\n Exiting from RhCkvG4Cerenkov::DoIt -- NumberOfSecondaries = "
+           << aParticleChange.GetNumberOfSecondaries() << G4endl;
+  }
+
+  return pParticleChange;
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+void RhCkvG4Cerenkov::PreparePhysicsTable(const G4ParticleDefinition&)
+{
+  Initialise();
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+G4double RhCkvG4Cerenkov::GetMeanFreePath(const G4Track&, G4double,
+                                     G4ForceCondition*)
+{
+  return 1.;
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+G4double RhCkvG4Cerenkov::PostStepGetPhysicalInteractionLength(
+  const G4Track& aTrack, G4double, G4ForceCondition* condition)
+{
+  *condition         = NotForced;
+  G4double StepLimit = DBL_MAX;
+  fNumPhotons        = 0;
+
+  const G4Material* aMaterial = aTrack.GetMaterial();
+  G4int materialIndex         = aMaterial->GetIndex();
+  // G4cout<<"RhCkv IntLenMethod MatIndex name "<< materialIndex <<"  "<< aMaterial->GetName()<<G4endl;
+
+  // If Physics Vector is not defined no Cerenkov photons
+  if(!(*thePhysicsTable)[materialIndex])
+  {
+    //G4cout<< " RhCkv No Physics table for ckv "<<G4endl;
+    return StepLimit;
+  }
+
+  const G4DynamicParticle* aParticle = aTrack.GetDynamicParticle();
+  const G4MaterialCutsCouple* couple = aTrack.GetMaterialCutsCouple();
+
+  G4double kineticEnergy                   = aParticle->GetKineticEnergy();
+
+  // G4cout<<"RhCkv IntLen Particle KE "<<  aParticle-> GetParticleDefinition()->GetParticleName() <<"   "
+  //      <<kineticEnergy <<G4endl;
+
+  const G4ParticleDefinition* particleType = aParticle->GetDefinition();
+  G4double mass                            = particleType->GetPDGMass();
+
+  G4double beta  = aParticle->GetTotalMomentum() / aParticle->GetTotalEnergy();
+  G4double gamma = aParticle->GetTotalEnergy() / mass;
+
+  G4MaterialPropertiesTable* aMaterialPropertiesTable =
+    aMaterial->GetMaterialPropertiesTable();
+
+  G4MaterialPropertyVector* Rindex = nullptr;
+
+  //Change to use Ref index table within a limited range
+  if(aMaterialPropertiesTable)
+    Rindex = aMaterialPropertiesTable->GetProperty(kRINDEX);
+
+  // if(aMaterialPropertiesTable)
+  //  Rindex = aMaterialPropertiesTable->GetProperty("CKVRNDX");
+  // G4cout<<" RhCkv PhyTable MatTable "<< aMaterialPropertiesTable <<"  "<<Rindex<<G4endl;
+
+  G4double nMax;
+  if(Rindex)
+  {
+    nMax = Rindex->GetMaxValue();
+    // G4cout<<" RhCkv PhyTable nMax "<< nMax <<G4endl;
+
+  }
+  else
+  {
+    return StepLimit;
+  }
+
+  G4double BetaMin = 1. / nMax;
+  if(BetaMin >= 1.)
+    return StepLimit;
+
+  G4double GammaMin = 1. / std::sqrt(1. - BetaMin * BetaMin);
+  if(gamma < GammaMin)
+    return StepLimit;
+
+  G4double kinEmin = mass * (GammaMin - 1.);
+  G4double RangeMin =
+    G4LossTableManager::Instance()->GetRange(particleType, kinEmin, couple);
+  G4double Range = G4LossTableManager::Instance()->GetRange(
+    particleType, kineticEnergy, couple);
+  G4double Step = Range - RangeMin;
+
+  // If the step is smaller than 1e-16 mm, it may happen that the particle
+  // does not move. See bug 1992.
+  //  2019-03-11: change to 1e-15
+  if(Step < 1.e-15 * mm)
+    return StepLimit;
+
+  if(Step < StepLimit)
+    StepLimit = Step;
+
+  // If user has defined an average maximum number of photons to be generated in
+  // a Step, then calculate the Step length for that number of photons.
+  if(fMaxPhotons > 0)
+  {
+    const G4double charge = aParticle->GetDefinition()->GetPDGCharge();
+    G4double MeanNumberOfPhotons =
+      GetAverageNumberOfPhotons(charge, beta, aMaterial, Rindex);
+    Step = 0.;
+    if(MeanNumberOfPhotons > 0.0)
+      Step = fMaxPhotons / MeanNumberOfPhotons;
+    if(Step > 0. && Step < StepLimit)
+      StepLimit = Step;
+  }
+
+  // If user has defined an maximum allowed change in beta per step
+  if(fMaxBetaChange > 0.)
+  {
+    G4double dedx = G4LossTableManager::Instance()->GetDEDX(
+      particleType, kineticEnergy, couple);
+    G4double deltaGamma =
+      gamma - 1. / std::sqrt(1. - beta * beta * (1. - fMaxBetaChange) *
+                                    (1. - fMaxBetaChange));
+
+    Step = mass * deltaGamma / dedx;
+    if(Step > 0. && Step < StepLimit)
+      StepLimit = Step;
+  }
+
+  *condition = StronglyForced;
+  //G4cout<<" Rh Ckv Phy Step lim "<< StepLimit <<G4endl;
+  return StepLimit;
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+G4double RhCkvG4Cerenkov::GetAverageNumberOfPhotons(
+  const G4double charge, const G4double beta, const G4Material* aMaterial,
+  G4MaterialPropertyVector* Rindex) const
+// This routine computes the number of Cerenkov photons produced per
+// GEANT4-unit (millimeter) in the current medium.
+//              ^^^^^^^^^^
+{
+  const G4double Rfact = 369.81 / (eV * cm);
+  if(beta <= 0.0)
+    return 0.0;
+  G4double BetaInverse = 1. / beta;
+
+  // Vectors used in computation of Cerenkov Angle Integral:
+  // 	- Refraction Indices for the current material
+  //	- new G4PhysicsOrderedFreeVector allocated to hold CAI's
+  G4int materialIndex = aMaterial->GetIndex();
+
+  // Retrieve the Cerenkov Angle Integrals for this material
+  G4PhysicsOrderedFreeVector* CerenkovAngleIntegrals =
+    (G4PhysicsOrderedFreeVector*) ((*thePhysicsTable)(materialIndex));
+
+  if(!(CerenkovAngleIntegrals->IsFilledVectorExist()))
+    return 0.0;
+
+  // Min and Max photon energies
+  G4double Pmin = Rindex->GetMinLowEdgeEnergy();
+  G4double Pmax = Rindex->GetMaxLowEdgeEnergy();
+
+  // Min and Max Refraction Indices
+  G4double nMin = Rindex->GetMinValue();
+  G4double nMax = Rindex->GetMaxValue();
+
+  // Max Cerenkov Angle Integral
+  G4double CAImax = CerenkovAngleIntegrals->GetMaxValue();
+
+  G4double dp, ge;
+  // If n(Pmax) < 1/Beta -- no photons generated
+  if(nMax < BetaInverse)
+  {
+    dp = 0.0;
+    ge = 0.0;
+  }
+  // otherwise if n(Pmin) >= 1/Beta -- photons generated
+  else if(nMin > BetaInverse)
+  {
+    dp = Pmax - Pmin;
+    ge = CAImax;
+  }
+  // If n(Pmin) < 1/Beta, and n(Pmax) >= 1/Beta, then we need to find a P such
+  // that the value of n(P) == 1/Beta. Interpolation is performed by the
+  // GetEnergy() and Value() methods of the G4MaterialPropertiesTable and
+  // the Value() method of G4PhysicsVector.
+  else
+  {
+    Pmin = Rindex->GetEnergy(BetaInverse);
+    dp   = Pmax - Pmin;
+
+    G4double CAImin = CerenkovAngleIntegrals->Value(Pmin);
+    ge              = CAImax - CAImin;
+
+    if(verboseLevel > 1)
+    {
+      G4cout << "CAImin = " << CAImin << G4endl << "ge = " << ge << G4endl;
+    }
+  }
+
+  // Calculate number of photons
+  G4double NumPhotons = Rfact * charge / eplus * charge / eplus *
+                        (dp - ge * BetaInverse * BetaInverse);
+
+  return NumPhotons;
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+void RhCkvG4Cerenkov::SetTrackSecondariesFirst(const G4bool state)
+{
+  fTrackSecondariesFirst = state;
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+void RhCkvG4Cerenkov::SetMaxBetaChangePerStep(const G4double value)
+{
+  fMaxBetaChange = value * CLHEP::perCent;
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+void RhCkvG4Cerenkov::SetMaxNumPhotonsPerStep(const G4int NumPhotons)
+{
+  fMaxPhotons = NumPhotons;
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+void RhCkvG4Cerenkov::DumpPhysicsTable() const
+{
+  G4PhysicsOrderedFreeVector* v;
+  for(size_t i = 0; i < thePhysicsTable->entries(); ++i)
+  {
+    v = (G4PhysicsOrderedFreeVector*) (*thePhysicsTable)[i];
+    v->DumpValues();
+  }
+}
+//===========================================================================//
+void RhCkvG4Cerenkov::printBackgrRich2Param() {
+  
+  G4cout<<" RhCkvG4Cerenkov Rich2 backgrActivateFlag  Rich2 backgrprob  "<<  m_AddBackGrRich2 <<"  "<<m_Rich2BackgrProb<<G4endl;
+
+
+}
+//==========================================================================//
+void RhCkvG4Cerenkov::InitCkvMatList() {
+
+ m_RichCkvProdMatIndex.clear();
+ m_RichCkvProdMatIndex.reserve(9);
+ RichGeoUtil*  aRichGeoUtil = RichGeoUtil::getRichGeoUtilInstance();
+ Rich2GeoUtil* aRich2GeoUtil = Rich2GeoUtil::getRich2GeoUtilInstance();
+ RichPmtGeoAux* aRichPmtGeoAux = RichPmtGeoAux::getRichPmtGeoAuxInstance();
+
+ m_RichCkvProdMatIndex.push_back(FindG4CkvMatIndex(aRichGeoUtil-> Rich1C4F10MatName(), -1080) ) ;
+ m_RichCkvProdMatIndex.push_back(FindG4CkvMatIndex(aRichGeoUtil-> Rich1RadiatorGasMatName (), -1090));
+ m_RichCkvProdMatIndex.push_back(FindG4CkvMatIndex(aRich2GeoUtil-> Rich2NitrogenMatName(), -1100));
+ m_RichCkvProdMatIndex.push_back(FindG4CkvMatIndex(aRich2GeoUtil-> Rich2CF4MatName (), -1110) );
+ m_RichCkvProdMatIndex.push_back(FindG4CkvMatIndex(aRich2GeoUtil-> Rich2RadiatorGasMatName (), -1120));
+ m_RichCkvProdMatIndex.push_back(FindG4CkvMatIndex(aRichPmtGeoAux -> RichPmtQWMatName(), -1060));
+ m_RichCkvProdMatIndex.push_back(FindG4CkvMatIndex(aRich2GeoUtil->Rich2CO2GasMatName(), -1130));
+ m_RichCkvProdMatIndex.push_back(FindG4CkvMatIndex(aRichGeoUtil->Rich1GasQuartzWMatName(),-1000 ));
+ m_RichCkvProdMatIndex.push_back(FindG4CkvMatIndex(aRich2GeoUtil->  Rich2GasQuartzWMatName(), -1010));
+
+}
+//===========================================================================//
+G4int RhCkvG4Cerenkov::FindG4CkvMatIndex (std::string aMatName, G4int aDummyIndex ) {
+  G4int aMatIndex = aDummyIndex;
+  const G4String bMatName = aMatName;
+  static const G4MaterialTable* theMaterialTable = G4Material::GetMaterialTable();
+  auto aR_itr = std::find_if(theMaterialTable->begin(),theMaterialTable->end(),
+			     [&bMatName] (const auto &aM ) {return (aM->GetName() ==  bMatName);});
+  if( aR_itr != theMaterialTable->end()) {
+    aMatIndex = (*aR_itr) ->  GetIndex();
+  }
+  
+  return   aMatIndex;
+
+}
+
+//=============================================================================//
diff --git a/Sim/GaussPhotonics/src/srcG4Photonics/RhCkvG4OpBoundaryProcess.cpp b/Sim/GaussPhotonics/src/srcG4Photonics/RhCkvG4OpBoundaryProcess.cpp
new file mode 100644
index 000000000..388ffc4f1
--- /dev/null
+++ b/Sim/GaussPhotonics/src/srcG4Photonics/RhCkvG4OpBoundaryProcess.cpp
@@ -0,0 +1,1819 @@
+//
+// ********************************************************************
+// * License and Disclaimer                                           *
+// *                                                                  *
+// * The  Geant4 software  is  copyright of the Copyright Holders  of *
+// * the Geant4 Collaboration.  It is provided  under  the terms  and *
+// * conditions of the Geant4 Software License,  included in the file *
+// * LICENSE and available at  http://cern.ch/geant4/license .  These *
+// * include a list of copyright holders.                             *
+// *                                                                  *
+// * Neither the authors of this software system, nor their employing *
+// * institutes,nor the agencies providing financial support for this *
+// * work  make  any representation or  warranty, express or implied, *
+// * regarding  this  software system or assume any liability for its *
+// * use.  Please see the license in the file  LICENSE  and URL above *
+// * for the full disclaimer and the limitation of liability.         *
+// *                                                                  *
+// * This  code  implementation is the result of  the  scientific and *
+// * technical work of the GEANT4 collaboration.                      *
+// * By using,  copying,  modifying or  distributing the software (or *
+// * any work based  on the software)  you  agree  to acknowledge its *
+// * use  in  resulting  scientific  publications,  and indicate your *
+// * acceptance of all terms of the Geant4 Software license.          *
+// ********************************************************************
+//
+////////////////////////////////////////////////////////////////////////
+// Optical Photon Boundary Process Class Implementation
+// with modification for LHCb
+////////////////////////////////////////////////////////////////////////
+//
+// File:        RhCkvG4OpBoundaryProcess.cc
+// Description: Discrete Process -- reflection/refraction at
+//                                  optical interfaces
+// Version:     1.1
+// Created:     1997-06-18
+// Modified:    1998-05-25 - Correct parallel component of polarization
+//                           (thanks to: Stefano Magni + Giovanni Pieri)
+//              1998-05-28 - NULL Rindex pointer before reuse
+//                           (thanks to: Stefano Magni)
+//              1998-06-11 - delete *sint1 in oblique reflection
+//                           (thanks to: Giovanni Pieri)
+//              1998-06-19 - move from GetLocalExitNormal() to the new
+//                           method: GetLocalExitNormal(&valid) to get
+//                           the surface normal in all cases
+//              1998-11-07 - NULL OpticalSurface pointer before use
+//                           comparison not sharp for: std::abs(cost1) < 1.0
+//                           remove sin1, sin2 in lines 556,567
+//                           (thanks to Stefano Magni)
+//              1999-10-10 - Accommodate changes done in DoAbsorption by
+//                           changing logic in DielectricMetal
+//              2001-10-18 - avoid Linux (gcc-2.95.2) warning about variables
+//                           might be used uninitialized in this function
+//                           moved E2_perp, E2_parl and E2_total out of 'if'
+//              2003-11-27 - Modified line 168-9 to reflect changes made to
+//                           G4OpticalSurface class ( by Fan Lei)
+//              2004-02-02 - Set theStatus = Undefined at start of DoIt
+//              2005-07-28 - add G4ProcessType to constructor
+//              2006-11-04 - add capability of calculating the reflectivity
+//                           off a metal surface by way of a complex index
+//                           of refraction - Thanks to Sehwook Lee and John
+//                           Hauptman (Dept. of Physics - Iowa State Univ.)
+//              2009-11-10 - add capability of simulating surface reflections
+//                           with Look-Up-Tables (LUT) containing measured
+//                           optical reflectance for a variety of surface
+//                           treatments - Thanks to Martin Janecek and
+//                           William Moses (Lawrence Berkeley National Lab.)
+//              2013-06-01 - add the capability of simulating the transmission
+//                           of a dichronic filter
+//              2017-02-24 - add capability of simulating surface reflections
+//                           with Look-Up-Tables (LUT) developed in DAVIS
+//
+//              Modif SE  01-09-2021
+//
+// Author:      Peter Gumplinger
+// 		adopted from work by Werner Keil - April 2/96
+//
+////////////////////////////////////////////////////////////////////////
+
+#include "Geant4/G4ios.hh"
+#include "Geant4/G4SystemOfUnits.hh"
+#include "Geant4/G4PhysicalConstants.hh"
+#include "Geant4/G4OpProcessSubType.hh"
+#include "Geant4/G4GeometryTolerance.hh"
+#include "Geant4/G4VSensitiveDetector.hh"
+#include "Geant4/G4ParallelWorldProcess.hh"
+#include "Geant4/G4TransportationManager.hh"
+#include "Geant4/G4LogicalBorderSurface.hh"
+#include "Geant4/G4LogicalSkinSurface.hh"
+
+//#include "Geant4/G4OpticalParameters.hh"
+#include "GaussPhotonics/RhCkvG4OpBoundaryProcess.h"
+
+#include "Detector/Rich1/RichGeoUtil.h"
+#include "Detector/Rich2/Rich2GeoUtil.h"
+#include "Detector/Rich1/RichPmtGeoAux.h"
+#include "DD4hep/DetectorData.h"
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+RhCkvG4OpBoundaryProcess::RhCkvG4OpBoundaryProcess(const G4String& processName,
+                                         G4ProcessType type)
+  : G4VDiscreteProcess(processName, type)
+{
+  Initialise();
+
+  if(verboseLevel > 0)
+  {
+    G4cout << GetProcessName() << " is created " << G4endl;
+  }
+  SetProcessSubType(fOpBoundary);
+
+  theStatus           = Undefined;
+  theModel            = glisur;
+  theFinish           = polished;
+  theReflectivity     = 1.;
+  theEfficiency       = 0.;
+  theTransmittance    = 0.;
+  theSurfaceRoughness = 0.;
+  prob_sl             = 0.;
+  prob_ss             = 0.;
+  prob_bs             = 0.;
+
+  fRealRIndexMPV = nullptr;
+  fImagRIndexMPV = nullptr;
+  Material1      = nullptr;
+  Material2      = nullptr;
+  OpticalSurface = nullptr;
+  kCarTolerance  = G4GeometryTolerance::GetInstance()->GetSurfaceTolerance();
+
+  iTE = iTM         = 0;
+  thePhotonMomentum = 0.;
+  Rindex1 = Rindex2 = 1.;
+  cost1 = cost2 = sint1 = sint2 = 0.;
+  idx = idy      = 0;
+  DichroicVector = nullptr;
+  CurPhotStepNum=0;
+  theMaxPhotStepNumInBoundaryProc=5000;
+
+
+  m_Material1Index= -1;
+  m_Material2Index= -2;
+  m_Rich1GasQWMatIndex= -10;
+  m_Rich2GasQWMatIndex= -11;
+  m_RichPmtQWMatIndex = -12;
+  m_RichAirMatIndex   = -13;
+  m_Rich1NitrogenMatIndex = -14;
+  m_RichPmtPhCathMatIndex = -15;
+  m_RichPmtQWMatIndex     = -16;
+  m_RichPmtVacMatIndex    = -17;
+  m_Rich1C4F10MatIndex    = -18;
+  m_Rich1RadiatorGasMatIndex = -19;
+  m_Rich2NitrogenMatIndex    = -20;
+  m_Rich2CF4MatIndex         = -21;
+  m_Rich2RadiatorGasMatIndex = -22;
+
+  m_RichTotalIntReflCheckList.clear();
+  m_RichTotalIntReflCheckList.reserve(3);
+
+  m_RichTransCoefCheckPairList.clear();
+  m_RichTransCoefCheckSingleList.clear();
+  m_RichTransCoefCheckSingleList.reserve(2);
+  m_RichReflSupCheckPairList.clear();
+  m_RichARCoatCheckPairList.clear();
+
+  SetRhCkvOptMatIndex();
+
+  // dd4hep::Detector& curDetector = dd4hep::Detector::getInstance();       
+ // TGeoManager& aGeoMan = curDetector.manager();
+  // TGDMLMatrix* aTable = curDetector.manager().GetGDMLMatrix("NominalPmtQuantumEff");
+  // aTable->Print();
+ 
+ //dd4hep::Material& aTestMat  = curDetector.material( );
+ 
+
+}
+
+
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+RhCkvG4OpBoundaryProcess::~RhCkvG4OpBoundaryProcess() {}
+
+
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+void RhCkvG4OpBoundaryProcess::SetRhCkvOptMatIndex() {
+
+
+  RichGeoUtil*  aRichGeoUtil = RichGeoUtil::getRichGeoUtilInstance();
+  Rich2GeoUtil* aRich2GeoUtil = Rich2GeoUtil::getRich2GeoUtilInstance();
+  RichPmtGeoAux* aRichPmtGeoAux = RichPmtGeoAux::getRichPmtGeoAuxInstance();
+  /*
+  std::string aRich1GasQWMatName = aRichGeoUtil->Rich1GasQuartzWMatName();
+  std::string aRich2GasQWMatName = aRich2GeoUtil->  Rich2GasQuartzWMatName();
+  std::string aRichPmQWMatName   = aRichPmtGeoAux ->RichPmtQuartzMatName();
+
+
+  std::string aRichAirMatName         =  aRichGeoUtil-> RichMasterMatName();
+  std::string aRich1NitrogenMatName   =  aRichGeoUtil-> Rich1NitrogenMatName() ;
+  std::string aRichPmtPhCathMatName   =  aRichPmtGeoAux -> RichPmtPhCathMatName() ;
+  std::string aRichPmtQWMatName       =  aRichPmtGeoAux -> RichPmtQWMatName() ;
+  std::string aRichPmtVacMatName      =  aRichPmtGeoAux -> RichPmtVacMatName() ;
+  std::string aRich1C4F10MatName      =  aRichGeoUtil-> Rich1C4F10MatName() ;
+  std::string aRich1RadiatorGasMatName=  aRichGeoUtil-> Rich1RadiatorGasMatName ();
+  std::string aRich2NitrogenMatName   =  aRich2GeoUtil-> Rich2NitrogenMatName() ;
+  std::string aRich2CF4MatName        =  aRich2GeoUtil-> Rich2CF4MatName () ;
+  std::string aRich2RadiatorGasMatName = aRich2GeoUtil-> Rich2RadiatorGasMatName () ;
+
+  */
+
+  m_Rich1GasQWMatIndex =  FindG4MatIndex(aRichGeoUtil->Rich1GasQuartzWMatName(),-100 );
+  m_Rich2GasQWMatIndex =  FindG4MatIndex(aRich2GeoUtil->  Rich2GasQuartzWMatName(), -101);
+  m_RichPmtQWMatIndex  =  FindG4MatIndex(aRichPmtGeoAux ->RichPmtQuartzMatName(), -102);
+
+  m_RichAirMatIndex       =  FindG4MatIndex(aRichGeoUtil-> RichMasterMatName() , -103 );
+  m_Rich1NitrogenMatIndex =  FindG4MatIndex(aRichGeoUtil-> Rich1NitrogenMatName() , -104);
+  m_RichPmtPhCathMatIndex =  FindG4MatIndex(aRichPmtGeoAux -> RichPmtPhCathMatName(), -105);
+  m_RichPmtQWMatIndex     =  FindG4MatIndex(aRichPmtGeoAux -> RichPmtQWMatName(), -106);
+  m_RichPmtVacMatIndex    =  FindG4MatIndex(aRichPmtGeoAux -> RichPmtVacMatName(), -107);
+  m_Rich1C4F10MatIndex    =  FindG4MatIndex(aRichGeoUtil-> Rich1C4F10MatName(), -108);
+  m_Rich1RadiatorGasMatIndex = FindG4MatIndex(aRichGeoUtil-> Rich1RadiatorGasMatName (), -109);
+  m_Rich2NitrogenMatIndex    = FindG4MatIndex(aRich2GeoUtil-> Rich2NitrogenMatName(), -110);
+  m_Rich2CF4MatIndex         = FindG4MatIndex(aRich2GeoUtil-> Rich2CF4MatName (), -111);
+  m_Rich2RadiatorGasMatIndex = FindG4MatIndex(aRich2GeoUtil-> Rich2RadiatorGasMatName (), -112);
+  
+  m_RichTotalIntReflCheckList.push_back(m_Rich1GasQWMatIndex);
+  m_RichTotalIntReflCheckList.push_back(m_Rich2GasQWMatIndex);
+  m_RichTotalIntReflCheckList.push_back(m_RichPmtQWMatIndex);
+
+  typedef std::pair<G4int,G4int> aTransCoefPair;
+  m_RichTransCoefCheckPairList.insert(aTransCoefPair(m_Rich1NitrogenMatIndex,m_RichPmtVacMatIndex));
+  m_RichTransCoefCheckPairList.insert(aTransCoefPair(m_Rich2NitrogenMatIndex,m_RichPmtVacMatIndex));
+  m_RichTransCoefCheckPairList.insert(aTransCoefPair(m_RichPmtVacMatIndex,m_Rich1NitrogenMatIndex));
+  m_RichTransCoefCheckPairList.insert(aTransCoefPair(m_RichPmtVacMatIndex,m_Rich2NitrogenMatIndex));
+  m_RichTransCoefCheckPairList.insert(aTransCoefPair(m_Rich1NitrogenMatIndex,m_Rich1C4F10MatIndex));
+  m_RichTransCoefCheckPairList.insert(aTransCoefPair(m_Rich1NitrogenMatIndex,m_Rich1RadiatorGasMatIndex));
+  m_RichTransCoefCheckPairList.insert(aTransCoefPair(m_Rich1C4F10MatIndex,m_Rich1NitrogenMatIndex));
+  m_RichTransCoefCheckPairList.insert(aTransCoefPair(m_Rich1RadiatorGasMatIndex,m_Rich1NitrogenMatIndex));
+  m_RichTransCoefCheckPairList.insert(aTransCoefPair(m_Rich2NitrogenMatIndex,m_Rich2CF4MatIndex));
+  m_RichTransCoefCheckPairList.insert(aTransCoefPair(m_Rich2NitrogenMatIndex,m_Rich2RadiatorGasMatIndex)); 
+  m_RichTransCoefCheckPairList.insert(aTransCoefPair(m_Rich2CF4MatIndex,m_Rich2NitrogenMatIndex));
+  m_RichTransCoefCheckPairList.insert(aTransCoefPair(m_Rich2RadiatorGasMatIndex,m_Rich2NitrogenMatIndex));
+  
+
+  m_RichTransCoefCheckSingleList.push_back(m_RichAirMatIndex);
+  m_RichTransCoefCheckSingleList.push_back(m_RichPmtPhCathMatIndex);
+  m_RichTransCoefCheckSingleList.push_back(m_RichPmtQWMatIndex);  
+
+  m_RichReflSupCheckPairList.insert(aTransCoefPair(m_Rich1NitrogenMatIndex,m_Rich1GasQWMatIndex));
+  m_RichReflSupCheckPairList.insert(aTransCoefPair(m_Rich1GasQWMatIndex,m_Rich1NitrogenMatIndex));
+  m_RichReflSupCheckPairList.insert(aTransCoefPair(m_Rich2NitrogenMatIndex, m_Rich2GasQWMatIndex));
+  m_RichReflSupCheckPairList.insert(aTransCoefPair(m_Rich2GasQWMatIndex,m_Rich2NitrogenMatIndex));
+  m_RichReflSupCheckPairList.insert(aTransCoefPair(m_Rich2CF4MatIndex, m_Rich2GasQWMatIndex));
+  m_RichReflSupCheckPairList.insert(aTransCoefPair(m_Rich2RadiatorGasMatIndex, m_Rich2GasQWMatIndex));
+  m_RichReflSupCheckPairList.insert(aTransCoefPair(m_Rich2GasQWMatIndex,m_Rich2CF4MatIndex  ));
+  m_RichReflSupCheckPairList.insert(aTransCoefPair(m_Rich2GasQWMatIndex,m_Rich2RadiatorGasMatIndex));
+  
+
+  m_RichARCoatCheckPairList.insert(aTransCoefPair(m_Rich1NitrogenMatIndex,m_Rich1GasQWMatIndex));
+  m_RichARCoatCheckPairList.insert(aTransCoefPair(m_Rich1GasQWMatIndex,m_Rich1NitrogenMatIndex));
+
+   // For now, with the line above , avoiding the
+  // reflections at the PmtQW surface, considering its effect is already in QE. This may be reviewed in the future
+  // as part of fine tuning.
+  
+
+  /*  
+  static const G4MaterialTable* theMaterialTable = G4Material::GetMaterialTable();
+  auto aR1QW_itr = std::find_if(theMaterialTable->begin(),theMaterialTable->end(),
+                          [&aRich1GasQWMatName] (const G4Material* aM ) {return (aM ->GetName() == aRich1GasQWMatName) ; });
+  if( aR1QW_itr != theMaterialTable->end()) {
+    //     auto aRQW_index = std::distance(theMaterialTable->begin(),aR1QW_itr);
+    // m_Rich1GasQWMatIndex = (*theMaterialTable)[aRQW_index] ->GetIndex();
+    m_Rich1GasQWMatIndex = (*aR1QW_itr) ->  GetIndex();
+    m_RichTotalIntReflCheckList.push_back(m_Rich1GasQWMatIndex);
+  }else { 
+    m_Rich1GasQWMatIndex=-100;  //in this case, this material does not exist.
+  }
+  
+  auto aR2QW_itr = std::find_if(theMaterialTable->begin(),theMaterialTable->end(),
+                          [&aRich2GasQWMatName] (const G4Material* aM ) {return (aM ->GetName() == aRich2GasQWMatName) ; });
+
+  if( aR2QW_itr != theMaterialTable->end()) {
+   m_Rich2GasQWMatIndex = (*aR2QW_itr) ->  GetIndex();
+   m_RichTotalIntReflCheckList.push_back(m_Rich2GasQWMatIndex);
+  }else {
+    m_Rich2GasQWMatIndex=-101; //in this case, this material does not exist.
+  }
+
+  auto aPmQW_itr = std::find_if(theMaterialTable->begin(),theMaterialTable->end(),
+                          [&aRichPmQWMatName] (const G4Material* aM ) {return (aM ->GetName() == aRichPmQWMatName) ; });
+  if( aPmQW_itr != theMaterialTable->end()) {
+   m_RichPmtQWMatIndex = (*aPmQW_itr) ->  GetIndex();
+   m_RichTotalIntReflCheckList.push_back(m_RichPmtQWMatIndex);
+  }else {
+    m_RichPmtQWMatIndex =-102; // in this case, this material does not exist
+  }
+  */
+
+
+  /*  
+  G4int numberOfMat= theMaterialTable->size() ;
+    
+
+  for (iMat = 0 ; iMat < (int) theMaterialTable->size() ; ++iMat ) {
+    G4String aCurMatName =   (*theMaterialTable)[iMat]->GetName() ;  
+    
+    if(m_Rich1GasQWMatIndex == -1 ) {
+      if( (aRichGeoUtil->Rich1GasQuartzWMatName()) == aCurMatName ) {
+        m_Rich1GasQWMatIndex = (*theMaterialTable)[iMat]->GetIndex();
+     }
+    }
+
+    if (m_Rich2GasQWMatIndex == -1) {
+      if( (aRich2GeoUtil-> Rich2GasQuartzWMatName() ) == aCurMatName ) { 
+        m_Rich2GasQWMatIndex = (*theMaterialTable)[iMat]->GetIndex();
+     }
+    }
+
+    if( m_RichPmtQWMatIndex == -1) {
+      if( (aRichPmtGeoAux -> RichPmtQuartzMatName() ) == aCurMatName  ) { 
+        m_RichPmtQWMatIndex = (*theMaterialTable)[iMat]->GetIndex();
+   
+     }
+    }
+  }
+  */
+
+
+}
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+G4int RhCkvG4OpBoundaryProcess::FindG4MatIndex (std::string aMatName, G4int aDummyIndex ) {
+  G4int aMatIndex = aDummyIndex;
+  const G4String bMatName = aMatName;
+  static const G4MaterialTable* theMaterialTable = G4Material::GetMaterialTable();
+  auto aR_itr = std::find_if(theMaterialTable->begin(),theMaterialTable->end(),
+			     [&bMatName] (const auto &aM ) {return (aM->GetName() ==  bMatName);});
+  if( aR_itr != theMaterialTable->end()) {
+    aMatIndex = (*aR_itr) ->  GetIndex();
+  }
+  
+  return aMatIndex;
+
+}
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+void RhCkvG4OpBoundaryProcess::PreparePhysicsTable(const G4ParticleDefinition&)
+{
+  Initialise();
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+void RhCkvG4OpBoundaryProcess::Initialise()
+{
+  //The following are already set from GaussCkvOpicalPhysicsList so that it can be controlled
+  // by options files. Hence it is avoided here. The SD is not used at any of the optical boundaries anyway.
+  //  G4OpticalParameters* params = G4OpticalParameters::Instance();
+  // SetInvokeSD(params->GetBoundaryInvokeSD());
+  // SetVerboseLevel(params->GetBoundaryVerboseLevel());
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+G4VParticleChange* RhCkvG4OpBoundaryProcess::PostStepDoIt(const G4Track& aTrack,
+                                                     const G4Step& aStep)
+{
+  theStatus = Undefined;
+  aParticleChange.Initialize(aTrack);
+  aParticleChange.ProposeVelocity(aTrack.GetVelocity());
+
+  // Get hyperStep from  G4ParallelWorldProcess
+  //  NOTE: PostSetpDoIt of this process to be invoked after
+  //  G4ParallelWorldProcess!
+  const G4Step* pStep = &aStep;
+  // // //
+  const G4Step* hStep = G4ParallelWorldProcess::GetHyperStep();
+  if(hStep)
+    pStep = hStep;
+  // //  //
+
+  G4bool isOnBoundary =
+    (pStep->GetPostStepPoint()->GetStepStatus() == fGeomBoundary);
+  if(isOnBoundary)
+  {
+    Material1 = pStep->GetPreStepPoint()->GetMaterial();
+    Material2 = pStep->GetPostStepPoint()->GetMaterial();
+    CurPhotStepNum=  aTrack.GetCurrentStepNumber() ;
+    m_Material1Index = Material1 ->GetIndex();
+    m_Material2Index = Material2 ->GetIndex();
+
+  }
+  else
+  {
+    theStatus = NotAtBoundary;
+    if(verboseLevel > 1)BoundaryProcessVerbose();
+    return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
+  }
+
+  G4VPhysicalVolume* thePrePV  = pStep->GetPreStepPoint()->GetPhysicalVolume();
+  G4VPhysicalVolume* thePostPV = pStep->GetPostStepPoint()->GetPhysicalVolume();
+
+  if(verboseLevel > 1)
+   {
+    G4cout << " RhCkvG4OpBP Photon at Boundary! " << G4endl;
+    if(thePrePV)  G4cout << " thePrePV:  " << thePrePV->GetName() << G4endl;
+    if(thePostPV) G4cout << " thePostPV: " << thePostPV->GetName() << G4endl;
+    }
+
+  if(aTrack.GetStepLength() <= kCarTolerance)
+  {
+    theStatus = StepTooSmall;
+    if(verboseLevel > 1)BoundaryProcessVerbose();
+    return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
+  }
+
+  const G4DynamicParticle* aParticle = aTrack.GetDynamicParticle();
+
+  thePhotonMomentum = aParticle->GetTotalMomentum();
+  OldMomentum       = aParticle->GetMomentumDirection();
+  OldPolarization   = aParticle->GetPolarization();
+
+  if(verboseLevel > 1)
+  {
+    G4cout << " Old Momentum Direction: " << OldMomentum << G4endl
+           << " Old Polarization:       " << OldPolarization << G4endl;
+  }
+
+  G4ThreeVector theGlobalPoint = pStep->GetPostStepPoint()->GetPosition();
+  G4bool valid;
+
+  // Remake Global normal for test and comment out the G4 update. SE. 21-Dec-2021
+        G4Navigator* theNavigator =
+                     G4TransportationManager::GetTransportationManager()->
+                                              GetNavigatorForTracking(); 
+       
+	G4ThreeVector theLocalNormal = theNavigator->GetLocalExitNormal(&valid);   	// Normal points back into volume
+        
+        if (valid) {
+	  theLocalNormal = -theLocalNormal;
+	}
+	else {
+          G4cout<< " RhCkvG4OpBP invalid local normal  GlobalPoint PreName PostName  "
+                <<theLocalNormal<<"   "
+                << theGlobalPoint <<"   "<< thePrePV->GetName() <<"   "
+                << thePostPV->GetName() <<G4endl;
+          G4ExceptionDescription edL;
+	  edL << " RichCkvG4OpBoundaryProcess/PostStepDoIt(): "
+	       << " The Navigator reports that it returned an invalid normal" 
+	       << G4endl;
+         G4Exception(
+             "RhCkvG4OpBoundaryProcess::PostStepDoIt", "OpBoun01", EventMustBeAborted, edL,
+              "Invalid Surface Local Normal - Geometry must return valid surface normal");
+
+	}
+	theGlobalNormal = theNavigator->GetLocalToGlobalTransform().
+	                                TransformAxis(theLocalNormal);
+
+        if (OldMomentum * theGlobalNormal > 0.0) {       
+
+           theGlobalNormal = -theGlobalNormal;
+           G4cout<<" Invalid Global normal -  OldMomentum LocalNormal GlobalNormal GlobalPoint PreVol PostVol "
+                 <<OldMomentum <<"   "<<theLocalNormal<<"   "
+                 <<theGlobalNormal <<"    "<< theGlobalPoint <<"   "
+                 <<   thePrePV->GetName() <<"   "
+		 << thePostPV->GetName() <<G4endl;
+
+           G4ExceptionDescription edG;
+           G4Exception("RhCkvG4OpBoundaryProcess::PostStepDoIt", "OpBoun02",
+                EventMustBeAborted,edG,
+                "Invalid Surface Global Normal - Geometry must return valid Global surface "
+                "normal pointing in the right direction");
+	
+	}
+      
+  ///  End of GlobalNormal Update
+
+  // The following lines commented out and replaced by the lines above. SE 21-Dec-2021
+  // ID of Navigator which limits step
+	/*
+  G4int hNavId = G4ParallelWorldProcess::GetHypNavigatorID();
+  auto iNav    = G4TransportationManager::GetTransportationManager()
+               ->GetActiveNavigatorsIterator();
+  theGlobalNormal = (iNav[hNavId])->GetGlobalExitNormal(theGlobalPoint, &valid);
+
+  if(valid)
+  {
+    theGlobalNormal = -theGlobalNormal;
+  }
+  else
+  {
+    G4ExceptionDescription ed;
+    ed << " RhCkvG4OpBoundaryProcess/PostStepDoIt(): "
+       << " The Navigator reports that it returned an invalid normal" << G4endl;
+    G4Exception(
+      "RhCkvG4OpBoundaryProcess::PostStepDoIt", "OpBoun01", EventMustBeAborted, ed,
+      "Invalid Surface Normal - Geometry must return valid surface normal");
+  }
+
+  if(OldMomentum * theGlobalNormal > 0.0)
+  {
+#ifdef G4OPTICAL_DEBUG
+    G4ExceptionDescription ed;
+    ed << " RhCkvG4OpBoundaryProcess/PostStepDoIt(): theGlobalNormal points in a "
+          "wrong direction. "
+       << G4endl
+       << "   The momentum of the photon arriving at interface (oldMomentum)"
+       << "   must exit the volume cross in the step. " << G4endl
+       << "   So it MUST have dot < 0 with the normal that Exits the new "
+          "volume (globalNormal)."
+       << G4endl << "   >> The dot product of oldMomentum and global Normal is "
+       << OldMomentum * theGlobalNormal << G4endl
+       << "     Old Momentum  (during step)     = " << OldMomentum << G4endl
+       << "     Global Normal (Exiting New Vol) = " << theGlobalNormal << G4endl
+       << G4endl;
+    G4Exception("RhCkvG4OpBoundaryProcess::PostStepDoIt", "OpBoun02",
+                EventMustBeAborted,  // Or JustWarning to see if it happens
+                                     // repeatedly on one ray
+                ed,
+                "Invalid Surface Normal - Geometry must return valid surface "
+                "normal pointing in the right direction");
+#else
+    theGlobalNormal = -theGlobalNormal;
+#endif
+  }
+	*/
+	//End of lines commented out for Global normal
+
+  G4MaterialPropertyVector* RindexMPV = nullptr;
+  G4MaterialPropertiesTable* MPT      = Material1->GetMaterialPropertiesTable();
+  if(MPT)
+  {
+    RindexMPV = MPT->GetProperty(kRINDEX);
+  }
+  else
+  {
+    theStatus = NoRINDEX;
+    if(verboseLevel > 1) BoundaryProcessVerbose();
+    aParticleChange.ProposeLocalEnergyDeposit(thePhotonMomentum);
+    aParticleChange.ProposeTrackStatus(fStopAndKill);
+    return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
+  }
+
+  if(RindexMPV)
+  {
+    Rindex1 = RindexMPV->Value(thePhotonMomentum, idx_rindex1);
+  }
+  else
+  {
+    theStatus = NoRINDEX;
+    if(verboseLevel > 1)
+      BoundaryProcessVerbose();
+    aParticleChange.ProposeLocalEnergyDeposit(thePhotonMomentum);
+    aParticleChange.ProposeTrackStatus(fStopAndKill);
+    return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
+  }
+
+  theReflectivity     = 1.;
+  theEfficiency       = 0.;
+  theTransmittance    = 0.;
+  theSurfaceRoughness = 0.;
+  theModel            = glisur;
+  theFinish           = polished;
+  G4SurfaceType type  = dielectric_dielectric;
+
+  RindexMPV      = nullptr;
+  OpticalSurface = nullptr;
+  G4LogicalSurface* Surface =
+    G4LogicalBorderSurface::GetSurface(thePrePV, thePostPV);
+
+  if(Surface == nullptr)
+  {
+    if(thePostPV->GetMotherLogical() == thePrePV->GetLogicalVolume())
+    {
+      Surface = G4LogicalSkinSurface::GetSurface(thePostPV->GetLogicalVolume());
+      if(Surface == nullptr)
+      {
+        Surface =
+          G4LogicalSkinSurface::GetSurface(thePrePV->GetLogicalVolume());
+      }
+    }
+    else
+    {
+      Surface = G4LogicalSkinSurface::GetSurface(thePrePV->GetLogicalVolume());
+      if(Surface == nullptr)
+      {
+        Surface =
+          G4LogicalSkinSurface::GetSurface(thePostPV->GetLogicalVolume());
+      }
+    }
+  }
+
+  // G4cout<<" RhCkvBP Pre Postvol Surface " <<  thePrePV->GetName()<<"   "<<the// PostPV->GetName() <<"  "<<Surface <<G4endl;
+
+
+  if(Surface)
+  {
+    OpticalSurface =
+      dynamic_cast<G4OpticalSurface*>(Surface->GetSurfaceProperty());
+  }
+  if(OpticalSurface)
+  {
+    type      = OpticalSurface->GetType();
+    theModel  = OpticalSurface->GetModel();
+    theFinish = OpticalSurface->GetFinish();
+
+    // G4cout<<" RhCkvBP Pre Postvol SurfaceProperty type " << thePrePV->GetName()<<"   "<<thePostPV->GetName() <<"  "<<type<<G4endl;
+
+    G4MaterialPropertiesTable* sMPT =
+      OpticalSurface->GetMaterialPropertiesTable();
+    if(sMPT)
+    {
+      if(theFinish == polishedbackpainted || theFinish == groundbackpainted)
+      {
+        RindexMPV = sMPT->GetProperty(kRINDEX);
+        if(RindexMPV)
+        {
+          Rindex2 = RindexMPV->Value(thePhotonMomentum, idx_rindex_surface);
+        }
+        else
+        {
+          theStatus = NoRINDEX;
+          if(verboseLevel > 1)BoundaryProcessVerbose();
+          aParticleChange.ProposeLocalEnergyDeposit(thePhotonMomentum);
+          aParticleChange.ProposeTrackStatus(fStopAndKill);
+          return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
+        }
+      }
+
+      fRealRIndexMPV = sMPT->GetProperty(kREALRINDEX);
+      fImagRIndexMPV = sMPT->GetProperty(kIMAGINARYRINDEX);
+      iTE = iTM = 1;
+
+      G4MaterialPropertyVector* pp;
+      if((pp = sMPT->GetProperty(kREFLECTIVITY)))
+      {
+        theReflectivity = pp->Value(thePhotonMomentum, idx_reflect);
+      }
+      else if(fRealRIndexMPV && fImagRIndexMPV)
+      {
+        CalculateReflectivity();
+      }
+
+      if((pp = sMPT->GetProperty(kEFFICIENCY)))
+      {
+        theEfficiency = pp->Value(thePhotonMomentum, idx_eff);
+      }
+      if((pp = sMPT->GetProperty(kTRANSMITTANCE)))
+      {
+        theTransmittance = pp->Value(thePhotonMomentum, idx_trans);
+      }
+      //The following to be uncommented after we start using a version above G4-10-6.1 in LHCb
+      // and then the two temporary replacement lines after these can be commented out. 
+      //      if(sMPT->ConstPropertyExists(kSURFACEROUGHNESS))
+      // {
+      //  theSurfaceRoughness = sMPT->GetConstProperty(kSURFACEROUGHNESS);
+      // }
+      // start of temporary replacement lines
+      if(sMPT->ConstPropertyExists("SURFACEROUGHNESS"))
+      {
+        theSurfaceRoughness = sMPT->GetConstProperty(kSURFACEROUGHNESS);
+      }
+      // end of temporary replacement lines
+
+      if(theModel == unified)
+      {
+        prob_sl = (pp = sMPT->GetProperty(kSPECULARLOBECONSTANT))
+                    ? pp->Value(thePhotonMomentum, idx_lobe)
+                    : 0.;
+        prob_ss = (pp = sMPT->GetProperty(kSPECULARSPIKECONSTANT))
+                    ? pp->Value(thePhotonMomentum, idx_spike)
+                    : 0.;
+        prob_bs = (pp = sMPT->GetProperty(kBACKSCATTERCONSTANT))
+                    ? pp->Value(thePhotonMomentum, idx_back)
+                    : 0.;
+      }
+    }  // end of if(sMPT)
+    else if(theFinish == polishedbackpainted || theFinish == groundbackpainted)
+    {
+      aParticleChange.ProposeLocalEnergyDeposit(thePhotonMomentum);
+      aParticleChange.ProposeTrackStatus(fStopAndKill);
+      return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
+    }
+  }  // end of if(OpticalSurface)
+
+  // test print
+  /*
+  G4cout<<" RhCkvBP M1 M2 Rndx1 Rndx2 type status refl transProb Position PrePhys PostPhys  "<<Material1->GetName()<<"   "
+        <<Material2->GetName()<<"   "<< ((Material1->GetMaterialPropertiesTable() )? Material1->GetMaterialPropertiesTable()->GetProperty(kRINDEX): 0 )
+        <<"   "<< (( Material2->GetMaterialPropertiesTable()) ? Material2->GetMaterialPropertiesTable()->GetProperty(kRINDEX):0 )<< "  "<< type << "  "<<theStatus<<"  "<< theReflectivity <<"  "<<theTransmittance<<
+    "    "<<  pStep->GetPreStepPoint()->GetPosition() << "  "
+     <<pStep->GetPreStepPoint()->GetPhysicalVolume()->GetName() <<"    "<< pStep->GetPostStepPoint()->GetPhysicalVolume()->GetName()<<   G4endl;
+  */
+  // end test print
+
+  //  DIELECTRIC-DIELECTRIC
+  if(type == dielectric_dielectric)
+  {
+    if(theFinish == polished || theFinish == ground)
+    {
+      if(Material1 == Material2)
+      {
+        theStatus = SameMaterial;
+        if(verboseLevel > 1)BoundaryProcessVerbose();
+        return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
+      }
+      MPT = Material2->GetMaterialPropertiesTable();
+      if(MPT)
+      {
+        RindexMPV = MPT->GetProperty(kRINDEX);
+      }
+      if(RindexMPV)
+      {
+        Rindex2 = RindexMPV->Value(thePhotonMomentum, idx_rindex2);
+      }
+      else
+      {
+        theStatus = NoRINDEX;
+        if(verboseLevel > 1)BoundaryProcessVerbose();
+        aParticleChange.ProposeLocalEnergyDeposit(thePhotonMomentum);
+        aParticleChange.ProposeTrackStatus(fStopAndKill);
+        return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
+      }
+    }
+    if(theFinish == polishedbackpainted || theFinish == groundbackpainted)
+    {
+      DielectricDielectric();
+    }
+    else
+    {
+      G4double rand = G4UniformRand();
+      if(rand > theReflectivity + theTransmittance)
+      {
+	//test print 
+	//	G4cout<<" RhCkvBP Photon absorbed Refl Tr rand "<< theReflectivity<<"  "<<theTransmittance<<" "<<rand<<G4endl;
+        // end test print
+        DoAbsorption();
+      }
+      else if(rand > theReflectivity)
+      {
+        theStatus       = Transmission;
+        NewMomentum     = OldMomentum;
+        NewPolarization = OldPolarization;
+      }
+      else
+      {
+        if(theFinish == polishedfrontpainted)
+        {
+          DoReflection();
+        }
+        else if(theFinish == groundfrontpainted)
+        {
+          theStatus = LambertianReflection;
+          DoReflection();
+        }
+        else
+        {
+	  //test print 
+	  //  G4cout<<" RhCkvBP Now start DD for position "<< pStep->GetPreStepPoint()->GetPosition()<<  G4endl;
+	  //end test print
+          DielectricDielectric();
+        }
+      }
+    }
+  }
+  else if(type == dielectric_metal)
+  {
+    //  G4cout<<" Now start DM for position "<<pStep->GetPreStepPoint()->GetPosition()<<G4endl;
+
+    DielectricMetal();
+  }
+  else if(type == dielectric_LUT)
+  {
+    DielectricLUT();
+  }
+  else if(type == dielectric_LUTDAVIS)
+  {
+    DielectricLUTDAVIS();
+  }
+  else if(type == dielectric_dichroic)
+  {
+    DielectricDichroic();
+  }
+  else
+  {
+    G4ExceptionDescription ed;
+    ed << " PostStepDoIt(): Illegal boundary type." << G4endl;
+    G4Exception("RhCkvG4OpBoundaryProcess", "OpBoun04", JustWarning, ed);
+    return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
+  }
+
+  NewMomentum     = NewMomentum.unit();
+  NewPolarization = NewPolarization.unit();
+
+  if(verboseLevel > 1)
+  {
+    G4cout << " New Momentum Direction: " << NewMomentum << G4endl
+           << " New Polarization:       " << NewPolarization << G4endl;
+    BoundaryProcessVerbose();
+  }
+
+  aParticleChange.ProposeMomentumDirection(NewMomentum);
+  aParticleChange.ProposePolarization(NewPolarization);
+
+  if(theStatus == FresnelRefraction || theStatus == Transmission)
+  {
+    G4MaterialPropertyVector* groupvel =
+      Material2->GetMaterialPropertiesTable()->GetProperty(kGROUPVEL);
+    if(groupvel)
+    {
+      aParticleChange.ProposeVelocity(
+        groupvel->Value(thePhotonMomentum, idx_groupvel));
+    }
+  }
+
+  if(theStatus == Detection && fInvokeSD)
+    InvokeSD(pStep);
+  return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+void RhCkvG4OpBoundaryProcess::BoundaryProcessVerbose() const
+{
+  G4cout << " *** ";
+  if(theStatus == Undefined)
+    G4cout << "Undefined";
+  else if(theStatus == Transmission)
+    G4cout << "Transmission";
+  else if(theStatus == FresnelRefraction)
+    G4cout << "FresnelRefraction";
+  else if(theStatus == FresnelReflection)
+    G4cout << "FresnelReflection";
+  else if(theStatus == TotalInternalReflection)
+    G4cout << "TotalInternalReflection";
+  else if(theStatus == LambertianReflection)
+    G4cout << "LambertianReflection";
+  else if(theStatus == LobeReflection)
+    G4cout << "LobeReflection";
+  else if(theStatus == SpikeReflection)
+    G4cout << "SpikeReflection";
+  else if(theStatus == BackScattering)
+    G4cout << "BackScattering";
+  else if(theStatus == PolishedLumirrorAirReflection)
+    G4cout << "PolishedLumirrorAirReflection";
+  else if(theStatus == PolishedLumirrorGlueReflection)
+    G4cout << "PolishedLumirrorGlueReflection";
+  else if(theStatus == PolishedAirReflection)
+    G4cout << "PolishedAirReflection";
+  else if(theStatus == PolishedTeflonAirReflection)
+    G4cout << "PolishedTeflonAirReflection";
+  else if(theStatus == PolishedTiOAirReflection)
+    G4cout << "PolishedTiOAirReflection";
+  else if(theStatus == PolishedTyvekAirReflection)
+    G4cout << "PolishedTyvekAirReflection";
+  else if(theStatus == PolishedVM2000AirReflection)
+    G4cout << "PolishedVM2000AirReflection";
+  else if(theStatus == PolishedVM2000GlueReflection)
+    G4cout << "PolishedVM2000GlueReflection";
+  else if(theStatus == EtchedLumirrorAirReflection)
+    G4cout << "EtchedLumirrorAirReflection";
+  else if(theStatus == EtchedLumirrorGlueReflection)
+    G4cout << "EtchedLumirrorGlueReflection";
+  else if(theStatus == EtchedAirReflection)
+    G4cout << "EtchedAirReflection";
+  else if(theStatus == EtchedTeflonAirReflection)
+    G4cout << "EtchedTeflonAirReflection";
+  else if(theStatus == EtchedTiOAirReflection)
+    G4cout << "EtchedTiOAirReflection";
+  else if(theStatus == EtchedTyvekAirReflection)
+    G4cout << "EtchedTyvekAirReflection";
+  else if(theStatus == EtchedVM2000AirReflection)
+    G4cout << "EtchedVM2000AirReflection";
+  else if(theStatus == EtchedVM2000GlueReflection)
+    G4cout << "EtchedVM2000GlueReflection";
+  else if(theStatus == GroundLumirrorAirReflection)
+    G4cout << "GroundLumirrorAirReflection";
+  else if(theStatus == GroundLumirrorGlueReflection)
+    G4cout << "GroundLumirrorGlueReflection";
+  else if(theStatus == GroundAirReflection)
+    G4cout << "GroundAirReflection";
+  else if(theStatus == GroundTeflonAirReflection)
+    G4cout << "GroundTeflonAirReflection";
+  else if(theStatus == GroundTiOAirReflection)
+    G4cout << "GroundTiOAirReflection";
+  else if(theStatus == GroundTyvekAirReflection)
+    G4cout << "GroundTyvekAirReflection";
+  else if(theStatus == GroundVM2000AirReflection)
+    G4cout << "GroundVM2000AirReflection";
+  else if(theStatus == GroundVM2000GlueReflection)
+    G4cout << "GroundVM2000GlueReflection";
+  else if(theStatus == Absorption)
+    G4cout << "Absorption";
+  else if(theStatus == Detection)
+    G4cout << "Detection";
+  else if(theStatus == NotAtBoundary)
+    G4cout << "NotAtBoundary";
+  else if(theStatus == SameMaterial)
+    G4cout << "SameMaterial";
+  else if(theStatus == StepTooSmall)
+    G4cout << "StepTooSmall";
+  else if(theStatus == NoRINDEX)
+    G4cout << "NoRINDEX";
+  else if(theStatus == Dichroic)
+    G4cout << "Dichroic Transmission";
+  G4cout << " ***" << G4endl;
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+G4ThreeVector RhCkvG4OpBoundaryProcess::GetFacetNormal(
+  const G4ThreeVector& Momentum, const G4ThreeVector& Normal) const
+{
+  G4ThreeVector facetNormal;
+  if(theModel == unified || theModel == LUT || theModel == DAVIS)
+  {
+    /* This function codes alpha to a random value taken from the
+    distribution p(alpha) = g(alpha; 0, sigma_alpha)*std::sin(alpha),
+    for alpha > 0 and alpha < 90, where g(alpha; 0, sigma_alpha) is a
+    gaussian distribution with mean 0 and standard deviation sigma_alpha.  */
+
+    G4double sigma_alpha = 0.0;
+    if(OpticalSurface)
+      sigma_alpha = OpticalSurface->GetSigmaAlpha();
+    if(sigma_alpha == 0.0)
+    {
+      return Normal;
+    }
+
+    G4double f_max = std::min(1.0, 4. * sigma_alpha);
+    G4double alpha, phi, sinAlpha;  //, cosPhi, sinPhi;
+
+    do
+    {  // Loop checking, 13-Aug-2015, Peter Gumplinger
+      do
+      {  // Loop checking, 13-Aug-2015, Peter Gumplinger
+        alpha = G4RandGauss::shoot(0.0, sigma_alpha);
+      } while(G4UniformRand() * f_max > std::sin(alpha) || alpha >= halfpi);
+
+      phi      = G4UniformRand() * twopi;
+      sinAlpha = std::sin(alpha);
+      facetNormal.set(sinAlpha * std::cos(phi), sinAlpha * std::sin(phi),
+                      std::cos(alpha));
+      facetNormal.rotateUz(Normal);
+    } while(Momentum * facetNormal >= 0.0);
+  }
+  else
+  {
+    G4double polish = 1.0;
+    if(OpticalSurface)
+      polish = OpticalSurface->GetPolish();
+    if(polish < 1.0)
+    {
+      do
+      {  // Loop checking, 13-Aug-2015, Peter Gumplinger
+        G4ThreeVector smear;
+        do
+        {  // Loop checking, 13-Aug-2015, Peter Gumplinger
+          smear.setX(2. * G4UniformRand() - 1.);
+          smear.setY(2. * G4UniformRand() - 1.);
+          smear.setZ(2. * G4UniformRand() - 1.);
+        } while(smear.mag() > 1.0);
+        facetNormal = Normal + (1. - polish) * smear;
+      } while(Momentum * facetNormal >= 0.0);
+      facetNormal = facetNormal.unit();
+    }
+    else
+    {
+      facetNormal = Normal;
+    }
+  }
+  return facetNormal;
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+void RhCkvG4OpBoundaryProcess::DielectricMetal()
+{
+  G4int n = 0;
+  G4double rand, EdotN;
+  G4ThreeVector A_trans, A_paral;
+
+  do
+  {
+    ++n;
+    rand = G4UniformRand();
+    if(rand > theReflectivity && n == 1)
+    {
+      if(rand > theReflectivity + theTransmittance)
+      {
+        DoAbsorption();
+      }
+      else
+      {
+        theStatus       = Transmission;
+        NewMomentum     = OldMomentum;
+        NewPolarization = OldPolarization;
+      }
+      break;
+    }
+    else
+    {
+      if(fRealRIndexMPV && fImagRIndexMPV)
+      {
+        if(n > 1)
+        {
+          CalculateReflectivity();
+          if(!G4BooleanRand(theReflectivity))
+          {
+            DoAbsorption();
+            break;
+          }
+        }
+      }
+      if(theModel == glisur || theFinish == polished)
+      {
+	// G4cout<<" Now doing DM reflection old new GlobalNormal Before status "
+	//        << OldMomentum <<"  "<< NewMomentum << "   "<<theGlobalNormal<<"  "<< theStatus<< G4endl;
+
+        DoReflection();
+	//  G4cout<<" Now doing DM reflection old new global normal After status "
+	//       << OldMomentum <<"  "<< NewMomentum <<"  "<<theGlobalNormal<<"   "<<theStatus<< G4endl;
+
+      }
+      else
+      {
+        if(n == 1)
+          ChooseReflection();
+        if(theStatus == LambertianReflection)
+        {
+          DoReflection();
+        }
+        else if(theStatus == BackScattering)
+        {
+          NewMomentum     = -OldMomentum;
+          NewPolarization = -OldPolarization;
+        }
+        else
+        {
+          if(theStatus == LobeReflection)
+          {
+            if(fRealRIndexMPV && fImagRIndexMPV)
+            {
+              //
+            }
+            else
+            {
+              theFacetNormal = GetFacetNormal(OldMomentum, theGlobalNormal);
+            }
+          }
+          NewMomentum =
+            OldMomentum - 2. * OldMomentum * theFacetNormal * theFacetNormal;
+          EdotN = OldPolarization * theFacetNormal;
+
+          A_trans = (sint1 > 0.0) ? OldMomentum.cross(theFacetNormal).unit()
+                                  : OldPolarization;
+          A_paral = NewMomentum.cross(A_trans).unit();
+
+          if(iTE > 0 && iTM > 0)
+          {
+            NewPolarization = -OldPolarization + (2. * EdotN) * theFacetNormal;
+          }
+          else if(iTE > 0)
+          {
+            NewPolarization = -A_trans;
+          }
+          else if(iTM > 0)
+          {
+            NewPolarization = -A_paral;
+          }
+        }
+      }
+      OldMomentum     = NewMomentum;
+      OldPolarization = NewPolarization;
+    }
+    // Loop checking, 13-Aug-2015, Peter Gumplinger
+  } while(NewMomentum * theGlobalNormal < 0.0);
+
+  //  G4cout<<" Dielectric metal old New momentum "<< OldMomentum <<"  "<<NewMomentum <<G4endl;
+
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+void RhCkvG4OpBoundaryProcess::DielectricLUT()
+{
+  G4int thetaIndex, phiIndex;
+  G4double AngularDistributionValue, thetaRad, phiRad, EdotN;
+  G4ThreeVector PerpendicularVectorTheta, PerpendicularVectorPhi;
+
+  theStatus = RhCkvG4OpBoundaryProcessStatus(
+    G4int(theFinish) + (G4int(NoRINDEX) - G4int(groundbackpainted)));
+
+  G4int thetaIndexMax = OpticalSurface->GetThetaIndexMax();
+  G4int phiIndexMax   = OpticalSurface->GetPhiIndexMax();
+
+  G4double rand;
+
+  do
+  {
+    rand = G4UniformRand();
+    if(rand > theReflectivity)
+    {
+      if(rand > theReflectivity + theTransmittance)
+      {
+        DoAbsorption();
+      }
+      else
+      {
+        theStatus       = Transmission;
+        NewMomentum     = OldMomentum;
+        NewPolarization = OldPolarization;
+      }
+      break;
+    }
+    else
+    {
+      // Calculate Angle between Normal and Photon Momentum
+      G4double anglePhotonToNormal = OldMomentum.angle(-theGlobalNormal);
+      // Round to closest integer: LBNL model array has 91 values
+      G4int angleIncident = G4lrint(anglePhotonToNormal / CLHEP::deg);
+
+      // Take random angles THETA and PHI,
+      // and see if below Probability - if not - Redo
+      do
+      {
+        thetaIndex = G4RandFlat::shootInt(thetaIndexMax - 1);
+        phiIndex   = G4RandFlat::shootInt(phiIndexMax - 1);
+        // Find probability with the new indeces from LUT
+        AngularDistributionValue = OpticalSurface->GetAngularDistributionValue(
+          angleIncident, thetaIndex, phiIndex);
+        // Loop checking, 13-Aug-2015, Peter Gumplinger
+      } while(!G4BooleanRand(AngularDistributionValue));
+
+      thetaRad = (-90 + 4 * thetaIndex) * pi / 180.;
+      phiRad   = (-90 + 5 * phiIndex) * pi / 180.;
+      // Rotate Photon Momentum in Theta, then in Phi
+      NewMomentum = -OldMomentum;
+
+      PerpendicularVectorTheta = NewMomentum.cross(theGlobalNormal);
+      if(PerpendicularVectorTheta.mag() < kCarTolerance)
+      {
+        PerpendicularVectorTheta = NewMomentum.orthogonal();
+      }
+      NewMomentum = NewMomentum.rotate(anglePhotonToNormal - thetaRad,
+                                       PerpendicularVectorTheta);
+      PerpendicularVectorPhi = PerpendicularVectorTheta.cross(NewMomentum);
+      NewMomentum = NewMomentum.rotate(-phiRad, PerpendicularVectorPhi);
+
+      // Rotate Polarization too:
+      theFacetNormal  = (NewMomentum - OldMomentum).unit();
+      EdotN           = OldPolarization * theFacetNormal;
+      NewPolarization = -OldPolarization + (2. * EdotN) * theFacetNormal;
+    }
+    // Loop checking, 13-Aug-2015, Peter Gumplinger
+  } while(NewMomentum * theGlobalNormal <= 0.0);
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+void RhCkvG4OpBoundaryProcess::DielectricLUTDAVIS()
+{
+  G4int angindex, random, angleIncident;
+  G4double ReflectivityValue, elevation, azimuth, EdotN;
+  G4double anglePhotonToNormal;
+
+  G4int LUTbin  = OpticalSurface->GetLUTbins();
+  G4double rand = G4UniformRand();
+
+  do
+  {
+    anglePhotonToNormal = OldMomentum.angle(-theGlobalNormal);
+
+    // Davis model has 90 reflection bins: round down
+    angleIncident     = G4lint(anglePhotonToNormal / CLHEP::deg);
+    ReflectivityValue = OpticalSurface->GetReflectivityLUTValue(angleIncident);
+
+    if(rand > ReflectivityValue)
+    {
+      if(theEfficiency > 0.)
+      {
+        DoAbsorption();
+        break;
+      }
+      else
+      {
+        theStatus = Transmission;
+
+        if(angleIncident <= 0.01)
+        {
+          NewMomentum = OldMomentum;
+          break;
+        }
+
+        do
+        {
+          random = G4RandFlat::shootInt(1, LUTbin + 1);
+          angindex =
+            (((random * 2) - 1)) + angleIncident * LUTbin * 2 + 3640000;
+
+          azimuth =
+            OpticalSurface->GetAngularDistributionValueLUT(angindex - 1);
+          elevation = OpticalSurface->GetAngularDistributionValueLUT(angindex);
+        } while(elevation == 0. && azimuth == 0.);
+
+        NewMomentum = -OldMomentum;
+
+        G4ThreeVector v     = theGlobalNormal.cross(-NewMomentum);
+        G4ThreeVector vNorm = v / v.mag();
+        G4ThreeVector u     = vNorm.cross(theGlobalNormal);
+
+        u               = u *= (std::sin(elevation) * std::cos(azimuth));
+        v               = vNorm *= (std::sin(elevation) * std::sin(azimuth));
+        G4ThreeVector w = theGlobalNormal *= (std::cos(elevation));
+        NewMomentum     = G4ThreeVector(u + v + w);
+
+        // Rotate Polarization too:
+        theFacetNormal  = (NewMomentum - OldMomentum).unit();
+        EdotN           = OldPolarization * theFacetNormal;
+        NewPolarization = -OldPolarization + (2. * EdotN) * theFacetNormal;
+      }
+    }
+    else
+    {
+      theStatus = LobeReflection;
+
+      if(angleIncident == 0)
+      {
+        NewMomentum = -OldMomentum;
+        break;
+      }
+
+      do
+      {
+        random   = G4RandFlat::shootInt(1, LUTbin + 1);
+        angindex = (((random * 2) - 1)) + (angleIncident - 1) * LUTbin * 2;
+
+        azimuth = OpticalSurface->GetAngularDistributionValueLUT(angindex - 1);
+        elevation = OpticalSurface->GetAngularDistributionValueLUT(angindex);
+      } while(elevation == 0. && azimuth == 0.);
+
+      NewMomentum = -OldMomentum;
+
+      G4ThreeVector v     = theGlobalNormal.cross(-NewMomentum);
+      G4ThreeVector vNorm = v / v.mag();
+      G4ThreeVector u     = vNorm.cross(theGlobalNormal);
+
+      u               = u *= (std::sin(elevation) * std::cos(azimuth));
+      v               = vNorm *= (std::sin(elevation) * std::sin(azimuth));
+      G4ThreeVector w = theGlobalNormal *= (std::cos(elevation));
+
+      NewMomentum = G4ThreeVector(u + v + w);
+
+      // Rotate Polarization too: (needs revision)
+      NewPolarization = OldPolarization;
+    }
+  } while(NewMomentum * theGlobalNormal <= 0.0);
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+void RhCkvG4OpBoundaryProcess::DielectricDichroic()
+{
+  // Calculate Angle between Normal and Photon Momentum
+  G4double anglePhotonToNormal = OldMomentum.angle(-theGlobalNormal);
+
+  // Round it to closest integer
+  G4double angleIncident = std::floor(180. / pi * anglePhotonToNormal + 0.5);
+
+  if(!DichroicVector)
+  {
+    if(OpticalSurface)
+      DichroicVector = OpticalSurface->GetDichroicVector();
+  }
+
+  if(DichroicVector)
+  {
+    G4double wavelength = h_Planck * c_light / thePhotonMomentum;
+    theTransmittance =
+      DichroicVector->Value(wavelength / nm, angleIncident, idx, idy) * perCent;
+    //   G4cout << "wavelength: " << std::floor(wavelength/nm)
+    //                            << "nm" << G4endl;
+    //   G4cout << "Incident angle: " << angleIncident << "deg" << G4endl;
+    //   G4cout << "Transmittance: "
+    //          << std::floor(theTransmittance/perCent) << "%" << G4endl;
+  }
+  else
+  {
+    G4ExceptionDescription ed;
+    ed << " RhCkvG4OpBoundaryProcess/DielectricDichroic(): "
+       << " The dichroic surface has no G4Physics2DVector" << G4endl;
+    G4Exception("RhCkvG4OpBoundaryProcess::DielectricDichroic", "OpBoun03",
+                FatalException, ed,
+                "A dichroic surface must have an associated G4Physics2DVector");
+  }
+
+  if(!G4BooleanRand(theTransmittance))
+  {  // Not transmitted, so reflect
+    if(theModel == glisur || theFinish == polished)
+    {
+      DoReflection();
+    }
+    else
+    {
+      ChooseReflection();
+      if(theStatus == LambertianReflection)
+      {
+        DoReflection();
+      }
+      else if(theStatus == BackScattering)
+      {
+        NewMomentum     = -OldMomentum;
+        NewPolarization = -OldPolarization;
+      }
+      else
+      {
+        G4double PdotN, EdotN;
+        do
+        {
+          if(theStatus == LobeReflection)
+          {
+            theFacetNormal = GetFacetNormal(OldMomentum, theGlobalNormal);
+          }
+          PdotN       = OldMomentum * theFacetNormal;
+          NewMomentum = OldMomentum - (2. * PdotN) * theFacetNormal;
+          // Loop checking, 13-Aug-2015, Peter Gumplinger
+        } while(NewMomentum * theGlobalNormal <= 0.0);
+
+        EdotN           = OldPolarization * theFacetNormal;
+        NewPolarization = -OldPolarization + (2. * EdotN) * theFacetNormal;
+      }
+    }
+  }
+  else
+  {
+    theStatus       = Dichroic;
+    NewMomentum     = OldMomentum;
+    NewPolarization = OldPolarization;
+  }
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+void RhCkvG4OpBoundaryProcess::DielectricDielectric()
+{
+  G4int aMaterial1Index = m_Material1Index;
+  G4int aMaterial2Index = m_Material2Index;
+
+
+  G4bool Inside = false;
+  G4bool Swap   = false;
+
+  G4bool SurfaceRoughnessCriterionPass = true;
+  if(theSurfaceRoughness != 0. && Rindex1 > Rindex2)
+  {
+    G4double wavelength                = h_Planck * c_light / thePhotonMomentum;
+    G4double SurfaceRoughnessCriterion = std::exp(-std::pow(
+      (4. * pi * theSurfaceRoughness * Rindex1 * cost1 / wavelength), 2));
+    SurfaceRoughnessCriterionPass = G4BooleanRand(SurfaceRoughnessCriterion);
+  }
+
+leap:
+
+  G4bool Through = false;
+  G4bool Done    = false;
+
+  G4double EdotN;
+  G4ThreeVector A_trans, A_paral, E1pp, E1pl;
+  G4double E1_perp, E1_parl;
+  G4double s1, s2, E2_perp, E2_parl, E2_total, TransCoeff;
+  G4double E2_abs, C_parl, C_perp;
+  G4double alpha;
+
+  do
+  {
+    if(Through)
+    {
+      Swap            = !Swap;
+      Through         = false;
+      theGlobalNormal = -theGlobalNormal;
+      G4SwapPtr(Material1, Material2);
+      G4SwapObj(&Rindex1, &Rindex2);
+    }
+
+    if(theFinish == polished)
+    {
+      theFacetNormal = theGlobalNormal;
+    }
+    else
+    {
+      theFacetNormal = GetFacetNormal(OldMomentum, theGlobalNormal);
+    }
+
+    // PdotN = OldMomentum * theFacetNormal;
+    EdotN = OldPolarization * theFacetNormal;
+
+    cost1 = -OldMomentum * theFacetNormal;
+    if(std::abs(cost1) < 1.0 - kCarTolerance)
+    {
+      sint1 = std::sqrt(1. - cost1 * cost1);
+      sint2 = sint1 * Rindex1 / Rindex2;  // *** Snell's Law ***
+                                          // this isn't a sine as we might
+                                          // expect from the name; can be > 1
+    }
+    else
+    {
+      sint1 = 0.0;
+      sint2 = 0.0;
+    }
+
+    // TOTAL INTERNAL REFLECTION
+    if(sint2 >= 1.0)
+    {
+      Swap = false;
+
+      theStatus = TotalInternalReflection;
+      if(!SurfaceRoughnessCriterionPass)
+        theStatus = LambertianReflection;
+      if(theModel == unified && theFinish != polished)
+        ChooseReflection();
+      if(theStatus == LambertianReflection)
+      {
+        DoReflection();
+      }
+      else if(theStatus == BackScattering)
+      {
+        NewMomentum     = -OldMomentum;
+        NewPolarization = -OldPolarization;
+      }
+      else
+      {
+
+	//Modification to avoid infinite loops of total internal reflection, for example
+        // in  a rectangular bloc where the incident angle is above the critical angle.
+        // For this, when the number of steps the photon travelled is more than a 
+        //large number (for example 5000),  the photon is killed.
+        if(std::find(m_RichTotalIntReflCheckList.begin(),m_RichTotalIntReflCheckList.end(),
+			aMaterial1Index) != m_RichTotalIntReflCheckList.end() ) {
+                    if(CurPhotStepNum > theMaxPhotStepNumInBoundaryProc ) {
+	                 DoAbsorption();
+		    }
+	}
+
+        // End modification to avoid infinite loops of total internal reflection
+
+        // PdotN = OldMomentum * theFacetNormal;
+        NewMomentum =
+          OldMomentum - 2. * OldMomentum * theFacetNormal * theFacetNormal;
+        EdotN           = OldPolarization * theFacetNormal;
+        NewPolarization = -OldPolarization + (2. * EdotN) * theFacetNormal;
+      }
+    }
+    // NOT TIR
+    else if(sint2 < 1.0)
+    {
+      // Calculate amplitude for transmission (Q = P x N)
+      if(cost1 > 0.0)
+      {
+        cost2 = std::sqrt(1. - sint2 * sint2);
+      }
+      else
+      {
+        cost2 = -std::sqrt(1. - sint2 * sint2);
+      }
+
+      if(sint1 > 0.0)
+      {
+        A_trans = (OldMomentum.cross(theFacetNormal)).unit();
+        E1_perp = OldPolarization * A_trans;
+        E1pp    = E1_perp * A_trans;
+        E1pl    = OldPolarization - E1pp;
+        E1_parl = E1pl.mag();
+      }
+      else
+      {
+        A_trans = OldPolarization;
+        // Here we Follow Jackson's conventions and set the parallel
+        // component = 1 in case of a ray perpendicular to the surface
+        E1_perp = 0.0;
+        E1_parl = 1.0;
+      }
+
+      s1       = Rindex1 * cost1;
+      E2_perp  = 2. * s1 * E1_perp / (Rindex1 * cost1 + Rindex2 * cost2);
+      E2_parl  = 2. * s1 * E1_parl / (Rindex2 * cost1 + Rindex1 * cost2);
+      E2_total = E2_perp * E2_perp + E2_parl * E2_parl;
+      s2       = Rindex2 * cost2 * E2_total;
+
+      if(theTransmittance > 0.) {
+        TransCoeff = theTransmittance;
+      } else if(cost1 != 0.0) {
+        TransCoeff = s2 / s1;
+      } else {
+        TransCoeff = 0.0;
+      }
+
+      //Modification to avoid reflections at some of the selected boundaries in RICH system.
+      // One reason is that the QE already contains the loss from reflection. Hence no need to
+      // apply it again from Fresnel calculations. Another reason is that, some of the boundaries
+      // are software created optical boundaries and there is no need to loose photons there.
+
+
+      const auto aTrans_itp = std::find_if( m_RichTransCoefCheckPairList.begin(),m_RichTransCoefCheckPairList.end(),
+					    [&aMaterial1Index, &aMaterial2Index](const auto &aT ) {
+					    return (aT.first == aMaterial1Index) && (aT.second == aMaterial2Index); });
+      
+      
+      const auto aTrans_its = std::find_if( m_RichTransCoefCheckSingleList.begin(),m_RichTransCoefCheckSingleList.end(),
+					    [&aMaterial1Index, &aMaterial2Index](const auto &aS ) {
+					      return (aS == aMaterial1Index) || (aS == aMaterial2Index) ; });
+
+      if( (aTrans_itp != m_RichTransCoefCheckPairList.end())  || ( aTrans_its != m_RichTransCoefCheckSingleList.end())   ) TransCoeff = 1.0;
+      // End modification to avoid reflections at some selected boundaries
+      //Now for the AR coating on quartz windows
+      // This is to be added in the future.
+      
+ 
+      //end of AR coating on quartz windows
+      // NOT TIR: REFLECTION
+      if(!G4BooleanRand(TransCoeff))
+      {
+        Swap      = false;
+        theStatus = FresnelReflection;
+
+        if(!SurfaceRoughnessCriterionPass)
+          theStatus = LambertianReflection;
+        if(theModel == unified && theFinish != polished)
+          ChooseReflection();
+        if(theStatus == LambertianReflection)
+        {
+          DoReflection();
+        }
+        else if(theStatus == BackScattering)
+        {
+          NewMomentum     = -OldMomentum;
+          NewPolarization = -OldPolarization;
+        }
+        else
+        {
+
+          // CPU optimization for LHCb RICH
+          //  Avoid the transport of photons reflected at the boundary between (C4F10 or Nitrogen) and Rich1GasWindowquartz. 
+         //  Avoid the transport of photons reflected at the boundary between (CF4 or Nitrogen) and Rich2 GasWindowquartz. 
+          //The photons which are set to reflect are killed by doing abosorption.There is
+          // around 4 percent of photons in this category on each of the two surfaces when there is no AR coating.
+          // The Rich1 for run3 has AR coating and hence this fraction is a bit smaller.
+
+          const auto aTrans_itrf = std::find_if( m_RichReflSupCheckPairList.begin(), m_RichReflSupCheckPairList.end(),
+					  [&aMaterial1Index, &aMaterial2Index](const auto &aT ) {
+					    return (aT.first == aMaterial1Index) && (aT.second == aMaterial2Index); });
+       
+          if(aTrans_itrf != m_RichReflSupCheckPairList.end() ) {
+               DoAbsorption();
+	  }
+
+          // end CPU optimization
+
+          NewMomentum =
+            OldMomentum - 2. * OldMomentum * theFacetNormal * theFacetNormal;
+          if(sint1 > 0.0)
+          {  // incident ray oblique
+            E2_parl  = Rindex2 * E2_parl / Rindex1 - E1_parl;
+            E2_perp  = E2_perp - E1_perp;
+            E2_total = E2_perp * E2_perp + E2_parl * E2_parl;
+            A_paral  = (NewMomentum.cross(A_trans)).unit();
+            E2_abs   = std::sqrt(E2_total);
+            C_parl   = E2_parl / E2_abs;
+            C_perp   = E2_perp / E2_abs;
+
+            NewPolarization = C_parl * A_paral + C_perp * A_trans;
+          }
+          else
+          {  // incident ray perpendicular
+            if(Rindex2 > Rindex1)
+            {
+              NewPolarization = -OldPolarization;
+            }
+            else
+            {
+              NewPolarization = OldPolarization;
+            }
+          }
+        }
+      }
+      // NOT TIR: TRANSMISSION
+      else
+      {
+        Inside    = !Inside;
+        Through   = true;
+        theStatus = FresnelRefraction;
+
+        if(sint1 > 0.0)
+        {  // incident ray oblique
+          alpha       = cost1 - cost2 * (Rindex2 / Rindex1);
+          NewMomentum = (OldMomentum + alpha * theFacetNormal).unit();
+          A_paral     = (NewMomentum.cross(A_trans)).unit();
+          E2_abs      = std::sqrt(E2_total);
+          C_parl      = E2_parl / E2_abs;
+          C_perp      = E2_perp / E2_abs;
+
+          NewPolarization = C_parl * A_paral + C_perp * A_trans;
+        }
+        else
+        {  // incident ray perpendicular
+          NewMomentum     = OldMomentum;
+          NewPolarization = OldPolarization;
+        }
+      }
+    }
+
+    OldMomentum     = NewMomentum.unit();
+    OldPolarization = NewPolarization.unit();
+
+    if(theStatus == FresnelRefraction)
+    {
+      Done = (NewMomentum * theGlobalNormal <= 0.0);
+    }
+    else
+    {
+      Done = (NewMomentum * theGlobalNormal >= -kCarTolerance);
+    }
+    // Loop checking, 13-Aug-2015, Peter Gumplinger
+  } while(!Done);
+
+  if(Inside && !Swap)
+  {
+    if(theFinish == polishedbackpainted || theFinish == groundbackpainted)
+    {
+      G4double rand = G4UniformRand();
+      if(rand > theReflectivity + theTransmittance)
+      {
+        DoAbsorption();
+      }
+      else if(rand > theReflectivity)
+      {
+        theStatus       = Transmission;
+        NewMomentum     = OldMomentum;
+        NewPolarization = OldPolarization;
+      }
+      else
+      {
+        if(theStatus != FresnelRefraction)
+        {
+          theGlobalNormal = -theGlobalNormal;
+        }
+        else
+        {
+          Swap = !Swap;
+          G4SwapPtr(Material1, Material2);
+          G4SwapObj(&Rindex1, &Rindex2);
+        }
+        if(theFinish == groundbackpainted)
+          theStatus = LambertianReflection;
+
+        DoReflection();
+
+        theGlobalNormal = -theGlobalNormal;
+        OldMomentum     = NewMomentum;
+
+        goto leap;
+      }
+    }
+  }
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+G4double RhCkvG4OpBoundaryProcess::GetMeanFreePath(const G4Track&, G4double,
+                                              G4ForceCondition* condition)
+{
+  *condition = Forced;
+  return DBL_MAX;
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+G4double RhCkvG4OpBoundaryProcess::GetIncidentAngle()
+{
+  G4double PdotN         = OldMomentum * theFacetNormal;
+  G4double magP          = OldMomentum.mag();
+  G4double magN          = theFacetNormal.mag();
+  G4double incidentangle = pi - std::acos(PdotN / (magP * magN));
+
+  return incidentangle;
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+G4double RhCkvG4OpBoundaryProcess::GetReflectivity(G4double E1_perp,
+                                              G4double E1_parl,
+                                              G4double incidentangle,
+                                              G4double RealRindex,
+                                              G4double ImaginaryRindex)
+{
+  G4complex Reflectivity, Reflectivity_TE, Reflectivity_TM;
+  G4complex N1(Rindex1, 0.), N2(RealRindex, ImaginaryRindex);
+  G4complex CosPhi;
+
+  G4complex u(1., 0.);  // unit number 1
+
+  G4complex numeratorTE;  // E1_perp=1 E1_parl=0 -> TE polarization
+  G4complex numeratorTM;  // E1_parl=1 E1_perp=0 -> TM polarization
+  G4complex denominatorTE, denominatorTM;
+  G4complex rTM, rTE;
+
+  G4MaterialPropertiesTable* MPT = Material1->GetMaterialPropertiesTable();
+  G4MaterialPropertyVector* ppR  = MPT->GetProperty(kREALRINDEX);
+  G4MaterialPropertyVector* ppI  = MPT->GetProperty(kIMAGINARYRINDEX);
+  if(ppR && ppI)
+  {
+    G4double RRindex = ppR->Value(thePhotonMomentum, idx_rrindex);
+    G4double IRindex = ppI->Value(thePhotonMomentum, idx_irindex);
+    N1               = G4complex(RRindex, IRindex);
+  }
+
+  // Following two equations, rTM and rTE, are from: "Introduction To Modern
+  // Optics" written by Fowles
+  CosPhi = std::sqrt(u - ((std::sin(incidentangle) * std::sin(incidentangle)) *
+                          (N1 * N1) / (N2 * N2)));
+
+  numeratorTE   = N1 * std::cos(incidentangle) - N2 * CosPhi;
+  denominatorTE = N1 * std::cos(incidentangle) + N2 * CosPhi;
+  rTE           = numeratorTE / denominatorTE;
+
+  numeratorTM   = N2 * std::cos(incidentangle) - N1 * CosPhi;
+  denominatorTM = N2 * std::cos(incidentangle) + N1 * CosPhi;
+  rTM           = numeratorTM / denominatorTM;
+
+  // This is my calculaton for reflectivity on a metalic surface
+  // depending on the fraction of TE and TM polarization
+  // when TE polarization, E1_parl=0 and E1_perp=1, R=abs(rTE)^2 and
+  // when TM polarization, E1_parl=1 and E1_perp=0, R=abs(rTM)^2
+
+  Reflectivity_TE = (rTE * conj(rTE)) * (E1_perp * E1_perp) /
+                    (E1_perp * E1_perp + E1_parl * E1_parl);
+  Reflectivity_TM = (rTM * conj(rTM)) * (E1_parl * E1_parl) /
+                    (E1_perp * E1_perp + E1_parl * E1_parl);
+  Reflectivity = Reflectivity_TE + Reflectivity_TM;
+
+  do
+  {
+    if(G4UniformRand() * real(Reflectivity) > real(Reflectivity_TE))
+    {
+      iTE = -1;
+    }
+    else
+    {
+      iTE = 1;
+    }
+    if(G4UniformRand() * real(Reflectivity) > real(Reflectivity_TM))
+    {
+      iTM = -1;
+    }
+    else
+    {
+      iTM = 1;
+    }
+    // Loop checking, 13-Aug-2015, Peter Gumplinger
+  } while(iTE < 0 && iTM < 0);
+
+  return real(Reflectivity);
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+
+void RhCkvG4OpBoundaryProcess::CalculateReflectivity()
+{
+  G4double RealRindex = fRealRIndexMPV->Value(thePhotonMomentum, idx_rrindex);
+  G4double ImaginaryRindex =
+    fImagRIndexMPV->Value(thePhotonMomentum, idx_irindex);
+
+  // calculate FacetNormal
+  if(theFinish == ground)
+  {
+    theFacetNormal = GetFacetNormal(OldMomentum, theGlobalNormal);
+  }
+  else
+  {
+    theFacetNormal = theGlobalNormal;
+  }
+
+  cost1 = -OldMomentum * theFacetNormal;
+  if(std::abs(cost1) < 1.0 - kCarTolerance)
+  {
+    sint1 = std::sqrt(1. - cost1 * cost1);
+  }
+  else
+  {
+    sint1 = 0.0;
+  }
+
+  G4ThreeVector A_trans, A_paral, E1pp, E1pl;
+  G4double E1_perp, E1_parl;
+
+  if(sint1 > 0.0)
+  {
+    A_trans = (OldMomentum.cross(theFacetNormal)).unit();
+    E1_perp = OldPolarization * A_trans;
+    E1pp    = E1_perp * A_trans;
+    E1pl    = OldPolarization - E1pp;
+    E1_parl = E1pl.mag();
+  }
+  else
+  {
+    A_trans = OldPolarization;
+    // Here we Follow Jackson's conventions and we set the parallel
+    // component = 1 in case of a ray perpendicular to the surface
+    E1_perp = 0.0;
+    E1_parl = 1.0;
+  }
+
+  G4double incidentangle = GetIncidentAngle();
+
+  // calculate the reflectivity depending on incident angle,
+  // polarization and complex refractive
+  theReflectivity = GetReflectivity(E1_perp, E1_parl, incidentangle, RealRindex,
+                                    ImaginaryRindex);
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+G4bool RhCkvG4OpBoundaryProcess::InvokeSD(const G4Step* pStep)
+{
+  G4Step aStep = *pStep;
+  aStep.AddTotalEnergyDeposit(thePhotonMomentum);
+
+  G4VSensitiveDetector* sd = aStep.GetPostStepPoint()->GetSensitiveDetector();
+  if(sd)
+    return sd->Hit(&aStep);
+  else
+    return false;
+}
+//======================================================================//
+
+
-- 
GitLab