Skip to content

Commit 2a94b79

Browse files
pillotshahor02
authored andcommitted
event finder algorithm and workflow
1 parent 69ef405 commit 2a94b79

20 files changed

Lines changed: 966 additions & 14 deletions

File tree

DataFormats/Detectors/MUON/MCH/include/DataFormatsMCH/Digit.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ class Digit
3636
~Digit() = default;
3737

3838
bool operator==(const Digit&) const;
39+
bool operator!=(const Digit& other) const { return !(*this == other); }
3940
bool operator<(const Digit&) const;
4041

4142
// time in bunch crossing units, relative to the beginning of the TimeFrame
@@ -65,10 +66,10 @@ class Digit
6566
uint32_t mADC; /// Amplitude of signal
6667

6768
ClassDefNV(Digit, 4);
68-
}; //class Digit
69+
}; // class Digit
6970

7071
std::ostream& operator<<(std::ostream& os, const Digit& d);
7172

72-
} //namespace mch
73-
} //namespace o2
73+
} // namespace mch
74+
} // namespace o2
7475
#endif // ALICEO2_MCH_DIGIT_H_

DataFormats/Detectors/MUON/MCH/include/DataFormatsMCH/ROFRecord.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ class ROFRecord
6464
mDataRef == other.mDataRef &&
6565
mBCWidth == other.mBCWidth;
6666
}
67+
bool operator!=(const ROFRecord& other) const { return !(*this == other); }
6768
bool operator<(const ROFRecord& other) const
6869
{
6970
if (mBCData == other.mBCData) {

DataFormats/Detectors/MUON/MCH/src/Digit.cxx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,8 @@ bool Digit::operator==(const Digit& other) const
6666
mPadID == other.mPadID &&
6767
mADC == other.mADC &&
6868
mTFtime == other.mTFtime &&
69-
mNofSamples == other.mNofSamples;
69+
mNofSamples == other.mNofSamples &&
70+
mIsSaturated == other.mIsSaturated;
7071
}
7172

7273
bool Digit::operator<(const Digit& other) const

Detectors/MUON/MCH/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
add_subdirectory(Base)
1313
add_subdirectory(Contour)
1414
add_subdirectory(Mapping)
15+
add_subdirectory(Triggering)
1516
add_subdirectory(TimeClustering)
1617
add_subdirectory(PreClustering)
1718
add_subdirectory(Geometry)

Detectors/MUON/MCH/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ This is a top page for the MCH detector documentation.
1313
\subpage refDetectorsMUONMCHRaw
1414
\subpage refDetectorsMUONMCHMapping
1515
\subpage refDetectorsMUONMCHTracking
16+
\subpage refDetectorsMUONMCHTriggering
1617
\subpage refDetectorsMUONMCHWorkflow
1718
\subpage refDetectorsMUONMCHGeometry
1819
\subpage refDetectorsMUONMCHConditions
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2+
# See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3+
# All rights not expressly granted are reserved.
4+
#
5+
# This software is distributed under the terms of the GNU General Public
6+
# License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7+
#
8+
# In applying this license CERN does not waive the privileges and immunities
9+
# granted to it by virtue of its status as an Intergovernmental Organization
10+
# or submit itself to any jurisdiction.
11+
12+
o2_add_library(MCHTriggering
13+
SOURCES
14+
src/EventFinder.cxx
15+
src/EventFinderParam.cxx
16+
PUBLIC_LINK_LIBRARIES O2::CommonUtils O2::DataFormatsMCH O2::DataFormatsMID)
17+
18+
o2_target_root_dictionary(MCHTriggering
19+
HEADERS include/MCHTriggering/EventFinderParam.h)
20+
21+
if(BUILD_TESTING)
22+
add_subdirectory(test)
23+
endif()
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<!-- doxy
2+
\page refDetectorsMUONMCHTriggering Triggering
3+
/doxy -->
4+
5+
# EventFinder.h(cxx)
6+
7+
Implementation of the MCH event finder algorithm.
8+
9+
## Input / Output
10+
11+
It takes as input the lists of MCH ROFs, MCH digits, MCH digit MC labels (if any) and MID ROFs. It returns the list of digits associated to an event, their MC labels (if any) and the list of ROFs corresponding to the events.
12+
13+
## Short description of the algorithm
14+
15+
The event finding is done in 4 steps:
16+
1) Create an empty event for each MID ROF with a trigger window opened around the MID Interaction Record (IR). The size of the window is defined via EventFinderParam (see below).
17+
2) Associate each MCH ROF to the first compatible event, if any. An event is compatible if the trigger window overlaps with the MCH RO window.
18+
3) Merge overlapping events and remove empty ones. Two events overlap if the MCH RO window associated to one event overlaps with the trigger window of another.
19+
4) Copy the digits (and MC labels) associated to each event in the ouput lists, merging them if the same pad is fired multiple times within the same event, and produce the output ROFs pointing to them. The time window of each ROF is set to contain only the MID IR(s) associated to the event.
20+
21+
# EventFinderParam.h(cxx)
22+
23+
Definition of the trigger window [min, max[, in BC unit, opened around to MID IR to gather the digits associated with this interaction.
24+
25+
The window is configurable via the command line or an INI or JSON configuration file (cf. [workflow documentation](../Workflow/README.md)).
26+
27+
## Example of workflow
28+
29+
`o2-mid-tracks-reader-workflow | o2-mch-reco-workflow --triggered`
30+
31+
This takes as input the root files with MCH digits and MID tracks and ROFs and gives as ouput a root file with the MCH tracks. The event finder device is activated in the reconstruction workflow with the option `--triggered`.
32+
33+
See the [workflow documentation](../Workflow/README.md) for more details about the event finder workflow.
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2+
// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3+
// All rights not expressly granted are reserved.
4+
//
5+
// This software is distributed under the terms of the GNU General Public
6+
// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7+
//
8+
// In applying this license CERN does not waive the privileges and immunities
9+
// granted to it by virtue of its status as an Intergovernmental Organization
10+
// or submit itself to any jurisdiction.
11+
12+
/// \file EventFinder.h
13+
/// \brief Definition of a class to group MCH digits based on MID information
14+
///
15+
/// \author Philippe Pillot, Subatech
16+
17+
#ifndef ALICEO2_MCH_EVENTFINDER_H_
18+
#define ALICEO2_MCH_EVENTFINDER_H_
19+
20+
#include <map>
21+
#include <unordered_map>
22+
#include <vector>
23+
24+
#include <gsl/span>
25+
26+
#include "SimulationDataFormat/MCCompLabel.h"
27+
#include "SimulationDataFormat/MCTruthContainer.h"
28+
#include "DataFormatsMCH/Digit.h"
29+
#include "DataFormatsMCH/ROFRecord.h"
30+
#include "DataFormatsMID/ROFRecord.h"
31+
32+
namespace o2
33+
{
34+
namespace mch
35+
{
36+
37+
/// Class to group MCH digits based on MID information
38+
class EventFinder
39+
{
40+
public:
41+
EventFinder() = default;
42+
~EventFinder() = default;
43+
44+
EventFinder(const EventFinder&) = delete;
45+
EventFinder& operator=(const EventFinder&) = delete;
46+
EventFinder(EventFinder&&) = delete;
47+
EventFinder& operator=(EventFinder&&) = delete;
48+
49+
void run(const gsl::span<const mch::ROFRecord>& mchROFs, const gsl::span<const mch::Digit>& digits,
50+
const dataformats::MCLabelContainer* labels, const gsl::span<const mid::ROFRecord>& midROFs);
51+
52+
/// get the output MCH ROFs
53+
const std::vector<mch::ROFRecord>& getOutputROFs() const { return mROFs; }
54+
/// get the output MCH digits
55+
const std::vector<mch::Digit>& getOutputDigits() const { return mDigits; }
56+
/// get the output MCH labels
57+
const dataformats::MCLabelContainer& getOutputLabels() const { return mLabels; }
58+
59+
private:
60+
/// internal event structure
61+
struct Event {
62+
/// contruct an empty event with trigger window = [bcMin, bcMax[
63+
Event(int64_t bcMin, int64_t bcMax) : maxRORange(bcMin)
64+
{
65+
trgRange[0] = bcMin;
66+
trgRange[1] = bcMax;
67+
}
68+
69+
int64_t trgRange[2]{}; ///< BC range of the MID trigger window
70+
int64_t maxRORange = 0; ///< upper limit of the MCH RO window
71+
std::vector<int> iMCHROFs{}; ///< list of associated MCH ROF indices
72+
};
73+
74+
std::map<int64_t, Event> mEvents{}; ///< sorted list of events found
75+
std::vector<mch::ROFRecord> mROFs{}; ///< list of output MCH ROFs
76+
std::vector<mch::Digit> mDigits{}; ///< list of output MCH digits
77+
dataformats::MCLabelContainer mLabels{}; ///< container of output MCH digit labels
78+
std::unordered_map<int, int> mDigitLoc{}; ///< map the digit indices of a particular event
79+
};
80+
81+
} // namespace mch
82+
} // namespace o2
83+
84+
#endif // ALICEO2_MCH_EVENTFINDER_H_
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2+
// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3+
// All rights not expressly granted are reserved.
4+
//
5+
// This software is distributed under the terms of the GNU General Public
6+
// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7+
//
8+
// In applying this license CERN does not waive the privileges and immunities
9+
// granted to it by virtue of its status as an Intergovernmental Organization
10+
// or submit itself to any jurisdiction.
11+
12+
/// \file EventFinderParam.h
13+
/// \brief Configurable parameters to group MCH digits based on MID information
14+
/// \author Philippe Pillot, Subatech
15+
16+
#ifndef ALICEO2_MCH_EVENTFINDERPARAM_H_
17+
#define ALICEO2_MCH_EVENTFINDERPARAM_H_
18+
19+
#include "CommonUtils/ConfigurableParam.h"
20+
#include "CommonUtils/ConfigurableParamHelper.h"
21+
22+
namespace o2
23+
{
24+
namespace mch
25+
{
26+
27+
/// Configurable parameters to group MCH digits based on MID information
28+
struct EventFinderParam : public o2::conf::ConfigurableParamHelper<EventFinderParam> {
29+
30+
int triggerRange[2] = {0, 1}; ///< BC range of the trigger window around the MID IR
31+
32+
O2ParamDef(EventFinderParam, "MCHTriggering");
33+
};
34+
35+
} // namespace mch
36+
} // namespace o2
37+
38+
#endif // ALICEO2_MCH_EVENTFINDERPARAM_H_
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2+
// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3+
// All rights not expressly granted are reserved.
4+
//
5+
// This software is distributed under the terms of the GNU General Public
6+
// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7+
//
8+
// In applying this license CERN does not waive the privileges and immunities
9+
// granted to it by virtue of its status as an Intergovernmental Organization
10+
// or submit itself to any jurisdiction.
11+
12+
/// \file EventFinder.cxx
13+
/// \brief Implementation of a class to group MCH digits based on MID information
14+
///
15+
/// \author Philippe Pillot, Subatech
16+
17+
#include "MCHTriggering/EventFinder.h"
18+
19+
#include <algorithm>
20+
#include <iterator>
21+
#include <utility>
22+
23+
#include "CommonDataFormat/InteractionRecord.h"
24+
#include "MCHTriggering/EventFinderParam.h"
25+
26+
namespace o2
27+
{
28+
namespace mch
29+
{
30+
31+
//_________________________________________________________________________________________________
32+
/// run the event finder algorithm
33+
void EventFinder::run(const gsl::span<const mch::ROFRecord>& mchROFs,
34+
const gsl::span<const mch::Digit>& digits,
35+
const dataformats::MCLabelContainer* labels,
36+
const gsl::span<const mid::ROFRecord>& midROFs)
37+
{
38+
mEvents.clear();
39+
mROFs.clear();
40+
mDigits.clear();
41+
mLabels.clear();
42+
43+
if (mchROFs.empty() || midROFs.empty()) {
44+
return;
45+
}
46+
47+
// create empty events ordered in increasing trigger time
48+
const auto& param = EventFinderParam::Instance();
49+
for (const auto& midROF : midROFs) {
50+
if (midROF.nEntries == 0) {
51+
continue;
52+
}
53+
auto midBC = midROF.interactionRecord.toLong();
54+
mEvents.emplace(std::make_pair(midBC, Event(midBC + param.triggerRange[0], midBC + param.triggerRange[1])));
55+
}
56+
57+
// associate each MCH ROF to the first compatible trigger, if any
58+
for (int i = 0; i < mchROFs.size(); ++i) {
59+
auto mchBC = mchROFs[i].getBCData().toLong();
60+
auto itEvent = mEvents.lower_bound(mchBC - param.triggerRange[1] + 1);
61+
if (itEvent != mEvents.end() && itEvent->second.trgRange[0] < mchBC + mchROFs[i].getBCWidth()) {
62+
itEvent->second.iMCHROFs.push_back(i);
63+
itEvent->second.maxRORange = std::max(itEvent->second.maxRORange, mchBC + mchROFs[i].getBCWidth());
64+
}
65+
}
66+
67+
// merge overlapping events (when a MCH ROF is compatible with multiple trigger) and cleanup
68+
for (auto itEvent = mEvents.begin(); itEvent != mEvents.end();) {
69+
if (itEvent->second.iMCHROFs.empty()) {
70+
itEvent = mEvents.erase(itEvent);
71+
} else {
72+
auto itNextEvent = std::next(itEvent);
73+
if (itNextEvent != mEvents.end() && itNextEvent->second.trgRange[0] < itEvent->second.maxRORange) {
74+
itEvent->second.trgRange[1] = itNextEvent->second.trgRange[1];
75+
itEvent->second.maxRORange = std::max(itEvent->second.maxRORange, itNextEvent->second.maxRORange);
76+
itEvent->second.iMCHROFs.insert(itEvent->second.iMCHROFs.end(),
77+
itNextEvent->second.iMCHROFs.begin(), itNextEvent->second.iMCHROFs.end());
78+
mEvents.erase(itNextEvent);
79+
} else {
80+
itEvent = itNextEvent;
81+
}
82+
}
83+
}
84+
85+
// merge digits associated to each event and produce the output ROFs pointing to them
86+
// the BC range of each ROF is set to contain only the MID IR(s) associated to the event
87+
InteractionRecord ir{};
88+
for (const auto& event : mEvents) {
89+
mDigitLoc.clear();
90+
int digitOffset = mDigits.size();
91+
for (auto iMCHROF : event.second.iMCHROFs) {
92+
for (int iDigit = mchROFs[iMCHROF].getFirstIdx(); iDigit <= mchROFs[iMCHROF].getLastIdx(); ++iDigit) {
93+
const auto& digit = digits[iDigit];
94+
auto digitLoc = mDigitLoc.emplace(((digit.getDetID() << 16) | digit.getPadID()), mDigits.size());
95+
if (digitLoc.second) {
96+
mDigits.emplace_back(digit);
97+
if (labels != nullptr) {
98+
mLabels.addElements(digitLoc.first->second, labels->getLabels(iDigit));
99+
}
100+
} else {
101+
auto& digit0 = mDigits[digitLoc.first->second];
102+
digit0.setADC(digit0.getADC() + digit.getADC());
103+
digit0.setNofSamples(digit0.getNofSamples() + digit.getNofSamples());
104+
digit0.setSaturated(digit0.isSaturated() || digit.isSaturated());
105+
if (labels != nullptr) {
106+
for (const auto& label : labels->getLabels(iDigit)) {
107+
mLabels.addElementRandomAccess(digitLoc.first->second, label);
108+
}
109+
}
110+
}
111+
}
112+
}
113+
ir.setFromLong(event.first);
114+
mROFs.emplace_back(ir, digitOffset, mDigits.size() - digitOffset,
115+
event.second.trgRange[1] - param.triggerRange[1] - event.first + 1);
116+
}
117+
}
118+
119+
} // namespace mch
120+
} // namespace o2

0 commit comments

Comments
 (0)