Loading [MathJax]/extensions/tex2jax.js
ATLAS Offline Software
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
Public Member Functions | Static Public Member Functions | Public Attributes | Static Public Attributes | List of all members
LVL1CaloMonitoringConfig.L1CaloMonitorCfgHelper Class Reference
Inheritance diagram for LVL1CaloMonitoringConfig.L1CaloMonitorCfgHelper:
Collaboration diagram for LVL1CaloMonitoringConfig.L1CaloMonitorCfgHelper:

Public Member Functions

def __init__ (self, flags, algClassOrObj=None, name=None, *args, **kwargs)
 
def defineDQAlgorithm (self, name, hanConfig, thresholdConfig=None)
 
def defineHistogram (self, *args, fillGroup=None, hanConfig={}, paths=[], **kwargs)
 
def defineTree (self, *args, fillGroup=None, **kwargs)
 
def result (self)
 

Static Public Member Functions

def createXmls ()
 
def printHanConfig (filename="collisions_run.config")
 

Public Attributes

 helper
 
 alg
 
 fillGroups
 
 dqEnv
 

Static Public Attributes

 hanConfigs
 
 hanAlgConfigs
 
 hanThresholdConfigs
 
 xmlConfigs
 
 SIGNATURES
 
 HELPURL
 

Detailed Description

This class is designed to handle registering all of L1Calo's monitoring histograms and trees in a
coherent way. It will also generate the han config file for all the histograms.

Definition at line 5 of file LVL1CaloMonitoringConfig.py.

Constructor & Destructor Documentation

◆ __init__()

def LVL1CaloMonitoringConfig.L1CaloMonitorCfgHelper.__init__ (   self,
  flags,
  algClassOrObj = None,
  name = None,
args,
**  kwargs 
)
Create the configuration helper.

Arguments:
flags -- the configuration flag object
algClassOrObj -- the name you want to assign the family of algorithms

Definition at line 205 of file LVL1CaloMonitoringConfig.py.

205  def __init__(self, flags, algClassOrObj = None, name = None, *args, **kwargs):
206  '''
207  Create the configuration helper.
208 
209  Arguments:
210  flags -- the configuration flag object
211  algClassOrObj -- the name you want to assign the family of algorithms
212  '''
213  from AthenaMonitoring import AthMonitorCfgHelper
214  self.helper = AthMonitorCfgHelper(flags,name)
215  self.alg = self.helper.addAlgorithm(algClassOrObj,name,*args, **kwargs) if algClassOrObj is not None else None
216  self.fillGroups = {}
217  self.dqEnv = flags.DQ.Environment # used to decide if should defineTree or not ...
218 

Member Function Documentation

◆ createXmls()

def LVL1CaloMonitoringConfig.L1CaloMonitorCfgHelper.createXmls ( )
static

Definition at line 24 of file LVL1CaloMonitoringConfig.py.

24  def createXmls():
25  # First create the DQAlgorithm config file
26  import config
27  db = config.Configuration()
28  db.create_db("l1calo_gen_phase1.data.xml",["daq/schema/dqm.schema.xml","daq/sw/dqm-algorithms.data.xml","daq/sw/repository.data.xml","daq/sw/dqm-default-streams.data.xml"])
29 
30  # first ensure all the algorithms exist
31  for confName,conf in L1CaloMonitorCfgHelper.hanAlgConfigs.items():
32  # only need algorithms for Shifter histograms
33  algUsed = False
34  for histPath,value in L1CaloMonitorCfgHelper.xmlConfigs.items():
35  if value.get("algorithm","") == confName:
36  algUsed = True
37  break
38  if not algUsed: continue
39  updated = False
40  try:
41  dqAlgo = db.get_dal("DQAlgorithm",conf["name"])
42  except RuntimeError:
43  # algorithm doesn't exist, create it ...
44  updated=True
45  db.create_obj("DQAlgorithm",conf["name"])
46  dqAlgo = db.get_dal("DQAlgorithm",conf["name"])
47  dqAlgo.LibraryName = conf["libname"]
48  # ensure all parameters appear in ParametersNames, and thresholds in ThresholdsNames
49  for par,val in conf.items():
50  if par=="thresholds" and val in L1CaloMonitorCfgHelper.hanThresholdConfigs:
51  for thresh,vals in L1CaloMonitorCfgHelper.hanThresholdConfigs[val].items():
52  if thresh not in dqAlgo.ThresholdsNames:
53  updated=True
54  dqAlgo.ThresholdsNames += [thresh]
55  elif par not in ["name","libname","thresholds"]+dqAlgo.ParametersNames:
56  updated=True
57  dqAlgo.ParametersNames += [par]
58  if updated:
59  db.update_dal(dqAlgo)
60 
61 
62  # now create DQParameter object for each histogram with a DQ algorithm
63  # need to have them all in a DQRegion that belongs to a DQLayout
64  db.create_obj("DQShape","L1CaloShapeDeveloper")
65  db.create_obj("DQLayout","L1CaloLayoutDeveloper")
66  db.create_obj("DQRegion","L1CaloRegionDeveloper")
67  dqLayout = db.get_dal("DQLayout","L1CaloLayoutDeveloper")
68  dqLayout.DefaultChildrenShape = db.get_dal("DQShape","L1CaloShapeDeveloper")
69  db.update_dal(dqLayout)
70  dqRegion = db.get_dal("DQRegion","L1CaloRegionDeveloper")
71  dqRegion.Description = "L1Calo Monitoring Development Folder"
72  dqRegion.Label = "Developer"
73  dqRegion.DQLayout = dqLayout
74  dqRegion.DQSummaryMaker = db.get_dal("DQSummaryMaker","WorstCaseSummary")
75 
76  for histPath,value in L1CaloMonitorCfgHelper.xmlConfigs.items():
77  if "algorithm" not in value.keys(): continue # only add histograms that have an algorithm
78 
79  name = "_".join(histPath.split("/"))
80  db.create_obj("DQParameter",name)
81  dqPar = db.get_dal("DQParameter",name)
82  dqPar.InputDataSource = ["Histogramming.l1calo-athenaHLT-Phase1./"+histPath]
83  dqPar.Description = value["description"]
84 
85  if value["algorithm"] in L1CaloMonitorCfgHelper.hanAlgConfigs:
86  algConf = L1CaloMonitorCfgHelper.hanAlgConfigs[value["algorithm"]]
87  dqPar.DQAlgorithm = db.get_dal("DQAlgorithm",algConf["name"])
88  for par,val in algConf.items():
89  if par in dqPar.DQAlgorithm.ParametersNames:
90  dqPar.Parameters += [f"{par}={val}"]
91  if "thresholds" in algConf:
92  for thresh,vals in L1CaloMonitorCfgHelper.hanThresholdConfigs[algConf["thresholds"]].items():
93  dqPar.GreenThresholds += [f"{thresh}={vals['warning']}"]
94  dqPar.RedThresholds += [f"{thresh}={vals['error']}"]
95  else:
96  dqPar.DQAlgorithm = db.get_dal("DQAlgorithm",value["algorithm"]) # catches cases of e.g. predefined parameterless alg like Histogram_Empty
97 
98  dqRegion.DQParameters += [dqPar]
99  db.update_dal(dqPar)
100 
101  db.update_dal(dqRegion)
102  db.commit("Autogenerated")
103 
104 

◆ defineDQAlgorithm()

def LVL1CaloMonitoringConfig.L1CaloMonitorCfgHelper.defineDQAlgorithm (   self,
  name,
  hanConfig,
  thresholdConfig = None 
)
:param name: name of algorithm
:param hanConfig: dict of algo properties
:param thresholdConfig: dict of thresholds, keys in form of ParName.level
:return:

Definition at line 219 of file LVL1CaloMonitoringConfig.py.

219  def defineDQAlgorithm(self,name,hanConfig,thresholdConfig=None):
220 
221  """
222 
223  :param name: name of algorithm
224  :param hanConfig: dict of algo properties
225  :param thresholdConfig: dict of thresholds, keys in form of ParName.level
226  :return:
227  """
228 
229  # note: this method will replace any existing alg definition
230 
231  #thresNum = len(self.hanThresholdConfigs)
232  if thresholdConfig is not None:
233  hanConfig["thresholds"] = f"{name}Thresholds"
234  threshDict = {}
235  for parName,limVals in thresholdConfig.items():
236  if len(limVals) != 2:
237  raise Exception("must specify two limits: warning and error")
238  if parName not in threshDict: threshDict[parName] = {}
239  threshDict[parName]["warning"] = limVals[0]
240  threshDict[parName]["error"] = limVals[1]
241  # see if any existing thresholds are identical, if so we can reuse
242  for threshName,thresh in self.hanThresholdConfigs.items():
243  if str(thresh)==str(threshDict):
244  threshDict = None
245  hanConfig["thresholds"] = threshName
246  break
247  if threshDict is not None: self.hanThresholdConfigs[hanConfig["thresholds"]] = threshDict
248  self.hanAlgConfigs[name] = hanConfig
249 
250  return
251 
252 

◆ defineHistogram()

def LVL1CaloMonitoringConfig.L1CaloMonitorCfgHelper.defineHistogram (   self,
args,
  fillGroup = None,
  hanConfig = {},
  paths = [],
**  kwargs 
)
:param path:
:param fillGroup:
:param args:
:param kwargs:
:return:

Definition at line 253 of file LVL1CaloMonitoringConfig.py.

253  def defineHistogram(self,*args,fillGroup=None,hanConfig={},paths=[],**kwargs):
254  '''
255 
256  :param path:
257  :param fillGroup:
258  :param args:
259  :param kwargs:
260  :return:
261  '''
262 
263  hanConfig = dict(hanConfig) # create a copy since will modify below (otherwise we end up modifying the default empty dict)
264 
265  if paths != []:
266  for path in paths:
267  # create a copy of the histogram in each of the extra locations
268  self.defineHistogram(*args,fillGroup=fillGroup,hanConfig=hanConfig,paths=[],path=path,**kwargs)
269  return None
270 
271  argsCopy = list(args) # need to convert tuple to list to convert it
272  if ";" not in args[0]:
273  argsCopy[0] += ";h_" + argsCopy[0].replace(":","_")
274 
275  if kwargs.get("path",None) is None:
276  # put in the Developer path, under the name of the algorithm
277  kwargs["path"] = "Developer/" + self.alg.name
278  elif kwargs["path"][-1] == '/':
279  kwargs["path"] = kwargs["path"][:-1] # strip trailing slash
280  # verify path obeys convention
281  splitPath = kwargs["path"].split("/")
282  if splitPath[0] not in ["Shifter","Expert","Developer"]:
283  raise Exception("Path of histogram invalid, does not start with one of the allowed audiences (Shifter,Expert,Developer)")
284 
285  # don't bother registering Shifter plots in tier0 ... only needed in p1 and user environments
286  if splitPath[0]=="Shifter" and self.dqEnv == 'tier0':
287  return None
288 
289  # require a hanConfig not in Developer or a detail dir
290  if splitPath[0] != "Developer" and splitPath[-1] != "detail" and ("algorithm" not in hanConfig):
291  # will default to using GatherData as long as there is a description
292  if "description" not in hanConfig:
293  raise Exception("Must specify a hanConfig for a Shifter or Expert (non-detail) histogram")
294  else:
295  hanConfig["algorithm"] = "GatherData" # must have an algo, otherwise wont be valid han config
296  elif "algorithm" in hanConfig and hanConfig["algorithm"] not in self.hanAlgConfigs and hanConfig["algorithm"] not in ["All_Bins_Filled","Histogram_Effective_Empty","Histogram_Empty","Histogram_Not_Empty","No_OverFlows","No_UnderFlows"]:
297  # if algorithm specified, must have been defined
298  raise Exception(f'DQ Algorithm {hanConfig["algorithm"]} for histogram {args[0]} not defined. Please use defineDQAlgorithm method to define it')
299 
300 
301  if fillGroup is None: fillGroup = self.alg.name + "_fillGroup"
302  if fillGroup not in self.fillGroups:
303  self.fillGroups[fillGroup] = self.helper.addGroup(self.alg,fillGroup,topPath="L1Calo")
304 
305 
306  if "merge" not in kwargs and kwargs.get("type","") !="TEfficiency":
307  kwargs["merge"] = "merge" # ensures we don't get a warning about not specifying merge method
308  out = self.fillGroups[fillGroup].defineHistogram(*argsCopy,**kwargs)
309  histName = argsCopy[0].split(";")[-1]
310 
311  # add help link for all expert plots
312  if splitPath[0] == "Expert":
313  linkUrl = self.HELPURL + "#" + "".join(splitPath[1:]+[histName])
314  linkUrl = f"<a href=\"{linkUrl}\">Help</a>"
315  if "description" not in hanConfig: hanConfig["description"] = linkUrl
316  else: hanConfig["description"] += " - " + linkUrl
317 
318  # only add to hanConfig if in Expert or Developer folder
319  if splitPath[0] == "Expert" or splitPath[0] == "Developer":
320  if "description" in hanConfig and hanConfig["description"]=="":
321  del hanConfig["description"]
322  splitPathWithHist = splitPath + [histName]
323  x = L1CaloMonitorCfgHelper.hanConfigs
324  for i,p in enumerate(splitPathWithHist):
325  key = ("dir " if i!=len(splitPathWithHist)-1 else "hist ") + p
326  if key not in x:
327  x[key] = {}
328  x = x[key]
329  hanConfig["output"] = "/".join(["L1Calo"]+splitPath)
330  x.update(hanConfig)
331  elif splitPath[0] == "Shifter": # record shifter histograms in another map, for generating xmls
332  L1CaloMonitorCfgHelper.xmlConfigs["/".join(["L1Calo"]+splitPath+[histName])] = {}
333  L1CaloMonitorCfgHelper.xmlConfigs["/".join(["L1Calo"]+splitPath+[histName])].update(hanConfig) # copy in the config
334 
335  return out
336 

◆ defineTree()

def LVL1CaloMonitoringConfig.L1CaloMonitorCfgHelper.defineTree (   self,
args,
  fillGroup = None,
**  kwargs 
)

Definition at line 337 of file LVL1CaloMonitoringConfig.py.

337  def defineTree(self,*args,fillGroup=None,**kwargs):
338 
339  if ";" not in args[0]:
340  raise Exception("Must specify a tree name using ';name' suffix")
341  treeName = args[0].split(";")[-1]
342 
343  if "," in args[1]: # catch a subtle typo that can screw up monitoring
344  raise Exception("Should not have comma in list of branch names and types")
345 
346  if kwargs.get("path",None) is None:
347  # put in the Developer path, under the name of the algorithm
348  kwargs["path"] = "Developer/" + self.alg.name
349 
350  # verify path obeys convention
351  splitPath = kwargs["path"].split("/")
352  if splitPath[0] not in ["Developer"]:
353  raise Exception("Path of tree invalid, must be in the audience=Developer directory")
354 
355 
356  if fillGroup is None: fillGroup = self.alg.name + "_fillGroup"
357  if fillGroup not in self.fillGroups:
358  self.fillGroups[fillGroup] = self.helper.addGroup(self.alg,fillGroup,topPath="L1Calo")
359 
360  # always define a histogram to go with the tree, which will indicate how many entries there are
361  # this also ensures we satisfy the requirement that every fillGroup has an object defined
362  # (in the cases of running online/tier0 the defineTrees are blocked, but we still need a hist then)
363  histName = "h_" + treeName + "_entries"
364  argsCopy = list(args)
365  argsCopy[0] = argsCopy[0].replace(";"+treeName,";"+histName)
366  kwargsCopy = dict(kwargs)
367  kwargsCopy["title"] = f"Number of Entries in {treeName} TTree" + ";" + ";".join(kwargsCopy.get("title","").split(";")[1:])
368  kwargsCopy["opt"] = ['kCanRebin','kAddBinsDynamically','kAlwaysCreate']
369  kwargsCopy["merge"] = "merge"
370  is2d = (kwargsCopy["title"].count(";")>1)
371  self.defineHistogram(argsCopy[0],type="TH2I" if is2d else "TH1I",xbins=1,xmin=0,xmax=1,ybins=1 if is2d else None,ymin=0,ymax=1,fillGroup=fillGroup,**kwargsCopy)
372  if not any([x in self.dqEnv for x in ['tier0','online']]):
373  out = self.fillGroups[fillGroup].defineTree(*args,**kwargs)
374  else:
375  out = None
376  return out
377 

◆ printHanConfig()

def LVL1CaloMonitoringConfig.L1CaloMonitorCfgHelper.printHanConfig (   filename = "collisions_run.config")
static

Definition at line 106 of file LVL1CaloMonitoringConfig.py.

106  def printHanConfig(filename="collisions_run.config"):
107  L1CaloMonitorCfgHelper.createXmls()
108  from contextlib import redirect_stdout
109  from PathResolver import PathResolver
110  header = PathResolver.FindCalibFile("TrigT1CaloMonitoring/hanConfig_header.txt")
111  with open(filename,'w') as f:
112  # copy the header if we have one
113  if header != "":
114  with open(header,'r') as fh:
115  for line in fh: f.write(line)
116  with redirect_stdout(f):
117  # Note: common configs (see common dir in DataQualityConfiguration) provides following algorithms by default:
118  # algorithm All_Bins_Filled
119  # algorithm Histogram_Effective_Empty
120  # algorithm Histogram_Empty
121  # algorithm Histogram_Not_Empty
122  # algorithm No_OverFlows
123  # algorithm No_UnderFlows
124 
125  outputs = set()
126  def printConf(d,prefix=""):
127  for key,value in d.items():
128  if type(value)==dict:
129  print(prefix,key,"{")
130  if(key=="dir detail" or key=="dir Developer"):
131  print(prefix+" algorithm = GatherData") # define GatherData as default algo for all of these hists
132  if key.startswith("dir ") and any([x.startswith("hist ") for x in value.keys()]):
133  # this is a dir with hists, so specify output as the path .. take from the first hist child
134  for childKey,childVal in value.items():
135  if childKey.startswith("hist ") and "output" in childVal:
136  print(prefix+" output = "+childVal["output"])
137  break
138  printConf(value,prefix + " ")
139  print(prefix,"}")
140  else:
141  # save all output paths to add to output block (don't need to print here b.c. specified at dir level
142  if key == "output": outputs.add(value)
143  else: print(prefix,key,"=",value)
144 
145 
146  print("#inputs")
147  print("dir L1Calo {")
148  printConf(L1CaloMonitorCfgHelper.hanConfigs," ")
149  print("}")
150  print("#outputs")
151  print("output top_level {")
152  def printOutputs(d,prefix=""):
153  for key,value in d.items():
154  if(key.startswith("hist ")):
155  pass # do nothing
156  elif type(value)==dict:
157  print(prefix,key.replace("dir ","output "),"{")
158  if key=="dir Developer": print(prefix," algorithm = L1Calo_AlwaysUndefinedSummary")
159  printOutputs(value,prefix + " ")
160  print(prefix,"}")
161  print(" output L1Calo {")
162  printOutputs(L1CaloMonitorCfgHelper.hanConfigs," ")
163  print(" }")
164  print("}")
165  # include example of adding algorithms and thresholds
166  print("""
167 #algorithms
168 algorithm AnyNonZeroBinIsError {
169  # Use this algo if want error on any non-zero bin content
170  libname = libdqm_summaries.so
171  name = Bins_NotEqual_Threshold
172  BinThreshold = 0.
173  thresholds = th_AnyBinIsError
174 }
175 algorithm L1Calo_AlwaysUndefinedSummary {
176  libname = libdqm_summaries.so
177  name = AlwaysUndefinedSummary
178 }
179 """)
180  for algName,algProps in L1CaloMonitorCfgHelper.hanAlgConfigs.items():
181  print(f"algorithm {algName} {{")
182  for propName,propVal in algProps.items():
183  print(f" {propName} = {propVal}")
184  print(" }")
185  print("""
186 #thresholds
187 thresholds th_AnyBinIsError {
188  limits NBins {
189  warning = 0
190  error = 1
191  }
192 }
193 """)
194  for threshName,threshProps in L1CaloMonitorCfgHelper.hanThresholdConfigs.items():
195  print(f"thresholds {threshName} {{")
196  for parName,parLims in threshProps.items():
197  print(f" limits {parName} {{")
198  for limName,limVal in parLims.items():
199  print(f" {limName} = {limVal}")
200  print(" }")
201  print("}")
202 
203 
204 

◆ result()

def LVL1CaloMonitoringConfig.L1CaloMonitorCfgHelper.result (   self)

Definition at line 378 of file LVL1CaloMonitoringConfig.py.

378  def result(self):
379  return self.helper.result()
380 
381 

Member Data Documentation

◆ alg

LVL1CaloMonitoringConfig.L1CaloMonitorCfgHelper.alg

Definition at line 215 of file LVL1CaloMonitoringConfig.py.

◆ dqEnv

LVL1CaloMonitoringConfig.L1CaloMonitorCfgHelper.dqEnv

Definition at line 217 of file LVL1CaloMonitoringConfig.py.

◆ fillGroups

LVL1CaloMonitoringConfig.L1CaloMonitorCfgHelper.fillGroups

Definition at line 216 of file LVL1CaloMonitoringConfig.py.

◆ hanAlgConfigs

LVL1CaloMonitoringConfig.L1CaloMonitorCfgHelper.hanAlgConfigs
static

Definition at line 16 of file LVL1CaloMonitoringConfig.py.

◆ hanConfigs

LVL1CaloMonitoringConfig.L1CaloMonitorCfgHelper.hanConfigs
static

Definition at line 15 of file LVL1CaloMonitoringConfig.py.

◆ hanThresholdConfigs

LVL1CaloMonitoringConfig.L1CaloMonitorCfgHelper.hanThresholdConfigs
static

Definition at line 17 of file LVL1CaloMonitoringConfig.py.

◆ helper

LVL1CaloMonitoringConfig.L1CaloMonitorCfgHelper.helper

Definition at line 214 of file LVL1CaloMonitoringConfig.py.

◆ HELPURL

LVL1CaloMonitoringConfig.L1CaloMonitorCfgHelper.HELPURL
static

Definition at line 21 of file LVL1CaloMonitoringConfig.py.

◆ SIGNATURES

LVL1CaloMonitoringConfig.L1CaloMonitorCfgHelper.SIGNATURES
static

Definition at line 20 of file LVL1CaloMonitoringConfig.py.

◆ xmlConfigs

LVL1CaloMonitoringConfig.L1CaloMonitorCfgHelper.xmlConfigs
static

Definition at line 18 of file LVL1CaloMonitoringConfig.py.


The documentation for this class was generated from the following file:
replace
std::string replace(std::string s, const std::string &s2, const std::string &s3)
Definition: hcg.cxx:307
PathResolver::FindCalibFile
static std::string FindCalibFile(const std::string &logical_file_name)
Definition: PathResolver.h:108
get_generator_info.result
result
Definition: get_generator_info.py:21
XMLtoHeader.count
count
Definition: XMLtoHeader.py:85
histSizes.list
def list(name, path='/')
Definition: histSizes.py:38
CxxUtils::set
constexpr std::enable_if_t< is_bitmask_v< E >, E & > set(E &lhs, E rhs)
Convenience function to set bits in a class enum bitmask.
Definition: bitmask.h:232
print
void print(char *figname, TCanvas *c1)
Definition: TRTCalib_StrawStatusPlots.cxx:25
TCS::join
std::string join(const std::vector< std::string > &v, const char c=',')
Definition: Trigger/TrigT1/L1Topo/L1TopoCommon/Root/StringUtils.cxx:10
TrigJetMonitorAlgorithm.items
items
Definition: TrigJetMonitorAlgorithm.py:71
python.processes.powheg.ZZ.ZZ.__init__
def __init__(self, base_directory, **kwargs)
Constructor: all process options are set here.
Definition: ZZ.py:18
Trk::open
@ open
Definition: BinningType.h:40
LVL1CaloMonitoringConfig.type
type
Definition: LVL1CaloMonitoringConfig.py:539
GenericMonitoringTool.defineTree
def defineTree(flags, varname, treedef, path=None, title=None, opt='', convention=None, cutmask=None)
Generate tree definition string for the GenericMonitoringTool.Histograms property.
Definition: GenericMonitoringTool.py:491
GenericMonitoringTool.defineHistogram
def defineHistogram(flags, varname, type='TH1F', path=None, title=None, weight=None, xbins=100, xmin=0, xmax=1, xlabels=None, ybins=None, ymin=None, ymax=None, ylabels=None, zmin=None, zmax=None, zlabels=None, opt=None, convention=None, cutmask=None, treedef=None, merge=None)
Generate histogram definition string for the GenericMonitoringTool.Histograms property.
Definition: GenericMonitoringTool.py:306
if
if(febId1==febId2)
Definition: LArRodBlockPhysicsV0.cxx:567
str
Definition: BTagTrackIpAccessor.cxx:11
Trk::split
@ split
Definition: LayerMaterialProperties.h:38