test
CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
SpecificationBuilder_cfi.py
Go to the documentation of this file.
1 import FWCore.ParameterSet.Config as cms
2 from copy import deepcopy
3 
4 # this is a pure Python module to build the deeply nested PSets that describe a
5 # SummationSpecification.
6 # The C++ code assumes the form is fully correct, so you should always use this,
7 # which outputs a valid form.
8 
9 # these need to stay in sync with the C++ enums. TODO: Can we use Python3 enum or sth.?
10 NO_TYPE = cms.int32(0)
11 GROUPBY = cms.int32(1) # only "SUM", real histograms
12 EXTEND_X = cms.int32(2) # use geometry column as coordinate axis, concatenate
13 EXTEND_Y = cms.int32(3)
14 COUNT = cms.int32(4) # drop all values, only count entries. Atm only step1.
15 REDUCE = cms.int32(5) # histogram-to-scalar operator for harvesting, atm only MEAN
16 SAVE = cms.int32(6) # atm not used in execution. Marks stage1/2 switch.
17 CUSTOM = cms.int32(7) # call callback in harvesting
18 USE_X = cms.int32(8) # use arg-th fill(...) parameter for the respective axis.
19 USE_Y = cms.int32(9)
20 USE_Z = cms.int32(10)
21 PROFILE = cms.int32(11) # marker for step1 to make a profile, related to REDUCE(MEAN)
22 
23 NO_STAGE = cms.int32(0)
24 FIRST = cms.int32(1) # first grouping, before and/or after counting
25 STAGE1 = cms.int32(2) # USE/EXTEND/PROFILE for step1
26 STAGE2 = cms.int32(3) # REDUCE/EXTEND/GROUPBY/CUSTOM for harvesting
27 
28 def val(maybecms):
29  if hasattr(maybecms, "value"):
30  return maybecms.value()
31  else:
32  return maybecms
33 
34 def parent(path):
35  parts = val(path).split("/")
36  return "/".join(parts[0:len(parts)-1])
37 
38 # do not change values here, Pass in a PSet instead
39 DefaultConf = cms.PSet(enabled = cms.bool(True))
40 
41 
42 # The Specification format is very rigid and looks much less like a program in
43 # the internal form:
44 # - There is one entry FIRST, which is a GROUPBY(SUM) or COUNT and some columns
45 # - There is another entry FIRST, which is a GROUPBY(SUM) and some columns iff
46 # the one before was COUNT
47 # - There are some entries STAGE1
48 # - There is one entry per dimension (ordered)
49 # - which is either USE_* or EXTEND_*
50 # - with one column, that is usually NOT listed in first.
51 # - There is optionally an entry PROFILE to make a profile.
52 # - There are 0-n steps STAGE2, which are one of GROUPBY(SUM), EXTEND_X, CUSTOM
53 # - The argument for GROUPBY and EXTEND_X is a subset of columns of last step
54 # - CUSTOM may have an arbitrary argument that is simply passed down
55 # - SAVE is ignored
56 
57 class Specification(cms.PSet):
58  def __init__(self, conf = DefaultConf):
59  super(Specification, self).__init__()
60  self.spec = cms.VPSet()
61  self.conf = conf
62  self._activeColumns = set()
63  self._state = FIRST
64 
65  def __deepcopy__(self, memo):
66  # override deepcopy to not copy .conf: it should remain a reference
67  # w/o this it is not cleanly possible to build a per-module switch.
68  t = Specification(self.conf)
69  t.spec = deepcopy(self.spec, memo)
70  return t
71 
72  def groupBy(self, cols, mode = "SUM"):
73  cnames = val(cols).split("/")
74  newstate = self._state
75 
76  if self._state == FIRST:
77  cname = cnames
78  if mode != "SUM":
79  raise Exception("First grouping must be SUM")
80  if "Event" in cnames:
81  cnames.remove("Event"); # per-Event grouping is done automatically
82  t = COUNT
83  mode = "COUNT"
84  newstate = FIRST
85  else:
86  t = GROUPBY
87  newstate = STAGE1
88 
89  if self._state == STAGE1:
90  cname = self._activeColumns.difference(cnames)
91  if len(cname) != 1:
92  raise Exception("EXTEND must drop exactly one column.")
93 
94  if mode == "EXTEND_X":
95  self._x.type = EXTEND_X
96  self._x.columns = cms.vstring(cname)
97  elif mode == "EXTEND_Y":
98  self._y.type = EXTEND_Y
99  self._y.columns = cms.vstring(cname)
100  else:
101  raise Exception("Only EXTEND_X or EXTEND_Y allowed here, not " + mode)
102 
103  # remove the column in earlier steps, we always re-extract in step1.
104  c = list(cname)[0]
105  for s in self.spec:
106  if s.stage == FIRST and c in s.columns:
107  s.columns.remove(c)
108  if c in self._activeColumns:
109  self._activeColumns.remove(c)
110  if c in self._lastColumns:
111  self._lastColumns.remove(c)
112 
113  return self # done here, no new step to add
114 
115  if self._state == STAGE2:
116  cname = cnames
117  if self._activeColumns.issubset(cname):
118  raise Exception("Harvesting GROUPBY must drop some columns")
119  if mode == "EXTEND_X":
120  t = EXTEND_X
121  elif mode == "SUM":
122  t = GROUPBY
123  else:
124  raise Exception("Currently only EXTEND_X and SUM supported in harvesting, not " + mode)
125 
126  self._activeColumns = set(cnames)
127  self._lastColumns = cnames
128  self._lastMode = mode
129 
130  self.spec.append(cms.PSet(
131  type = t,
132  stage = self._state,
133  columns = cms.vstring(cname),
134  arg = cms.string(mode)
135  ))
136 
137  if newstate == STAGE1 and self._state == FIRST:
138  # emit standard column assignments, will be changed later
139  self._x = cms.PSet(
140  type = USE_X, stage = STAGE1,
141  columns = cms.vstring(),
142  arg = cms.string("")
143  )
144  self.spec.append(self._x)
145  self._y = cms.PSet(
146  type = USE_Y, stage = STAGE1,
147  columns = cms.vstring(),
148  arg = cms.string("")
149  )
150  self.spec.append(self._y)
151  self._z = cms.PSet(
152  type = USE_Z, stage = STAGE1,
153  columns = cms.vstring(),
154  arg = cms.string("")
155  )
156  self.spec.append(self._z)
157 
158  self._state = newstate
159 
160  return self
161 
162  def reduce(self, sort):
163  if self._state == FIRST:
164  if sort != "COUNT":
165  raise Exception("First statement must be groupBy.")
166  self.spec[0].type = COUNT # this is actually a noop
167  # groupBy already saw the "Event" column and set up counting.
168 
169  return self
170 
171  if self._state == STAGE1:
172  if sort == "MEAN":
173  self.spec.append(cms.PSet(
174  type = PROFILE, stage = STAGE1,
175  columns = cms.vstring(), arg = cms.string("")
176  ))
177  return self
178 
179  if sort != "MEAN":
180  raise Exception("Harvesting allows only reduce(MEAN) at the moment, not " + sort)
181 
182  self.spec.append(cms.PSet(
183  type = REDUCE,
184  stage = self._state,
185  columns = cms.vstring(),
186  arg = cms.string(sort)
187  ))
188  return self
189 
190  def save(self):
191  if self._state == FIRST:
192  raise Exception("First statement must be groupBy.")
193 
194  if self._state == STAGE1:
195  # end of STAGE1, fix the parameter assignments
196  n = 1
197  if self._x.type == USE_X: self._x.arg = cms.string(str(n)); n = n+1
198  if self._y.type == USE_Y: self._y.arg = cms.string(str(n)); n = n+1
199  if self._z.type == USE_Z: self._z.arg = cms.string(str(n)); n = n+1
200  # we don't know how many parameters the user wants to pass here, but the
201  # HistogramManager knows. So we just add 3.
202 
203  # SAVE is implicit in step1 and ignored in harvesting, so not really needed.
204  #self.spec.append(cms.PSet(
205  # type = SAVE,
206  # stage = self._state,
207  # columns = cms.vstring(),
208  # arg = cms.string("")
209  #))
210  self._state = STAGE2
211  return self
212 
213  def custom(self, arg = ""):
214  if self._state != STAGE2:
215  raise Exception("Custom processing exists only in Harvesting.")
216  self.spec.append(cms.PSet(
217  type = CUSTOM,
218  stage = self._state,
219  columns = cms.vstring(),
220  arg = cms.string(arg)
221  ))
222  return self
223 
224 
225  def saveAll(self):
226  self.save()
227  columns = self._lastColumns
228  for i in range(len(columns)-1, 0, -1):
229  cols = columns[0:i]
230  self.groupBy("/".join(cols), self._lastMode)
231  self.save()
232  return self
233 
234  # this is used for serialization, and for that this is just a PSet.
235  def pythonTypeName(self):
236  return 'cms.PSet';
static std::string join(char **cmd)
Definition: RemoteFile.cc:18
double split
Definition: MVATrainer.cc:139
How EventSelector::AcceptEvent() decides whether to accept an event for output otherwise it is excluding the probing of A single or multiple positive and the trigger will pass if any such matching triggers are PASS or EXCEPTION[A criterion thatmatches no triggers at all is detected and causes a throw.] A single negative with an expectation of appropriate bit checking in the decision and the trigger will pass if any such matching triggers are FAIL or EXCEPTION A wildcarded negative criterion that matches more than one trigger in the trigger list("!*","!HLTx*"if it matches 2 triggers or more) will accept the event if all the matching triggers are FAIL.It will reject the event if any of the triggers are PASS or EXCEPTION(this matches the behavior of"!*"before the partial wildcard feature was incorporated).Triggers which are in the READY state are completely ignored.(READY should never be returned since the trigger paths have been run