This chapter will explain to you how to integrate these updates when there are new updates to common dependencies, configuration or process functions in O2-DQ Framework or in Common framework.
Tools used to add new configurable or new process functions in JSONs and more are defined as functions in the PythonInterfaceOOP/extramodules/configSetter.py script in the extramodules folder (You can found more information in doc strings).
If you need a modification, you only need to modify the functions in the main tools. Helper tools are utility functions and you don't need to modify them. These are standard.
Main Tools:
- SetArgsToArgumentParser → An interface creator class that parses the JSON configuration file and creates the arguments for the CLI, defining possible autocompletes and defining hard coded arguments.
- setConverters → This function that allows to include converter tasks given to the CLI into the workflow
Helper Tools:
- dispArgs → Prints each argument provided by the CLI to the screen for monitoring
- dispInterfaceMode → Prints the mode in which the interface will work.
- dispO2HelpMessage → Utility function to run
--help fullcommand in O2 with--helpO2argument in python scripts - debugSettings → Utility function to log terminal or file (or both)
- generateDescriptors → Utility function that creates a descriptor json file for generating reduced tables
- tableProducerSkimming/tableProducerAnalysis → They are helper functions for the generatorDescriptor utility function that saves the tables defined in the DQ data model to a hashmap data structure and then writes it to the descriptor json file.
- setProcessDummy → if a task contains a processDummy function, processDummy must be true if no other process functions are true, and processDummy must be false if at least one process function is true. This is the auxiliary function that automatically manages the situation.
- setParallelismOnSkimming → It is a helper function that allows to run tableMaker and tableReader or tableMakerMC and dqEfficiency workflows at the same time.
- commonDepsToRun → It is the utility function used to set the dependencies required in the workflow.
- setSwitch → It is a utility function that automates the process functions according to the JSON interface mode.
- setConfigs → It is the utility function that allows to assign the argument parameter pairs provided by the CLI to the configurations in the json config file.
Two strategies are used to manage O2 dependencies in Python scripts:
1-) Keeping the dependencies for common, barrel and muon in a separate list, then running the dependencies required according to the workflow with the naming rules (this strategy is used in the runTableMaker.py script) 2-) Collect all dependencies in one list and run them directly
In the first strategy, it is added to the list where it is defined according to the dependency type. For example, the dependencies defined for tableMaker are as follows:
commonDeps= ["o2-analysis-timestamp", "o2-analysis-event-selection", "o2-analysis-multiplicity-table"]
barrelDeps= ["o2-analysis-trackselection", "o2-analysis-trackextension", "o2-analysis-pid-tof-base", "o2-analysis-pid-tof", "o2-analysis-pid-tof-full", "o2-analysis-pid-tof-beta", "o2-analysis-pid-tpc-full"]
muonDeps= ["o2-analysis-fwdtrackextension"]Relevant dependencies can be added here if necessary, first the common DepsToRun function calls all dependencies:
# Check which dependencies need to be rundepsToRun=commonDepsToRun(commonDeps)Then the barrel and/or muon dependencies are invoked depending on whether the process function in the tableMaker contains the barrel or muon substring:
# LOOK AT HEREforprocessFuncinspecificDeps.keys():
ifprocessFuncnotinconfig[taskNameInConfig].keys():
continueifconfig[taskNameInConfig][processFunc] =="true":
if"processFull"inprocessFuncor"processBarrel"inprocessFuncor"processAmbiguousBarrel"inprocessFunc:
fordepinbarrelDeps:
depsToRun[dep] =1if"processFull"inprocessFuncor"processMuon"inprocessFuncor"processAmbiguousMuon"inprocessFunc:
fordepinmuonDeps:
depsToRun[dep] =1# THIS WILL EXPLAIN LATERfordepinspecificDeps[processFunc]:
depsToRun[dep] =1Then the command to be executed in O2 is given as a string. Related dependencies for this string | is added by separating with:
commandToRun=f"{taskNameInCommandLine} --configuration json://{updatedConfigFileName} --severity error --shm-segment-size 12000000000 --aod-writer-json {writerConfigFileName} -b"fordepindepsToRun.keys():
commandToRun+=" | "+dep+" --configuration json://"+updatedConfigFileName+" -b"logging.debug("%s added your workflow", dep)In the second strategy all the dependency are added to a single list, then they are all added to the similarly generated commandToRun string. For ex. for runFilterPP:
# All dependenciescommonDeps= ["o2-analysis-timestamp", "o2-analysis-event-selection", "o2-analysis-multiplicity-table", "o2-analysis-trackselection", "o2-analysis-trackextension", "o2-analysis-pid-tof-base", "o2-analysis-pid-tof", "o2-analysis-pid-tof-full", "o2-analysis-pid-tof-beta", "o2-analysis-pid-tpc-full", "o2-analysis-fwdtrackextension"]
# Check which dependencies need to be rundepsToRun=commonDepsToRun(commonDeps)
commandToRun=f"{taskNameInCommandLine} --configuration json://{updatedConfigFileName} --severity error --shm-segment-size 12000000000 -b"fordepindepsToRun.keys():
commandToRun+=" | "+dep+" --configuration json://"+updatedConfigFileName+" -b"logging.debug("%s added your workflow", dep)If two or more DQ workflows or common dependencies are wanted to be pipelined and run at the same time, then specific dependency trees can be created with hashmap like O2 dependencies can be added, and they can be run depending on the process functions. for e.g in runTableMaker.py:
specificDeps= {
"processFull": [],
"processFullTiny": [],
"processFullWithCov": [],
"processFullWithCent": ["o2-analysis-centrality-table"],
"processBarrelOnly": [],
"processBarrelOnlyWithCov": [],
"processBarrelOnlyWithV0Bits": ["o2-analysis-dq-v0-selector"],
"processBarrelOnlyWithDalitzBits": ["o2-analysis-dq-dalitz-selection"],
"processBarrelOnlyWithEventFilter": ["o2-analysis-dq-filter-pp"],
"processBarrelOnlyWithQvector": ["o2-analysis-centrality-table", "o2-analysis-dq-flow"],
"processBarrelOnlyWithCent": ["o2-analysis-centrality-table"],
"processMuonOnly": [],
"processMuonOnlyWithCov": [],
"processMuonOnlyWithCent": ["o2-analysis-centrality-table"],
"processMuonOnlyWithQvector": ["o2-analysis-centrality-table", "o2-analysis-dq-flow"],
"processMuonOnlyWithFilter": ["o2-analysis-dq-filter-pp"],
"processAmbiguousMuonOnly": [],
"processAmbiguousBarrelOnly": []
# "processFullWithCentWithV0Bits": ["o2-analysis-centrality-table","o2-analysis-dq-v0-selector", "o2-analysis-weak-decay-indices"],# "processFullWithEventFilterWithV0Bits": ["o2-analysis-dq-filter-pp","o2-analysis-dq-v0-selector", "o2-analysis-weak-decay-indices"],
}As can be seen, O2 dependency dependencies according to the process function (for example, if the processBarrelOnlyWithCent function is true, it also includes the o2-analysis-centrality-table dependency in the workflow) or other DQ workflows (for example, if the processBarrelOnlyWithEventFilter function is true o2-analysis-dq-filter- pp is included in the workflow and run simultaneously with the table-maker) can be included in the pipeline by process function
we manage this with hashmaps as mentioned before (this code block was given above when explaining O2 dependencies):
forprocessFuncinspecificDeps.keys():
ifprocessFuncnotinconfig[taskNameInConfig].keys():
continueifconfig[taskNameInConfig][processFunc] =="true":
if"processFull"inprocessFuncor"processBarrel"inprocessFuncor"processAmbiguousBarrel"inprocessFunc:
fordepinbarrelDeps:
depsToRun[dep] =1if"processFull"inprocessFuncor"processMuon"inprocessFuncor"processAmbiguousMuon"inprocessFunc:
fordepinmuonDeps:
depsToRun[dep] =1# LOOK AT HEREfordepinspecificDeps[processFunc]:
depsToRun[dep] =1Starting from here, you can add dependency trees and specific dependencies according to each process function, and you can directly add common, barrel or muon dependencies to the lists.
Tables in the O2-DQ framework data model are integrated into the python script with list and hashmap. The tables variable is a hashmap structure that contains all the tables that we can produce with table-maker or table-maker-mc in the O2-DQ framework The dependencies of each table are divided according to the process functions and whether they are general or not. Common tables are always generated, barrel tables are generated if at least one process function starting with processBarrel is true in table-maker or table-maker-mc, muon tables are generated if at least one process function starting with processMuon is true. they are assigned in a list structure called commonTables, barrelTables and muonTables variables to keep table names. If the process function needs to generate a special table (for example, processBarrelOnlyWithCov generates the extra necessary covariance tables for the track barrel) these are specified under the variable specificTables with the hashmap:
# yapf: disable# Definition of all the tables we may writetables= {
"ReducedEvents": {"table": "AOD/REDUCEDEVENT/0"},
"ReducedEventsExtended": {"table": "AOD/REEXTENDED/0"},
"ReducedEventsVtxCov": {"table": "AOD/REVTXCOV/0"},
"ReducedEventsQvector": {"table": "AOD/REQVECTOR/0"},
"ReducedMCEventLabels": {"table": "AOD/REMCCOLLBL/0"},
"ReducedMCEvents": {"table": "AOD/REDUCEDMCEVENT/0"},
"ReducedTracks": {"table": "AOD/REDUCEDTRACK/0"},
"ReducedTracksBarrel": {"table": "AOD/RTBARREL/0"},
"ReducedTracksBarrelCov": {"table": "AOD/RTBARRELCOV/0"},
"ReducedTracksBarrelPID": {"table": "AOD/RTBARRELPID/0"},
"ReducedTracksBarrelLabels": {"table": "AOD/RTBARRELLABELS/0"},
"ReducedMCTracks": {"table": "AOD/REDUCEDMCTRACK/0"},
"ReducedMuons": {"table": "AOD/RTMUON/0"},
"ReducedMuonsExtra": {"table": "AOD/RTMUONEXTRA/0"},
"ReducedMuonsCov": {"table": "AOD/RTMUONCOV/0"},
"ReducedMuonsLabels": {"table": "AOD/RTMUONSLABELS/0"},
"AmbiguousTracksMid": {"table": "AOD/AMBIGUOUSTRACK/0"},
"AmbiguousTracksFwd": {"table": "AOD/AMBIGUOUSFWDTR/0"},
"DalitzBits": {"table": "AOD/DALITZBITS/0"},
#"ReducedV0s": {"table": "AOD/REDUCEDV0/0"}, # NOTE V0 Bits cannot save to reduced tables#"V0Bits": {"table": "AOD/V0BITS/0"}
}
# yapf: enable# Tables to be written, per process functioncommonTables= ["ReducedEvents", "ReducedEventsExtended", "ReducedEventsVtxCov"]
barrelCommonTables= ["ReducedTracks", "ReducedTracksBarrel", "ReducedTracksBarrelPID"]
muonCommonTables= ["ReducedMuons", "ReducedMuonsExtra"]
specificTables= {
"processFull": [],
"processFullTiny": [],
"processFullWithCov": ["ReducedTracksBarrelCov", "ReducedMuonsCov"],
"processFullWithCent": [],
"processBarrelOnly": [],
"processBarrelOnlyWithCov": ["ReducedTracksBarrelCov"],
"processBarrelOnlyWithV0Bits": [],
"processBarrelOnlyWithDalitzBits": ["DalitzBits"],
"processBarrelOnlyWithQvector": ["ReducedEventsQvector"],
"processBarrelOnlyWithEventFilter": [],
"processBarrelOnlyWithCent": [],
"processMuonOnly": [],
"processMuonOnlyWithCov": ["ReducedMuonsCov"],
"processMuonOnlyWithCent": [],
"processMuonOnlyWithQvector": ["ReducedEventsQvector"],
"processMuonOnlyWithFilter": [],
"processAmbiguousMuonOnly": ["AmbiguousTracksFwd"],
"processAmbiguousBarrelOnly": ["AmbiguousTracksMid"]
}if a table has been added to the DQ data model and you want to modify it to scripts, always first! You should add this table to the tables variable. If this table is linked to a process function, then you must define it against the relevant process function in the hashmap list in the specificTables variable. If it is a more general table (common, barrel or muon) then you can add it directly to the lists.
finally after adding them to python scripts, Finally, after adding them to the python scripts, you should add the tables you added in the reader json files (readerConfiguration_reducedEvent.json for Data, readerConfiguration_reducedEventMC.json for MC).
If a new configurable or processFunction has been added to O2 DQ framework then if you just add it to the corresponding task in JSON configuration files, the argument will be generated automatically by the python scripts. For example, assuming we want to add a new configurable cfgNewCuts variable to the analysis-same-event pairing task (tableReader) in the configAnalysisData.json file. Before:
"analysis-same-event-pairing": {
"cfgTrackCuts": "jpsiO2MCdebugCuts",
"cfgMuonCuts": "muonQualityCuts",
"cfgAddSEPHistogram": "barrel,vertexing,flow",
"ccdb-url": "http:\/\/alice-ccdb.cern.ch",
"ccdb-path": "Users\/lm",
"ccdb-no-later-than": "1638360910432",
"processDecayToEESkimmed": "true",
"processDecayToEEPrefilterSkimmed": "false",
"processDecayToMuMuSkimmed": "true",
"processDecayToMuMuVertexingSkimmed": "false",
"processVnDecayToEESkimmed": "false",
"processVnDecayToMuMuSkimmed": "false",
"processElectronMuonSkimmed": "false",
"processAllSkimmed": "false",
"processDummy": "false"
},After:
"analysis-same-event-pairing": {
"cfgNewCuts": """cfgTrackCuts": "jpsiO2MCdebugCuts",
"cfgMuonCuts": "muonQualityCuts",
"cfgAddSEPHistogram": "barrel,vertexing,flow",
"ccdb-url": "http:\/\/alice-ccdb.cern.ch",
"ccdb-path": "Users\/lm",
"ccdb-no-later-than": "1638360910432",
"processDecayToEESkimmed": "true",
"processDecayToEEPrefilterSkimmed": "false",
"processDecayToMuMuSkimmed": "true",
"processDecayToMuMuVertexingSkimmed": "false",
"processVnDecayToEESkimmed": "false",
"processVnDecayToMuMuSkimmed": "false",
"processElectronMuonSkimmed": "false",
"processAllSkimmed": "false",
"processDummy": "false"
},Adding it like this will suffice. So you will be able to access this command as:
--analysis-same-event-pairing:cfgNewCutsif you want to add a global argument, they are hardcoded in SetArgsToArgumentParser class in the configSetter.py script. You can add here directly and you can define business logic in run scripts:
# We can define hard coded global argumentsself.parser.add_argument("cfgFileName", metavar="Config.json", default="config.json", help="config JSON file name (mandatory)")
self.parser.add_argument("-runParallel", help="Run parallel in session", action="store_true", default=False)
# GLOBAL OPTIONSgroupGlobal=self.parser.add_argument_group(title=f"Global workflow options")
groupGlobal.add_argument("--aod-memory-rate-limit", help="Rate limit AOD processing based on memory", action="store", type=str)
groupGlobal.add_argument("--writer", help="Argument for producing extra reduced tables", action="store", type=str).completer=ChoicesCompleter(booleanSelections)
groupGlobal.add_argument("--helpO2", help="Display help message on O2", action="store_true", default=False)
# Converter Task OptionsgroupO2Converters=self.parser.add_argument_group(title=f"Add to workflow O2 Converter task options")
groupO2Converters.add_argument("--add_mc_conv", help="Add the converter from mcparticle to mcparticle+001 (Adds your workflow o2-analysis-mc-converter task)", action="store_true",)
groupO2Converters.add_argument("--add_fdd_conv", help="Add the fdd converter (Adds your workflow o2-analysis-fdd-converter task)", action="store_true",)
groupO2Converters.add_argument("--add_track_prop", help="Add track propagation to the innermost layer (TPC or ITS) (Adds your workflow o2-analysis-track-propagation task)", action="store_true",)
groupO2Converters.add_argument("--add_weakdecay_ind", help="Add Converts V0 and cascade version 000 to 001 (Adds your workflow o2-analysis-weak-decay-indices task)", action="store_true",)
groupO2Converters.add_argument("--add_col_conv", help="Add the converter from collision to collision+001", action="store_true")
# Helper OptionsgroupHelper=self.parser.add_argument_group(title=f"Helper Options")
groupHelper.add_argument("--debug", help="execute with debug options", action="store", type=str.upper, default="INFO", choices=debugLevelSelectionsList,).completer=ChoicesCompleterList(debugLevelSelectionsList)
groupHelper.add_argument("--logFile", help="Enable logger for both file and CLI", action="store_true")
groupHelper.add_argument("--override", help="If true JSON Overrider Interface If false JSON Additional Interface", action="store", default="true", type=str.lower, choices=booleanSelections,).completer=ChoicesCompleter(booleanSelections)for ex. For example, --debug and --logFile arguments are global, and the scripts for logging settings are specifically defined:
# Debug SettingsdebugSettings(args.debug, args.logFile, fileName="v0selector.log")Autocompletions are defined for a configurable or process function in python scripts. These are defined in the SetArgsToArgumentParser class in the configSetter.py script in the extramodules folder. Two types of autocompletion are currently available:
1-) Autocompletions by parsing DQ header files and assigning analysis cuts, MC signals, histogram groups or event mixing variables to a variable.
2-) Hard codded selections (such as true-false for process functions or QA options, or -1, 0 or 1 selections for autocompletion e.g. in pid or est configurations etc.).
Configuration strings (such as analysis cuts) obtained by parsing DQ libraries are retrieved by instantiating the DQLibGetter class in the dqLibGetter.py script in the extramodules folder:
# Dependency injectiondqLibGetter=DQLibGetter()
# Get All Configurables for DQ Framework from DQ header filesallAnalysisCuts=dqLibGetter.allAnalysisCutsallMCSignals=dqLibGetter.allMCSignalsallSels=dqLibGetter.allSelsallMixing=dqLibGetter.allMixing# Get all histogram groups for DQ Framework from histogram library# NOTE Now we use only all histos for backward comp.allHistos=dqLibGetter.allHistos# allEventHistos = dqLibGetter.allEventHistos# allTrackHistos = dqLibGetter.allTrackHistos# allMCTruthHistos = dqLibGetter.allMCTruthHistos# allPairHistos = dqLibGetter.allPairHistos# allDileptonHistos = dqLibGetter.allDileptonHistosHard coded selections are defined in lists by the user:
# Predefined lists for autocompletionbooleanSelections= ["true", "false"]
itsMatchingSelections= ["0", "1", "2", "3"]
binarySelection= ["0", "1"]
tripletSelection= ["-1", "0", "1"]
collisionSystemSelections= ["PbPb", "pp", "pPb", "Pbp", "XeXe"]
eventMuonSelections= ["0", "1", "2"]
debugLevelSelectionsList= ["NOTSET", "DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"]Autocompletion property is assigned to later configurations according to naming conventions. For example, since all analysis cuts in the entire DQ framework contain the "Cuts" substring:
# AUTOCOMPLETION CONDITIONcontainsCuts="Cuts"inconfigurable# ASSIGN AUTOCOMPLETIONifcontainsCuts:
groupJsonParser.add_argument("--"+arg, help="", action="store", nargs="*", type=str, metavar="\b").completer=ChoicesCompleterList(allAnalysisCuts)Definition has been made. Thus, an autocompletion is made for each configuration that contains Cuts in the JSON config file. Every configuration that satisfies this condition, ie configurables containing Cuts, analysis segments parsed from the DQ library, is assigned to the argument as autocompletion.
These are all currently defined autocompletion conditions and when you add a configuration that satisfies these conditions to JSON, autocompletion will be automatically assigned to the relevant parameter (You can examine autocompletion conditions from SetArgsToArgumentParser class):
# Define some autocompletion rules for match-case (for O2-DQ Framework)containsCuts="Cuts"inconfigurablecontainsSignals=configurable.endswith("Signals") orconfigurable.endswith("signals")
containsHistogram="Histogram"inconfigurablecontainsSels=configurable.endswith("BarrelSels") orconfigurable.endswith("MuonSels")
containsMixingVars="MixingVars"inconfigurablecontainsQA=configurable.startswith("cfg") and"QA"inconfigurablecontainsAmbiguous=configurable=="cfgIsAmbiguous"containsFillCandidateTable=configurable=="cfgFillCandidateTable"containsFlatTables=configurable=="cfgFlatTables"containsTPCpostCalib=configurable=="cfgTPCpostCalib"containsProcess=configurable.startswith("process")These autocompletion conditions are assigned to the parser arguments with if conditions. If you are going to add a new autocompletion, you must first define the condition as above, then integrate it into the following if conditions(You can examine if conditions from SetArgsToArgumentParser class):
# We may define posible all autocompletions as semi hard-coded with substring search (according to naming conventions)# DQ FrameworkifcontainsCuts:
groupJsonParser.add_argument("--"+arg, help="", action="store", nargs="*", type=str, metavar="\b").completer=ChoicesCompleterList(allAnalysisCuts)
elifcontainsSignals:
groupJsonParser.add_argument("--"+arg, help="", action="store", nargs="*", type=str, metavar="\b").completer=ChoicesCompleterList(allMCSignals)
elifcontainsHistogram:
groupJsonParser.add_argument("--"+arg, help="", action="store", nargs="*", type=str, metavar="\b").completer=ChoicesCompleterList(allHistos)
elifcontainsSels:
groupJsonParser.add_argument("--"+arg, help="", action="store", nargs="*", type=str, metavar="\b").completer=ChoicesCompleterList(allSels)
elifcontainsMixingVars:
groupJsonParser.add_argument("--"+arg, help="", action="store", nargs="*", type=str, metavar="\b").completer=ChoicesCompleterList(allMixing)
elifcontainsQA:
groupJsonParser.add_argument("--"+arg, help="", action="store", type=str.lower, metavar="\b").completer=ChoicesCompleter(booleanSelections)
elifcontainsAmbiguous:
groupJsonParser.add_argument("--"+arg, help="", action="store", type=str.lower, metavar="\b").completer=ChoicesCompleter(booleanSelections)
elifcontainsFillCandidateTable:
groupJsonParser.add_argument("--"+arg, help="", action="store", type=str.lower, metavar="\b").completer=ChoicesCompleter(booleanSelections)
elifcontainsFlatTables:
groupJsonParser.add_argument("--"+arg, help="", action="store", type=str.lower, metavar="\b").completer=ChoicesCompleter(booleanSelections)
elifcontainsTPCpostCalib:
groupJsonParser.add_argument("--"+arg, help="", action="store", type=str.lower, metavar="\b").completer=ChoicesCompleter(booleanSelections)
elifconfigurable=="processDummy": # NOTE we don't need configure processDummy since we have dummy automizercontinue# Common FrameworkelifcontainsProcess: # NOTE This is an global definition in O2 Analysis framework, all process functions startswith "process"groupJsonParser.add_argument("--"+arg, help="", action="store", type=str.lower, metavar="\b").completer=ChoicesCompleter(booleanSelections)
elifconfigurable=="syst":
groupJsonParser.add_argument("--"+arg, help="", action="store", type=str, metavar="\b").completer=ChoicesCompleter(collisionSystemSelections)
elifconfigurable=="doVertexZeq":
groupJsonParser.add_argument("--"+arg, help="", action="store", type=str, metavar="\b").completer=ChoicesCompleter(binarySelection)
elifconfigurable.startswith("pid-") orconfigurable.startswith("est"):
groupJsonParser.add_argument("--"+arg, help="", action="store", nargs="*", type=str, metavar="\b").completer=ChoicesCompleterList(tripletSelection)
elifconfigurable=="muonSelection":
groupJsonParser.add_argument("--"+arg, help="", action="store", type=str, metavar="\b").completer=ChoicesCompleter(eventMuonSelections)
elifconfigurable=="itsMatching":
groupJsonParser.add_argument("--"+arg, help="", action="store", type=str, metavar="\b").completer=ChoicesCompleter(itsMatchingSelections)
elifconfigurable=="compatibilityIU":
groupJsonParser.add_argument("--"+arg, help="", action="store", type=str.lower, metavar="\b").completer=ChoicesCompleter(booleanSelections)
else:
groupJsonParser.add_argument("--"+arg, help="", action="store", type=str, metavar="\b") # Has no autocompletionargcomplete.autocomplete(self.parser, always_complete_options=False)
self.parser.parse_args()To avoid confusion here the autocomplete conditions are splitted for the DQ framework and the code for the common framework. Conditions in common framework are full hardcoded, conditions in DQ framework are semi hardcoded.
Another important point is that if the argument takes more than one parameter, nargs = "*" should be given as a parameter to the parser argument and the ChoicesCompleterList function should be used. If the argument can take a single parameter, then nargs should not be given as a parameter and the ChoicesCompleter function should be used. For ex.
ifcontainsCuts: # YOU CAN DEFINE MORE THAN ONE CUTS AS PARAMETERgroupJsonParser.add_argument("--"+arg, help="", action="store", nargs="*", type=str, metavar="\b").completer=ChoicesCompleterList(allAnalysisCuts)
elifcontainsProcess: # YOU CAN ONLY DEFINE ONE PARAMETER AS true OR false for process FunctionsgroupJsonParser.add_argument("--"+arg, help="", action="store", type=str.lower, metavar="\b").completer=ChoicesCompleter(booleanSelections)The arguments required to include converter tasks in the workflow are defined as hardcoded in the SetArgsToArgumentParser class in the configSetter.py script in the extramodules folder:
# Converter Task OptionsgroupO2Converters=self.parser.add_argument_group(title=f"Add to workflow O2 Converter task options")
groupO2Converters.add_argument("--add_mc_conv", help="Add the converter from mcparticle to mcparticle+001 (Adds your workflow o2-analysis-mc-converter task)", action="store_true",)
groupO2Converters.add_argument("--add_fdd_conv", help="Add the fdd converter (Adds your workflow o2-analysis-fdd-converter task)", action="store_true",)
groupO2Converters.add_argument("--add_track_prop", help="Add track propagation to the innermost layer (TPC or ITS) (Adds your workflow o2-analysis-track-propagation task)", action="store_true",)
groupO2Converters.add_argument("--add_weakdecay_ind", help="Add Converts V0 and cascade version 000 to 001 (Adds your workflow o2-analysis-weak-decay-indices task)", action="store_true",)
groupO2Converters.add_argument("--add_col_conv", help="Add the converter from collision to collision+001", action="store_true")
(booleanSelections)
# YOU CAN ADD NEW O2 CONVERTER TASK HEREhere you can add the new argument similarly. Then, to set these arguments, a hashmap in the form of argument - o2-analysis-|taskname| was created in the setConverter function in the configSetter.py script. It will be enough to add the converter task argument you just added here.
defsetConverters(allArgs: dict, updatedConfigFileName: str, commandToRun: str) ->str:
specificTasks= {
"add_mc_conv": "o2-analysis-mc-converter",
"add_fdd_conv": "o2-analysis-fdd-converter",
"add_track_prop": "o2-analysis-track-propagation",
"add_weakdecay_ind": "o2-analysis-weak-decay-indices",
"add_col_conv": "o2-analysis-collision-converter"# Add Your O2 converter task key-value pair to here
}
forcliArg, cliValueinallArgs.items():
forconverterArg, taskNameinspecificTasks.items():
ifconverterArg==cliArgandcliValueisTrue:
logging.debug(taskName+" added your workflow")
commandToRun+= (" | "+taskName+" --configuration json://"+updatedConfigFileName+" -b")
returncommandToRun- Folders: All lowercase
- Class: Upper camelcase
- Function: Lower camelcase
- Variables: Lower camelcase
- Constants: Screaming camelcase
- O2 converter arguments: Snake case
← Go back to Instructions For Tutorials | ↑ Go to the Table of Content ↑ | Continue to TroubleshootingTreeNotFound →