Skip to content

Commit 880b57a

Browse files
tmadlenerm-fila
andauthored
Make sure that reading of LCIO events stops early enough (#210)
* Make sure that spuriously missing ParticleID info fails CI * Make the LcioEventAlgo stop the run before running out of events Effectively stop the run when processing the last event even if it is at the beginning of the event loop. Also make it throw a proper exception to immediately abort when the reading fails. * Add a warning output for potential issues * Add some documentation about the current limitation --------- Co-authored-by: Mateusz Jakub Fila <37295697+m-fila@users.noreply.github.com>
1 parent d27c9e6 commit 880b57a

File tree

5 files changed

+59
-45
lines changed

5 files changed

+59
-45
lines changed

doc/MarlinWrapperIntroduction.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,3 +220,25 @@ collection in the process, you would configure the tool like so
220220
lcio2edm4hepConv = Lcio2EDM4hepTool("Lcio2EDM4hep")
221221
lcio2edm4hepConv.collNameMapping = {"MCParticle": "MCParticles"}
222222
```
223+
224+
## Potential pitfalls when using other Gaudi Algorithms
225+
226+
Although mixing wrapped Marlin Processors with other Gaudi Algorithms is working
227+
for most cases, there are a few conceptual differences that have not yet been
228+
completely mapped. This might lead to unexpected or different results when
229+
running in Gaudi vs. running the same processors via Marlin (as far as
230+
possible). This list aims to collect them and where possible also tries to point
231+
out ways to work around them.
232+
233+
- In Marlin processors can use a `marlin::SkipEventException` to skip the
234+
processing of the rest of the event.
235+
- In Marlin a `marlin::StopProcessingException` will immediately stop the
236+
processing of the event loop. However, in Gaudi the current event will still
237+
finish processing.
238+
239+
For the `MarlinProcessorWrapper` algorithm we have put in checks and effectively
240+
skip the execution of the actual wrapped processor in these cases. However,
241+
other Gaudi algorithms will not have this check. Hence, execution chains that
242+
**only consist of wrapped Marlin processors will work as expected** here.
243+
However, **mixed chains will most likely not work as expected** (e.g. algorithms
244+
will not find expected inputs, etc.).

k4MarlinWrapper/examples/clicRec_e4h_input.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2433,7 +2433,7 @@
24332433
from Configurables import PodioOutput
24342434

24352435
out = PodioOutput("PodioOutput", filename="my_output.root")
2436-
out.outputCommands = ["keep *"]
2436+
out.outputCommands = ["keep *", "drop RefinedVertexJets_PID_RefinedVertex"]
24372437

24382438

24392439
algList.append(inp)

k4MarlinWrapper/k4MarlinWrapper/LcioEventAlgo.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ class LcioEvent : public Gaudi::Algorithm {
4141
private:
4242
Gaudi::Property<std::vector<std::string>> m_fileNames{this, "Files", {}};
4343
MT::LCReader* m_reader = nullptr;
44+
int m_numberOfEvents{};
45+
mutable int m_currentEvent{}; // No atomicity necessary since not re-entrant
4446
bool isReEntrant() const final { return false; }
4547
};
4648

k4MarlinWrapper/src/components/LcioEventAlgo.cpp

Lines changed: 30 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -16,19 +16,18 @@
1616
* See the License for the specific language governing permissions and
1717
* limitations under the License.
1818
*/
19-
20-
#include <GaudiKernel/IEventProcessor.h>
21-
22-
#include "k4MarlinWrapper/LCEventWrapper.h"
2319
#include "k4MarlinWrapper/LcioEventAlgo.h"
20+
#include "k4MarlinWrapper/LCEventWrapper.h"
2421

2522
#include "marlin/Global.h"
2623
#include "marlin/StringParameters.h"
2724

2825
#include <EVENT/LCIO.h>
2926
#include <MT/LCReader.h>
3027

31-
#include <memory>
28+
#include <GaudiKernel/IEventProcessor.h>
29+
30+
#include <stdexcept>
3231
#include <string>
3332

3433
DECLARE_COMPONENT(LcioEvent)
@@ -44,54 +43,42 @@ StatusCode LcioEvent::initialize() {
4443

4544
m_reader = new MT::LCReader(0);
4645
m_reader->open(m_fileNames);
47-
info() << "Initialized the LcioEvent Algo: " << m_fileNames[0] << endmsg;
46+
m_numberOfEvents = m_reader->getNumberOfEvents();
47+
info() << "Initialized the LcioEvent Algo. Reading from " << m_fileNames.size() << " with " << m_numberOfEvents
48+
<< " events in total." << endmsg;
4849
return StatusCode::SUCCESS;
4950
}
5051

5152
StatusCode LcioEvent::execute(const EventContext&) const {
53+
debug() << "Reading event " << ++m_currentEvent << " / " << m_numberOfEvents << endmsg;
5254
auto theEvent = m_reader->readNextEvent(EVENT::LCIO::UPDATE);
5355

54-
if (!theEvent) {
55-
// Store flag to indicate there was NOT a LCEvent
56-
auto pStatus = std::make_unique<LCEventWrapperStatus>(false);
57-
const StatusCode scStatus = eventSvc()->registerObject("/Event/LCEventStatus", pStatus.release());
58-
if (scStatus.isFailure()) {
59-
error() << "Failed to store flag for underlying LCEvent: MarlinProcessorWrapper may try to run over non existing "
60-
"event"
61-
<< endmsg;
62-
return scStatus;
63-
}
56+
if (theEvent == nullptr) {
57+
fatal() << "Failed to read event " << m_currentEvent << endmsg;
58+
throw std::runtime_error("LCEvent could not be read");
59+
}
6460

65-
auto svc = service<IEventProcessor>("ApplicationMgr");
66-
if (svc) {
67-
svc->stopRun().ignore();
68-
svc->release();
69-
} else {
70-
abort();
61+
// Since this is presumably the first algorithm to run we have to check here
62+
// to see if we need to stop the run. Events in flight will still be
63+
// processed, so technically this signals that we want to end the run after
64+
// all of the algorithms for this event have finished.
65+
if (m_currentEvent >= m_numberOfEvents) {
66+
info() << "This is the last event in the input files. Stopping the run" << endmsg;
67+
auto evtProcService = service<IEventProcessor>("ApplicationMgr", false);
68+
if (!evtProcService) {
69+
fatal() << "Could not get the ApplicationMgr for stopping the run" << endmsg;
7170
}
72-
} else {
73-
// pass theEvent to the DataStore, so we can access them in our processor
74-
// wrappers
75-
info() << "Reading from file: " << m_fileNames[0] << endmsg;
76-
77-
auto myEvWr = new LCEventWrapper(std::move(theEvent));
78-
const StatusCode sc = eventSvc()->registerObject("/Event/LCEvent", myEvWr);
79-
if (sc.isFailure()) {
80-
error() << "Failed to store the LCEvent" << endmsg;
81-
return sc;
82-
} else {
83-
// Store flag to indicate there was a LCEvent
84-
auto pStatus = std::make_unique<LCEventWrapperStatus>(true);
85-
std::cout << "Saving status: " << pStatus->hasLCEvent << std::endl;
86-
const StatusCode scStatus = eventSvc()->registerObject("/Event/LCEventStatus", pStatus.release());
87-
if (scStatus.isFailure()) {
88-
error() << "Failed to store flag for underlying LCEvent: MarlinProcessorWrapper may try to run over non "
89-
"existing event"
90-
<< endmsg;
91-
return scStatus;
92-
}
71+
if (evtProcService->stopRun().isFailure()) {
72+
error() << "Out of events, but could not signal to stop the run" << endmsg;
9373
}
9474
}
9575

76+
auto myEvWr = new LCEventWrapper(std::move(theEvent));
77+
const StatusCode sc = eventSvc()->registerObject("/Event/LCEvent", myEvWr);
78+
if (sc.isFailure()) {
79+
error() << "Failed to store the LCEvent" << endmsg;
80+
return sc;
81+
}
82+
9683
return StatusCode::SUCCESS;
9784
}

k4MarlinWrapper/src/components/MarlinProcessorWrapper.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,7 @@ StatusCode MarlinProcessorWrapper::initialize() {
214214
}
215215

216216
StatusCode MarlinProcessorWrapper::execute(const EventContext&) const {
217-
// Get flag to know if there was an underlying LCEvent
217+
// Get flag to check if this processor should be skipped or not
218218
DataObject* pStatus = nullptr;
219219
StatusCode scStatus = eventSvc()->retrieveObject("/Event/LCEventStatus", pStatus);
220220
if (scStatus.isSuccess()) {
@@ -279,6 +279,9 @@ StatusCode MarlinProcessorWrapper::execute(const EventContext&) const {
279279

280280
// Handle exceptions that may come from Marlin
281281
catch (marlin::SkipEventException& e) {
282+
warning() << "Caught marlin::SkipEventException. Skipping the wrapped Processors, but Gaudi Algorithms will still "
283+
"execute and may fail"
284+
<< endmsg;
282285
// Store flag to prevent the rest of the event from processing
283286
auto upStatus = std::make_unique<LCEventWrapperStatus>(false);
284287
const StatusCode code = eventSvc()->registerObject("/Event/LCEventStatus", upStatus.release());

0 commit comments

Comments
 (0)