-
Notifications
You must be signed in to change notification settings - Fork 34
Add factory introspection CLI commands: --list-available-factories and --print-factory-info #2023
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
base: main
Are you sure you want to change the base?
Changes from 5 commits
37e4c03
9b7aa2a
1bb3e7e
1f50f30
1eea988
25121b9
6623f95
d94f23d
dbd1d7c
0afc6ec
d64a0b3
a698d05
a20de1a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,125 @@ | ||
| # EICrecon Factory Help Commands | ||
|
|
||
| This document describes the new factory introspection commands added to the `eicrecon` CLI. | ||
|
|
||
| ## New Commands | ||
|
|
||
| ### `--list-available-factories <plugin>` | ||
|
|
||
| Lists all factories provided by a specific plugin. | ||
|
|
||
| **Usage:** | ||
| ```bash | ||
| eicrecon --list-available-factories EEMC | ||
| eicrecon --list-available-factories BEMC | ||
| ``` | ||
|
|
||
| **Output:** | ||
| - Shows all factories provided by the specified plugin | ||
| - Displays factory object names and tags in a table format | ||
| - If plugin not found, shows list of available plugins with factories | ||
| - Includes a summary count of factories provided by the plugin | ||
|
|
||
| **Example:** | ||
| ``` | ||
| $ eicrecon --list-available-factories EEMC | ||
|
|
||
| Factories provided by plugin 'EEMC': | ||
|
|
||
| | Object name | Tag | Description | | ||
| |------------------------------|------------------------------------------|---------------------------------------------------------------| | ||
| | CalorimeterHitDigi | EcalEndcapNRawHits | Produces: CalorimeterHitDigi (tag: EcalEndcapNRawHits) | | ||
| | CalorimeterHitReco | EcalEndcapNRecHits | Produces: CalorimeterHitReco (tag: EcalEndcapNRecHits) | | ||
| | CalorimeterClusterRecoCoG | EcalEndcapNTruthClustersWithoutShapes | Produces: CalorimeterClusterRecoCoG (tag: EcalEndcapN...) | | ||
|
|
||
| Summary: Plugin 'EEMC' provides 15 factories. | ||
| ``` | ||
|
|
||
| ### `--print-factory-info` | ||
|
|
||
| Shows detailed information about all factories in the system. | ||
|
|
||
| **Usage:** | ||
| ```bash | ||
| eicrecon --print-factory-info | ||
| ``` | ||
|
|
||
| **Output:** | ||
| - Complete table of all factories with plugin, object name, tag, and type info | ||
| - Factory summary statistics including total count | ||
| - Breakdown of factories by plugin | ||
| - Collection naming pattern analysis (heuristic) | ||
| - Guidance on how to get more detailed input/output information | ||
|
|
||
| **Example:** | ||
| ``` | ||
| $ eicrecon --print-factory-info | ||
|
|
||
| Detailed factory information: | ||
|
|
||
| | Plugin | Object name | Tag | Type Info | | ||
| |--------|--------------------------|----------------------------|-------------------------------------| | ||
| | EEMC | CalorimeterHitDigi | EcalEndcapNRawHits | CalorimeterHitDigi [EcalEndcapN...] | | ||
| | BEMC | CalorimeterHitDigi | EcalBarrelRawHits | CalorimeterHitDigi [EcalBarrel...] | | ||
| | ... | ... | ... | ... | | ||
|
|
||
| Factory Summary: | ||
| Total factories: 157 | ||
| Factories by plugin: | ||
| EEMC: 15 factories | ||
| BEMC: 12 factories | ||
| tracking: 8 factories | ||
| ... | ||
|
|
||
| Collection naming patterns (heuristic analysis): | ||
| Ecal*: 45 collections (EcalEndcapNRawHits, EcalBarrelRawHits, EcalEndcapNRecHits, ...) | ||
| Hcal*: 23 collections (HcalEndcapNRawHits, HcalBarrelRawHits, ...) | ||
| ... | ||
|
|
||
| For detailed input/output collection information: | ||
| 1. Use --list-available-factories <plugin> to see factories by plugin | ||
| 2. Inspect factory source code for precise input/output definitions | ||
| 3. Look at plugin registration code (e.g., EEMC.cc) for I/O specifications | ||
| ``` | ||
|
|
||
| ## Integration with Existing Commands | ||
|
|
||
| These new commands work alongside existing EICrecon CLI commands: | ||
|
|
||
| - `--list-available-plugins` - Lists all available plugins | ||
| - `--list-factories` (`-L`) - Lists all factories (basic format) | ||
| - `--list-default-plugins` - Lists default plugins | ||
|
|
||
| ## Technical Notes | ||
|
|
||
| ### Factory Input/Output Collections | ||
|
|
||
| While these commands provide comprehensive factory listings, detailed input/output collection information requires examination of: | ||
|
|
||
| 1. **Factory source code**: Look at the `PodioInput<>` and `PodioOutput<>` declarations in factory headers | ||
| 2. **Plugin registration**: Check the plugin's `.cc` file (e.g., `EEMC.cc`) for `JOmniFactoryGeneratorT` calls that specify input and output collections | ||
| 3. **Factory documentation**: Some factories may have additional documentation in their source files | ||
|
|
||
| ### Example Factory Registration | ||
|
|
||
| In plugin registration code, you'll find patterns like: | ||
| ```cpp | ||
| app->Add(new JOmniFactoryGeneratorT<CalorimeterHitDigi_factory>( | ||
| "EcalEndcapNRawHits", // Factory tag | ||
| {"EventHeader", "EcalEndcapNHits"}, // Input collections | ||
| {"EcalEndcapNRawHits", "EcalEndcapNRawHitAssociations"}, // Output collections | ||
| config_object | ||
| )); | ||
| ``` | ||
|
|
||
| This provides the precise input/output relationships that are not currently accessible through the runtime CLI introspection. | ||
|
|
||
| ## Future Enhancements | ||
|
|
||
| These commands provide a foundation for factory introspection. Potential future enhancements could include: | ||
|
|
||
| - Runtime access to input/output collection information through extended JANA APIs | ||
| - Factory dependency graph visualization | ||
| - Collection type information | ||
| - Factory parameter inspection | ||
| - Performance metrics integration |
| Original file line number | Diff line number | Diff line change | ||||||
|---|---|---|---|---|---|---|---|---|
|
|
@@ -14,6 +14,7 @@ | |||||||
| #include <cstring> | ||||||||
| #include <filesystem> | ||||||||
| #include <iostream> | ||||||||
| #include <map> | ||||||||
| #include <memory> | ||||||||
| #include <set> | ||||||||
| #include <sstream> | ||||||||
|
|
@@ -49,6 +50,9 @@ void PrintUsageOptions() { | |||||||
| std::cout << " -b --benchmark Run in benchmark mode" << std::endl; | ||||||||
| std::cout << " -L --list-factories List all the factories without running" | ||||||||
| << std::endl; | ||||||||
| std::cout << " --list-available-factories <plugin> List factories for a specific plugin" | ||||||||
| << std::endl; | ||||||||
| std::cout << " --print-factory-info Print detailed factory information" << std::endl; | ||||||||
| std::cout << " -Pkey=value Specify a configuration parameter" << std::endl; | ||||||||
| std::cout << " -Pplugin:param=value Specify a parameter value for a plugin" | ||||||||
| << std::endl; | ||||||||
|
|
@@ -72,7 +76,9 @@ void PrintUsageExample() { | |||||||
| std::cout << "Example:" << std::endl; | ||||||||
| std::cout << " eicrecon -Pplugins=plugin1,plugin2,plugin3 -Pnthreads=8 infile.root" | ||||||||
| << std::endl; | ||||||||
| std::cout << " eicrecon -Ppodio:print_type_table=1 infile.root" << std::endl << std::endl; | ||||||||
| std::cout << " eicrecon -Ppodio:print_type_table=1 infile.root" << std::endl; | ||||||||
| std::cout << " eicrecon --list-available-factories EEMC" << std::endl; | ||||||||
| std::cout << " eicrecon --print-factory-info" << std::endl << std::endl; | ||||||||
| std::cout << std::endl << std::endl; | ||||||||
| } | ||||||||
|
|
||||||||
|
|
@@ -321,6 +327,61 @@ void PrintFactories(JApplication* app) { | |||||||
| std::cout << std::endl; | ||||||||
| } | ||||||||
|
|
||||||||
| void PrintPluginFactories(JApplication* app, const std::string& plugin_name) { | ||||||||
| std::cout << std::endl | ||||||||
| << "Factories provided by plugin '" << plugin_name << "':" << std::endl | ||||||||
| << std::endl; | ||||||||
|
|
||||||||
| auto cs = app->GetComponentSummary(); | ||||||||
| JTablePrinter factory_table; | ||||||||
| factory_table.AddColumn("Object name"); | ||||||||
| factory_table.AddColumn("Tag"); | ||||||||
| factory_table.AddColumn("Description"); | ||||||||
|
|
||||||||
| bool found_any = false; | ||||||||
| int factory_count = 0; | ||||||||
|
|
||||||||
| for (const auto& factory : cs.factories) { | ||||||||
| if (factory.plugin_name == plugin_name) { | ||||||||
| std::string description = "Produces: " + factory.object_name; | ||||||||
| if (!factory.factory_tag.empty()) { | ||||||||
| description += " (tag: " + factory.factory_tag + ")"; | ||||||||
| } | ||||||||
| factory_table | factory.object_name | factory.factory_tag | description; | ||||||||
| found_any = true; | ||||||||
| factory_count++; | ||||||||
| } | ||||||||
| } | ||||||||
|
|
||||||||
| if (!found_any) { | ||||||||
| std::cout << "No factories found for plugin '" << plugin_name << "'" << std::endl; | ||||||||
| std::cout << std::endl << "Available plugins with factories:" << std::endl; | ||||||||
|
|
||||||||
| // Show available plugins that have factories | ||||||||
| std::set<std::string> available_plugins; | ||||||||
| for (const auto& factory : cs.factories) { | ||||||||
| available_plugins.insert(factory.plugin_name); | ||||||||
| } | ||||||||
|
|
||||||||
| JTablePrinter plugin_table; | ||||||||
| plugin_table.AddColumn("Plugin name"); | ||||||||
| for (const auto& plugin : available_plugins) { | ||||||||
| plugin_table | plugin; | ||||||||
| } | ||||||||
|
|
||||||||
| std::ostringstream plugin_ss; | ||||||||
| plugin_table.Render(plugin_ss); | ||||||||
| std::cout << plugin_ss.str() << std::endl; | ||||||||
| } else { | ||||||||
| std::ostringstream ss; | ||||||||
| factory_table.Render(ss); | ||||||||
| std::cout << ss.str() << std::endl; | ||||||||
| std::cout << "Summary: Plugin '" << plugin_name << "' provides " << factory_count | ||||||||
| << " factories." << std::endl; | ||||||||
| } | ||||||||
| std::cout << std::endl; | ||||||||
| } | ||||||||
|
|
||||||||
| void PrintPodioCollections(JApplication* app) { | ||||||||
| if (app->GetJParameterManager()->Exists("PODIO:PRINT_TYPE_TABLE")) { | ||||||||
| bool print_type_table = app->GetParameterValue<bool>("podio:print_type_table"); | ||||||||
|
|
@@ -339,6 +400,81 @@ void PrintPodioCollections(JApplication* app) { | |||||||
| } | ||||||||
| } | ||||||||
|
|
||||||||
| void PrintFactoryInfo(JApplication* app) { | ||||||||
| std::cout << std::endl << "Detailed factory information:" << std::endl << std::endl; | ||||||||
|
|
||||||||
| auto cs = app->GetComponentSummary(); | ||||||||
| JTablePrinter factory_table; | ||||||||
| factory_table.AddColumn("Plugin"); | ||||||||
| factory_table.AddColumn("Object name"); | ||||||||
| factory_table.AddColumn("Tag"); | ||||||||
| factory_table.AddColumn("Type Info"); | ||||||||
|
|
||||||||
| for (const auto& factory : cs.factories) { | ||||||||
| std::string type_info = factory.object_name; | ||||||||
| if (!factory.factory_tag.empty()) { | ||||||||
| type_info += " [" + factory.factory_tag + "]"; | ||||||||
| } | ||||||||
| factory_table | factory.plugin_name | factory.object_name | factory.factory_tag | type_info; | ||||||||
| } | ||||||||
|
|
||||||||
| std::ostringstream ss; | ||||||||
| factory_table.Render(ss); | ||||||||
| std::cout << ss.str() << std::endl; | ||||||||
|
|
||||||||
| std::cout << "Factory Summary:" << std::endl; | ||||||||
| std::cout << " Total factories: " << cs.factories.size() << std::endl; | ||||||||
|
|
||||||||
| // Count factories by plugin | ||||||||
| std::map<std::string, int> plugin_counts; | ||||||||
| for (const auto& factory : cs.factories) { | ||||||||
| plugin_counts[factory.plugin_name]++; | ||||||||
| } | ||||||||
|
|
||||||||
| std::cout << " Factories by plugin:" << std::endl; | ||||||||
| for (const auto& pair : plugin_counts) { | ||||||||
| std::cout << " " << pair.first << ": " << pair.second << " factories" << std::endl; | ||||||||
| } | ||||||||
|
|
||||||||
| // Look for potential collection patterns (basic heuristic) | ||||||||
| std::cout << std::endl << " Collection naming patterns (heuristic analysis):" << std::endl; | ||||||||
| std::map<std::string, std::vector<std::string>> patterns; | ||||||||
|
|
||||||||
| for (const auto& factory : cs.factories) { | ||||||||
| // Extract potential collection base names by looking at factory tags | ||||||||
| std::string tag = factory.factory_tag.empty() ? factory.object_name : factory.factory_tag; | ||||||||
|
|
||||||||
| // Simple pattern matching - look for common prefixes | ||||||||
| if (tag.length() > 4) { | ||||||||
| std::string prefix = tag.substr(0, 4); | ||||||||
| patterns[prefix].push_back(tag); | ||||||||
| } | ||||||||
| } | ||||||||
|
|
||||||||
| for (const auto& pattern : patterns) { | ||||||||
| if (pattern.second.size() > 1) { // Only show patterns with multiple factories | ||||||||
| std::cout << " " << pattern.first << "*: " << pattern.second.size() << " collections ("; | ||||||||
| for (size_t i = 0; i < std::min(pattern.second.size(), size_t(3)); ++i) { | ||||||||
| if (i > 0) | ||||||||
| std::cout << ", "; | ||||||||
| std::cout << pattern.second[i]; | ||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
| } | ||||||||
| if (pattern.second.size() > 3) | ||||||||
|
||||||||
| if (pattern.second.size() > 3) | |
| if (pattern.second.size() > 3) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
statement should be inside braces
| std::cout << ")" << std::endl; | |
| } | |
| std::cout << ")" << std::endl; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
statement should be inside braces