Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rough cut of external wiring service #353

Merged
merged 12 commits into from
Sep 6, 2024
101 changes: 101 additions & 0 deletions cmake/AddJanaLibrary.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@

macro(add_jana_library library_name)

# Parse remaining arguments
set(options)
set(oneValueArgs EXPORT)
set(multiValueArgs SOURCES PUBLIC_HEADER TESTS)

cmake_parse_arguments(LIBRARY "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})

if (NOT LIBRARY_SOURCES AND NOT LIBRARY_PUBLIC_HEADER AND NOT LIBRARY_TESTS)
# If no arguments provided, glob everything
file(GLOB HEADERS_IN_SUBDIR "include/*")
file(GLOB SOURCES_IN_SUBDIR "src/*")
file(GLOB TESTS_IN_SUBDIR "test*/*")
file(GLOB HEADERS_IN_CWD "*.h*")
set(SOURCES_IN_CWD)
set(TESTS_IN_CWD)

file(GLOB ALL_SOURCES_IN_CWD "*.c*")
foreach(file IN LISTS ALL_SOURCES_IN_CWD)
string(TOLOWER "${file}" file_lower)
if(NOT file_lower MATCHES ".*/test[^/]*$|.*test$|.*tests$")
list(APPEND SOURCES_IN_CWD ${file})
else()
list(APPEND TESTS_IN_CWD ${file})
endif()
endforeach()

set(LIBRARY_SOURCES ${SOURCES_IN_CWD} ${SOURCES_IN_SUBDIR})
set(LIBRARY_PUBLIC_HEADER ${HEADERS_IN_CWD} ${HEADERS_IN_SUBDIR})
set(LIBRARY_TESTS ${TESTS_IN_CWD} ${TESTS_IN_SUBDIR})
message(STATUS "Plugin ${library_name}: found sources: ${LIBRARY_SOURCES}")
message(STATUS "Plugin ${library_name}: found headers: ${LIBRARY_PUBLIC_HEADER}")
message(STATUS "Plugin ${library_name}: found tests: ${LIBRARY_TESTS}")
endif()

if (${PROJECT_NAME} STREQUAL "jana2")
# This is an internal plugin
set(INSTALL_NAMESPACE "JANA")
set(JANA_NAMESPACE "")
if (NOT LIBRARY_EXPORT)
set(LIBRARY_EXPORT "jana2_targets")
endif()
else()
# This is an external plugin
# Figure out install namespace, which _might_ be different than PROJECT_NAME
if (NOT DEFINED INSTALL_NAMESPACE)
set(INSTALL_NAMESPACE ${PROJECT_NAME} CACHE STRING "Project-specific namespace for installation paths, e.g. /lib/PROJECT_NAMESPACE/plugins")
endif()
set(JANA_NAMESPACE "JANA::")
endif()

# Set up target
add_library(${library_name} SHARED ${LIBRARY_SOURCES})

set_target_properties(${library_name} PROPERTIES
EXPORT_NAME ${library_name}
SKIP_BUILD_RPATH FALSE
BUILD_WITH_INSTALL_RPATH TRUE
INSTALL_RPATH_USE_LINK_PATH TRUE
INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib;${CMAKE_INSTALL_PREFIX}/lib/${INSTALL_NAMESPACE}/plugins"
)

target_link_libraries(${library_name} PUBLIC "${JANA_NAMESPACE}jana2_static_lib")

# Handle public headers
if (LIBRARY_PUBLIC_HEADER)
set_target_properties(${library_name} PROPERTIES
PUBLIC_HEADER "${LIBRARY_PUBLIC_HEADER}"
)
target_include_directories(${library_name}
PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
$<INSTALL_INTERFACE:include/${INSTALL_NAMESPACE}/plugins/${library_name}>
)
endif()

# Install target
install(TARGETS ${library_name}
EXPORT ${LIBRARY_EXPORT}
PUBLIC_HEADER DESTINATION include/${INSTALL_NAMESPACE}/plugins/${library_name}
LIBRARY DESTINATION lib/${INSTALL_NAMESPACE}/plugins
)

# Handle tests
if (LIBRARY_TESTS)
add_executable(${library_name}_tests ${LIBRARY_TESTS})
target_link_libraries(${library_name}_tests PRIVATE ${library_name} "${JANA_NAMESPACE}VendoredCatch2")
set_target_properties(${library_name}_tests PROPERTIES
SKIP_BUILD_RPATH FALSE
BUILD_WITH_INSTALL_RPATH TRUE
INSTALL_RPATH_USE_LINK_PATH TRUE
INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib;${CMAKE_INSTALL_PREFIX}/lib/${INSTALL_NAMESPACE}/plugins"
)
#install(TARGETS ${library_name}_tests RUNTIME DESTINATION bin)
add_test(NAME ${library_name}_tests COMMAND ${library_name}_tests)
endif()
endmacro()


1 change: 1 addition & 0 deletions src/examples/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ add_subdirectory(UnitTestingExample)
add_subdirectory(PodioDatamodel)
add_subdirectory(PodioFileReader)
add_subdirectory(PodioFileWriter)
add_subdirectory(PodioFactories)
add_subdirectory(PodioExample)
add_subdirectory(TimesliceExample)
add_subdirectory(RootDatamodelExample)
Expand Down
21 changes: 21 additions & 0 deletions src/examples/JObjectDatamodel/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@


# This is a "header-only" CMake target. Use it to include any of the headers
# via `target_link_libraries(SOMETHING PUBLIC JObjectDatamodel)`. It works both
# in-tree and externally.

add_library(Examples::JObjectDatamodel INTERFACE)

target_include_directories(Examples::JObjectDatamodel INTERFACE
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
$<INSTALL_INTERFACE:include/JANA/JObjectDatamodel
)

file(GLOB JObjectDatamodel_HEADERS "*.h")

install(FILES ${JObjectDatamodel_HEADERS}
DESTINATION include/JANA/JObjectDatamodel)

install(TARGETS Examples::JObjectDatamodel
EXPORT jana2_targets)

40 changes: 40 additions & 0 deletions src/examples/JObjectDatamodel/CalorimeterCluster.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// Copyright 2020, Jefferson Science Associates, LLC.
// Subject to the terms in the LICENSE file found in the top-level directory.

#pragma once
#include <JANA/JObject.h>

/// JObjects are plain-old data containers for inputs, intermediate results, and outputs.
/// They have member functions for introspection and maintaining associations with other JObjects, but
/// all of the numerical code which goes into their creation should live in a JFactory instead.
/// You are allowed to include STL containers and pointers to non-POD datatypes inside your JObjects,
/// however, it is highly encouraged to keep them flat and include only primitive datatypes if possible.
/// Think of a JObject as being a row in a database table, with event number as an implicit foreign key.

struct CalorimeterCluster : public JObject {

JOBJECT_PUBLIC(CalorimeterCluster)

double x_center; // Pixel coordinates centered around 0,0
double y_center; // Pixel coordinates centered around 0,0
double E_tot; // Energy loss in GeV
double t_begin; // Time in us
double t_end; // Time in us


/// Override Summarize to tell JANA how to produce a convenient string representation for our JObject.
/// This can be used called from user code, but also lets JANA automatically inspect its own data. For instance,
/// adding JCsvWriter<Hit> will automatically generate a CSV file containing each hit. Warning: This is obviously
/// slow, so use this for debugging and monitoring but not inside the performance critical code paths.

void Summarize(JObjectSummary& summary) const override {
summary.add(x_center, NAME_OF(x_center), "%f", "Pixel coords <- [0,80)");
summary.add(y_center, NAME_OF(y_center), "%f", "Pixel coords <- [0,24)");
summary.add(E_tot, NAME_OF(E_tot), "%f", "Energy loss in GeV");
summary.add(t_begin, NAME_OF(t_begin), "%f", "Earliest observed time in us");
summary.add(t_end, NAME_OF(t_end), "%f", "Latest observed time in us");
}

};


38 changes: 38 additions & 0 deletions src/examples/JObjectDatamodel/CalorimeterHit.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@

// Copyright 2020, Jefferson Science Associates, LLC.
// Subject to the terms in the LICENSE file found in the top-level directory.

#pragma once
#include <JANA/JObject.h>

/// JObjects are plain-old data containers for inputs, intermediate results, and outputs.
/// They have member functions for introspection and maintaining associations with other JObjects, but
/// all of the numerical code which goes into their creation should live in a JFactory instead.
/// You are allowed to include STL containers and pointers to non-POD datatypes inside your JObjects,
/// however, it is highly encouraged to keep them flat and include only primitive datatypes if possible.
/// Think of a JObject as being a row in a database table, with event number as an implicit foreign key.

struct CalorimeterHit : public JObject {

JOBJECT_PUBLIC(CalorimeterHit)

int x; // Pixel coordinates centered around 0,0
int y; // Pixel coordinates centered around 0,0
double E; // Energy loss in GeV
double t; // Time in ms


/// Override Summarize to tell JANA how to produce a convenient string representation for our JObject.
/// This can be used called from user code, but also lets JANA automatically inspect its own data. For instance,
/// adding JCsvWriter<Hit> will automatically generate a CSV file containing each hit. Warning: This is obviously
/// slow, so use this for debugging and monitoring but not inside the performance critical code paths.

void Summarize(JObjectSummary& summary) const override {
summary.add(x, NAME_OF(x), "%d", "Pixel coordinates centered around 0,0");
summary.add(y, NAME_OF(y), "%d", "Pixel coordinates centered around 0,0");
summary.add(E, NAME_OF(E), "%f", "Energy loss in GeV");
summary.add(t, NAME_OF(t), "%f", "Time in ms");
}
};


41 changes: 41 additions & 0 deletions src/examples/JObjectDatamodel/F250Hit.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@

// Copyright 2020, Jefferson Science Associates, LLC.
// Subject to the terms in the LICENSE file found in the top-level directory.

#pragma once
#include <JANA/JObject.h>
#include <cstdint>

/// JObjects are plain-old data containers for inputs, intermediate results, and outputs.
/// They have member functions for introspection and maintaining associations with other JObjects, but
/// all of the numerical code which goes into their creation should live in a JFactory instead.
/// You are allowed to include STL containers and pointers to non-POD datatypes inside your JObjects,
/// however, it is highly encouraged to keep them flat and include only primitive datatypes if possible.
/// Think of a JObject as being a row in a database table, with event number as an implicit foreign key.

struct F250Hit : public JObject {

JOBJECT_PUBLIC(F250Hit)

uint32_t crate;
uint32_t slot;
uint32_t channel;
uint32_t E;
uint32_t t;


/// Override Summarize to tell JANA how to produce a convenient string representation for our JObject.
/// This can be used called from user code, but also lets JANA automatically inspect its own data. For instance,
/// adding JCsvWriter<Hit> will automatically generate a CSV file containing each hit. Warning: This is obviously
/// slow, so use this for debugging and monitoring but not inside the performance critical code paths.

void Summarize(JObjectSummary& summary) const override {
summary.add(crate, NAME_OF(crate), "%f");
summary.add(slot, NAME_OF(slot), "%f");
summary.add(channel, NAME_OF(channel), "%f");
summary.add(E, NAME_OF(E), "%f", "Energy in GeV");
summary.add(t, NAME_OF(t), "%f", "Time in ms");
}
};


14 changes: 14 additions & 0 deletions src/examples/PodioFactories/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@

if (USE_PODIO)

add_jana_plugin(PodioFactories)
target_link_libraries(PodioFactories PUBLIC PodioDatamodel PodioDatamodelDict)

else()

message(STATUS "Skipping examples/PodioFactories because USE_PODIO=Off")

endif()



35 changes: 35 additions & 0 deletions src/examples/PodioFactories/PodioClusteringFactory.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@

#include <JANA/JApplication.h>
#include <JANA/Components/JOmniFactory.h>
#include <JANA/Components/JOmniFactoryGeneratorT.h>
#include <PodioDatamodel/ExampleClusterCollection.h>


struct PodioClusteringFactory : public JOmniFactory<PodioClusteringFactory> {

PodioInput<ExampleCluster> m_protoclusters_in {this};
PodioOutput<ExampleCluster> m_clusters_out {this};

Parameter<double> m_scale {this, "scale", 1.0, "Scaling factor"};
Parameter<double> m_offset {this, "offset", 0.0, "Amount to offset [mm]"};

void Configure() {
}

void ChangeRun(int32_t /*run_nr*/) {
}

void Execute(int32_t /*run_nr*/, uint64_t /*evt_nr*/) {

auto cs = std::make_unique<ExampleClusterCollection>();

for (auto protocluster : *m_protoclusters_in()) {
auto cluster = cs->create();
cluster.energy((m_scale() * protocluster.energy()) + m_offset());
}

m_clusters_out() = std::move(cs);
}
};


32 changes: 32 additions & 0 deletions src/examples/PodioFactories/PodioFactories.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@

#include <JANA/JApplication.h>
#include <JANA/Components/JOmniFactoryGeneratorT.h>
#include "PodioClusteringFactory.h"
#include "PodioProtoclusteringFactory.h"

extern "C"{
void InitPlugin(JApplication *app) {

InitJANAPlugin(app);

auto cluster_gen = new JOmniFactoryGeneratorT<PodioClusteringFactory>();

cluster_gen->AddWiring("clusterizer",
{"protoclusters"},
{"clusters"},
{{"offset", "1000"}});

app->Add(cluster_gen);



auto protocluster_gen = new JOmniFactoryGeneratorT<PodioProtoclusteringFactory>();

protocluster_gen->AddWiring("protoclusterizer",
{"hits"},
{"protoclusters"});

app->Add(protocluster_gen);

}
} // "C"
34 changes: 34 additions & 0 deletions src/examples/PodioFactories/PodioProtoclusteringFactory.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// Copyright 2024, Jefferson Science Associates, LLC.
// Subject to the terms in the LICENSE file found in the top-level directory.

#pragma once

#include <JANA/Components/JOmniFactory.h>
#include <PodioDatamodel/ExampleHitCollection.h>
#include <PodioDatamodel/ExampleClusterCollection.h>


struct PodioProtoclusteringFactory : public JOmniFactory<PodioProtoclusteringFactory> {

PodioInput<ExampleHit> hits_in {this};
PodioOutput<ExampleCluster> clusters_out {this};

void Configure() {
}

void ChangeRun(int32_t /*run_nr*/) {
}

void Execute(int32_t /*run_nr*/, uint64_t /*evt_nr*/) {

auto cs = std::make_unique<ExampleClusterCollection>();
for (auto hit : *hits_in()) {
auto cluster = cs->create();
cluster.energy(hit.energy());
cluster.addHits(hit);
}
clusters_out() = std::move(cs);
}
};


5 changes: 4 additions & 1 deletion src/examples/PodioFileWriter/PodioFileWriter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ class PodioFileWriter : public JEventProcessor {
m_writer->finish();
}

void Process(const JEvent& event) override {
void ProcessParallel(const JEvent& event) override {

for (const auto& collection_name : *m_collection_names) {

Expand All @@ -50,6 +50,9 @@ class PodioFileWriter : public JEventProcessor {
// may contain dangling references and segfault upon reading.
event.GetCollectionBase(collection_name);
}
}

void Process(const JEvent& event) override {

auto* frame = event.GetSingle<podio::Frame>();
// This will throw if no PODIO frame is found.
Expand Down
Loading
Loading