Merge lp:~maddm/mg5amcnlo/maddm_dev2 into lp:~mg5core1/mg5amcnlo/2.6.2

Proposed by Olivier Mattelaer
Status: Merged
Approved by: Valentin Hirschi
Approved revision: 393
Merged at revision: 333
Proposed branch: lp:~maddm/mg5amcnlo/maddm_dev2
Merge into: lp:~mg5core1/mg5amcnlo/2.6.2
Diff against target: 3994 lines (+1303/-702)
34 files modified
MadSpin/decay.py (+1/-1)
MadSpin/interface_madspin.py (+1/-0)
Template/LO/Cards/run_card.dat (+3/-0)
Template/LO/SubProcesses/genps.f (+9/-10)
Template/LO/SubProcesses/setcuts.f (+4/-2)
Template/LO/bin/generate_events (+9/-9)
Template/LO/bin/madevent (+52/-47)
Template/NLO/Cards/run_card.dat (+3/-0)
UpdateNotes.txt (+14/-1)
VERSION (+2/-2)
madgraph/core/base_objects.py (+10/-4)
madgraph/interface/.mg5_logging.conf (+13/-3)
madgraph/interface/amcatnlo_run_interface.py (+3/-3)
madgraph/interface/coloring_logging.py (+20/-4)
madgraph/interface/common_run_interface.py (+522/-245)
madgraph/interface/extended_cmd.py (+111/-53)
madgraph/interface/launch_ext_program.py (+67/-65)
madgraph/interface/loop_interface.py (+1/-1)
madgraph/interface/madevent_interface.py (+2/-2)
madgraph/interface/madgraph_interface.py (+149/-115)
madgraph/interface/madweight_interface.py (+1/-1)
madgraph/interface/master_interface.py (+7/-4)
madgraph/interface/reweight_interface.py (+47/-23)
madgraph/interface/tutorial_text.py (+11/-8)
madgraph/iolibs/export_v4.py (+11/-1)
madgraph/iolibs/file_writers.py (+8/-3)
madgraph/iolibs/files.py (+1/-0)
madgraph/loop/loop_exporters.py (+2/-2)
madgraph/various/banner.py (+92/-64)
madgraph/various/misc.py (+48/-2)
models/__init__.py (+5/-7)
models/check_param_card.py (+11/-8)
models/usermod.py (+62/-12)
tests/acceptance_tests/test_cmd_madevent.py (+1/-0)
To merge this branch: bzr merge lp:~maddm/mg5amcnlo/maddm_dev2
Reviewer Review Type Date Requested Status
Valentin Hirschi Pending
Review via email: mp+342008@code.launchpad.net

Description of the change

Change to increase plugin flexibility
this include
1) improve the tutorial capabilities
2) refactor the question about the card edition to have it more manageable
3) more possiblity for help message
4) possibility to control an entry of the cards to check that they are in an allowed range
5) allow --loop_filter for loop-induced [should have done that directly in 2.6.2 but ok]
6) New possibility for handling the RunWeb file (both via context manager or decorator)
   -> before crashing it checks if the associated pid is still running.
   -> use context manager for LO but NOT for gridpack/NLO.
7) fix some issue with add model (for some NLO model)
8) add "update to_full" to display all hidden options of the run_card

To post a comment you must log in.
Revision history for this message
Olivier Mattelaer (olivier-mattelaer) wrote :

made a quick look and found three stuff to change (see below)

lp:~maddm/mg5amcnlo/maddm_dev2 updated
380. By olivier-mattelaer

allow plugin to have control on detect_card + better handling of the edit/add functionality

381. By olivier-mattelaer

refactoring to allow the plugin to define itself how the pdg of the <init> block should be written

382. By olivier-mattelaer

add hidden syntax import model --last: loading last modified model

383. By olivier-mattelaer

add a clean_process function to ease the job of plugin function

384. By olivier-mattelaer

fixing issue with re-weighting when doing rewgt from two different process directory

385. By olivier-mattelaer

1) set new runweb handling for file ./bin/madevent
2) better fix for t-channel
3) fix issue for set lep 1.2 (avoid the crash)

386. By olivier-mattelaer

forbids install maddm for the temporary release

387. By olivier-mattelaer

correct date

388. By olivier-mattelaer

fixing issue with version

389. By olivier-mattelaer

fix an issue with NLO model

390. By olivier-mattelaer

remove pointless printout

391. By olivier-mattelaer

UPdate note

392. By olivier-mattelaer

small change for the installer

393. By olivier-mattelaer

revert release creation script + improve install

394. By olivier-mattelaer

comment from the review

395. By olivier-mattelaer

improve UpdateNotes and merge with lastest 2.6.2

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'MadSpin/decay.py'
2--- MadSpin/decay.py 2018-02-05 12:41:25 +0000
3+++ MadSpin/decay.py 2018-04-20 08:32:43 +0000
4@@ -3848,7 +3848,7 @@
5 min_br = min([m['total_br'] for m in self.all_ME.values()])
6 logger.info('''All production process does not have the same total Branching Ratio.
7 Therefore the total number of events after decay will be lower than the original file.
8- [max_br = %s, min_br = %s]''' % (max_br, min_br),'$MG:color:BLACK')
9+ [max_br = %s, min_br = %s]''' % (max_br, min_br),'$MG:BOLD')
10 fake_decay = {'br': max_br - production['total_br'],
11 'path': None, 'matrix_element': None,
12 'finals': None, 'base_order': None,
13
14=== modified file 'MadSpin/interface_madspin.py'
15--- MadSpin/interface_madspin.py 2018-02-21 17:03:42 +0000
16+++ MadSpin/interface_madspin.py 2018-04-20 08:32:43 +0000
17@@ -1022,6 +1022,7 @@
18
19 run_card["iseed"] = self.seed
20 run_card['gridpack'] = True
21+ run_card['systematics_program'] = 'False'
22 run_card['use_syst'] = False
23 run_card.write(pjoin(decay_dir, "Cards", "run_card.dat"))
24 param_card = self.banner['slha']
25
26=== modified file 'Template/LO/Cards/run_card.dat'
27--- Template/LO/Cards/run_card.dat 2017-11-18 00:45:31 +0000
28+++ Template/LO/Cards/run_card.dat 2018-04-20 08:32:43 +0000
29@@ -10,6 +10,9 @@
30 # Lines starting with a '# ' are info or comments *
31 # *
32 # mind the format: value = variable ! comment *
33+# *
34+# To display more options, you can type the command: *
35+* update full_run_card *
36 #*********************************************************************
37 #
38 #*******************
39
40=== modified file 'Template/LO/SubProcesses/genps.f'
41--- Template/LO/SubProcesses/genps.f 2017-08-09 12:56:57 +0000
42+++ Template/LO/SubProcesses/genps.f 2018-04-20 08:32:43 +0000
43@@ -863,21 +863,20 @@
44
45 c write(*,*) 'tmin, tmax',tmin,tmax
46
47- tmax = max(tmax,0d0) !This line if want really t freedom
48+ if (tmax.gt.-0.01.and.tmin.lt.-0.02)then
49+c set tmax to 0. The idea is to be sure to be able to hit zero
50+c and not to be block by numerical inacuracy
51+c tmax = max(tmax,0d0) !This line if want really t freedom
52+ call sample_get_x(wgt,x(-ibranch),-ibranch,iconfig,
53+ $ 0, -tmin/stot)
54+ t = stot*(-x(-ibranch))
55
56+ else
57 call sample_get_x(wgt,x(-ibranch),-ibranch,iconfig,
58 $ -tmax/stot, -tmin/stot)
59 t = stot*(-x(-ibranch))
60-c
61-c now reset tmax if messed it up for t freedom 3 lines above
62-c
63- call yminmax(s1,t,m12,ma2,mb2,mn2,tmin,tmax)
64+ endif
65
66-c write(*,*) tmin,t,tmax
67-c if (t .eq. 0d0) then
68-c jac = -3
69-c return
70-c endif
71 if (t .lt. tmin .or. t .gt. tmax) then
72 jac=-3d0
73 return
74
75=== modified file 'Template/LO/SubProcesses/setcuts.f'
76--- Template/LO/SubProcesses/setcuts.f 2018-02-23 15:30:14 +0000
77+++ Template/LO/SubProcesses/setcuts.f 2018-04-20 08:32:43 +0000
78@@ -138,8 +138,10 @@
79 lpp(2)=0
80 ebeam(1)=pmass(1)/2d0
81 ebeam(2)=pmass(1)/2d0
82- scale=pmass(1)
83- fixed_ren_scale=.true.
84+ if (.not.fixed_ren_scale)then
85+ scale=pmass(1)
86+ fixed_ren_scale=.true.
87+ endif
88 fixed_fac_scale=.true.
89 use_syst=.false.
90 endif
91
92=== modified file 'Template/LO/bin/generate_events'
93--- Template/LO/bin/generate_events 2015-10-24 19:53:10 +0000
94+++ Template/LO/bin/generate_events 2018-04-20 08:32:43 +0000
95@@ -33,7 +33,6 @@
96
97 # Check if optimize mode is (and should be) activated
98 if __debug__ and (not os.path.exists(pjoin(root_path,'../..', 'bin','create_release.py'))):
99- print 'launch in debug mode'
100 subprocess.call([sys.executable] + ['-O'] + sys.argv)
101 sys.exit()
102
103@@ -146,18 +145,22 @@
104 # Check that python version is valid
105
106 set_configuration()
107- argument = sys.argv
108+ argument = sys.argv
109 try:
110 if '-h' in argument or '--help' in argument:
111- launch = ME.MadEventCmdShell(me_dir=root_path)
112+ launch = ME.MadEventCmdShell(me_dir=root_path, force_run=True)
113 launch.exec_cmd('help generate_events')
114 sys.exit()
115 elif len(argument) > 1 and argument[1] in ['0', '1', '2']:
116 argument = treat_old_argument(argument)
117
118- launch = ME.MadEventCmdShell(me_dir=root_path)
119- launch.run_cmd('generate_events %s' % ' '.join(argument[1:]))
120- launch.run_cmd('quit')
121+ with ME.MadEventCmdShell.RunWebHandling(root_path, ):
122+ launch = ME.MadEventCmdShell(me_dir=root_path, force_run=True)
123+ launch.run_cmd('generate_events %s' % ' '.join(argument[1:]))
124+ launch.run_cmd('quit')
125+ except ME.MadEventAlreadyRunning, message:
126+ logging.getLogger('madgraph').log(40, str(message))
127+ sys.exit(1)
128 except KeyboardInterrupt:
129 try:
130 launch.run_cmd('quit')
131@@ -166,9 +169,6 @@
132 except Exception, error:
133 logging.error(str(error))
134 sys.exit()
135-
136- if os.path.exists(pjoin(root_path, 'RunWeb')):
137- os.remove(pjoin(root_path, 'RunWeb'))
138
139 # reconfigure path for the web
140 #if len(argument) == 5:
141
142=== modified file 'Template/LO/bin/madevent'
143--- Template/LO/bin/madevent 2016-04-25 14:02:24 +0000
144+++ Template/LO/bin/madevent 2018-04-20 08:32:43 +0000
145@@ -146,53 +146,58 @@
146
147 # Call the cmd interface main loop
148 try:
149- if (args and os.path.isfile(args[0])):
150- # They are an input file
151- input_file = args[0]
152- if options.web:
153- cmd_line = cmd_interface.MadEventCmd()
154- cmd_line.debug_output = os.path.join(os.path.dirname(input_file),'generation.log')
155- cmd_line.use_rawinput = False
156- cmd_line.haspiping = False
157- cmd_line.run_cmd('import command ' + input_file)
158- cmd_line.run_cmd('quit')
159- else:
160- cmd_line = cmd_interface.MadEventCmdShell()
161- cmd_line.use_rawinput = False
162- cmd_line.haspiping = False
163- cmd_line.run_cmd('import command ' + input_file)
164- cmd_line.run_cmd('quit')
165- elif args:
166- # a single command is provided
167- if options.web:
168- cmd_line = cmd_interface.MadEventCmd()
169- else:
170- cmd_line = cmd_interface.MadEventCmdShell()
171- if not hasattr(cmd_line, 'do_%s' % args[0]):
172- if parser_error:
173- print parser_error
174- print 'and %s can not be interpreted as a valid command.' % args[0]
175- else:
176- print 'ERROR: %s not a valid command. Please retry' % args[0]
177- else:
178- cmd_line.use_rawinput = False
179- cmd_line.run_cmd(' '.join(args))
180- cmd_line.run_cmd('quit')
181- else:
182- # Interactive mode
183- if options.web:
184- cmd_line = cmd_interface.MadEventCmd()
185- cmd_line.cmdloop()
186- else:
187- cmd_line = cmd_interface.MadEventCmdShell()
188- cmd_line.cmdloop()
189-
190+ if '-h' in args or '--help' in args:
191+ launch = ME.MadEventCmdShell(me_dir=os.path.dirname(root_path), force_run=True)
192+ launch.exec_cmd('help generate_events')
193+ sys.exit(0)
194+ with cmd_interface.MadEventCmdShell.RunWebHandling(os.path.dirname(root_path), ):
195+ if (args and os.path.isfile(args[0])):
196+ # They are an input file
197+ input_file = args[0]
198+ if options.web:
199+ cmd_line = cmd_interface.MadEventCmd(force_run=True)
200+ cmd_line.debug_output = os.path.join(os.path.dirname(input_file),'generation.log')
201+ cmd_line.use_rawinput = False
202+ cmd_line.haspiping = False
203+ cmd_line.run_cmd('import command ' + input_file)
204+ cmd_line.run_cmd('quit')
205+ else:
206+ cmd_line = cmd_interface.MadEventCmdShell(force_run=True)
207+ cmd_line.use_rawinput = False
208+ cmd_line.haspiping = False
209+ cmd_line.run_cmd('import command ' + input_file)
210+ cmd_line.run_cmd('quit')
211+ elif args:
212+ # a single command is provided
213+ if options.web:
214+ cmd_line = cmd_interface.MadEventCmd(force_run=True)
215+ else:
216+ cmd_line = cmd_interface.MadEventCmdShell(force_run=True)
217+ if not hasattr(cmd_line, 'do_%s' % args[0]):
218+ if parser_error:
219+ print parser_error
220+ print 'and %s can not be interpreted as a valid command.' % args[0]
221+ else:
222+ print 'ERROR: %s not a valid command. Please retry' % args[0]
223+ else:
224+ cmd_line.use_rawinput = False
225+ cmd_line.run_cmd(' '.join(args))
226+ cmd_line.run_cmd('quit')
227+ else:
228+ # Interactive mode
229+ if options.web:
230+ cmd_line = cmd_interface.MadEventCmd(force_run=True)
231+ cmd_line.cmdloop()
232+ else:
233+ cmd_line = cmd_interface.MadEventCmdShell(force_run=True)
234+ cmd_line.cmdloop()
235 except KeyboardInterrupt:
236 print 'writting history and directory and quit on KeyboardInterrupt'
237 pass
238 except cmd_interface.MadEventAlreadyRunning, error:
239 logging.error(str(error))
240- sys.exit()
241+ sys.exit(1)
242+
243 try:
244 readline.set_history_length(100)
245 if not os.path.exists(os.path.join(os.environ['HOME'], '.mg5')):
246@@ -208,8 +213,8 @@
247 pass
248
249
250-try:
251- # Remove lock file
252- os.remove(os.path.join(root_path,os.pardir, 'RunWeb'))
253-except:
254- pass
255+#try:
256+# # Remove lock file
257+# os.remove(os.path.join(root_path,os.pardir, 'RunWeb'))
258+#except:
259+# pass
260
261=== modified file 'Template/NLO/Cards/run_card.dat'
262--- Template/NLO/Cards/run_card.dat 2017-11-17 16:07:39 +0000
263+++ Template/NLO/Cards/run_card.dat 2018-04-20 08:32:43 +0000
264@@ -13,6 +13,9 @@
265 # *
266 # Some of the values of variables can be list. These can either be *
267 # comma or space separated. *
268+# *
269+# To display additional parameter, you can use the command: *
270+# update to_full *
271 #***********************************************************************
272 #
273 #*******************
274
275=== modified file 'UpdateNotes.txt'
276--- UpdateNotes.txt 2018-04-03 15:01:12 +0000
277+++ UpdateNotes.txt 2018-04-20 08:32:43 +0000
278@@ -1,10 +1,18 @@
279 Update notes for MadGraph5_aMC@NLO (in reverse time order)
280
281-2.6.2 ()
282+
283+2.6.2.beta (30-04-02)
284 OM: Fix issue with madspin introduced in 2.6.1 (failing to generate correct diagram for NLO process)
285+ OM: introduce "update to_full" command to display all the hidden parameter
286+ OM: improve handling of (some) run_card parameter:
287+ - add comment that can be displayed via "help NAME"
288+ - add autocompletion for some parameter
289+ - add direct rejection of parameter edition if not in some allowed list/range
290 OM: add the value of all the widths in Auto-width in the scan summary file
291 OM: fix crash in 1>N reweighting
292 RF: Fixed an issue where too many files were opened for fNLO runs in rare cases
293+ OM: For 1>N, if the user set fixed_run_scale to True, then the scale is choose accordingly
294+ and not following the mass of the inital state anymore
295 RF: For the HwU histograms, if no gnuplot installation is found, write the gnuplot scripts in v5
296 format (instead of the very old v4 format).
297 RF+MZ: Fixed a problem with (f)NLO(+PS) runs in case the Born has identical QCD-charged
298@@ -18,8 +26,13 @@
299 RF: Fixed a bug for ApplGrid: in rare cases the ApplGrid tables were filled twice for the same event
300 OM: Fixed a bug for fixed target experiment when the energy of the beam was set to 0.
301 RF: Fixed an issue with the computation of (partial) decay width processes at NLO.
302+ OM: loop-filter commands are now working for loop-induced processes
303+ OM: New method avoiding that two process are running inside the same output directory.
304+ This is implemented only for Gridpack and LO run so far.
305+ The new method should be more robust in case of crash (i.e. not wrongly trigger as before)
306
307 2.6.1 (12/12/17)
308+
309 RF+MZ: It is now possible to add LO matrix elements (with [LOonly])
310 to Fx-Fx merged samples. Thanks to Josh Bendavid for testing.
311 OM: Re-factoring the code asking which program to use (both at LO and NLO)
312
313=== modified file 'VERSION'
314--- VERSION 2017-12-12 21:11:08 +0000
315+++ VERSION 2018-04-20 08:32:43 +0000
316@@ -1,5 +1,5 @@
317-version = 2.6.1
318-date = 2017-12-12
319+version = 2.6.2.beta
320+date = 2018-04-02
321
322
323
324
325=== modified file 'madgraph/core/base_objects.py'
326--- madgraph/core/base_objects.py 2018-02-28 14:10:19 +0000
327+++ madgraph/core/base_objects.py 2018-04-20 08:32:43 +0000
328@@ -2972,8 +2972,10 @@
329 the user-defined list of orders, it can be ommitted for some info
330 displays."""
331
332- if prefix:
333+ if isinstance(prefix, bool):
334 mystr = " " * indent + "Process: "
335+ elif isinstance(prefix, str):
336+ mystr = prefix
337 else:
338 mystr = ""
339 prevleg = None
340@@ -3354,10 +3356,14 @@
341 def get_initial_pdg(self, number):
342 """Return the pdg codes for initial state particles for beam number"""
343
344- return filter(lambda leg: leg.get('state') == False and\
345+ legs = filter(lambda leg: leg.get('state') == False and\
346 leg.get('number') == number,
347- self.get('legs'))[0].get('id')
348-
349+ self.get('legs'))
350+ if not legs:
351+ return None
352+ else:
353+ return legs[0].get('id')
354+
355 def get_initial_final_ids(self):
356 """return a tuple of two tuple containing the id of the initial/final
357 state particles. Each list is ordered"""
358
359=== modified file 'madgraph/interface/.mg5_logging.conf'
360--- madgraph/interface/.mg5_logging.conf 2013-11-27 17:25:48 +0000
361+++ madgraph/interface/.mg5_logging.conf 2018-04-20 08:32:43 +0000
362@@ -1,11 +1,11 @@
363 [formatters]
364-keys: cmdprint,simple,madgraph
365+keys: cmdprint,simple,madgraph,tutorial
366
367 [handlers]
368 keys: cmdprint,root,madgraph,fatalerror,tutorial,tutorial_aMCatNLO,tutorial_MadLoop,decay,cmdprint2
369
370 [loggers]
371-keys: root,cmdprint,madgraph,fatalerror,tutorial,tutorial,tutorial_aMCatNLO,tutorial_MadLoop,madevent,amcatnlo,decay,cmdprint2
372+keys: root,cmdprint,madgraph,fatalerror,tutorial,tutorial,tutorial_aMCatNLO,tutorial_MadLoop,madevent,amcatnlo,decay,cmdprint2,tutorial_plugin
373
374
375 [formatter_cmdprint]
376@@ -20,6 +20,10 @@
377 class: logging.ColorFormatter
378 format: $COLOR%(levelname)s: %(message)s $RESET
379
380+[formatter_tutorial]
381+class: logging.ColorFormatter
382+format: $_BOLD========== Tutorial ==========$_RESET$BR$COLOR%(message)s $RESET$BR$_BOLD========== Tutorial ==========$_RESET
383+
384 [handler_cmdprint]
385 class: StreamHandler
386 args: [sys.stdout]
387@@ -38,7 +42,7 @@
388 [handler_tutorial]
389 class: StreamHandler
390 args: [sys.stdout]
391-formatter: simple
392+formatter: tutorial
393
394 [handler_tutorial_aMCatNLO]
395 class: StreamHandler
396@@ -122,6 +126,12 @@
397 qualname=tutorial
398 propagate=0
399
400+[logger_tutorial_plugin]
401+level : ERROR
402+handlers: tutorial
403+qualname=tutorial_plugin
404+propagate=0
405+
406 [logger_tutorial_MadLoop]
407 level : ERROR
408 handlers: tutorial_MadLoop
409
410=== modified file 'madgraph/interface/amcatnlo_run_interface.py'
411--- madgraph/interface/amcatnlo_run_interface.py 2018-02-07 21:30:27 +0000
412+++ madgraph/interface/amcatnlo_run_interface.py 2018-04-20 08:32:43 +0000
413@@ -1729,7 +1729,7 @@
414 param_card_iterator.write(pjoin(self.me_dir,'Cards','param_card.dat'))
415 name = misc.get_scan_name(orig_name, self.run_name)
416 path = pjoin(self.me_dir, 'Events','scan_%s.txt' % name)
417- logger.info("write all cross-section results in %s" % path, '$MG:color:BLACK')
418+ logger.info("write all cross-section results in %s" % path, '$MG:BOLD')
419 param_card_iterator.write_summary(path)
420
421 if self.allow_notification_center:
422@@ -5187,7 +5187,7 @@
423 """read and parse the test_ME/MC.log file"""
424 content = open(log).read()
425 if 'FAILED' in content:
426- logger.info('Output of the failing test:\n'+content[:-1],'$MG:color:BLACK')
427+ logger.info('Output of the failing test:\n'+content[:-1],'$MG:BOLD')
428 raise aMCatNLOError('Some tests failed, run cannot continue.\n' + \
429 'Please check that widths of final state particles (e.g. top) have been' + \
430 ' set to 0 in the param_card.dat.')
431@@ -5310,7 +5310,7 @@
432 else:
433 logger.info("""Your Parton-shower choice is not available for running.
434 The events will be generated for the associated Parton-Shower.
435- Remember that NLO events without showering are NOT physical.""", '$MG:color:BLACK')
436+ Remember that NLO events without showering are NOT physical.""", '$MG:BOLD')
437
438
439 # specify the cards which are needed for this run.
440
441=== modified file 'madgraph/interface/coloring_logging.py'
442--- madgraph/interface/coloring_logging.py 2016-02-19 13:21:31 +0000
443+++ madgraph/interface/coloring_logging.py 2018-04-20 08:32:43 +0000
444@@ -1,6 +1,7 @@
445 import logging
446 # method to add color to a logging.info add a second argument:
447-# '$MG:color:BLACK'
448+# '$MG:BOLD'
449+# '$MG:color:RED'
450
451
452 BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE = range(8)
453@@ -31,7 +32,7 @@
454 class ColorFormatter(logging.Formatter):
455
456 def __init__(self, *args, **kwargs):
457- # can't do super(...) here because Formatter is an old school class
458+ # can't do super(...) here because Formatter is an old school class)
459 logging.Formatter.__init__(self, *args, **kwargs)
460
461 def format(self, record):
462@@ -44,6 +45,7 @@
463 # A not-so-nice but working way of passing arguments to this formatter
464 # from MadGraph.
465 color_specified = False
466+ bold_specified = False
467 for arg in record.args:
468 if isinstance(arg,str) and arg.startswith('$MG'):
469 elems=arg.split(':')
470@@ -53,12 +55,26 @@
471 color_choice = COLORS[elems[2]]
472 if color_choice == 0:
473 color_choice = 30
474+ if len(elems)==2 and elems[1].lower()=='bold':
475+ bold_specified = True
476 else:
477 new_args.append(arg)
478+
479+
480 record.args = tuple(new_args)
481- color = COLOR_SEQ % (30 + color_choice)
482+ if bold_specified:
483+ color = BOLD_SEQ
484+ color_specified = True
485+ else:
486+ color = COLOR_SEQ % (30 + color_choice)
487 message = logging.Formatter.format(self, record)
488- if not message.endswith('$RESET'):
489+ if not message:
490+ return message
491+ # if some need to be applied no matter what:
492+ message = message.replace('$_BOLD', BOLD_SEQ).replace('$_RESET', RESET_SEQ).replace('$BR','\n')
493+
494+ # for the conditional one
495+ if '$RESET' not in message:
496 message += '$RESET'
497 for k,v in COLORS.items():
498 color_flag = COLOR_SEQ % (v+30)
499
500=== modified file 'madgraph/interface/common_run_interface.py'
501--- madgraph/interface/common_run_interface.py 2018-03-28 20:42:08 +0000
502+++ madgraph/interface/common_run_interface.py 2018-04-20 08:32:43 +0000
503@@ -21,6 +21,7 @@
504
505 import ast
506 import logging
507+import math
508 import os
509 import re
510 import shutil
511@@ -485,6 +486,12 @@
512 args.remove('-from_cards')
513 opts.append('-from_cards')
514
515+ if any(t.startswith('--plugin=') for t in args):
516+ plugin = [t for t in args if t.startswith('--plugin')][0]
517+ args.remove(plugin)
518+ opts.append(plugin)
519+
520+
521 if len(args) == 0:
522 if self.run_name:
523 args.insert(0, self.run_name)
524@@ -501,6 +508,7 @@
525
526 args += opts
527
528+
529 def check_check_events(self,args):
530 """Check the argument for decay_events command
531 syntax is "decay_events [NAME]"
532@@ -611,6 +619,7 @@
533 """common"""
534
535 self.force_run = False # this flag force the run even if RunWeb is present
536+ self.stop_for_runweb = False # this flag indicates if we stop this run because of RunWeb.
537 if 'force_run' in opts and opts['force_run']:
538 self.force_run = True
539 del opts['force_run']
540@@ -641,6 +650,7 @@
541 (for this exact same directory) Please wait that this is instance is
542 closed. If no instance is running, you can delete the file
543 %s and try again.''' % pjoin(me_dir,'RunWeb')
544+ self.stop_for_runweb = True
545 raise AlreadyRunning, message
546 else:
547 self.write_RunWeb(me_dir)
548@@ -677,12 +687,82 @@
549
550
551 def write_RunWeb(self, me_dir):
552+ self.writeRunWeb(me_dir)
553+ self.gen_card_html()
554+
555+ @staticmethod
556+ def writeRunWeb(me_dir):
557 pid = os.getpid()
558 fsock = open(pjoin(me_dir,'RunWeb'),'w')
559 fsock.write(`pid`)
560- fsock.close()
561- self.gen_card_html()
562-
563+ fsock.close()
564+
565+ class RunWebHandling(object):
566+
567+ def __init__(self, me_dir, crashifpresent=True, warnifpresent=True):
568+ """raise error if RunWeb already exists
569+ me_dir is the directory where the write RunWeb"""
570+
571+ self.remove_run_web = True
572+ self.me_dir = me_dir
573+
574+ if crashifpresent or warnifpresent:
575+ if os.path.exists(pjoin(me_dir, 'RunWeb')):
576+ pid = open(pjoin(me_dir, 'RunWeb')).read()
577+ try:
578+ pid = int(pid)
579+ except Exception:
580+ pid = "unknown"
581+
582+ if pid == 'unknown' or misc.pid_exists(pid):
583+ # bad situation
584+ if crashifpresent:
585+ if isinstance(crashifpresent, Exception):
586+ raise crashifpresent
587+ else:
588+ message = '''Another instance of the program is currently running (pid = %s).
589+ (for this exact same directory). Please wait that this is instance is
590+ closed. If no instance is running, you can delete the file
591+ %s and try again.''' % (pid, pjoin(me_dir, 'RunWeb'))
592+ raise AlreadyRunning, message
593+ elif warnifpresent:
594+ if isinstance( warnifpresent, bool):
595+ logger.warning("%s/RunWeb is present. Please check that only one run is running in that directory.")
596+ else:
597+ logger.log(warnifpresent, "%s/RunWeb is present. Please check that only one run is running in that directory.")
598+ self.remove_run_web = False
599+ else:
600+ logger.debug('RunWeb exists but no associated process. Will Ignore it!')
601+ return
602+
603+ # write RunWeb
604+
605+ CommonRunCmd.writeRunWeb(me_dir)
606+
607+ def __enter__(self):
608+ return
609+
610+ def __exit__(self,exc_type, exc_value, traceback):
611+
612+ if self.remove_run_web:
613+ try:
614+ os.remove(pjoin(self.me_dir,'RunWeb'))
615+ except Exception:
616+ if os.path.exists(pjoin(self.me_dir,'RunWeb')):
617+ logger.warning('fail to remove: %s' % pjoin(self.me_dir,'RunWeb'))
618+ return
619+
620+ def __call__(self, f):
621+ """allow to use this as decorator as well"""
622+ def wrapper(*args, **kw):
623+ with self:
624+ return f(*args, **kw)
625+ return wrapper
626+
627+
628+
629+
630+
631 ############################################################################
632 def split_arg(self, line, error=False):
633 """split argument and remove run_options"""
634@@ -887,6 +967,16 @@
635
636 self.ask_edit_card_static(cards, mode, plot, self.options['timeout'],
637 self.ask, first_cmd=first_cmd)
638+
639+ for c in cards:
640+ if not os.path.isabs(c):
641+ c = pjoin(self.me_dir, c)
642+ if not os.path.exists(c):
643+ default = c.replace('dat', '_default.dat')
644+ if os.path.exists(default):
645+ files.cp(default, c)
646+
647+
648
649 @staticmethod
650 def ask_edit_card_static(cards, mode='fixed', plot=True,
651@@ -950,6 +1040,7 @@
652 path_msg='enter path', ask_class = AskforEditCard,
653 cards=cards, mode=mode, **opt)
654
655+
656 @staticmethod
657 def detect_card_type(path):
658 """detect the type of the card. Return value are
659@@ -1212,7 +1303,7 @@
660 else:
661 PY8_plots_root_path = pjoin(self.me_dir,'HTML',
662 self.run_name,'%s_PY8_plots'%tag)
663-
664+
665 if 'ickkw' in self.run_card:
666 if int(self.run_card['ickkw']) and mode == 'Pythia':
667 self.update_status('Create matching plots for Pythia', level='pythia')
668@@ -1473,12 +1564,12 @@
669 ############################################################################
670 def help_systematics(self):
671 """help for systematics command"""
672- logger.info("syntax: systematics RUN_NAME [OUTPUT] [options]",'$MG:color:BLACK')
673+ logger.info("syntax: systematics RUN_NAME [OUTPUT] [options]",'$MG:BOLD')
674 logger.info("-- Run the systematics run on the RUN_NAME run.")
675 logger.info(" RUN_NAME can be a path to a lhef file.")
676 logger.info(" OUTPUT can be the path to the output lhe file, otherwise the input file will be overwritten")
677 logger.info("")
678- logger.info("options: (values written are the default)", '$MG:color:BLACK')
679+ logger.info("options: (values written are the default)", '$MG:BOLD')
680 logger.info("")
681 logger.info(" --mur=0.5,1,2 # specify the values for renormalisation scale variation")
682 logger.info(" --muf=0.5,1,2 # specify the values for factorisation scale variation")
683@@ -1494,7 +1585,7 @@
684 logger.info(" --keep_weights= # force to keep the weight even if in the list of remove_weights")
685 logger.info(" --start_id= # define the starting digit for the additial weight. If not specify it is determine automatically")
686 logger.info("")
687- logger.info(" Allowed value for the pdf options:", '$MG:color:BLACK')
688+ logger.info(" Allowed value for the pdf options:", '$MG:BOLD')
689 logger.info(" central : Do not perform any pdf variation" )
690 logger.info(" errorset : runs over the all the members of the PDF set used to generate the events")
691 logger.info(" 244800 : runs over the associated set and all its members")
692@@ -1505,7 +1596,7 @@
693 logger.info(" CT10@X : runs over the Xth member of the associated PDF set")
694 logger.info(" XX,YY,ZZ : runs over the sets for XX,YY,ZZ (those three follows above syntax)")
695 logger.info("")
696- logger.info(" Allowed value for the keep/remove_wgts options:", '$MG:color:BLACK')
697+ logger.info(" Allowed value for the keep/remove_wgts options:", '$MG:BOLD')
698 logger.info(" all : keep/remove all weights")
699 logger.info(" name : keep/remove that particular weight")
700 logger.info(" id1,id2 : keep/remove all the weights between those two values --included--")
701@@ -1792,6 +1883,7 @@
702 cp3.irmp.ucl.ac.be/projects/madgraph/wiki/Reweight
703 """
704
705+
706 #### Utility function
707 def check_multicore(self):
708 """ determine if the cards are save for multicore use"""
709@@ -1843,7 +1935,7 @@
710 elif hasattr(self, 'switch') and self.switch['reweight'] not in ['ON','OFF']:
711 plugin=self.switch['reweight']
712
713-
714+
715
716 # Check that MG5 directory is present .
717 if MADEVENT and not self.options['mg5_path']:
718@@ -1865,6 +1957,9 @@
719
720 # load the name of the event file
721 args = self.split_arg(line)
722+ if plugin and '--plugin=' not in line:
723+ args.append('--plugin=%s' % plugin)
724+
725
726 if not self.force_run:
727 # forbid this function to create an empty item in results.
728@@ -1884,8 +1979,6 @@
729 if not isinstance(self, cmd.CmdShell):
730 command.append('--web')
731 command.append('reweight')
732- if plugin:
733- command.append('--plugin=%s' % plugin)
734
735 ######### START SINGLE CORE MODE ############
736 if self.options['nb_core']==1 or self.run_card['nevents'] < 101 or not check_multicore(self):
737@@ -1971,6 +2064,8 @@
738
739 if '-from_cards' not in command:
740 new_command.append('-from_cards')
741+ if plugin:
742+ new_command.append('--plugin=%s' % plugin)
743 if i==0:
744 if __debug__:
745 stdout = None
746@@ -3214,7 +3309,10 @@
747 #Force class default
748 self.debug_output = CommonRunCmd.debug_output
749 if os.path.exists('ME5_debug') and not 'ME5_debug' in self.debug_output:
750- os.remove('ME5_debug')
751+ try:
752+ os.remove('ME5_debug')
753+ except Exception:
754+ pass
755 if not 'ME5_debug' in self.debug_output:
756 os.system('ln -s %s ME5_debug &> /dev/null' % self.debug_output)
757
758@@ -3245,6 +3343,15 @@
759 do_EOF = do_quit
760 do_exit = do_quit
761
762+ def __del__(self):
763+ """try to remove RunWeb?"""
764+
765+ if not self.stop_for_runweb and not self.force_run:
766+ try:
767+ os.remove(pjoin(self.me_dir,'RunWeb'))
768+ except Exception:
769+ pass
770+
771
772 def update_status(self, status, level, makehtml=True, force=True,
773 error=False, starttime = None, update_results=True,
774@@ -4084,56 +4191,31 @@
775
776 class AskforEditCard(cmd.OneLinePathCompletion):
777 """A class for asking a question where in addition you can have the
778- set command define and modifying the param_card/run_card correctly"""
779+ set command define and modifying the param_card/run_card correctly
780+
781+ special action can be trigger via trigger_XXXX when the user start a line
782+ with XXXX. the output of such function should be new line that can be handle.
783+ (return False to repeat the question)
784+ """
785
786 all_card_name = ['param_card', 'run_card', 'pythia_card', 'pythia8_card',
787 'madweight_card', 'MadLoopParams', 'shower_card']
788-
789- special_shortcut = {'ebeam':([float],['run_card ebeam1 %(0)s', 'run_card ebeam2 %(0)s']),
790- 'lpp': ([int],['run_card lpp1 %(0)s', 'run_card lpp2 %(0)s' ]),
791- 'lhc': ([int],['run_card lpp1 1', 'run_card lpp2 1', 'run_card ebeam1 %(0)s*1000/2', 'run_card ebeam2 %(0)s*1000/2']),
792- 'lep': ([int],['run_card lpp1 0', 'run_card lpp2 0', 'run_card ebeam1 %(0)s/2', 'run_card ebeam2 %(0)s/2']),
793- 'ilc': ([int],['run_card lpp1 0', 'run_card lpp2 0', 'run_card ebeam1 %(0)s/2', 'run_card ebeam2 %(0)s/2']),
794- 'lcc': ([int],['run_card lpp1 1', 'run_card lpp2 1', 'run_card ebeam1 %(0)s*1000/2', 'run_card ebeam2 %(0)s*1000/2']),
795- 'fixed_scale': ([float],['run_card fixed_fac_scale T', 'run_card fixed_ren_scale T', 'run_card scale %(0)s', 'run_card dsqrt_q2fact1 %(0)s' ,'run_card dsqrt_q2fact2 %(0)s']),
796- 'simplepy8':([],['pythia8_card hadronlevel:all False',
797- 'pythia8_card partonlevel:mpi False',
798- 'pythia8_card BeamRemnants:primordialKT False',
799- 'pythia8_card PartonLevel:Remnants False',
800- 'pythia8_card Check:event False',
801- 'pythia8_card TimeShower:QEDshowerByQ False',
802- 'pythia8_card TimeShower:QEDshowerByL False',
803- 'pythia8_card SpaceShower:QEDshowerByQ False',
804- 'pythia8_card SpaceShower:QEDshowerByL False',
805- 'pythia8_card PartonLevel:FSRinResonances False',
806- 'pythia8_card ProcessLevel:resonanceDecays False',
807- ]),
808- 'mpi':([bool],['pythia8_card partonlevel:mpi %(0)s']),
809- 'no_parton_cut':([],['run_card nocut T'])
810- }
811-
812- special_shortcut_help = {
813- 'ebeam' : 'syntax: set ebeam VALUE:\n This parameter sets the energy to both beam to the value in GeV',
814- 'lpp' : 'syntax: set ebeam VALUE:\n'+\
815- ' Set the type of beam to a given value for both beam\n'+\
816- ' 0 : means no PDF\n'+\
817- ' 1 : means proton PDF\n'+\
818- ' -1 : means antiproton PDF\n'+\
819- ' 2 : means PDF for elastic photon emited from a proton\n'+\
820- ' 3 : means PDF for elastic photon emited from an electron',
821- 'lhc' : 'syntax: set lhc VALUE:\n Set for a proton-proton collision with that given center of mass energy (in TeV)',
822- 'lep' : 'syntax: set lep VALUE:\n Set for a electron-positron collision with that given center of mass energy (in GeV)',
823- 'fixed_scale' : 'syntax: set fixed_scale VALUE:\n Set all scales to the give value (in GeV)',
824- 'simplepy8' : 'Turn off non-perturbative slow features of Pythia8.',
825- 'mpi' : 'syntax: set mpi value: allow to turn mpi in Pythia8 on/off'
826- }
827+ to_init_card = ['param', 'run', 'madweight', 'madloop',
828+ 'shower', 'pythia8','delphes','madspin']
829+ special_shortcut = {}
830+ special_shortcut_help = {}
831+
832+ integer_bias = 1 # integer corresponding to the first entry in self.cards
833+
834+ PY8Card_class = banner_mod.PY8Card
835
836 def load_default(self):
837 """ define all default variable. No load of card here.
838 This allow to subclass this class and just change init and still have
839 all variables defined."""
840
841- self.me_dir = None
842+ if not hasattr(self, 'me_dir'):
843+ self.me_dir = None
844 self.param_card = None
845 self.run_card = {}
846 self.pname2block = {}
847@@ -4146,6 +4228,7 @@
848 self.has_ml = False
849 self.has_shower = False
850 self.has_PY8 = False
851+ self.has_delphes = False
852 self.paths = {}
853
854
855@@ -4186,22 +4269,110 @@
856 self.paths['madanalysis5_hadron_default'] = pjoin(self.me_dir,'Cards','madanalysis5_hadron_card_default.dat')
857 self.paths['FO_analyse'] = pjoin(self.me_dir,'Cards', 'FO_analyse_card.dat')
858
859+
860+
861+
862 def __init__(self, question, cards=[], mode='auto', *args, **opt):
863
864+
865 self.load_default()
866 self.define_paths(**opt)
867+ self.last_editline_pos = 0
868+
869+ if 'allow_arg' not in opt or not opt['allow_arg']:
870+ # add some mininal content for this:
871+ opt['allow_arg'] = range(self.integer_bias, self.integer_bias+len(cards))
872+
873+ self.param_consistency = True
874+ if 'param_consistency' in opt:
875+ self.param_consistency = opt['param_consistency']
876+
877 cmd.OneLinePathCompletion.__init__(self, question, *args, **opt)
878
879-
880+ self.conflict = set()
881+ self.mode = mode
882+ self.cards = cards
883+ self.all_vars = set()
884+
885+ #update default path by custom one if specify in cards
886+ for card in cards:
887+ if os.path.exists(card):
888+ card_name = CommonRunCmd.detect_card_type(card)
889+ card_name = card_name.split('_',1)[0]
890+ self.paths[card_name] = card
891+
892+ # go trough the initialisation of each card and detect conflict
893+ for name in self.to_init_card:
894+ new_vars = set(getattr(self, 'init_%s' % name)(cards))
895+ new_conflict = self.all_vars.intersection(new_vars)
896+ self.conflict.union(new_conflict)
897+ self.all_vars.union(new_vars)
898+
899+ def get_path(self, name, cards):
900+ """initialise the path if requested"""
901+
902+ defname = '%s_default' % name
903+ if isinstance(cards, list):
904+ if name in cards:
905+ return True
906+ elif '%s_card.dat' % name in cards:
907+ return True
908+ elif name in self.paths and self.paths[name] in cards:
909+ return True
910+ else:
911+ cardnames = [os.path.basename(p) for p in cards]
912+ if '%s_card.dat' % name in cardnames:
913+ return True
914+ else:
915+ return False
916+
917+ elif isinstance(cards, dict) and name in cards:
918+ self.paths[name]= cards[name]
919+ if defname in cards:
920+ self.paths[defname] = cards[defname]
921+ elif os.path.isfile(cards[name].replace('.dat', '_default.dat')):
922+ self.paths[defname] = cards[name].replace('.dat', '_default.dat')
923+ else:
924+ self.paths[defname] = self.paths[name]
925+
926+ return True
927+ else:
928+ return False
929+
930+ def init_param(self, cards):
931+ """check if we need to load the param_card"""
932+
933+ self.pname2block = {}
934+ self.restricted_value = {}
935+ self.param_card = {}
936+ if not self.get_path('param', cards):
937+ self.param_consistency = False
938+ return []
939+
940 try:
941 self.param_card = check_param_card.ParamCard(self.paths['param'])
942 except (check_param_card.InvalidParamCard, ValueError) as e:
943 logger.error('Current param_card is not valid. We are going to use the default one.')
944 logger.error('problem detected: %s' % e)
945 files.cp(self.paths['param_default'], self.paths['param'])
946- self.param_card = check_param_card.ParamCard(self.paths['param'])
947- default_param = check_param_card.ParamCard(self.paths['param_default'])
948+ self.param_card = check_param_card.ParamCard(self.paths['param'])
949+
950+ # Read the comment of the param_card_default to find name variable for
951+ # the param_card also check which value seems to be constrained in the
952+ # model.
953+ if os.path.exists(self.paths['param_default']):
954+ default_param = check_param_card.ParamCard(self.paths['param_default'])
955+ else:
956+ default_param = check_param_card.ParamCard(self.param_card)
957+ self.pname2block, self.restricted_value = default_param.analyze_param_card()
958 self.param_card_default = default_param
959+ return self.pname2block.keys()
960+
961+ def init_run(self, cards):
962+
963+ self.run_set = []
964+ if not self.get_path('run', cards):
965+ return []
966
967 try:
968 self.run_card = banner_mod.RunCard(self.paths['run'], consistency='warning')
969@@ -4212,124 +4383,186 @@
970 except IOError:
971 run_card_def = {}
972
973- self.pname2block = {}
974- self.conflict = []
975- self.restricted_value = {}
976- self.mode = mode
977- self.cards = cards
978- self.last_editline_pos=0
979-
980- # Read the comment of the param_card_default to find name variable for
981- # the param_card also check which value seems to be constrained in the
982- # model.
983- self.pname2block, self.restricted_value = \
984- default_param.analyze_param_card()
985-
986 if run_card_def:
987- self.run_set = run_card_def.keys() + self.run_card.hidden_param
988+ if self.run_card:
989+ self.run_set = run_card_def.keys() + self.run_card.hidden_param
990+ else:
991+ self.run_set = run_card_def.keys() + run_card_def.hidden_param
992 elif self.run_card:
993 self.run_set = self.run_card.keys()
994 else:
995 self.run_set = []
996- # check for conflict with run_card
997- for var in self.pname2block:
998- if var in self.run_set:
999- self.conflict.append(var)
1000-
1001-
1002- self.has_delphes = False
1003- if 'delphes_card.dat' in cards:
1004- self.has_delphes = True
1005-
1006- #check if Madweight_card is present:
1007+
1008+ if self.run_set:
1009+ self.special_shortcut.update(
1010+ {'ebeam':([float],['run_card ebeam1 %(0)s', 'run_card ebeam2 %(0)s']),
1011+ 'lpp': ([int],['run_card lpp1 %(0)s', 'run_card lpp2 %(0)s' ]),
1012+ 'lhc': ([int],['run_card lpp1 1', 'run_card lpp2 1', 'run_card ebeam1 %(0)s*1000/2', 'run_card ebeam2 %(0)s*1000/2']),
1013+ 'lep': ([int],['run_card lpp1 0', 'run_card lpp2 0', 'run_card ebeam1 %(0)s/2', 'run_card ebeam2 %(0)s/2']),
1014+ 'ilc': ([int],['run_card lpp1 0', 'run_card lpp2 0', 'run_card ebeam1 %(0)s/2', 'run_card ebeam2 %(0)s/2']),
1015+ 'lcc': ([int],['run_card lpp1 1', 'run_card lpp2 1', 'run_card ebeam1 %(0)s*1000/2', 'run_card ebeam2 %(0)s*1000/2']),
1016+ 'fixed_scale': ([float],['run_card fixed_fac_scale T', 'run_card fixed_ren_scale T', 'run_card scale %(0)s', 'run_card dsqrt_q2fact1 %(0)s' ,'run_card dsqrt_q2fact2 %(0)s']),
1017+ 'no_parton_cut':([],['run_card nocut T']),
1018+ 'cm_velocity':([float], [lambda self :self.set_CM_velocity])
1019+ })
1020+
1021+ self.special_shortcut_help.update({
1022+ 'ebeam' : 'syntax: set ebeam VALUE:\n This parameter sets the energy to both beam to the value in GeV',
1023+ 'lpp' : 'syntax: set ebeam VALUE:\n'+\
1024+ ' Set the type of beam to a given value for both beam\n'+\
1025+ ' 0 : means no PDF\n'+\
1026+ ' 1 : means proton PDF\n'+\
1027+ ' -1 : means antiproton PDF\n'+\
1028+ ' 2 : means PDF for elastic photon emited from a proton\n'+\
1029+ ' 3 : means PDF for elastic photon emited from an electron',
1030+ 'lhc' : 'syntax: set lhc VALUE:\n Set for a proton-proton collision with that given center of mass energy (in TeV)',
1031+ 'lep' : 'syntax: set lep VALUE:\n Set for a electron-positron collision with that given center of mass energy (in GeV)',
1032+ 'fixed_scale' : 'syntax: set fixed_scale VALUE:\n Set all scales to the give value (in GeV)',
1033+ 'no_parton_cut': 'remove all cut (but BW_cutoff)',
1034+ 'cm_velocity': 'set sqrts to have the above velocity for the incoming particles',
1035+ })
1036+
1037+ return self.run_set
1038+
1039+ def init_madweight(self, cards):
1040+
1041 self.has_mw = False
1042- if 'madweight_card.dat' in cards:
1043-
1044- self.do_change_tf = self.mother_interface.do_define_transfer_fct
1045- self.complete_change_tf = self.mother_interface.complete_define_transfer_fct
1046- self.help_change_tf = self.mother_interface.help_define_transfer_fct
1047- if not os.path.exists(self.paths['transfer']):
1048- logger.warning('No transfer function currently define. Please use the change_tf command to define one.')
1049-
1050-
1051- self.has_mw = True
1052- try:
1053- import madgraph.madweight.Cards as mwcards
1054- except:
1055- import internal.madweight.Cards as mwcards
1056- self.mw_card = mwcards.Card(self.paths['MadWeight'])
1057- self.mw_card = self.mw_card.info
1058- self.mw_vars = []
1059- for key in self.mw_card:
1060- if key == 'comment':
1061- continue
1062- for key2 in self.mw_card.info[key]:
1063- if isinstance(key2, str) and not key2.isdigit():
1064- self.mw_vars.append(key2)
1065-
1066- # check for conflict with run_card/param_card
1067- for var in self.pname2block:
1068- if var in self.mw_vars:
1069- self.conflict.append(var)
1070- for var in self.mw_vars:
1071- if var in self.run_card:
1072- self.conflict.append(var)
1073-
1074- #check if MadLoopParams.dat is present:
1075+ if not self.get_path('madweight', cards):
1076+ return []
1077+
1078+ #add special function associated to MW
1079+ self.do_change_tf = self.mother_interface.do_define_transfer_fct
1080+ self.complete_change_tf = self.mother_interface.complete_define_transfer_fct
1081+ self.help_change_tf = self.mother_interface.help_define_transfer_fct
1082+ if not os.path.exists(self.paths['transfer']):
1083+ logger.warning('No transfer function currently define. Please use the change_tf command to define one.')
1084+
1085+ self.has_mw = True
1086+ try:
1087+ import madgraph.madweight.Cards as mwcards
1088+ except:
1089+ import internal.madweight.Cards as mwcards
1090+ self.mw_card = mwcards.Card(self.paths['MadWeight'])
1091+ self.mw_card = self.mw_card.info
1092+ self.mw_vars = []
1093+ for key in self.mw_card:
1094+ if key == 'comment':
1095+ continue
1096+ for key2 in self.mw_card.info[key]:
1097+ if isinstance(key2, str) and not key2.isdigit():
1098+ self.mw_vars.append(key2)
1099+ return self.mw_vars
1100+
1101+ def init_madloop(self, cards):
1102+
1103+ if isinstance(cards, dict):
1104+ for key in ['ML', 'madloop','MadLoop']:
1105+ if key in cards:
1106+ self.paths['ML'] = cards[key]
1107+
1108 self.has_ml = False
1109 if os.path.isfile(self.paths['ML']):
1110 self.has_ml = True
1111 self.MLcard = banner_mod.MadLoopParam(self.paths['ML'])
1112 self.MLcardDefault = banner_mod.MadLoopParam()
1113-
1114 self.ml_vars = [k.lower() for k in self.MLcard.keys()]
1115- # check for conflict
1116- for var in self.ml_vars:
1117- if var in self.run_card:
1118- self.conflict.append(var)
1119- if var in self.pname2block:
1120- self.conflict.append(var)
1121- if self.has_mw and var in self.mw_vars:
1122- self.conflict.append(var)
1123-
1124- #check if shower_card is present:
1125+ return self.ml_vars
1126+ return []
1127+
1128+ def init_shower(self, cards):
1129+
1130 self.has_shower = False
1131- if 'shower_card.dat' in cards:
1132- self.has_shower = True
1133- self.shower_card = shower_card_mod.ShowerCard(self.paths['shower'])
1134- self.shower_vars = self.shower_card.keys()
1135-
1136- # check for conflict with run_card/param_card
1137- for var in self.pname2block:
1138- if var in self.shower_vars:
1139- self.conflict.append(var)
1140- for var in self.shower_vars:
1141- if var in self.run_card:
1142- self.conflict.append(var)
1143-
1144- #check if pythia8_card.dat is present:
1145+ if not self.get_path('shower', cards):
1146+ return []
1147+ self.has_shower = True
1148+ self.shower_card = shower_card_mod.ShowerCard(self.paths['shower'])
1149+ self.shower_vars = self.shower_card.keys()
1150+ return self.shower_vars
1151+
1152+ def init_pythia8(self, cards):
1153+
1154 self.has_PY8 = False
1155- if 'pythia8_card.dat' in cards:
1156- self.has_PY8 = True
1157- self.PY8Card = banner_mod.PY8Card(self.paths['pythia8'])
1158- self.PY8CardDefault = banner_mod.PY8Card()
1159-
1160- self.py8_vars = [k.lower() for k in self.PY8Card.keys()]
1161- # check for conflict
1162- for var in self.py8_vars:
1163- if var in self.run_card:
1164- self.conflict.append(var)
1165- if var in self.pname2block:
1166- self.conflict.append(var)
1167- if self.has_mw and var in self.mw_vars:
1168- self.conflict.append(var)
1169- if self.has_ml and var in self.ml_vars:
1170- self.conflict.append(var)
1171-
1172- def do_help(self, line, conflict_raise=False, banner=True):
1173+ if not self.get_path('pythia8', cards):
1174+ return []
1175+
1176+ self.has_PY8 = True
1177+ self.PY8Card = self.PY8Card_class(self.paths['pythia8'])
1178+ self.PY8CardDefault = self.PY8Card_class()
1179+
1180+ self.py8_vars = [k.lower() for k in self.PY8Card.keys()]
1181+
1182+ self.special_shortcut.update({
1183+ 'simplepy8':([],['pythia8_card hadronlevel:all False',
1184+ 'pythia8_card partonlevel:mpi False',
1185+ 'pythia8_card BeamRemnants:primordialKT False',
1186+ 'pythia8_card PartonLevel:Remnants False',
1187+ 'pythia8_card Check:event False',
1188+ 'pythia8_card TimeShower:QEDshowerByQ False',
1189+ 'pythia8_card TimeShower:QEDshowerByL False',
1190+ 'pythia8_card SpaceShower:QEDshowerByQ False',
1191+ 'pythia8_card SpaceShower:QEDshowerByL False',
1192+ 'pythia8_card PartonLevel:FSRinResonances False',
1193+ 'pythia8_card ProcessLevel:resonanceDecays False',
1194+ ]),
1195+ 'mpi':([bool],['pythia8_card partonlevel:mpi %(0)s']),
1196+ })
1197+ self.special_shortcut_help.update({
1198+ 'simplepy8' : 'Turn off non-perturbative slow features of Pythia8.',
1199+ 'mpi' : 'syntax: set mpi value: allow to turn mpi in Pythia8 on/off',
1200+ })
1201+ return []
1202+
1203+ def init_madspin(self, cards):
1204+
1205+ if not self.get_path('madspin', cards):
1206+ return []
1207+
1208+ self.special_shortcut.update({
1209+ 'spinmode':([str], ['add madspin_card --before_line="launch" set spinmode %(0)s'])
1210+ })
1211+ self.special_shortcut_help.update({
1212+ 'spinmode' : 'full|none|onshell. Choose the mode of madspin.\n - full: spin-correlation and off-shell effect\n - onshell: only spin-correlation,]\n - none: no spin-correlation and not offshell effects.'
1213+ })
1214+ return []
1215+
1216+ def init_delphes(self, cards):
1217+
1218+ self.has_delphes = False
1219+ if not self.get_path('pythia8', cards):
1220+ return []
1221+ self.has_delphes = True
1222+ return []
1223+
1224+
1225+ def set_CM_velocity(self, line):
1226+ """compute sqrts from the velocity in the center of mass frame"""
1227+
1228+ v = banner_mod.ConfigFile.format_variable(line, float, 'velocity')
1229+ # Define self.proc_characteristics
1230+ self.mother_interface.get_characteristics()
1231+ proc_info = self.mother_interface.proc_characteristics
1232+ if 'pdg_initial1' not in proc_info:
1233+ logger.warning('command not supported')
1234+
1235+ if len(proc_info['pdg_initial1']) == 1 == len(proc_info['pdg_initial2']) and\
1236+ abs(proc_info['pdg_initial1'][0]) == abs(proc_info['pdg_initial2'][0]):
1237+
1238+ m = self.param_card.get_value('mass', abs(proc_info['pdg_initial1'][0]))
1239+ sqrts = 2*m/ math.sqrt(1-v**2)
1240+ self.do_set('run_card ebeam1 %s' % (sqrts/2.0))
1241+ self.do_set('run_card ebeam2 %s' % (sqrts/2.0))
1242+ self.do_set('run_card lpp 0')
1243+ else:
1244+ logger.warning('This is only possible for a single particle in the initial state')
1245+
1246+
1247+
1248+ def do_help(self, line, conflict_raise=False, banner=True):
1249+ # TODO nicer factorization !
1250+
1251 # try:
1252 if banner:
1253- logger.info('*** HELP MESSAGE ***', '$MG:color:BLACK')
1254+ logger.info('*** HELP MESSAGE ***', '$MG:BOLD')
1255
1256 args = self.split_arg(line)
1257 # handle comand related help
1258@@ -4346,7 +4579,7 @@
1259 print '\t'.join(self.special_shortcut)
1260 print
1261 if banner:
1262- logger.info('*** END HELP ***', '$MG:color:BLACK')
1263+ logger.info('*** END HELP ***', '$MG:BOLD')
1264 return out
1265 # check for special shortcut.
1266 # special shortcut:
1267@@ -4354,7 +4587,7 @@
1268 if args[0] in self.special_shortcut_help:
1269 print self.special_shortcut_help[args[0]]
1270 if banner:
1271- logger.info('*** END HELP ***', '$MG:color:BLACK')
1272+ logger.info('*** END HELP ***', '$MG:BOLD')
1273 return
1274
1275 start = 0
1276@@ -4391,8 +4624,8 @@
1277 logger.info("List of parameter associated", '$MG:color:BLUE')
1278 print "\t".join(eval('self.%s' % args[0]).keys())
1279 if banner:
1280- logger.info('*** END HELP ***', '$MG:color:BLACK')
1281- return
1282+ logger.info('*** END HELP ***', '$MG:BOLD')
1283+ return card
1284
1285 #### RUN CARD
1286 if args[start] in [l.lower() for l in self.run_card.keys()] and card in ['', 'run_card']:
1287@@ -4401,9 +4634,9 @@
1288
1289 if args[start] in self.conflict and not conflict_raise:
1290 conflict_raise = True
1291- logger.info('** AMBIGUOUS NAME: %s **', args[start], '$MG:color:BLACK')
1292+ logger.info('** AMBIGUOUS NAME: %s **', args[start], '$MG:BOLD')
1293 if card == '':
1294- logger.info('** If not explicitely speficy this parameter will modif the run_card file', '$MG:color:BLACK')
1295+ logger.info('** If not explicitely speficy this parameter will modif the run_card file', '$MG:BOLD')
1296
1297 self.run_card.do_help(args[start])
1298 ### PARAM_CARD WITH BLOCK NAME -----------------------------------------
1299@@ -4436,7 +4669,7 @@
1300 key = tuple([int(i) for i in args[start+1:]])
1301 except ValueError:
1302 logger.warning('Failed to identify LHA information')
1303- return
1304+ return card
1305
1306 if key in self.param_card[args[start]].param_dict:
1307 self.param_card.do_help(args[start], key, default=self.param_card_default)
1308@@ -4481,13 +4714,13 @@
1309 print 'MA5'
1310
1311
1312- else:
1313+ elif banner:
1314 print "no help available"
1315
1316 if banner:
1317 logger.info('*** END HELP ***', '$MG:color:BLACK')
1318 #raw_input('press enter to quit the help')
1319- return
1320+ return card
1321 # except Exception, error:
1322 # if __debug__:
1323 # import traceback
1324@@ -4522,8 +4755,9 @@
1325
1326 arg = line[:begidx].split()
1327 if len(arg) <=1:
1328- return self.list_completion(text, ['dependent', 'missing', 'to_slha1', 'to_slha2'], line)
1329-
1330+ return self.list_completion(text, ['dependent', 'missing', 'to_slha1', 'to_slha2', 'to_full'], line)
1331+ elif arg[0] == 'to_full':
1332+ return self.list_completion(text, self.cards , line)
1333
1334 def complete_set(self, text, line, begidx, endidx, formatting=True):
1335 """ Complete the set command"""
1336@@ -4560,7 +4794,7 @@
1337 allowed = {'run_card':'default'}
1338 elif args[1] == 'param_card':
1339 allowed = {'block':'all', 'param_card':'default'}
1340- elif args[1] in self.param_card.keys():
1341+ elif self.param_card and args[1] in self.param_card.keys():
1342 allowed = {'block':args[1]}
1343 elif args[1] == 'width':
1344 allowed = {'block': 'decay'}
1345@@ -4689,12 +4923,13 @@
1346
1347 possibilities['Special Value'] = self.list_completion(text, opts)
1348
1349- if 'block' in allowed.keys():
1350- if allowed['block'] == 'all':
1351+ if 'block' in allowed.keys() and self.param_card:
1352+ if allowed['block'] == 'all' and self.param_card:
1353 allowed_block = [i for i in self.param_card.keys() if 'qnumbers' not in i]
1354 allowed_block.append('width')
1355 possibilities['Param Card Block' ] = \
1356 self.list_completion(text, allowed_block)
1357+
1358 elif isinstance(allowed['block'], basestring):
1359 block = self.param_card[allowed['block']].param_dict
1360 ids = [str(i[0]) for i in block
1361@@ -4750,6 +4985,8 @@
1362
1363
1364 args = self.split_arg(line)
1365+
1366+
1367 if len(args) == 0:
1368 logger.warning("No argument. For help type 'help set'.")
1369 # fix some formatting problem
1370@@ -4776,20 +5013,35 @@
1371 except ValueError as e:
1372 logger.warning("Wrong argument: The entry #%s should be of type %s.", i+1, argtype)
1373 return
1374+ except InvalidCmd as e:
1375+ logger.warning(str(e))
1376+ return
1377 #else:
1378 # logger.warning("too many argument for this command")
1379 # return
1380 for arg in cmd:
1381- try:
1382- text = arg % values
1383- except KeyError:
1384- logger.warning("This command requires one argument")
1385- return
1386- except Exception as e:
1387- logger.warning(str(e))
1388- return
1389+ if isinstance(arg, str):
1390+ try:
1391+ text = arg % values
1392+ except KeyError:
1393+ logger.warning("This command requires one argument")
1394+ return
1395+ except Exception as e:
1396+ logger.warning(str(e))
1397+ return
1398+ else:
1399+ split = text.split()
1400+ if hasattr(self, 'do_%s' % split[0]):
1401+ getattr(self, 'do_%s' % split[0])(' '.join(split[1:]))
1402+ else:
1403+ self.do_set(text)
1404+ #need to call a function
1405 else:
1406- self.do_set(arg % values)
1407+ val = [values[str(i)] for i in range(len(values))]
1408+ try:
1409+ arg(self)(*val)
1410+ except Exception, e:
1411+ logger.warning(str(e))
1412 return
1413
1414
1415@@ -4902,7 +5154,7 @@
1416 elif args[0] in ['pythia8_card']:
1417 if args[1] == 'default':
1418 logger.info('replace pythia8_card.dat by the default card','$MG:color:BLACK')
1419- self.PY8Card = banner_mod.PY8Card(self.PY8CardDefault)
1420+ self.PY8Card = self.PY8Card_class(self.PY8CardDefault)
1421 self.PY8Card.write(pjoin(self.me_dir,'Cards','pythia8_card.dat'),
1422 pjoin(self.me_dir,'Cards','pythia8_card_default.dat'),
1423 print_only_visible=True)
1424@@ -5308,7 +5560,7 @@
1425 self.do_set('run_card store_rwgt_info True')
1426
1427 # @LO if PY6 shower => event_norm on sum
1428- if 'pythia_card.dat' in self.cards:
1429+ if 'pythia_card.dat' in self.cards and 'run' in self.allow_arg:
1430 if self.run_card['event_norm'] != 'sum':
1431 logger.info('Pythia6 needs a specific normalisation of the events. We will change it accordingly.', '$MG:color:BLACK' )
1432 self.do_set('run_card event_norm sum')
1433@@ -5391,19 +5643,20 @@
1434
1435 if ending_question:
1436 self.check_card_consistency()
1437- try:
1438- self.do_update('dependent', timer=20)
1439- except MadGraph5Error, error:
1440- if 'Missing block:' in str(error):
1441- self.fail_due_to_format +=1
1442- if self.fail_due_to_format == 10:
1443- missing, unknow = str(error).split('\n')[-2:]
1444- logger.warning("Invalid param_card:\n%s\n%s\n" % (missing, unknow))
1445- logger.info("Type \"update missing\" to use default value.\n ", '$MG:color:BLACK')
1446- self.value = False # to avoid that entering a command stop the question
1447- return self.reask(True)
1448- else:
1449- raise
1450+ if self.param_consistency:
1451+ try:
1452+ self.do_update('dependent', timer=20)
1453+ except MadGraph5Error, error:
1454+ if 'Missing block:' in str(error):
1455+ self.fail_due_to_format +=1
1456+ if self.fail_due_to_format == 10:
1457+ missing, unknow = str(error).split('\n')[-2:]
1458+ logger.warning("Invalid param_card:\n%s\n%s\n" % (missing, unknow))
1459+ logger.info("Type \"update missing\" to use default value.\n ", '$MG:color:BLACK')
1460+ self.value = False # to avoid that entering a command stop the question
1461+ return self.reask(True)
1462+ else:
1463+ raise
1464
1465 return ending_question
1466
1467@@ -5415,8 +5668,9 @@
1468 """ syntax: update dependent: Change the mass/width of particles which are not free parameter for the model.
1469 update missing: add to the current param_card missing blocks/parameters.
1470 update to_slha1: pass SLHA2 card to SLHA1 convention. (beta)
1471- update to_slha2: pass SLHA1 card to SLHA2 convention. (beta)"""
1472-
1473+ update to_slha2: pass SLHA1 card to SLHA2 convention. (beta)
1474+ update to_full [run_card]
1475+ """
1476 args = self.split_arg(line)
1477 if len(args)==0:
1478 logger.warning('miss an argument (dependent or missing). Please retry')
1479@@ -5461,7 +5715,16 @@
1480 except Exception, error:
1481 logger.warning('failed to update to slha1 due to %s' % error)
1482 self.param_card = check_param_card.ParamCard(self.paths['param'])
1483-
1484+ elif args[0] == 'to_full':
1485+ return self.update_to_full(args[1:])
1486+
1487+
1488+ def update_to_full(self, line):
1489+ """ trigger via update to_full LINE"""
1490+
1491+ logger.info("update the run_card by including all the hidden parameter")
1492+ self.run_card.write(self.paths['run'], self.paths['run_default'], write_hidden=True)
1493+
1494 @staticmethod
1495 def update_dependent(mecmd, me_dir, param_card, path ,timer=0):
1496 """static method which can also be called from outside the class
1497@@ -5471,6 +5734,7 @@
1498
1499 if not param_card:
1500 return False
1501+
1502 logger.info('Update the dependent parameter of the param_card.dat')
1503 modify = True
1504 class TimeOutError(Exception):
1505@@ -5638,12 +5902,34 @@
1506 logger.info(' set run_card default')
1507 logger.info('********************* HELP SET ***************************')
1508
1509+ def trigger(self, line):
1510+
1511+ line = line.strip()
1512+ args = line.split()
1513+
1514+ if not args:
1515+ return line
1516+ if not hasattr(self, 'trigger_%s' % args[0]):
1517+ return line
1518+
1519+ triggerfct = getattr(self, 'trigger_%s' % args[0])
1520+
1521+ # run the trigger function
1522+ outline = triggerfct(' '.join(args[1:]))
1523+ if not outline:
1524+ return 'repeat'
1525+ return outline
1526
1527 def default(self, line):
1528 """Default action if line is not recognized"""
1529
1530+ # check if the line need to be modified by a trigger
1531+ line = self.trigger(line)
1532+
1533+ # splitting the line
1534 line = line.strip()
1535 args = line.split()
1536+
1537 if line == '' and self.default_value is not None:
1538 self.value = self.default_value
1539 # check if input is a file
1540@@ -5681,6 +5967,7 @@
1541
1542 return line
1543
1544+
1545 def do_decay(self, line):
1546 """edit the madspin_card to define the decay of the associate particle"""
1547 signal.alarm(0) # avoid timer if any
1548@@ -5841,7 +6128,7 @@
1549 pjoin(self.me_dir,'Cards','pythia8_card_default.dat'),
1550 print_only_visible=True)
1551 logger.info("add in the pythia8_card the parameter \"%s\" with value \"%s\"" % (name, value), '$MG:color:BLACK')
1552- elif len(args) > 0:
1553+ elif len(args) > 0:
1554 if args[0] in self.cards:
1555 card = args[0]
1556 elif "%s.dat" % args[0] in self.cards:
1557@@ -5853,46 +6140,56 @@
1558 else:
1559 logger.error("unknow card %s. Please retry." % args[0])
1560 return
1561+
1562+ if card in self.paths:
1563+ path = self.paths[card]
1564+ elif os.path.exists(card):
1565+ path = card
1566+ elif os.path.exists(pjoin(self.me_dir,'Cards',card)):
1567+ path = pjoin(self.me_dir,'Cards',card)
1568+ else:
1569+ raise Exception, 'unknow path'
1570+
1571 # handling the various option on where to write the line
1572 if args[1] == '--clean':
1573- ff = open(pjoin(self.me_dir,'Cards',card),'w')
1574+ ff = open(path,'w')
1575 ff.write("# %s \n" % card)
1576 ff.write("%s \n" % line.split(None,2)[2])
1577 ff.close()
1578 logger.info("writing the line in %s (empty file) the line: \"%s\"" %(card, line.split(None,2)[2] ),'$MG:color:BLACK')
1579 elif args[1].startswith('--line_position=afterlast'):
1580 #position in file determined by user
1581- text = open(pjoin(self.me_dir,'Cards',card)).read()
1582+ text = open(path).read()
1583 split = text.split('\n')
1584 if self.last_editline_pos > 0:
1585 pos = self.last_editline_pos +1
1586 newline = line.split(None,2)[2]
1587 split.insert(pos, newline)
1588- ff = open(pjoin(self.me_dir,'Cards',card),'w')
1589+ ff = open(path,'w')
1590 ff.write('\n'.join(split))
1591 logger.info("writting at line %d of the file %s the line: \"%s\"" %(pos, card, line.split(None,2)[2] ),'$MG:color:BLACK')
1592 self.last_editline_pos = pos
1593 elif args[1].startswith('--line_position='):
1594 #position in file determined by user
1595- text = open(pjoin(self.me_dir,'Cards',card)).read()
1596+ text = open(path).read()
1597 split = text.split('\n')
1598 pos = int(args[1].split('=',1)[1])
1599 newline = line.split(None,2)[2]
1600 split.insert(pos, newline)
1601- ff = open(pjoin(self.me_dir,'Cards',card),'w')
1602+ ff = open(path,'w')
1603 ff.write('\n'.join(split))
1604 logger.info("writting at line %d of the file %s the line: \"%s\"" %(pos, card, line.split(None,2)[2] ),'$MG:color:BLACK')
1605 self.last_editline_pos = pos
1606
1607 elif args[1].startswith('--after_line=banner'):
1608 # write the line at the first not commented line
1609- text = open(pjoin(self.me_dir,'Cards',card)).read()
1610+ text = open(path).read()
1611 split = text.split('\n')
1612 for posline,l in enumerate(split):
1613 if not l.startswith('#'):
1614 break
1615 split.insert(posline, line.split(None,2)[2])
1616- ff = open(pjoin(self.me_dir,'Cards',card),'w')
1617+ ff = open(path,'w')
1618 ff.write('\n'.join(split))
1619 logger.info("writting at line %d of the file %s the line: \"%s\"" %(posline, card, line.split(None,2)[2] ),'$MG:color:BLACK')
1620 self.last_editline_pos = posline
1621@@ -5900,7 +6197,7 @@
1622 elif args[1].startswith('--replace_line='):
1623 # catch the line/regular expression and replace the associate line
1624 # if no line match go to check if args[2] has other instruction starting with --
1625- text = open(pjoin(self.me_dir,'Cards',card)).read()
1626+ text = open(path).read()
1627 split = text.split('\n')
1628 search_pattern=r'''replace_line=(?P<quote>["'])(?:(?=(\\?))\2.)*?\1'''
1629 pattern = '^\s*' + re.search(search_pattern, line).group()[14:-1]
1630@@ -5921,7 +6218,7 @@
1631 # overwrite the previous line
1632 old_line = split[posline]
1633 split[posline] = new_line
1634- ff = open(pjoin(self.me_dir,'Cards',card),'w')
1635+ ff = open(path,'w')
1636 ff.write('\n'.join(split))
1637 logger.info("Replacing the line \"%s\" [line %d of %s] by \"%s\"" %
1638 (old_line, posline, card, new_line ),'$MG:color:BLACK')
1639@@ -5930,7 +6227,7 @@
1640
1641 elif args[1].startswith('--before_line='):
1642 # catch the line/regular expression and write before that line
1643- text = open(pjoin(self.me_dir,'Cards',card)).read()
1644+ text = open(path).read()
1645 split = text.split('\n')
1646 search_pattern=r'''before_line=(?P<quote>["'])(?:(?=(\\?))\2.)*?\1'''
1647 pattern = '^\s*' + re.search(search_pattern, line).group()[13:-1]
1648@@ -5940,14 +6237,14 @@
1649 else:
1650 raise Exception, 'invalid regular expression: not found in file'
1651 split.insert(posline, re.split(search_pattern,line)[-1])
1652- ff = open(pjoin(self.me_dir,'Cards',card),'w')
1653+ ff = open(path,'w')
1654 ff.write('\n'.join(split))
1655 logger.info("writting at line %d of the file %s the line: \"%s\"" %(posline, card, line.split(None,2)[2] ),'$MG:color:BLACK')
1656 self.last_editline_pos = posline
1657
1658 elif args[1].startswith('--after_line='):
1659 # catch the line/regular expression and write after that line
1660- text = open(pjoin(self.me_dir,'Cards',card)).read()
1661+ text = open(path).read()
1662 split = text.split('\n')
1663 search_pattern = r'''after_line=(?P<quote>["'])(?:(?=(\\?))\2.)*?\1'''
1664 pattern = '^\s*' + re.search(search_pattern, line).group()[12:-1]
1665@@ -5957,19 +6254,20 @@
1666 else:
1667 posline=len(split)
1668 split.insert(posline+1, re.split(search_pattern,line)[-1])
1669- ff = open(pjoin(self.me_dir,'Cards',card),'w')
1670+ ff = open(path,'w')
1671 ff.write('\n'.join(split))
1672- logger.info("writting at line %d o the file %s the line: \"%s\"" %(posline, card, line.split(None,1)[1] ),'$MG:color:BLACK')
1673+
1674+ logger.info("writting at line %d of the file %s the line: \"%s\"" %(posline, card, line.split(None,2)[2] ),'$MG:color:BLACK')
1675 self.last_editline_pos = posline
1676
1677 else:
1678- ff = open(pjoin(self.me_dir,'Cards',card),'a')
1679+ ff = open(path,'a')
1680 ff.write("%s \n" % line.split(None,1)[1])
1681 ff.close()
1682 logger.info("adding at the end of the file %s the line: \"%s\"" %(card, line.split(None,1)[1] ),'$MG:color:BLACK')
1683 self.last_editline_pos = -1
1684
1685- self.reload_card(pjoin(self.me_dir,'Cards',card))
1686+ self.reload_card(path)
1687
1688 do_edit = do_add
1689 complete_edit = complete_add
1690@@ -6052,7 +6350,7 @@
1691 self.do_set('mw_run inputfile %s' % os.path.relpath(path, self.mother_interface.me_dir))
1692 return
1693 else:
1694- card_name = CommonRunCmd.detect_card_type(path)
1695+ card_name = self.detect_card_type(path)
1696
1697 if card_name == 'unknown':
1698 logger.warning('Fail to determine the type of the file. Not copied')
1699@@ -6068,6 +6366,11 @@
1700 for card_name in self.cards:
1701 self.reload_card(pjoin(self.me_dir, 'Cards', card_name))
1702
1703+ def detect_card_type(self, path):
1704+ """detect card type"""
1705+
1706+ return CommonRunCmd.detect_card_type(path)
1707+
1708 def open_file(self, answer):
1709 """open the file"""
1710 try:
1711@@ -6079,7 +6382,7 @@
1712 if answer == '9':
1713 answer = 'plot'
1714 else:
1715- answer = self.cards[int(answer)-1]
1716+ answer = self.cards[int(answer)-self.integer_bias]
1717
1718 if 'madweight' in answer:
1719 answer = answer.replace('madweight', 'MadWeight')
1720@@ -6147,7 +6450,7 @@
1721 # Use the read function so that modified/new parameters are correctly
1722 # set as 'user_set'
1723 if not self.PY8Card:
1724- self.PY8Card = banner_mod.PY8Card(self.paths['pythia8_default'])
1725+ self.PY8Card = self.PY8Card_class(self.paths['pythia8_default'])
1726
1727 self.PY8Card.read(self.paths['pythia8'], setter='user')
1728 self.py8_vars = [k.lower() for k in self.PY8Card.keys()]
1729@@ -6161,29 +6464,3 @@
1730 logger.debug('not keep in sync: %s', path)
1731 return path
1732
1733-class EditParamCard(AskforEditCard):
1734- """a dedicated module for the param"""
1735-
1736- special_shortcut ={}
1737-
1738- def __init__(self, question, card=[], mode='auto', *args, **opt):
1739-
1740- self.load_default()
1741- cmd.OneLinePathCompletion.__init__(self, question, *args, **opt)
1742- if os.path.isfile(card[0]):
1743- self.param_card = check_param_card.ParamCard(card[0])
1744- self.paths['param'] = card[0]
1745- if os.path.isfile(card[0].replace('.dat', '_default.dat')):
1746- self.paths['param_default'] = card[0].replace('.dat', '_default.dat')
1747- else:
1748- self.paths['param_default'] = card[0]
1749- else:
1750- raise Exception, 'path %s do not exists' % card[0]
1751-
1752- self.pname2block, self.restricted_value = self.param_card.analyze_param_card()
1753- self.cards=['param']
1754-
1755- def do_asperge(self, *args, **opts):
1756- "Not available"
1757- logger.warning("asperge not available in this mode")
1758-
1759
1760=== modified file 'madgraph/interface/extended_cmd.py'
1761--- madgraph/interface/extended_cmd.py 2018-02-21 22:35:09 +0000
1762+++ madgraph/interface/extended_cmd.py 2018-04-20 08:32:43 +0000
1763@@ -12,7 +12,6 @@
1764 # For more information, visit madgraph.phys.ucl.ac.be and amcatnlo.web.cern.ch
1765 #
1766 ################################################################################
1767-from __builtin__ import True
1768 """ A file containing different extension of the cmd basic python library"""
1769
1770
1771@@ -35,6 +34,8 @@
1772
1773 logger = logging.getLogger('cmdprint') # for stdout
1774 logger_stderr = logging.getLogger('fatalerror') # for stderr
1775+logger_tuto = logging.getLogger('tutorial') # for stdout
1776+logger_plugin = logging.getLogger('tutorial_plugin') # for stdout
1777
1778 try:
1779 import madgraph.various.misc as misc
1780@@ -468,7 +469,7 @@
1781 out = []
1782 for name, opt in dico.items():
1783 out += opt
1784- return out
1785+ return list(set(out))
1786
1787 # check if more than one categories but only one value:
1788 if not forceCategory and all(len(s) <= 1 for s in dico.values() ):
1789@@ -768,13 +769,13 @@
1790
1791 def help_quit(self):
1792 logger.info("-- terminates the application",'$MG:color:BLUE')
1793- logger.info("syntax: quit",'$MG:color:BLACK')
1794+ logger.info("syntax: quit",'$MG:BOLD')
1795
1796 help_EOF = help_quit
1797
1798 def help_history(self):
1799 logger.info("-- interact with the command history.",'$MG:color:BLUE')
1800- logger.info("syntax: history [FILEPATH|clean|.] ",'$MG:color:BLACK')
1801+ logger.info("syntax: history [FILEPATH|clean|.] ",'$MG:BOLD')
1802 logger.info(" > If FILEPATH is \'.\' and \'output\' is done,")
1803 logger.info(" Cards/proc_card_mg5.dat will be used.")
1804 logger.info(" > If FILEPATH is omitted, the history will be output to stdout.")
1805@@ -782,17 +783,17 @@
1806
1807 def help_help(self):
1808 logger.info("-- access to the in-line help",'$MG:color:BLUE')
1809- logger.info("syntax: help",'$MG:color:BLACK')
1810+ logger.info("syntax: help",'$MG:BOLD')
1811
1812 def help_save(self):
1813 """help text for save"""
1814 logger.info("-- save options configuration to filepath.",'$MG:color:BLUE')
1815- logger.info("syntax: save [options] [FILEPATH]",'$MG:color:BLACK')
1816+ logger.info("syntax: save [options] [FILEPATH]",'$MG:BOLD')
1817
1818 def help_display(self):
1819 """help for display command"""
1820 logger.info("-- display a the status of various internal state variables",'$MG:color:BLUE')
1821- logger.info("syntax: display " + "|".join(self._display_opts),'$MG:color:BLACK')
1822+ logger.info("syntax: display " + "|".join(self._display_opts),'$MG:BOLD')
1823
1824 class CompleteCmd(object):
1825 """Extension of the cmd object for only the complete command"""
1826@@ -1187,8 +1188,8 @@
1827 self.store_line(line)
1828 return None # print the question and use the pipe
1829 logger.info(question_instance.question)
1830- logger.info('The answer to the previous question is not set in your input file', '$MG:color:BLACK')
1831- logger.info('Use %s value' % default, '$MG:color:BLACK')
1832+ logger.info('The answer to the previous question is not set in your input file', '$MG:BOLD')
1833+ logger.info('Use %s value' % default, '$MG:BOLD')
1834 return str(default)
1835
1836 line = line.replace('\n','').strip()
1837@@ -1455,7 +1456,7 @@
1838 me_dir = os.path.basename(me_dir) + ' '
1839
1840 misc.EasterEgg('error')
1841- stop=True
1842+ stop=False
1843 try:
1844 raise
1845 except self.InvalidCmd as error:
1846@@ -1486,6 +1487,7 @@
1847 if __debug__:
1848 self.nice_config_error(error, line)
1849 logger.error(self.keyboard_stop_msg)
1850+
1851
1852 if stop:
1853 self.do_quit('all')
1854@@ -2018,11 +2020,11 @@
1855 def help_shell(self):
1856 """help for the shell"""
1857 logger.info("-- run the shell command CMD and catch output",'$MG:color:BLUE')
1858- logger.info("syntax: shell CMD (or ! CMD)",'$MG:color:BLACK')
1859-
1860-
1861-
1862-
1863+ logger.info("syntax: shell CMD (or ! CMD)",'$MG:BOLD')
1864+
1865+
1866+
1867+class NotValidInput(Exception): pass
1868 #===============================================================================
1869 # Question with auto-completion
1870 #===============================================================================
1871@@ -2042,6 +2044,7 @@
1872
1873 def __init__(self, question, allow_arg=[], default=None,
1874 mother_interface=None, *arg, **opt):
1875+
1876 self.question = question
1877 self.wrong_answer = 0 # forbids infinite loop
1878 self.allow_arg = [str(a) for a in allow_arg]
1879@@ -2066,6 +2069,8 @@
1880 setattr(self, key, value)
1881 if reprint_opt:
1882 print question
1883+ logger_tuto.info("Need help here? type 'help'", '$MG:BOLD')
1884+ logger_plugin.info("Need help here? type 'help'" , '$MG:BOLD')
1885 return self.cmdloop()
1886
1887
1888@@ -2157,21 +2162,21 @@
1889
1890 if not text:
1891 if out['Options']:
1892- logger.info( "Here is the list of all valid options:", '$MG:color:BLACK')
1893+ logger.info( "Here is the list of all valid options:", '$MG:BOLD')
1894 logger.info( " "+ "\n ".join(out['Options']))
1895 if out['command']:
1896- logger.info( "Here is the list of command available:", '$MG:color:BLACK')
1897+ logger.info( "Here is the list of command available:", '$MG:BOLD')
1898 logger.info( " "+ "\n ".join(out['command']))
1899 else:
1900 if out['Options']:
1901- logger.info( "Here is the list of all valid options starting with \'%s\'" % text, '$MG:color:BLACK')
1902+ logger.info( "Here is the list of all valid options starting with \'%s\'" % text, '$MG:BOLD')
1903 logger.info( " "+ "\n ".join(out['Options']))
1904 if out['command']:
1905- logger.info( "Here is the list of command available starting with \'%s\':" % text, '$MG:color:BLACK')
1906+ logger.info( "Here is the list of command available starting with \'%s\':" % text, '$MG:BOLD')
1907 logger.info( " "+ "\n ".join(out['command']))
1908 elif not out['Options']:
1909- logger.info( "No possibility starting with \'%s\'" % text, '$MG:color:BLACK')
1910- logger.info( "You can type help XXX, to see all command starting with XXX", '$MG:color:BLACK')
1911+ logger.info( "No possibility starting with \'%s\'" % text, '$MG:BOLD')
1912+ logger.info( "You can type help XXX, to see all command starting with XXX", '$MG:BOLD')
1913 def complete_help(self, text, line, begidx, endidx):
1914 """ """
1915 return self.completenames(text, line)
1916@@ -2338,6 +2343,7 @@
1917
1918 Behavior for each switch can be customize via:
1919 set_default_XXXX() -> set default value
1920+ This is super-seeded by self.default_switch if that attribute is defined (and has a key for XXXX)
1921 get_allowed_XXXX() -> return list of possible value
1922 check_value_XXXX(value) -> return True/False if the user can set such value
1923 switch_off_XXXXX() -> set it off (called for special mode)
1924@@ -2399,9 +2405,9 @@
1925 if 'allow_arg' in opts:
1926 allowed_args += opts['allow_arg']
1927 del opts['allow_arg']
1928-
1929+
1930 allowed_args +=["0", "done"]
1931- super(ControlSwitch, self).__init__(question, allowed_args, *args, **opts)
1932+ SmartQuestion.__init__(self, question, allowed_args, *args, **opts)
1933 self.options = self.mother_interface.options
1934
1935 def special_check_answer_in_input_file(self, line, default):
1936@@ -2439,11 +2445,14 @@
1937
1938 for key,_ in self.to_control:
1939 key = key.lower()
1940+ if hasattr(self, 'default_switch') and key in self.default_switch:
1941+ self.switch[key] = self.default_switch[key]
1942+ continue
1943 if hasattr(self, 'set_default_%s' % key):
1944 getattr(self, 'set_default_%s' % key)()
1945 else:
1946 self.default_switch_for(key)
1947-
1948+
1949 def default_switch_for(self, key):
1950 """use this if they are no dedicated function for such key"""
1951
1952@@ -2498,8 +2507,8 @@
1953 return getattr(self, 'get_allowed_%s' % key)()
1954 else:
1955 return ['ON', 'OFF']
1956-
1957- def default(self, line):
1958+
1959+ def default(self, line, raise_error=False):
1960 """Default action if line is not recognized"""
1961
1962 line=line.strip().replace('@', '__at__')
1963@@ -2511,6 +2520,8 @@
1964
1965 if '=' in line:
1966 base, value = line.split('=',1)
1967+ base = base.strip()
1968+ value = value.strip()
1969 # allow 1=OFF
1970 if base.isdigit() :
1971 try:
1972@@ -2521,7 +2532,7 @@
1973 base, value = line.split(' ', 1)
1974 elif hasattr(self, 'ans_%s' % line.lower()):
1975 base, value = line.lower(), None
1976- elif line.isdigit() and line in [`i` for i in range(1, len(self.switch)+1)]:
1977+ elif line.isdigit() and line in [`i` for i in range(1, len(self.to_control)+1)]:
1978 # go from one valid option to the next in the get_allowed for that option
1979 base = self.to_control[int(line)-1][0].lower()
1980 return self.default(base) # just recall this function with the associate name
1981@@ -2533,7 +2544,7 @@
1982 except:
1983 if self.get_allowed(base):
1984 value = self.get_allowed(base)[0]
1985- else:
1986+ else:
1987 logger.warning('Can not switch "%s" to another value via number', base)
1988 self.value='reask'
1989 return
1990@@ -2548,6 +2559,8 @@
1991 elif line in 'auto':
1992 self.switch['dynamical'] = True
1993 return super(ControlSwitch, self).default(line)
1994+ elif raise_error:
1995+ raise NotValidInput('unknow command: %s' % line)
1996 else:
1997 logger.warning('unknow command: %s' % line)
1998 self.value = 'reask'
1999@@ -2560,7 +2573,9 @@
2000 value = value.lower()
2001 getattr(self, 'ans_%s' % base)(value)
2002 elif base in self.switch:
2003- self.set_switch(base, value)
2004+ self.set_switch(base, value)
2005+ elif raise_error:
2006+ raise NotValidInput('Not valid command: %s' % line)
2007 else:
2008 logger.warning('Not valid command: %s' % line)
2009
2010@@ -2608,8 +2623,6 @@
2011 """change a switch to a given value"""
2012
2013 assert key in self.switch
2014-
2015-
2016
2017 if hasattr(self, 'ans_%s' % key):
2018 if not self.is_case_sensitive(key):
2019@@ -2827,6 +2840,52 @@
2020 if info == '':
2021 info = 'Please install module'
2022 return info
2023+
2024+ def do_help(self, line, list_command=False):
2025+ """dedicated help for the control switch"""
2026+
2027+ if line:
2028+ return self.print_help_for_switch(line)
2029+
2030+ # here for simple "help"
2031+ logger.info(" ")
2032+ logger.info(" In order to change a switch you can:")
2033+ logger.info(" - type 'NAME = VALUE' to set the switch NAME to a given value.")
2034+ logger.info(" - type 'ID = VALUE' to set the switch correspond to the line ID to a given value.")
2035+ logger.info(" - type 'ID' where ID is the value of the line to pass from one value to the next.")
2036+ logger.info(" - type 'NAME' to set the switch NAME to the next value.")
2037+ logger.info("")
2038+ logger.info(" You can type 'help NAME' for more help on a given switch")
2039+ logger.info("")
2040+ logger.info(" Special keyword:", '$MG:BOLD')
2041+ logger.info(" %s" % '\t'.join([p[4:] for p in dir(self) if p.startswith('ans_')]) )
2042+ logger.info(" type 'help XXX' for more information")
2043+ if list_command:
2044+ super(ControlSwitch, self).do_help(line)
2045+
2046+
2047+ def print_help_for_switch(self, line):
2048+ """ """
2049+
2050+ arg = line.split()[0]
2051+
2052+ if hasattr(self, 'help_%s' % arg):
2053+ return getattr(self, 'help_%s' % arg)('')
2054+
2055+ if hasattr(self, 'ans_%s' % arg):
2056+ return getattr(self, 'help_%s' % arg).__doc__
2057+
2058+ if arg in self.switch:
2059+ logger.info(" information for switch %s: ", arg, '$MG:BOLD')
2060+ logger.info(" allowed value:")
2061+ logger.info(" %s", '\t'.join(self.get_allowed(arg)))
2062+ if hasattr(self, 'help_text_%s' % arg):
2063+ logger.info("")
2064+ for line in getattr(self, 'help_text_%s' % arg):
2065+ logger.info(line)
2066+
2067+
2068+
2069
2070 def question_formatting(self, nb_col = 80,
2071 ldescription=0,
2072@@ -3000,7 +3059,7 @@
2073
2074 return upper, lower, f1, f2
2075
2076- def create_question(self):
2077+ def create_question(self, help_text=True):
2078 """ create the question with correct formatting"""
2079
2080 # geth the number of line and column of the shell to adapt the printing
2081@@ -3090,31 +3149,30 @@
2082
2083 if not example:
2084 example = ('KEY', 'VALUE')
2085-
2086- text += \
2087- ["Either type the switch number (1 to %s) to change its setting," % len(self.to_control),
2088- "Set any switch explicitly (e.g. type '%s=%s' at the prompt)" % example,
2089- "Type 'help' for the list of all valid option",
2090- "Type '0', 'auto', 'done' or just press enter when you are done."]
2091-
2092- # check on the number of row:
2093- if len(text) > nb_rows:
2094- # too many lines. Remove some
2095- to_remove = [ -2, #Type 'help' for the list of all valid option
2096- -5, # \====/
2097- -4, #Either type the switch number (1 to %s) to change its setting,
2098- -3, # Set any switch explicitly
2099- -1, # Type '0', 'auto', 'done' or just press enter when you are done.
2100- ]
2101- to_remove = to_remove[:min(len(to_remove), len(text)-nb_rows)]
2102- text = [t for i,t in enumerate(text) if i-len(text) not in to_remove]
2103-
2104+
2105+ if help_text:
2106+ text += \
2107+ ["Either type the switch number (1 to %s) to change its setting," % len(self.to_control),
2108+ "Set any switch explicitly (e.g. type '%s=%s' at the prompt)" % example,
2109+ "Type 'help' for the list of all valid option",
2110+ "Type '0', 'auto', 'done' or just press enter when you are done."]
2111+
2112+ # check on the number of row:
2113+ if len(text) > nb_rows:
2114+ # too many lines. Remove some
2115+ to_remove = [ -2, #Type 'help' for the list of all valid option
2116+ -5, # \====/
2117+ -4, #Either type the switch number (1 to %s) to change its setting,
2118+ -3, # Set any switch explicitly
2119+ -1, # Type '0', 'auto', 'done' or just press enter when you are done.
2120+ ]
2121+ to_remove = to_remove[:min(len(to_remove), len(text)-nb_rows)]
2122+ text = [t for i,t in enumerate(text) if i-len(text) not in to_remove]
2123+
2124 self.question = "\n".join(text)
2125 return self.question
2126
2127
2128-
2129-
2130 #===============================================================================
2131 #
2132 #===============================================================================
2133
2134=== modified file 'madgraph/interface/launch_ext_program.py'
2135--- madgraph/interface/launch_ext_program.py 2018-02-21 22:35:09 +0000
2136+++ madgraph/interface/launch_ext_program.py 2018-04-20 08:32:43 +0000
2137@@ -625,73 +625,75 @@
2138 import madgraph.interface.madevent_interface as ME
2139
2140 stdout_level = self.cmd_int.options['stdout_level']
2141- if self.shell:
2142- usecmd = ME.MadEventCmdShell(me_dir=self.running_dir, options=self.options)
2143- else:
2144- usecmd = ME.MadEventCmd(me_dir=self.running_dir, options=self.options)
2145- usecmd.pass_in_web_mode()
2146- #Check if some configuration were overwritten by a command. If so use it
2147- set_cmd = [l for l in self.cmd_int.history if l.strip().startswith('set')]
2148- all_options = usecmd.options_configuration.keys() + usecmd.options_madgraph.keys() + usecmd.options_madevent.keys()
2149- for line in set_cmd:
2150- arg = line.split()
2151- if arg[1] not in all_options:
2152- continue
2153+
2154+ with ME.MadEventCmd.RunWebHandling(self.running_dir):
2155+ if self.shell:
2156+ usecmd = ME.MadEventCmdShell(me_dir=self.running_dir, options=self.options, force_run=True)
2157+ else:
2158+ usecmd = ME.MadEventCmd(me_dir=self.running_dir, options=self.options, force_run=True)
2159+ usecmd.pass_in_web_mode()
2160+ #Check if some configuration were overwritten by a command. If so use it
2161+ set_cmd = [l for l in self.cmd_int.history if l.strip().startswith('set')]
2162+ all_options = usecmd.options_configuration.keys() + usecmd.options_madgraph.keys() + usecmd.options_madevent.keys()
2163+ for line in set_cmd:
2164+ arg = line.split()
2165+ if arg[1] not in all_options:
2166+ continue
2167+ try:
2168+ usecmd.do_set(line[3:], log=False)
2169+ except usecmd.InvalidCmd:
2170+ pass
2171+ usecmd.do_set('stdout_level %s' % stdout_level,log=False)
2172+ #ensure that the logger level
2173+ launch = self.cmd_int.define_child_cmd_interface(
2174+ usecmd, interface=False)
2175+ #launch.me_dir = self.running_dir
2176+ if self.unit == 'pb':
2177+ command = 'generate_events %s' % self.name
2178+ else:
2179+ warning_text = '''\
2180+ Note that since 2.3. The launch for 1>N pass in event generation
2181+ For efficient width computation see arXiv:1402.1178.'''
2182+ logger.warning(warning_text)
2183+ command = 'generate_events %s' % self.name
2184+ if mode == "1":
2185+ command += " --cluster"
2186+ elif mode == "2":
2187+ command += " --nb_core=%s" % nb_node
2188+
2189+ if self.force:
2190+ command+= " -f"
2191+
2192+ if self.laststep:
2193+ command += ' --laststep=%s' % self.laststep
2194+ if self.reweight:
2195+ command += ' -R '
2196+ if self.madspin:
2197+ command += ' -M '
2198+
2199+
2200 try:
2201- usecmd.do_set(line[3:], log=False)
2202- except usecmd.InvalidCmd:
2203+ os.remove('ME5_debug')
2204+ except:
2205 pass
2206- usecmd.do_set('stdout_level %s' % stdout_level,log=False)
2207- #ensure that the logger level
2208- launch = self.cmd_int.define_child_cmd_interface(
2209- usecmd, interface=False)
2210- #launch.me_dir = self.running_dir
2211- if self.unit == 'pb':
2212- command = 'generate_events %s' % self.name
2213- else:
2214- warning_text = '''\
2215- Note that since 2.3. The launch for 1>N pass in event generation
2216- For efficient width computation see arXiv:1402.1178.'''
2217- logger.warning(warning_text)
2218- command = 'generate_events %s' % self.name
2219- if mode == "1":
2220- command += " --cluster"
2221- elif mode == "2":
2222- command += " --nb_core=%s" % nb_node
2223-
2224- if self.force:
2225- command+= " -f"
2226-
2227- if self.laststep:
2228- command += ' --laststep=%s' % self.laststep
2229- if self.reweight:
2230- command += ' -R '
2231- if self.madspin:
2232- command += ' -M '
2233-
2234-
2235- try:
2236- os.remove('ME5_debug')
2237- except:
2238- pass
2239-
2240- launch.run_cmd(command)
2241- launch.run_cmd('quit')
2242-
2243- if os.path.exists('ME5_debug'):
2244- return True
2245-
2246- # Display the cross-section to the screen
2247- path = os.path.join(self.running_dir, 'SubProcesses', 'results.dat')
2248- if not os.path.exists(path):
2249- logger.error('Generation failed (no results.dat file found)')
2250- return
2251- fsock = open(path)
2252- line = fsock.readline()
2253- cross, error = line.split()[0:2]
2254-
2255- logger.info('more information in %s'
2256- % os.path.join(self.running_dir, 'index.html'))
2257+
2258+ launch.run_cmd(command)
2259+ launch.run_cmd('quit')
2260+
2261+ if os.path.exists('ME5_debug'):
2262+ return True
2263+
2264+ # Display the cross-section to the screen
2265+ path = os.path.join(self.running_dir, 'SubProcesses', 'results.dat')
2266+ if not os.path.exists(path):
2267+ logger.error('Generation failed (no results.dat file found)')
2268+ return
2269+ fsock = open(path)
2270+ line = fsock.readline()
2271+ cross, error = line.split()[0:2]
2272+
2273+ logger.info('more information in %s'
2274+ % os.path.join(self.running_dir, 'index.html'))
2275
2276
2277 class Pythia8Launcher(ExtLauncher):
2278
2279=== modified file 'madgraph/interface/loop_interface.py'
2280--- madgraph/interface/loop_interface.py 2017-08-04 15:48:15 +0000
2281+++ madgraph/interface/loop_interface.py 2018-04-20 08:32:43 +0000
2282@@ -503,7 +503,7 @@
2283 if (opt['ninja'] is None) or (os.path.isfile(pjoin(MG5DIR, opt['ninja'],'libninja.a'))):
2284 return
2285
2286- logger.info("First output using loop matrix-elements has been detected. Now asking for loop reduction:", '$MG:color:BLACK')
2287+ logger.info("First output using loop matrix-elements has been detected. Now asking for loop reduction:", '$MG:BOLD')
2288 to_install = self.ask('install', '0', ask_class=AskLoopInstaller, timeout=300,
2289 path_msg=' ')
2290
2291
2292=== modified file 'madgraph/interface/madevent_interface.py'
2293--- madgraph/interface/madevent_interface.py 2018-04-06 09:56:08 +0000
2294+++ madgraph/interface/madevent_interface.py 2018-04-20 08:32:43 +0000
2295@@ -2590,7 +2590,7 @@
2296 param_card_iterator.write(path)
2297 name = misc.get_scan_name(orig_name, self.run_name)
2298 path = pjoin(self.me_dir, 'Events','scan_%s.txt' % name)
2299- logger.info("write all cross-section results in %s" % path ,'$MG:color:BLACK')
2300+ logger.info("write all cross-section results in %s" % path ,'$MG:BOLD')
2301 param_card_iterator.write_summary(path)
2302
2303
2304@@ -2988,7 +2988,7 @@
2305 param_card_iterator.write(pjoin(self.me_dir,'Cards','param_card.dat'))
2306 scan_name = misc.get_scan_name(orig_name, self.run_name)
2307 path = pjoin(self.me_dir, 'Events','scan_%s.txt' % scan_name)
2308- logger.info("write all cross-section results in %s" % path, '$MG:color:BLACK')
2309+ logger.info("write all cross-section results in %s" % path, '$MG:BOLD')
2310 param_card_iterator.write_summary(path)
2311
2312
2313
2314=== modified file 'madgraph/interface/madgraph_interface.py'
2315--- madgraph/interface/madgraph_interface.py 2018-03-27 19:11:45 +0000
2316+++ madgraph/interface/madgraph_interface.py 2018-04-20 08:32:43 +0000
2317@@ -297,7 +297,7 @@
2318
2319 def help_save(self):
2320 logger.info("syntax: save %s FILENAME" % "|".join(self._save_opts),'$MG:color:BLUE')
2321- logger.info("-- save information as file FILENAME",'$MG:color:BLACK')
2322+ logger.info("-- save information as file FILENAME",'$MG:BOLD')
2323 logger.info(" FILENAME is optional for saving 'options'.")
2324 logger.info(' By default it uses ./input/mg5_configuration.txt')
2325 logger.info(' If you put "global" for FILENAME it will use ~/.mg5/mg5_configuration.txt')
2326@@ -306,14 +306,14 @@
2327
2328 def help_load(self):
2329 logger.info("syntax: load %s FILENAME" % "|".join(self._save_opts),'$MG:color:BLUE')
2330- logger.info("-- load information from file FILENAME",'$MG:color:BLACK')
2331+ logger.info("-- load information from file FILENAME",'$MG:BOLD')
2332
2333 def help_import(self):
2334 logger.info("syntax: import " + "|".join(self._import_formats) + \
2335 " FILENAME",'$MG:color:BLUE')
2336 logger.info("-- imports file(s) in various formats",'$MG:color:GREEN')
2337 logger.info("")
2338- logger.info(" import model MODEL[-RESTRICTION] [OPTIONS]:",'$MG:color:BLACK')
2339+ logger.info(" import model MODEL[-RESTRICTION] [OPTIONS]:",'$MG:BOLD')
2340 logger.info(" Import a UFO model.")
2341 logger.info(" MODEL should be a valid UFO model name")
2342 logger.info(" Model restrictions are specified by MODEL-RESTRICTION")
2343@@ -324,21 +324,21 @@
2344 logger.info("")
2345 logger.info(" Type 'display modellist' to have the list of all model available.",'$MG:color:GREEN')
2346 logger.info("")
2347- logger.info(" import model_v4 MODEL [--modelname] :",'$MG:color:BLACK')
2348+ logger.info(" import model_v4 MODEL [--modelname] :",'$MG:BOLD')
2349 logger.info(" Import an MG4 model.")
2350 logger.info(" Model should be the name of the model")
2351 logger.info(" or the path to theMG4 model directory")
2352 logger.info(" '--modelname' keeps the original particle names for the model")
2353 logger.info("")
2354- logger.info(" import proc_v4 [PATH] :",'$MG:color:BLACK')
2355+ logger.info(" import proc_v4 [PATH] :",'$MG:BOLD')
2356 logger.info(" Execute MG5 based on a proc_card.dat in MG4 format.")
2357 logger.info(" Path to the proc_card is optional if you are in a")
2358 logger.info(" madevent directory")
2359 logger.info("")
2360- logger.info(" import command PATH :",'$MG:color:BLACK')
2361+ logger.info(" import command PATH :",'$MG:BOLD')
2362 logger.info(" Execute the list of command in the file at PATH")
2363 logger.info("")
2364- logger.info(" import banner PATH [--no_launch]:",'$MG:color:BLACK')
2365+ logger.info(" import banner PATH [--no_launch]:",'$MG:BOLD')
2366 logger.info(" Rerun the exact same run define in the valid banner.")
2367
2368 def help_install(self):
2369@@ -354,7 +354,7 @@
2370 logger.info(" --force Overwrite without asking any existing installation.")
2371 logger.info(" --keep_source Keep a local copy of the sources of the tools MG5_aMC installed from.")
2372 logger.info(" ")
2373- logger.info(" \"install update\"",'$MG:color:BLACK')
2374+ logger.info(" \"install update\"",'$MG:BOLD')
2375 logger.info(" check if your MG5 installation is the latest one.")
2376 logger.info(" If not it load the difference between your current version and the latest one,")
2377 logger.info(" and apply it to the code. Two options are available for this command:")
2378@@ -378,11 +378,11 @@
2379 # color schemes.
2380 #_launch_parser.print_help()
2381 logger.info("syntax: launch <dir_path> <options>",'$MG:color:BLUE')
2382- logger.info("-- execute the aMC@NLO/madevent/standalone/pythia8 output present in dir_path",'$MG:color:BLACK')
2383+ logger.info("-- execute the aMC@NLO/madevent/standalone/pythia8 output present in dir_path",'$MG:BOLD')
2384 logger.info("By default, dir_path points to the last created directory.")
2385 logger.info("(for pythia8, it should be the Pythia 8 main directory)")
2386 logger.info("")
2387- logger.info("Launch on madevent/pythia8/standalone outputs:",'$MG:color:BLACK')
2388+ logger.info("Launch on madevent/pythia8/standalone outputs:",'$MG:BOLD')
2389 logger.info(" o Example: launch PROC_sm_1 --name=run2",'$MG:color:GREEN')
2390 logger.info(" o Example: launch ../pythia8",'$MG:color:GREEN')
2391 logger.info(" > Options:")
2392@@ -397,7 +397,7 @@
2393 logger.info(" last program run in MadEvent run.")
2394 logger.info(" [auto|parton|pythia|pgs|delphes]")
2395 logger.info("")
2396- logger.info("Launch on MadLoop standalone output:",'$MG:color:BLACK')
2397+ logger.info("Launch on MadLoop standalone output:",'$MG:BOLD')
2398 logger.info(" o Example: launch PROC_loop_sm_1 -f",'$MG:color:GREEN')
2399 logger.info(" > Simple check of a single Phase-space points.")
2400 logger.info(" > You will be asked whether you want to edit the MadLoop ")
2401@@ -405,7 +405,7 @@
2402 logger.info(" the -f option is specified. All other options are ")
2403 logger.info(" irrelevant for this kind of launch.")
2404 logger.info("")
2405- logger.info("Launch on aMC@NLO output:",'$MG:color:BLACK')
2406+ logger.info("Launch on aMC@NLO output:",'$MG:BOLD')
2407 logger.info(" > launch <dir_path> <mode> <options>",'$MG:color:BLUE')
2408 logger.info(" o Example: launch MyProc aMC@NLO -f -p",'$MG:color:GREEN')
2409
2410@@ -417,7 +417,7 @@
2411
2412 def help_open(self):
2413 logger.info("syntax: open FILE ",'$MG:color:BLUE')
2414- logger.info("-- open a file with the appropriate editor.",'$MG:color:BLACK')
2415+ logger.info("-- open a file with the appropriate editor.",'$MG:BOLD')
2416 logger.info(' If FILE belongs to index.html, param_card.dat, run_card.dat')
2417 logger.info(' the path to the last created/used directory is used')
2418 logger.info(' The program used to open those files can be chosen in the')
2419@@ -425,16 +425,16 @@
2420
2421 def help_customize_model(self):
2422 logger.info("syntax: customize_model --save=NAME",'$MG:color:BLUE')
2423- logger.info("-- Open an invite where you options to tweak the model.",'$MG:color:BLACK')
2424+ logger.info("-- Open an invite where you options to tweak the model.",'$MG:BOLD')
2425 logger.info(" If you specify the option --save=NAME, this tweak will be")
2426 logger.info(" available for future import with the command 'import model XXXX-NAME'")
2427
2428 def help_output(self):
2429 logger.info("syntax: output [" + "|".join(self._export_formats) + \
2430 "] [path|.|auto] [options]",'$MG:color:BLUE')
2431- logger.info("-- Output any generated process(es) to file.",'$MG:color:BLACK')
2432+ logger.info("-- Output any generated process(es) to file.",'$MG:BOLD')
2433 logger.info(" Default mode is madevent. Default path is \'.\' or auto.")
2434- logger.info(" mode:",'$MG:color:BLACK')
2435+ logger.info(" mode:",'$MG:BOLD')
2436 logger.info(" - For MadLoop and aMC@NLO runs, there is only one mode and")
2437 logger.info(" it is set by default.")
2438 logger.info(" - If mode is madevent, create a MadEvent process directory.")
2439@@ -452,10 +452,10 @@
2440 logger.info(" valid options for aloha output are:")
2441 logger.info(" --format=Fortran|Python|Cpp : defining the output language")
2442 logger.info(" --output= : defining output directory")
2443- logger.info(" path: The path of the process directory.",'$MG:color:BLACK')
2444+ logger.info(" path: The path of the process directory.",'$MG:BOLD')
2445 logger.info(" If you put '.' as path, your pwd will be used.")
2446 logger.info(" If you put 'auto', an automatic directory PROC_XX_n will be created.")
2447- logger.info(" options:",'$MG:color:BLACK')
2448+ logger.info(" options:",'$MG:BOLD')
2449 logger.info(" -f: force cleaning of the directory if it already exists")
2450 logger.info(" -d: specify other MG/ME directory")
2451 logger.info(" -noclean: no cleaning performed in \"path\".")
2452@@ -468,8 +468,8 @@
2453
2454 def help_check(self):
2455 logger.info("syntax: check [" + "|".join(self._check_opts) + "] [param_card] process_definition [--energy=] [--split_orders=] [--reduction=]",'$MG:color:BLUE')
2456- logger.info("-- check a process or set of processes.",'$MG:color:BLACK')
2457- logger.info("General options:",'$MG:color:BLACK')
2458+ logger.info("-- check a process or set of processes.",'$MG:BOLD')
2459+ logger.info("General options:",'$MG:BOLD')
2460 logger.info("o full:",'$MG:color:GREEN')
2461 logger.info(" Perform all four checks described below:")
2462 logger.info(" permutation, brs, gauge and lorentz_invariance.")
2463@@ -530,7 +530,7 @@
2464 logger.info(" > Except for the 'gauge' test, all checks above are also")
2465 logger.info(" available for loop processes with ML5 ('virt=' mode)")
2466 logger.info("Example: check full p p > j j",'$MG:color:GREEN')
2467- logger.info("Options for loop processes only:",'$MG:color:BLACK')
2468+ logger.info("Options for loop processes only:",'$MG:BOLD')
2469 logger.info("o timing:",'$MG:color:GREEN')
2470 logger.info(" Generate and output a process and returns detailed")
2471 logger.info(" information about the code and a timing benchmark.")
2472@@ -560,7 +560,7 @@
2473 def help_generate(self):
2474
2475 logger.info("-- generate diagrams for a given process",'$MG:color:BLUE')
2476- logger.info("General leading-order syntax:",'$MG:color:BLACK')
2477+ logger.info("General leading-order syntax:",'$MG:BOLD')
2478 logger.info(" o generate INITIAL STATE > REQ S-CHANNEL > FINAL STATE $ EXCL S-CHANNEL / FORBIDDEN PARTICLES COUP1=ORDER1 COUP2^2=ORDER2 @N")
2479 logger.info(" o Example: generate l+ vl > w+ > l+ vl a $ z / a h QED<=3 QCD=0 @1",'$MG:color:GREEN')
2480 logger.info(" > Alternative required s-channels can be separated by \"|\":")
2481@@ -576,11 +576,11 @@
2482 logger.info(" > allowed coupling operator are: \"==\", \"=\", \"<=\" and \">\".")
2483 logger.info(" \"==\" request exactly that number of coupling while \"=\" is interpreted as \"<=\".")
2484 logger.info(" > To generate a second process use the \"add process\" command")
2485- logger.info("Decay chain syntax:",'$MG:color:BLACK')
2486+ logger.info("Decay chain syntax:",'$MG:BOLD')
2487 logger.info(" o core process, decay1, (decay2, (decay2', ...)), ... etc")
2488 logger.info(" o Example: generate p p > t~ t QED=0, (t~ > W- b~, W- > l- vl~), t > j j b @2",'$MG:color:GREEN')
2489 logger.info(" > Note that identical particles will all be decayed.")
2490- logger.info("Loop processes syntax:",'$MG:color:BLACK')
2491+ logger.info("Loop processes syntax:",'$MG:BOLD')
2492 logger.info(" o core process [ <NLO_mode=> LoopOrder1 LoopOrder2 ... ] SQUAREDCOUPi=ORDERi")
2493 logger.info(" o Example: generate p p > t~ t QED=0 QCD=2 [ all= QCD ] QCD=6",'$MG:color:GREEN')
2494 logger.info(" > Notice that in this format, decay chains are not allowed.")
2495@@ -604,7 +604,7 @@
2496 logger.info(" OR merge two model",'$MG:color:BLUE')
2497 logger.info('')
2498 logger.info("-- generate diagrams for a process and add to existing processes",'$MG:color:BLUE')
2499- logger.info("General leading-order syntax:",'$MG:color:BLACK')
2500+ logger.info("General leading-order syntax:",'$MG:BOLD')
2501 logger.info(" o add process INITIAL STATE > REQ S-CHANNEL > FINAL STATE $ EXCL S-CHANNEL / FORBIDDEN PARTICLES COUP1=ORDER1 COUP2=ORDER2 @N")
2502 logger.info(" o Example: add process l+ vl > w+ > l+ vl a $ z / a h QED=3 QCD=0 @1",'$MG:color:GREEN')
2503 logger.info(" > Alternative required s-channels can be separated by \"|\":")
2504@@ -613,11 +613,11 @@
2505 logger.info(" orders to ensure maximum number of QCD vertices.")
2506 logger.info(" > Note that if there are more than one non-QCD coupling type,")
2507 logger.info(" coupling orders need to be specified by hand.")
2508- logger.info("Decay chain syntax:",'$MG:color:BLACK')
2509+ logger.info("Decay chain syntax:",'$MG:BOLD')
2510 logger.info(" o core process, decay1, (decay2, (decay2', ...)), ... etc")
2511 logger.info(" o Example: add process p p > t~ t QED=0, (t~ > W- b~, W- > l- vl~), t > j j b @2",'$MG:color:GREEN')
2512 logger.info(" > Note that identical particles will all be decayed.")
2513- logger.info("Loop processes syntax:",'$MG:color:BLACK')
2514+ logger.info("Loop processes syntax:",'$MG:BOLD')
2515 logger.info(" o core process [ <NLO_mode=> LoopOrder1 LoopOrder2 ... ] SQUAREDCOUPi=ORDERi")
2516 logger.info(" o Example: add process p p > t~ t QED=0 QCD=2 [ all= QCD ] QCD=6",'$MG:color:GREEN')
2517 logger.info(" > Notice that in this format, decay chains are not allowed.")
2518@@ -637,7 +637,7 @@
2519 logger.info(" can still handle these.")
2520
2521 logger.info("-- merge two model to create a new one", '$MG:color:BLUE')
2522- logger.info("syntax:",'$MG:color:BLACK')
2523+ logger.info("syntax:",'$MG:BOLD')
2524 logger.info(" o add model MODELNAME [OPTIONS]")
2525 logger.info(" o Example: add model taudecay",'$MG:color:GREEN')
2526 logger.info(" > Merge the two model in a single one. If that same merge was done before.")
2527@@ -706,7 +706,7 @@
2528
2529 def help_set(self):
2530 logger.info("-- set options for generation or output.",'$MG:color:BLUE')
2531- logger.info("syntax: set <option_name> <option_value>",'$MG:color:BLACK')
2532+ logger.info("syntax: set <option_name> <option_value>",'$MG:BOLD')
2533 logger.info("Possible options are: ")
2534 for opts in [self._set_options[i*3:(i+1)*3] for i in \
2535 range((len(self._set_options)//4)+1)]:
2536@@ -716,8 +716,8 @@
2537 logger.info(" > (default Auto) Smart grouping of subprocesses into ")
2538 logger.info(" directories, mirroring of initial states, and ")
2539 logger.info(" combination of integration channels.")
2540- logger.info(" > Example: p p > j j j w+ gives 5 directories and 184 channels",'$MG:color:BLACK')
2541- logger.info(" (cf. 65 directories and 1048 channels for regular output)",'$MG:color:BLACK')
2542+ logger.info(" > Example: p p > j j j w+ gives 5 directories and 184 channels",'$MG:BOLD')
2543+ logger.info(" (cf. 65 directories and 1048 channels for regular output)",'$MG:BOLD')
2544 logger.info(" > Auto means False for decay computation and True for collisions.")
2545 logger.info("ignore_six_quark_processes multi_part_label",'$MG:color:GREEN')
2546 logger.info(" > (default none) ignore processes with at least 6 of any")
2547@@ -1081,7 +1081,7 @@
2548
2549 def check_import(self, args):
2550 """check the validity of line"""
2551-
2552+
2553 modelname = False
2554 prefix = True
2555 if '-modelname' in args:
2556@@ -1095,6 +1095,26 @@
2557 args.remove('--noprefix')
2558 prefix = False
2559
2560+ if args and args[0] == 'model' and '--last' in args:
2561+ # finding last created directory
2562+ args.remove('--last')
2563+ last_change = 0
2564+ to_search = [pjoin(MG5DIR,'models')]
2565+ if 'PYTHONPATH' in os.environ:
2566+ to_search += os.environ['PYTHONPATH'].split(':')
2567+ to_search = [d for d in to_search if os.path.exists(d)]
2568+
2569+ models = []
2570+ for d in to_search:
2571+ for p in misc.glob('*/particles.py', path=d ):
2572+ if p.endswith(('__REAL/particles.py','__COMPLEX/particles.py')):
2573+ continue
2574+ models.append(os.path.dirname(p))
2575+
2576+ lastmodel = max(models, key=os.path.getmtime)
2577+ logger.info('last model found is %s', lastmodel)
2578+ args.insert(1, lastmodel)
2579+
2580 if not args:
2581 self.help_import()
2582 raise self.InvalidCmd('wrong \"import\" format')
2583@@ -1160,7 +1180,7 @@
2584 # to install as argument.
2585 args = args[:1]
2586
2587- if args[0] not in self._install_opts + hidden_prog:
2588+ if args[0] not in self._install_opts + hidden_prog + self._advanced_install_opts:
2589 if not args[0].startswith('td'):
2590 self.help_install()
2591 raise self.InvalidCmd('Not recognize program %s ' % args[0])
2592@@ -1499,7 +1519,6 @@
2593 def check_output(self, args, default='madevent'):
2594 """ check the validity of the line"""
2595
2596-
2597 if args and args[0] in self._export_formats:
2598 self._export_format = args.pop(0)
2599 elif args:
2600@@ -2717,7 +2736,7 @@
2601 args = self.split_arg(line[0:begidx])
2602 # Format
2603 if len(args) == 1:
2604- return self.list_completion(text, self._install_opts)
2605+ return self.list_completion(text, self._install_opts + self._advanced_install_opts)
2606 elif len(args) and args[0] == 'update':
2607 return self.list_completion(text, ['-f','--timeout='])
2608 elif len(args)>=2 and args[1] in self._advanced_install_opts:
2609@@ -2763,7 +2782,7 @@
2610 'gauge','lorentz', 'brs', 'cms']
2611 _import_formats = ['model_v4', 'model', 'proc_v4', 'command', 'banner']
2612 _install_opts = ['Delphes', 'MadAnalysis4', 'ExRootAnalysis',
2613- 'update', 'SysCalc', 'Golem95', 'PJFry', 'QCDLoop', 'maddm']
2614+ 'update', 'SysCalc', 'Golem95', 'PJFry', 'QCDLoop']
2615
2616 # The targets below are installed using the HEPToolsInstaller.py script
2617 _advanced_install_opts = ['pythia8','zlib','boost','lhapdf6','lhapdf5','collier',
2618@@ -4422,23 +4441,32 @@
2619 if not options['reuse']:
2620 process_checks.clean_up(self._mgme_dir)
2621
2622+
2623+ def clean_process(self):
2624+ """ensure that all processes are cleaned from memory.
2625+ typically called from import model and generate XXX command
2626+ """
2627+
2628+ aloha_lib.KERNEL.clean()
2629+ # Reset amplitudes
2630+ self._curr_amps = diagram_generation.AmplitudeList()
2631+ # Reset Process definition
2632+ self._curr_proc_defs = base_objects.ProcessDefinitionList()
2633+ # Reset Helas matrix elements
2634+ self._curr_matrix_elements = helas_objects.HelasMultiProcess()
2635+ self._generate_info = ""
2636+ # Reset _done_export, since we have new process
2637+ self._done_export = False
2638+ # Also reset _export_format and _export_dir
2639+ self._export_format = None
2640+
2641+
2642 # Generate a new amplitude
2643 def do_generate(self, line):
2644 """Main commands: Generate an amplitude for a given process"""
2645
2646- aloha_lib.KERNEL.clean()
2647- # Reset amplitudes
2648- self._curr_amps = diagram_generation.AmplitudeList()
2649- # Reset Process definition
2650- self._curr_proc_defs = base_objects.ProcessDefinitionList()
2651- # Reset Helas matrix elements
2652- self._curr_matrix_elements = helas_objects.HelasMultiProcess()
2653+ self.clean_process()
2654 self._generate_info = line
2655- # Reset _done_export, since we have new process
2656- self._done_export = False
2657- # Also reset _export_format and _export_dir
2658- self._export_format = None
2659-
2660
2661 # Call add process
2662 args = self.split_arg(line)
2663@@ -4563,7 +4591,7 @@
2664 if name not in orders and name not in squared_orders]
2665 if to_set:
2666 logger.info('the following coupling will be allowed up to the maximal value of %s: %s' %
2667- (self.options['default_unset_couplings'], ', '.join(to_set)), '$MG:color:BLACK')
2668+ (self.options['default_unset_couplings'], ', '.join(to_set)), '$MG:BOLD')
2669 for name in to_set:
2670 orders[name] = self.options['default_unset_couplings']
2671
2672@@ -4791,7 +4819,15 @@
2673 else:
2674 optimize = False
2675
2676-
2677+ # Extract potential loop_filter
2678+ loop_filter=None
2679+ for arg in args:
2680+ if arg.startswith('--loop_filter='):
2681+ loop_filter = arg[14:]
2682+ #if not isinstance(self, extended_cmd.CmdShell):
2683+ # raise self.InvalidCmd, "loop_filter is not allowed in web mode"
2684+ args = [a for a in args if not a.startswith('--loop_filter=')]
2685+
2686 if not myprocdef:
2687 myprocdef = self.extract_process(' '.join(args))
2688
2689@@ -4840,7 +4876,8 @@
2690 myproc = loop_diagram_generation.LoopInducedMultiProcess(myprocdef,
2691 collect_mirror_procs = collect_mirror_procs,
2692 ignore_six_quark_processes = ignore_six_quark_processes,
2693- optimize=optimize)
2694+ optimize=optimize,
2695+ loop_filter=loop_filter)
2696
2697 for amp in myproc.get('amplitudes'):
2698 if amp not in self._curr_amps:
2699@@ -5149,10 +5186,7 @@
2700 if args[0].startswith('model'):
2701 self._model_v4_path = None
2702 # Reset amplitudes and matrix elements
2703- self._curr_amps = diagram_generation.AmplitudeList()
2704- # Reset proc defs
2705- self._curr_proc_defs = base_objects.ProcessDefinitionList()
2706- self._curr_matrix_elements = helas_objects.HelasMultiProcess()
2707+ self.clean_process()
2708 # Import model
2709 if args[0].endswith('_v4'):
2710 self._curr_model, self._model_v4_path = \
2711@@ -5638,9 +5672,9 @@
2712
2713 if tool=='madanalysis5':
2714 if not any(o.startswith(('--with_','--veto_','--update')) for o in add_options):
2715- logger.info(' To install recasting capabilities of madanalysis5 and/or', '$MG:color:BLACK')
2716- logger.info(' to allow delphes analysis at parton level.','$MG:color:BLACK')
2717- logger.info(' Please run \'install MadAnalysis5 --with_delphes --update\':', '$MG:color:BLACK')
2718+ logger.info(' To install recasting capabilities of madanalysis5 and/or', '$MG:BOLD')
2719+ logger.info(' to allow delphes analysis at parton level.','$MG:BOLD')
2720+ logger.info(' Please run \'install MadAnalysis5 --with_delphes --update\':', '$MG:BOLD')
2721
2722 elif return_code == 66:
2723 answer = self.ask(question=
2724@@ -5712,6 +5746,9 @@
2725 MG5aMC that supports quadruple precision (typically g++ based on gcc 4.6+).""")
2726 self.options['ninja'] = pjoin(prefix,'lib')
2727 self.exec_cmd('save options %s ninja' % config_file, printcmd=False, log=False)
2728+ elif '%s_path' % tool in self.options:
2729+ self.options['%s_path' % tool] = pjoin(prefix, tool)
2730+ self.exec_cmd('save options %s %s_path' % (config_file,tool), printcmd=False, log=False)
2731
2732 # Now warn the user if he didn't add HEPTools first in his environment
2733 # variables.
2734@@ -5761,34 +5798,8 @@
2735 # Return true for successful installation
2736 return True
2737
2738- def do_install(self, line, paths=None, additional_options=[]):
2739- """Install optional package from the MG suite.
2740- The argument 'additional_options' will be passed to the advanced_install
2741- functions. If it contains the option '--force', then the advanced_install
2742- function will overwrite any existing installation of the tool without
2743- warnings.
2744- """
2745-
2746- # Make sure to avoid any border effect on custom_additional_options
2747- add_options = list(additional_options)
2748-
2749- args = self.split_arg(line)
2750- #check the validity of the arguments
2751- install_options = self.check_install(args)
2752-
2753- if sys.platform == "darwin":
2754- program = "curl"
2755- else:
2756- program = "wget"
2757-
2758- # special command for auto-update
2759- if args[0] == 'update':
2760- self.install_update(['update']+install_options['update_options'],wget=program)
2761- return
2762-
2763- plugin = ['maddm']
2764-
2765- advertisements = {'pythia-pgs':['arXiv:0603175'],
2766+ install_plugin = ['maddm']
2767+ install_ad = {'pythia-pgs':['arXiv:0603175'],
2768 'Delphes':['arXiv:1307.6346'],
2769 'Delphes2':['arXiv:0903.2225'],
2770 'SysCalc':['arXiv:1801.08401'],
2771@@ -5806,15 +5817,54 @@
2772 'collier':['arXiv:1604.06792'],
2773 'oneloop':['arXiv:1007.4716'],
2774 'maddm':['arXiv:1505.04190']}
2775+ install_server = ['http://madgraph.phys.ucl.ac.be/package_info.dat',
2776+ 'http://madgraph.physics.illinois.edu/package_info.dat']
2777+ install_name = {'td_mac': 'td', 'td_linux':'td', 'Delphes2':'Delphes',
2778+ 'Delphes3':'Delphes', 'pythia-pgs':'pythia-pgs',
2779+ 'ExRootAnalysis': 'ExRootAnalysis','MadAnalysis':'madanalysis5',
2780+ 'MadAnalysis4':'MadAnalysis',
2781+ 'SysCalc':'SysCalc', 'Golem95': 'golem95',
2782+ 'PJFry':'PJFry','QCDLoop':'QCDLoop','MadAnalysis5':'madanalysis5',
2783+ 'maddm':'maddm'
2784+ }
2785+
2786+ def do_install(self, line, paths=None, additional_options=[]):
2787+ """Install optional package from the MG suite.
2788+ The argument 'additional_options' will be passed to the advanced_install
2789+ functions. If it contains the option '--force', then the advanced_install
2790+ function will overwrite any existing installation of the tool without
2791+ warnings.
2792+ """
2793+
2794+ # Make sure to avoid any border effect on custom_additional_options
2795+ add_options = list(additional_options)
2796+
2797+ args = self.split_arg(line)
2798+ #check the validity of the arguments
2799+ install_options = self.check_install(args)
2800+
2801+ if sys.platform == "darwin":
2802+ program = "curl"
2803+ else:
2804+ program = "wget"
2805+
2806+ # special command for auto-update
2807+ if args[0] == 'update':
2808+ self.install_update(['update']+install_options['update_options'],wget=program)
2809+ return
2810+
2811+ plugin = self.install_plugin
2812+
2813+ advertisements = self.install_ad
2814
2815
2816 if args[0] in advertisements:
2817-# logger.info('{:^80}'.format("-"*70), '$MG:color:BLACK')
2818-# logger.info('{:^80}'.format("You are installing '%s', please cite ref(s):"%args[0]), '$MG:color:BLACK')
2819+# logger.info('{:^80}'.format("-"*70), '$MG:BOLD')
2820+# logger.info('{:^80}'.format("You are installing '%s', please cite ref(s):"%args[0]), '$MG:BOLD')
2821 # logger.info('{:^80}'.format(', '.join(advertisements[args[0]])), '$MG:color:GREEN')
2822-# logger.info('{:^80}'.format("when using results produced with this tool."), '$MG:color:BLACK')
2823-# logger.info('{:^80}'.format("-"*70), '$MG:color:BLACK')
2824- logger.info(" You are installing '%s', please cite ref(s): \033[92m%s\033[0m. " % (args[0], ', '.join(advertisements[args[0]])), '$MG:color:BLACK')
2825+# logger.info('{:^80}'.format("when using results produced with this tool."), '$MG:BOLD')
2826+# logger.info('{:^80}'.format("-"*70), '$MG:BOLD')
2827+ logger.info(" You are installing '%s', please cite ref(s): \033[92m%s\033[0m. " % (args[0], ', '.join(advertisements[args[0]])), '$MG:BOLD')
2828
2829 # Load file with path of the different program:
2830 import urllib
2831@@ -5823,8 +5873,7 @@
2832 else:
2833 path = {}
2834
2835- data_path = ['http://madgraph.phys.ucl.ac.be/package_info.dat',
2836- 'http://madgraph.physics.illinois.edu/package_info.dat']
2837+ data_path = self.install_server
2838
2839 # Force here to choose one particular server
2840 if any(a.startswith('--source=') for a in args):
2841@@ -5864,15 +5913,11 @@
2842
2843 if args[0] == 'Delphes':
2844 args[0] = 'Delphes3'
2845+ if args[0] == 'MadAnalysis4':
2846+ args[0] = 'MadAnalysis'
2847
2848 try:
2849- name = {'td_mac': 'td', 'td_linux':'td', 'Delphes2':'Delphes',
2850- 'Delphes3':'Delphes', 'pythia-pgs':'pythia-pgs',
2851- 'ExRootAnalysis': 'ExRootAnalysis','MadAnalysis':'madanalysis5',
2852- 'MadAnalysis4':'MadAnalysis',
2853- 'SysCalc':'SysCalc', 'Golem95': 'golem95',
2854- 'PJFry':'PJFry','QCDLoop':'QCDLoop','MadAnalysis5':'madanalysis5'
2855- }
2856+ name = self.install_name
2857 name = name[args[0]]
2858 except KeyError:
2859 name = args[0]
2860@@ -5900,19 +5945,7 @@
2861
2862 if args[0] == 'Delphes':
2863 args[0] = 'Delphes3'
2864- if args[0] == 'MadAnalysis4':
2865- args[0] = 'MadAnalysis'
2866- try:
2867- name = {'td_mac': 'td', 'td_linux':'td', 'Delphes2':'Delphes',
2868- 'Delphes3':'Delphes', 'pythia-pgs':'pythia-pgs',
2869- 'ExRootAnalysis': 'ExRootAnalysis','MadAnalysis':'MadAnalysis',
2870- 'SysCalc':'SysCalc', 'Golem95': 'golem95',
2871- 'PJFry':'PJFry','QCDLoop':'QCDLoop',
2872- 'maddm':'maddm'
2873- }
2874- name = name[args[0]]
2875- except:
2876- pass
2877+
2878
2879 #check outdated install
2880 substitution={'Delphes2':'Delphes','pythia-pgs':'pythia8'}
2881@@ -5948,6 +5981,8 @@
2882 created_name = created_name[0]
2883 files.mv(pjoin(MG5DIR, created_name), pjoin(MG5DIR, name))
2884
2885+ if hasattr(self, 'post_install_%s' %name):
2886+ return getattr(self, 'post_install_%s' %name)()
2887
2888 logger.info('compile %s. This might take a while.' % name)
2889
2890@@ -7402,7 +7437,6 @@
2891 # Check Argument validity
2892 self.check_output(args)
2893
2894-
2895 noclean = '-noclean' in args
2896 force = '-f' in args
2897 nojpeg = '-nojpeg' in args
2898@@ -8182,7 +8216,7 @@
2899 #compile the code
2900 if not os.path.exists(pjoin(model_path, 'SMWidth','smwidth')):
2901 logger.info('Compiling SMWidth. This has to be done only once and'+\
2902- ' can take a couple of minutes.','$MG:color:BLACK')
2903+ ' can take a couple of minutes.','$MG:BOLD')
2904 current = misc.detect_current_compiler(pjoin(model_path, 'SMWidth',
2905 'makefile_MW5'))
2906 new = 'gfortran' if self.options_configuration['fortran_compiler'] is None else \
2907
2908=== modified file 'madgraph/interface/madweight_interface.py'
2909--- madgraph/interface/madweight_interface.py 2017-07-13 15:12:05 +0000
2910+++ madgraph/interface/madweight_interface.py 2018-04-20 08:32:43 +0000
2911@@ -275,7 +275,7 @@
2912 if not self.options['cluster_temp_path']:
2913 if self.options['run_mode'] == 2:
2914 logger.info('Options cluster_temp_path is required for MW run. Trying to run with /tmp',
2915- '$MG:color:BLACK')
2916+ '$MG:BOLD')
2917 self.exec_cmd('set cluster_temp_path /tmp --no_save')
2918 elif self.options['cluster_type'] != 'condor':
2919 raise Exception, 'cluster_temp_path needs to be define for MW. Please retry.'
2920
2921=== modified file 'madgraph/interface/master_interface.py'
2922--- madgraph/interface/master_interface.py 2017-11-30 23:06:17 +0000
2923+++ madgraph/interface/master_interface.py 2018-04-20 08:32:43 +0000
2924@@ -216,13 +216,15 @@
2925 coupling_type=orders)
2926 self.change_principal_cmd('MadGraph')
2927 return self.cmd.create_loop_induced(self, line, *args, **opts)
2928+ else:
2929+ self.change_principal_cmd('MadGraph')
2930 try:
2931 return self.cmd.do_add(self, line, *args, **opts)
2932 except fks_base.NoBornException:
2933- logger.info("------------------------------------------------------------------------", '$MG:color:BLACK')
2934- logger.info(" No Born diagrams found. Now switching to the loop-induced mode. ", '$MG:color:BLACK')
2935- logger.info(" Please cite ref. 'arXiv:1507.00020' when using results from this mode. ", '$MG:color:BLACK')
2936- logger.info("------------------------------------------------------------------------", '$MG:color:BLACK')
2937+ logger.info("------------------------------------------------------------------------", '$MG:BOLD')
2938+ logger.info(" No Born diagrams found. Now switching to the loop-induced mode. ", '$MG:BOLD')
2939+ logger.info(" Please cite ref. 'arXiv:1507.00020' when using results from this mode. ", '$MG:BOLD')
2940+ logger.info("------------------------------------------------------------------------", '$MG:BOLD')
2941 self.change_principal_cmd('MadGraph')
2942 return self.cmd.create_loop_induced(self, line, *args, **opts)
2943
2944@@ -607,6 +609,7 @@
2945 %','.join(interface_quick_name.keys()))
2946
2947 def change_principal_cmd(self, name):
2948+
2949 old_cmd=self.current_interface
2950 if name in self.interface_names.keys():
2951 self.prompt= self.interface_names[name][0]+'>'
2952
2953=== modified file 'madgraph/interface/reweight_interface.py'
2954--- madgraph/interface/reweight_interface.py 2018-03-28 08:21:22 +0000
2955+++ madgraph/interface/reweight_interface.py 2018-04-20 08:32:43 +0000
2956@@ -915,6 +915,33 @@
2957 def do_compute_widths(self, line):
2958 return self.mother.do_compute_widths(line)
2959
2960+
2961+ dynamical_scale_warning=True
2962+ def change_kinematics(self, event):
2963+
2964+
2965+ if isinstance(self.run_card, banner.RunCardLO):
2966+ jac = event.change_ext_mass(self.new_param_card)
2967+ new_event = event
2968+ else:
2969+ jac =1
2970+ new_event = event
2971+
2972+ if jac != 1:
2973+ if self.output_type == 'default':
2974+ logger.critical('mass reweighting requires dedicated lhe output!. Please include "change output 2.0" in your reweight_card')
2975+ raise Exception
2976+ mode = self.run_card['dynamical_scale_choice']
2977+ if mode == -1:
2978+ if self.dynamical_scale_warning:
2979+ logger.warning('dynamical_scale is set to -1. New sample will be with HT/2 dynamical scale for renormalisation scale')
2980+ mode = 3
2981+ new_event.scale = event.get_scale(mode)
2982+ new_event.aqcd = self.lhe_input.get_alphas(new_event.scale, lhapdf_config=self.mother.options['lhapdf'])
2983+
2984+ return jac, new_event
2985+
2986+
2987 def calculate_weight(self, event):
2988 """space defines where to find the calculator (in multicore)"""
2989
2990@@ -927,27 +954,15 @@
2991 orig_wgt = event.wgt
2992 # LO reweighting
2993 w_orig = self.calculate_matrix_element(event, 0)
2994+
2995 # reshuffle event for mass effect # external mass only
2996- if isinstance(self.run_card, banner.RunCardLO):
2997- jac = event.change_ext_mass(self.new_param_card)
2998- else:
2999- jac =1
3000-
3001- if jac != 1:
3002- if self.output_type == 'default':
3003- logger.critical('mass reweighting requires dedicated lhe output!. Please include "change output 2.0" in your reweight_card')
3004- raise Exception
3005- mode = self.run_card['dynamical_scale_choice']
3006- if mode == -1:
3007- logger.warning('dynamical_scale is set to -1. New sample will be with HT/2 dynamical scale for renormalisation scale')
3008- mode = 3
3009- event.scale = event.get_scale(mode)
3010- event.aqcd = self.lhe_input.get_alphas(event.scale, lhapdf_config=self.mother.options['lhapdf'])
3011-
3012+ # carefull that new_event can sometimes be = to event
3013+ # (i.e. change can be in place)
3014+ jac, new_event = self.change_kinematics(event)
3015
3016
3017 if event.wgt != 0: # impossible reshuffling
3018- w_new = self.calculate_matrix_element(event, 1)
3019+ w_new = self.calculate_matrix_element(new_event, 1)
3020 else:
3021 w_new = 0
3022
3023@@ -1697,9 +1712,19 @@
3024 continue
3025 pdir = pjoin(path_me, onedir, 'SubProcesses')
3026 for tag in [2*metag,2*metag+1]:
3027- with misc.TMP_variable(sys, 'path', [pjoin(path_me)]+sys.path):
3028- mymod = __import__('%s.SubProcesses.allmatrix%spy' % (onedir, tag), globals(), locals(), [],-1)
3029- reload(mymod)
3030+ with misc.TMP_variable(sys, 'path', [pjoin(path_me)]+sys.path):
3031+ mod_name = '%s.SubProcesses.allmatrix%spy' % (onedir, tag)
3032+ #mymod = __import__('%s.SubProcesses.allmatrix%spy' % (onedir, tag), globals(), locals(), [],-1)
3033+ if mod_name in sys.modules.keys():
3034+ del sys.modules[mod_name]
3035+ tmp_mod_name = mod_name
3036+ while '.' in tmp_mod_name:
3037+ tmp_mod_name = tmp_mod_name.rsplit('.',1)[0]
3038+ del sys.modules[tmp_mod_name]
3039+ mymod = __import__(mod_name, globals(), locals(), [],-1)
3040+ else:
3041+ mymod = __import__(mod_name, globals(), locals(), [],-1)
3042+
3043 S = mymod.SubProcesses
3044 mymod = getattr(S, 'allmatrix%spy' % tag)
3045
3046@@ -1713,7 +1738,7 @@
3047 data = self.id_to_path
3048 if '_second' in onedir:
3049 data = self.id_to_path_second
3050-
3051+
3052 # get all the information
3053 all_pdgs = mymod.get_pdg_order()
3054 all_pdgs = [[pdg for pdg in pdgs if pdg!=0] for pdgs in mymod.get_pdg_order()]
3055@@ -1746,7 +1771,6 @@
3056 else:
3057 incoming = pdg[0:2]
3058 outgoing = pdg[2:]
3059- misc.sprint(incoming, outgoing)
3060 order = (list(incoming), list(outgoing))
3061 incoming.sort()
3062 outgoing.sort()
3063@@ -1774,7 +1798,7 @@
3064 misc.sprint(data[tag][:-1])
3065 misc.sprint(order, pdir,)
3066 raise Exception
3067-
3068+
3069 data[tag] = order, pdir, hel
3070
3071
3072
3073=== modified file 'madgraph/interface/tutorial_text.py'
3074--- madgraph/interface/tutorial_text.py 2015-10-01 16:00:08 +0000
3075+++ madgraph/interface/tutorial_text.py 2018-04-20 08:32:43 +0000
3076@@ -1,6 +1,6 @@
3077 ################################################################################
3078 #
3079-# Copyright (c) 2009 The MadGraph5_aMC@NLO Development team and Contributors
3080+# Copyright (c) 2018 The MadGraph5_aMC@NLO Development team and Contributors
3081 #
3082 # This file is a part of the MadGraph5_aMC@NLO project, an application which
3083 # automatically generates Feynman diagrams and matrix elements for arbitrary
3084@@ -77,11 +77,10 @@
3085 """
3086 output = """
3087 If you are following the tutorial, a directory MY_FIRST_MG5_RUN has
3088-been created which can be used in order to run MadEvent exactly as if
3089-it was coming from MG4.
3090+been created which can be used in order to generate LO events/compute cross-section.
3091
3092-Additionally to the MG4 command (see MY_FIRST_MG5_RUN/README), you can also
3093-generate your events/compute the cross-section from this interface:
3094+From that directory you can run the command './bin/generate_events'
3095+You can also generate your events/compute the cross-section from this interface:
3096 Please Enter:
3097 MG5_aMC> launch MY_FIRST_MG5_RUN
3098 (you can interrupt the computation to continue the tutorial by pressing Ctrl-C)
3099@@ -110,13 +109,17 @@
3100 MadEvent output
3101
3102 To import a model, write:
3103-MG5_aMC>import model mssm
3104+MG5_aMC>import model MSSM_SLHA2
3105 """
3106
3107 import_model ="""
3108 You have successfully imported a model. If you followed the tutorial
3109 this is the MSSM.
3110
3111+MadGraph can auto-download a large class of model (and more can be used).
3112+To see the full list of model, write:
3113+MG5_aMC>display modellist
3114+
3115 If you want to know more information about this model you can use the
3116 following commands:
3117 MG5_aMC>display particles
3118@@ -194,9 +197,9 @@
3119 different command in a single line:
3120 MG5_aMC>generate p p > go go; display diagrams
3121
3122-Note that when you run output [madevent_v4], the diagrams are
3123+Note that when you run output [madevent], the diagrams are
3124 automatically written to the matrix.ps files in subprocess
3125-directory, just like with MadGraph 4.
3126+directory.
3127 """
3128
3129 display_diagrams = """
3130
3131=== modified file 'madgraph/iolibs/export_v4.py'
3132--- madgraph/iolibs/export_v4.py 2018-02-20 18:09:19 +0000
3133+++ madgraph/iolibs/export_v4.py 2018-04-20 08:32:43 +0000
3134@@ -3784,7 +3784,17 @@
3135 if not isinstance(self, ProcessExporterFortranMEGroup):
3136 self.proc_characteristic['grouped_matrix'] = False
3137 self.proc_characteristic['complex_mass_scheme'] = mg5options['complex_mass_scheme']
3138-
3139+ # indicate the PDG of all initial particle
3140+ try:
3141+ pdgs1 = [p.get_initial_pdg(1) for me in matrix_elements for m in me.get('matrix_elements') for p in m.get('processes') if p.get_initial_pdg(1)]
3142+ pdgs2 = [p.get_initial_pdg(2) for me in matrix_elements for m in me.get('matrix_elements') for p in m.get('processes') if p.get_initial_pdg(2)]
3143+ except AttributeError:
3144+ pdgs1 = [p.get_initial_pdg(1) for m in matrix_elements.get('matrix_elements') for p in m.get('processes') if p.get_initial_pdg(1)]
3145+ pdgs2 = [p.get_initial_pdg(2) for m in matrix_elements.get('matrix_elements') for p in m.get('processes') if p.get_initial_pdg(2)]
3146+ self.proc_characteristic['pdg_initial1'] = pdgs1
3147+ self.proc_characteristic['pdg_initial2'] = pdgs2
3148+
3149+
3150 modelname = self.opt['model']
3151 if modelname == 'mssm' or modelname.startswith('mssm-'):
3152 param_card = pjoin(self.dir_path, 'Cards','param_card.dat')
3153
3154=== modified file 'madgraph/iolibs/file_writers.py'
3155--- madgraph/iolibs/file_writers.py 2016-12-01 22:06:31 +0000
3156+++ madgraph/iolibs/file_writers.py 2018-04-20 08:32:43 +0000
3157@@ -86,7 +86,7 @@
3158
3159 pass
3160
3161- def writelines(self, lines, context={}):
3162+ def writelines(self, lines, context={}, formatting=True):
3163 """Extends the regular file.writeline() function to write out
3164 nicely formatted code. When defining a context, then the lines
3165 will be preprocessed to apply possible conditional statements on the
3166@@ -107,7 +107,10 @@
3167 splitlines = self.preprocess_template(splitlines,context=context)
3168
3169 for line in splitlines:
3170- res_lines = self.write_line(line)
3171+ if formatting:
3172+ res_lines = self.write_line(line)
3173+ else:
3174+ res_lines = [line+'\n']
3175 for line_to_write in res_lines:
3176 self.write(line_to_write)
3177
3178@@ -200,6 +203,7 @@
3179 __indent = 0
3180 __keyword_list = []
3181 __comment_pattern = re.compile(r"^(\s*#|c$|(c\s+([^=]|$))|cf2py|c\-\-|c\*\*)", re.IGNORECASE)
3182+ __continuation_line = re.compile(r"(?: )[$&]")
3183
3184 def write_line(self, line):
3185 """Write a fortran line, with correct indent and line splits"""
3186@@ -220,7 +224,8 @@
3187 # This is a comment
3188 res_lines = self.write_comment_line(line.lstrip()[1:])
3189 return res_lines
3190-
3191+ elif self.__continuation_line.search(line):
3192+ return line+'\n'
3193 else:
3194 # This is a regular Fortran line
3195
3196
3197=== modified file 'madgraph/iolibs/files.py'
3198--- madgraph/iolibs/files.py 2017-09-24 21:24:55 +0000
3199+++ madgraph/iolibs/files.py 2018-04-20 08:32:43 +0000
3200@@ -227,6 +227,7 @@
3201 os.symlink(target, os.path.join(starting_dir, name))
3202 except Exception, error:
3203 if log:
3204+ logger.debug(error)
3205 logger.warning('Could not link %s at position: %s' % (file_pos, \
3206 os.path.realpath(starting_dir)))
3207
3208
3209=== modified file 'madgraph/loop/loop_exporters.py'
3210--- madgraph/loop/loop_exporters.py 2017-07-31 12:50:36 +0000
3211+++ madgraph/loop/loop_exporters.py 2018-04-20 08:32:43 +0000
3212@@ -155,7 +155,7 @@
3213 elif self.dependencies=='external':
3214 if not os.path.exists(os.path.join(self.cuttools_dir,'includects','libcts.a')):
3215 logger.info('Compiling CutTools. This has to be done only once and'+\
3216- ' can take a couple of minutes.','$MG:color:BLACK')
3217+ ' can take a couple of minutes.','$MG:BOLD')
3218 current = misc.detect_current_compiler(os.path.join(\
3219 self.cuttools_dir,'makefile'))
3220 new = 'gfortran' if self.fortran_compiler is None else \
3221@@ -1978,7 +1978,7 @@
3222
3223
3224 logger.info('Compiling IREGI. This has to be done only once and'+\
3225- ' can take a couple of minutes.','$MG:color:BLACK')
3226+ ' can take a couple of minutes.','$MG:BOLD')
3227
3228 current = misc.detect_current_compiler(os.path.join(\
3229 libpath,'makefile_ML5_lib'))
3230
3231=== modified file 'madgraph/various/banner.py'
3232--- madgraph/various/banner.py 2018-03-09 15:38:21 +0000
3233+++ madgraph/various/banner.py 2018-04-20 08:32:43 +0000
3234@@ -1086,7 +1086,7 @@
3235 val = val.lower()
3236 allowed = allowed.lower()
3237 if value in allowed:
3238- i = allowed.find(value)
3239+ i = allowed.index(value)
3240 new_values.append(self.allowed_value[i])
3241 continue
3242 # no continue -> bad input
3243@@ -1186,10 +1186,10 @@
3244 valid=True
3245 elif isinstance(value, str):
3246 value = value.lower()
3247- allowed = allowed.lower()
3248+ allowed = [v.lower() for v in allowed]
3249 if value in allowed:
3250- i = allowed.find(value)
3251- value = self.allowed_value[i]
3252+ i = allowed.index(value)
3253+ value = self.allowed_value[lower_name][i]
3254 valid=True
3255
3256 if not valid:
3257@@ -1288,10 +1288,10 @@
3258 if new_value == value:
3259 value = new_value
3260 else:
3261- raise Exception, "Wrong input type for %s found %s and expecting %s for value %s" %\
3262+ raise InvalidCmd, "Wrong input type for %s found %s and expecting %s for value %s" %\
3263 (name, type(value), targettype, value)
3264 else:
3265- raise Exception, "Wrong input type for %s found %s and expecting %s for value %s" %\
3266+ raise InvalidCmd, "Wrong input type for %s found %s and expecting %s for value %s" %\
3267 (name, type(value), targettype, value)
3268 else:
3269 # We have a string we have to format the attribute from the string
3270@@ -1305,7 +1305,7 @@
3271 elif value.lower() in ['1', '.true.', 't', 'true', 'on']:
3272 value = True
3273 else:
3274- raise Exception, "%s can not be mapped to True/False for %s" % (repr(value),name)
3275+ raise InvalidCmd, "%s can not be mapped to True/False for %s" % (repr(value),name)
3276 elif targettype == str:
3277 value = value.strip()
3278 if value.startswith('\'') and value.endswith('\''):
3279@@ -1324,16 +1324,16 @@
3280 try:
3281 value = float(value.replace('d','e'))
3282 except ValueError:
3283- raise Exception, "%s can not be mapped to an integer" % value
3284+ raise InvalidCmd, "%s can not be mapped to an integer" % value
3285 try:
3286 new_value = int(value)
3287 except ValueError:
3288- raise Exception, "%s can not be mapped to an integer" % value
3289+ raise InvalidCmd, "%s can not be mapped to an integer" % value
3290 else:
3291 if value == new_value:
3292 value = new_value
3293 else:
3294- raise Exception, "incorect input: %s need an integer for %s" % (value,name)
3295+ raise InvalidCmd, "incorect input: %s need an integer for %s" % (value,name)
3296 elif targettype == float:
3297 value = value.replace('d','e') # pass from Fortran formatting
3298 try:
3299@@ -1349,11 +1349,11 @@
3300 v /= float(split[2*i+2])
3301 except:
3302 v=0
3303- raise Exception, "%s can not be mapped to a float" % value
3304+ raise InvalidCmd, "%s can not be mapped to a float" % value
3305 finally:
3306 value = v
3307 else:
3308- raise Exception, "type %s is not handle by the card" % targettype
3309+ raise InvalidCmd, "type %s is not handle by the card" % targettype
3310
3311 return value
3312
3313@@ -1409,7 +1409,9 @@
3314 self.add_param('bias_module','None')
3315 self.add_param('max_n_matched_jets', 0)
3316 self.add_param('colored_pdgs', [1,2,3,4,5])
3317- self.add_param('complex_mass_scheme', False)
3318+ self.add_param('complex_mass_scheme', False)
3319+ self.add_param('pdg_initial1', [0])
3320+ self.add_param('pdg_initial2', [0])
3321
3322 def read(self, finput):
3323 """Read the input file, this can be a path to a file,
3324@@ -1883,7 +1885,9 @@
3325 started_subrun_reading = False
3326 while line!='':
3327 # Skip comments
3328- if line.strip().startswith('!') or line.strip().startswith('\n'):
3329+ if line.strip().startswith('!') or \
3330+ line.strip().startswith('\n') or\
3331+ line.strip() == '':
3332 output.write(line)
3333 # Proceed to next line
3334 last_pos = tmpl.tell()
3335@@ -2033,8 +2037,8 @@
3336 # If 'LHEFInputs:nSubruns' is not user_set, then make sure it is
3337 # updated at least larger or equal to the maximum SubRunID
3338 if 'LHEFInputs:nSubruns'.lower() not in self.user_set and \
3339- len(subruns_to_write)>0 and self['LHEFInputs:nSubruns']<\
3340- max(subruns_to_write.keys()):
3341+ len(subruns_to_write)>0 and 'LHEFInputs:nSubruns' in self\
3342+ and self['LHEFInputs:nSubruns']<max(subruns_to_write.keys()):
3343 logger.info("Updating PY8 parameter 'LHEFInputs:nSubruns' to "+
3344 "%d so as to cover all defined subruns."%max(subruns_to_write.keys()))
3345 self['LHEFInputs:nSubruns'] = max(subruns_to_write.keys())
3346@@ -2206,6 +2210,8 @@
3347 self.cuts_parameter = []
3348 # parameter added where legacy requires an older value.
3349 self.system_default = {}
3350+
3351+ self.warned=False
3352
3353
3354
3355@@ -2238,10 +2244,7 @@
3356 if legacy:
3357 self.legacy_parameter[name] = value
3358 include = False
3359- if include is True:
3360- self.includepath[True].append(name)
3361- elif include:
3362- self.includepath[include].append(name)
3363+ self.includepath[include].append(name)
3364 if hidden or system:
3365 self.hidden_param.append(name)
3366 if cut:
3367@@ -2287,11 +2290,13 @@
3368 raise
3369
3370
3371- def write(self, output_file, template=None, python_template=False):
3372+ def write(self, output_file, template=None, python_template=False,
3373+ write_hidden=False):
3374 """Write the run_card in output_file according to template
3375 (a path to a valid run_card)"""
3376
3377 to_write = set(self.user_set)
3378+ written = set()
3379 if not template:
3380 raise Exception
3381
3382@@ -2324,23 +2329,37 @@
3383 endline = '\n'
3384 else:
3385 endline = ''
3386- text += ' %s\t= %s %s%s' % (value, name, comment, endline)
3387+ text += ' %s\t= %s %s%s' % (value, name, comment, endline)
3388+ written.add(name)
3389
3390 if name.lower() in to_write:
3391 to_write.remove(nline[1].strip().lower())
3392 else:
3393 logger.info('Adding missing parameter %s to current %s (with default value)',
3394 (name, self.filename))
3395+ written.add(name)
3396 text += line
3397
3398- if to_write:
3399+ if to_write or write_hidden:
3400 text+="""#*********************************************************************
3401-# Additional parameter
3402+# Additional hidden parameters
3403 #*********************************************************************
3404-"""
3405-
3406+"""
3407+ if write_hidden:
3408+ #
3409+ # do not write hidden parameter not hidden for this template
3410+ #
3411+ if python_template:
3412+ written = written.union(set(re.findall('\%\((\w*)\)s', file(template,'r').read(), re.M)))
3413+ to_write = to_write.union(set(self.hidden_param))
3414+ to_write = to_write.difference(written)
3415+
3416 for key in to_write:
3417- text += ' %s\t= %s # %s\n' % (self[key], key, 'hidden parameter')
3418+ if key in self.system_only:
3419+ continue
3420+
3421+ comment = self.comments.get(key,'hidden_parameter').replace('\n','\n#')
3422+ text += ' %s\t= %s # %s\n' % (self[key], key, comment)
3423
3424 if isinstance(output_file, str):
3425 fsock = open(output_file,'w')
3426@@ -2367,6 +2386,7 @@
3427 log_level = 20
3428 if not default:
3429 default = dict.__getitem__(self, name.lower())
3430+
3431 logger.log(log_level, '%s missed argument %s. Takes default: %s'
3432 % (self.filename, name, default))
3433 self[name] = default
3434@@ -2426,11 +2446,18 @@
3435 return "'%s'" % value
3436
3437
3438- def check_validity(self):
3439+
3440+ def check_validity(self, log_level=30):
3441 """check that parameter missing in the card are set to the expected value"""
3442
3443 for name, value in self.system_default.items():
3444 self.set(name, value, changeifuserset=False)
3445+
3446+
3447+ for name in self.includepath[False]:
3448+ to_bypass = self.hidden_param + self.legacy_parameter.keys()
3449+ if name not in to_bypass:
3450+ self.get_default(name, log_level=log_level)
3451
3452 for name in self.legacy_parameter:
3453 if self[name] != self.legacy_parameter[name]:
3454@@ -2457,6 +2484,8 @@
3455 for incname in self.includepath:
3456 if incname is True:
3457 pathinc = self.default_include_file
3458+ elif incname is False:
3459+ continue
3460 else:
3461 pathinc = incname
3462
3463@@ -2498,28 +2527,26 @@
3464 fsock.writelines(line)
3465 fsock.close()
3466
3467+ @staticmethod
3468+ def get_idbmup(lpp):
3469+ """return the particle colliding pdg code"""
3470+ if lpp in (1,2, -1,-2):
3471+ return math.copysign(2212, lpp)
3472+ elif lpp in (3,-3):
3473+ return math.copysign(11, lpp)
3474+ elif lpp == 0:
3475+ #logger.critical("Fail to write correct idbmup in the lhe file. Please correct those by hand")
3476+ return 0
3477+ else:
3478+ return lpp
3479
3480 def get_banner_init_information(self):
3481 """return a dictionary with the information needed to write
3482 the first line of the <init> block of the lhe file."""
3483
3484 output = {}
3485-
3486- def get_idbmup(lpp):
3487- """return the particle colliding pdg code"""
3488- if lpp in (1,2, -1,-2):
3489- return math.copysign(2212, lpp)
3490- elif lpp in (3,-3):
3491- return math.copysign(11, lpp)
3492- elif lpp == 0:
3493- #logger.critical("Fail to write correct idbmup in the lhe file. Please correct those by hand")
3494- return 0
3495- else:
3496- return lpp
3497-
3498-
3499- output["idbmup1"] = get_idbmup(self['lpp1'])
3500- output["idbmup2"] = get_idbmup(self['lpp2'])
3501+ output["idbmup1"] = self.get_idbmup(self['lpp1'])
3502+ output["idbmup2"] = self.get_idbmup(self['lpp2'])
3503 output["ebmup1"] = self["ebeam1"]
3504 output["ebmup2"] = self["ebeam2"]
3505 output["pdfgup1"] = 0
3506@@ -2570,7 +2597,7 @@
3507
3508 self.add_param("run_tag", "tag_1", include=False)
3509 self.add_param("gridpack", False)
3510- self.add_param("time_of_flight", -1.0, include=False, hidden=True)
3511+ self.add_param("time_of_flight", -1.0, include=False)
3512 self.add_param("nevents", 10000)
3513 self.add_param("iseed", 0)
3514 self.add_param("lpp1", 1, fortran_name="lpp(1)", allowed=[-1,1,0,2,3,9, -2,-3],
3515@@ -2738,7 +2765,7 @@
3516 self.add_param("sys_alpsfact", "None", include=False)
3517 self.add_param("sys_matchscale", "auto", include=False)
3518 self.add_param("sys_pdf", "NNPDF23_lo_as_0130_qed", include=False)
3519- self.add_param("sys_scalecorrelation", -1, include=False)
3520+ self.add_param("sys_scalecorrelation", -1, include=False, hidden=True)
3521
3522 #parameter not in the run_card by default
3523 self.add_param('gridrun', False, hidden=True)
3524@@ -2763,17 +2790,17 @@
3525 self.add_param('eta_min_pdg',{'__type__':0.}, include=False)
3526 self.add_param('eta_max_pdg',{'__type__':0.}, include=False)
3527 self.add_param('mxx_min_pdg',{'__type__':0.}, include=False)
3528- self.add_param('mxx_only_part_antipart', {'default':False}, include=False, hidden=True)
3529+ self.add_param('mxx_only_part_antipart', {'default':False}, include=False)
3530
3531- self.add_param('pdg_cut',[0], hidden=True, system=True) # store which PDG are tracked
3532- self.add_param('ptmin4pdg',[0.], hidden=True, system=True) # store pt min
3533- self.add_param('ptmax4pdg',[-1.], hidden=True, system=True)
3534- self.add_param('Emin4pdg',[0.], hidden=True, system=True) # store pt min
3535- self.add_param('Emax4pdg',[-1.], hidden=True, system=True)
3536- self.add_param('etamin4pdg',[0.], hidden=True, system=True) # store pt min
3537- self.add_param('etamax4pdg',[-1.], hidden=True, system=True)
3538- self.add_param('mxxmin4pdg',[-1.], hidden=True, system=True)
3539- self.add_param('mxxpart_antipart', [False], hidden=True, system=True)
3540+ self.add_param('pdg_cut',[0], system=True) # store which PDG are tracked
3541+ self.add_param('ptmin4pdg',[0.], system=True) # store pt min
3542+ self.add_param('ptmax4pdg',[-1.], system=True)
3543+ self.add_param('Emin4pdg',[0.], system=True) # store pt min
3544+ self.add_param('Emax4pdg',[-1.], system=True)
3545+ self.add_param('etamin4pdg',[0.], system=True) # store pt min
3546+ self.add_param('etamax4pdg',[-1.], system=True)
3547+ self.add_param('mxxmin4pdg',[-1.], system=True)
3548+ self.add_param('mxxpart_antipart', [False], system=True)
3549 # Not implemetented right now (double particle cut)
3550 #self.add_param('pdg_cut_2',[0], hidden=True, system=True)
3551 # self.add_param('M_min_pdg',[0.], hidden=True, system=True) # store pt min
3552@@ -3031,7 +3058,8 @@
3553 self['use_syst'] = False
3554 self['systematics_program'] = 'none'
3555
3556- def write(self, output_file, template=None, python_template=False):
3557+ def write(self, output_file, template=None, python_template=False,
3558+ **opt):
3559 """Write the run_card in output_file according to template
3560 (a path to a valid run_card)"""
3561
3562@@ -3045,7 +3073,7 @@
3563 python_template = False
3564
3565 super(RunCardLO, self).write(output_file, template=template,
3566- python_template=python_template)
3567+ python_template=python_template, **opt)
3568
3569
3570 class InvalidMadAnalysis5Card(InvalidCmd):
3571@@ -3598,28 +3626,28 @@
3572 for scale in scales:
3573 if self[scale]:
3574 logger.warning('''For consistency in the FxFx merging, \'%s\' has been set to false'''
3575- % scale,'$MG:color:BLACK')
3576+ % scale,'$MG:BOLD')
3577 self[scale]= False
3578 #and left to default dynamical scale
3579 if len(self["dynamical_scale_choice"]) > 1 or self["dynamical_scale_choice"][0] != -1:
3580 self["dynamical_scale_choice"] = [-1]
3581 self["reweight_scale"]=[self["reweight_scale"][0]]
3582 logger.warning('''For consistency in the FxFx merging, dynamical_scale_choice has been set to -1 (default)'''
3583- ,'$MG:color:BLACK')
3584+ ,'$MG:BOLD')
3585
3586 # 2. Use kT algorithm for jets with pseudo-code size R=1.0
3587 jetparams=['jetradius','jetalgo']
3588 for jetparam in jetparams:
3589 if float(self[jetparam]) != 1.0:
3590 logger.info('''For consistency in the FxFx merging, \'%s\' has been set to 1.0'''
3591- % jetparam ,'$MG:color:BLACK')
3592+ % jetparam ,'$MG:BOLD')
3593 self[jetparam] = 1.0
3594 elif self['ickkw'] == -1 and (self["dynamical_scale_choice"][0] != -1 or
3595 len(self["dynamical_scale_choice"]) > 1):
3596 self["dynamical_scale_choice"] = [-1]
3597 self["reweight_scale"]=[self["reweight_scale"][0]]
3598 logger.warning('''For consistency with the jet veto, the scale which will be used is ptj. dynamical_scale_choice will be set at -1.'''
3599- ,'$MG:color:BLACK')
3600+ ,'$MG:BOLD')
3601
3602 # For interface to APPLGRID, need to use LHAPDF and reweighting to get scale uncertainties
3603 if self['iappl'] != 0 and self['pdlabel'].lower() != 'lhapdf':
3604@@ -3773,7 +3801,7 @@
3605 self['mxxmin4pdg'] = [0.]
3606 self['mxxpart_antipart'] = [False]
3607
3608- def write(self, output_file, template=None, python_template=False):
3609+ def write(self, output_file, template=None, python_template=False, **opt):
3610 """Write the run_card in output_file according to template
3611 (a path to a valid run_card)"""
3612
3613@@ -3787,7 +3815,7 @@
3614 python_template = False
3615
3616 super(RunCardNLO, self).write(output_file, template=template,
3617- python_template=python_template)
3618+ python_template=python_template, **opt)
3619
3620
3621 def create_default_for_process(self, proc_characteristic, history, proc_def):
3622
3623=== modified file 'madgraph/various/misc.py'
3624--- madgraph/various/misc.py 2018-03-27 17:23:29 +0000
3625+++ madgraph/various/misc.py 2018-04-20 08:32:43 +0000
3626@@ -575,6 +575,37 @@
3627 # reset it to change the next file
3628 mod = False
3629
3630+def pid_exists(pid):
3631+ """Check whether pid exists in the current process table.
3632+ UNIX only.
3633+ https://stackoverflow.com/questions/568271/how-to-check-if-there-exists-a-process-with-a-given-pid-in-python
3634+ """
3635+ import errno
3636+
3637+ if pid < 0:
3638+ return False
3639+ if pid == 0:
3640+ # According to "man 2 kill" PID 0 refers to every process
3641+ # in the process group of the calling process.
3642+ # On certain systems 0 is a valid PID but we have no way
3643+ # to know that in a portable fashion.
3644+ raise ValueError('invalid PID 0')
3645+ try:
3646+ os.kill(pid, 0)
3647+ except OSError as err:
3648+ if err.errno == errno.ESRCH:
3649+ # ESRCH == No such process
3650+ return False
3651+ elif err.errno == errno.EPERM:
3652+ # EPERM clearly means there's a process to deny access to
3653+ return True
3654+ else:
3655+ # According to "man 2 kill" possible error values are
3656+ # (EINVAL, EPERM, ESRCH)
3657+ raise
3658+ else:
3659+ return True
3660+
3661 #===============================================================================
3662 # mute_logger (designed to work as with statement)
3663 #===============================================================================
3664@@ -874,6 +905,19 @@
3665 """nice way to call an external program with nice error treatment"""
3666 return subprocess.Popen(arg, *args, **opt)
3667
3668+@check_system_error()
3669+def call_stdout(arg, *args, **opt):
3670+ """nice way to call an external program with nice error treatment"""
3671+ try:
3672+ out = subprocess.Popen(arg, *args, stdout=subprocess.PIPE, **opt)
3673+ except OSError:
3674+ arg[0] = './%s' % arg[0]
3675+ out = subprocess.call(arg, *args, stdout=subprocess.PIPE, **opt)
3676+
3677+ str_out = out.stdout.read().strip()
3678+ return str_out
3679+
3680+
3681 @multiple_try()
3682 def mult_try_open(filepath, *args, **opt):
3683 """try to open a file with multiple try to ensure that filesystem is sync"""
3684@@ -1397,6 +1441,8 @@
3685
3686 if wait:
3687 raw_input('press_enter to continue')
3688+ elif opt.has_key('sleep'):
3689+ time.sleep(int(opt['sleep']))
3690
3691 return
3692
3693@@ -1901,9 +1947,9 @@
3694 else:
3695 if keyname in getattr(plugin, target_type):
3696 if not info:
3697- logger.info('Using from plugin %s mode %s' % (plug, keyname), '$MG:color:BLACK')
3698+ logger.info('Using from plugin %s mode %s' % (plug, keyname), '$MG:BOLD')
3699 else:
3700- logger.info(info % {'plug': plug, 'key':keyname}, '$MG:color:BLACK')
3701+ logger.info(info % {'plug': plug, 'key':keyname}, '$MG:BOLD')
3702 return getattr(plugin, target_type)[keyname]
3703
3704 if not keyname:
3705
3706=== modified file 'models/__init__.py'
3707--- models/__init__.py 2017-02-16 14:49:57 +0000
3708+++ models/__init__.py 2018-04-20 08:32:43 +0000
3709@@ -16,6 +16,7 @@
3710
3711 import os
3712 import sys
3713+import madgraph.various.misc as misc
3714
3715 def load_model(name, decay=False):
3716
3717@@ -24,6 +25,7 @@
3718 name = name[:-1]
3719
3720
3721+
3722 path_split = name.split(os.sep)
3723 if len(path_split) == 1:
3724 model_pos = 'models.%s' % name
3725@@ -36,8 +38,8 @@
3726 raise Exception, 'name %s already consider as a python library cann\'t be reassigned(%s!=%s)' % \
3727 (path_split[-1], model_path, sys_path)
3728
3729- sys.path.insert(0, os.sep.join(path_split[:-1]))
3730- __import__(path_split[-1])
3731+ with misc.TMP_variable(sys, 'path', [os.sep.join(path_split[:-1])]):
3732+ __import__(path_split[-1])
3733 output = sys.modules[path_split[-1]]
3734 if decay:
3735 dec_name = '%s.decays' % path_split[-1]
3736@@ -47,9 +49,5 @@
3737 pass
3738 else:
3739 output.all_decays = sys.modules[dec_name].all_decays
3740-
3741- sys.path.pop(0)
3742-
3743-
3744-
3745+
3746 return sys.modules[path_split[-1]]
3747
3748=== modified file 'models/check_param_card.py'
3749--- models/check_param_card.py 2018-02-20 18:09:19 +0000
3750+++ models/check_param_card.py 2018-04-20 08:32:43 +0000
3751@@ -488,7 +488,7 @@
3752 if not misc.equal(model_value, param_value, 4):
3753 modify = True
3754 if loglevel == 20:
3755- logger.info('For consistency, the mass of particle %s (%s) is changed to %s.' % (lhacode, particle.get('name'), model_value), '$MG:color:BLACK')
3756+ logger.info('For consistency, the mass of particle %s (%s) is changed to %s.' % (lhacode, particle.get('name'), model_value), '$MG:BOLD')
3757 else:
3758 logger.log(loglevel, 'For consistency, the mass of particle %s (%s) is changed to %s.' % (lhacode, particle.get('name'), model_value))
3759 #logger.debug('was %s', param_value)
3760@@ -511,7 +511,7 @@
3761 if not misc.equal(model_value, param_value, 4):
3762 modify = True
3763 if loglevel == 20:
3764- logger.info('For consistency, the width of particle %s (%s) is changed to %s.' % (lhacode, particle.get('name'), model_value), '$MG:color:BLACK')
3765+ logger.info('For consistency, the width of particle %s (%s) is changed to %s.' % (lhacode, particle.get('name'), model_value), '$MG:BOLD')
3766 else:
3767 logger.log(loglevel,'For consistency, the width of particle %s (%s) is changed to %s.' % (lhacode, particle.get('name'), model_value))
3768 #logger.debug('was %s', param_value)
3769@@ -955,7 +955,7 @@
3770 for positions in itertools.product(*lengths):
3771 self.itertag = []
3772 if self.logging:
3773- logger.info("Create the next param_card in the scan definition", '$MG:color:BLACK')
3774+ logger.info("Create the next param_card in the scan definition", '$MG:BOLD')
3775 for i, pos in enumerate(positions):
3776 key = keys[i]
3777 for param, values in all_iterators[key]:
3778@@ -988,6 +988,7 @@
3779 for param in self.autowidth:
3780 self.cross[-1]['width#%s' % param.lhacode[0]] = paramcard.get_value(param.lhablock, param.lhacode)
3781
3782+
3783 def write_summary(self, path, order=None, lastline=False, nbcol=20):
3784 """ """
3785
3786@@ -1016,11 +1017,13 @@
3787 ff.write(formatting % tuple(['run_name'] + self.param_order + keys))
3788 formatting = "%s%s%s\n" %('%%-%is ' % (nbcol), ('%%-%ie ' % (nbcol))* len(self.param_order),
3789 ('%%-%ie ' % (nbcol))* len(keys))
3790-
3791+
3792+
3793 if not lastline:
3794 to_print = self.cross
3795 else:
3796 to_print = self.cross[-1:]
3797+
3798 for info in to_print:
3799 name = info['run_name']
3800 bench = info['bench']
3801@@ -1268,7 +1271,7 @@
3802 is_modified = True
3803 if log ==20:
3804 logger.log(log,'For model consistency, update %s with id %s to value %s',
3805- block, id, 0.0, '$MG:color:BLACK')
3806+ block, id, 0.0, '$MG:BOLD')
3807 elif log:
3808 logger.log(log,'For model consistency, update %s with id %s to value %s',
3809 block, id, 0.0)
3810@@ -1299,7 +1302,7 @@
3811 is_modified = True
3812 if log ==20:
3813 logger.log(log,'For model consistency, update %s with id %s to value %s',
3814- (block, id, 1.0), '$MG:color:BLACK')
3815+ (block, id, 1.0), '$MG:BOLD')
3816 elif log:
3817 logger.log(log,'For model consistency, update %s with id %s to value %s',
3818 (block, id, 1.0))
3819@@ -1336,7 +1339,7 @@
3820 is_modified = True
3821 if log ==20:
3822 logger.log(log,'For model consistency, update %s with id %s to value %s since it should be equal to parameter with id %s',
3823- block, id1, value2, id2, '$MG:color:BLACK')
3824+ block, id1, value2, id2, '$MG:BOLD')
3825 elif log:
3826 logger.log(log,'For model consistency, update %s with id %s to value %s since it should be equal to parameter with id %s',
3827 block, id1, value2, id2)
3828@@ -1365,7 +1368,7 @@
3829 is_modified = True
3830 if log ==20:
3831 logger.log(log,'For model consistency, update %s with id %s to value %s since it should be equal to the opposite of the parameter with id %s',
3832- block, id1, -value2, id2, '$MG:color:BLACK')
3833+ block, id1, -value2, id2, '$MG:BOLD')
3834 elif log:
3835 logger.log(log,'For model consistency, update %s with id %s to value %s since it should be equal to the opposite of the parameter with id %s',
3836 block, id1, -value2, id2)
3837
3838=== modified file 'models/usermod.py'
3839--- models/usermod.py 2017-11-30 23:09:49 +0000
3840+++ models/usermod.py 2018-04-20 08:32:43 +0000
3841@@ -96,6 +96,12 @@
3842 self.CTvertices = list(model.all_CTvertices)
3843 else:
3844 self.CTvertices = []
3845+ # UFO NLO extension
3846+ if hasattr(model, 'all_CTparameters'):
3847+ self.CTparameters = list(model.all_CTparameters)
3848+ else:
3849+ self.CTparameters = []
3850+
3851
3852 #translate for how to write the python file
3853 if 'self.expr = expression' in open(pjoin(self.modelpath, 'object_library.py')).read():
3854@@ -132,6 +138,7 @@
3855 self.write_functions(outputdir)
3856 self.write_propagators(outputdir)
3857 self.write_ctvertices(outputdir)
3858+ self.write_ctparameters(outputdir)
3859
3860 self.write_external_files(outputdir)
3861 self.write_restrict_card(outputdir)
3862@@ -144,10 +151,7 @@
3863 to_change = {}
3864 to_change.update(self.translate)
3865 to_change.update(self.old_new)
3866- for particle in self.particles:
3867- if hasattr(particle, 'replace') and particle.replace:
3868- misc.sprint(particle.get('name'), particle.replace.get('name'))
3869-
3870+
3871 pattern = re.compile(r'\b(%s)\b' % ('|'.join(to_change)))
3872
3873 #need to check that all particle are written correctly <- Fix potential issue
3874@@ -204,19 +208,12 @@
3875 # all added -> write it
3876 param_card.write(pjoin(outputdir, p), precision=7)
3877
3878-
3879-
3880-
3881-
3882-
3883-
3884-
3885 def format_param(self, param):
3886 """convert param to string in order to have it written correctly for the
3887 UFO file"""
3888
3889 if isinstance(param, basestring):
3890- return "'%s'" % param.replace('\'', '\\\'').replace('\"', '\\\"')
3891+ return "'%s'" % param.replace("\\", "\\\\").replace('\'', '\\\'').replace('\"', '\\\"')
3892 elif isinstance(param, int) or isinstance(param, float) or \
3893 isinstance(param, complex):
3894 return "%s" % param
3895@@ -271,6 +268,9 @@
3896 add_space = len(text)
3897 else:
3898 add_space = 0
3899+
3900+ if ',' in data:
3901+ continue
3902
3903 try:
3904 expr = getattr(obj, data)
3905@@ -294,6 +294,10 @@
3906 else:
3907 other_attr = obj.__dict__.keys()
3908
3909+ if str(obj.__class__.__name__) == 'CTParameter' and 'nature' in other_attr:
3910+ logger.critical('UFO model is outdated (including some bugs). Please update object_library.py to latest version')
3911+ other_attr.remove('nature')
3912+
3913 other_attr.sort()
3914 if other_attr == ['GhostNumber', 'LeptonNumber', 'Y', 'partial_widths', 'selfconjugate']:
3915 other_attr=['GhostNumber', 'LeptonNumber', 'Y','selfconjugate']
3916@@ -417,6 +421,26 @@
3917 ff.close()
3918 return
3919
3920+ def write_ctparameters(self, outputdir):
3921+ """ """
3922+ if not self.CTparameters:
3923+ return
3924+
3925+ text = """
3926+# This file was automatically created by The UFO_usermod
3927+
3928+from object_library import all_CTparameters, CTParameter
3929+
3930+from function_library import complexconjugate, re, im, csc, sec, acsc, asec, cot
3931+"""
3932+
3933+ text += self.create_file_content(self.CTparameters)
3934+ ff = open(os.path.join(outputdir, 'CT_parameters.py'), 'w')
3935+ ff.writelines(text)
3936+ ff.close()
3937+ return
3938+
3939+
3940 def write_orders(self, outputdir):
3941 """ """
3942 text = """
3943@@ -588,6 +612,9 @@
3944 elif p_plugin.mass.name.lower() == 'zero':
3945 pass
3946 else:
3947+ misc.sprint(p_base.mass.value, p_plugin.mass.value, dir(p_base.mass))
3948+ misc.sprint(p_base.mass.nature, p_plugin.mass.nature)
3949+ misc.sprint(self.old_new)
3950 raise USRMODERROR, 'Some inconsistency in the mass assignment in the model\n' + \
3951 ' Mass: %s and %s\n' %(p_base.mass.name, p_plugin.mass.name) + \
3952 ' conflict name %s\n' % self.old_new + \
3953@@ -657,6 +684,29 @@
3954 self.old_new[parameter.name] = old_param.name
3955 # self.add_internal_parameter(iden_param)
3956
3957+ elif parameter.lhablock.lower() in ['mass', 'decay'] and int(parameter.lhacode[0]) in identify_pid:
3958+ # this means that the parameter is an internal parameter in the original model...
3959+ #find it via the particle name
3960+ orig_particle = self.particle_dict[lhacode[0]]
3961+ if parameter.lhablock.lower() == 'mass':
3962+ old_param = orig_particle.mass
3963+ else:
3964+ old_param = orig_particle.width
3965+ if old_param.name.lower() == 'zero':
3966+ #Just add the new parameter to the current list
3967+ self.parameters.append(parameter)
3968+ self.new_external.append(parameter)
3969+ else:
3970+ logger.info('The two model defines the parameter for block \'%s\' with id \'%s\' with different parameter name \'%s\', \'%s\'\n'\
3971+ % (parameter.lhablock.lower(), lhacode[0], parameter.name, old_param.name) + \
3972+ ' We will merge those two parameters in a single one')
3973+ if parameter.name in self.old_new.values():
3974+ key = [k for k in self.old_new if self.old_new[k] == parameter.name][0]
3975+ self.old_new[key] = old_param.name
3976+ self.old_new[parameter.name] = old_param.name
3977+ else:
3978+ self.old_new[parameter.name] = old_param.name
3979+ # self.add_internal_parameter(iden_param)
3980 else:
3981 #Just add the new parameter to the current list
3982 self.parameters.append(parameter)
3983
3984=== modified file 'tests/acceptance_tests/test_cmd_madevent.py'
3985--- tests/acceptance_tests/test_cmd_madevent.py 2017-05-22 09:11:33 +0000
3986+++ tests/acceptance_tests/test_cmd_madevent.py 2018-04-20 08:32:43 +0000
3987@@ -634,6 +634,7 @@
3988
3989 if not self.debuging:
3990 shutil.rmtree(self.path)
3991+ self.assertFalse(self.debuging)
3992
3993 def test_add_time_of_flight(self):
3994 """checking time of flight is working fine"""

Subscribers

People subscribed via source and target branches

to all changes: