diff --git a/src/global/CMakeLists.txt b/src/global/CMakeLists.txt index 4d12e01fc8..72ad0cea07 100644 --- a/src/global/CMakeLists.txt +++ b/src/global/CMakeLists.txt @@ -5,3 +5,4 @@ add_subdirectory(reco) add_subdirectory(pid) add_subdirectory(pid_lut) add_subdirectory(beam) +add_subdirectory(splitting) diff --git a/src/global/splitting/CMakeLists.txt b/src/global/splitting/CMakeLists.txt new file mode 100644 index 0000000000..55aed9ba3f --- /dev/null +++ b/src/global/splitting/CMakeLists.txt @@ -0,0 +1,34 @@ +cmake_minimum_required(VERSION 3.16) + +get_filename_component(PLUGIN_NAME ${CMAKE_CURRENT_LIST_DIR} NAME) + +# Function creates ${PLUGIN_NAME}_plugin and ${PLUGIN_NAME}_library targets +# Setting default includes, libraries and installation paths +plugin_add(${PLUGIN_NAME} PLUGIN_USE_CC_ONLY) + +# The macro grabs sources as *.cc *.cpp *.c and headers as *.h *.hh *.hpp Then +# correctly sets sources for ${_name}_plugin and ${_name}_library targets Adds +# headers to the correct installation directory +plugin_glob_all(${PLUGIN_NAME}) + +# Find dependencies plugin_add_dd4hep(${PLUGIN_NAME}#) +# plugin_add_acts(${PLUGIN_NAME}) plugin_add_cern_root(${PLUGIN_NAME}) +plugin_add_event_model(${PLUGIN_NAME}) + +# Add include directories (works same as target_include_directories) +# plugin_include_directories(${PLUGIN_NAME} SYSTEM PUBLIC ... ) + +# Add libraries (same as target_include_directories but for both plugin and +# library) +plugin_link_libraries(${PLUGIN_NAME} algorithms_digi_library + algorithms_tracking_library) +# +# Add include directories (works same as target_include_directories) +# plugin_include_directories(${PLUGIN_NAME} PUBLIC ${CMAKE_CURRENT_LIST_DIR} +# SYSTEM PUBLIC ${podio_INCLUDE_DIR} ${EDM4HEP_INCLUDE_DIR} +# ${DD4hep_INCLUDE_DIRS} ${ROOT_INCLUDE_DIRS} ${EDM4EIC_INCLUDE_DIRS}) +# +# Add libraries (works same as target_include_directories) +# plugin_link_libraries(${PLUGIN_NAME} ${ROOT_LIBRARIES} +# algorithms_tracking_library EDM4HEP::edm4hep EDM4EIC::edm4eic spdlog::spdlog +# Boost::boost ${ROOT_EG_LIBRARY}) diff --git a/src/global/splitting/TimeframeSplitter.h b/src/global/splitting/TimeframeSplitter.h new file mode 100644 index 0000000000..5f82d00c46 --- /dev/null +++ b/src/global/splitting/TimeframeSplitter.h @@ -0,0 +1,44 @@ +// Copyright 2024, Jefferson Science Associates, LLC. +// Subject to the terms in the LICENSE file found in the top-level directory. + +#pragma once + +#include + +struct TimeframeSplitter : public JEventUnfolder { + + // PodioInput m_timeslice_clusters_in {this, {.name = "ts_protoclusters", .level = JEventLevel::Timeslice}}; + + // PodioOutput m_event_clusters_out {this, "evt_protoclusters"}; + // PodioOutput m_event_info_out {this, "evt_info"}; + + TimeframeSplitter() { + SetTypeName(NAME_OF_THIS); + SetParentLevel(JEventLevel::Timeslice); + SetChildLevel(JEventLevel::PhysicsEvent); + } + + + Result Unfold(const JEvent& parent, JEvent& child, int child_idx) override { + + auto timeslice_nr = parent.GetEventNumber(); + size_t event_nr = 100*timeslice_nr + child_idx; + child.SetEventNumber(event_nr); + + // For now, a one-to-one relationship between timeslices and events + + /* + auto event_clusters_out = std::make_unique(); + event_clusters_out->setSubsetCollection(true); + event_clusters_out->push_back(m_timeslice_clusters_in()->at(child_idx)); + + auto event_info_out = std::make_unique(); + event_info_out->push_back(MutableEventInfo(event_nr, timeslice_nr, 0)); + + m_event_clusters_out() = std::move(event_clusters_out); + m_event_info_out() = std::move(event_info_out); + */ + + return (child_idx == 2) ? Result::NextChildNextParent : Result::NextChildKeepParent; + } +}; diff --git a/src/global/splitting/splitting.cc b/src/global/splitting/splitting.cc new file mode 100644 index 0000000000..acce6b2440 --- /dev/null +++ b/src/global/splitting/splitting.cc @@ -0,0 +1,28 @@ +// Copyright 2024, Jefferson Science Associates, LLC. +// Subject to the terms in the LICENSE file found in the top-level directory. + + +#include "TimeframeSplitter.h" +#include + + +extern "C"{ +void InitPlugin(JApplication *app) { + + InitJANAPlugin(app); + + // Unfolder that takes timeframes and splits them into physics events. + app->Add(new TimeframeSplitter()); + + // Factory that produces timeslice-level protoclusters from timeslice-level hits + /* + app->Add(new JOmniFactoryGeneratorT( + { .tag = "timeslice_protoclusterizer", + .level = JEventLevel::Timeslice, + .input_names = {"hits"}, + .output_names = {"ts_protoclusters"} + })); + */ + +} +} // "C" diff --git a/src/services/io/podio/JEventSourcePODIO_generator.h b/src/services/io/podio/JEventSourcePODIO_generator.h new file mode 100644 index 0000000000..a6df6e762d --- /dev/null +++ b/src/services/io/podio/JEventSourcePODIO_generator.h @@ -0,0 +1,34 @@ + + +#include +#include "JEventSourcePODIO.h" + + +class JEventSourcePODIO_generator : public JEventSourceGenerator { + + JEventSource* MakeJEventSource(std::string resource_name) override { + + auto* source = new JEventSourcePODIO(resource_name, nullptr); + source->SetResourceName(resource_name); + + // Check if the string "timeslices" appears anywhere in our filename. + // If so, we assume the file contains timeslices, otherwise it contains physics events. + // Another approach might be to peek at the file's contents + if (resource_name.find("timeslices") != std::string::npos) { + source->SetLevel(JEventLevel::Timeslice); + } + else { + source->SetLevel(JEventLevel::PhysicsEvent); + } + return source; + } + + double CheckOpenable(std::string resource_name) override { + // In theory, we should check whether PODIO can open the file and + // whether it contains an 'events' or 'timeslices' tree. If not, return 0. + if (resource_name.find(".root") != std::string::npos) { + return 0.01; + } + return 0; + } +}; diff --git a/src/services/io/podio/podio.cc b/src/services/io/podio/podio.cc index 829527f104..d60b03781a 100644 --- a/src/services/io/podio/podio.cc +++ b/src/services/io/podio/podio.cc @@ -4,17 +4,16 @@ // #include -#include #include "JEventProcessorPODIO.h" -#include "JEventSourcePODIO.h" +#include "JEventSourcePODIO_generator.h" // Make this a JANA plugin extern "C" { void InitPlugin(JApplication *app) { InitJANAPlugin(app); - app->Add(new JEventSourceGeneratorT()); + app->Add(new JEventSourcePODIO_generator); // Disable this behavior for now so one can run eicrecon with only the // input file as an argument. diff --git a/src/utilities/eicrecon/eicrecon.cc b/src/utilities/eicrecon/eicrecon.cc index e8c75c6948..7783007464 100644 --- a/src/utilities/eicrecon/eicrecon.cc +++ b/src/utilities/eicrecon/eicrecon.cc @@ -49,6 +49,7 @@ std::vector EICRECON_DEFAULT_PLUGINS = { "LUMISPECCAL", "podio", "janatop", + "splitter" }; int main( int narg, char **argv)