-
Notifications
You must be signed in to change notification settings - Fork 19
Add utilities to facilitate the handling of the different I/O formats and related conversions #234
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
Merged
Merged
Changes from 11 commits
Commits
Show all changes
12 commits
Select commit
Hold shift + click to select a range
dc406fb
Introduce a helper to facilitate I/O and related conversions
tmadlener 1882ea1
Add docstrings
tmadlener 3e51ca6
Rework the logic of attaching converters to be a bit simpler
tmadlener e73ce68
Detach from upstream k4FWCore functionality
tmadlener 935102b
Switch event_display example to use new functionality
tmadlener 97f3e92
Make output commands an optional argument
tmadlener 32efd21
Remove unnecessary member
tmadlener ed1b6af
Add documentation
tmadlener c0b9676
Fix formatting issues
tmadlener 1c16fa6
Add deprecation warning for old module
tmadlener bcbbef5
Fix missing comma in documentation
tmadlener 5726a23
Fix minor typos in docstrings
tmadlener File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,199 @@ | ||
| #!/usr/bin/env python3 | ||
| # | ||
| # Copyright (c) 2019-2024 Key4hep-Project. | ||
| # | ||
| # This file is part of Key4hep. | ||
| # See https://key4hep.github.io/key4hep-doc/ for further info. | ||
| # | ||
| # Licensed under the Apache License, Version 2.0 (the "License"); | ||
| # you may not use this file except in compliance with the License. | ||
| # You may obtain a copy of the License at | ||
| # | ||
| # http://www.apache.org/licenses/LICENSE-2.0 | ||
| # | ||
| # Unless required by applicable law or agreed to in writing, software | ||
| # distributed under the License is distributed on an "AS IS" BASIS, | ||
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| # See the License for the specific language governing permissions and | ||
| # limitations under the License. | ||
| # | ||
|
|
||
| import sys | ||
| import logging | ||
|
|
||
| from Configurables import ( | ||
| LcioEvent, | ||
| MarlinProcessorWrapper, | ||
| EDM4hep2LcioTool, | ||
| Lcio2EDM4hepTool, | ||
| ) | ||
|
|
||
| logger = logging.getLogger() | ||
|
|
||
|
|
||
| def _is_wrapped_proc_without_conv(alg, from_edm, to_edm): | ||
| """Check if this algorithm has a configured (i.e. named) converter attached | ||
| for the direction described by from_edm and to_edm""" | ||
| if isinstance(alg, MarlinProcessorWrapper): | ||
| if not getattr(alg, f"{from_edm}2{to_edm}Tool").getName(): | ||
| return True | ||
|
|
||
| return False | ||
|
|
||
|
|
||
| class IOHandlerHelper: | ||
| """Helper class to facilitate the transparent handling of LCIO or EDM4hep | ||
| inputs and outputs. | ||
|
|
||
| This class allows to | ||
| - add the correct reader as determined from the input file name(s) | ||
| - add (multiple) LCIO writers | ||
| - add an EDM4hep writer | ||
| - make sure that the necessary converters are introduced at the right places | ||
| """ | ||
|
|
||
| def __init__(self, alg_list, io_svc): | ||
| """Create a IOHandlerHelper | ||
|
|
||
| Args: | ||
| alg_list (list): The algorithm list which is being populated | ||
| io_svc (IOSvc): The IOSvc that is being used for this run | ||
| """ | ||
| self._alg_list = alg_list | ||
| self._io_svc = io_svc | ||
| self._lcio_input = False | ||
| self._edm4hep_output = False | ||
|
|
||
| def add_reader(self, input_files): | ||
| """Add a reader that is equipped to read the passed files | ||
|
|
||
| If the input is LCIO the necessary algorithm will be configured and | ||
| added to the list of algorithms at the current spot. If the input is | ||
| EDM4hep the file names will be passed to the IOSvc.Input | ||
|
|
||
| Args: | ||
| input_files (list): The input files that should be read | ||
|
|
||
| """ | ||
| if input_files[0].endswith(".slcio"): | ||
| if any(not f.endswith(".slcio") for f in input_files): | ||
| logger.error("All input files need to have the same format (LCIO)") | ||
| sys.exit(1) | ||
|
|
||
| read = LcioEvent() | ||
| read.Files = input_files | ||
| self._alg_list.append(read) | ||
| self._lcio_input = True | ||
| else: | ||
| if any(not f.endswith(".root") for f in input_files): | ||
| logger.error("All input files need to have the same format (EDM4hep)") | ||
| sys.exit(1) | ||
|
|
||
| self._io_svc.Input = input_files | ||
|
|
||
| def add_lcio_writer(self, alg_name): | ||
| """Add a writer for LCIO output at the current spot in the algorithm list | ||
|
|
||
| Note: | ||
| This doesn't configure anything yet, that is still left to do outside | ||
|
|
||
| Args: | ||
| alg_name (str): The name this writer should have | ||
|
|
||
| Returns: | ||
| MarlinProcessorWrapper: The wrapped processor that has just been | ||
| inserted into the algorithm list and that now needs to be | ||
| further configured | ||
| """ | ||
| writer = MarlinProcessorWrapper(alg_name, ProcessorType="LCIOOutputProcessor") | ||
| self._alg_list.append(writer) | ||
| return writer | ||
|
|
||
| def add_edm4hep_writer(self, output_file, output_cmds=["keep *"]): | ||
| """Add an EDM4hep writer at the very end of the algorithm execution | ||
|
|
||
| This will pass the output file name as well as the output commands to | ||
| the IOSvc.Ouptut and IOSvc.outputCommands respectively | ||
|
|
||
| Args: | ||
| output_file (str): The name of the output file | ||
|
|
||
| output_cmds (list, optional): The list of output commands that | ||
| should be applied. Defaults to ["keep *"] | ||
| """ | ||
| self._io_svc.Output = output_file | ||
| self._io_svc.outputCommands = output_cmds | ||
| self._edm4hep_output = True | ||
|
|
||
| def finalize_converters(self): | ||
| """Attach the appropriate converters in all places they are necessary | ||
|
|
||
| Go through the algorihtm list and determine where appropriate converters | ||
|
tmadlener marked this conversation as resolved.
Outdated
|
||
| need be inserted such that the algorithms or wrapped processors always | ||
|
tmadlener marked this conversation as resolved.
Outdated
|
||
| see a consistent picture of the event in both formats. Basically what | ||
| this does is to go through the complete list of algorithms and introduce | ||
| an LCIO to EDM4hep converter at the start of every run of | ||
| MarlinProcessorWrappers and in the other direction at the end of every | ||
| such run | ||
|
|
||
| Note: | ||
| Call this just before you pass the algorithm list to the ApplicationMgr | ||
|
|
||
| Note: | ||
| This will not change existing converters on wrapped processors | ||
| """ | ||
| for alg, next_alg in zip(self._alg_list, self._alg_list[1:]): | ||
| if not isinstance(next_alg, MarlinProcessorWrapper) and _is_wrapped_proc_without_conv( | ||
| alg, "Lcio", "EDM4hep" | ||
| ): | ||
| # We change from a run of wrapped processors to algorithms and | ||
| # we don't have a converter yet | ||
| output_conv = Lcio2EDM4hepTool(f"{alg.getName()}_OutputConverter") | ||
| output_conv.convertAll = True | ||
| output_conv.collNameMapping = {"MCParticle": "MCParticles"} | ||
| alg.Lcio2EDM4hepTool = output_conv | ||
| logger.info( | ||
| f"Added an output converter (LCIO to EDM4hep) to the {alg.getName()} algorithm" | ||
| ) | ||
|
|
||
| if not isinstance( | ||
| alg, (MarlinProcessorWrapper, LcioEvent) | ||
| ) and _is_wrapped_proc_without_conv(next_alg, "EDM4hep", "Lcio"): | ||
| # We change from a run of algorithms to wrapped processors and | ||
| # we do not have a converter yet | ||
| input_conv = EDM4hep2LcioTool(f"{next_alg.getName()}_InputConverter") | ||
| input_conv.convertAll = True | ||
| input_conv.collNameMapping = {"MCParticles": "MCParticle"} | ||
| next_alg.EDM4hep2LcioTool = input_conv | ||
| logger.info( | ||
| f"Added an input converter (EDM4hep to LCIO) to the {next_alg.getName()} algorithm" | ||
| ) | ||
|
|
||
| if not self._lcio_input: | ||
| # We need to convert the input to LCIO from EDM4hep. We attach this | ||
| # to the first wrapped processor that does NOT have another converter | ||
| # configured | ||
| for alg in self._alg_list: | ||
| if _is_wrapped_proc_without_conv(alg, "EDM4hep", "Lcio"): | ||
| input_conv = EDM4hep2LcioTool("InputConversion") | ||
| input_conv.convertAll = True | ||
| input_conv.collNameMapping = {"MCParticles": "MCParticle"} | ||
| alg.EDM4hep2LcioTool = input_conv | ||
| logger.info( | ||
| f"Added an input converter (EDM4hep to LCIO) to the {alg.getName()} algorithm" | ||
| ) | ||
| break | ||
|
|
||
| if self._edm4hep_output: | ||
| # We need to convert to EDM4hep. We attach the converter to the last | ||
| # wrapped processor that thas not have another converter attached | ||
|
tmadlener marked this conversation as resolved.
Outdated
|
||
| for alg in reversed(self._alg_list): | ||
| if _is_wrapped_proc_without_conv(alg, "Lcio", "EDM4hep"): | ||
| output_conv = Lcio2EDM4hepTool("OutputConverter") | ||
| output_conv.convertAll = True | ||
| output_conv.collNameMapping = {"MCParticle": "MCParticles"} | ||
| alg.Lcio2EDM4hepTool = output_conv | ||
| logger.info( | ||
| f"Added an output converter (LCIO to EDM4hep) to the {alg.getName()} algorithm" | ||
| ) | ||
| break | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.