Merge lp:~maddevelopers/mg5amcnlo/controlswitch into lp:~mg5core1/mg5amcnlo/2.5.6
- controlswitch
- Merge into 2.5.6
Status: | Superseded |
---|---|
Proposed branch: | lp:~maddevelopers/mg5amcnlo/controlswitch |
Merge into: | lp:~mg5core1/mg5amcnlo/2.5.6 |
Diff against target: |
1767 lines (+1113/-488) 3 files modified
madgraph/interface/amcatnlo_run_interface.py (+295/-186) madgraph/interface/extended_cmd.py (+481/-27) madgraph/interface/madevent_interface.py (+337/-275) |
To merge this branch: | bzr merge lp:~maddevelopers/mg5amcnlo/controlswitch |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Rikkert Frederix | Pending | ||
marco zaro | Pending | ||
Valentin Hirschi | Pending | ||
Review via email: mp+329031@code.launchpad.net |
This proposal has been superseded by a proposal from 2017-08-17.
Commit message
Description of the change
Hi,
This branch refactor the code on how to ask to the user which code to run.
The idea is to have dedicated class for that to ease the possibility to edit such crucial
part of the interface via plugin method.
For that reason, this code use highly modular method and factorise the different step in a quite deep way. This makes the new code much longer than the equivalent one that it replaces.
For the user point of view the change are actually quite minimal:
1) Change the description to fit on 80 char shell.
2) Change question presentation @NLO to match the one already present @LO
3) New method for the gestion of conflict:
- The previous user value is not overwritten directly anymore
- The conflicted value is now set in red and the "replacement" value is set after an arrow
- This allows to allow to use the cycle trough options without creating annoying side effects
4) The cycle trough option is now available for all options
5) the user can now set multiple switch with a single line (need to be separated by ";")
This should not be part of 2.5.6/2.6.0 but rather part of 2.6.1, at the same time,
I would like to have it merged in 2.6.1 as soon as possible such that we have plenty of time to discover potential side effects/error in the conflict handling.
- 324. By olivier-mattelaer
-
remove print statement
Rikkert Frederix (frederix) wrote : | # |
Olivier Mattelaer (olivier-mattelaer) wrote : | # |
Hi Rik,
Yes, but since that branch was not yet released, this was the only branch available in order to have a nice diff. As said in my comment, this was not intended to be merged in 2.5.6.
As soon as the branch 2.6.1 will be pushed, I will change the target.
Cheers,
Olivier
- 325. By olivier-mattelaer
-
improve question displayed -- adapt to the screen size--
- 326. By olivier-mattelaer
-
improve the display of the conflict with striketrough instead of yellow color
- 327. By olivier-mattelaer
-
longer striketrough to increase visibility
- 328. By olivier-mattelaer
-
fix problem when some program are not installed + allowed 1=PY8
- 329. By olivier-mattelaer
-
fix some displayed problem pointed by Stefano when some program are not available
- 330. By olivier-mattelaer
-
fix problem with script and command not accepted due to the missing;
- 331. By olivier-mattelaer
-
first change related to Valentin review
- 332. By olivier-mattelaer
-
allow to choose the shower before the edition of the card
- 333. By olivier-mattelaer
-
improvment associated to the PS choice
- 334. By olivier-mattelaer
-
improve the handling of scripting method.
- 335. By olivier-mattelaer
-
merge with latest 2.6.1
- 336. By olivier-mattelaer
-
fixing problem revealed by test suite
- 337. By olivier-mattelaer
-
merge with latest 2.6.1
Unmerged revisions
- 337. By olivier-mattelaer
-
merge with latest 2.6.1
- 336. By olivier-mattelaer
-
fixing problem revealed by test suite
- 335. By olivier-mattelaer
-
merge with latest 2.6.1
- 334. By olivier-mattelaer
-
improve the handling of scripting method.
- 333. By olivier-mattelaer
-
improvment associated to the PS choice
- 332. By olivier-mattelaer
-
allow to choose the shower before the edition of the card
- 331. By olivier-mattelaer
-
first change related to Valentin review
- 330. By olivier-mattelaer
-
fix problem with script and command not accepted due to the missing;
- 329. By olivier-mattelaer
-
fix some displayed problem pointed by Stefano when some program are not available
- 328. By olivier-mattelaer
-
fix problem when some program are not installed + allowed 1=PY8
Preview Diff
1 | === modified file 'madgraph/interface/amcatnlo_run_interface.py' |
2 | --- madgraph/interface/amcatnlo_run_interface.py 2017-08-10 13:09:28 +0000 |
3 | +++ madgraph/interface/amcatnlo_run_interface.py 2017-08-15 12:03:07 +0000 |
4 | @@ -907,6 +907,274 @@ |
5 | class aMCatNLOAlreadyRunning(InvalidCmd): |
6 | pass |
7 | |
8 | +class AskRunNLO(cmd.ControlSwitch): |
9 | + |
10 | + to_control = [('order', 'Type of perturbative computation'), |
11 | + ('fixed_order', 'No MC@[N]LO matching / event generation'), |
12 | + ('shower', 'Shower the generated events'), |
13 | + ('madspin', 'Decay onshell particles'), |
14 | + ('reweight', 'Add weights to events for new hypp.'), |
15 | + ('madanalysis','Run MadAnalysis5 on the events generated')] |
16 | + |
17 | + quit_on = cmd.ControlSwitch.quit_on + ['onlyshower'] |
18 | + |
19 | + def __init__(self, question, line_args=[], mode=None, force=False, |
20 | + *args, **opt): |
21 | + |
22 | + self.check_available_module(opt['mother_interface'].options) |
23 | + self.me_dir = opt['mother_interface'].me_dir |
24 | + self.last_mode = opt['mother_interface'].last_mode |
25 | + misc.sprint(self.last_mode) |
26 | + self.proc_characteristics = opt['mother_interface'].proc_characteristics |
27 | + super(AskRunNLO,self).__init__(self.to_control, opt['mother_interface'], |
28 | + *args, **opt) |
29 | + |
30 | + def check_available_module(self, options): |
31 | + |
32 | + self.available_module = set() |
33 | + if options['madanalysis5_path']: |
34 | + self.available_module.add('MA5') |
35 | + if not aMCatNLO or ('mg5_path' in options and options['mg5_path']): |
36 | + self.available_module.add('MadSpin') |
37 | + if misc.has_f2py() or self.mother_interface.options['f2py_compiler']: |
38 | + self.available_module.add('reweight') |
39 | +# |
40 | +# shorcut |
41 | +# |
42 | + def ans_lo(self, value): |
43 | + |
44 | + if value is None: |
45 | + self.switch['order'] = 'LO' |
46 | + self.switch['fixed_order'] = 'ON' |
47 | + self.set_switch('shower', 'OFF') |
48 | + else: |
49 | + logger.warning('Invalid command: lo=%s' % value) |
50 | + |
51 | + def ans_nlo(self, value): |
52 | + if value is None: |
53 | + self.switch['order'] = 'NLO' |
54 | + self.switch['fixed_order'] = 'ON' |
55 | + self.set_switch('shower', 'OFF') |
56 | + else: |
57 | + logger.warning('Invalid command: nlo=%s' % value) |
58 | + |
59 | + def ans_amc__at__nlo(self, value): |
60 | + if value is None: |
61 | + self.switch['order'] = 'NLO' |
62 | + self.switch['fixed_order'] = 'OFF' |
63 | + self.set_switch('shower', 'ON') |
64 | + else: |
65 | + logger.warning('Invalid command: aMC@NLO=%s' % value) |
66 | + |
67 | + def ans_amc__at__lo(self, value): |
68 | + if value is None: |
69 | + self.switch['order'] = 'LO' |
70 | + self.switch['fixed_order'] = 'OFF' |
71 | + self.set_switch('shower', 'ON') |
72 | + else: |
73 | + logger.warning('Invalid command: aMC@LO=%s' % value) |
74 | + |
75 | + def ans_noshower(self, value): |
76 | + if value is None: |
77 | + self.switch['order'] = 'NLO' |
78 | + self.switch['fixed_order'] = 'OFF' |
79 | + self.set_switch('shower', 'OFF') |
80 | + else: |
81 | + logger.warning('Invalid command: noshower=%s' % value) |
82 | + |
83 | + def ans_onlyshower(self, value): |
84 | + if value is None: |
85 | + self.switch['mode'] = 'onlyshower' |
86 | + self.switch['madspin'] = 'OFF' |
87 | + self.switch['reweight'] = 'OFF' |
88 | + else: |
89 | + logger.warning('Invalid command: onlyshower=%s' % value) |
90 | + |
91 | + def ans_noshowerlo(self, value): |
92 | + if value is None: |
93 | + self.switch['order'] = 'LO' |
94 | + self.switch['fixed_order'] = 'OFF' |
95 | + self.set_switch('shower', 'OFF') |
96 | + else: |
97 | + logger.warning('Invalid command: noshowerlo=%s' % value) |
98 | + |
99 | + def ans_madanalysis5(self, value): |
100 | + """ shortcut madanalysis5 -> madanalysis """ |
101 | + |
102 | + if value is None: |
103 | + return self.onecmd('madanalysis') |
104 | + else: |
105 | + self.set_switch('madanalysis', value) |
106 | +# |
107 | +# ORDER |
108 | +# |
109 | + def get_allowed_order(self): |
110 | + return ["LO", "NLO"] |
111 | + |
112 | + def set_default_order(self): |
113 | + |
114 | + if self.last_mode in ['LO', 'aMC@L0', 'noshowerLO']: |
115 | + self.switch['order'] = 'LO' |
116 | + self.switch['order'] = 'NLO' |
117 | + |
118 | + def set_switch_off_order(self): |
119 | + return |
120 | +# |
121 | +# Fix order |
122 | +# |
123 | + def get_allowed_fixed_order(self): |
124 | + """ """ |
125 | + if self.proc_characteristics['ninitial'] == 1: |
126 | + return ['ON'] |
127 | + else: |
128 | + return ['ON', 'OFF'] |
129 | + |
130 | + def set_default_fixed_order(self): |
131 | + |
132 | + if self.last_mode in ['LO', 'NLO']: |
133 | + self.switch['fixed_order'] = 'ON' |
134 | + self.switch['fixed_order'] = 'OFF' |
135 | + |
136 | + def color_for_fixed_order(self, switch_value): |
137 | + |
138 | + if switch_value in ['OFF']: |
139 | + return self.green % switch_value |
140 | + else: |
141 | + return self.red % switch_value |
142 | + |
143 | + def consistency_fixed_order_shower(self, vfix, vshower): |
144 | + """ consistency_XX_YY(val_XX, val_YY) |
145 | + -> XX is the new key set by the user to a new value val_XX |
146 | + -> YY is another key set by the user. |
147 | + -> return value should be None or "replace_YY" |
148 | + """ |
149 | + |
150 | + if vfix == 'ON' and vshower != 'OFF' : |
151 | + return 'OFF' |
152 | + return None |
153 | + |
154 | + consistency_fixed_order_madspin = consistency_fixed_order_shower |
155 | + consistency_fixed_order_reweight = consistency_fixed_order_shower |
156 | + |
157 | + def consistency_fixed_order_madanalysis(self, vfix, vma5): |
158 | + |
159 | + if vfix == 'ON' and vma5 == 'ON' : |
160 | + return 'OFF' |
161 | + return None |
162 | + |
163 | + |
164 | + def consistency_shower_fixed_order(self, vshower, vfix): |
165 | + """ consistency_XX_YY(val_XX, val_YY) |
166 | + -> XX is the new key set by the user to a new value val_XX |
167 | + -> YY is another key set by the user. |
168 | + -> return value should be None or "replace_YY" |
169 | + """ |
170 | + |
171 | + if vshower == 'ON' and vfix == 'ON': |
172 | + return 'OFF' |
173 | + return None |
174 | + |
175 | + consistency_madspin_fixed_order = consistency_shower_fixed_order |
176 | + consistency_reweight_fixed_order = consistency_shower_fixed_order |
177 | + consistency_madanalysis_fixed_order = consistency_shower_fixed_order |
178 | + |
179 | +# |
180 | +# Shower |
181 | +# |
182 | + def get_allowed_shower(self): |
183 | + """ """ |
184 | + if self.proc_characteristics['ninitial'] == 1: |
185 | + return ['OFF'] |
186 | + else: |
187 | + return ['ON', 'OFF'] |
188 | + |
189 | + def set_default_shower(self): |
190 | + |
191 | + if self.last_mode in ['LO', 'NLO', 'noshower', 'noshowerLO']: |
192 | + self.switch['shower'] = 'OFF' |
193 | + return |
194 | + |
195 | + if os.path.exists(pjoin(self.me_dir, 'Cards', 'shower_card.dat')): |
196 | + self.switch['shower'] = 'ON' |
197 | + self.switch['fixed_order'] = "OFF" |
198 | + else: |
199 | + self.switch['shower'] = 'OFF' |
200 | + |
201 | + def consistency_shower_madanalysis(self, vshower, vma5): |
202 | + """ MA5 only possible with (N)LO+PS if shower is run""" |
203 | + |
204 | + if vshower == 'OFF' and vma5 == 'ON': |
205 | + return 'OFF' |
206 | + return None |
207 | + |
208 | + def consistency_madanalysis_sower(self, vma5, vshower): |
209 | + |
210 | + if vma5=='ON' and vshower =='OFF': |
211 | + return 'ON' |
212 | + return None |
213 | + |
214 | +# |
215 | +# madspin |
216 | +# |
217 | + def get_allowed_madspin(self): |
218 | + """ """ |
219 | + if self.proc_characteristics['ninitial'] == 1: |
220 | + return ['OFF'] |
221 | + else: |
222 | + return ['ON', 'OFF'] |
223 | + |
224 | + def set_default_madspin(self): |
225 | + |
226 | + if 'MadSpin' in self.available_module: |
227 | + if os.path.exists(pjoin(self.me_dir,'Cards','madspin_card.dat')): |
228 | + self.switch['madspin'] = 'ON' |
229 | + else: |
230 | + self.switch['madspin'] = 'OFF' |
231 | + else: |
232 | + self.switch['madspin'] = 'Not Avail.' |
233 | + |
234 | + |
235 | +# |
236 | +# reweight |
237 | +# |
238 | + get_allowed_reweight = get_allowed_madspin |
239 | + |
240 | + def set_default_reweight(self): |
241 | + """initialise the switch for reweight""" |
242 | + |
243 | + if 'reweight' in self.available_module: |
244 | + if os.path.exists(pjoin(self.me_dir,'Cards','reweight_card.dat')): |
245 | + self.switch['reweight'] = 'ON' |
246 | + else: |
247 | + self.switch['reweight'] = 'OFF' |
248 | + else: |
249 | + self.switch['reweight'] = 'Not Avail.' |
250 | +# |
251 | +# MadAnalysis5 |
252 | +# |
253 | + get_allowed_madanalysis = get_allowed_madspin |
254 | + |
255 | + def set_default_madanalysis(self): |
256 | + """initialise the switch for reweight""" |
257 | + |
258 | + if 'MA5' not in self.available_module: |
259 | + self.switch['madanalysis'] = 'Not Avail.' |
260 | + elif os.path.exists(pjoin(self.me_dir,'Cards', 'madanalysis5_hadron_card.dat')): |
261 | + self.switch['madanalysis'] = 'ON' |
262 | + else: |
263 | + self.switch['madanalysis'] = 'OFF' |
264 | + |
265 | + def check_value_madanalysis(self, value): |
266 | + """check an entry is valid. return the valid entry in case of shortcut""" |
267 | + |
268 | + if value.upper() in self.get_allowed('madanalysis'): |
269 | + return True |
270 | + value = value.lower() |
271 | + if value == 'hadron': |
272 | + return 'ON' if 'ON' in self.get_allowed_madanalysis5 else False |
273 | + else: |
274 | + return False |
275 | + |
276 | #=============================================================================== |
277 | # aMCatNLOCmd |
278 | #=============================================================================== |
279 | @@ -4826,7 +5094,7 @@ |
280 | return model |
281 | |
282 | |
283 | - |
284 | + action_switcher = AskRunNLO |
285 | ############################################################################ |
286 | def ask_run_configuration(self, mode, options, switch={}): |
287 | """Ask the question when launching generate_events/multi_run""" |
288 | @@ -4836,194 +5104,35 @@ |
289 | if 'reweightonly' not in options: |
290 | options['reweightonly'] = False |
291 | |
292 | - |
293 | - void = 'Not installed' |
294 | - switch_order = ['order', 'fixed_order', 'shower','madspin', 'reweight','madanalysis5'] |
295 | - switch_default = {'order': 'NLO', 'fixed_order': 'OFF', 'shower': void, |
296 | - 'madspin': void,'reweight':'OFF','madanalysis5':void} |
297 | - if not switch: |
298 | - switch = switch_default |
299 | - else: |
300 | - switch.update(dict((k,value) for k,v in switch_default.items() if k not in switch)) |
301 | - default_switch = ['ON', 'OFF'] |
302 | - |
303 | - |
304 | - allowed_switch_value = {'order': ['LO', 'NLO'], |
305 | - 'fixed_order': default_switch, |
306 | - 'shower': default_switch, |
307 | - 'madspin': default_switch, |
308 | - 'reweight': default_switch, |
309 | - 'madanalysis5':['OFF','HADRON']} |
310 | - |
311 | - if not os.path.exists(pjoin(self.me_dir, 'Cards', |
312 | - 'madanalysis5_hadron_card_default.dat')): |
313 | - allowed_switch_value['madanalysis5']=[] |
314 | - |
315 | - description = {'order': 'Perturbative order of the calculation:', |
316 | - 'fixed_order': 'Fixed order (no event generation and no MC@[N]LO matching):', |
317 | - 'shower': 'Shower the generated events:', |
318 | - 'madspin': 'Decay particles with the MadSpin module:', |
319 | - 'reweight': 'Add weights to the events based on changing model parameters:', |
320 | - 'madanalysis5':'Run MadAnalysis5 on the events generated:'} |
321 | - |
322 | - force_switch = {('shower', 'ON'): {'fixed_order': 'OFF'}, |
323 | - ('madspin', 'ON'): {'fixed_order':'OFF'}, |
324 | - ('reweight', 'ON'): {'fixed_order':'OFF'}, |
325 | - ('fixed_order', 'ON'): {'shower': 'OFF', 'madspin': 'OFF', 'reweight':'OFF','madanalysis5':'OFF'}, |
326 | - ('madanalysis5','HADRON'): {'shower': 'ON','fixed_order':'OFF'}, |
327 | - ('shower','OFF'): {'madanalysis5': 'OFF'}, |
328 | - } |
329 | - special_values = ['LO', 'NLO', 'aMC@NLO', 'aMC@LO', 'noshower', 'noshowerLO'] |
330 | - |
331 | - assign_switch = lambda key, value: switch.__setitem__(key, value if switch[key] != void else void ) |
332 | - |
333 | - if self.proc_characteristics['ninitial'] == 1: |
334 | - switch['fixed_order'] = 'ON' |
335 | - switch['shower'] = 'Not available for decay' |
336 | - switch['madspin'] = 'Not available for decay' |
337 | - switch['reweight'] = 'Not available for decay' |
338 | - switch['madanalysis5'] = 'Not available for decay' |
339 | - allowed_switch_value['fixed_order'] = ['ON'] |
340 | - allowed_switch_value['shower'] = ['OFF'] |
341 | - allowed_switch_value['madspin'] = ['OFF'] |
342 | - allowed_switch_value['reweight'] = ['OFF'] |
343 | - allowed_switch_value['madanalysis5'] = ['OFF'] |
344 | - available_mode = ['0','1'] |
345 | - special_values = ['LO', 'NLO'] |
346 | - else: |
347 | - # Init the switch value according to the current status |
348 | - available_mode = ['0', '1', '2','3'] |
349 | - |
350 | if mode == 'auto': |
351 | mode = None |
352 | if not mode and (options['parton'] or options['reweightonly']): |
353 | - mode = 'noshower' |
354 | - |
355 | - |
356 | - if '3' in available_mode: |
357 | - if os.path.exists(pjoin(self.me_dir, 'Cards', 'shower_card.dat')): |
358 | - switch['shower'] = 'ON' |
359 | - else: |
360 | - switch['shower'] = 'OFF' |
361 | - if os.path.exists(pjoin(self.me_dir, 'Cards', 'madanalysis5_hadron_card_default.dat')): |
362 | - available_mode.append('6') |
363 | - if os.path.exists(pjoin(self.me_dir, 'Cards', 'madanalysis5_hadron_card.dat')): |
364 | - switch['madanalysis5'] = 'HADRON' |
365 | - else: |
366 | - switch['madanalysis5'] = 'OFF' |
367 | - |
368 | - if (not aMCatNLO or self.options['mg5_path']) and '3' in available_mode: |
369 | - available_mode.append('4') |
370 | - if os.path.exists(pjoin(self.me_dir,'Cards','madspin_card.dat')): |
371 | - switch['madspin'] = 'ON' |
372 | - else: |
373 | - switch['madspin'] = 'OFF' |
374 | - if misc.has_f2py() or self.options['f2py_compiler']: |
375 | - available_mode.append('5') |
376 | - if os.path.exists(pjoin(self.me_dir,'Cards','reweight_card.dat')): |
377 | - switch['reweight'] = 'ON' |
378 | - else: |
379 | - switch['reweight'] = 'OFF' |
380 | - else: |
381 | - switch['reweight'] = 'Not available (requires NumPy)' |
382 | - |
383 | - if 'do_reweight' in options and options['do_reweight'] and '3' in available_mode: |
384 | - if switch['reweight'] == "OFF": |
385 | - switch['reweight'] = "ON" |
386 | - elif switch['reweight'] != "ON": |
387 | - logger.critical("Cannot run REWEIGHT: %s" % switch['reweight']) |
388 | + mode = 'noshower' |
389 | + |
390 | + passing_cmd = [] |
391 | + for key,value in switch.keys(): |
392 | + passing_cmd.append('%s=%s' % (key,value)) |
393 | + |
394 | + if 'do_reweight' in options and options['do_reweight']: |
395 | + passing_cmd.append('reweight=ON') |
396 | if 'do_madspin' in options and options['do_madspin']: |
397 | - if switch['madspin'] == "OFF": |
398 | - switch['madspin'] = 'ON' |
399 | - elif switch['madspin'] != "ON": |
400 | - logger.critical("Cannot run MadSpin module: %s" % switch['reweight']) |
401 | - |
402 | - answers = list(available_mode) + ['auto', 'done'] |
403 | - alias = {} |
404 | - for id, key in enumerate(switch_order): |
405 | - if switch[key] != void and switch[key] in allowed_switch_value[key] and \ |
406 | - len(allowed_switch_value[key])>1: |
407 | - answers += ['%s=%s' % (key, s) for s in allowed_switch_value[key]] |
408 | - #allow lower case for on/off |
409 | - alias.update(dict(('%s=%s' % (key, s.lower()), '%s=%s' % (key, s)) |
410 | - for s in allowed_switch_value[key])) |
411 | - answers += special_values |
412 | - |
413 | - def create_question(switch): |
414 | - switch_format = " %i %-61s %12s=%s\n" |
415 | - question = "The following switches determine which operations are executed:\n" |
416 | - for id, key in enumerate(switch_order): |
417 | - question += switch_format % (id+1, description[key], key, switch[key]) |
418 | - question += ' Either type the switch number (1 to %s) to change its default setting,\n' % (id+1) |
419 | - question += ' or set any switch explicitly (e.g. type \'order=LO\' at the prompt)\n' |
420 | - question += ' Type \'0\', \'auto\', \'done\' or just press enter when you are done.\n' |
421 | - return question |
422 | - |
423 | - |
424 | - def modify_switch(mode, answer, switch): |
425 | - if '=' in answer: |
426 | - key, status = answer.split('=') |
427 | - switch[key] = status |
428 | - if (key, status) in force_switch: |
429 | - for key2, status2 in force_switch[(key, status)].items(): |
430 | - if switch[key2] not in [status2, void]: |
431 | - logger.info('For coherence \'%s\' is set to \'%s\'' |
432 | - % (key2, status2), '$MG:color:BLACK') |
433 | - switch[key2] = status2 |
434 | - elif answer in ['0', 'auto', 'done']: |
435 | - return |
436 | - elif answer in special_values: |
437 | - logger.info('Enter mode value: %s. Go to the related mode' % answer, '$MG:color:BLACK') |
438 | - #assign_switch('reweight', 'OFF') |
439 | - #assign_switch('madspin', 'OFF') |
440 | - if answer == 'LO': |
441 | - switch['order'] = 'LO' |
442 | - switch['fixed_order'] = 'ON' |
443 | - assign_switch('shower', 'OFF') |
444 | - elif answer == 'NLO': |
445 | - switch['order'] = 'NLO' |
446 | - switch['fixed_order'] = 'ON' |
447 | - assign_switch('shower', 'OFF') |
448 | - elif answer == 'aMC@NLO': |
449 | - switch['order'] = 'NLO' |
450 | - switch['fixed_order'] = 'OFF' |
451 | - assign_switch('shower', 'ON') |
452 | - elif answer == 'aMC@LO': |
453 | - switch['order'] = 'LO' |
454 | - switch['fixed_order'] = 'OFF' |
455 | - assign_switch('shower', 'ON') |
456 | - elif answer == 'noshower': |
457 | - switch['order'] = 'NLO' |
458 | - switch['fixed_order'] = 'OFF' |
459 | - assign_switch('shower', 'OFF') |
460 | - elif answer == 'noshowerLO': |
461 | - switch['order'] = 'LO' |
462 | - switch['fixed_order'] = 'OFF' |
463 | - assign_switch('shower', 'OFF') |
464 | - if mode: |
465 | - return |
466 | - return switch |
467 | - |
468 | - modify_switch(mode, self.last_mode, switch) |
469 | - if switch['madspin'] == 'OFF' and os.path.exists(pjoin(self.me_dir,'Cards','madspin_card.dat')): |
470 | - assign_switch('madspin', 'ON') |
471 | - |
472 | - if not self.force: |
473 | - answer = '' |
474 | - while answer not in ['0', 'done', 'auto', 'onlyshower']: |
475 | - question = create_question(switch) |
476 | - if mode: |
477 | - answer = mode |
478 | - else: |
479 | - answer = self.ask(question, '0', answers, alias=alias) |
480 | - if answer.isdigit() and answer != '0': |
481 | - key = switch_order[int(answer) - 1] |
482 | - opt1 = allowed_switch_value[key][0] |
483 | - opt2 = allowed_switch_value[key][1] |
484 | - answer = '%s=%s' % (key, opt1 if switch[key] == opt2 else opt2) |
485 | - |
486 | - if not modify_switch(mode, answer, switch): |
487 | - break |
488 | + passing_cmd.append('madspin=ON') |
489 | + |
490 | + force = self.force |
491 | + if mode == 'onlyshower': |
492 | + passing_cmd.append('onlyshower') |
493 | + force = True |
494 | + elif mode: |
495 | + passing_cmd.append(mode) |
496 | + |
497 | + switch = self.ask('', '0', [], ask_class = self.action_switcher, |
498 | + mode=mode, force=force, |
499 | + first_cmd=passing_cmd) |
500 | + |
501 | + misc.sprint(switch) |
502 | + |
503 | + if 'mode' in switch: |
504 | + mode = switch['mode'] |
505 | |
506 | #assign the mode depending of the switch |
507 | if not mode or mode == 'auto': |
508 | @@ -5060,7 +5169,7 @@ |
509 | cards.append('madspin_card.dat') |
510 | if switch['reweight'] == 'ON': |
511 | cards.append('reweight_card.dat') |
512 | - if switch['madanalysis5'] == 'HADRON': |
513 | + if switch['madanalysis'] == 'HADRON': |
514 | cards.append('madanalysis5_hadron_card.dat') |
515 | if 'aMC@' in mode: |
516 | cards.append('shower_card.dat') |
517 | |
518 | === modified file 'madgraph/interface/extended_cmd.py' |
519 | --- madgraph/interface/extended_cmd.py 2017-08-04 20:30:41 +0000 |
520 | +++ madgraph/interface/extended_cmd.py 2017-08-15 12:03:07 +0000 |
521 | @@ -1041,7 +1041,7 @@ |
522 | #=============================================================================== |
523 | def ask(self, question, default, choices=[], path_msg=None, |
524 | timeout = True, fct_timeout=None, ask_class=None, alias={}, |
525 | - first_cmd=None, text_format='4', **opt): |
526 | + first_cmd=None, text_format='4', force=False, **opt): |
527 | """ ask a question with some pre-define possibility |
528 | path info is |
529 | """ |
530 | @@ -1082,6 +1082,7 @@ |
531 | if alias: |
532 | choices += alias.keys() |
533 | |
534 | + |
535 | question_instance = obj(question, allow_arg=choices, default=default, |
536 | mother_interface=self, **opt) |
537 | |
538 | @@ -1095,26 +1096,30 @@ |
539 | if hasattr(obj, "haspiping"): |
540 | obj.haspiping = self.haspiping |
541 | |
542 | - |
543 | - |
544 | - |
545 | - answer = self.check_answer_in_input_file(question_instance, default, path_msg) |
546 | - if answer is not None: |
547 | - if answer in alias: |
548 | - answer = alias[answer] |
549 | - if ask_class: |
550 | - line=answer |
551 | - answer = question_instance.default(line) |
552 | - question_instance.postcmd(answer, line) |
553 | - return question_instance.answer |
554 | - if hasattr(question_instance, 'check_answer_consistency'): |
555 | - question_instance.check_answer_consistency() |
556 | - return answer |
557 | + if not force: |
558 | + answer = default |
559 | + else: |
560 | + |
561 | + answer = self.check_answer_in_input_file(question_instance, default, path_msg) |
562 | + if answer is not None: |
563 | + if answer in alias: |
564 | + answer = alias[answer] |
565 | + if ask_class: |
566 | + line=answer |
567 | + answer = question_instance.default(line) |
568 | + question_instance.postcmd(answer, line) |
569 | + return question_instance.answer |
570 | + if hasattr(question_instance, 'check_answer_consistency'): |
571 | + question_instance.check_answer_consistency() |
572 | + return answer |
573 | |
574 | question = question_instance.question |
575 | - value = Cmd.timed_input(question, default, timeout=timeout, |
576 | + if not force: |
577 | + value = Cmd.timed_input(question, default, timeout=timeout, |
578 | fct=question_instance, fct_timeout=fct_timeout) |
579 | - |
580 | + else: |
581 | + value = default |
582 | + |
583 | try: |
584 | if value in alias: |
585 | value = alias[value] |
586 | @@ -1123,6 +1128,7 @@ |
587 | |
588 | if value == default and ask_class: |
589 | value = question_instance.default(default) |
590 | + |
591 | return value |
592 | |
593 | def do_import(self, line): |
594 | @@ -2014,7 +2020,7 @@ |
595 | try: |
596 | out = {} |
597 | out[' Options'] = Cmd.list_completion(text, self.allow_arg) |
598 | - out[' Recognized command'] = BasicCmd.completenames(self, text) |
599 | + out[' Recognized command'] = super(SmartQuestion, self).completenames(text,line, *ignored) |
600 | |
601 | return self.deal_multiple_categories(out) |
602 | except Exception, error: |
603 | @@ -2067,10 +2073,7 @@ |
604 | if prev_timer: |
605 | if pat.search(self.question): |
606 | timeout = int(pat.search(self.question).groups()[0]) |
607 | - else: |
608 | - timeout=20 |
609 | |
610 | - signal.alarm(timeout) |
611 | + signal.alarm(timeout) |
612 | if reprint_opt: |
613 | if not prev_timer: |
614 | self.question = pat.sub('',self.question) |
615 | @@ -2139,7 +2142,7 @@ |
616 | return True |
617 | elif line and hasattr(self, 'do_%s' % line.split()[0]): |
618 | return self.reask() |
619 | - elif self.value == 'repeat': |
620 | + elif self.value in ['repeat', 'reask']: |
621 | return self.reask() |
622 | elif len(self.allow_arg)==0: |
623 | return True |
624 | @@ -2202,7 +2205,7 @@ |
625 | out = {} |
626 | out[' Options'] = Cmd.list_completion(text, self.allow_arg) |
627 | out[' Path from ./'] = Cmd.path_completion(text, only_dirs = False) |
628 | - out[' Recognized command'] = BasicCmd.completenames(self, text) |
629 | + out[' Recognized command'] = BasicCmd.completenames(self, text, line, begidx, endidx) |
630 | |
631 | return self.deal_multiple_categories(out, formatting) |
632 | except Exception, error: |
633 | @@ -2231,8 +2234,9 @@ |
634 | |
635 | return Cmd.path_completion(text, |
636 | os.path.join('.',*[a for a in args \ |
637 | - if a.endswith(os.path.sep)])) |
638 | - self.completenames(line+text) |
639 | + if a.endswith(os.path.sep)]), |
640 | + begidx, endidx) |
641 | + return self.completenames(text, line, begidx, endidx) |
642 | |
643 | |
644 | def postcmd(self, stop, line): |
645 | @@ -2267,6 +2271,456 @@ |
646 | obj = OneLinePathCompletion(allow_arg=allow_arg, default=default ) |
647 | return obj.cmdloop() |
648 | |
649 | + |
650 | + |
651 | +class ControlSwitch(SmartQuestion): |
652 | + """A class for asking a question on which program to run. |
653 | + This is the abstract class |
654 | + |
655 | + Behavior for each switch can be customize via: |
656 | + set_default_XXXX() -> set default value |
657 | + get_allowed_XXXX() -> return list of possible value |
658 | + check_value_XXXX(value) -> return True/False if the user can set such value |
659 | + switch_off_XXXXX() -> set if off (called for special mode) |
660 | + color_for_XXXX(value) -> return the representation on the screen for value |
661 | + |
662 | + consistency_XX_YY(val_XX, val_YY) |
663 | + -> XX is the new key set by the user to a new value val_XX |
664 | + -> YY is another key set by the user. |
665 | + -> return value should be None or "replace_YY" |
666 | + |
667 | + consistency_XX(val_XX): |
668 | + check the consistency of the other switch given the new status of this one. |
669 | + return a dict {key:replaced_value} or {} if nothing to do |
670 | + |
671 | + user typing "NAME" will result to a call to self.ans_NAME(None) |
672 | + user typing "NAME=XX" will result to a call to self.ans_NAME('XX') |
673 | + |
674 | + Note on case sensitivity: |
675 | + ------------------------- |
676 | + the XXX is displayed with the case in self.to_control |
677 | + but ALL functions should use the lower case version. |
678 | + for key associated to get_allowed_keys(), |
679 | + if (user) value not in that list. |
680 | + -> try to find the first entry matching up to the case |
681 | + for ans_XXX, set the value to lower case, but if case_XXX is set to True |
682 | + """ |
683 | + |
684 | + line_length = 80 |
685 | + case_sensitive = False |
686 | + quit_on = ['0','done', 'EOF','','auto'] |
687 | + |
688 | + def __init__(self, to_control, motherinstance, *args, **opts): |
689 | + """to_control is a list of ('KEY': 'Choose the shower/hadronization program') |
690 | + """ |
691 | + |
692 | + self.to_control = to_control |
693 | + self.mother_interface = motherinstance |
694 | + self.inconsistent_keys = {} #flag parameter which are currently not consistent |
695 | + # and the value by witch they will be replaced if the |
696 | + # inconsistency remains. |
697 | + self.inconsistent_details = {} # flag to list |
698 | + self.last_changed = [] # keep the order in which the flag have been modified |
699 | + # to choose the resolution order of conflict |
700 | + #initialise the main return value |
701 | + self.switch = {} |
702 | + for key, _ in to_control: |
703 | + self.switch[key.lower()] = 'temporary' |
704 | + |
705 | + self.set_default_switch() |
706 | + question = self.create_question() |
707 | + |
708 | + #check all default for auto-completion |
709 | + allowed_args = [ `i`+';' for i in range(1, 1+len(self.to_control))] |
710 | + for key in self.switch: |
711 | + allowed_args += ['%s=%s;' % (key,s) for s in self.get_allowed(key)] |
712 | + # adding special mode |
713 | + allowed_args += [key[4:]+';' for key in dir(self) if key.startswith('ans_')] |
714 | + if 'allow_arg' in opts: |
715 | + allowed_args += opts['allow_arg'] |
716 | + del opts['allow_arg'] |
717 | + |
718 | + super(ControlSwitch, self).__init__(question, allowed_args, *args, **opts) |
719 | + self.options = self.mother_interface.options |
720 | + |
721 | + |
722 | + def set_default_switch(self): |
723 | + |
724 | + for key,_ in self.to_control: |
725 | + key = key.lower() |
726 | + if hasattr(self, 'set_default_%s' % key): |
727 | + getattr(self, 'set_default_%s' % key)() |
728 | + else: |
729 | + self.default_switch_for(key) |
730 | + |
731 | + def default_switch_for(self, key): |
732 | + """use this if they are no dedicated function for such key""" |
733 | + |
734 | + if hasattr(self, 'get_allowed_%s' % key): |
735 | + return getattr(self, 'get_allowed_%s' % key)()[0] |
736 | + else: |
737 | + self.switch[key] = 'OFF' |
738 | + |
739 | + def set_all_off(self): |
740 | + """set all valid parameter to OFF --call before special keyword-- |
741 | + """ |
742 | + |
743 | + for key in self.switch: |
744 | + if hasattr(self, 'switch_off_%s' % key): |
745 | + getattr(self, 'switch_off_%s' % key)() |
746 | + elif self.check_value(key, self.switch[key]): |
747 | + self.switch[key] = 'OFF' |
748 | + self.inconsistent_details = {} |
749 | + self.inconsistent_keys = {} |
750 | + |
751 | + |
752 | + def check_value(self, key, value): |
753 | + """return True/False if the value is a correct value to be set by the USER. |
754 | + other value than those can be set by the system --like-- Not available. |
755 | + This does not check the full consistency of the switch |
756 | + """ |
757 | + |
758 | + if hasattr(self, 'check_value_%s' % key): |
759 | + return getattr(self, 'check_value_%s' % key)(value) |
760 | + elif value in self.get_allowed(key): |
761 | + return True |
762 | + else: |
763 | + return False |
764 | + |
765 | + |
766 | + |
767 | + def get_allowed(self, key): |
768 | + """return the list of possible value for key""" |
769 | + |
770 | + if hasattr(self, 'get_allowed_%s' % key): |
771 | + return getattr(self, 'get_allowed_%s' % key)() |
772 | + else: |
773 | + return ['ON', 'OFF'] |
774 | + |
775 | + def default(self, line): |
776 | + """Default action if line is not recognized""" |
777 | + |
778 | + line=line.strip().replace('@', '__at__') |
779 | + if ';' in line: |
780 | + for l in line.split(';'): |
781 | + if l: |
782 | + out = self.default(l) |
783 | + return out |
784 | + |
785 | + if '=' in line: |
786 | + base, value = line.split('=') |
787 | + elif ' ' in line: |
788 | + base, value = line.split(' ', 1) |
789 | + elif hasattr(self, 'ans_%s' % line.lower()): |
790 | + base, value = line.lower(), None |
791 | + elif line.isdigit() and line in [`i` for i in range(1, len(self.switch)+1)]: |
792 | + # go from one valid option to the next in the get_allowed for that option |
793 | + base = self.to_control[int(line)-1][0].lower() |
794 | + return self.default(base) # just recall this function with the associate name |
795 | + elif line.lower() in self.switch: |
796 | + # go from one valid option to the next in the get_allowed for that option |
797 | + base = line.lower() |
798 | + try: |
799 | + cur = self.get_allowed(base).index(self.switch[base]) |
800 | + except: |
801 | + if self.get_allowed(base): |
802 | + value = self.get_allowed(base)[0] |
803 | + else: |
804 | + logger.warning('Can not switch "%s" to another value via number', base) |
805 | + self.value='reask' |
806 | + return |
807 | + else: |
808 | + try: |
809 | + value = self.get_allowed(base)[cur+1] |
810 | + except IndexError: |
811 | + value = self.get_allowed(base)[0] |
812 | + elif line in ['', 'done', 'EOF', 'eof','0']: |
813 | + super(ControlSwitch, self).default(line) |
814 | + return self.answer |
815 | + elif line in 'auto': |
816 | + self.switch['dynamical'] = True |
817 | + return super(ControlSwitch, self).default(line) |
818 | + else: |
819 | + logger.warning('unknow command: %s' % line) |
820 | + self.value = 'reask' |
821 | + return |
822 | + |
823 | + self.value = 'reask' |
824 | + base = base.lower() |
825 | + if hasattr(self, 'ans_%s' % base): |
826 | + if value and not self.is_case_sensitive(base): |
827 | + value = value.lower() |
828 | + getattr(self, 'ans_%s' % base)(value) |
829 | + elif base in self.switch: |
830 | + self.set_switch(base, value) |
831 | + else: |
832 | + logger.warning('Not valid command: %s' % line) |
833 | + |
834 | + def is_case_sensitive(self, key): |
835 | + """check if a key is case sensitive""" |
836 | + |
837 | + case = self.case_sensitive |
838 | + if hasattr(self, 'case_%s' % key): |
839 | + case = getattr(self, 'case_%s' % key) |
840 | + return case |
841 | + |
842 | + def onecmd(self, line, **opt): |
843 | + """ensure to rewrite the function if a call is done directly""" |
844 | + out = super(ControlSwitch, self).onecmd(line, **opt) |
845 | + self.create_question() |
846 | + return out |
847 | + |
848 | + @property |
849 | + def answer(self): |
850 | + if not self.inconsistent_keys: |
851 | + return self.switch |
852 | + else: |
853 | + out = dict(self.switch) |
854 | + out.update(self.inconsistent_keys) |
855 | + return out |
856 | + |
857 | + def postcmd(self, stop, line): |
858 | + |
859 | + line = line.strip() |
860 | + if ';' in line: |
861 | + line= [l for l in line.split(';') if l][-1] |
862 | + if line in self.quit_on: |
863 | + return True |
864 | + return self.reask(True) |
865 | + |
866 | + |
867 | + def set_switch(self, key, value, user=True): |
868 | + """change a switch to a given value""" |
869 | + |
870 | + assert key in self.switch |
871 | + |
872 | + |
873 | + |
874 | + if hasattr(self, 'ans_%s' % key): |
875 | + if not self.is_case_sensitive(key): |
876 | + value = value.lower() |
877 | + return getattr(self, 'ans_%s' % key)(value) |
878 | + |
879 | + if not self.is_case_sensitive(key) and value not in self.get_allowed(key): |
880 | + lower = [t.lower() for t in self.get_allowed(key)] |
881 | + try: |
882 | + ind = lower.index(value.lower()) |
883 | + except ValueError: |
884 | + pass # keep the current case, in case check_value accepts it anyway. |
885 | + else: |
886 | + value = self.get_allowed(key)[ind] |
887 | + |
888 | + check = self.check_value(key, value) |
889 | + if not check: |
890 | + logger.warning('"%s" not valid option for "%s"', value, key) |
891 | + return |
892 | + if isinstance(check, str): |
893 | + value = check |
894 | + |
895 | + self.switch[key] = value |
896 | + |
897 | + if user: |
898 | + self.check_consistency(key, value) |
899 | + |
900 | + def remove_inconsistency(self, keys=[]): |
901 | + |
902 | + if not keys: |
903 | + self.inconsistent_keys = {} |
904 | + self.inconsistent_details = {} |
905 | + elif isinstance(keys, list): |
906 | + for key in keys: |
907 | + if key in self.inconsistent_keys: |
908 | + del self.inconsistent_keys[keys] |
909 | + del self.inconsistent_details[keys] |
910 | + else: |
911 | + if keys in self.inconsistent_keys: |
912 | + del self.inconsistent_keys[keys] |
913 | + del self.inconsistent_details[keys] |
914 | + |
915 | + def check_consistency(self, key, value): |
916 | + """check the consistency of the new flag with the old ones""" |
917 | + |
918 | + if key in self.last_changed: |
919 | + self.last_changed.remove(key) |
920 | + self.last_changed.append(key) |
921 | + |
922 | + # this is used to update self.consistency_keys which contains: |
923 | + # {key: replacement value with solved conflict} |
924 | + # it is based on self.consistency_details which is a dict |
925 | + # key: {'orig_value': |
926 | + # 'changed_key': |
927 | + # 'new_changed_key_val': |
928 | + # 'replacement': |
929 | + # which keeps track of all conflict and of their origin. |
930 | + |
931 | + |
932 | + # rules is a dict: {keys:None} if the value for that key is consistent. |
933 | + # {keys:value_to_replace} if that key is inconsistent |
934 | + if hasattr(self, 'consistency_%s' % key): |
935 | + rules = dict([(key2, None) for key2 in self.switch]) |
936 | + rules.update(getattr(self, 'consistency_%s' % key)(value, self.switch)) |
937 | + else: |
938 | + rules = {} |
939 | + for key2,value2 in self.switch.items(): |
940 | + if hasattr(self, 'consistency_%s_%s' % (key,key2)): |
941 | + rules[key2] = getattr(self, 'consistency_%s_%s' % (key,key2))(value, value2) |
942 | + else: |
943 | + rules[key2] = None |
944 | + |
945 | + #update the self.inconsisten_details adding new conflict |
946 | + # start by removing the inconsistency for the newly set parameter |
947 | + self.remove_inconsistency(key) |
948 | + # then add the new ones |
949 | + for key2 in self.switch: |
950 | + if rules[key2]: |
951 | + info = {'orig_value': self.switch[key2], |
952 | + 'changed_key': key, |
953 | + 'new_changed_key_val': value, |
954 | + 'replacement': rules[key2]} |
955 | + if key2 in self.inconsistent_details: |
956 | + self.inconsistent_details[key2].append(info) |
957 | + else: |
958 | + self.inconsistent_details[key2] = [info] |
959 | + |
960 | + if not self.inconsistent_details: |
961 | + return |
962 | + |
963 | + # review the status of all conflict |
964 | + for key2 in dict(self.inconsistent_details): |
965 | + for conflict in list(self.inconsistent_details[key2]): |
966 | + keep_conflict = True |
967 | + # check that we are still at the current value |
968 | + if conflict['orig_value'] != self.switch[key2]: |
969 | + keep_conflict = False |
970 | + # check if the reason of the conflict still in place |
971 | + if self.switch[conflict['changed_key']] != conflict['new_changed_key_val']: |
972 | + keep_conflict = False |
973 | + if not keep_conflict: |
974 | + self.inconsistent_details[key2].remove(conflict) |
975 | + if not self.inconsistent_details[key2]: |
976 | + del self.inconsistent_details[key2] |
977 | + |
978 | + |
979 | + # create the valid set of replacement for this current conflict |
980 | + # start by current status to avoid to keep irrelevant conflict |
981 | + tmp_switch = dict(self.switch) |
982 | + |
983 | + # build the order in which we have to check the various conflict reported |
984 | + to_check = [(c['changed_key'], c['new_changed_key_val']) \ |
985 | + for k in self.inconsistent_details.values() for c in k |
986 | + if c['changed_key'] != key] |
987 | + |
988 | + to_check.sort(lambda x, y: -1 if self.last_changed.index(x[0])>self.last_changed.index(y[0]) else 1) |
989 | + |
990 | + # validate tmp_switch. |
991 | + to_check = [(key, value)] + to_check |
992 | + |
993 | + i = 0 |
994 | + while len(to_check) and i < 50: |
995 | + # check in a iterative way the consistency of the tmp_switch parameter |
996 | + i +=1 |
997 | + key2, value2 = to_check.pop(0) |
998 | + if hasattr(self, 'consistency_%s' % key2): |
999 | + rules2 = dict([(key2, None) for key2 in self.switch]) |
1000 | + rules2.update(getattr(self, 'consistency_%s' % key2)(value, tmp_switch)) |
1001 | + else: |
1002 | + rules = {} |
1003 | + for key3,value3 in self.switch.items(): |
1004 | + if hasattr(self, 'consistency_%s_%s' % (key2,key3)): |
1005 | + rules[key3] = getattr(self, 'consistency_%s_%s' % (key2,key3))(value2, value3) |
1006 | + else: |
1007 | + rules[key3] = None |
1008 | + |
1009 | + for key, replacement in rules.items(): |
1010 | + if replacement: |
1011 | + tmp_switch[key] = replacement |
1012 | + to_check.append((key, replacement)) |
1013 | + # avoid situation like |
1014 | + # to_check = [('fixed_order', 'ON'), ('fixed_order', 'OFF')] |
1015 | + # always keep the last one |
1016 | + pos = {} |
1017 | + for i, (key,value) in enumerate(to_check): |
1018 | + pos[key] = i |
1019 | + to_check_new = [] |
1020 | + for i, (key,value) in enumerate(to_check): |
1021 | + if pos[key] == i: |
1022 | + to_check_new.append((key,value)) |
1023 | + to_check = to_check_new |
1024 | + |
1025 | + # Now tmp_switch is to a fully consistent setup for sure. |
1026 | + # fill self.inconsistent_key |
1027 | + self.inconsistent_keys = {} |
1028 | + for key2, value2 in tmp_switch.items(): |
1029 | + if value2 != self.switch[key2]: |
1030 | + self.inconsistent_keys[key2] = value2 |
1031 | + |
1032 | + # |
1033 | + # Helper routine for putting questions with correct color |
1034 | + # |
1035 | + green = '\x1b[32m%s\x1b[0m' |
1036 | + bold = '\x1b[33m%s\x1b[0m' |
1037 | + red = '\x1b[31m%s\x1b[0m' |
1038 | + def color_for_value(self, key, switch_value): |
1039 | + |
1040 | + if key in self.inconsistent_keys: |
1041 | + return self.red % switch_value + '-> ' + self.bold % self.inconsistent_keys[key] |
1042 | + |
1043 | + if self.check_value(key, switch_value): |
1044 | + if hasattr(self, 'color_for_%s' % key): |
1045 | + return getattr(self, 'color_for_%s' % key)(switch_value) |
1046 | + if switch_value in ['OFF']: |
1047 | + # inconsistent key are the list of key which are inconsistent with the last change |
1048 | + return self.red % switch_value |
1049 | + else: |
1050 | + return self.green % switch_value |
1051 | + else: |
1052 | + if ' ' in switch_value: |
1053 | + return self.bold % switch_value |
1054 | + else: |
1055 | + return self.red % switch_value |
1056 | + |
1057 | + def create_question(self): |
1058 | + |
1059 | + text = \ |
1060 | + ["The following switches determine which programs are run:", |
1061 | + "/%s\\" % ("=" * (self.line_length-2)) |
1062 | + ] |
1063 | + |
1064 | + format = '| %2d. %{0}s %11s = %11s'.format(self.line_length-34) |
1065 | + |
1066 | + for i,(key, descrip) in enumerate(self.to_control): |
1067 | + text.append(format % (i+1, descrip+':', key, self.color_for_value(key,self.switch[key]))) |
1068 | + |
1069 | + |
1070 | + text.append("\\%s/" % ("=" * (self.line_length-2))) |
1071 | + |
1072 | + # find a good example of switch to set |
1073 | + example = None |
1074 | + for key in self.switch: |
1075 | + if len(self.get_allowed(key)) > 1: |
1076 | + for val in self.get_allowed(key): |
1077 | + if val != self.switch[key]: |
1078 | + example = (key, val) |
1079 | + break |
1080 | + else: |
1081 | + continue |
1082 | + break |
1083 | + |
1084 | + if not example: |
1085 | + example = ('KEY', 'VALUE') |
1086 | + |
1087 | + text += \ |
1088 | + ["Either type the switch number (1 to %s) to change its setting," % len(self.to_control), |
1089 | + "Set any switch explicitly (e.g. type '%s=%s' at the prompt)" % example, |
1090 | + "Type 'help' for the list of all valid option", |
1091 | + "Type '0', 'auto', 'done' or just press enter when you are done."] |
1092 | + |
1093 | + self.question = "\n".join(text) |
1094 | + return self.question |
1095 | + |
1096 | + |
1097 | + |
1098 | + |
1099 | #=============================================================================== |
1100 | # |
1101 | #=============================================================================== |
1102 | |
1103 | === modified file 'madgraph/interface/madevent_interface.py' |
1104 | --- madgraph/interface/madevent_interface.py 2017-08-10 13:09:28 +0000 |
1105 | +++ madgraph/interface/madevent_interface.py 2017-08-15 12:03:07 +0000 |
1106 | @@ -494,6 +494,321 @@ |
1107 | logger.info(" The banner can be remove only if all files are removed first.") |
1108 | |
1109 | |
1110 | +class AskRun(cmd.ControlSwitch): |
1111 | + """a class for the question on what to do on a madevent run""" |
1112 | + |
1113 | + to_control = [('shower', 'Choose the shower/hadronization program'), |
1114 | + ('detector', 'Choose the detector simulation program'), |
1115 | + ('analysis', 'Choose an analysis package (plot/convert)'), |
1116 | + ('madspin', 'Decay onshell particles'), |
1117 | + ('reweight', 'Add weights to events for new hypp.') |
1118 | + ] |
1119 | + |
1120 | + def __init__(self, question, line_args=[], mode=None, force=False, |
1121 | + *args, **opt): |
1122 | + |
1123 | + self.check_available_module(opt['mother_interface'].options) |
1124 | + self.me_dir = opt['mother_interface'].me_dir |
1125 | + super(AskRun,self).__init__(self.to_control, opt['mother_interface'], |
1126 | + *args, **opt) |
1127 | + |
1128 | + |
1129 | + def check_available_module(self, options): |
1130 | + |
1131 | + self.available_module = set() |
1132 | + |
1133 | + if options['pythia-pgs_path']: |
1134 | + self.available_module.add('PY6') |
1135 | + self.available_module.add('PGS') |
1136 | + if options['pythia8_path']: |
1137 | + self.available_module.add('PY8') |
1138 | + if options['madanalysis_path']: |
1139 | + self.available_module.add('MA4') |
1140 | + if options['madanalysis5_path']: |
1141 | + self.available_module.add('MA5') |
1142 | + if options['exrootanalysis_path']: |
1143 | + self.available_module.add('ExRoot') |
1144 | + if options['delphes_path']: |
1145 | + if 'PY6' in self.available_module or 'PY8' in self.available_module: |
1146 | + self.available_module.add('Delphes') |
1147 | + if not MADEVENT or ('mg5_path' in options and options['mg5_path']): |
1148 | + self.available_module.add('MadSpin') |
1149 | + if misc.has_f2py() or self.mother_interface.options['f2py_compiler']: |
1150 | + self.available_module.add('reweight') |
1151 | + |
1152 | +# old mode to activate the shower |
1153 | + def ans_parton(self, value=None): |
1154 | + """None: means that the user type 'pythia' |
1155 | + value: means that the user type pythia=value""" |
1156 | + |
1157 | + if value is None: |
1158 | + self.set_all_off() |
1159 | + else: |
1160 | + logger.warning('Invalid command: parton=%s' % value) |
1161 | + |
1162 | + |
1163 | +# |
1164 | +# HANDLING SHOWER |
1165 | +# |
1166 | + def get_allowed_shower(self): |
1167 | + """return valid entry for the shower switch""" |
1168 | + |
1169 | + if hasattr(self, 'allowed_shower'): |
1170 | + return self.allowed_shower |
1171 | + |
1172 | + self.allowed_shower = [] |
1173 | + if 'PY6' in self.available_module: |
1174 | + self.allowed_shower.append('Pythia6') |
1175 | + if 'PY8' in self.available_module: |
1176 | + self.allowed_shower.append('Pythia8') |
1177 | + if self.allowed_shower: |
1178 | + self.allowed_shower.append('OFF') |
1179 | + return self.allowed_shower |
1180 | + |
1181 | + def set_default_shower(self): |
1182 | + |
1183 | + if 'PY6' in self.available_module and\ |
1184 | + os.path.exists(pjoin(self.me_dir,'Cards','pythia_card.dat')): |
1185 | + self.switch['shower'] = 'Pythia6' |
1186 | + elif 'PY8' in self.available_module and\ |
1187 | + os.path.exists(pjoin(self.me_dir,'Cards','pythia8_card.dat')): |
1188 | + self.switch['shower'] = 'Pythia8' |
1189 | + elif self.get_allowed_shower(): |
1190 | + self.switch['shower'] = 'OFF' |
1191 | + else: |
1192 | + self.switch['shower'] = 'Not Avail' |
1193 | + |
1194 | + def check_shower(self, value): |
1195 | + """check an entry is valid. return the valid entry in case of shortcut""" |
1196 | + |
1197 | + if value in self.get_allowed_shower(): |
1198 | + return True |
1199 | + |
1200 | + value =value.lower() |
1201 | + if value in ['py6','6','pythia_6']: |
1202 | + return 'Pythia6' |
1203 | + elif value in ['py8','8','pythia_8']: |
1204 | + return 'Pythia8' |
1205 | + else: |
1206 | + return False |
1207 | + |
1208 | + |
1209 | +# old mode to activate the shower |
1210 | + def ans_pythia(self, value=None): |
1211 | + """None: means that the user type 'pythia' |
1212 | + value: means that the user type pythia=value""" |
1213 | + |
1214 | + if 'PY6' not in self.available_module: |
1215 | + logger.info('pythia-pgs not available. Ignore commmand') |
1216 | + return |
1217 | + |
1218 | + if value is None: |
1219 | + self.set_all_off() |
1220 | + self.switch['shower'] = 'Pythia6' |
1221 | + elif value == 'on': |
1222 | + return self.ans_pythia(None) |
1223 | + elif value == 'off': |
1224 | + self.set_switch('shower', 'OFF') |
1225 | + else: |
1226 | + logger.warning('Invalid command: pythia=%s' % value) |
1227 | + |
1228 | + |
1229 | + def consistency_shower_detector(self, vshower, vdetector): |
1230 | + """consistency_XX_YY(val_XX, val_YY) |
1231 | + -> XX is the new key set by the user to a new value val_XX |
1232 | + -> YY is another key |
1233 | + -> return value should be None or "replace_YY" |
1234 | + """ |
1235 | + |
1236 | + if vshower == 'OFF': |
1237 | + if self.check_value('detector', vdetector) and vdetector!= 'OFF': |
1238 | + return 'OFF' |
1239 | + if vshower == 'Pythia8' and vdetector == 'PGS': |
1240 | + return 'OFF' |
1241 | + |
1242 | + return None |
1243 | +# |
1244 | +# HANDLING DETECTOR |
1245 | +# |
1246 | + def get_allowed_detector(self): |
1247 | + """return valid entry for the switch""" |
1248 | + |
1249 | + if hasattr(self, 'allowed_detector'): |
1250 | + return self.allowed_detector |
1251 | + |
1252 | + self.allowed_detector = [] |
1253 | + if 'PGS' in self.available_module: |
1254 | + self.allowed_detector.append('PGS') |
1255 | + if 'Delphes' in self.available_module: |
1256 | + self.allowed_detector.append('Delphes') |
1257 | + |
1258 | + |
1259 | + if self.allowed_detector: |
1260 | + self.allowed_detector.append('OFF') |
1261 | + return self.allowed_detector |
1262 | + |
1263 | + def set_default_detector(self): |
1264 | + |
1265 | + self.set_default_shower() #ensure that this one is called first! |
1266 | + |
1267 | + if 'PGS' in self.available_module and self.switch['shower'] == 'Pythia6': |
1268 | + self.switch['detector'] = 'PGS' |
1269 | + elif 'Delphes' in self.available_module and self.switch['shower'] != 'OFF': |
1270 | + self.switch['detector'] = 'Delphes' |
1271 | + elif self.get_allowed_detector(): |
1272 | + self.switch['detector'] = 'OFF' |
1273 | + else: |
1274 | + self.switch['detector'] = 'missing' |
1275 | + |
1276 | +# old mode to activate pgs |
1277 | + def ans_pgs(self, value=None): |
1278 | + """None: means that the user type 'pgs' |
1279 | + value: means that the user type pgs=value""" |
1280 | + |
1281 | + if 'PGS' not in self.available_module: |
1282 | + logger.info('pythia-pgs not available. Ignore commmand') |
1283 | + return |
1284 | + |
1285 | + if value is None: |
1286 | + self.set_all_off() |
1287 | + self.switch['shower'] = 'Pythia6' |
1288 | + self.switch['detector'] = 'PGS' |
1289 | + elif value == 'on': |
1290 | + self.switch['shower'] = 'Pythia6' |
1291 | + self.switch['detector'] = 'PGS' |
1292 | + elif value == 'off': |
1293 | + self.set_switch('detector', 'OFF') |
1294 | + else: |
1295 | + logger.warning('Invalid command: pgs=%s' % value) |
1296 | + |
1297 | + |
1298 | +# old mode to activate Delphes |
1299 | + def ans_delphes(self, value=None): |
1300 | + """None: means that the user type 'delphes' |
1301 | + value: means that the user type delphes=value""" |
1302 | + |
1303 | + if 'Delphes' not in self.available_module: |
1304 | + logger.warning('Delphes not available. Ignore commmand') |
1305 | + return |
1306 | + |
1307 | + if value is None: |
1308 | + self.set_all_off() |
1309 | + if 'PY6' in self.available_module: |
1310 | + self.switch['shower'] = 'Pythia6' |
1311 | + else: |
1312 | + self.switch['shower'] = 'Pythia8' |
1313 | + self.switch['detector'] = 'Delphes' |
1314 | + elif value == 'on': |
1315 | + return self.ans_delphes(None) |
1316 | + elif value == 'off': |
1317 | + self.set_switch('detector', 'OFF') |
1318 | + else: |
1319 | + logger.warning('Invalid command: pgs=%s' % value) |
1320 | + |
1321 | + def consistency_detector_shower(self,vdetector, vshower): |
1322 | + """consistency_XX_YY(val_XX, val_YY) |
1323 | + -> XX is the new key set by the user to a new value val_XX |
1324 | + -> YY is another key |
1325 | + -> return value should be None or "replace_YY" |
1326 | + """ |
1327 | + |
1328 | + if vdetector == 'PGS' and vshower != 'Pythia6': |
1329 | + return 'Pythia6' |
1330 | + if vdetector == 'Delphes' and vshower not in ['Pythia6', 'Pythia8']: |
1331 | + if 'PY8' in self.available_module: |
1332 | + return 'Pythia8' |
1333 | + elif 'PY6' in self.available_module: |
1334 | + return 'Pythia6' |
1335 | + else: |
1336 | + raise Exception |
1337 | + return None |
1338 | + |
1339 | + |
1340 | +# |
1341 | +# HANDLING ANALYSIS |
1342 | +# |
1343 | + def get_allowed_analysis(self): |
1344 | + """return valid entry for the shower switch""" |
1345 | + |
1346 | + if hasattr(self, 'allowed_analysis'): |
1347 | + return self.allowed_analysis |
1348 | + |
1349 | + self.allowed_analysis = [] |
1350 | + if 'ExRoot' in self.available_module: |
1351 | + self.allowed_analysis.append('ExRoot') |
1352 | + if 'MA4' in self.available_module: |
1353 | + self.allowed_analysis.append('MadAnalysis4') |
1354 | + if 'MA5' in self.available_module: |
1355 | + self.allowed_analysis.append('MadAnalysis5') |
1356 | + |
1357 | + if self.allowed_analysis: |
1358 | + self.allowed_analysis.append('OFF') |
1359 | + |
1360 | + return self.allowed_analysis |
1361 | + |
1362 | + def check_analysis(self, value): |
1363 | + """check an entry is valid. return the valid entry in case of shortcut""" |
1364 | + |
1365 | + if value in self.get_allowed_analysis(): |
1366 | + return True |
1367 | + if value.lower() in ['ma4', 'madanalysis4', 'madanalysis_4','4']: |
1368 | + return 'MadAnalysis4' |
1369 | + if value.lower() in ['ma5', 'madanalysis5', 'madanalysis_5','5']: |
1370 | + return 'MadAnalysis5' |
1371 | + if value.lower() in ['ma', 'madanalysis']: |
1372 | + if 'MA5' in self.available_module: |
1373 | + return 'MadAnalysis5' |
1374 | + elif 'MA4' in self.available_module: |
1375 | + return 'MadAnalysis4' |
1376 | + else: |
1377 | + return False |
1378 | + else: |
1379 | + return False |
1380 | + |
1381 | + |
1382 | + def set_default_analysis(self): |
1383 | + """initialise the switch for analysis""" |
1384 | + |
1385 | + if 'MA4' in self.available_module and \ |
1386 | + os.path.exists(pjoin(self.me_dir,'Cards','plot_card.dat')): |
1387 | + self.switch['analysis'] = 'MadAnalysis4' |
1388 | + elif 'MA5' in self.available_module and\ |
1389 | + (os.path.exists(pjoin(self.me_dir,'Cards','madanalysis5_parton_card.dat'))\ |
1390 | + or os.path.exists(pjoin(self.me_dir,'Cards', 'madanalysis5_hadron_card.dat'))): |
1391 | + self.switch['analysis'] = 'MadAnalysis5' |
1392 | + elif 'ExRoot' in self.available_module: |
1393 | + self.switch['analysis'] = 'ExRoot' |
1394 | + elif self.get_allowed_analysis(): |
1395 | + self.switch['analysis'] = 'OFF' |
1396 | + else: |
1397 | + self.switch['analysis'] = 'Not Avail.' |
1398 | + |
1399 | +# |
1400 | +# MADSPIN handling |
1401 | +# |
1402 | + def set_default_madspin(self): |
1403 | + """initialise the switch for madspin""" |
1404 | + |
1405 | + if 'MadSpin' in self.available_module: |
1406 | + if os.path.exists(pjoin(self.me_dir,'Cards','madspin_card.dat')): |
1407 | + self.switch['madspin'] = 'ON' |
1408 | + else: |
1409 | + self.switch['madspin'] = 'OFF' |
1410 | + else: |
1411 | + self.switch['madspin'] = 'Not Avail.' |
1412 | +# |
1413 | +# ReWeight handling |
1414 | +# |
1415 | + def set_default_reweight(self): |
1416 | + """initialise the switch for reweight""" |
1417 | + |
1418 | + if 'reweight' in self.available_module: |
1419 | + if os.path.exists(pjoin(self.me_dir,'Cards','reweight_card.dat')): |
1420 | + self.switch['reweight'] = 'ON' |
1421 | + else: |
1422 | + self.switch['reweight'] = 'OFF' |
1423 | + else: |
1424 | + self.switch['reweight'] = 'Not Avail.' |
1425 | |
1426 | #=============================================================================== |
1427 | # CheckValidForCmd |
1428 | @@ -1724,6 +2039,8 @@ |
1429 | 'delphes' : ['generate_events [OPTIONS]', 'multi_run [OPTIONS]'] |
1430 | } |
1431 | |
1432 | + asking_for_run = AskRun |
1433 | + |
1434 | ############################################################################ |
1435 | def __init__(self, me_dir = None, options={}, *completekey, **stdin): |
1436 | """ add information to the cmd """ |
1437 | @@ -5760,290 +6077,35 @@ |
1438 | return True |
1439 | |
1440 | |
1441 | - |
1442 | + action_switcher = AskRun |
1443 | ############################################################################ |
1444 | def ask_run_configuration(self, mode=None, args=[]): |
1445 | """Ask the question when launching generate_events/multi_run""" |
1446 | - |
1447 | - available_mode = ['0'] |
1448 | - void = 'Not installed' |
1449 | - switch_order = ['shower', 'detector', 'analysis', 'madspin', 'reweight'] |
1450 | - |
1451 | - switch = dict((k, void) for k in switch_order) |
1452 | - |
1453 | - description = {'shower': 'Choose the shower/hadronization program:', |
1454 | - 'detector': 'Choose the detector simulation program:', |
1455 | - 'madspin': 'Decay particles with the MadSpin module:', |
1456 | - 'reweight':'Add weights to events for different model hypothesis:', |
1457 | - 'analysis':'Run an analysis package on the events generated:' |
1458 | - } |
1459 | - |
1460 | - force_switch = {('shower', 'OFF'): {'detector': 'OFF'}, |
1461 | - ('detector', 'PGS'): {'shower':'PYTHIA6'}, |
1462 | - ('detector', 'DELPHES'): {'shower': ['PYTHIA8', 'PYTHIA6']}} |
1463 | - |
1464 | - switch_assign = lambda key, value: switch.__setitem__(key, value if value \ |
1465 | - in valid_options[key] else switch[key]) |
1466 | - |
1467 | - valid_options = dict((k, ['OFF']) for k in switch_order) # track of all possible input for an entry |
1468 | - options = ['auto', 'done'] |
1469 | - options_legacy = [] |
1470 | - |
1471 | - # Init the switch value according to the current status |
1472 | - if self.options['pythia-pgs_path']: |
1473 | - available_mode.append('1') |
1474 | - available_mode.append('2') |
1475 | - valid_options['shower'].append('PYTHIA6') |
1476 | - valid_options['detector'].append('PGS') |
1477 | - options_legacy += ['pythia', 'pgs', 'pythia=ON', 'pythia=OFF', 'pgs=ON', 'pgs=OFF'] |
1478 | - if os.path.exists(pjoin(self.me_dir,'Cards','pythia_card.dat')): |
1479 | - switch['shower'] = 'PYTHIA6' |
1480 | - else: |
1481 | - switch['shower'] = 'OFF' |
1482 | - if os.path.exists(pjoin(self.me_dir,'Cards','pgs_card.dat')): |
1483 | - switch['detector'] = 'PGS' |
1484 | - else: |
1485 | - switch['detector'] = 'OFF' |
1486 | - |
1487 | - if self.options['pythia8_path']: |
1488 | - available_mode.append('1') |
1489 | - valid_options['shower'].append('PYTHIA8') |
1490 | - if os.path.exists(pjoin(self.me_dir,'Cards','pythia8_card.dat')): |
1491 | - switch['shower'] = 'PYTHIA8' |
1492 | - elif switch['shower'] == void: |
1493 | - switch['shower'] = 'OFF' |
1494 | - |
1495 | - # MadAnalysis4 options |
1496 | - if self.options['madanalysis_path']: |
1497 | - if os.path.exists(pjoin(self.me_dir,'Cards','plot_card_default.dat')): |
1498 | - valid_options['analysis'].insert(0,'MADANALYSIS_4') |
1499 | - |
1500 | - if os.path.exists(pjoin(self.me_dir,'Cards','plot_card.dat')): |
1501 | - switch['analysis'] = 'MADANALYSIS_4' |
1502 | - |
1503 | - # MadAnalysis5 options |
1504 | - if self.options['madanalysis5_path']: |
1505 | - if os.path.exists(pjoin(self.me_dir,'Cards','madanalysis5_parton_card_default.dat')) or \ |
1506 | - os.path.exists(pjoin(self.me_dir,'Cards','madanalysis5_hadron_card_default.dat')): |
1507 | - valid_options['analysis'].append('MADANALYSIS_5') |
1508 | - |
1509 | - parton_card_present = os.path.exists(pjoin(self.me_dir,'Cards', |
1510 | - 'madanalysis5_parton_card.dat')) |
1511 | - hadron_card_present = os.path.exists(pjoin(self.me_dir,'Cards', |
1512 | - 'madanalysis5_hadron_card.dat')) |
1513 | - if hadron_card_present or parton_card_present: |
1514 | - switch['analysis'] = 'MADANALYSIS_5' |
1515 | - |
1516 | - # ExRootanalysis |
1517 | - eradir = self.options['exrootanalysis_path'] |
1518 | - if eradir and misc.is_executable(pjoin(eradir,'ExRootLHEFConverter')): |
1519 | - valid_options['analysis'].insert(0,'EXROOTANALYSIS') |
1520 | - if switch['analysis'] in ['OFF', void]: |
1521 | - switch['analysis'] = 'EXROOTANALYSIS' |
1522 | - |
1523 | - |
1524 | - |
1525 | - if len(valid_options['analysis'])>1: |
1526 | - available_mode.append('3') |
1527 | - if switch['analysis'] == void: |
1528 | - switch['analysis'] = 'OFF' |
1529 | - else: |
1530 | - switch['analysis'] = 'No analysis tool interfaced to MG5aMC.' |
1531 | - |
1532 | - # Need to allow Delphes only if a shower exists |
1533 | - if self.options['delphes_path']: |
1534 | - if valid_options['shower'] != ['OFF']: |
1535 | - available_mode.append('2') |
1536 | - valid_options['detector'].append('DELPHES') |
1537 | - options += ['delphes', 'delphes=ON', 'delphes=OFF'] |
1538 | - if os.path.exists(pjoin(self.me_dir,'Cards','delphes_card.dat')): |
1539 | - switch['detector'] = 'DELPHES' |
1540 | - elif switch['detector'] not in ['PGS']: |
1541 | - switch['detector'] = 'OFF' |
1542 | - elif valid_options['detector'] == ['OFF']: |
1543 | - switch['detector'] = "Requires a shower" |
1544 | - |
1545 | - # Check switch status for MS/reweight |
1546 | - if not MADEVENT or ('mg5_path' in self.options and self.options['mg5_path']): |
1547 | - available_mode.append('4') |
1548 | - valid_options['madspin'] = ['ON', 'OFF'] |
1549 | - if os.path.exists(pjoin(self.me_dir,'Cards','madspin_card.dat')): |
1550 | - switch['madspin'] = 'ON' |
1551 | - else: |
1552 | - switch['madspin'] = 'OFF' |
1553 | - if misc.has_f2py() or self.options['f2py_compiler']: |
1554 | - available_mode.append('5') |
1555 | - valid_options['reweight'] = ['ON', 'OFF'] |
1556 | - if os.path.exists(pjoin(self.me_dir,'Cards','reweight_card.dat')): |
1557 | - switch['reweight'] = 'ON' |
1558 | - else: |
1559 | - switch['reweight'] = 'OFF' |
1560 | - else: |
1561 | - switch['reweight'] = 'Not available (requires NumPy/f2py)' |
1562 | - |
1563 | + |
1564 | + passing_cmd = [] |
1565 | if '-R' in args or '--reweight' in args: |
1566 | - if switch['reweight'] == 'OFF': |
1567 | - switch['reweight'] = 'ON' |
1568 | - elif switch['reweight'] != 'ON': |
1569 | - logger.critical("Cannot run reweight: %s", switch['reweight']) |
1570 | + passing_cmd.append('reweight=ON') |
1571 | if '-M' in args or '--madspin' in args: |
1572 | - if switch['madspin'] == 'OFF': |
1573 | - switch['madspin'] = 'ON' |
1574 | - elif switch['madspin'] != 'ON': |
1575 | - logger.critical("Cannot run madspin: %s", switch['reweight']) |
1576 | - |
1577 | - for id, key in enumerate(switch_order): |
1578 | - if len(valid_options[key]) >1: |
1579 | - options += ['%s=%s' % (key, s) for s in valid_options[key]] |
1580 | - options.append(key) |
1581 | - else: |
1582 | - options.append('%s=OFF' % (key)) |
1583 | - |
1584 | - options += ['parton'] + sorted(list(set(available_mode))) |
1585 | - options += options_legacy |
1586 | - #options += ['pythia=ON', 'pythia=OFF', 'delphes=ON', 'delphes=OFF', 'pgs=ON', 'pgs=OFF'] |
1587 | - #ask the question |
1588 | - |
1589 | - def color(switch_value): |
1590 | - green = '\x1b[32m%s\x1b[0m' |
1591 | - bold = '\x1b[33m%s\x1b[0m' |
1592 | - red = '\x1b[31m%s\x1b[0m' |
1593 | - if switch_value in ['OFF',void,'Requires a shower', |
1594 | - 'Not available (requires NumPy)', |
1595 | - 'Not available yet for this output/process']: |
1596 | - return red%switch_value |
1597 | - elif switch_value in ['ON','MADANALYSIS_4','MADANALYSIS_5', |
1598 | - 'PYTHIA8','PYTHIA6','PGS','DELPHES-ATLAS', |
1599 | - 'DELPHES-CMS','DELPHES', 'EXROOTANALYSIS']: |
1600 | - return green%switch_value |
1601 | - else: |
1602 | - return bold%switch_value |
1603 | - |
1604 | - if mode or not self.force: |
1605 | - answer = '' |
1606 | - while answer not in ['0', 'done', 'auto']: |
1607 | - if mode: |
1608 | - answer = mode |
1609 | - else: |
1610 | - switch_format = " \x1b[31m%i\x1b[0m. %-60s %12s = %s" |
1611 | - question = "The following switches determine which programs are run:\n" |
1612 | - question += '/'+'-'*98+'\\\n' |
1613 | - for id, key in enumerate(switch_order): |
1614 | - question += '| %-115s|\n'%(switch_format%(id+1, description[key], key, color(switch[key]))) |
1615 | - question += '\\'+'-'*98+'/\n' |
1616 | - question += ' Either type the switch number (1 to %s) to change its setting,\n' % (id+1) |
1617 | - question += ' Set any switch explicitly (e.g. type \'madspin=ON\' at the prompt)\n' |
1618 | - question += ' Type \'help\' for the list of all valid option\n' |
1619 | - question += ' Type \'0\', \'auto\', \'done\' or just press enter when you are done.\n' |
1620 | - answer = self.ask(question, '0', options, casesensitive=False) |
1621 | - if (answer.isdigit() and answer != '0') or answer in ['shower', 'detector']: |
1622 | - if answer.isdigit(): |
1623 | - key = switch_order[int(answer) - 1] |
1624 | - else: |
1625 | - key = answer |
1626 | - for i, opt in enumerate(valid_options[key]): |
1627 | - if opt == switch[key]: |
1628 | - break |
1629 | - i +=1 |
1630 | - if i == len(valid_options[key]): |
1631 | - i=0 |
1632 | - answer = '%s=%s' % (key, valid_options[key][i]) |
1633 | - |
1634 | - if '=' in answer: |
1635 | - key, status = answer.split('=') |
1636 | - key, status = key.lower().strip(), status.upper().strip() |
1637 | - |
1638 | - if key not in switch: |
1639 | - # this means use use outdated switch. Use converter to new syntax |
1640 | - logger.warning("Using old syntax. Please check that we run what you expect.") |
1641 | - if key == "pythia" and status == "ON": |
1642 | - key, status = "shower", "PYTHIA6" |
1643 | - elif key == "pythia" and status == "OFF": |
1644 | - key, status = "shower", "OFF" |
1645 | - elif key == "pgs" and status == "ON": |
1646 | - if switch["detector"] in ["OFF", "PGS"] : |
1647 | - key, status = "detector", "PGS" |
1648 | - else: |
1649 | - key, status = "detector", "DELPHES+PGS" |
1650 | - elif key == "delphes" and status == "ON": |
1651 | - if switch["detector"] in ["OFF", "DELPHES"] : |
1652 | - key, status = "detector", "DELPHES" |
1653 | - else: |
1654 | - key, status = "detector", "DELPHES+PGS" |
1655 | - elif key == "pgs" and status == "OFF": |
1656 | - if switch["detector"] in ["OFF", "PGS"] : |
1657 | - key, status = "detector", "OFF" |
1658 | - elif switch["detector"] == "DELPHES+PGS": |
1659 | - key, status = "detector", "DELPHES" |
1660 | - else: |
1661 | - key, status = "detector", switch['detector'] |
1662 | - elif key == "delphes" and status == "OFF": |
1663 | - if switch["detector"] in ["OFF", "DELPHES"] : |
1664 | - key, status = "detector", "OFF" |
1665 | - elif switch["detector"] == "DELPHES+PGS": |
1666 | - key, status = "detector", "PGS" |
1667 | - else: |
1668 | - key, status = "detector", switch['detector'] |
1669 | - |
1670 | - |
1671 | - switch[key] = status |
1672 | - if (key, status) in force_switch: |
1673 | - for key2, status2 in force_switch[(key, status)].items(): |
1674 | - if isinstance(status2, str): |
1675 | - if switch[key2] not in [status2, void]: |
1676 | - logger.info('For coherence \'%s\' is set to \'%s\'' |
1677 | - % (key2, status2), '$MG:color:BLACK') |
1678 | - switch[key2] = status2 |
1679 | - else: |
1680 | - if switch[key2] not in status2 + [void]: |
1681 | - logger.info('For coherence \'%s\' is set to \'%s\'' |
1682 | - % (key2, status2[0]), '$MG:color:BLACK') |
1683 | - switch[key2] = status2[0] |
1684 | - elif answer in ['0', 'auto', 'done']: |
1685 | - continue |
1686 | - elif answer in ['parton', 'pythia','pgs','madspin','reweight', 'delphes']: |
1687 | - logger.info('pass in %s only mode' % answer, '$MG:color:BLACK') |
1688 | - switch_assign('madspin', 'OFF') |
1689 | - switch_assign('reweight', 'OFF') |
1690 | - if answer == 'parton': |
1691 | - switch_assign('shower', 'OFF') |
1692 | - switch_assign('detector', 'OFF') |
1693 | - elif answer == 'pythia': |
1694 | - switch_assign('shower', 'PYTHIA6') |
1695 | - switch_assign('detector', 'OFF') |
1696 | - elif answer == 'pgs': |
1697 | - switch_assign('shower', 'PYTHIA6') |
1698 | - switch_assign('detector', 'PGS') |
1699 | - elif answer == 'delphes': |
1700 | - switch_assign('shower', 'PYTHIA6') |
1701 | - if switch['shower'] == 'OFF': |
1702 | - switch_assign('shower', 'PYTHIA8') |
1703 | - switch_assign('detector', 'DELPHES') |
1704 | - elif answer == 'madspin': |
1705 | - switch_assign('madspin', 'ON') |
1706 | - switch_assign('shower', 'OFF') |
1707 | - switch_assign('detector', 'OFF') |
1708 | - elif answer == 'reweight': |
1709 | - switch_assign('reweight', 'ON') |
1710 | - switch_assign('shower', 'OFF') |
1711 | - switch_assign('detector', 'OFF') |
1712 | - |
1713 | - if mode: |
1714 | - answer = '0' #mode auto didn't pass here (due to the continue) |
1715 | - else: |
1716 | - answer = 'auto' |
1717 | - |
1718 | + passing_cmd.append('madspin=ON') |
1719 | + |
1720 | + switch = self.ask('', '0', [], ask_class = self.action_switcher, |
1721 | + mode=mode, line_args=args, force=self.force, |
1722 | + first_cmd=passing_cmd) |
1723 | + |
1724 | + if 'dynamical' in switch: |
1725 | + mode = 'auto' |
1726 | + |
1727 | # Now that we know in which mode we are check that all the card |
1728 | #exists (copy default if needed) |
1729 | |
1730 | cards = ['param_card.dat', 'run_card.dat'] |
1731 | - if switch['shower'] in ['PY6', 'PYTHIA6']: |
1732 | + if switch['shower'] == 'Pythia6': |
1733 | cards.append('pythia_card.dat') |
1734 | - if switch['shower'] in ['PY8', 'PYTHIA8']: |
1735 | + if switch['shower'] == 'Pythia8': |
1736 | cards.append('pythia8_card.dat') |
1737 | if switch['detector'] in ['PGS','DELPHES+PGS']: |
1738 | cards.append('pgs_card.dat') |
1739 | - if switch['detector'] in ['DELPHES', 'DELPHES+PGS']: |
1740 | + if switch['detector'] in ['Delphes', 'DELPHES+PGS']: |
1741 | cards.append('delphes_card.dat') |
1742 | delphes3 = True |
1743 | if os.path.exists(pjoin(self.options['delphes_path'], 'data')): |
1744 | @@ -6053,11 +6115,11 @@ |
1745 | cards.append('madspin_card.dat') |
1746 | if switch['reweight'] == 'ON': |
1747 | cards.append('reweight_card.dat') |
1748 | - if switch['analysis'] in ['MADANALYSIS_5']: |
1749 | + if switch['analysis'] in ['MADANALYSIS5']: |
1750 | cards.append('madanalysis5_parton_card.dat') |
1751 | - if switch['analysis'] in ['MADANALYSIS_5'] and not switch['shower']=='OFF': |
1752 | + if switch['analysis'] in ['MADANALYSIS5'] and not switch['shower']=='OFF': |
1753 | cards.append('madanalysis5_hadron_card.dat') |
1754 | - if switch['analysis'] in ['MADANALYSIS_4']: |
1755 | + if switch['analysis'] in ['MADANALYSIS4']: |
1756 | cards.append('plot_card.dat') |
1757 | |
1758 | self.keep_cards(cards) |
1759 | @@ -6069,7 +6131,7 @@ |
1760 | self.check_param_card(pjoin(self.me_dir,'Cards','param_card.dat' )) |
1761 | return switch |
1762 | |
1763 | - if answer == 'auto': |
1764 | + if 'dynamical' in switch and switch['dynamical']: |
1765 | self.ask_edit_cards(cards, plot=False, mode='auto') |
1766 | else: |
1767 | self.ask_edit_cards(cards, plot=False) |
Hi Olivier,
Shouldn't the merge target be something different than 2.5.6?
Cheers,
Rik