diff --git a/reco/eventbuilder/digis/CbmBuildEventsIdeal.cxx b/reco/eventbuilder/digis/CbmBuildEventsIdeal.cxx
index 4445900cd482f8e9fbfd8d33b7bdf32dca004d47..1baac969438063fb06f9c476be5113c197f45079 100644
--- a/reco/eventbuilder/digis/CbmBuildEventsIdeal.cxx
+++ b/reco/eventbuilder/digis/CbmBuildEventsIdeal.cxx
@@ -32,53 +32,89 @@ CbmBuildEventsIdeal::~CbmBuildEventsIdeal() {}
 // ===========================================================================
 
 
+// =====   Number if different pairs (input,event) in a match object   =======
+UInt_t CbmBuildEventsIdeal::EventsInMatch(const CbmMatch* match) {
+
+  // --- No or empty match object
+  if (match == nullptr) return 0;
+  if (!match->GetNofLinks()) return 0;
+
+  // --- Only one link
+  if (match->GetNofLinks() == 1) return 1;
+
+  // --- More than one link: check whether they are from different events
+  CbmMatch testMatch;
+  for (Int_t iLink = 0; iLink < match->GetNofLinks(); iLink++) {
+    Int_t input = match->GetLink(iLink).GetFile();
+    Int_t event = match->GetLink(iLink).GetEntry();
+    testMatch.AddLink(1., 0, event, input);
+  }
+  return testMatch.GetNofLinks();
+}
+// ===========================================================================
+
+
 // =====   Task execution   ==================================================
 void CbmBuildEventsIdeal::Exec(Option_t*) {
 
+  // --- Timer and counters
   TStopwatch timer;
   timer.Start();
-  std::map<Int_t, CbmEvent*> eventMap;
-  Int_t nEvents      = 0;
-  UInt_t nDigisTot   = 0;
-  UInt_t nDigisNoise = 0;
+  Int_t nEvents      = 0;  // Number of created events
+  UInt_t nDigisTot   = 0;  // Total number of digis
+  UInt_t nDigisNoise = 0;  // Digis without link to MC event
+  UInt_t nDigisAmbig = 0;  // Digis with links to multiple MC events
 
-  // Clear output array
+  // --- Clear output array
   fEvents->Delete();
 
+  // --- Bookkeeping: Map from (input number, event number) to event
+  map<pair<Int_t, Int_t>, CbmEvent*> eventMap;
+
+  // --- Loop over all detector systems
   for (ECbmModuleId& system : fSystems) {
+
+    // --- Skip system if no data branch or no match match present
     if (!fDigiMan->IsPresent(system)) continue;
     if (!fDigiMan->IsMatchPresent(system)) continue;
+
+    // --- Loop over digis for the current system
     Int_t nDigis  = fDigiMan->GetNofDigis(system);
     UInt_t nNoise = 0;
-    LOG(info) << GetName() << ": System "
-              << CbmModuleList::GetModuleNameCaps(system) << ", digis "
-              << nDigis;
-
+    UInt_t nAmbig = 0;
     for (Int_t iDigi = 0; iDigi < nDigis; iDigi++) {
+
+      // --- Get the MC input and event number through the match object
       const CbmMatch* match = fDigiMan->GetMatch(system, iDigi);
       assert(match);
+      Int_t mcInput = -1;
+      Int_t mcEvent = -1;
+      if (match->GetNofLinks()) {
+        mcInput = match->GetMatchedLink().GetFile();
+        mcEvent = match->GetMatchedLink().GetEntry();
+      }
 
-      // This implementation uses only MC event number from
-      // the matched link, i.e. that with the largest weight.
-      // Can be refined later on.
-      Int_t mcEventNr = match->GetMatchedLink().GetEntry();
-
-      // Ignore digis with missing event number (noise)
-      if (mcEventNr < 0) {
+      // --- Empty match objects or negative event numbers signal noise
+      if (mcInput < 0 || mcEvent < 0) {
         nNoise++;
         continue;
       }
 
-      // Get event pointer. If event is not yet present, create it.
-      CbmEvent* event = NULL;
-      if (eventMap.find(mcEventNr) == eventMap.end()) {
-        event               = new ((*fEvents)[nEvents]) CbmEvent(nEvents);
-        eventMap[mcEventNr] = event;
+      // --- Count occurrences of multiple MC events in match
+      if (EventsInMatch(match) > 1) nAmbig++;
+
+      // --- Get event pointer. If event is not yet present, create it.
+      CbmEvent* event = nullptr;
+      auto it         = eventMap.find(make_pair(mcInput, mcEvent));
+      if (it == eventMap.end()) {
+        assert(nEvents == fEvents->GetEntriesFast());
+        event = new ((*fEvents)[nEvents]) CbmEvent(nEvents);
+        eventMap[make_pair(mcInput, mcEvent)] = event;
         nEvents++;
       } else
-        event = eventMap.at(mcEventNr);
+        event = it->second;
 
-      // Fill digi index into event
+      // --- Fill digi index into event
       switch (system) {
         case ECbmModuleId::kMvd:
           event->AddData(ECbmDataType::kMvdDigi, iDigi);
@@ -105,25 +141,25 @@ void CbmBuildEventsIdeal::Exec(Option_t*) {
       }  //? detector
 
     }  //# digis
-    LOG(debug) << GetName() << ": Detector "
-               << CbmModuleList::GetModuleNameCaps(system) << ", digis "
-               << nDigis << ", noise " << nNoise;
+    LOG(info) << GetName() << ": Detector "
+              << CbmModuleList::GetModuleNameCaps(system) << ", digis "
+              << nDigis << " (" << nAmbig << " ambiguous), noise " << nNoise;
     nDigisTot += nDigis;
+    nDigisAmbig += nAmbig;
     nDigisNoise += nNoise;
 
-  }  //# detectors
-
+  }  //# detector systems
 
   timer.Stop();
   assert(nEvents == fEvents->GetEntriesFast());
 
   // --- Execution log
   std::cout << std::endl;
-  LOG(info) << "+ " << setw(15) << GetName() << ": Time-slice " << setw(3)
-            << right << fNofEntries << ", events: " << setw(6) << nEvents
-            << ", digis: " << nDigisTot << ", noise: " << nDigisNoise
-            << ". Exec time " << fixed << setprecision(6) << timer.RealTime()
-            << " s.";
+  Double_t execTime = 1000. * timer.RealTime();
+  LOG(info) << setw(20) << left << GetName() << "[" << fixed << setprecision(4)
+            << execTime << " ms] : TSlice " << right << fNofEntries
+            << ", events: " << nEvents << ", digis: " << nDigisTot << " ("
+            << nDigisAmbig << " ambiguous), noise: " << nDigisNoise;
 
   // --- For debug: event info
   if (gLogger->IsLogNeeded(fair::Severity::debug)) {
diff --git a/reco/eventbuilder/digis/CbmBuildEventsIdeal.h b/reco/eventbuilder/digis/CbmBuildEventsIdeal.h
index 80de7fb5e38712b6d3514f6251c5086af7cd1727..f093135592700e6fcfb6ff05108ddaffdd6beb27 100644
--- a/reco/eventbuilder/digis/CbmBuildEventsIdeal.h
+++ b/reco/eventbuilder/digis/CbmBuildEventsIdeal.h
@@ -1,8 +1,10 @@
 /** @file CbmBuildEventsIdeal.h
  ** @author Volker Friese <v.friese@gsi.de>
- ** @date 17.09.2016
+ ** @since 17.09.2016
+ ** @date 15.^^.1010
  **/
-#ifndef CBMBUILDEVENTSIDEAL_H_
+
+#ifndef CBMBUILDEVENTSIDEAL_H
 #define CBMBUILDEVENTSIDEAL_H 1
 
 
@@ -12,41 +14,57 @@
 
 class TClonesArray;
 class CbmDigiManager;
+class CbmMatch;
+
 
 /** @class CbmStsBuildEventsIdeal
  ** @brief Task class for associating digis to events
  ** @author Volker Friese <v.friese@gsi.de>
  ** @since 17.09.2016
- ** @version 1.0
+ ** @date 15.11.2020
+ **
+ ** The digi event builder creates objects of class CbmEvent and fills them
+ ** with digi objects. For the association of the digis to the events, the
+ ** MC-truth information in the digi match objects is employed. A digi
+ ** is attributed to the event of its link with the largest weight.
  **
- ** The event association uses MC truth (CbmMatch of CbmDigi).
- ** It operates within one time slice; splitting of events between
- ** time slice is not treated.
+ ** The event builder operates within one time slice; splitting of events
+ ** between time slices is not treated.
  **/
 class CbmBuildEventsIdeal : public FairTask {
 
 public:
-  /** Constructor **/
+  /** @brief Constructor **/
   CbmBuildEventsIdeal();
 
-  /** Destructor **/
+  /** @brief Copy constructor (disabled) **/
+  CbmBuildEventsIdeal(const CbmBuildEventsIdeal&) = delete;
+
+  /** @brief Destructor **/
   virtual ~CbmBuildEventsIdeal();
 
-  /** Task execution **/
+  /** @brief Task execution **/
   virtual void Exec(Option_t* opt);
 
+  /** @brief Assignment operator (disabled) **/
+  CbmBuildEventsIdeal& operator=(const CbmBuildEventsIdeal&) = delete;
 
-private:
-  CbmDigiManager* fDigiMan = nullptr;  //!
-  std::vector<ECbmModuleId> fSystems {};
-  TClonesArray* fEvents = nullptr;  //! Output array (class CbmEvent)
-  Int_t fNofEntries     = 0;        //  Number of processed time slices
 
-  /** Task initialisation **/
+private:  // methods
+  /** @brief Task initialisation **/
   virtual InitStatus Init();
 
-  CbmBuildEventsIdeal(const CbmBuildEventsIdeal&) = delete;
-  CbmBuildEventsIdeal& operator=(const CbmBuildEventsIdeal&) = delete;
+
+  /** @brief Number of different MC events in a match object **/
+  UInt_t EventsInMatch(const CbmMatch* match);
+
+
+private:                                  // members
+  CbmDigiManager* fDigiMan = nullptr;     //!
+  std::vector<ECbmModuleId> fSystems {};  //  List of detector systems
+  TClonesArray* fEvents = nullptr;        //! Output array (class CbmEvent)
+  Int_t fNofEntries     = 0;              //  Number of processed time slices
+
 
   ClassDef(CbmBuildEventsIdeal, 3);
 };