From 28a9b3fdf4691bc306d7558b5b72f60734d8d461 Mon Sep 17 00:00:00 2001
From: Moritz Kiehn <msmk@cern.ch>
Date: Tue, 21 Jan 2020 11:28:40 +0100
Subject: [PATCH 01/12] EventData: replace BarcodeSvc w/ directly encoded
 Barcode

---
 Core/include/ACTFW/EventData/Barcode.hpp     | 182 +++++++++++++------
 Core/include/ACTFW/EventData/SimParticle.hpp |  18 +-
 2 files changed, 131 insertions(+), 69 deletions(-)

diff --git a/Core/include/ACTFW/EventData/Barcode.hpp b/Core/include/ACTFW/EventData/Barcode.hpp
index 8bd0d55e5..b306ec8b2 100644
--- a/Core/include/ACTFW/EventData/Barcode.hpp
+++ b/Core/include/ACTFW/EventData/Barcode.hpp
@@ -9,84 +9,113 @@
 #pragma once
 
 #include <cstdint>
+#include <ostream>
 
 namespace FW {
 
-/// Particle barcode.
-using barcode_type = uint64_t;
-
-/// Encode and decode particle barcodes.
-class BarcodeSvc
+/// Particle identifier that encodes some event information.
+class Barcode
 {
 public:
-  struct Config
-  {
-    barcode_type vertex_mask     = 0xfff0000000000000;
-    barcode_type primary_mask    = 0x000ffff000000000;
-    barcode_type generation_mask = 0x0000000fff000000;
-    barcode_type secondary_mask  = 0x0000000000fff000;
-    barcode_type process_mask    = 0x0000000000000fff;
-  };
+  using Value = uint64_t;
 
-  BarcodeSvc(const Config& cfg) : m_cfg(cfg) {}
+  /// Construct the barcode from an already encoded value
+  constexpr Barcode(Value encoded) : m_value(encoded) {}
+  /// Construct default Barcode with all values set to zero.
+  Barcode()               = default;
+  Barcode(Barcode&&)      = default;
+  Barcode(const Barcode&) = default;
+  ~Barcode()              = default;
+  Barcode&
+  operator=(Barcode&&)
+      = default;
+  Barcode&
+  operator=(const Barcode&)
+      = default;
 
-  /// Encode a new barcode.
-  barcode_type
-  generate(barcode_type vertex     = 0,
-           barcode_type primary    = 0,
-           barcode_type generation = 0,
-           barcode_type secondary  = 0,
-           barcode_type process    = 0) const
+  /// Return the encoded value.
+  constexpr Value
+  value() const
   {
-    barcode_type barcode = 0;
-    // create the barcode w/ all components
-    barcode = setBits(barcode, m_cfg.vertex_mask, vertex);
-    barcode = setBits(barcode, m_cfg.primary_mask, primary);
-    barcode = setBits(barcode, m_cfg.generation_mask, generation);
-    barcode = setBits(barcode, m_cfg.secondary_mask, secondary);
-    barcode = setBits(barcode, m_cfg.process_mask, process);
-    return barcode;
+    return m_value;
   }
 
-  /// Decode the vertex number.
-  barcode_type
-  vertex(barcode_type barcode) const
+  /// Return the vertex identifier.
+  constexpr Value
+  vertex() const
   {
-    return getBits(barcode, m_cfg.vertex_mask);
+    return getBits(Masks::Vertex);
   }
-
-  /// Decode the primary index.
-  barcode_type
-  primary(barcode_type barcode) const
+  /// Return the primary particle identifier.
+  constexpr Value
+  primary() const
   {
-    return getBits(barcode, m_cfg.primary_mask);
+    return getBits(Masks::Primary);
   }
-
-  /// Decode the generation number.
-  barcode_type
-  generation(barcode_type barcode) const
+  /// Return the generation identifier.
+  constexpr Value
+  generation() const
   {
-    return getBits(barcode, m_cfg.generation_mask);
+    return getBits(Masks::Generation);
   }
-
-  /// Decode the secondary index.
-  barcode_type
-  secondary(barcode_type barcode) const
+  /// Return the secondary particle identifier.
+  constexpr Value
+  secondary() const
+  {
+    return getBits(Masks::Secondary);
+  }
+  /// Return the process identifier.
+  constexpr Value
+  process() const
   {
-    return getBits(barcode, m_cfg.secondary_mask);
+    return getBits(Masks::Process);
   }
 
-  /// Decode the process number.
-  barcode_type
-  process(barcode_type barcode) const
+  /// Set the vertex identifier.
+  constexpr Barcode&
+  setVertex(Value id)
+  {
+    return setBits(Masks::Vertex, id);
+  }
+  /// Set the primary particle identifier.
+  constexpr Barcode&
+  setPrimary(Value id)
+  {
+    return setBits(Masks::Primary, id);
+  }
+  /// Set the generation identifier.
+  constexpr Barcode&
+  setGeneration(Value id)
+  {
+    return setBits(Masks::Generation, id);
+  }
+  /// Set the secondary particle identifier.
+  constexpr Barcode&
+  setSecondary(Value id)
+  {
+    return setBits(Masks::Secondary, id);
+  }
+  /// Set the process identifier.
+  constexpr Barcode&
+  setProcess(Value id)
   {
-    return getBits(barcode, m_cfg.process_mask);
+    return setBits(Masks::Process, id);
   }
 
 private:
+  enum Masks : Value {
+    Vertex     = UINT64_C(0xfff0000000000000),
+    Primary    = UINT64_C(0x000ffff000000000),
+    Generation = UINT64_C(0x0000000fff000000),
+    Secondary  = UINT64_C(0x0000000000fff000),
+    Process    = UINT64_C(0x0000000000000fff),
+  };
+
+  Value m_value = 0;
+
   /// Extract the bit shift necessary to access the masked values.
   static constexpr int
-  extractShift(barcode_type mask)
+  extractShift(Value mask)
   {
     // use compiler builtin to extract the number of trailing zero bits from the
     // mask. the builtin should be available on all supported compilers.
@@ -95,19 +124,52 @@ private:
     return __builtin_ctzll(mask);
   }
   /// Extract the masked bits from the encoded value.
-  static constexpr barcode_type
-  getBits(barcode_type value, barcode_type mask)
+  constexpr Value
+  getBits(Value mask) const
   {
-    return (value & mask) >> extractShift(mask);
+    return (m_value & mask) >> extractShift(mask);
   }
   /// Set the masked bits to id in the encoded value.
-  static constexpr barcode_type
-  setBits(barcode_type value, barcode_type mask, barcode_type id)
+  constexpr Barcode&
+  setBits(Value mask, Value id)
   {
-    return (value & ~mask) | ((id << extractShift(mask)) & mask);
+    m_value = (m_value & ~mask) | ((id << extractShift(mask)) & mask);
+    // return *this here so we need to write less lines in the set... methods
+    return *this;
   }
 
-  Config m_cfg;
+  friend constexpr bool
+  operator==(Barcode lhs, Barcode rhs)
+  {
+    return lhs.m_value == rhs.m_value;
+  }
+  friend constexpr bool
+  operator<(Barcode lhs, Barcode rhs)
+  {
+    return lhs.m_value < rhs.m_value;
+  }
+  friend std::ostream&
+  operator<<(std::ostream& os, Barcode x)
+  {
+    os << x.vertex() << "|" << x.primary() << "|" << x.generation() << "|"
+       << x.secondary() << "|" << x.process();
+    return os;
+  }
 };
 
 }  // namespace FW
+
+namespace std {
+
+// specialize std::hash so the Barcode can be used e.g. in an unordered_map
+template <>
+struct hash<FW::Barcode>
+{
+  auto
+  operator()(FW::Barcode idx) const noexcept
+  {
+    return std::hash<FW::Barcode::Value>()(idx.value());
+  }
+};
+
+}  // namespace std
diff --git a/Core/include/ACTFW/EventData/SimParticle.hpp b/Core/include/ACTFW/EventData/SimParticle.hpp
index 4c33a9746..cff9338a2 100644
--- a/Core/include/ACTFW/EventData/SimParticle.hpp
+++ b/Core/include/ACTFW/EventData/SimParticle.hpp
@@ -41,7 +41,7 @@ namespace Data {
                 double                mass,
                 double                charge,
                 pdg_type              pdg     = 0,
-                barcode_type          barcode = 0,
+                Barcode               barcode = Barcode(),
                 double                time    = 0.)
       : m_position(position)
       , m_time(time)
@@ -68,7 +68,7 @@ namespace Data {
 
     /// Place the particle at the given position and reset its identifier.
     void
-    place(Acts::Vector3D position, barcode_type barcode, double time = 0.)
+    place(Acts::Vector3D position, Barcode barcode, double time = 0.)
     {
       m_position = position;
       m_time     = time;
@@ -187,7 +187,7 @@ namespace Data {
       return m_pdg;
     }
     /// Particle identifier/ barcode.
-    barcode_type
+    Barcode
     barcode() const
     {
       return m_barcode;
@@ -233,9 +233,9 @@ namespace Data {
     double         m_mass     = 0.;                          //!< particle mass
     double         m_charge   = 0.;                          //!< the charge
     pdg_type       m_pdg      = 0;         //!< pdg code of the particle
-    barcode_type   m_barcode  = 0;         //!< barcode of the particle
-    double         m_pathInX0 = 0.;        //!< passed path in X0
-    double         m_pathInL0 = 0.;        //!< passed path in L0
+    Barcode        m_barcode;              //!< barcode of the particle
+    double         m_pathInX0  = 0.;       //!< passed path in X0
+    double         m_pathInL0  = 0.;       //!< passed path in L0
     double         m_limitTime = DBL_MAX;  //!< time limit
     double         m_limitInX0 = DBL_MAX;  //!< path limit in X0
     double         m_limitInL0 = DBL_MAX;  //!< path limit in X0
@@ -254,12 +254,12 @@ namespace detail {
       return left.barcode() < right.barcode();
     }
     bool
-    operator()(barcode_type left, const Data::SimParticle& right) const
+    operator()(Barcode left, const Data::SimParticle& right) const
     {
       return left < right.barcode();
     }
     bool
-    operator()(const Data::SimParticle& left, barcode_type right) const
+    operator()(const Data::SimParticle& left, Barcode right) const
     {
       return left.barcode() < right;
     }
@@ -271,4 +271,4 @@ using SimParticles
     = boost::container::flat_set<Data::SimParticle,
                                  detail::CompareSimParticleBarcode>;
 
-}  // end of namespace FW
\ No newline at end of file
+}  // end of namespace FW
-- 
GitLab


From 927915b8cca80790cc9fe3fa367d95e25310d2d8 Mon Sep 17 00:00:00 2001
From: Moritz Kiehn <msmk@cern.ch>
Date: Tue, 21 Jan 2020 11:29:50 +0100
Subject: [PATCH 02/12] Core: use Barcode

---
 Core/include/ACTFW/Validation/EffPlotTool.hpp         |  2 +-
 .../ACTFW/Validation/ProtoTrackClassification.hpp     | 11 +++++------
 Core/include/ACTFW/Validation/ResPlotTool.hpp         |  2 +-
 Core/src/Validation/ProtoTrackClassification.cpp      |  2 +-
 4 files changed, 8 insertions(+), 9 deletions(-)

diff --git a/Core/include/ACTFW/Validation/EffPlotTool.hpp b/Core/include/ACTFW/Validation/EffPlotTool.hpp
index d360f0dae..76cd6a394 100644
--- a/Core/include/ACTFW/Validation/EffPlotTool.hpp
+++ b/Core/include/ACTFW/Validation/EffPlotTool.hpp
@@ -10,7 +10,7 @@
 
 #include <map>
 #include <string>
-#include "ACTFW/EventData/Barcode.hpp"
+
 #include "ACTFW/EventData/SimHit.hpp"
 #include "ACTFW/EventData/SimParticle.hpp"
 #include "ACTFW/EventData/SimSourceLink.hpp"
diff --git a/Core/include/ACTFW/Validation/ProtoTrackClassification.hpp b/Core/include/ACTFW/Validation/ProtoTrackClassification.hpp
index bbbb75e94..8e0da4b43 100644
--- a/Core/include/ACTFW/Validation/ProtoTrackClassification.hpp
+++ b/Core/include/ACTFW/Validation/ProtoTrackClassification.hpp
@@ -20,15 +20,14 @@ namespace FW {
 /// Associate a particle to its hit count within a proto track.
 struct ParticleHitCount
 {
-  barcode_type particleId;
-  size_t       hitCount;
+  Barcode particleId;
+  size_t  hitCount;
 };
 
 /// Identify all particles that contribute to the proto track and count hits.
 void
-identifyContributingParticles(
-    const IndexMultimap<barcode_type>& hitParticlesMap,
-    const ProtoTrack&                  protoTrack,
-    std::vector<ParticleHitCount>&     particleHitCount);
+identifyContributingParticles(const IndexMultimap<Barcode>&  hitParticlesMap,
+                              const ProtoTrack&              protoTrack,
+                              std::vector<ParticleHitCount>& particleHitCount);
 
 }  // namespace FW
diff --git a/Core/include/ACTFW/Validation/ResPlotTool.hpp b/Core/include/ACTFW/Validation/ResPlotTool.hpp
index 943de6e85..df22d27ae 100644
--- a/Core/include/ACTFW/Validation/ResPlotTool.hpp
+++ b/Core/include/ACTFW/Validation/ResPlotTool.hpp
@@ -10,7 +10,7 @@
 
 #include <map>
 #include <string>
-#include "ACTFW/EventData/Barcode.hpp"
+
 #include "ACTFW/EventData/SimHit.hpp"
 #include "ACTFW/EventData/SimParticle.hpp"
 #include "ACTFW/EventData/SimSourceLink.hpp"
diff --git a/Core/src/Validation/ProtoTrackClassification.cpp b/Core/src/Validation/ProtoTrackClassification.cpp
index 265289c49..35235f353 100644
--- a/Core/src/Validation/ProtoTrackClassification.cpp
+++ b/Core/src/Validation/ProtoTrackClassification.cpp
@@ -14,7 +14,7 @@
 
 void
 FW::identifyContributingParticles(
-    const IndexMultimap<barcode_type>& hitParticlesMap,
+    const IndexMultimap<Barcode>&      hitParticlesMap,
     const ProtoTrack&                  protoTrack,
     std::vector<FW::ParticleHitCount>& particleHitCount)
 {
-- 
GitLab


From 9e98efcec4f4e694d1311601eaeea1e8d57e9a5a Mon Sep 17 00:00:00 2001
From: Moritz Kiehn <msmk@cern.ch>
Date: Tue, 21 Jan 2020 11:30:22 +0100
Subject: [PATCH 03/12] Algorithms: replace BarcodeSvc w/ Barcode

---
 Algorithms/Digitization/src/DigitizationAlgorithm.cpp |  1 -
 .../Generators/ACTFW/Generators/EventGenerator.cpp    | 11 ++---------
 .../Generators/ACTFW/Generators/EventGenerator.hpp    |  3 ---
 .../ACTFW/Generators/ParametricProcessGenerator.cpp   |  3 +--
 .../ACTFW/TruthTracking/TruthTrackFinder.cpp          |  2 +-
 5 files changed, 4 insertions(+), 16 deletions(-)

diff --git a/Algorithms/Digitization/src/DigitizationAlgorithm.cpp b/Algorithms/Digitization/src/DigitizationAlgorithm.cpp
index 51d9eba9b..9d86b058e 100644
--- a/Algorithms/Digitization/src/DigitizationAlgorithm.cpp
+++ b/Algorithms/Digitization/src/DigitizationAlgorithm.cpp
@@ -11,7 +11,6 @@
 #include <iostream>
 #include <stdexcept>
 
-#include "ACTFW/EventData/Barcode.hpp"
 #include "ACTFW/EventData/DataContainers.hpp"
 #include "ACTFW/EventData/SimHit.hpp"
 #include "ACTFW/EventData/SimParticle.hpp"
diff --git a/Algorithms/Generators/ACTFW/Generators/EventGenerator.cpp b/Algorithms/Generators/ACTFW/Generators/EventGenerator.cpp
index cf0cd8fb2..f6b061e24 100644
--- a/Algorithms/Generators/ACTFW/Generators/EventGenerator.cpp
+++ b/Algorithms/Generators/ACTFW/Generators/EventGenerator.cpp
@@ -24,9 +24,6 @@ FW::EventGenerator::EventGenerator(const Config& cfg, Acts::Logging::Level lvl)
   if (m_cfg.generators.empty()) {
     throw std::invalid_argument("No generators are configured");
   }
-  if (!m_cfg.barcodeSvc) {
-    throw std::invalid_argument("Missing barcode service");
-  }
   if (!m_cfg.randomNumbers) {
     throw std::invalid_argument("Missing random numbers service");
   }
@@ -90,12 +87,8 @@ FW::EventGenerator::read(const AlgorithmContext& ctx)
           // using the number of primary vertices as the index ensures
           // that barcode=0 is not used, since it is typically used elsewhere
           // to signify elements w/o an associated particle.
-          auto iPrimary    = m_cfg.barcodeSvc->primary(particle.barcode());
-          auto iGeneration = m_cfg.barcodeSvc->generation(particle.barcode());
-          auto iSecondary  = m_cfg.barcodeSvc->secondary(particle.barcode());
-          auto iProcess    = m_cfg.barcodeSvc->process(particle.barcode());
-          auto barcode     = m_cfg.barcodeSvc->generate(
-              nPrimaryVertices, iPrimary, iGeneration, iSecondary, iProcess);
+          auto barcode = particle.barcode();
+          barcode.setVertex(nPrimaryVertices);
           particle.place(particlePos, barcode, particleTime);
         };
 
diff --git a/Algorithms/Generators/ACTFW/Generators/EventGenerator.hpp b/Algorithms/Generators/ACTFW/Generators/EventGenerator.hpp
index 5c4d6084c..9003320de 100644
--- a/Algorithms/Generators/ACTFW/Generators/EventGenerator.hpp
+++ b/Algorithms/Generators/ACTFW/Generators/EventGenerator.hpp
@@ -20,7 +20,6 @@
 #include <Acts/Utilities/Definitions.hpp>
 #include <Acts/Utilities/Logger.hpp>
 
-#include "ACTFW/EventData/Barcode.hpp"
 #include "ACTFW/EventData/SimVertex.hpp"
 #include "ACTFW/Framework/IReader.hpp"
 #include "ACTFW/Framework/RandomNumbers.hpp"
@@ -69,8 +68,6 @@ public:
     bool shuffle = false;
     /// The random number service
     std::shared_ptr<RandomNumbers> randomNumbers = nullptr;
-    /// The barcode service to generate particle identifiers
-    std::shared_ptr<BarcodeSvc> barcodeSvc = nullptr;
   };
 
   EventGenerator(const Config& cfg, Acts::Logging::Level lvl);
diff --git a/Algorithms/Generators/ACTFW/Generators/ParametricProcessGenerator.cpp b/Algorithms/Generators/ACTFW/Generators/ParametricProcessGenerator.cpp
index 4fcf5854d..1aa590ce1 100644
--- a/Algorithms/Generators/ACTFW/Generators/ParametricProcessGenerator.cpp
+++ b/Algorithms/Generators/ACTFW/Generators/ParametricProcessGenerator.cpp
@@ -43,8 +43,7 @@ FW::ParametricProcessGenerator::operator()(FW::RandomEngine& rng) const
     auto pt    = ptDist(rng);
     auto qsign = generateChargeSign(rng);
     // all generated particles are treated as primary particles
-    // TODO remove barcode service altogether
-    auto barcode = BarcodeSvc(BarcodeSvc::Config()).generate(0u, ip);
+    auto barcode = Barcode().setPrimary(ip);
 
     Acts::Vector3D position(d0 * std::sin(phi), d0 * -std::cos(phi), z0);
     Acts::Vector3D momentum(
diff --git a/Algorithms/TruthTracking/ACTFW/TruthTracking/TruthTrackFinder.cpp b/Algorithms/TruthTracking/ACTFW/TruthTracking/TruthTrackFinder.cpp
index 26753c34a..005076e63 100644
--- a/Algorithms/TruthTracking/ACTFW/TruthTracking/TruthTrackFinder.cpp
+++ b/Algorithms/TruthTracking/ACTFW/TruthTracking/TruthTrackFinder.cpp
@@ -36,7 +36,7 @@ TruthTrackFinder::TruthTrackFinder(const Config& cfg, Acts::Logging::Level lvl)
 ProcessCode
 TruthTrackFinder::execute(const AlgorithmContext& ctx) const
 {
-  using HitParticlesMap = IndexMultimap<barcode_type>;
+  using HitParticlesMap = IndexMultimap<Barcode>;
 
   // prepare input collections
   const auto& particles
-- 
GitLab


From 487d9f6f277d5252bcfaa7dbdf0162f2e4b0b5ab Mon Sep 17 00:00:00 2001
From: Moritz Kiehn <msmk@cern.ch>
Date: Tue, 21 Jan 2020 11:31:20 +0100
Subject: [PATCH 04/12] Io: replace BarcodeSvc w/ Barcode

---
 Io/Csv/src/CsvParticleReader.cpp              |  1 -
 Io/Csv/src/CsvParticleWriter.cpp              |  7 +++----
 Io/Csv/src/CsvPlanarClusterReader.cpp         |  2 +-
 Io/Csv/src/CsvPlanarClusterWriter.cpp         |  2 +-
 .../TrackFinderPerformanceWriter.cpp          | 15 ++++++-------
 .../TrackFitterPerformanceWriter.cpp          |  2 +-
 .../ACTFW/Io/Root/RootParticleWriter.hpp      |  5 +----
 .../ACTFW/Io/Root/RootTrajectoryWriter.hpp    |  1 -
 .../Io/Root/RootVertexAndTracksWriter.hpp     |  5 +----
 Io/Root/src/RootParticleWriter.cpp            | 21 +++++++------------
 Io/Root/src/RootPlanarClusterWriter.cpp       |  2 +-
 Io/Root/src/RootSimHitWriter.cpp              |  1 -
 Io/Root/src/RootTrajectoryWriter.cpp          |  2 +-
 13 files changed, 26 insertions(+), 40 deletions(-)

diff --git a/Io/Csv/src/CsvParticleReader.cpp b/Io/Csv/src/CsvParticleReader.cpp
index fbdb4aeb4..673df6ea5 100644
--- a/Io/Csv/src/CsvParticleReader.cpp
+++ b/Io/Csv/src/CsvParticleReader.cpp
@@ -17,7 +17,6 @@
 #include <Acts/Utilities/Units.hpp>
 #include <dfe/dfe_io_dsv.hpp>
 
-#include "ACTFW/EventData/Barcode.hpp"
 #include "ACTFW/EventData/SimParticle.hpp"
 #include "ACTFW/Framework/WhiteBoard.hpp"
 #include "ACTFW/Utilities/Paths.hpp"
diff --git a/Io/Csv/src/CsvParticleWriter.cpp b/Io/Csv/src/CsvParticleWriter.cpp
index 0df66a638..2d9da0184 100644
--- a/Io/Csv/src/CsvParticleWriter.cpp
+++ b/Io/Csv/src/CsvParticleWriter.cpp
@@ -14,7 +14,6 @@
 #include <Acts/Utilities/Units.hpp>
 #include <dfe/dfe_io_dsv.hpp>
 
-#include "ACTFW/EventData/Barcode.hpp"
 #include "ACTFW/Framework/WhiteBoard.hpp"
 #include "ACTFW/Utilities/Paths.hpp"
 #include "TrackMlData.hpp"
@@ -35,9 +34,9 @@ FW::CsvParticleWriter::writeT(const FW::AlgorithmContext&         context,
                               const std::vector<Data::SimVertex>& vertices)
 {
   // use pointer instead of reference since it is optional
-  const std::map<barcode_type, size_t>* hitsPerParticle = nullptr;
+  const std::map<Barcode, size_t>* hitsPerParticle = nullptr;
   if (not m_cfg.inputHitsPerParticle.empty()) {
-    hitsPerParticle = &context.eventStore.get<std::map<barcode_type, size_t>>(
+    hitsPerParticle = &context.eventStore.get<std::map<Barcode, size_t>>(
         m_cfg.inputHitsPerParticle);
   }
 
@@ -50,7 +49,7 @@ FW::CsvParticleWriter::writeT(const FW::AlgorithmContext&         context,
   data.nhits = -1;  // default for every entry if information unvailable
   for (auto& vertex : vertices) {
     for (auto& particle : vertex.outgoing) {
-      data.particle_id   = particle.barcode();
+      data.particle_id   = particle.barcode().value();
       data.particle_type = particle.pdg();
       data.vx            = particle.position().x() / Acts::UnitConstants::mm;
       data.vy            = particle.position().y() / Acts::UnitConstants::mm;
diff --git a/Io/Csv/src/CsvPlanarClusterReader.cpp b/Io/Csv/src/CsvPlanarClusterReader.cpp
index aa419bafd..08cf653f8 100644
--- a/Io/Csv/src/CsvPlanarClusterReader.cpp
+++ b/Io/Csv/src/CsvPlanarClusterReader.cpp
@@ -171,7 +171,7 @@ FW::CsvPlanarClusterReader::read(const FW::AlgorithmContext& ctx)
   // prepare containers for the hit data using the framework event data types
   GeometryIdMultimap<Acts::PlanarModuleCluster> clusters;
   std::vector<uint64_t>                         hitIds;
-  IndexMultimap<barcode_type>                   hitParticlesMap;
+  IndexMultimap<Barcode>                        hitParticlesMap;
   SimHits                                       simHits;
   clusters.reserve(hits.size());
   hitIds.reserve(hits.size());
diff --git a/Io/Csv/src/CsvPlanarClusterWriter.cpp b/Io/Csv/src/CsvPlanarClusterWriter.cpp
index d4970a4df..4e53e348c 100644
--- a/Io/Csv/src/CsvPlanarClusterWriter.cpp
+++ b/Io/Csv/src/CsvPlanarClusterWriter.cpp
@@ -93,7 +93,7 @@ FW::CsvPlanarClusterWriter::writeT(
     // each hit can have multiple particles, e.g. in a dense environment
     truth.hit_id = hit.hit_id;
     for (auto& p : cluster.sourceLink().truthParticles()) {
-      truth.particle_id = p->barcode();
+      truth.particle_id = p->barcode().value();
       truth.tx          = p->position().x() / Acts::UnitConstants::mm;
       truth.ty          = p->position().y() / Acts::UnitConstants::mm;
       truth.tz          = p->position().z() / Acts::UnitConstants::mm;
diff --git a/Io/Performance/ACTFW/Io/Performance/TrackFinderPerformanceWriter.cpp b/Io/Performance/ACTFW/Io/Performance/TrackFinderPerformanceWriter.cpp
index 005d43784..ae2e63006 100644
--- a/Io/Performance/ACTFW/Io/Performance/TrackFinderPerformanceWriter.cpp
+++ b/Io/Performance/ACTFW/Io/Performance/TrackFinderPerformanceWriter.cpp
@@ -27,7 +27,7 @@
 
 namespace {
 using SimParticles        = FW::SimParticles;
-using HitParticlesMap     = FW::IndexMultimap<FW::barcode_type>;
+using HitParticlesMap     = FW::IndexMultimap<FW::Barcode>;
 using ProtoTrackContainer = FW::ProtoTrackContainer;
 }  // namespace
 
@@ -142,10 +142,10 @@ struct FW::TrackFinderPerformanceWriter::Impl
     // compute the inverse mapping on-the-fly
     const auto& particleHitsMap = invertIndexMultimap(hitParticlesMap);
     // How often a particle was reconstructed.
-    std::unordered_map<barcode_type, size_t> reconCount;
+    std::unordered_map<Barcode, size_t> reconCount;
     reconCount.reserve(particles.size());
     // How often a particle was reconstructed as the majority particle.
-    std::unordered_map<barcode_type, size_t> majorityCount;
+    std::unordered_map<Barcode, size_t> majorityCount;
     majorityCount.reserve(particles.size());
     // For each particle within a track, how many hits did it contribute
     std::vector<ParticleHitCount> particleHitCounts;
@@ -181,10 +181,11 @@ struct FW::TrackFinderPerformanceWriter::Impl
         trkParticleNumHitsTotal.clear();
         trkParticleNumHitsOnTrack.clear();
         for (const auto& phc : particleHitCounts) {
-          trkParticleId.push_back(phc.particleId);
+          trkParticleId.push_back(phc.particleId.value());
           // count total number of hits for this particle
-          trkParticleNumHitsTotal.push_back(
-              makeRange(particleHitsMap.equal_range(phc.particleId)).size());
+          auto trueParticleHits
+              = makeRange(particleHitsMap.equal_range(phc.particleId.value()));
+          trkParticleNumHitsTotal.push_back(trueParticleHits.size());
           trkParticleNumHitsOnTrack.push_back(phc.hitCount);
         }
 
@@ -201,7 +202,7 @@ struct FW::TrackFinderPerformanceWriter::Impl
 
         // identification
         prtEventId      = eventId;
-        prtParticleId   = particle.barcode();
+        prtParticleId   = particle.barcode().value();
         prtParticleType = particle.pdg();
         // kinematics
         prtVx = particle.position().x();
diff --git a/Io/Performance/ACTFW/Io/Performance/TrackFitterPerformanceWriter.cpp b/Io/Performance/ACTFW/Io/Performance/TrackFitterPerformanceWriter.cpp
index ef924bc33..3ddd235b7 100644
--- a/Io/Performance/ACTFW/Io/Performance/TrackFitterPerformanceWriter.cpp
+++ b/Io/Performance/ACTFW/Io/Performance/TrackFitterPerformanceWriter.cpp
@@ -90,7 +90,7 @@ FW::TrackFitterPerformanceWriter::writeT(
   std::lock_guard<std::mutex> lock(m_writeMutex);
 
   // All reconstructed trajectories with truth info
-  std::map<barcode_type, TruthFitTrack> reconTrajectories;
+  std::map<Barcode, TruthFitTrack> reconTrajectories;
 
   // Loop over all trajectories
   for (const auto& traj : trajectories) {
diff --git a/Io/Root/include/ACTFW/Io/Root/RootParticleWriter.hpp b/Io/Root/include/ACTFW/Io/Root/RootParticleWriter.hpp
index af4c04eb1..1f735affa 100644
--- a/Io/Root/include/ACTFW/Io/Root/RootParticleWriter.hpp
+++ b/Io/Root/include/ACTFW/Io/Root/RootParticleWriter.hpp
@@ -10,7 +10,6 @@
 
 #include <mutex>
 
-#include "ACTFW/EventData/Barcode.hpp"
 #include "ACTFW/EventData/SimParticle.hpp"
 #include "ACTFW/EventData/SimVertex.hpp"
 #include "ACTFW/Framework/WriterT.hpp"
@@ -40,9 +39,7 @@ public:
     std::string filePath;                ///< path of the output file
     std::string fileMode = "RECREATE";   ///< file access mode
     std::string treeName = "particles";  ///< name of the output tree
-    std::shared_ptr<FW::BarcodeSvc>
-           barcodeSvc;          ///< the barcode service to decode (optional)
-    TFile* rootFile = nullptr;  ///< common root file
+    TFile*      rootFile = nullptr;      ///< common root file
   };
 
   /// Constructor
diff --git a/Io/Root/include/ACTFW/Io/Root/RootTrajectoryWriter.hpp b/Io/Root/include/ACTFW/Io/Root/RootTrajectoryWriter.hpp
index 0f1d3a6ca..f3f9b1704 100644
--- a/Io/Root/include/ACTFW/Io/Root/RootTrajectoryWriter.hpp
+++ b/Io/Root/include/ACTFW/Io/Root/RootTrajectoryWriter.hpp
@@ -15,7 +15,6 @@
 #include <Acts/Geometry/GeometryID.hpp>
 #include <Acts/Utilities/ParameterDefinitions.hpp>
 
-#include "ACTFW/EventData/Barcode.hpp"
 #include "ACTFW/EventData/DataContainers.hpp"
 #include "ACTFW/EventData/SimParticle.hpp"
 #include "ACTFW/EventData/SimSourceLink.hpp"
diff --git a/Io/Root/include/ACTFW/Io/Root/RootVertexAndTracksWriter.hpp b/Io/Root/include/ACTFW/Io/Root/RootVertexAndTracksWriter.hpp
index bd69a7371..ef14c624e 100644
--- a/Io/Root/include/ACTFW/Io/Root/RootVertexAndTracksWriter.hpp
+++ b/Io/Root/include/ACTFW/Io/Root/RootVertexAndTracksWriter.hpp
@@ -10,7 +10,6 @@
 
 #include <mutex>
 
-#include "ACTFW/EventData/Barcode.hpp"
 #include "ACTFW/Framework/WriterT.hpp"
 #include "ACTFW/TruthTracking/VertexAndTracks.hpp"
 
@@ -39,9 +38,7 @@ public:
     std::string filePath;               ///< path of the output file
     std::string fileMode = "RECREATE";  ///< file access mode
     std::string treeName = "event";     ///< name of the output tree
-    std::shared_ptr<FW::BarcodeSvc>
-           barcodeSvc;          ///< the barcode service to decode (optional)
-    TFile* rootFile = nullptr;  ///< common root file
+    TFile*      rootFile = nullptr;     ///< common root file
   };
 
   /// Constructor
diff --git a/Io/Root/src/RootParticleWriter.cpp b/Io/Root/src/RootParticleWriter.cpp
index 4b900c674..611476554 100644
--- a/Io/Root/src/RootParticleWriter.cpp
+++ b/Io/Root/src/RootParticleWriter.cpp
@@ -103,7 +103,7 @@ FW::RootParticleWriter::writeT(const AlgorithmContext&             context,
   // loop over the process vertices
   for (auto& vertex : vertices) {
     for (auto& particle : vertex.outgoing) {
-      /// collect the information
+      // collect the information
       m_vx      = particle.position().x();
       m_vy      = particle.position().y();
       m_vz      = particle.position().z();
@@ -117,18 +117,13 @@ FW::RootParticleWriter::writeT(const AlgorithmContext&             context,
       m_charge  = particle.q();
       m_mass    = particle.m();
       m_pdgCode = particle.pdg();
-
-      auto barcode = particle.barcode();
-      m_barcode    = barcode;
-      // decode using the barcode service
-      if (m_cfg.barcodeSvc) {
-        // the barcode service
-        m_vertex     = m_cfg.barcodeSvc->vertex(barcode);
-        m_primary    = m_cfg.barcodeSvc->primary(barcode);
-        m_generation = m_cfg.barcodeSvc->generate(barcode);
-        m_secondary  = m_cfg.barcodeSvc->secondary(barcode);
-        m_process    = m_cfg.barcodeSvc->process(barcode);
-      }
+      // store encoded and decoded barcode
+      m_barcode    = particle.barcode().value();
+      m_vertex     = particle.barcode().vertex();
+      m_primary    = particle.barcode().primary();
+      m_generation = particle.barcode().generation();
+      m_secondary  = particle.barcode().secondary();
+      m_process    = particle.barcode().process();
       m_outputTree->Fill();
     }
   }
diff --git a/Io/Root/src/RootPlanarClusterWriter.cpp b/Io/Root/src/RootPlanarClusterWriter.cpp
index a7b9d8be3..8f2bf22ce 100644
--- a/Io/Root/src/RootPlanarClusterWriter.cpp
+++ b/Io/Root/src/RootPlanarClusterWriter.cpp
@@ -174,7 +174,7 @@ FW::RootPlanarClusterWriter::writeT(
       m_t_gt.push_back(sParticle->time());
       m_t_lx.push_back(lPosition.x());
       m_t_ly.push_back(lPosition.y());
-      m_t_barcode.push_back(sParticle->barcode());
+      m_t_barcode.push_back(sParticle->barcode().value());
     }
     // fill the tree
     m_outputTree->Fill();
diff --git a/Io/Root/src/RootSimHitWriter.cpp b/Io/Root/src/RootSimHitWriter.cpp
index 5c9f579c8..3b062d6e1 100644
--- a/Io/Root/src/RootSimHitWriter.cpp
+++ b/Io/Root/src/RootSimHitWriter.cpp
@@ -17,7 +17,6 @@
 #include <TFile.h>
 #include <TTree.h>
 
-#include "ACTFW/EventData/Barcode.hpp"
 #include "ACTFW/EventData/DataContainers.hpp"
 #include "ACTFW/Framework/WhiteBoard.hpp"
 #include "ACTFW/Utilities/Paths.hpp"
diff --git a/Io/Root/src/RootTrajectoryWriter.cpp b/Io/Root/src/RootTrajectoryWriter.cpp
index 4cca3ab61..9209ac1a0 100644
--- a/Io/Root/src/RootTrajectoryWriter.cpp
+++ b/Io/Root/src/RootTrajectoryWriter.cpp
@@ -279,7 +279,7 @@ FW::RootTrajectoryWriter::writeT(const AlgorithmContext&    ctx,
         = traj.identifyMajorityParticle();
     if (not particleHitCount.empty()) {
       // Get the barcode of the majority truth particle
-      m_t_barcode = particleHitCount.front().particleId;
+      m_t_barcode = particleHitCount.front().particleId.value();
       // Find the truth particle via the barcode
       auto ip = particles.find(m_t_barcode);
       if (ip != particles.end()) {
-- 
GitLab


From 6943a5cea94447716ef740f6b76e6ce9be81fe3d Mon Sep 17 00:00:00 2001
From: Moritz Kiehn <msmk@cern.ch>
Date: Tue, 21 Jan 2020 11:32:21 +0100
Subject: [PATCH 05/12] HepMC3: use Barcode

---
 Plugins/HepMC3/src/HepMC3Event.cpp  | 5 +++--
 Plugins/HepMC3/src/HepMC3Vertex.cpp | 8 +++++---
 2 files changed, 8 insertions(+), 5 deletions(-)

diff --git a/Plugins/HepMC3/src/HepMC3Event.cpp b/Plugins/HepMC3/src/HepMC3Event.cpp
index 2726f5a1f..82ea1c162 100644
--- a/Plugins/HepMC3/src/HepMC3Event.cpp
+++ b/Plugins/HepMC3/src/HepMC3Event.cpp
@@ -169,14 +169,15 @@ FW::HepMC3Event::removeParticle(
     const std::shared_ptr<Data::SimParticle>& particle)
 {
   const std::vector<HepMC3::GenParticlePtr> genParticles = event->particles();
-  const barcode_type                        id           = particle->barcode();
+  const auto                                id           = particle->barcode();
   // Search HepMC3::GenParticle with the same id as the Acts particle
-  for (auto& genParticle : genParticles)
+  for (auto& genParticle : genParticles) {
     if (genParticle->id() == id) {
       // Remove particle if found
       event->remove_particle(genParticle);
       break;
     }
+  }
 }
 
 bool
diff --git a/Plugins/HepMC3/src/HepMC3Vertex.cpp b/Plugins/HepMC3/src/HepMC3Vertex.cpp
index ce67ed16f..c1719a2cb 100644
--- a/Plugins/HepMC3/src/HepMC3Vertex.cpp
+++ b/Plugins/HepMC3/src/HepMC3Vertex.cpp
@@ -111,12 +111,14 @@ FW::HepMC3Vertex::matchParticles(
     const std::vector<HepMC3::GenParticlePtr>& genParticles,
     std::shared_ptr<Data::SimParticle>         actsParticle)
 {
-  const barcode_type id = actsParticle->barcode();
+  const auto id = actsParticle->barcode();
   // Search HepMC3::GenParticle with the same id as the Acts particle
-  for (auto& genParticle : genParticles)
-    if (genParticle->id() == id)
+  for (auto& genParticle : genParticles) {
+    if (genParticle->id() == id) {
       // Return particle if found
       return genParticle;
+    }
+  }
   return nullptr;
 }
 
-- 
GitLab


From 2e977222efcd854193f2e95653b7eed8836f9bcb Mon Sep 17 00:00:00 2001
From: Moritz Kiehn <msmk@cern.ch>
Date: Tue, 21 Jan 2020 11:33:26 +0100
Subject: [PATCH 06/12] Pythia8: only assign primary ids via Barcode

---
 .../Generators/Pythia8ProcessGenerator.cpp    | 48 +++++++------------
 1 file changed, 18 insertions(+), 30 deletions(-)

diff --git a/Plugins/Pythia8/ACTFW/Generators/Pythia8ProcessGenerator.cpp b/Plugins/Pythia8/ACTFW/Generators/Pythia8ProcessGenerator.cpp
index b7c4897d6..16a761235 100644
--- a/Plugins/Pythia8/ACTFW/Generators/Pythia8ProcessGenerator.cpp
+++ b/Plugins/Pythia8/ACTFW/Generators/Pythia8ProcessGenerator.cpp
@@ -58,9 +58,6 @@ FW::Pythia8Generator::operator()(FW::RandomEngine& rng)
   using namespace Acts::UnitLiterals;
   using namespace Data;
 
-  // TODO remove barcode service altogether
-  auto barcodeSvc = BarcodeSvc(BarcodeSvc::Config());
-
   // first process vertex is the primary one at origin with time=0
   std::vector<SimVertex> processVertices = {
       SimVertex({0.0, 0.0, 0.0}),
@@ -95,13 +92,18 @@ FW::Pythia8Generator::operator()(FW::RandomEngine& rng)
     const auto mom  = Acts::Vector3D(
         particle.px() * 1_GeV, particle.py() * 1_GeV, particle.pz() * 1_GeV);
 
+    // vertex identifier is set by the event generator not the process generator
+    // at the moment all particles from the event generator must be treated as
+    // primary particles including the ones from displaced decay vertices. there
+    // is no secondary vertex identifier in the barcode at the moment.
+    // TODO update barcode definition
+    Barcode barcode;
+    barcode.setPrimary(ip);
+
     if (not particle.hasVertex()) {
       // w/o defined vertex, must belong to the first (primary) process vertex
-      auto& outgoing = processVertices.front().outgoing;
-      // TODO validate available index range
-      auto iprimary = outgoing.size();
-      auto barcode  = barcodeSvc.generate(0u, iprimary);
-      outgoing.emplace_back(pos, mom, mass, charge, pdg, barcode, time);
+      processVertices.front().outgoing.emplace_back(
+          pos, mom, mass, charge, pdg, barcode, time);
     } else {
       // either add to existing process vertex w/ if exists or create new one
       // TODO can we do this w/o the manual search and position/time check?
@@ -112,34 +114,20 @@ FW::Pythia8Generator::operator()(FW::RandomEngine& rng)
                                    and (vertex.time == time);
                              });
       if (it == processVertices.end()) {
-        // no maching secondary vertex exists
-        // 1st particle (primary mask) for nth process vertex (secondary mask)
-        // TODO what is the generation and process code?
-        auto iprimary    = 0u;
-        auto igeneration = 0u;
-        auto isecondary  = processVertices.size();
-        auto iprocess    = 0u;
-        auto barcode     = barcodeSvc.generate(
-            0u, iprimary, igeneration, isecondary, iprocess);
-        // no incoming particles
-        auto vertex = SimVertex(
+        // no maching secondary vertex exists -> create new one
+        SimVertex vertex(
             pos,
-            {},
-            {SimParticle(pos, mom, mass, charge, pdg, barcode, time)},
-            iprocess,
+            {},  // ignore incoming particles
+            {
+                SimParticle(pos, mom, mass, charge, pdg, barcode, time),
+            },
+            0u,  // no process identifier
             time);
         processVertices.push_back(std::move(vertex));
         ACTS_VERBOSE("created new secondary vertex " << pos.transpose());
       } else {
         // particle belongs to an existing secondary vertex
-        auto& outgoing    = it->outgoing;
-        auto  iprimary    = outgoing.size();
-        auto  igeneration = 0u;
-        auto  isecondary  = std::distance(processVertices.begin(), it);
-        auto  iprocess    = 0u;
-        auto  barcode     = barcodeSvc.generate(
-            0u, iprimary, igeneration, isecondary, iprocess);
-        outgoing.emplace_back(pos, mom, mass, charge, pdg, barcode, time);
+        it->outgoing.emplace_back(pos, mom, mass, charge, pdg, barcode, time);
       }
     }
   }
-- 
GitLab


From 35c7107740d678a3d163747ae518580156c70520 Mon Sep 17 00:00:00 2001
From: Moritz Kiehn <msmk@cern.ch>
Date: Tue, 21 Jan 2020 11:33:45 +0100
Subject: [PATCH 07/12] Examples: remove BarcodeSvc

---
 Examples/Common/src/FatrasEvgenBase.cpp            |  5 -----
 Examples/Common/src/FatrasExampleBase.cpp          |  7 ++-----
 Examples/Common/src/FatrasSimulationBase.cpp       | 14 +++-----------
 Examples/Common/src/detail/FatrasEvgenBase.hpp     |  2 --
 .../Common/src/detail/FatrasSimulationBase.hpp     |  2 --
 Examples/EventGenerator/ParticleGun.cpp            |  4 ----
 Examples/EventGenerator/Pythia8/Pythia8.cpp        |  4 ----
 Examples/ReadCsv/GenericReadCsvExample.cpp         |  1 -
 Examples/ReadCsv/PrintHits.cpp                     |  2 +-
 Examples/Reconstruction/RecTruthTracks.cpp         |  1 -
 .../VertexAndTracksReaderAndFinderExample.cpp      |  1 -
 .../Vertexing/VertexAndTracksWriterExample.cpp     |  7 ++-----
 Examples/Vertexing/VertexFinderExample.cpp         |  7 ++-----
 Examples/Vertexing/VertexFitterExample.cpp         | 10 +++-------
 14 files changed, 13 insertions(+), 54 deletions(-)

diff --git a/Examples/Common/src/FatrasEvgenBase.cpp b/Examples/Common/src/FatrasEvgenBase.cpp
index 555985b6d..cc5061aa4 100644
--- a/Examples/Common/src/FatrasEvgenBase.cpp
+++ b/Examples/Common/src/FatrasEvgenBase.cpp
@@ -8,7 +8,6 @@
 
 #include "detail/FatrasEvgenBase.hpp"
 
-#include "ACTFW/EventData/Barcode.hpp"
 #include "ACTFW/Framework/RandomNumbers.hpp"
 #include "ACTFW/Framework/Sequencer.hpp"
 #include "ACTFW/Generators/EventGenerator.hpp"
@@ -22,7 +21,6 @@
 void
 setupEvgenInput(boost::program_options::variables_map& vm,
                 FW::Sequencer&                         sequencer,
-                std::shared_ptr<FW::BarcodeSvc>        barcodeSvc,
                 std::shared_ptr<FW::RandomNumbers>     randomNumberSvc)
 {
   // Read the standard options
@@ -34,14 +32,12 @@ setupEvgenInput(boost::program_options::variables_map& vm,
     auto evgCfg          = FW::Options::readParticleGunOptions(vm);
     evgCfg.output        = "particles";
     evgCfg.randomNumbers = randomNumberSvc;
-    evgCfg.barcodeSvc    = barcodeSvc;
     sequencer.addReader(std::make_shared<FW::EventGenerator>(evgCfg, logLevel));
 
   } else if (evgenInput == "pythia8") {
     auto evgCfg          = FW::Options::readPythia8Options(vm, logLevel);
     evgCfg.output        = "particles";
     evgCfg.randomNumbers = randomNumberSvc;
-    evgCfg.barcodeSvc    = barcodeSvc;
     sequencer.addReader(std::make_shared<FW::EventGenerator>(evgCfg, logLevel));
 
   } else {
@@ -68,7 +64,6 @@ setupEvgenInput(boost::program_options::variables_map& vm,
     pWriterRootConfig.collection = "particles";
     pWriterRootConfig.filePath   = FW::joinPaths(outputDir, "particles.root");
     pWriterRootConfig.treeName   = "particles";
-    pWriterRootConfig.barcodeSvc = barcodeSvc;
     sequencer.addWriter(
         std::make_shared<FW::RootParticleWriter>(pWriterRootConfig));
   }
diff --git a/Examples/Common/src/FatrasExampleBase.cpp b/Examples/Common/src/FatrasExampleBase.cpp
index 87a67243d..af80a6bb1 100644
--- a/Examples/Common/src/FatrasExampleBase.cpp
+++ b/Examples/Common/src/FatrasExampleBase.cpp
@@ -10,7 +10,6 @@
 
 #include <boost/program_options.hpp>
 
-#include "ACTFW/EventData/Barcode.hpp"
 #include "ACTFW/Fatras/FatrasOptions.hpp"
 #include "ACTFW/Framework/RandomNumbers.hpp"
 #include "ACTFW/Framework/Sequencer.hpp"
@@ -60,8 +59,6 @@ fatrasExample(int argc, char* argv[], FW::IBaseDetector& detector)
   auto randomNumberSvcCfg = FW::Options::readRandomNumbersConfig(vm);
   auto randomNumberSvc
       = std::make_shared<FW::RandomNumbers>(randomNumberSvcCfg);
-  // Create the barcode service
-  auto barcodeSvc = std::make_shared<FW::BarcodeSvc>(FW::BarcodeSvc::Config());
 
   // The geometry, material and decoration
   auto geometry          = FW::Geometry::build(vm, detector);
@@ -75,11 +72,11 @@ fatrasExample(int argc, char* argv[], FW::IBaseDetector& detector)
 
   // (A) EVGEN
   // Setup the evgen input to the simulation
-  setupEvgenInput(vm, sequencer, barcodeSvc, randomNumberSvc);
+  setupEvgenInput(vm, sequencer, randomNumberSvc);
 
   // (B) SIMULATION
   // Setup the simulation
-  setupSimulation(vm, sequencer, tGeometry, barcodeSvc, randomNumberSvc);
+  setupSimulation(vm, sequencer, tGeometry, randomNumberSvc);
 
   // (C) DIGITIZATION
   // Setup the digitization
diff --git a/Examples/Common/src/FatrasSimulationBase.cpp b/Examples/Common/src/FatrasSimulationBase.cpp
index 7e9aa8d91..d5c551d4a 100644
--- a/Examples/Common/src/FatrasSimulationBase.cpp
+++ b/Examples/Common/src/FatrasSimulationBase.cpp
@@ -21,7 +21,6 @@
 #include <Acts/Surfaces/Surface.hpp>
 #include <boost/program_options.hpp>
 
-#include "ACTFW/EventData/Barcode.hpp"
 #include "ACTFW/EventData/SimHit.hpp"
 #include "ACTFW/EventData/SimParticle.hpp"
 #include "ACTFW/EventData/SimVertex.hpp"
@@ -139,7 +138,6 @@ setupSimulationAlgorithm(
     FW::Sequencer&                                sequencer,
     boost::program_options::variables_map&        vm,
     std::shared_ptr<const Acts::TrackingGeometry> trackingGeometry,
-    std::shared_ptr<FW::BarcodeSvc>               barcodeSvc,
     std::shared_ptr<FW::RandomNumbers>            randomNumberSvc)
 {
   // Read the log level
@@ -243,8 +241,7 @@ setupSimulationAlgorithm(
     pWriterRootConfig.collection = fatrasConfig.simulatedEventCollection;
     pWriterRootConfig.filePath   = FW::joinPaths(
         outputDir, fatrasConfig.simulatedEventCollection + ".root");
-    pWriterRootConfig.treeName   = fatrasConfig.simulatedEventCollection;
-    pWriterRootConfig.barcodeSvc = barcodeSvc;
+    pWriterRootConfig.treeName = fatrasConfig.simulatedEventCollection;
     sequencer.addWriter(
         std::make_shared<FW::RootParticleWriter>(pWriterRootConfig));
 
@@ -263,7 +260,6 @@ void
 setupSimulation(boost::program_options::variables_map&        vm,
                 FW::Sequencer&                                sequencer,
                 std::shared_ptr<const Acts::TrackingGeometry> tGeometry,
-                std::shared_ptr<FW::BarcodeSvc>               barcodeSvc,
                 std::shared_ptr<FW::RandomNumbers>            randomNumberSvc)
 {
   // Create BField service
@@ -274,12 +270,8 @@ setupSimulation(boost::program_options::variables_map&        vm,
         using field_type =
             typename std::decay_t<decltype(bField)>::element_type;
         Acts::SharedBField<field_type> fieldMap(bField);
-        setupSimulationAlgorithm(std::move(fieldMap),
-                                 sequencer,
-                                 vm,
-                                 tGeometry,
-                                 barcodeSvc,
-                                 randomNumberSvc);
+        setupSimulationAlgorithm(
+            std::move(fieldMap), sequencer, vm, tGeometry, randomNumberSvc);
       },
       bFieldVar);
 }
diff --git a/Examples/Common/src/detail/FatrasEvgenBase.hpp b/Examples/Common/src/detail/FatrasEvgenBase.hpp
index 6b9ca0e9e..6d1d4158c 100644
--- a/Examples/Common/src/detail/FatrasEvgenBase.hpp
+++ b/Examples/Common/src/detail/FatrasEvgenBase.hpp
@@ -14,12 +14,10 @@
 
 namespace FW {
 class Sequencer;
-class BarcodeSvc;
 class RandomNumbers;
 }  // namespace FW
 
 void
 setupEvgenInput(boost::program_options::variables_map& vm,
                 FW::Sequencer&                         sequencer,
-                std::shared_ptr<FW::BarcodeSvc>        barcodeSvc,
                 std::shared_ptr<FW::RandomNumbers>     randomNumberSvc);
diff --git a/Examples/Common/src/detail/FatrasSimulationBase.hpp b/Examples/Common/src/detail/FatrasSimulationBase.hpp
index 8242e2ff7..3ae6c6652 100644
--- a/Examples/Common/src/detail/FatrasSimulationBase.hpp
+++ b/Examples/Common/src/detail/FatrasSimulationBase.hpp
@@ -14,7 +14,6 @@
 
 namespace FW {
 class Sequencer;
-class BarcodeSvc;
 class RandomNumbers;
 }  // namespace FW
 
@@ -37,5 +36,4 @@ void
 setupSimulation(boost::program_options::variables_map&        vm,
                 FW::Sequencer&                                sequencer,
                 std::shared_ptr<const Acts::TrackingGeometry> tGeometry,
-                std::shared_ptr<FW::BarcodeSvc>               barcodeSvc,
                 std::shared_ptr<FW::RandomNumbers>            randomNumberSvc);
diff --git a/Examples/EventGenerator/ParticleGun.cpp b/Examples/EventGenerator/ParticleGun.cpp
index 3df2215e7..597a42972 100644
--- a/Examples/EventGenerator/ParticleGun.cpp
+++ b/Examples/EventGenerator/ParticleGun.cpp
@@ -11,7 +11,6 @@
 
 #include <Acts/Utilities/Units.hpp>
 
-#include "ACTFW/EventData/Barcode.hpp"
 #include "ACTFW/Framework/RandomNumbers.hpp"
 #include "ACTFW/Framework/Sequencer.hpp"
 #include "ACTFW/Io/Csv/CsvParticleWriter.hpp"
@@ -42,13 +41,11 @@ main(int argc, char* argv[])
   // basic services
   auto rnd
       = std::make_shared<RandomNumbers>(Options::readRandomNumbersConfig(vm));
-  auto barcode = std::make_shared<BarcodeSvc>(BarcodeSvc::Config());
 
   // event generation w/ particle gun
   EventGenerator::Config evgenCfg = Options::readParticleGunOptions(vm);
   evgenCfg.output                 = "particles";
   evgenCfg.randomNumbers          = rnd;
-  evgenCfg.barcodeSvc             = barcode;
   sequencer.addReader(std::make_shared<EventGenerator>(evgenCfg, logLevel));
 
   // different output modes
@@ -65,7 +62,6 @@ main(int argc, char* argv[])
     RootParticleWriter::Config rootWriterCfg;
     rootWriterCfg.collection = evgenCfg.output;
     rootWriterCfg.filePath   = joinPaths(outputDir, "particles.root");
-    rootWriterCfg.barcodeSvc = barcode;
     sequencer.addWriter(
         std::make_shared<RootParticleWriter>(rootWriterCfg, logLevel));
   }
diff --git a/Examples/EventGenerator/Pythia8/Pythia8.cpp b/Examples/EventGenerator/Pythia8/Pythia8.cpp
index 7f24a4e7f..2f664c18c 100644
--- a/Examples/EventGenerator/Pythia8/Pythia8.cpp
+++ b/Examples/EventGenerator/Pythia8/Pythia8.cpp
@@ -11,7 +11,6 @@
 
 #include <Acts/Utilities/Units.hpp>
 
-#include "ACTFW/EventData/Barcode.hpp"
 #include "ACTFW/Framework/RandomNumbers.hpp"
 #include "ACTFW/Framework/Sequencer.hpp"
 #include "ACTFW/Generators/ParticleSelector.hpp"
@@ -43,13 +42,11 @@ main(int argc, char* argv[])
   // basic services
   auto rnd
       = std::make_shared<RandomNumbers>(Options::readRandomNumbersConfig(vm));
-  auto barcode = std::make_shared<BarcodeSvc>(BarcodeSvc::Config());
 
   // event generation w/ internal pythia8 instance
   EventGenerator::Config evgenCfg = Options::readPythia8Options(vm, logLevel);
   evgenCfg.output                 = "generated_particles";
   evgenCfg.randomNumbers          = rnd;
-  evgenCfg.barcodeSvc             = barcode;
   sequencer.addReader(std::make_shared<EventGenerator>(evgenCfg, logLevel));
 
   // event selection
@@ -77,7 +74,6 @@ main(int argc, char* argv[])
     RootParticleWriter::Config rootWriterCfg;
     rootWriterCfg.collection = selectorCfg.output;
     rootWriterCfg.filePath   = joinPaths(outputDir, "particles.root");
-    rootWriterCfg.barcodeSvc = barcode;
     sequencer.addWriter(
         std::make_shared<RootParticleWriter>(rootWriterCfg, logLevel));
   }
diff --git a/Examples/ReadCsv/GenericReadCsvExample.cpp b/Examples/ReadCsv/GenericReadCsvExample.cpp
index b99bb2e0e..aeb0526cf 100644
--- a/Examples/ReadCsv/GenericReadCsvExample.cpp
+++ b/Examples/ReadCsv/GenericReadCsvExample.cpp
@@ -8,7 +8,6 @@
 
 #include <memory>
 
-#include "ACTFW/EventData/Barcode.hpp"
 #include "ACTFW/Framework/Sequencer.hpp"
 #include "ACTFW/Framework/WhiteBoard.hpp"
 #include "ACTFW/GenericDetector/GenericDetector.hpp"
diff --git a/Examples/ReadCsv/PrintHits.cpp b/Examples/ReadCsv/PrintHits.cpp
index 44e5023a4..73105ed31 100644
--- a/Examples/ReadCsv/PrintHits.cpp
+++ b/Examples/ReadCsv/PrintHits.cpp
@@ -28,7 +28,7 @@ FW::ProcessCode
 FW::PrintHits::execute(const FW::AlgorithmContext& ctx) const
 {
   using Clusters        = FW::GeometryIdMultimap<Acts::PlanarModuleCluster>;
-  using HitParticlesMap = FW::IndexMultimap<FW::barcode_type>;
+  using HitParticlesMap = FW::IndexMultimap<FW::Barcode>;
   using HitIds          = std::vector<size_t>;
 
   const auto& clusters = ctx.eventStore.get<Clusters>(m_cfg.inputClusters);
diff --git a/Examples/Reconstruction/RecTruthTracks.cpp b/Examples/Reconstruction/RecTruthTracks.cpp
index 925f36cec..25e423da6 100644
--- a/Examples/Reconstruction/RecTruthTracks.cpp
+++ b/Examples/Reconstruction/RecTruthTracks.cpp
@@ -11,7 +11,6 @@
 #include <Acts/Utilities/Units.hpp>
 
 #include "ACTFW/Digitization/HitSmearing.hpp"
-#include "ACTFW/EventData/Barcode.hpp"
 #include "ACTFW/Fitting/FittingAlgorithm.hpp"
 #include "ACTFW/Framework/Sequencer.hpp"
 #include "ACTFW/Framework/WhiteBoard.hpp"
diff --git a/Examples/Vertexing/VertexAndTracksReaderAndFinderExample.cpp b/Examples/Vertexing/VertexAndTracksReaderAndFinderExample.cpp
index c4a653e54..986a840b2 100644
--- a/Examples/Vertexing/VertexAndTracksReaderAndFinderExample.cpp
+++ b/Examples/Vertexing/VertexAndTracksReaderAndFinderExample.cpp
@@ -11,7 +11,6 @@
 
 #include <Acts/EventData/TrackParameters.hpp>
 
-#include "ACTFW/EventData/Barcode.hpp"
 #include "ACTFW/Framework/Sequencer.hpp"
 #include "ACTFW/Io/Root/RootVertexAndTracksReader.hpp"
 #include "ACTFW/Options/CommonOptions.hpp"
diff --git a/Examples/Vertexing/VertexAndTracksWriterExample.cpp b/Examples/Vertexing/VertexAndTracksWriterExample.cpp
index 999a85a9b..1de55a089 100644
--- a/Examples/Vertexing/VertexAndTracksWriterExample.cpp
+++ b/Examples/Vertexing/VertexAndTracksWriterExample.cpp
@@ -11,7 +11,6 @@
 #include <Acts/EventData/TrackParameters.hpp>
 #include <boost/program_options.hpp>
 
-#include "ACTFW/EventData/Barcode.hpp"
 #include "ACTFW/Framework/Sequencer.hpp"
 #include "ACTFW/Generators/ParticleSelector.hpp"
 #include "ACTFW/Generators/Pythia8ProcessGenerator.hpp"
@@ -45,15 +44,13 @@ main(int argc, char* argv[])
   auto logLevel = Options::readLogLevel(vm);
 
   // basic services
-  auto rndCfg  = Options::readRandomNumbersConfig(vm);
-  auto rnd     = std::make_shared<RandomNumbers>(rndCfg);
-  auto barcode = std::make_shared<BarcodeSvc>(BarcodeSvc::Config());
+  auto rndCfg = Options::readRandomNumbersConfig(vm);
+  auto rnd    = std::make_shared<RandomNumbers>(rndCfg);
 
   // Set up event generator producing one single hard collision
   EventGenerator::Config evgenCfg = Options::readPythia8Options(vm, logLevel);
   evgenCfg.output                 = "generated_particles";
   evgenCfg.randomNumbers          = rnd;
-  evgenCfg.barcodeSvc             = barcode;
 
   ParticleSelector::Config ptcSelectorCfg;
   ptcSelectorCfg.input       = evgenCfg.output;
diff --git a/Examples/Vertexing/VertexFinderExample.cpp b/Examples/Vertexing/VertexFinderExample.cpp
index 56e0f4826..3e899027f 100644
--- a/Examples/Vertexing/VertexFinderExample.cpp
+++ b/Examples/Vertexing/VertexFinderExample.cpp
@@ -11,7 +11,6 @@
 #include <Acts/EventData/TrackParameters.hpp>
 #include <boost/program_options.hpp>
 
-#include "ACTFW/EventData/Barcode.hpp"
 #include "ACTFW/Framework/Sequencer.hpp"
 #include "ACTFW/Generators/ParticleSelector.hpp"
 #include "ACTFW/Generators/Pythia8ProcessGenerator.hpp"
@@ -45,15 +44,13 @@ main(int argc, char* argv[])
   auto logLevel = Options::readLogLevel(vm);
 
   // basic services
-  auto rndCfg  = Options::readRandomNumbersConfig(vm);
-  auto rnd     = std::make_shared<RandomNumbers>(rndCfg);
-  auto barcode = std::make_shared<BarcodeSvc>(BarcodeSvc::Config());
+  auto rndCfg = Options::readRandomNumbersConfig(vm);
+  auto rnd    = std::make_shared<RandomNumbers>(rndCfg);
 
   // Set up event generator producing one single hard collision
   EventGenerator::Config evgenCfg = Options::readPythia8Options(vm, logLevel);
   evgenCfg.output                 = "generated_particles";
   evgenCfg.randomNumbers          = rnd;
-  evgenCfg.barcodeSvc             = barcode;
 
   ParticleSelector::Config ptcSelectorCfg;
   ptcSelectorCfg.input       = evgenCfg.output;
diff --git a/Examples/Vertexing/VertexFitterExample.cpp b/Examples/Vertexing/VertexFitterExample.cpp
index 067587b76..4c9f499d8 100644
--- a/Examples/Vertexing/VertexFitterExample.cpp
+++ b/Examples/Vertexing/VertexFitterExample.cpp
@@ -11,7 +11,6 @@
 #include <Acts/EventData/TrackParameters.hpp>
 #include <boost/program_options.hpp>
 
-#include "ACTFW/EventData/Barcode.hpp"
 #include "ACTFW/Framework/Sequencer.hpp"
 #include "ACTFW/Generators/MultiplicityGenerators.hpp"
 #include "ACTFW/Generators/Pythia8ProcessGenerator.hpp"
@@ -46,9 +45,8 @@ main(int argc, char* argv[])
   auto logLevel = Options::readLogLevel(vm);
 
   // basic services
-  auto rndCfg  = Options::readRandomNumbersConfig(vm);
-  auto rnd     = std::make_shared<RandomNumbers>(rndCfg);
-  auto barcode = std::make_shared<BarcodeSvc>(BarcodeSvc::Config());
+  auto rndCfg = Options::readRandomNumbersConfig(vm);
+  auto rnd    = std::make_shared<RandomNumbers>(rndCfg);
 
   // Set up event generator producing one single hard collision
   Pythia8Generator::Config hardCfg;
@@ -61,13 +59,11 @@ main(int argc, char* argv[])
   auto vtxStdZ  = vm["evg-vertex-z-std"].template as<double>();
 
   EventGenerator::Config evgenCfg;
-  evgenCfg.generators = {{FixedMultiplicityGenerator{1},
+  evgenCfg.generators    = {{FixedMultiplicityGenerator{1},
                           GaussianVertexGenerator{vtxStdXY, vtxStdXY, vtxStdZ},
                           Pythia8Generator::makeFunction(hardCfg, logLevel)}};
-
   evgenCfg.output        = "generated_particles";
   evgenCfg.randomNumbers = rnd;
-  evgenCfg.barcodeSvc    = barcode;
 
   // Set magnetic field
   Acts::Vector3D bField(0., 0., 2. * Acts::units::_T);
-- 
GitLab


From d8b95da82eeac35b89c42e516bc33930ddb37956 Mon Sep 17 00:00:00 2001
From: Moritz Kiehn <msmk@cern.ch>
Date: Tue, 21 Jan 2020 11:42:54 +0100
Subject: [PATCH 08/12] move hit printer to separate module

---
 Algorithms/CMakeLists.txt                           |  1 +
 .../Printers/ACTFW/Printers}/PrintHits.cpp          |  2 +-
 .../Printers/ACTFW/Printers}/PrintHits.hpp          |  5 ++---
 Algorithms/Printers/CMakeLists.txt                  | 13 +++++++++++++
 Examples/ReadCsv/CMakeLists.txt                     |  5 ++---
 Examples/ReadCsv/GenericReadCsvExample.cpp          |  2 +-
 6 files changed, 20 insertions(+), 8 deletions(-)
 rename {Examples/ReadCsv => Algorithms/Printers/ACTFW/Printers}/PrintHits.cpp (98%)
 rename {Examples/ReadCsv => Algorithms/Printers/ACTFW/Printers}/PrintHits.hpp (88%)
 create mode 100644 Algorithms/Printers/CMakeLists.txt

diff --git a/Algorithms/CMakeLists.txt b/Algorithms/CMakeLists.txt
index fa5588e2b..c341a2b09 100644
--- a/Algorithms/CMakeLists.txt
+++ b/Algorithms/CMakeLists.txt
@@ -2,6 +2,7 @@ add_subdirectory(Digitization)
 add_subdirectory(Fatras)
 add_subdirectory(Generators)
 add_subdirectory(MaterialMapping)
+add_subdirectory(Printers)
 add_subdirectory(Propagation)
 add_subdirectory(TruthTracking)
 add_subdirectory(Vertexing)
diff --git a/Examples/ReadCsv/PrintHits.cpp b/Algorithms/Printers/ACTFW/Printers/PrintHits.cpp
similarity index 98%
rename from Examples/ReadCsv/PrintHits.cpp
rename to Algorithms/Printers/ACTFW/Printers/PrintHits.cpp
index 73105ed31..6baa1c65d 100644
--- a/Examples/ReadCsv/PrintHits.cpp
+++ b/Algorithms/Printers/ACTFW/Printers/PrintHits.cpp
@@ -10,8 +10,8 @@
 
 #include <vector>
 
+#include <Acts/Plugins/Digitization/PlanarModuleCluster.hpp>
 #include <Acts/Utilities/Logger.hpp>
-#include "Acts/Plugins/Digitization/PlanarModuleCluster.hpp"
 
 #include "ACTFW/EventData/DataContainers.hpp"
 #include "ACTFW/EventData/SimParticle.hpp"
diff --git a/Examples/ReadCsv/PrintHits.hpp b/Algorithms/Printers/ACTFW/Printers/PrintHits.hpp
similarity index 88%
rename from Examples/ReadCsv/PrintHits.hpp
rename to Algorithms/Printers/ACTFW/Printers/PrintHits.hpp
index 8aea8b568..de17b4bd2 100644
--- a/Examples/ReadCsv/PrintHits.hpp
+++ b/Algorithms/Printers/ACTFW/Printers/PrintHits.hpp
@@ -15,7 +15,7 @@
 
 namespace FW {
 
-/// Select tracks by applying some selection cuts.
+/// Print hits within some geometric region-of-interest.
 class PrintHits : public BareAlgorithm
 {
 public:
@@ -37,8 +37,7 @@ public:
     size_t moduleId = 0u;
   };
 
-  PrintHits(const Config&        cfg,
-            Acts::Logging::Level level = Acts::Logging::INFO);
+  PrintHits(const Config& cfg, Acts::Logging::Level level);
 
   ProcessCode
   execute(const AlgorithmContext& ctx) const;
diff --git a/Algorithms/Printers/CMakeLists.txt b/Algorithms/Printers/CMakeLists.txt
new file mode 100644
index 000000000..60d547c45
--- /dev/null
+++ b/Algorithms/Printers/CMakeLists.txt
@@ -0,0 +1,13 @@
+add_library(
+  ActsFrameworkPrinters SHARED
+  ACTFW/Printers/PrintHits.cpp)
+target_include_directories(
+  ActsFrameworkPrinters
+  PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>)
+target_link_libraries(
+  ActsFrameworkPrinters
+  PUBLIC ActsCore ActsDigitizationPlugin ACTFramework)
+
+install(
+  TARGETS ActsFrameworkPrinters
+  LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})
diff --git a/Examples/ReadCsv/CMakeLists.txt b/Examples/ReadCsv/CMakeLists.txt
index 810a362e0..5097a5155 100644
--- a/Examples/ReadCsv/CMakeLists.txt
+++ b/Examples/ReadCsv/CMakeLists.txt
@@ -1,11 +1,10 @@
 add_executable(
   ACTFWGenericReadCsvExample
-  GenericReadCsvExample.cpp
-  PrintHits.cpp)
+  GenericReadCsvExample.cpp)
 target_link_libraries(
   ACTFWGenericReadCsvExample
   PRIVATE ActsCore ACTFramework ACTFWExamplesCommon ActsFrameworkIoCsv
-    ACTFWGenericDetector Boost::program_options)
+    ActsFrameworkPrinters ACTFWGenericDetector Boost::program_options)
 
 install(
   TARGETS ACTFWGenericReadCsvExample
diff --git a/Examples/ReadCsv/GenericReadCsvExample.cpp b/Examples/ReadCsv/GenericReadCsvExample.cpp
index aeb0526cf..a597e4fce 100644
--- a/Examples/ReadCsv/GenericReadCsvExample.cpp
+++ b/Examples/ReadCsv/GenericReadCsvExample.cpp
@@ -17,8 +17,8 @@
 #include "ACTFW/Io/Csv/CsvPlanarClusterReader.hpp"
 #include "ACTFW/Io/Csv/CsvPlanarClusterWriter.hpp"
 #include "ACTFW/Options/CommonOptions.hpp"
+#include "ACTFW/Printers/PrintHits.hpp"
 #include "ACTFW/Utilities/Options.hpp"
-#include "PrintHits.hpp"
 
 int
 main(int argc, char* argv[])
-- 
GitLab


From bf07d970418bfa0311eecd6dde47050dce508033 Mon Sep 17 00:00:00 2001
From: Moritz Kiehn <msmk@cern.ch>
Date: Tue, 21 Jan 2020 13:06:21 +0100
Subject: [PATCH 09/12] Printers: add particle printer

---
 .../ACTFW/Printers/PrintParticles.cpp         | 42 +++++++++++++++++++
 .../ACTFW/Printers/PrintParticles.hpp         | 37 ++++++++++++++++
 Algorithms/Printers/CMakeLists.txt            |  3 +-
 3 files changed, 81 insertions(+), 1 deletion(-)
 create mode 100644 Algorithms/Printers/ACTFW/Printers/PrintParticles.cpp
 create mode 100644 Algorithms/Printers/ACTFW/Printers/PrintParticles.hpp

diff --git a/Algorithms/Printers/ACTFW/Printers/PrintParticles.cpp b/Algorithms/Printers/ACTFW/Printers/PrintParticles.cpp
new file mode 100644
index 000000000..a28118d87
--- /dev/null
+++ b/Algorithms/Printers/ACTFW/Printers/PrintParticles.cpp
@@ -0,0 +1,42 @@
+// This file is part of the Acts project.
+//
+// Copyright (C) 2020 CERN for the benefit of the Acts project
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "PrintParticles.hpp"
+
+#include <vector>
+
+#include <Acts/Utilities/Logger.hpp>
+
+#include "ACTFW/EventData/SimVertex.hpp"
+#include "ACTFW/Framework/WhiteBoard.hpp"
+
+FW::PrintParticles::PrintParticles(const Config& cfg, Acts::Logging::Level lvl)
+  : BareAlgorithm("PrintParticles", lvl), m_cfg(cfg)
+{
+}
+
+FW::ProcessCode
+FW::PrintParticles::execute(const FW::AlgorithmContext& ctx) const
+{
+  using Event = std::vector<Data::SimVertex>;
+
+  const auto& event = ctx.eventStore.get<Event>(m_cfg.inputEvent);
+
+  ACTS_INFO("event=" << ctx.eventNumber);
+
+  for (size_t ivtx = 0; ivtx < event.size(); ++ivtx) {
+    const auto& vtx = event[ivtx];
+
+    ACTS_INFO("vertex idx=" << ivtx);
+
+    for (const auto& prt : vtx.outgoing) {
+      ACTS_INFO("  barcode=" << prt.barcode() << " pdg=" << prt.pdg());
+    }
+  }
+  return ProcessCode::SUCCESS;
+}
diff --git a/Algorithms/Printers/ACTFW/Printers/PrintParticles.hpp b/Algorithms/Printers/ACTFW/Printers/PrintParticles.hpp
new file mode 100644
index 000000000..2c53a626e
--- /dev/null
+++ b/Algorithms/Printers/ACTFW/Printers/PrintParticles.hpp
@@ -0,0 +1,37 @@
+// This file is part of the Acts project.
+//
+// Copyright (C) 2020 CERN for the benefit of the Acts project
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#pragma once
+
+#include <cstddef>
+#include <string>
+
+#include "ACTFW/Framework/BareAlgorithm.hpp"
+
+namespace FW {
+
+/// Print all particles.
+class PrintParticles : public BareAlgorithm
+{
+public:
+  struct Config
+  {
+    /// Input event collection.
+    std::string inputEvent;
+  };
+
+  PrintParticles(const Config& cfg, Acts::Logging::Level lvl);
+
+  ProcessCode
+  execute(const AlgorithmContext& ctx) const;
+
+private:
+  Config m_cfg;
+};
+
+}  // namespace FW
diff --git a/Algorithms/Printers/CMakeLists.txt b/Algorithms/Printers/CMakeLists.txt
index 60d547c45..2eba339a0 100644
--- a/Algorithms/Printers/CMakeLists.txt
+++ b/Algorithms/Printers/CMakeLists.txt
@@ -1,6 +1,7 @@
 add_library(
   ActsFrameworkPrinters SHARED
-  ACTFW/Printers/PrintHits.cpp)
+  ACTFW/Printers/PrintHits.cpp
+  ACTFW/Printers/PrintParticles.cpp)
 target_include_directories(
   ActsFrameworkPrinters
   PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>)
-- 
GitLab


From 318839817b4877d59277ed43d43452dbc41450e5 Mon Sep 17 00:00:00 2001
From: Moritz Kiehn <msmk@cern.ch>
Date: Tue, 21 Jan 2020 13:08:30 +0100
Subject: [PATCH 10/12] Examples: generator examples print particles

---
 Examples/EventGenerator/CMakeLists.txt         | 2 +-
 Examples/EventGenerator/ParticleGun.cpp        | 6 ++++++
 Examples/EventGenerator/Pythia8/CMakeLists.txt | 3 ++-
 Examples/EventGenerator/Pythia8/Pythia8.cpp    | 7 ++++++-
 4 files changed, 15 insertions(+), 3 deletions(-)

diff --git a/Examples/EventGenerator/CMakeLists.txt b/Examples/EventGenerator/CMakeLists.txt
index 109cee218..82bc1797b 100644
--- a/Examples/EventGenerator/CMakeLists.txt
+++ b/Examples/EventGenerator/CMakeLists.txt
@@ -5,7 +5,7 @@ target_link_libraries(
   ActsParticleGun
   PRIVATE
     ActsFrameworkGenerators ACTFWExamplesCommon ActsFrameworkIoRoot
-    ActsFrameworkIoCsv  Boost::program_options)
+  ActsFrameworkIoCsv ActsFrameworkPrinters Boost::program_options)
 
 install(
   TARGETS ActsParticleGun
diff --git a/Examples/EventGenerator/ParticleGun.cpp b/Examples/EventGenerator/ParticleGun.cpp
index 597a42972..6a32cfa23 100644
--- a/Examples/EventGenerator/ParticleGun.cpp
+++ b/Examples/EventGenerator/ParticleGun.cpp
@@ -17,6 +17,7 @@
 #include "ACTFW/Io/Root/RootParticleWriter.hpp"
 #include "ACTFW/Options/CommonOptions.hpp"
 #include "ACTFW/Options/ParticleGunOptions.hpp"
+#include "ACTFW/Printers/PrintParticles.hpp"
 #include "ACTFW/Utilities/Paths.hpp"
 
 using namespace Acts::units;
@@ -48,6 +49,11 @@ main(int argc, char* argv[])
   evgenCfg.randomNumbers          = rnd;
   sequencer.addReader(std::make_shared<EventGenerator>(evgenCfg, logLevel));
 
+  // print generated particles
+  PrintParticles::Config printCfg;
+  printCfg.inputEvent = evgenCfg.output;
+  sequencer.addAlgorithm(std::make_shared<PrintParticles>(printCfg, logLevel));
+
   // different output modes
   std::string outputDir = vm["output-dir"].as<std::string>();
   if (vm["output-csv"].as<bool>()) {
diff --git a/Examples/EventGenerator/Pythia8/CMakeLists.txt b/Examples/EventGenerator/Pythia8/CMakeLists.txt
index 9aacd8cf2..42913737a 100644
--- a/Examples/EventGenerator/Pythia8/CMakeLists.txt
+++ b/Examples/EventGenerator/Pythia8/CMakeLists.txt
@@ -3,7 +3,8 @@ target_link_libraries(
   ActsPythia8
   PRIVATE
     ActsFrameworkGenerators ActsFrameworkPythia8 ACTFWExamplesCommon
-    ActsFrameworkIoRoot ActsFrameworkIoCsv Boost::program_options)
+    ActsFrameworkIoRoot ActsFrameworkIoCsv ActsFrameworkPrinters
+    Boost::program_options)
 
 install(
   TARGETS ActsPythia8
diff --git a/Examples/EventGenerator/Pythia8/Pythia8.cpp b/Examples/EventGenerator/Pythia8/Pythia8.cpp
index 2f664c18c..0bc927e2c 100644
--- a/Examples/EventGenerator/Pythia8/Pythia8.cpp
+++ b/Examples/EventGenerator/Pythia8/Pythia8.cpp
@@ -18,6 +18,7 @@
 #include "ACTFW/Io/Root/RootParticleWriter.hpp"
 #include "ACTFW/Options/CommonOptions.hpp"
 #include "ACTFW/Options/Pythia8Options.hpp"
+#include "ACTFW/Printers/PrintParticles.hpp"
 #include "ACTFW/Utilities/Paths.hpp"
 
 using namespace Acts::units;
@@ -59,9 +60,13 @@ main(int argc, char* argv[])
   sequencer.addAlgorithm(
       std::make_shared<ParticleSelector>(selectorCfg, logLevel));
 
+  // print generated particles
+  PrintParticles::Config printCfg;
+  printCfg.inputEvent = selectorCfg.output;
+  sequencer.addAlgorithm(std::make_shared<PrintParticles>(printCfg, logLevel));
+
   // different output modes
   std::string outputDir = vm["output-dir"].as<std::string>();
-
   if (vm["output-csv"].as<bool>()) {
     CsvParticleWriter::Config csvWriterCfg;
     csvWriterCfg.inputEvent = selectorCfg.output;
-- 
GitLab


From e9652c30fa1622dff55c2a63cbf235eb1af75e54 Mon Sep 17 00:00:00 2001
From: Bastian Schlag <bastian.schlag@cern.ch>
Date: Wed, 22 Jan 2020 11:28:42 +0000
Subject: [PATCH 11/12] Apply suggestion to
 Algorithms/Generators/ACTFW/Generators/EventGenerator.cpp

---
 Algorithms/Generators/ACTFW/Generators/EventGenerator.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Algorithms/Generators/ACTFW/Generators/EventGenerator.cpp b/Algorithms/Generators/ACTFW/Generators/EventGenerator.cpp
index f6b061e24..1a134f173 100644
--- a/Algorithms/Generators/ACTFW/Generators/EventGenerator.cpp
+++ b/Algorithms/Generators/ACTFW/Generators/EventGenerator.cpp
@@ -69,7 +69,7 @@ FW::EventGenerator::read(const AlgorithmContext& ctx)
       // particles associated directly to the primary vertex itself.
       auto processVertices = generate.process(rng);
 
-      // updae
+      // update
       for (auto& processVertex : processVertices) {
         nSecondaryVertices += 1;
 
-- 
GitLab


From 2c2a1de0adb606eb90d6642659135b348be6903b Mon Sep 17 00:00:00 2001
From: Bastian Schlag <bastian.schlag@cern.ch>
Date: Wed, 22 Jan 2020 11:29:02 +0000
Subject: [PATCH 12/12] Apply suggestion to
 Plugins/Pythia8/ACTFW/Generators/Pythia8ProcessGenerator.cpp

---
 Plugins/Pythia8/ACTFW/Generators/Pythia8ProcessGenerator.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Plugins/Pythia8/ACTFW/Generators/Pythia8ProcessGenerator.cpp b/Plugins/Pythia8/ACTFW/Generators/Pythia8ProcessGenerator.cpp
index 16a761235..803ba1f11 100644
--- a/Plugins/Pythia8/ACTFW/Generators/Pythia8ProcessGenerator.cpp
+++ b/Plugins/Pythia8/ACTFW/Generators/Pythia8ProcessGenerator.cpp
@@ -114,7 +114,7 @@ FW::Pythia8Generator::operator()(FW::RandomEngine& rng)
                                    and (vertex.time == time);
                              });
       if (it == processVertices.end()) {
-        // no maching secondary vertex exists -> create new one
+        // no matching secondary vertex exists -> create new one
         SimVertex vertex(
             pos,
             {},  // ignore incoming particles
-- 
GitLab