Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-07-06 07:55:53

0001 
0002 #include "JEventProcessorPODIO.h"
0003 
0004 #include <JANA/JApplication.h>
0005 #include <JANA/JApplicationFwd.h>
0006 #include <JANA/Services/JParameterManager.h>
0007 #include <JANA/Utils/JTypeInfo.h>
0008 #include <edm4eic/EDM4eicVersion.h>
0009 #include <fmt/core.h>
0010 #include <podio/CollectionBase.h>
0011 #include <podio/Frame.h>
0012 #include <podio/ROOTWriter.h>
0013 #include <exception>
0014 #include <ostream>
0015 #include <stdexcept>
0016 
0017 #include "services/log/Log_service.h"
0018 
0019 JEventProcessorPODIO::JEventProcessorPODIO() {
0020   SetTypeName(NAME_OF_THIS); // Provide JANA with this class's name
0021 
0022   japp->SetDefaultParameter("podio:output_file", m_output_file,
0023                             "Name of EDM4hep/podio output file to write to. Setting this will "
0024                             "cause the output file to be created and written to.");
0025 
0026   // Allow user to set PODIO:OUTPUT_FILE to "1" to specify using the default name.
0027   if (m_output_file == "1") {
0028     auto* param = japp->GetJParameterManager()->FindParameter("podio:output_file");
0029     if (param != nullptr) {
0030       param->SetValue(param->GetDefault());
0031       m_output_file = param->GetDefault();
0032     }
0033   }
0034 
0035   // Get the output directory path for creating a second copy of the output file at the end of processing.
0036   // (this is duplicating similar functionality in Juggler/Gaudi so assume it is useful).
0037   japp->SetDefaultParameter("podio:output_file_copy_dir", m_output_file_copy_dir,
0038                             "Directory name to make an additional copy of the output file to. Copy "
0039                             "will be done at end of processing. Default is empty string which "
0040                             "means do not make a copy. No check is made on path existing.");
0041 
0042   // Get the list of output collections to include/exclude
0043   std::vector<std::string> output_collections = {
0044     // Header and other metadata
0045     "EventHeader",
0046 
0047     // Truth record
0048     "MCParticles",
0049     "MCBeamElectrons",
0050     "MCBeamProtons",
0051     "MCScatteredElectrons",
0052     "MCScatteredProtons",
0053     "MCParticlesHeadOnFrameNoBeamFX",
0054 
0055     // Central tracking hits combined
0056     "CentralTrackerTruthSeeds",
0057     "CentralTrackingRecHits",
0058     "CentralTrackingRawHitAssociations",
0059     "CentralTrackSeedingResults",
0060     "CentralTrackerMeasurements",
0061 
0062     // Si tracker hits
0063     "SiBarrelTrackerRecHits",
0064     "SiBarrelVertexRecHits",
0065     "SiEndcapTrackerRecHits",
0066 
0067     "SiBarrelRawHits",
0068     "SiBarrelVertexRawHits",
0069     "SiEndcapTrackerRawHits",
0070 
0071     "SiBarrelHits",
0072     "VertexBarrelHits",
0073     "TrackerEndcapHits",
0074 
0075     "SiBarrelRawHitAssociations",
0076     "SiBarrelVertexRawHitAssociations",
0077     "SiEndcapTrackerRawHitAssociations",
0078 
0079     // TOF
0080     "TOFBarrelRecHits",
0081     "TOFEndcapRecHits",
0082 
0083     "TOFBarrelRawHits",
0084     "TOFEndcapRawHits",
0085 
0086     "TOFBarrelHits",
0087     "TOFBarrelADCTDC",
0088     "TOFEndcapHits",
0089 
0090     "TOFBarrelRawHitAssociations",
0091     "TOFEndcapRawHitAssociations",
0092 
0093     "CombinedTOFTruthSeededParticleIDs",
0094     "CombinedTOFParticleIDs",
0095 
0096     // DRICH
0097     "DRICHRawHits",
0098     "DRICHRawHitsAssociations",
0099     "DRICHAerogelTracks",
0100     "DRICHGasTracks",
0101     "DRICHAerogelIrtCherenkovParticleID",
0102     "DRICHGasIrtCherenkovParticleID",
0103     "DRICHTruthSeededParticleIDs",
0104     "DRICHParticleIDs",
0105 
0106     // PFRICH
0107     "RICHEndcapNRawHits",
0108     "RICHEndcapNRawHitsAssociations",
0109     "RICHEndcapNTruthSeededParticleIDs",
0110     "RICHEndcapNParticleIDs",
0111 
0112     // MPGD
0113     "MPGDBarrelRecHits",
0114     "OuterMPGDBarrelRecHits",
0115     "BackwardMPGDEndcapRecHits",
0116     "ForwardMPGDEndcapRecHits",
0117 
0118     "MPGDBarrelRawHits",
0119     "OuterMPGDBarrelRawHits",
0120     "BackwardMPGDEndcapRawHits",
0121     "ForwardMPGDEndcapRawHits",
0122 
0123     "MPGDBarrelHits",
0124     "OuterMPGDBarrelHits",
0125     "BackwardMPGDEndcapHits",
0126     "ForwardMPGDEndcapHits",
0127 
0128     "MPGDBarrelRawHitAssociations",
0129     "OuterMPGDBarrelRawHitAssociations",
0130     "BackwardMPGDEndcapRawHitAssociations",
0131     "ForwardMPGDEndcapRawHitAssociations",
0132 
0133     // LOWQ2 hits
0134     "TaggerTrackerHits",
0135     "TaggerTrackerSharedHits",
0136     "TaggerTrackerHitPulses",
0137     "TaggerTrackerCombinedPulses",
0138     "TaggerTrackerCombinedPulsesWithNoise",
0139     "TaggerTrackerRawHits",
0140     "TaggerTrackerRawHitAssociations",
0141     "TaggerTrackerM1L0ClusterPositions",
0142     "TaggerTrackerM1L1ClusterPositions",
0143     "TaggerTrackerM1L2ClusterPositions",
0144     "TaggerTrackerM1L3ClusterPositions",
0145     "TaggerTrackerM2L0ClusterPositions",
0146     "TaggerTrackerM2L1ClusterPositions",
0147     "TaggerTrackerM2L2ClusterPositions",
0148     "TaggerTrackerM2L3ClusterPositions",
0149     "TaggerTrackerM1LocalTracks",
0150     "TaggerTrackerM2LocalTracks",
0151     "TaggerTrackerM1LocalTrackAssociations",
0152     "TaggerTrackerM2LocalTrackAssociations",
0153     "TaggerTrackerLocalTracks",
0154     "TaggerTrackerLocalTrackAssociations",
0155     "TaggerTrackerProjectedTracks",
0156     "TaggerTrackerTracks",
0157     "TaggerTrackerTrajectories",
0158     "TaggerTrackerTrackParameters",
0159     "TaggerTrackerTrackAssociations",
0160     "TaggerTrackerReconstructedParticles",
0161 
0162     // Forward & Far forward hits
0163     "B0TrackerTruthSeeds",
0164     "B0TrackerRecHits",
0165     "B0TrackerRawHits",
0166     "B0TrackerHits",
0167     "B0TrackerRawHitAssociations",
0168     "B0TrackerSeedingResults",
0169     "B0TrackerMeasurements",
0170 
0171     "ForwardRomanPotRecHits",
0172     "ForwardOffMTrackerRecHits",
0173 
0174     "ForwardRomanPotRecParticles",
0175     "ForwardOffMRecParticles",
0176 
0177     "ForwardRomanPotRawHits",
0178     "ForwardRomanPotRawHitAssociations",
0179     "ForwardOffMTrackerRawHits",
0180     "ForwardOffMTrackerRawHitAssociations",
0181 
0182     // Reconstructed data
0183     "GeneratedParticles",
0184     "GeneratedBreitFrameParticles",
0185     "ReconstructedParticles",
0186     "ReconstructedParticleAssociations",
0187     "ReconstructedTruthSeededChargedParticles",
0188     "ReconstructedTruthSeededChargedParticleAssociations",
0189     "ReconstructedChargedRealPIDParticles",
0190     "ReconstructedChargedRealPIDParticleIDs",
0191     "ReconstructedChargedParticles",
0192     "ReconstructedChargedParticleAssociations",
0193     "MCScatteredElectronAssociations",    // Remove if/when used internally
0194     "MCNonScatteredElectronAssociations", // Remove if/when used internally
0195     "ReconstructedBreitFrameParticles",
0196 
0197     // Central tracking
0198     "CentralTrackSegments",
0199     "CentralTrackVertices",
0200     "CentralCKFTruthSeededTrajectories",
0201     "CentralCKFTruthSeededTracks",
0202     "CentralCKFTruthSeededTrackAssociations",
0203     "CentralCKFTruthSeededTrackParameters",
0204     "CentralCKFTrajectories",
0205     "CentralCKFTracks",
0206     "CentralCKFTrackAssociations",
0207     "CentralCKFTrackParameters",
0208     // tracking properties - true seeding
0209     "CentralCKFTruthSeededTrajectoriesUnfiltered",
0210     "CentralCKFTruthSeededTracksUnfiltered",
0211     "CentralCKFTruthSeededTrackUnfilteredAssociations",
0212     "CentralCKFTruthSeededTrackParametersUnfiltered",
0213     // tracking properties - realistic seeding
0214     "CentralCKFTrajectoriesUnfiltered",
0215     "CentralCKFTracksUnfiltered",
0216     "CentralCKFTrackUnfilteredAssociations",
0217     "CentralCKFTrackParametersUnfiltered",
0218 
0219     // B0 tracking
0220     "B0TrackerCKFTruthSeededTrajectories",
0221     "B0TrackerCKFTruthSeededTracks",
0222     "B0TrackerCKFTruthSeededTrackAssociations",
0223     "B0TrackerCKFTruthSeededTrackParameters",
0224     "B0TrackerCKFTrajectories",
0225     "B0TrackerCKFTracks",
0226     "B0TrackerCKFTrackAssociations",
0227     "B0TrackerCKFTrackParameters",
0228     // tracking properties - true seeding
0229     "B0TrackerCKFTruthSeededTrajectoriesUnfiltered",
0230     "B0TrackerCKFTruthSeededTracksUnfiltered",
0231     "B0TrackerCKFTruthSeededTrackUnfilteredAssociations",
0232     "B0TrackerCKFTruthSeededTrackParametersUnfiltered",
0233     // tracking properties - realistic seeding
0234     "B0TrackerCKFTrajectoriesUnfiltered",
0235     "B0TrackerCKFTrackParametersUnfiltered",
0236     "B0TrackerCKFTracksUnfiltered",
0237     "B0TrackerCKFTrackUnfilteredAssociations",
0238 
0239     "CentralAndB0TrackVertices",
0240 
0241     // Inclusive kinematics
0242     "InclusiveKinematicsDA",
0243     "InclusiveKinematicsJB",
0244     "InclusiveKinematicsML",
0245     "InclusiveKinematicsSigma",
0246     "InclusiveKinematicseSigma", // Deprecated, use ESigma
0247     "InclusiveKinematicsESigma",
0248     "InclusiveKinematicsElectron",
0249     "InclusiveKinematicsTruth",
0250     "GeneratedJets",
0251     "GeneratedChargedJets",
0252     "GeneratedCentauroJets",
0253     "ReconstructedJets",
0254     "ReconstructedChargedJets",
0255     "ReconstructedCentauroJets",
0256     "ReconstructedElectrons",
0257     "ScatteredElectronsTruth",
0258     "ScatteredElectronsEMinusPz",
0259     "PrimaryVertices",
0260     "BarrelClusters",
0261 #if EDM4EIC_VERSION_MAJOR >= 6
0262     "HadronicFinalState",
0263 #endif
0264 
0265     // Track projections
0266     "CalorimeterTrackProjections",
0267 
0268     // Ecal stuff
0269     "EcalEndcapNRawHits",
0270     "EcalEndcapNRecHits",
0271     "EcalEndcapNTruthClusters",
0272     "EcalEndcapNTruthClusterAssociations",
0273     "EcalEndcapNClusters",
0274     "EcalEndcapNClusterAssociations",
0275     "EcalEndcapNSplitMergeClusters",
0276     "EcalEndcapNSplitMergeClusterAssociations",
0277     "EcalEndcapPRawHits",
0278     "EcalEndcapPRecHits",
0279     "EcalEndcapPTruthClusters",
0280     "EcalEndcapPTruthClusterAssociations",
0281     "EcalEndcapPClusters",
0282     "EcalEndcapPClusterAssociations",
0283     "EcalEndcapPSplitMergeClusters",
0284     "EcalEndcapPSplitMergeClusterAssociations",
0285     "EcalBarrelClusters",
0286     "EcalBarrelClusterAssociations",
0287     "EcalBarrelTruthClusters",
0288     "EcalBarrelTruthClusterAssociations",
0289     "EcalBarrelImagingRawHits",
0290     "EcalBarrelImagingRecHits",
0291     "EcalBarrelImagingClusters",
0292     "EcalBarrelImagingClusterAssociations",
0293     "EcalBarrelScFiPAttenuatedHits",
0294     "EcalBarrelScFiPAttenuatedHitContributions",
0295     "EcalBarrelScFiNAttenuatedHits",
0296     "EcalBarrelScFiNAttenuatedHitContributions",
0297     "EcalBarrelScFiRawHits",
0298     "EcalBarrelScFiRecHits",
0299     "EcalBarrelScFiClusters",
0300     "EcalBarrelScFiClusterAssociations",
0301     "EcalLumiSpecRawHits",
0302     "EcalLumiSpecRecHits",
0303     "EcalLumiSpecTruthClusters",
0304     "EcalLumiSpecTruthClusterAssociations",
0305     "EcalLumiSpecClusters",
0306     "EcalLumiSpecClusterAssociations",
0307     "HcalEndcapNRawHits",
0308     "HcalEndcapNRecHits",
0309     "HcalEndcapNMergedHits",
0310     "HcalEndcapNClusters",
0311     "HcalEndcapNClusterAssociations",
0312     "HcalEndcapNSplitMergeClusters",
0313     "HcalEndcapNSplitMergeClusterAssociations",
0314     "HcalEndcapPInsertRawHits",
0315     "HcalEndcapPInsertRecHits",
0316     "HcalEndcapPInsertMergedHits",
0317     "HcalEndcapPInsertClusters",
0318     "HcalEndcapPInsertClusterAssociations",
0319     "LFHCALRawHits",
0320     "LFHCALRecHits",
0321     "LFHCALClusters",
0322     "LFHCALClusterAssociations",
0323     "LFHCALSplitMergeClusters",
0324     "LFHCALSplitMergeClusterAssociations",
0325     "HcalBarrelRawHits",
0326     "HcalBarrelRecHits",
0327     "HcalBarrelMergedHits",
0328     "HcalBarrelClusters",
0329     "HcalBarrelClusterAssociations",
0330     "HcalBarrelSplitMergeClusters",
0331     "HcalBarrelSplitMergeClusterAssociations",
0332     "B0ECalRawHits",
0333     "B0ECalRecHits",
0334     "B0ECalClusters",
0335     "B0ECalClusterAssociations",
0336     "HcalEndcapNTruthClusters",
0337     "HcalEndcapNTruthClusterAssociations",
0338     "HcalBarrelTruthClusters",
0339     "HcalBarrelTruthClusterAssociations",
0340 
0341     //ZDC Ecal
0342     "EcalFarForwardZDCRawHits",
0343     "EcalFarForwardZDCRecHits",
0344     "EcalFarForwardZDCClusters",
0345     "EcalFarForwardZDCClusterAssociations",
0346     "EcalFarForwardZDCTruthClusters",
0347     "EcalFarForwardZDCTruthClusterAssociations",
0348 
0349     //ZDC HCal
0350     "HcalFarForwardZDCRawHits",
0351     "HcalFarForwardZDCRecHits",
0352     "HcalFarForwardZDCSubcellHits",
0353     "HcalFarForwardZDCClusters",
0354     "HcalFarForwardZDCClusterAssociations",
0355     "HcalFarForwardZDCClustersBaseline",
0356     "HcalFarForwardZDCClusterAssociationsBaseline",
0357     "HcalFarForwardZDCTruthClusters",
0358     "HcalFarForwardZDCTruthClusterAssociations",
0359     "ReconstructedFarForwardZDCNeutrals",
0360     "ReconstructedFarForwardZDCLambdas",
0361     "ReconstructedFarForwardZDCLambdaDecayProductsCM",
0362 
0363     // DIRC
0364     "DIRCRawHits",
0365     "DIRCTruthSeededParticleIDs",
0366     "DIRCParticleIDs",
0367 
0368 #if EDM4EIC_VERSION_MAJOR >= 7
0369     "B0ECalRawHitAssociations",
0370     "EcalBarrelScFiRawHitAssociations",
0371     "EcalBarrelImagingRawHitAssociations",
0372     "HcalBarrelRawHitAssociations",
0373     "EcalEndcapNRawHitAssociations",
0374     "HcalEndcapNRawHitAssociations",
0375     "EcalEndcapPRawHitAssociations",
0376     "HcalEndcapPInsertRawHitAssociations",
0377     "LFHCALRawHitAssociations",
0378     "EcalLumiSpecRawHitAssociations",
0379     "EcalFarForwardZDCRawHitAssociations",
0380     "HcalFarForwardZDCRawHitAssociations",
0381 #endif
0382 #if EDM4EIC_VERSION_MAJOR >= 8
0383     "EcalEndcapPTrackClusterMatches",
0384     "LFHCALTrackClusterMatches",
0385     "HcalEndcapPInsertClusterMatches",
0386     "EcalBarrelTrackClusterMatches",
0387     "HcalBarrelTrackClusterMatches",
0388     "EcalEndcapNTrackClusterMatches",
0389     "HcalEndcapNTrackClusterMatches",
0390 #endif
0391 
0392   };
0393   std::vector<std::string> output_exclude_collections; // need to get as vector, then convert to set
0394   std::string output_include_collections = "DEPRECATED";
0395   japp->SetDefaultParameter("podio:output_include_collections", output_include_collections,
0396                             "DEPRECATED. Use podio:output_collections instead.");
0397   if (output_include_collections != "DEPRECATED") {
0398     output_collections.clear();
0399     JParameterManager::Parse(output_include_collections, output_collections);
0400     m_output_include_collections_set = true;
0401   }
0402   japp->SetDefaultParameter(
0403       "podio:output_collections", output_collections,
0404       "Comma separated list of collection names to write out. If not set, all collections will be "
0405       "written (including ones from input file). Don't set this and use "
0406       "PODIO:OUTPUT_EXCLUDE_COLLECTIONS to write everything except a selection.");
0407   japp->SetDefaultParameter("podio:output_exclude_collections", output_exclude_collections,
0408                             "Comma separated list of collection names to not write out.");
0409   japp->SetDefaultParameter(
0410       "podio:print_collections", m_collections_to_print,
0411       "Comma separated list of collection names to print to screen, e.g. for debugging.");
0412 
0413   m_output_collections =
0414       std::set<std::string>(output_collections.begin(), output_collections.end());
0415   m_output_exclude_collections =
0416       std::set<std::string>(output_exclude_collections.begin(), output_exclude_collections.end());
0417 }
0418 
0419 void JEventProcessorPODIO::Init() {
0420 
0421   auto* app = GetApplication();
0422   m_log     = app->GetService<Log_service>()->logger("JEventProcessorPODIO");
0423   m_writer  = std::make_unique<podio::ROOTWriter>(m_output_file);
0424   // TODO: NWB: Verify that output file is writable NOW, rather than after event processing completes.
0425   //       I definitely don't trust PODIO to do this for me.
0426 
0427   if (m_output_include_collections_set) {
0428     m_log->error("The podio:output_include_collections was provided, but is deprecated. Use "
0429                  "podio:output_collections instead.");
0430     throw std::runtime_error("The podio:output_include_collections was provided, but is "
0431                              "deprecated. Use podio:output_collections instead.");
0432   }
0433 }
0434 
0435 void JEventProcessorPODIO::FindCollectionsToWrite(const std::shared_ptr<const JEvent>& event) {
0436 
0437   // Set up the set of collections_to_write.
0438   std::vector<std::string> all_collections = event->GetAllCollectionNames();
0439 
0440   if (m_output_collections.empty()) {
0441     // User has not specified an include list, so we include _all_ PODIO collections present in the first event.
0442     for (const std::string& col : all_collections) {
0443       if (m_output_exclude_collections.find(col) == m_output_exclude_collections.end()) {
0444         m_collections_to_write.push_back(col);
0445         m_log->info("Persisting collection '{}'", col);
0446       }
0447     }
0448   } else {
0449     m_log->debug("Persisting podio types from includes list");
0450 
0451     // We match up the include list with what is actually present in the event
0452     std::set<std::string> all_collections_set =
0453         std::set<std::string>(all_collections.begin(), all_collections.end());
0454 
0455     for (const auto& col : m_output_collections) {
0456       if (m_output_exclude_collections.find(col) == m_output_exclude_collections.end()) {
0457         // Included and not excluded
0458         if (all_collections_set.find(col) == all_collections_set.end()) {
0459           // Included, but not a valid PODIO type
0460           m_log->warn("Explicitly included collection '{}' not present in factory set, omitting.",
0461                       col);
0462         } else {
0463           // Included, not excluded, and a valid PODIO type
0464           m_collections_to_write.push_back(col);
0465           m_log->info("Persisting collection '{}'", col);
0466         }
0467       }
0468     }
0469   }
0470 }
0471 
0472 void JEventProcessorPODIO::Process(const std::shared_ptr<const JEvent>& event) {
0473 
0474   // Find all collections to write from the first event
0475   std::call_once(m_is_first_event, &JEventProcessorPODIO::FindCollectionsToWrite, this, event);
0476 
0477   // Print the contents of some collections, just for debugging purposes
0478   // Do this before writing just in case writing crashes
0479   if (!m_collections_to_print.empty()) {
0480     m_log->info("========================================");
0481     m_log->info("JEventProcessorPODIO: Event {}", event->GetEventNumber());
0482     ;
0483   }
0484   for (const auto& coll_name : m_collections_to_print) {
0485     m_log->info("------------------------------");
0486     m_log->info("{}", coll_name);
0487     try {
0488       const auto* coll_ptr = event->GetCollectionBase(coll_name);
0489       if (coll_ptr == nullptr) {
0490         m_log->info("missing");
0491       } else {
0492         std::stringstream ss;
0493         coll_ptr->print(ss);
0494         m_log->info(ss.str());
0495       }
0496     } catch (std::exception& e) {
0497       m_log->info("missing");
0498     }
0499   }
0500 
0501   m_log->trace("==================================");
0502   m_log->trace("Event #{}", event->GetEventNumber());
0503 
0504   // Make sure that all factories get called that need to be written into the frame.
0505   // We need to do this for _all_ factories unless we've constrained it by using includes/excludes.
0506   // Note that all collections need to be present in the first event, as podio::RootFrameWriter constrains us to write one event at a time, so there
0507   // is no way to add a new branch after the first event.
0508 
0509   // If we get an exception below while trying to add a factory for any
0510   // reason then mark that factory as bad and don't try running it again.
0511   // This is motivated by trying to write EcalBarrelSciGlass objects for
0512   // data simulated using the imaging calorimeter. In that case, it will
0513   // always throw an exception, but DD4hep also prints its own error message.
0514   // Thus, to prevent that error message every event, we must avoid calling
0515   // it.
0516 
0517   // Activate factories.
0518   std::vector<std::string> successful_collections;
0519   std::set<std::string> failed_collections;
0520   for (const std::string& coll : m_collections_to_write) {
0521     try {
0522       m_log->trace("Ensuring factory for collection '{}' has been called.", coll);
0523       const auto* coll_ptr = event->GetCollectionBase(coll);
0524       if (coll_ptr == nullptr) {
0525         // If a collection is missing from the frame, the podio root writer will segfault.
0526         // To avoid this, we treat this as a failing collection and omit from this point onwards.
0527         // However, this code path is expected to be unreachable because any missing collection will be
0528         // replaced with an empty collection in JFactoryPodioTFixed::Create.
0529         if (!failed_collections.contains(coll)) {
0530           m_log->error("Omitting PODIO collection '{}' because it is null", coll);
0531           failed_collections.insert(coll);
0532         }
0533       } else {
0534         m_log->trace("Including PODIO collection '{}'", coll);
0535         successful_collections.push_back(coll);
0536       }
0537     } catch (std::exception& e) {
0538       // Limit printing warning to just once per factory
0539       if (!failed_collections.contains(coll)) {
0540         m_log->error("Omitting PODIO collection '{}' due to exception: {}.", coll, e.what());
0541         failed_collections.insert(coll);
0542       }
0543     }
0544   }
0545 
0546   // Frame will contain data from all Podio factories that have been triggered,
0547   // including by the `event->GetCollectionBase(coll);` above.
0548   // Note that collections MUST be present in frame. If a collection is null, the writer will segfault.
0549   const auto* frame = event->GetSingle<podio::Frame>();
0550   {
0551     std::lock_guard<std::mutex> lock(m_mutex);
0552     m_writer->writeFrame(*frame, "events", m_collections_to_write);
0553   }
0554 }
0555 
0556 void JEventProcessorPODIO::Finish() {
0557   if (m_output_include_collections_set) {
0558     m_log->error("The podio:output_include_collections was provided, but is deprecated. Use "
0559                  "podio:output_collections instead.");
0560     throw std::runtime_error("The podio:output_include_collections was provided, but is "
0561                              "deprecated. Use podio:output_collections instead.");
0562   }
0563 
0564   m_writer->finish();
0565 }