Skip to content

Commit

Permalink
Add JWiredFactoryGenerator
Browse files Browse the repository at this point in the history
  • Loading branch information
nathanwbrei committed Jan 6, 2025
1 parent aa0d852 commit f4a5bd5
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 20 deletions.
56 changes: 56 additions & 0 deletions src/libraries/JANA/Components/JWiredFactoryGeneratorT.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// Copyright 2025, Jefferson Science Associates, LLC.
// Subject to the terms in the LICENSE file found in the top-level directory.
// Created by Nathan Brei

#pragma once

#include <JANA/JFactorySet.h>
#include <JANA/JFactoryGenerator.h>
#include <JANA/Services/JWiringService.h>


namespace jana::components {

template<class FactoryT>
class JWiredFactoryGeneratorT : public JFactoryGenerator {

public:
using FactoryConfigType = typename FactoryT::ConfigType;

explicit JWiredFactoryGeneratorT() = default;

void GenerateFactories(JFactorySet *factory_set) override {

auto wiring_svc = GetApplication()->template GetService<jana::services::JWiringService>();
const auto& type_name = JTypeInfo::demangle<FactoryT>();
for (const auto* wiring : wiring_svc->GetWirings(GetPluginName(), type_name)) {

FactoryT *factory = new FactoryT;
factory->SetApplication(GetApplication());
factory->SetPluginName(this->GetPluginName());
factory->SetTypeName(type_name);

// Set the parameter values on the factory. This way, the values in the wiring file
// show up as "defaults" and the values set on the command line show up as "overrides".
factory->ConfigureAllParameters(wiring->configs);

// Check that output levels in wiring file match the factory's level
for (auto output_level : wiring->output_levels) {
if (output_level != wiring->level) {
throw JException("JOmniFactories are constrained to a single output level");
}
}

factory->PreInit(wiring->prefix,
wiring->level,
wiring->input_names,
wiring->input_levels,
wiring->output_names);

factory_set->Add(factory);
}
}
};

} // namespace jana::components
using jana::components::JWiredFactoryGeneratorT;
2 changes: 1 addition & 1 deletion src/libraries/JANA/Services/JWiringService.cc
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ void JWiringService::AddWirings(const toml::table& table, const std::string& sou
}
auto& f = *fac.as_table();

wiring->plugin_name = f["plugin_name"].value<std::string>().value();
wiring->plugin_name = f["plugin_name"].value<std::string>().value_or("");
wiring->type_name = f["type_name"].value<std::string>().value();
wiring->prefix = f["prefix"].value<std::string>().value();

Expand Down
59 changes: 40 additions & 19 deletions src/programs/unit_tests/Services/JWiringServiceTests.cc
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@

#include "JANA/Components/JOmniFactory.h"
#include "JANA/Components/JOmniFactoryGeneratorT.h"
#include "JANA/Components/JWiredFactoryGeneratorT.h"
#include <PodioDatamodel/ExampleClusterCollection.h>
#include "JANA/JException.h"
#include "JANA/Utils/JEventLevel.h"
Expand Down Expand Up @@ -207,39 +207,60 @@ struct WiredOmniFac : jana::components::JOmniFactory<WiredOmniFac> {
}
};

TEST_CASE("WiringTests_RealFacGen") {
static constexpr std::string_view realfacgen_wiring = R"(
[[factory]]
type_name = "WiredOmniFac"
prefix = "myfac"
input_names = ["usual_input"]
output_names = ["usual_output"]
JApplication app;
[factory.configs]
x = "22"
y = "verbose"
auto wiring_svc = app.GetService<jana::services::JWiringService>();
toml::table table = toml::parse(fake_wiring_file);
wiring_svc->AddWirings(table, "testcase");
[[factory]]
type_name = "WiredOmniFac"
prefix = "myfac_modified"
input_names = ["different_input"]
output_names = ["different_output"]
auto gen = new jana::components::JOmniFactoryGeneratorT<WiredOmniFac>;
[factory.configs]
x = "100"
y = "silent"
// One gets overlaid with an existing wiring
gen->AddWiring("variantfac", {"protoclusters"}, {"clusters"}, {{"x","42"}});
)";

// The other is brand new
gen->AddWiring("exuberantfac", {"protoclusters"}, {"wackyclusters"}, {{"x","27"}});
TEST_CASE("WiringTests_RealFacGen") {

// We should end up with three in total
JApplication app;

auto wiring_svc = app.GetService<jana::services::JWiringService>();
toml::table table = toml::parse(realfacgen_wiring);
wiring_svc->AddWirings(table, "testcase");

auto gen = new jana::components::JWiredFactoryGeneratorT<WiredOmniFac>;
app.Add(gen);
app.Initialize();

auto& summary = app.GetComponentSummary();
LOG << summary;
auto vf = summary.FindComponents("variantfac");
jout << summary;
auto vf = summary.FindComponents("myfac");
REQUIRE(vf.size() == 1);
REQUIRE(vf.at(0)->GetOutputs().at(0)->GetName() == "clusters");
REQUIRE(vf.at(0)->GetOutputs().at(0)->GetName() == "usual_output");

auto ef = summary.FindComponents("exuberantfac");
auto ef = summary.FindComponents("myfac_modified");
REQUIRE(ef.size() == 1);
REQUIRE(ef.at(0)->GetOutputs().at(0)->GetName() == "wackyclusters");
REQUIRE(ef.at(0)->GetOutputs().at(0)->GetName() == "different_output");

// Check that parameter values propagated from wiring file to parameter manager
REQUIRE(app.GetParameterValue<int>("myfac:x") == 22);
REQUIRE(app.GetParameterValue<std::string>("myfac:y") == "verbose");
REQUIRE(app.GetParameterValue<int>("myfac_modified:x") == 100);
REQUIRE(app.GetParameterValue<std::string>("myfac_modified:y") == "silent");

auto event = std::make_shared<JEvent>(&app);
auto facs = event->GetFactorySet()->GetAllMultifactories();
//app.GetJParameterManager()->PrintParameters(2, 0);
//auto event = std::make_shared<JEvent>(&app);
//auto facs = event->GetFactorySet()->GetAllMultifactories();

}

Expand Down

0 comments on commit f4a5bd5

Please sign in to comment.