Merge lp:~madteam/mg5amcnlo/MG5_on_web into lp:~madteam/mg5amcnlo/trunk

Proposed by Olivier Mattelaer
Status: Merged
Merged at revision: 32
Proposed branch: lp:~madteam/mg5amcnlo/MG5_on_web
Merge into: lp:~madteam/mg5amcnlo/trunk
Diff against target: 3912 lines (+219/-1567)
12 files modified
.pydevproject (+1/-1)
bin/mg5 (+14/-5)
madgraph/interface/cmd_interface.py (+0/-1532)
madgraph/iolibs/drawing.py (+9/-3)
madgraph/iolibs/drawing_eps.py (+1/-0)
madgraph/iolibs/export_v4.py (+11/-4)
madgraph/iolibs/import_v4.py (+17/-10)
tests/input_files/v4_proc_card.dat (+2/-1)
tests/test_manager.py (+24/-7)
tests/unit_tests/interface/test_cmd.py (+137/-0)
tests/unit_tests/iolibs/test_drawing.py (+0/-1)
tests/unit_tests/iolibs/test_import_v4.py (+3/-3)
To merge this branch: bzr merge lp:~madteam/mg5amcnlo/MG5_on_web
Reviewer Review Type Date Requested Status
MadTeam Pending
Review via email: mp+25285@code.launchpad.net

Description of the change

This version includes mostly modification in the cmd interface in order to authorize strict security restriction on what can (or cann't) be done via the web interface.

This is off course linked to a web interface:
http://madgraph.phys.ucl.ac.be/new_gen_proc_card_mg5.html
In order to be operational you should have javascript activated (which is quite common).
This authorize, for example, to forbid heft and quarkonium model if we run with MG5.

To post a comment you must log in.
Revision history for this message
Johan Alwall (johan-alwall) wrote :

Hi Olivier!

This is really cool! Great job!

I made some tests, and have a few questions:
- What happened here:
http://<email address hidden>/PROC11/index.html
?
(I defined the process p p > t t~ QED=0, t > j j b, t~ > l- vl b~ in
the proc line, and chose MG4 syntax).
It looks like the generation just died once the SM was loaded, and
there's error message.
In the same process, you see that the card page doesn't look that
good. We need to think about how to treat QED/QCD orders in a better
way in the gen_cardhtml-pl script.
- We need a link describing the MG5 syntax, and if you could provide a
warning message when MG5 is chosen (by Javascript) saying that for
decay chains, the coupling orders only apply to the core process, that
would be great!
- I would like to be able to upload an MG4 proc_card to MG5, and right
now it's not clear how to do this. I think there should be two
different upload fields, one for MG5 proc_cards, one for MG4
proc_cards, and for the latter there should be a choice which
generator should be used.

All the best,
Johan

Revision history for this message
Johan Alwall (johan-alwall) wrote :

Hi again Olivier,

I tried choosing MG5 syntax, but also that went wrong, see
http://<email address hidden>/PROC16/index.html

All the best,
Johan

Revision history for this message
Johan Alwall (johan-alwall) wrote :

Sorry for spamming you Olivier, but I have one more question:

Yesterday, I updated the newprocess_mg5 script so that the output of
mg5 is piped to the proc_log.txt file. In the web version, it seems
that only the stdout and not the logging output appears in the file.
It would be very nice to have the full logging output in the file,
since this is a good way to check exactly what is happening during the
generation, and corresponds closer to the output of MG4.

Best,
Johan

lp:~madteam/mg5amcnlo/MG5_on_web updated
140. By Olivier Mattelaer

correct bug when choosing mg5 format and specifying orders/decay chains

Revision history for this message
Olivier Mattelaer (olivier-mattelaer) wrote :

Hi Johan, Thanks a lot for all your comment:

>I tried choosing MG5 syntax, but also that went wrong, see
>http://<email address hidden>/PROC16/index.html

ok this was a stupid mistake on my side... so this is solve.

>- I would like to be able to upload an MG4 proc_card to MG5, and right
>now it's not clear how to do this. I think there should be two
>different upload fields, one for MG5 proc_cards, one for MG4
>proc_cards, and for the latter there should be a choice which
>generator should be used.

In fact you have all those possibilities... But ok this is not that clear...
In fact my way to do is that you have one upload field where you can choose to upload either a MG4 or MG5 proc_card. If you upload a MG4 proc_card then when usually you confirm that the upload is correct. You will see a new box authorizing you to choose MG4 or MG5 to run this card.

>Yesterday, I updated the newprocess_mg5 script so that the output of
>mg5 is piped to the proc_log.txt file. In the web version, it seems
>that only the stdout and not the logging output appears in the file.
>It would be very nice to have the full logging output in the file,
>since this is a good way to check exactly what is happening during the
>generation, and corresponds closer to the output of MG4.

As for MG4 the newprocess for mg5 are disconected from the MG_ME one, and it's slightly different from the standard one. I will take a look at your modification, to see if they are compatible.

>>- We need a link describing the MG5 syntax, and if you could provide a
>>warning message when MG5 is chosen (by Javascript) saying that for
>>decay chains, the coupling orders only apply to the core process, that
>>would be great!

The warning is interesting once but it will be fastly boring...
So I suggest that we put it for the moment, and then at point or another simply remove this warning.

For the link, we should use epidoc in order to help us I think ;-)

>>- What happened here:
>>http://<email address hidden>/PROC11/index.html
>>?
>>(I defined the process p p > t t~ QED=0, t > j j b, t~ > l- vl b~ in
>>the proc line, and chose MG4 syntax).
>>It looks like the generation just died once the SM was loaded, and
>>there's error message.

This is quite strange... I'll take a look but I simply don't understand what happen...

Revision history for this message
Johan Alwall (johan-alwall) wrote :

Hi Olivier,

> In fact you have all those possibilities... But ok this is not that clear...
> In fact my way to do is that you have one upload field where you can choose to upload either a MG4 or MG5 proc_card. If you upload a MG4 proc_card then when usually you confirm that the upload is correct. You will see a new box authorizing you to choose MG4 or MG5 to run this card.

Ah, I was hoping this was the case, but it was not clear. Just add a
line saying "Choose MG version to use for this MG4 card:" or something
like that. I tried it, and the upload worked, but once again not the
generation:
http://<email address hidden>/PROC21/index.html

I should add that I have done a number of generations that work
perfectly (using only MG4 syntax in the process definition test
field), e.g.
http://<email address hidden>/PROC20/index.html
So most of the time your page is working fine!

> As for MG4 the newprocess for mg5 are disconected from the MG_ME one, and it's slightly different from the standard one. I will take a look at your modification, to see if they are compatible.

It's just a matter of adding "2>&1" after ">> proc_log.txt".

>>>- We need a link describing the MG5 syntax, and if you could provide a
>>>warning message when MG5 is chosen (by Javascript) saying that for
>>>decay chains, the coupling orders only apply to the core process, that
>>>would be great!
>
> The warning is interesting once but it will be fastly boring...
> So I suggest that we put it for the moment, and then at point or another simply remove this warning.

Ok it's not really necessary, I think it's enough that it is described
in the link.

> For the link, we should use epidoc in order to help us I think ;-)

I didn't mean a link to the complete MG5 manual, just a short note
about process generation syntax and some examples, max. 10 lines.

>>>- What happened here:
>>>http://<email address hidden>/PROC11/index.html
>>>?
>
> This is quite strange... I'll take a look but I simply don't understand what happen...

Ok thanks!

Revision history for this message
Olivier Mattelaer (olivier-mattelaer) wrote :

Hi Johan,

>>It's just a matter of adding "2>&1" after ">> proc_log.txt".
Done

>>>- What happened here:
>>>http://<email address hidden>/PROC11/index.html
>>>?
>
> This is quite strange... I'll take a look but I simply don't understand what happen...

Not sure what the problem was, but it's work on my computer (selecting mg5 and mg4 syntax)
http://<email address hidden>/PROC2/index.html
http://<email address hidden>/PROC6/index.html

But please retry on your side.

>>Ah, I was hoping this was the case, but it was not clear. Just add a
>>line saying "Choose MG version to use for this MG4 card:" or something
>>like that.

Sure (done)

Revision history for this message
Johan Alwall (johan-alwall) wrote :

Hi Olivier,

>>>It's just a matter of adding "2>&1" after ">> proc_log.txt".
> Done

Great, thanks!

> Not sure what the problem was, but it's work on my computer (selecting mg5 and mg4 syntax)
> http://<email address hidden>/PROC2/index.html
> http://<email address hidden>/PROC6/index.html

Ok now it works on my side too, great!

I get a problem when I'm uploading a proc_card though (probably it's
not the upload but the process, please take a look):
http://<email address hidden>/PROC24/index.html
I think the problem might be that you expect a comment after the
coupling definition.

One presentation detail: You are now extracting also the comma (",")
when you extract the coupling, which makes the process definition look
funny:

Process: p p > t t~ t > j j b, t~ > l- vl~ b~
 QED=0,

I noticed in the proc_card_mg5.dat that the model import comes twice,
once before the import proc_v4 line and once after. Is this on purpose
or a "bug"?

Thanks, all the best,
Johan

lp:~madteam/mg5amcnlo/MG5_on_web updated
141. By Olivier Mattelaer

Correct the bug (and test) find by johan

Revision history for this message
Olivier Mattelaer (olivier-mattelaer) wrote :

> I get a problem when I'm uploading a proc_card though (probably it's
> not the upload but the process, please take a look):
> http://<email address hidden>/PROC24/index.html
> I think the problem might be that you expect a comment after the
> coupling definition.
>

In fact that's the pure comment line which was not treated correctly by the regexp.
Solve (and add a test for this)

> One presentation detail: You are now extracting also the comma (",")
> when you extract the coupling, which makes the process definition look
> funny:
>
> Process: p p > t t~ t > j j b, t~ > l- vl~ b~
> QED=0,

Corrected

> I noticed in the proc_card_mg5.dat that the model import comes twice,
> once before the import proc_v4 line and once after. Is this on purpose
> or a "bug"?

I put it for debugging purpose, I think I can remove it now.

>
> Thanks, all the best,
> Johan

Thanks

Olivier

Revision history for this message
Johan Alwall (johan-alwall) wrote :

Hi again Olivier,

Great, all my previous points are now very nicely taken care of. Thanks!

I submitted a proc_card with a mistake - I hadn't defined the
multiparticle label "j". In this case, the error treatment doesn't
work very well for the web generation (see
http://<email address hidden>/PROC26/proc_log.txt).
It says
ERROR:root:Invalid characters: j j
ERROR:root:Invalid characters: j j
but doesn't stop the generation as in the regular (non-web)
generation. I think it's better to do as in the command-line case, to
stop generation with a warning message if some particles are not
available, since this indicates that the result will not be what the
user expected, and it would save time for the user to just exit the
generation gracefully with a reasonable error message.

After this detail I think we're good to go public! :-D
(Of course I haven't looked at the security aspect, I'm no expert
there. I will take a look at the code before I approve though.)

Thanks,
Johan

lp:~madteam/mg5amcnlo/MG5_on_web updated
142. By Olivier Mattelaer

more explicit error message
more smart check for options validity
raise an error if the particles are not recognized in v4 conversion

143. By Olivier Mattelaer

catch the error if a particle is not define in the MG4 conversion

Revision history for this message
Olivier Mattelaer (olivier-mattelaer) wrote :

Hi Johan,

In fact you have basically the same problem on shell mode.
indeed if you run
generate J J > J J
it will stop with a beautiful error message
but if you run
import command file
with the same process, then it's impossible to know if generate J J > J J stops normally or not.
So this problem is not related with the web interface at all. And the only correct way to solve this is to raise error that we can catch at the level of the cmd. In order to stop ALL executed command.
This could be done for version 0.5.0 if you want.

In fact the special case of this problem is slightly more easy, since the first error appears before the call to generate (in the conversion of the MG4 proc_card). In consequence it's possible to always raise an error and catch it inside the import. In order to stop it correctly. So this specific case is solved. But we should think about this for next version. I think

Revision history for this message
Johan Alwall (johan-alwall) wrote :

Hi Olivier,

I have now gone through the code, and it looks really nice, great
refactorng. Just a few comments:

HelpToCmd:
- "HelpToCmd" sounds funny, I think "HelpForCmd" is better English
- Can you add all options to the help printouts? help_makehtml
doesn't mention the --nojpg option

CheckValidForCmd:
- It would be good I think if we have lists for all commands that have
options, and always check against the list. That way there's
one less thing to remember if we add new options to a command.
Ex: check_add, where the 'process' option check is now hard-coded,
check_import, check_load etc. These should be defined in a separate
class CmdOptions I guess (which is of course also used in complete -
or just define them in the CompleteForCmd class).
- For check_add, if the option is not 'process', it should print the
help message, not "Empty or wrong format process...".

CmdFile:
- Is this just a temporary debug solution? Either remove or change doc
line.

MadGraphCmd: - do_history: Add version info as well in the header,
for completeness (and possible future debugging).

Thanks a lot!
Johan

lp:~madteam/mg5amcnlo/MG5_on_web updated
144. By Olivier Mattelaer

wrong help message

Revision history for this message
Johan Alwall (johan-alwall) wrote :

Hi Olivier,

Could you please address my comments from 2010-05-19 (either by answering them or by fixing them)?
Did anybody approve the branch before you merged it?

Thanks,
Johan

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file '.pydevproject'
2--- .pydevproject 2010-04-30 21:38:06 +0000
3+++ .pydevproject 2010-05-19 07:36:39 +0000
4@@ -5,6 +5,6 @@
5 <pydev_property name="org.python.pydev.PYTHON_PROJECT_VERSION">python 2.6</pydev_property>
6 <pydev_property name="org.python.pydev.PYTHON_PROJECT_INTERPRETER">Default</pydev_property>
7 <pydev_pathproperty name="org.python.pydev.PROJECT_SOURCE_PATH">
8-<path>/history_and_v4_proc_card</path>
9+<path>/MG5_on_web</path>
10 </pydev_pathproperty>
11 </pydev_project>
12
13=== modified file 'bin/mg5'
14--- bin/mg5 2010-05-06 19:22:46 +0000
15+++ bin/mg5 2010-05-19 07:36:39 +0000
16@@ -37,6 +37,8 @@
17 help="logging level (DEBUG|INFO|WARNING|ERROR|CRITICAL) [%default]")
18 parser.add_option("-f", "--file", default='',
19 help="use script file FILE")
20+parser.add_option("","--web", action="store_true", default=False, dest='web', \
21+ help='force to be in secure mode')
22
23 (options, args) = parser.parse_args()
24 if len(args) == 0:
25@@ -54,12 +56,19 @@
26 input_file = args[0]
27 else:
28 input_file = options.file
29-
30 input_file = cmd_interface.CmdFile(input_file,'rU')
31- cmd_line = cmd_interface.MadGraphCmd(stdin=input_file)
32- cmd_line.use_rawinput = False #put it in non interactive mode
33- cmd_line.cmdloop()
34+ if options.web:
35+ cmd_line = cmd_interface.MadGraphCmdWeb(stdin=input_file)
36+ cmd_line.use_rawinput = False #put it in non interactive mode
37+ cmd_line.cmdloop()
38+ else:
39+ cmd_line = cmd_interface.MadGraphCmdShell(stdin=input_file)
40+ cmd_line.use_rawinput = False #put it in non interactive mode
41+ cmd_line.cmdloop()
42 else:
43 # Interactive mode
44- cmd_interface.MadGraphCmd().cmdloop()
45+ if options.web:
46+ cmd_interface.MadGraphCmdWeb().cmdloop()
47+ else:
48+ cmd_interface.MadGraphCmdShell().cmdloop()
49
50
51=== added file 'madgraph/interface/cmd_interface.py'
52--- madgraph/interface/cmd_interface.py 1970-01-01 00:00:00 +0000
53+++ madgraph/interface/cmd_interface.py 2010-05-19 07:36:39 +0000
54@@ -0,0 +1,1866 @@
55+################################################################################
56+#
57+# Copyright (c) 2009 The MadGraph Development team and Contributors
58+#
59+# This file is a part of the MadGraph 5 project, an application which
60+# automatically generates Feynman diagrams and matrix elements for arbitrary
61+# high-energy processes in the Standard Model and beyond.
62+#
63+# It is subject to the MadGraph license which should accompany this
64+# distribution.
65+#
66+# For more information, please visit: http://madgraph.phys.ucl.ac.be
67+#
68+################################################################################
69+"""A user friendly command line interface to access MadGraph features.
70+ Uses the cmd package for command interpretation and tab completion.
71+"""
72+
73+import atexit
74+import cmd
75+import logging
76+import optparse
77+import os
78+import re
79+import readline
80+import subprocess
81+import sys
82+import time
83+
84+import madgraph.iolibs.misc as misc
85+import madgraph.iolibs.files as files
86+
87+import madgraph.iolibs.import_v4 as import_v4
88+#import madgraph.iolibs.save_model as save_model
89+import madgraph.iolibs.save_load_object as save_load_object
90+import madgraph.iolibs.export_v4 as export_v4
91+
92+import madgraph.core.base_objects as base_objects
93+import madgraph.core.diagram_generation as diagram_generation
94+
95+import madgraph.core.helas_objects as helas_objects
96+import madgraph.iolibs.drawing as draw_lib
97+import madgraph.iolibs.drawing_eps as draw
98+
99+#position of MG5
100+root_path = os.path.split(os.path.dirname(os.path.realpath(__file__)))[0]
101+root_path = os.path.split(root_path)[0]
102+
103+#position of MG_ME
104+MGME_dir = None
105+MGME_dir_possibility = [os.path.join(root_path, os.path.pardir),
106+ os.path.join(os.getcwd(), os.path.pardir),
107+ os.getcwd()]
108+
109+for position in MGME_dir_possibility:
110+ if os.path.exists(os.path.join(position, 'MGMEVersion.txt')) and \
111+ os.path.exists(os.path.join(position, 'UpdateNotes.txt')):
112+ MGME_dir = os.path.realpath(position)
113+ break
114+del MGME_dir_possibility
115+#===============================================================================
116+# CmdExtended
117+#===============================================================================
118+class CmdExtended(cmd.Cmd):
119+ """Extension of the cmd.Cmd command line.
120+ This extensions supports linesbreak, history
121+ support commentary
122+ """
123+
124+ class MadGraphCmdError(Exception):
125+ """Exception raised if an error occurs in the execution
126+ of command."""
127+ pass
128+
129+ def __init__(self, *arg, **opt):
130+ """add possibility of line break/history """
131+
132+ self.history = []
133+ self.save_line = ''
134+ cmd.Cmd.__init__(self, *arg, **opt)
135+
136+ def precmd(self, line):
137+ """ force the printing of the line if this is executed with an stdin """
138+ # Update the history of this suite of command
139+ self.history.append(line)
140+
141+ # Print the calling line in the non interactive mode
142+ if not self.use_rawinput:
143+ print line
144+
145+ #Check if they are a save line:
146+ if self.save_line:
147+ line = self.save_line + line
148+ self.save_line = ''
149+
150+ #Check that the line is complete
151+ if line.endswith('\\'):
152+ self.save_line = line[:-1]
153+ return '' # do nothing
154+
155+ #remove comment
156+ if '#' in line:
157+ line = line.split('#')[0]
158+
159+ # execute the line command
160+ return line
161+
162+ def exec_cmd(self, line):
163+ """for third party call, call the line with pre and postfix treatment"""
164+
165+ print line
166+ line = self.precmd(line)
167+ stop = self.onecmd(line)
168+ stop = self.postcmd(stop, line)
169+ return stop
170+
171+ def emptyline(self):
172+ """If empty line, do nothing. Default is repeat previous command."""
173+ pass
174+
175+ def default(self, line):
176+ """Default action if line is not recognized"""
177+
178+ # Faulty command
179+ print "Command \"%s\" not recognized, please try again" % \
180+ line.split()[0]
181+ # Quit
182+ def do_quit(self, line):
183+ sys.exit(1)
184+
185+ # Aliases
186+ do_EOF = do_quit
187+
188+
189+#===============================================================================
190+# Helper function
191+#=============================================================================
192+def split_arg(line):
193+ """Split a line of arguments"""
194+ return line.split()
195+
196+
197+#===============================================================================
198+# HelpToCmd
199+#===============================================================================
200+class HelpToCmd(object):
201+ """ The Series of help routine for the MadGraphCmd"""
202+
203+ def help_save(self):
204+ print "syntax: save %s FILENAME" % "|".join(self._save_opts)
205+ print "-- save information as file FILENAME"
206+
207+
208+ def help_load(self):
209+ print "syntax: load %s FILENAME" % "|".join(self._save_opts)
210+ print "-- load information from file FILENAME"
211+
212+ def help_import(self):
213+
214+ print "syntax: import " + "|".join(self._import_formats) + \
215+ " FILENAME"
216+ print "-- imports file(s) in various formats"
217+ print
218+ print " import model_v4 MODEL_info :"
219+ print " Import a MG4 Model in MG5 Model"""
220+ print " Model_info could be the name of the model"""
221+ print " or the path to MG4_Model directory"""
222+ print
223+ print " import proc_v4 [PATH] :"
224+ print " Execute MG5 based on a proc_card.dat in MG4 format."""
225+ print " Path to the proc_card is optional if you have setup a"
226+ print " madevent directory"
227+ print
228+ print " import command PATH :"
229+ print " Execute the list of command in the file at PATH"
230+
231+ def help_display(self):
232+ print "syntax: display " + "|".join(self._display_opts)
233+ print "-- display a the status of various internal state variables"
234+
235+ def help_setup(self):
236+ print "syntax madevent_v4 name|.|auto [options]"
237+ print "-- Create a copy of the V4 Template in the MG_ME directory."
238+ print " name will be the name of the copy the madevent Template that"
239+ print " will be use by default in following steps"
240+ print " If you put '.' instead of a name, the code will try to locate"
241+ print " a valid copy of the Template under focus"
242+ print " If you put 'auto' instead an automatic name will be created"
243+ print " options:"
244+ print " -f: force the cleaning of the directory if this one exist"
245+ print " -d PATH: specify the directory where to create name"
246+ print " -noclean: no cleaning perform in name"
247+ print " Example:"
248+ print " setup madevent_v4 MYRUN"
249+ print " setup madevent_v4 MYRUN -d ../MG_ME -f"
250+
251+ def help_generate(self):
252+
253+ print "syntax: generate INITIAL STATE > REQ S-CHANNEL > FINAL STATE $ EXCL S-CHANNEL / FORBIDDEN PARTICLES COUP1=ORDER1 COUP2=ORDER2"
254+ print "-- generate diagrams for a given process"
255+ print " Example: u d~ > w+ > m+ vm g $ a / z h QED=3 QCD=0 @1"
256+ print "Decay chain syntax:"
257+ print " core process, decay1, (decay2, (decay3, ...)), ... etc"
258+ print " Example: g g > t~ t @2, (t~ > W- b~, W- > e- ve~), t > W+ b"
259+ print " Note that identical particles will all be decayed"
260+
261+ def help_add(self):
262+
263+ print "syntax: add process INITIAL STATE > REQ S-CHANNEL > FINAL STATE $ EXCL S-CHANNEL / FORBIDDEN PARTICLES COUP1=ORDER1 COUP2=ORDER2"
264+ print "-- generate diagrams for a process and add to existing processes"
265+ print " Syntax example: u d~ > w+ > m+ vm g $ a / z h QED=3 QCD=0 @1"
266+ print "Decay chain syntax:"
267+ print " core process, decay1, (decay2, (decay3, ...)), ... etc"
268+ print " Example: g g > t~ t @2, (t~ > W- b~, W- > e- ve~), t > W+ b"
269+ print " Note that identical particles will all be decayed"
270+
271+ def help_define(self):
272+ print "syntax: define multipart_name [ part_name_list ]"
273+ print "-- define a multiparticle"
274+ print " Example: define p u u~ c c~ d d~ s s~"
275+
276+ def help_export(self):
277+ print "syntax: export " + "|".join(self._export_formats) + \
278+ " FILEPATH"
279+ print """-- export matrix elements. For standalone_v4, the resulting
280+ files will be FILEPATH/matrix_\"process_string\".f. For sa_dirs_v4,
281+ the result is a set of complete MG4 Standalone process directories.
282+ For madevent_v4, the path needs to be to a MadEvent SubProcesses
283+ directory, and the result is the Pxxx directories (including the
284+ diagram .ps and .jpg files) for the subprocesses as well as a
285+ correctly generated subproc.mg file. Note that if you have run the
286+ 'setup', FILEPATH is optional."""
287+
288+ def help_history(self):
289+ print "syntax: history [FILEPATH] [-clean] "
290+ print "-- write in the specified files all the call to MG5 that you have"""
291+ print " perform since that you have open this command line applet."""
292+ print " -clean option will remove all the entry of the history"""
293+
294+ def help_makehtml(self):
295+ print "syntax: makehtlm madevent_v4 [PATH]"
296+ print "-- create the web page related to the directory PATH"
297+ print " by default PATH is the directory defined with the setup command"
298+
299+
300+ def help_draw(self):
301+ _draw_parser.print_help()
302+
303+ def help_shell(self):
304+ print "syntax: shell CMD (or ! CMD)"
305+ print "-- run the shell command CMD and catch output"
306+
307+ def help_quit(self):
308+ print "syntax: quit"
309+ print "-- terminates the application"
310+
311+ help_EOF = help_quit
312+
313+ def help_help(self):
314+ print "syntax: help"
315+ print "-- access to the in-line help"
316+
317+#===============================================================================
318+# CheckValidForCmd
319+#===============================================================================
320+class CheckValidForCmd(object):
321+ """ The Series of help routine for the MadGraphCmd"""
322+
323+ def check_add(self, args):
324+ """check the validity of line
325+ syntax: add process PROCESS
326+ """
327+
328+ if len(args) < 1:
329+ self.help_generate()
330+ return False
331+
332+ if len(self._curr_model['particles']) == 0:
333+ print "No particle list currently active, please create one first!"
334+ return False
335+
336+ if len(self._curr_model['interactions']) == 0:
337+ print "No interaction list currently active," + \
338+ " please create one first!"
339+ return False
340+
341+ if len(args) < 2:
342+ self.help_add()
343+ return False
344+
345+ if args[0] != 'process':
346+ print "Empty or wrong format process, please try again."
347+ return False
348+
349+ return True
350+
351+ def check_define(self, args):
352+ """check the validity of line
353+ syntax: define multipart_name [ part_name_list ]
354+ """
355+
356+ if len(args) < 1:
357+ self.help_define()
358+ return False
359+
360+ if len(self._curr_model['particles']) == 0:
361+ print "No particle list currently active, please create one first!"
362+ return False
363+
364+ return True
365+
366+ def check_display(self, args):
367+ """check the validity of line
368+ syntax: display XXXXX
369+ """
370+
371+ if len(args) != 1:
372+ self.help_display()
373+ return False
374+ else:
375+ return True
376+
377+ def check_draw(self, args):
378+ """check the validity of line
379+ syntax: draw FILEPATH [option=value]
380+ """
381+ if len(args) < 1:
382+ self.help_draw()
383+ return False
384+
385+ if not self._curr_amps:
386+ print "No process generated, please generate a process!"
387+ return False
388+
389+ if not os.path.isdir(args[0]):
390+ print "%s is not a valid directory for export file" % args[1]
391+ return False
392+
393+ return True
394+
395+ def check_export(self, args):
396+ """check the validity of line
397+ syntax: export MODE FILEPATH
398+ """
399+ if len(args) == 0 or (len(args) == 1 and not self._export_dir) or \
400+ args[0] not in self._export_formats:
401+ self.help_export()
402+ return False
403+
404+ if not self._curr_amps:
405+ print "No process generated, please generate a process!"
406+ return False
407+
408+ if len(args) == 1:
409+ path = os.path.join(self._export_dir, 'SubProcesses')
410+ else:
411+ path = args[1]
412+
413+ if not os.path.isdir(path):
414+ print "%s is not a valid directory for export file" % path
415+ if args[0] == 'madevent_v4':
416+ print "to create a valid output directory you can use the command"
417+ print "$> setup madevent_v4 auto"
418+ print " and then run export as follow:"
419+ print "$> export madevent_v4"
420+ return False
421+
422+ if args[0] == 'madevent_v4' and not os.path.isdir(
423+ os.path.join(path,'..','SubProcesses')):
424+ print "%s is not a valid directory for export file" % path
425+ print "to create a valid output directory you can use the command"
426+ print "$> setup madevent_v4 auto"
427+ print " and then run export as follow:"
428+ print "$> export madevent_v4"
429+ return False
430+
431+ return path
432+
433+ def check_generate(self, line):
434+ """check the validity of line"""
435+
436+ if len(line) < 1:
437+ self.help_generate()
438+ return False
439+
440+ if len(self._curr_model['particles']) == 0:
441+ print "No particle list currently active, please create one first!"
442+ return False
443+
444+ if len(self._curr_model['interactions']) == 0:
445+ print "No interaction list currently active," + \
446+ " please create one first!"
447+ return False
448+
449+ return True
450+
451+ def check_history(self, args):
452+ """check the validity of line"""
453+
454+ if len(args) > 1:
455+ self.help_history()
456+ return False
457+
458+ if len(args):
459+ if args[0] not in ['clean', '.']:
460+ dirpath = os.path.dirname(args[0])
461+ if dirpath and not os.path.exists(dirpath):
462+ print "invalid path"
463+ return False
464+ elif args[0] == '.' and not self._export_dir:
465+ print 'no export dir configure'
466+ return False
467+ return True
468+
469+ def check_import(self, args):
470+ """check the validity of line"""
471+
472+ if not args or args[0] not in self._import_formats:
473+ self.help_import()
474+ return False
475+
476+ if args[0] != 'proc_v4' and len(args) != 2:
477+ self.help_import()
478+ return False
479+
480+ if args[0] == 'proc_v4' and len(args)!=2 and not self._export_dir:
481+ self.help_import()
482+ return False
483+
484+ return True
485+
486+ def check_load(self, args):
487+ """ check the validity of the line"""
488+
489+ if len(args) != 2:
490+ self.help_load()
491+ return False
492+ return True
493+
494+ def check_makehtml(self, args):
495+ """check the validity of the line"""
496+
497+ if len(args) < 1:
498+ self.help_makehtml()
499+ return False
500+
501+ if args[0] != 'madevent_v4':
502+ self.help_makehtml()
503+ return False
504+
505+ if (len(args) == 1 and not self._export_dir) or \
506+ (len(args) > 1 and not os.path.isdir(args[1])):
507+ self.help_makehtml()
508+ return False
509+ return True
510+
511+ def check_save(self, args):
512+ """ check the validity of the line"""
513+ if len(args) != 2:
514+ self.help_save()
515+ return False
516+ return True
517+
518+ def check_setup(self, args):
519+ """ check the validity of the line"""
520+
521+ if len(args) < 2:
522+ self.help_setup()
523+ return False
524+
525+ if not self._model_dir:
526+ print 'No model found. Please import a model first and then retry'
527+ print ' for example do : import model_v4 sm'
528+ return False
529+ return True
530+
531+#===============================================================================
532+# CheckValidForCmdWeb
533+#===============================================================================
534+class CheckValidForCmdWeb(CheckValidForCmd):
535+ """ Check the validity of input line for web entry
536+ (no explicit path authorized)"""
537+
538+ def check_draw(self, args):
539+ """check the validity of line
540+ syntax: draw FILEPATH [option=value]
541+ """
542+ # return False since they are always a path
543+ return False
544+
545+ def check_export(self, args):
546+ """check the validity of line
547+ syntax: export MODE FILEPATH
548+ No FilePath authorized on the web
549+ """
550+ if len(args) > 1:
551+ return False
552+
553+ return CheckValidForCmd.check_export(self, args)
554+
555+ def check_history(self, args):
556+ """check the validity of line
557+ No Path authorize for the Web"""
558+
559+ if len(args) == 2 and args[1] not in ['.','clean']:
560+ return False
561+
562+ return CheckValidForCmd.check_history(self, args)
563+
564+ def check_import(self, args):
565+ """check the validity of line
566+ No Path authorize for the Web"""
567+
568+ if len(args) >= 2 and args[0] == 'proc_v4' and args[1] != '.':
569+ return False
570+
571+ if len(args) >= 1 and args[0] == 'command':
572+ return False
573+
574+ for arg in args:
575+ if '/' in arg:
576+ print 'Path are not authorized on the web'
577+ return False
578+
579+ return CheckValidForCmd.check_import(self, args)
580+
581+ def check_makehtml(self, args):
582+ """check the validity of the line
583+ No Path authorize for the Web"""
584+
585+ if len(args) > 1:
586+ return False
587+
588+ return CheckValidForCmd.check_makehtml(self, args)
589+
590+ def check_load(self, args):
591+ """ check the validity of the line
592+ No Path authorize for the Web"""
593+
594+ if len(args)==2:
595+ if args[0] != 'model':
596+ print 'only model can be load online'
597+ return False
598+ if 'model.pkl' not in args[1]:
599+ print 'not valid format'
600+ return False
601+ if not os.path.realpath(args[1]).startswith(os.path.join(MGME_dir, \
602+ 'Models')):
603+ return False
604+
605+
606+ def check_save(self, args):
607+ """ not authorize on web"""
608+ return False
609+
610+
611+ def check_setup(self, args):
612+ """ check the validity of the line"""
613+
614+ if not CheckValidForCmd.check_setup(self, args):
615+ return False
616+
617+ if '/' in args[2]:
618+ return False
619+
620+ return True
621+
622+#===============================================================================
623+# CompleteForCmd
624+#===============================================================================
625+class CompleteForCmd(CheckValidForCmd):
626+ """ The Series of help routine for the MadGraphCmd"""
627+
628+ def list_completion(self, text, list):
629+ """Propose completions of text in list"""
630+ if not text:
631+ completions = list
632+ else:
633+ completions = [ f
634+ for f in list
635+ if f.startswith(text)
636+ ]
637+ return completions
638+
639+ def path_completion(self, text, base_dir=None):
640+ """Propose completions of text to compose a valid path"""
641+
642+ if base_dir is None:
643+ base_dir = os.getcwd()
644+
645+ completion = [f
646+ for f in os.listdir(base_dir)
647+ if f.startswith(text) and \
648+ os.path.isfile(os.path.join(base_dir, f))
649+ ]
650+
651+ completion = completion + \
652+ [f + '/'
653+ for f in os.listdir(base_dir)
654+ if f.startswith(text) and \
655+ os.path.isdir(os.path.join(base_dir, f))
656+ ]
657+
658+ return completion
659+
660+
661+ def complete_makehtml(self, text, line, begidx, endidx):
662+ """ format: makehtlm madevent_v4 [PATH] [--nojpeg]"""
663+
664+ # Format
665+ if len(split_arg(line[0:begidx])) == 1:
666+ return self.list_completion(text, ['madevent_v4'])
667+
668+ if text.startswith('-'):
669+ return self.list_completion(text, ['--nojpeg'])
670+
671+ # Filename if directory is not given
672+ if len(split_arg(line[0:begidx])) == 2:
673+ return self.path_completion(text)
674+
675+ # Filename if directory is given
676+ if len(split_arg(line[0:begidx])) == 3:
677+ return self.path_completion(text,
678+ base_dir=\
679+ split_arg(line[0:begidx])[2])
680+
681+ def complete_export(self, text, line, begidx, endidx):
682+ "Complete the export command"
683+
684+ # Format
685+ if len(split_arg(line[0:begidx])) == 1:
686+ return self.list_completion(text, self._export_formats)
687+
688+ # Filename if directory is not given
689+ if len(split_arg(line[0:begidx])) == 2:
690+ return self.path_completion(text)
691+
692+ # Filename if directory is given
693+ if len(split_arg(line[0:begidx])) == 3:
694+ return self.path_completion(text,
695+ base_dir=\
696+ split_arg(line[0:begidx])[2])
697+
698+ def complete_history(self, text, line, begidx, endidx):
699+ "Complete the add command"
700+
701+ # Format
702+ if len(split_arg(line[0:begidx])) == 1:
703+ return self.path_completion(text)
704+
705+ def complete_add(self, text, line, begidx, endidx):
706+ "Complete the add command"
707+
708+ # Format
709+ if len(split_arg(line[0:begidx])) == 1:
710+ return self.list_completion(text, self._add_opts)
711+
712+ def complete_display(self, text, line, begidx, endidx):
713+ "Complete the display command"
714+
715+ # Format
716+ if len(split_arg(line[0:begidx])) == 1:
717+ return self.list_completion(text, self._display_opts)
718+
719+ def complete_draw(self, text, line, begidx, endidx):
720+ "Complete the import command"
721+
722+ # Format
723+ if len(split_arg(line[0:begidx])) == 1:
724+ return self.path_completion(text)
725+
726+
727+ #option
728+ if len(split_arg(line[0:begidx])) >= 2:
729+ opt = ['horizontal', 'external=', 'max_size=', 'add_gap=',
730+ 'non_propagating','--']
731+ return self.list_completion(text, opt)
732+
733+ def complete_load(self, text, line, begidx, endidx):
734+ "Complete the load command"
735+
736+ # Format
737+ if len(split_arg(line[0:begidx])) == 1:
738+ return self.list_completion(text, self._save_opts)
739+
740+ # Filename if directory is not given
741+ if len(split_arg(line[0:begidx])) == 2:
742+ return self.path_completion(text)
743+
744+ # Filename if directory is given
745+ if len(split_arg(line[0:begidx])) == 3:
746+ return self.path_completion(text,
747+ base_dir=\
748+ split_arg(line[0:begidx])[2])
749+
750+ def complete_save(self, text, line, begidx, endidx):
751+ "Complete the save command"
752+
753+ # Format
754+ if len(split_arg(line[0:begidx])) == 1:
755+ return self.list_completion(text, self._save_opts)
756+
757+ # Filename if directory is not given
758+ if len(split_arg(line[0:begidx])) == 2:
759+ return self.path_completion(text)
760+
761+ # Filename if directory is given
762+ if len(split_arg(line[0:begidx])) == 3:
763+ return self.path_completion(text,
764+ base_dir=\
765+ split_arg(line[0:begidx])[2])
766+
767+ def complete_setup(self, text, line, begidx, endidx):
768+ "Complete the setup command"
769+
770+ possible_option = ['-d ', '-f', '-noclean']
771+ possible_option2 = ['d ', 'f', 'noclean']
772+ possible_format = ['madevent_v4']
773+ #don't propose directory use by MG_ME
774+ forbidden_name = ['MadGraphII', 'Template', 'pythia-pgs', 'CVS',
775+ 'Calculators', 'MadAnalysis', 'SimpleAnalysis',
776+ 'mg5', 'DECAY', 'EventConverter', 'Models',
777+ 'ExRootAnalysis', 'HELAS', 'Transfer_Fct']
778+ # Format
779+ if len(split_arg(line[0:begidx])) == 1:
780+ return self.list_completion(text, possible_format)
781+
782+ #name of the run =>proposes old run name
783+ if len(split_arg(line[0:begidx])) == 2:
784+ content = [name for name in os.listdir(MGME_dir) if \
785+ name not in forbidden_name and \
786+ os.path.isdir(os.path.join(MGME_dir, name))]
787+ content += ['.', 'auto']
788+ return self.list_completion(text, content)
789+
790+ # Returning options
791+ if len(split_arg(line[0:begidx])) > 2:
792+ if split_arg(line[0:begidx])[-1] == '-d':
793+ return self.path_completion(text)
794+ elif split_arg(line[0:begidx])[-2] == '-d' and line[-1] != ' ':
795+ return self.path_completion(text, \
796+ split_arg(line[0:begidx])[-1])
797+ elif split_arg(line[0:begidx])[-1] == '-':
798+ return self.list_completion(text, possible_option2)
799+ else:
800+ return self.list_completion(text, possible_option)
801+
802+ def complete_shell(self, text, line, begidx, endidx):
803+ """ add path for shell """
804+
805+ # Filename if directory is given
806+ #
807+ if len(split_arg(line[0:begidx])) > 1 and line[begidx-1] == os.path.sep:
808+ if not text:
809+ text = ''
810+ output = self.path_completion(text,
811+ base_dir=\
812+ split_arg(line[0:begidx])[-1])
813+ else:
814+ output = self.path_completion(text)
815+ return output
816+
817+ def complete_import(self, text, line, begidx, endidx):
818+ "Complete the import command"
819+
820+ # Format
821+ if len(split_arg(line[0:begidx])) == 1:
822+ return self.list_completion(text, self._import_formats)
823+
824+ # Filename if directory is not given
825+ if len(split_arg(line[0:begidx])) == 2:
826+ return self.path_completion(text)
827+
828+ # Filename if directory is given
829+ if len(split_arg(line[0:begidx])) == 3:
830+ return self.path_completion(text,
831+ base_dir=\
832+ split_arg(line[0:begidx])[2])
833+
834+
835+
836+
837+
838+#===============================================================================
839+# MadGraphCmd
840+#===============================================================================
841+class MadGraphCmd(CmdExtended, HelpToCmd):
842+ """The command line processor of MadGraph"""
843+
844+ _curr_model = base_objects.Model()
845+ _model_dir = None
846+ _curr_amps = diagram_generation.AmplitudeList()
847+ _curr_matrix_elements = helas_objects.HelasMultiProcess()
848+ _curr_fortran_model = export_v4.HelasFortranModel()
849+ _multiparticles = {}
850+
851+ _display_opts = ['particles', 'interactions', 'processes', 'multiparticles']
852+ _add_opts = ['process']
853+ _save_opts = ['model', 'processes']
854+ _import_formats = ['model_v4', 'proc_v4', 'command']
855+ _export_formats = ['standalone_v4', 'sa_dirs_v4', 'madevent_v4']
856+
857+ def __init__(self, *arg, **opt):
858+ """ add a tracker of the history """
859+
860+ CmdExtended.__init__(self, *arg, **opt)
861+ self._generate_info = "" # store the first generated process
862+
863+ # Detect If this script is launched from a valid copy of the Template
864+ #and if so store this position as standard output directory
865+ if 'Cards' in os.listdir('.'):
866+ #Check for ./
867+ self._export_dir = os.path.realpath('.')
868+ elif 'Cards' in os.listdir('..'):
869+ #Check for ../
870+ self._export_dir = os.path.realpath('..')
871+ elif self.stdin != sys.stdin:
872+ #Check for position defined by the input files
873+ input_path = os.path.realpath(self.stdin.name).split(os.path.sep)
874+ if input_path[-2] == 'Cards':
875+ self._export_dir = os.path.sep.join(input_path[:-2])
876+ else:
877+ self._export_dir = None
878+ else:
879+ self._export_dir = None
880+
881+ # Add a process to the existing multiprocess definition
882+ # Generate a new amplitude
883+ def do_add(self, line):
884+ """Generate an amplitude for a given process and add to
885+ existing amplitudes
886+ syntax:
887+ """
888+
889+ args = split_arg(line)
890+ if not self.check_add(args):
891+ return
892+
893+ if args[0] == 'process':
894+ # Rejoin line
895+ line = ' '.join(args[1:])
896+
897+ # store the first process (for the perl script)
898+ if not self._generate_info:
899+ self._generate_info = line
900+
901+ # Reset Helas matrix elements
902+ self._curr_matrix_elements = helas_objects.HelasMultiProcess()
903+
904+ try:
905+ if line.find(',') == -1:
906+ myprocdef = self.extract_process(line)
907+ else:
908+ myprocdef, line = self.extract_decay_chain_process(line)
909+ except self.MadGraphCmdError, error:
910+ print "Empty or wrong format process, please try again. Error:"
911+ print error
912+ myprocdef = None
913+
914+ if myprocdef:
915+
916+ cpu_time1 = time.time()
917+
918+ myproc = diagram_generation.MultiProcess(myprocdef)
919+
920+ for amp in myproc.get('amplitudes'):
921+ if amp not in self._curr_amps:
922+ self._curr_amps.append(amp)
923+ else:
924+ print "Warning: Already in processes:"
925+ print amp.nice_string_processes()
926+
927+ cpu_time2 = time.time()
928+
929+ nprocs = len(myproc.get('amplitudes'))
930+ ndiags = sum([amp.get_number_of_diagrams() for \
931+ amp in myproc.get('amplitudes')])
932+ print "%i processes with %i diagrams generated in %0.3f s" % \
933+ (nprocs, ndiags, (cpu_time2 - cpu_time1))
934+ ndiags = sum([amp.get_number_of_diagrams() for \
935+ amp in self._curr_amps])
936+ print "Total: %i processes with %i diagrams" % \
937+ (len(self._curr_amps), ndiags)
938+
939+ # Define a multiparticle label
940+ def do_define(self, line):
941+ """Define a multiparticle"""
942+
943+ # Particle names always lowercase
944+ line = line.lower()
945+ args = split_arg(line)
946+ if not self.check_define(args):
947+ return
948+
949+
950+ label = args[0]
951+ pdg_list = []
952+
953+ for part_name in args[1:]:
954+
955+ mypart = self._curr_model['particles'].find_name(part_name)
956+
957+ if mypart:
958+ pdg_list.append(mypart.get_pdg_code())
959+ else:
960+ print "No particle %s in model: skipped" % part_name
961+
962+ if not pdg_list:
963+ print """Empty or wrong format for multiparticle.
964+ Please try again."""
965+
966+ self._multiparticles[label] = pdg_list
967+
968+ # Display
969+ def do_display(self, line):
970+ """Display current internal status"""
971+
972+ args = split_arg(line)
973+ if not self.check_display(args):
974+ return
975+
976+ if args[0] == 'particles':
977+ print "Current model contains %i particles:" % \
978+ len(self._curr_model['particles'])
979+ part_antipart = [part for part in self._curr_model['particles'] \
980+ if not part['self_antipart']]
981+ part_self = [part for part in self._curr_model['particles'] \
982+ if part['self_antipart']]
983+ for part in part_antipart:
984+ print part['name'] + '/' + part['antiname'],
985+ print ''
986+ for part in part_self:
987+ print part['name'],
988+ print ''
989+
990+ if args[0] == 'interactions':
991+ print "Current model contains %i interactions" % \
992+ len(self._curr_model['interactions'])
993+ for inter in self._curr_model['interactions']:
994+ print str(inter['id']) + ':',
995+ for part in inter['particles']:
996+ if part['is_part']:
997+ print part['name'],
998+ else:
999+ print part['antiname'],
1000+ print
1001+
1002+ if args[0] == 'processes':
1003+ for amp in self._curr_amps:
1004+ print amp.nice_string()
1005+ if args[0] == 'multiparticles':
1006+ print 'Multiparticle labels:'
1007+ for key in self._multiparticles:
1008+ print key, " = ", self._multiparticles[key]
1009+
1010+ def do_draw(self, line):
1011+ """ draw the Feynman diagram for the given process """
1012+
1013+ args = split_arg(line)
1014+ if not self.check_draw(args):
1015+ return
1016+
1017+
1018+ (options, args) = _draw_parser.parse_args(args)
1019+ options = draw_lib.DrawOption(options)
1020+ start = time.time()
1021+
1022+
1023+ # Collect amplitudes
1024+ amplitudes = diagram_generation.AmplitudeList()
1025+
1026+ for amp in self._curr_amps:
1027+ amplitudes.extend(amp.get_amplitudes())
1028+
1029+ for amp in amplitudes:
1030+ filename = os.path.join(args[0], 'diagrams_' + \
1031+ amp.get('process').shell_string() + ".eps")
1032+ plot = draw.MultiEpsDiagramDrawer(amp['diagrams'],
1033+ filename,
1034+ model=self._curr_model,
1035+ amplitude='')
1036+
1037+ logging.info("Drawing " + \
1038+ amp.get('process').nice_string())
1039+ #plot.draw(opt=options)
1040+ plot.draw()
1041+ print "Wrote file " + filename
1042+
1043+ stop = time.time()
1044+ print 'time to draw', stop - start
1045+
1046+ # Export a matrix element
1047+ def do_export(self, line):
1048+ """Export a generated amplitude to file"""
1049+
1050+ def generate_matrix_elements(self):
1051+ """Helper function to generate the matrix elements before
1052+ exporting"""
1053+
1054+ cpu_time1 = time.time()
1055+ if not self._curr_matrix_elements.get('matrix_elements'):
1056+ self._curr_matrix_elements = \
1057+ helas_objects.HelasMultiProcess(\
1058+ self._curr_amps)
1059+ cpu_time2 = time.time()
1060+
1061+ ndiags = sum([len(me.get('diagrams')) for \
1062+ me in self._curr_matrix_elements.\
1063+ get('matrix_elements')])
1064+
1065+ return ndiags, cpu_time2 - cpu_time1
1066+
1067+ # Start of the actual routine
1068+
1069+ args = split_arg(line)
1070+ path = self.check_export(args) #if valid return the path of the output
1071+ if not path:
1072+ return
1073+
1074+ ndiags, cpu_time = generate_matrix_elements(self)
1075+ calls = 0
1076+
1077+ if args[0] == 'standalone_v4':
1078+ for me in self._curr_matrix_elements.get('matrix_elements'):
1079+ filename = os.path.join(path, 'matrix_' + \
1080+ me.get('processes')[0].shell_string() + ".f")
1081+ if os.path.isfile(filename):
1082+ print "Overwriting existing file %s" % filename
1083+ else:
1084+ print "Creating new file %s" % filename
1085+ calls = calls + files.write_to_file(filename,
1086+ export_v4.write_matrix_element_v4_standalone,
1087+ me, self._curr_fortran_model)
1088+
1089+
1090+ if args[0] == 'sa_dirs_v4':
1091+ for me in self._curr_matrix_elements.get('matrix_elements'):
1092+ calls = calls + \
1093+ export_v4.generate_subprocess_directory_v4_standalone(\
1094+ me, self._curr_fortran_model, path)
1095+
1096+ if args[0] == 'madevent_v4':
1097+ for me in self._curr_matrix_elements.get('matrix_elements'):
1098+ calls = calls + \
1099+ export_v4.generate_subprocess_directory_v4_madevent(\
1100+ me, self._curr_fortran_model, path)
1101+
1102+ card_path = os.path.join(path, os.path.pardir, 'SubProcesses', \
1103+ 'procdef_mg5.dat')
1104+ if self._generate_info:
1105+ export_v4.write_procdef_mg5(card_path,
1106+ os.path.split(self._model_dir)[-1],
1107+ self._generate_info)
1108+
1109+ print ("Generated helas calls for %d subprocesses " + \
1110+ "(%d diagrams) in %0.3f s") % \
1111+ (len(self._curr_matrix_elements.get('matrix_elements')),
1112+ ndiags, cpu_time)
1113+
1114+ print "Wrote %d helas calls" % calls
1115+
1116+ # Replace the amplitudes with the actual amplitudes from the
1117+ # matrix elements, which allows proper diagram drawing also of
1118+ # decay chain processes
1119+ self._curr_amps = diagram_generation.AmplitudeList(\
1120+ [me.get('base_amplitude') for me in \
1121+ self._curr_matrix_elements.get('matrix_elements')])
1122+
1123+
1124+ # Generate a new amplitude
1125+ def do_generate(self, line):
1126+ """Generate an amplitude for a given process"""
1127+
1128+ if not self.check_generate(line):
1129+ return
1130+
1131+ # Reset Helas matrix elements
1132+ self._curr_matrix_elements = helas_objects.HelasMultiProcess()
1133+ self._generate_info = line
1134+
1135+ try:
1136+ if ',' not in line:
1137+ myprocdef = self.extract_process(line)
1138+ else:
1139+ myprocdef, line = self.extract_decay_chain_process(line)
1140+ except self.MadGraphCmdError as error:
1141+ print "Empty or wrong format process, please try again. Error:\n" \
1142+ + str(error)
1143+ myprocdef = None
1144+
1145+ if myprocdef:
1146+
1147+ cpu_time1 = time.time()
1148+ myproc = diagram_generation.MultiProcess(myprocdef)
1149+ self._curr_amps = myproc.get('amplitudes')
1150+ cpu_time2 = time.time()
1151+
1152+ nprocs = len(self._curr_amps)
1153+ ndiags = sum([amp.get_number_of_diagrams() for \
1154+ amp in self._curr_amps])
1155+ print "%i processes with %i diagrams generated in %0.3f s" % \
1156+ (nprocs, ndiags, (cpu_time2 - cpu_time1))
1157+
1158+ else:
1159+ print "Empty or wrong format process, please try again."
1160+
1161+
1162+ def extract_process(self, line, proc_number = 0):
1163+ """Extract a process definition from a string. Returns
1164+ a ProcessDefinition."""
1165+
1166+ # Perform sanity modifications on the lines:
1167+ # Add a space before any > , $ /
1168+ space_before=re.compile(r"(?P<carac>\S)(?P<tag>[/\,\\$\\>])")
1169+ line = space_before.sub(r'\g<carac> \g<tag>',line)
1170+ # Add a space after any + - ~ > , $ /
1171+ space_after=re.compile(r"(?P<tag>[+-/\,\\$\\>~])(?P<carac>[^\s+-])")
1172+ line = space_after.sub(r'\g<tag> \g<carac>',line)
1173+
1174+
1175+ # Use regular expressions to extract s-channel propagators,
1176+ # forbidden s-channel propagators/particles, coupling orders
1177+ # and process number, starting from the back
1178+
1179+ # Start with process number (identified by "@")
1180+ proc_number_pattern = re.compile("^(.+)@\s*(\d+)\s*(.*)$")
1181+ proc_number_re = proc_number_pattern.match(line)
1182+ if proc_number_re:
1183+ proc_number = int(proc_number_re.group(2))
1184+ line = proc_number_re.group(1) + \
1185+ proc_number_re.group(3)
1186+
1187+ # Start with coupling orders (identified by "=")
1188+ order_pattern = re.compile("^(.+)\s+(\w+)\s*=\s*(\d+)\s*$")
1189+ order_re = order_pattern.match(line)
1190+ orders = {}
1191+ while order_re:
1192+ orders[order_re.group(2)] = int(order_re.group(3))
1193+ line = order_re.group(1)
1194+ order_re = order_pattern.match(line)
1195+
1196+ # Particle names always lowercase
1197+ line = line.lower()
1198+
1199+ # Now check for forbidden particles, specified using "/"
1200+ slash = line.find("/")
1201+ dollar = line.find("$")
1202+ forbidden_particles = ""
1203+ if slash > 0:
1204+ if dollar > slash:
1205+ forbidden_particles_re = re.match("^(.+)\s*/\s*(.+\s*)(\$.*)$", line)
1206+ else:
1207+ forbidden_particles_re = re.match("^(.+)\s*/\s*(.+\s*)$", line)
1208+ if forbidden_particles_re:
1209+ forbidden_particles = forbidden_particles_re.group(2)
1210+ line = forbidden_particles_re.group(1)
1211+ if len(forbidden_particles_re.groups()) > 2:
1212+ line = line + forbidden_particles_re.group(3)
1213+
1214+ # Now check for forbidden schannels, specified using "$"
1215+ forbidden_schannels_re = re.match("^(.+)\s*\$\s*(.+)\s*$", line)
1216+ forbidden_schannels = ""
1217+ if forbidden_schannels_re:
1218+ forbidden_schannels = forbidden_schannels_re.group(2)
1219+ line = forbidden_schannels_re.group(1)
1220+
1221+ # Now check for required schannels, specified using "> >"
1222+ required_schannels_re = re.match("^(.+?)>(.+?)>(.+)$", line)
1223+ required_schannels = ""
1224+ if required_schannels_re:
1225+ required_schannels = required_schannels_re.group(2)
1226+ line = required_schannels_re.group(1) + ">" + \
1227+ required_schannels_re.group(3)
1228+
1229+ args = split_arg(line)
1230+
1231+ myleglist = base_objects.MultiLegList()
1232+ state = False
1233+
1234+ # Extract process
1235+ for part_name in args:
1236+
1237+ if part_name == '>':
1238+ if not myleglist:
1239+ raise self.MadGraphCmdError, \
1240+ "No final state particles"
1241+ state = True
1242+ continue
1243+
1244+ mylegids = []
1245+ if part_name in self._multiparticles:
1246+ mylegids.extend(self._multiparticles[part_name])
1247+ else:
1248+ mypart = self._curr_model['particles'].find_name(part_name)
1249+ if mypart:
1250+ mylegids.append(mypart.get_pdg_code())
1251+
1252+ if mylegids:
1253+ myleglist.append(base_objects.MultiLeg({'ids':mylegids,
1254+ 'state':state}))
1255+ else:
1256+ raise self.MadGraphCmdError, \
1257+ "No particle %s in model" % part_name
1258+
1259+ if filter(lambda leg: leg.get('state') == True, myleglist):
1260+ # We have a valid process
1261+
1262+ # Now extract restrictions
1263+ forbidden_particle_ids = []
1264+ forbidden_schannel_ids = []
1265+ required_schannel_ids = []
1266+
1267+ #decay_process = len(filter(lambda leg: \
1268+ # leg.get('state') == False,
1269+ # myleglist)) == 1
1270+
1271+ if forbidden_particles:
1272+ args = split_arg(forbidden_particles)
1273+ for part_name in args:
1274+ if part_name in self._multiparticles:
1275+ forbidden_particle_ids.extend( \
1276+ self._multiparticles[part_name])
1277+ else:
1278+ mypart = self._curr_model['particles'].find_name( \
1279+ part_name)
1280+ if mypart:
1281+ forbidden_particle_ids.append(mypart.get_pdg_code())
1282+
1283+ if forbidden_schannels:
1284+ args = split_arg(forbidden_schannels)
1285+ for part_name in args:
1286+ if part_name in self._multiparticles:
1287+ forbidden_schannel_ids.extend(\
1288+ self._multiparticles[part_name])
1289+ else:
1290+ mypart = self._curr_model['particles'].find_name(\
1291+ part_name)
1292+ if mypart:
1293+ forbidden_schannel_ids.append(mypart.get_pdg_code())
1294+
1295+ if required_schannels:
1296+ args = split_arg(required_schannels)
1297+ for part_name in args:
1298+ if part_name in self._multiparticles:
1299+ required_schannel_ids.extend(\
1300+ self._multiparticles[part_name])
1301+ else:
1302+ mypart = self._curr_model['particles'].find_name(\
1303+ part_name)
1304+ if mypart:
1305+ required_schannel_ids.append(mypart.get_pdg_code())
1306+
1307+ return \
1308+ base_objects.ProcessDefinition({'legs': myleglist,
1309+ 'model': self._curr_model,
1310+ 'id': proc_number,
1311+ 'orders': orders,
1312+ 'forbidden_particles': forbidden_particle_ids,
1313+ 'forbidden_s_channels': forbidden_schannel_ids,
1314+ 'required_s_channels': required_schannel_ids
1315+ })
1316+ # 'is_decay_chain': decay_process\
1317+ else:
1318+ return None
1319+
1320+ def extract_decay_chain_process(self, line, level_down=False):
1321+ """Recursively extract a decay chain process definition from a
1322+ string. Returns a ProcessDefinition."""
1323+
1324+ # Start with process number (identified by "@")
1325+ proc_number_pattern = re.compile("^(.+)@\s*(\d+)\s*(.*)$")
1326+ proc_number_re = proc_number_pattern.match(line)
1327+ proc_number = 0
1328+ if proc_number_re:
1329+ proc_number = int(proc_number_re.group(2))
1330+ line = proc_number_re.group(1) + \
1331+ proc_number_re.group(3)
1332+ print line
1333+
1334+ index_comma = line.find(",")
1335+ index_par = line.find(")")
1336+ min_index = index_comma
1337+ if index_par > -1 and (index_par < min_index or min_index == -1):
1338+ min_index = index_par
1339+
1340+ if min_index > -1:
1341+ core_process = self.extract_process(line[:min_index], proc_number)
1342+ else:
1343+ core_process = self.extract_process(line, proc_number)
1344+
1345+ #level_down = False
1346+
1347+ while index_comma > -1:
1348+ line = line[index_comma + 1:]
1349+ index_par = line.find(')')
1350+ if line.lstrip()[0] == '(':
1351+ # Go down one level in process hierarchy
1352+ #level_down = True
1353+ line = line.lstrip()[1:]
1354+ # This is where recursion happens
1355+ decay_process, line = \
1356+ self.extract_decay_chain_process(line,
1357+ level_down=True)
1358+ index_comma = line.find(",")
1359+ index_par = line.find(')')
1360+ else:
1361+ index_comma = line.find(",")
1362+ min_index = index_comma
1363+ if index_par > -1 and \
1364+ (index_par < min_index or min_index == -1):
1365+ min_index = index_par
1366+ if min_index > -1:
1367+ decay_process = self.extract_process(line[:min_index])
1368+ else:
1369+ decay_process = self.extract_process(line)
1370+
1371+ core_process.get('decay_chains').append(decay_process)
1372+
1373+ if level_down:
1374+ if index_par == -1:
1375+ raise self.MadGraphCmdError, \
1376+ "Missing ending parenthesis for decay process"
1377+
1378+ if index_par < index_comma:
1379+ line = line[index_par + 1:]
1380+ level_down = False
1381+ break
1382+
1383+ if level_down:
1384+ index_par = line.find(')')
1385+ if index_par == -1:
1386+ raise self.MadGraphCmdError, \
1387+ "Missing ending parenthesis for decay process"
1388+ line = line[index_par + 1:]
1389+
1390+ # Return the core process (ends recursion when there are no
1391+ # more decays)
1392+ return core_process, line
1393+
1394+ # Write the list of command line use in this session
1395+ def do_history(self, line):
1396+ """write in a file the suite of command that was used"""
1397+
1398+ args = split_arg(line)
1399+ if not self.check_history(args):
1400+ return
1401+
1402+ if len(args) == 0:
1403+ print '\n'.join(self.history)
1404+ return False
1405+ elif args[0] == 'clean':
1406+ self.history = []
1407+ print 'history is cleaned'
1408+ return False
1409+ elif args[0] == '.':
1410+ output_file = os.path.join(self._export_dir, 'Cards', \
1411+ 'proc_card_mg5.dat')
1412+ output_file = open(output_file, 'w')
1413+ else:
1414+ output_file = open(args[0], 'w')
1415+
1416+
1417+ # Define a simple header for the file
1418+ creation_time = time.asctime()
1419+ time_info = \
1420+ '# automaticaly generated the %s%s*\n' % (creation_time, ' ' * \
1421+ (26 - len(creation_time)))
1422+ text = \
1423+ '#***********************************************************\n' + \
1424+ '# MadGraph 5 *\n' + \
1425+ '# *\n' + \
1426+ "# * * *\n" + \
1427+ "# * * * * *\n" + \
1428+ "# * * * * 5 * * * * *\n" + \
1429+ "# * * * * *\n" + \
1430+ "# * * *\n" + \
1431+ "# *\n" + \
1432+ "# *\n" + \
1433+ "# The MadGraph Development Team - Please visit us at *\n" + \
1434+ "# https://server06.fynu.ucl.ac.be/projects/madgraph *\n" + \
1435+ '# *\n' + \
1436+ '#***********************************************************\n' + \
1437+ '# *\n' + \
1438+ '# Command File for MadGraph 5 *\n' + \
1439+ '# *\n' + \
1440+ '# run as ./bin/mg5 filename *\n' + \
1441+ time_info + \
1442+ '# *\n' + \
1443+ '#***********************************************************\n'
1444+
1445+ #Avoid repetition of header
1446+ if self.history[0] == '#'+'*' * 59:
1447+ text=''
1448+ # Add the comand used
1449+ text += '\n'.join(self.history) + '\n'
1450+
1451+ #write this information in a file
1452+ output_file.write(text)
1453+ output_file.close()
1454+
1455+ # Import files
1456+ def do_import(self, line):
1457+ """Import files with external formats"""
1458+
1459+ def import_v4file(self, filepath):
1460+ """Helper function to load a v4 file from file path filepath"""
1461+ filename = os.path.basename(filepath)
1462+ if filename.endswith('particles.dat'):
1463+ self._curr_model.set('particles',
1464+ files.read_from_file(
1465+ filepath,
1466+ import_v4.read_particles_v4))
1467+ print "%d particles imported" % \
1468+ len(self._curr_model['particles'])
1469+ return True
1470+ elif filename.endswith('interactions.dat'):
1471+ if len(self._curr_model['particles']) == 0:
1472+ print "No particle list currently active,",
1473+ print "please create one first!"
1474+ return False
1475+ self._curr_model.set('interactions',
1476+ files.read_from_file(
1477+ filepath,
1478+ import_v4.read_interactions_v4,
1479+ self._curr_model['particles']))
1480+ print "%d interactions imported" % \
1481+ len(self._curr_model['interactions'])
1482+ return True
1483+
1484+ #not valid File
1485+ return False
1486+
1487+ args = split_arg(line)
1488+ if not self.check_import(args):
1489+ return
1490+
1491+ if args[0] == 'model_v4':
1492+ # Check for a file
1493+ if os.path.isfile(args[1]):
1494+ suceed = import_v4file(self, args[1])
1495+ if not suceed:
1496+ print "%s is not a valid v4 file name" % \
1497+ os.path.basename(args[1])
1498+ else:
1499+ self._model_dir = os.path.dirname(args[1])
1500+ return
1501+
1502+ # Check for a valid directory
1503+ if os.path.isdir(args[1]):
1504+ self._model_dir = args[1]
1505+ elif MGME_dir and os.path.isdir(os.path.join(MGME_dir, 'Models', \
1506+ args[1])):
1507+ self._model_dir = os.path.join(MGME_dir, 'Models', args[1])
1508+ elif not MGME_dir:
1509+ print "Path %s is not a valid pathname" % args[1]
1510+ print "and no MG_ME installation detected in other to search in Models"
1511+ return False
1512+ else:
1513+ print "Path %s is not a valid pathname" % args[1]
1514+ return False
1515+
1516+ #Load the directory
1517+ if os.path.exists(os.path.join(self._model_dir, 'model.pkl')):
1518+ self.do_load('model %s' % os.path.join(self._model_dir, \
1519+ 'model.pkl'))
1520+ return
1521+ files_to_import = ('particles.dat', 'interactions.dat')
1522+ for filename in files_to_import:
1523+ if os.path.isfile(os.path.join(self._model_dir, filename)):
1524+ import_v4file(self, os.path.join(self._model_dir, \
1525+ filename))
1526+ else:
1527+ print "%s files doesn't exist in %s directory" % \
1528+ (filename, os.path.basename(args[1]))
1529+ #save model for next usage
1530+ self.do_save('model %s ' % os.path.join(self._model_dir, \
1531+ 'model.pkl'))
1532+
1533+ elif args[0] == 'proc_v4':
1534+
1535+ if len(args) == 1 and self._export_dir:
1536+ proc_card = os.path.join(self._export_dir, 'Cards', \
1537+ 'proc_card.dat')
1538+ elif len(args) == 2:
1539+ proc_card = args[1]
1540+ # Check the status of export and try to use file position is no
1541+ #self._export dir are define
1542+ if os.path.isdir(args[1]):
1543+ proc_card = os.path.join(proc_card, 'Cards', \
1544+ 'proc_card.dat')
1545+ self.check_for_export_dir(os.path.realpath(proc_card))
1546+ else:
1547+ logging.error('No default directory are setup')
1548+ return
1549+
1550+ #convert and excecute the card
1551+ self.import_mg4_proc_card(proc_card)
1552+
1553+ elif args[0] == 'command':
1554+ if not os.path.isfile(args[1]):
1555+ print "Path %s is not a valid pathname" % args[1]
1556+ else:
1557+ # Check the status of export and try to use file position is no
1558+ #self._export dir are define
1559+ self.check_for_export_dir(args[1])
1560+ # Execute the card
1561+ self.import_mg5_proc_card(args[1])
1562+ else:
1563+ self.help_import()
1564+ return False
1565+
1566+
1567+ def import_mg4_proc_card(self, filepath):
1568+ """ read a V4 proc card, convert it and run it in mg5"""
1569+
1570+ # change the status of this line in the history -> pass in comment
1571+ self.history[-1] = '#%s' % self.history[-1]
1572+
1573+ # read the proc_card.dat
1574+ reader = files.read_from_file(filepath, import_v4.read_proc_card_v4)
1575+
1576+ if MGME_dir:
1577+ #model_dir = os.path.join(MGME_dir, 'Models')
1578+ line = self.exec_cmd('import model_v4 %s' % (reader.model))
1579+ else:
1580+ logging.error('No MG_ME installation detected')
1581+ return
1582+
1583+
1584+ # Now that we have the model we can split the information
1585+ try:
1586+ lines = reader.extract_command_lines(self._curr_model)
1587+ except import_v4.ParticleError as why:
1588+ print why
1589+ print 'stop import proc_card_v4'
1590+ return
1591+
1592+ for line in lines:
1593+ self.exec_cmd(line)
1594+
1595+ return
1596+
1597+ def import_mg5_proc_card(self, filepath):
1598+ # change the status of this line in the history -> pass in comment
1599+ self.history[-1] = '#%s' % self.history[-1]
1600+
1601+ # Read the lines of the file and execute them
1602+ for line in CmdFile(filepath):
1603+ #remove pointless spaces and \n
1604+ line = line.replace('\n', '').strip()
1605+ # execute the line if this one is not empty
1606+ if line:
1607+ self.exec_cmd(line)
1608+
1609+ return
1610+
1611+ def check_for_export_dir(self, filepath):
1612+ """Check if the files is in a valid export directory and assign it to
1613+ export path if if is"""
1614+
1615+ # keep previous if a previous one is defined
1616+ if self._export_dir:
1617+ return
1618+
1619+ path_split = filepath.split(os.path.sep)
1620+ if len(path_split)>2 and path_split[-2] == 'Cards':
1621+ self._export_dir = os.path.sep.join(path_split[:-2])
1622+
1623+
1624+
1625+ def do_load(self, line):
1626+ """Load information from file"""
1627+
1628+ args = split_arg(line)
1629+ if not self.check_load(args):
1630+ print 'not accepted'
1631+ return
1632+
1633+
1634+ cpu_time1 = time.time()
1635+ if args[0] == 'model':
1636+ self._curr_model = save_load_object.load_from_file(args[1])
1637+ #save_model.save_model(args[1], self._curr_model)
1638+ if isinstance(self._curr_model, base_objects.Model):
1639+ cpu_time2 = time.time()
1640+ print "Loaded model from file in %0.3f s" % \
1641+ (cpu_time2 - cpu_time1)
1642+ else:
1643+ print 'Error: Could not load model from file ', args[1]
1644+ elif args[0] == 'processes':
1645+ self._curr_amps = save_load_object.load_from_file(args[1])
1646+ if isinstance(self._curr_amps, diagram_generation.AmplitudeList):
1647+ cpu_time2 = time.time()
1648+ print "Loaded processes from file in %0.3f s" % \
1649+ (cpu_time2 - cpu_time1)
1650+ if self._curr_amps and not self._curr_model.get('name'):
1651+ self._curr_model = self._curr_amps[0].\
1652+ get('process').get('model')
1653+ print "Model set from process."
1654+ else:
1655+ print 'Error: Could not load processes from file ', args[1]
1656+ else:
1657+ self.help_save()
1658+
1659+ def do_save(self, line):
1660+ """Save information to file"""
1661+
1662+ args = split_arg(line)
1663+ if not self.check_save(args):
1664+ return False
1665+
1666+ if args[0] == 'model':
1667+ if self._curr_model:
1668+ #save_model.save_model(args[1], self._curr_model)
1669+ if save_load_object.save_to_file(args[1], self._curr_model):
1670+ print 'Saved model to file ', args[1]
1671+ else:
1672+ print 'No model to save!'
1673+ elif args[0] == 'processes':
1674+ if self._curr_amps:
1675+ if save_load_object.save_to_file(args[1], self._curr_amps):
1676+ print 'Saved processes to file ', args[1]
1677+ else:
1678+ print 'No processes to save!'
1679+ else:
1680+ self.help_save()
1681+
1682+
1683+ def do_makehtml(self, line):
1684+ """ make the html output for a MAdevent directory """
1685+
1686+ args = split_arg(line)
1687+ if not self.check_makehtml(args):
1688+ return
1689+
1690+
1691+ if self._export_dir:
1692+ dir_path = self._export_dir
1693+ else:
1694+ dir_path = args[1]
1695+
1696+ #look if the user ask to bypass the jpeg creation
1697+ if '--nojpeg' in args:
1698+ makejpg = False
1699+ else:
1700+ makejpg = True
1701+
1702+ os.system('touch %s/done' % os.path.join(dir_path,'SubProcesses'))
1703+ export_v4.create_v4_webpage(dir_path, makejpg)
1704+
1705+
1706+
1707+ def do_setup(self, line):
1708+ """Initialize a new Template or reinitialize one"""
1709+
1710+ args = split_arg(line)
1711+ if not self.check_setup(args):
1712+ return False
1713+
1714+ clean = '-noclean' not in args
1715+ force = '-f' in args
1716+ dir = '-d' in args
1717+ if dir:
1718+ mgme_dir = args[args.find('-d') + 1]
1719+ else:
1720+ mgme_dir = MGME_dir
1721+
1722+ # Check for special directory treatment
1723+ if args[1] == '.':
1724+ if self._export_dir:
1725+ dir_path = self._export_dir
1726+ else:
1727+ print 'No possible working directory are detected'
1728+ self.help_setup()
1729+ return False
1730+ elif args[1] == 'auto':
1731+ name_dir = lambda i: 'PROC_%s_%s' % \
1732+ (os.path.split(self._model_dir)[-1], i)
1733+ auto_path = lambda i: os.path.join(self.writing_dir, name_dir(i))
1734+
1735+ for i in range(500):
1736+ if os.path.isdir(auto_path(i)):
1737+ continue
1738+ else:
1739+ dir_path = auto_path(i)
1740+ break
1741+ else:
1742+ dir_path = os.path.join(self.writing_dir, args[1])
1743+
1744+ if not force and os.path.isdir(dir_path):
1745+ print 'INFO: directory %s already exists.' % args[1]
1746+ if clean:
1747+ print 'If you continue this directory will be cleaned'
1748+
1749+ answer = raw_input('Do you want to continue? [y/n]')
1750+ if answer != 'y':
1751+ print 'stop'
1752+ return False
1753+
1754+ export_v4.copy_v4template(mgme_dir, dir_path, self._model_dir, clean)
1755+ # Import the model
1756+ print 'import model files %s in directory %s' % \
1757+ (os.path.basename(self._model_dir), args[1])
1758+ export_v4.export_model(self._model_dir, dir_path)
1759+ self._export_dir = dir_path
1760+
1761+#===============================================================================
1762+# MadGraphCmd
1763+#===============================================================================
1764+class MadGraphCmdWeb(MadGraphCmd, CheckValidForCmdWeb):
1765+ """The command line processor of MadGraph"""
1766+
1767+ def __init__(self, *arg, **opt):
1768+
1769+ if os.environ.has_key('_CONDOR_SCRATCH_DIR'):
1770+ self.writing_dir = os.path.join(os.environ['_CONDOR_SCRATCH_DIR'], \
1771+ os.path.pardir)
1772+ else:
1773+ self.writing_dir = os.path.join(os.environ['MADGRAPH_DATA'],
1774+ os.environ['REMOTE_USER'])
1775+
1776+ #standard initialization
1777+ MadGraphCmd.__init__(self, *arg, **opt)
1778+
1779+#===============================================================================
1780+# MadGraphCmd
1781+#===============================================================================
1782+class MadGraphCmdShell(MadGraphCmd, CompleteForCmd, CheckValidForCmd):
1783+ """The command line processor of MadGraph"""
1784+
1785+ writing_dir = MGME_dir
1786+
1787+ def preloop(self):
1788+ """Initializing before starting the main loop"""
1789+
1790+ self.prompt = 'mg5>'
1791+
1792+ readline.parse_and_bind("tab: complete")
1793+
1794+ # initialize command history
1795+ history_file = os.path.join(os.environ['HOME'], '.mg5history')
1796+ try:
1797+ readline.read_history_file(history_file)
1798+ except IOError:
1799+ pass
1800+ atexit.register(readline.write_history_file, history_file)
1801+
1802+ # If possible, build an info line with current version number
1803+ # and date, from the VERSION text file
1804+
1805+ info = misc.get_pkg_info()
1806+ info_line = ""
1807+
1808+ if info.has_key('version') and info.has_key('date'):
1809+ len_version = len(info['version'])
1810+ len_date = len(info['date'])
1811+ if len_version + len_date < 30:
1812+ info_line = "* VERSION %s %s %s *\n" % \
1813+ (info['version'],
1814+ (30 - len_version - len_date) * ' ',
1815+ info['date'])
1816+
1817+ self.intro = \
1818+ "************************************************************\n" + \
1819+ "* *\n" + \
1820+ "* W E L C O M E to M A D G R A P H 5 *\n" + \
1821+ "* *\n" + \
1822+ "* *\n" + \
1823+ "* * * *\n" + \
1824+ "* * * * * *\n" + \
1825+ "* * * * * 5 * * * * *\n" + \
1826+ "* * * * * *\n" + \
1827+ "* * * *\n" + \
1828+ "* *\n" + \
1829+ info_line + \
1830+ "* *\n" + \
1831+ "* The MadGraph Development Team - Please visit us at *\n" + \
1832+ "* https://server06.fynu.ucl.ac.be/projects/madgraph *\n" + \
1833+ "* *\n" + \
1834+ "* Type 'help' for in-line help. *\n" + \
1835+ "* *\n" + \
1836+ "************************************************************"
1837+
1838+ # Access to shell
1839+ def do_shell(self, line):
1840+ "Run a shell command"
1841+
1842+ if line.strip() is '':
1843+ self.help_shell()
1844+ else:
1845+ print "running shell command:", line
1846+ subprocess.call(line, shell=True)
1847+
1848+#===============================================================================
1849+#
1850+#===============================================================================
1851+class CmdFile(file):
1852+ """ a class for command input file -in order to debug cmd \n problem"""
1853+
1854+ def __init__(self, name, opt='rU'):
1855+
1856+ file.__init__(self, name, opt)
1857+ self.text = file.read(self)
1858+ self.close()
1859+ self.lines = self.text.split('\n')
1860+
1861+ def readline(self, *arg, **opt):
1862+ """readline method treating correctly a line whithout \n at the end
1863+ (add it)
1864+ """
1865+ if self.lines:
1866+ line = self.lines.pop(0)
1867+ else:
1868+ return ''
1869+
1870+ if line.endswith('\n'):
1871+ return line
1872+ else:
1873+ return line + '\n'
1874+
1875+ def __next__(self):
1876+ return self.lines.__next__()
1877+ def __iter__(self):
1878+ return self.lines.__iter__()
1879+
1880+#===============================================================================
1881+# Draw Command Parser
1882+#===============================================================================
1883+_usage = "draw FILEPATH [options]\n" + \
1884+ "-- draw the diagrams in eps format\n" + \
1885+ " Files will be FILEPATH/diagrams_\"process_string\".eps \n" + \
1886+ " Example: draw plot_dir . \n"
1887+_draw_parser = optparse.OptionParser(usage=_usage)
1888+_draw_parser.add_option("", "--horizontal", default=False,
1889+ action='store_true', help="force S-channel to be horizontal")
1890+_draw_parser.add_option("", "--external", default=0, type='float',
1891+ help="authorizes external particles to end at top or " + \
1892+ "bottom of diagram. If bigger than zero this tune the " + \
1893+ "length of those line.")
1894+_draw_parser.add_option("", "--max_size", default=1.5, type='float',
1895+ help="this forbids external line bigger than max_size")
1896+_draw_parser.add_option("", "--non_propagating", default=True, \
1897+ dest="contract_non_propagating", action='store_false',
1898+ help= "avoid contractions of non propagating lines")
1899+_draw_parser.add_option("", "--add_gap", default=0, type='float', \
1900+ help= "set the x-distance between external particles")
1901+
1902+
1903+
1904+
1905+#===============================================================================
1906+# __main__
1907+#===============================================================================
1908+
1909+if __name__ == '__main__':
1910+
1911+ run_option = sys.argv
1912+ if len(run_option) > 1:
1913+ # The first argument of sys.argv is the name of the program
1914+ input_file = open(run_option[1], 'rU')
1915+ cmd_line = MadGraphCmd(stdin=input_file)
1916+ cmd_line.use_rawinput = False #put it in non interactive mode
1917+ cmd_line.cmdloop()
1918+ else:
1919+ # Interactive mode
1920+ MadGraphCmd().cmdloop()
1921
1922=== removed file 'madgraph/interface/cmd_interface.py'
1923--- madgraph/interface/cmd_interface.py 2010-05-11 13:38:25 +0000
1924+++ madgraph/interface/cmd_interface.py 1970-01-01 00:00:00 +0000
1925@@ -1,1532 +0,0 @@
1926-################################################################################
1927-#
1928-# Copyright (c) 2009 The MadGraph Development team and Contributors
1929-#
1930-# This file is a part of the MadGraph 5 project, an application which
1931-# automatically generates Feynman diagrams and matrix elements for arbitrary
1932-# high-energy processes in the Standard Model and beyond.
1933-#
1934-# It is subject to the MadGraph license which should accompany this
1935-# distribution.
1936-#
1937-# For more information, please visit: http://madgraph.phys.ucl.ac.be
1938-#
1939-################################################################################
1940-"""A user friendly command line interface to access MadGraph features.
1941- Uses the cmd package for command interpretation and tab completion.
1942-"""
1943-
1944-import atexit
1945-import cmd
1946-import logging
1947-import os
1948-import re
1949-import readline
1950-import subprocess
1951-import sys
1952-import time
1953-
1954-import madgraph.iolibs.misc as misc
1955-import madgraph.iolibs.files as files
1956-
1957-import madgraph.iolibs.import_v4 as import_v4
1958-#import madgraph.iolibs.save_model as save_model
1959-import madgraph.iolibs.save_load_object as save_load_object
1960-import madgraph.iolibs.export_v4 as export_v4
1961-
1962-import madgraph.core.base_objects as base_objects
1963-import madgraph.core.diagram_generation as diagram_generation
1964-
1965-import madgraph.core.helas_objects as helas_objects
1966-import madgraph.iolibs.drawing as draw_lib
1967-import madgraph.iolibs.drawing_eps as draw
1968-
1969-#position of MG5
1970-root_path = os.path.split(os.path.dirname(os.path.realpath(__file__)))[0]
1971-root_path = os.path.split(root_path)[0]
1972-
1973-#position of MG_ME
1974-MGME_dir = None
1975-MGME_dir_possibility = [os.path.join(root_path, os.path.pardir),
1976- os.path.join(os.getcwd(), os.path.pardir),
1977- os.getcwd()]
1978-
1979-for position in MGME_dir_possibility:
1980- if os.path.exists(os.path.join(position, 'MGMEVersion.txt')) and \
1981- os.path.exists(os.path.join(position, 'UpdateNotes.txt')):
1982- MGME_dir = os.path.realpath(position)
1983- del MGME_dir_possibility
1984- break
1985-#===============================================================================
1986-# MadGraphCmd
1987-#===============================================================================
1988-class MadGraphCmd(cmd.Cmd):
1989- """The command line processor of MadGraph"""
1990-
1991- __curr_model = base_objects.Model()
1992- __model_dir = None
1993- __curr_amps = diagram_generation.AmplitudeList()
1994- __curr_matrix_elements = helas_objects.HelasMultiProcess()
1995- __curr_fortran_model = export_v4.HelasFortranModel()
1996- __multiparticles = {}
1997-
1998- __display_opts = ['particles',
1999- 'interactions',
2000- 'processes',
2001- 'multiparticles']
2002- __add_opts = ['process']
2003- __save_opts = ['model', 'processes']
2004- __import_formats = ['model_v4', 'proc_v4', 'command']
2005- __export_formats = ['standalone_v4', 'sa_dirs_v4', 'madevent_v4']
2006-
2007- class MadGraphCmdError(Exception):
2008- """Exception raised if an error occurs in the execution
2009- of command."""
2010- pass
2011-
2012- def __init__(self, *arg, **opt):
2013- """ add a tracker of the history """
2014-
2015- self.history = []
2016- self.save_line = ''
2017- cmd.Cmd.__init__(self, *arg, **opt)
2018- self.__generate_info = "" # information line on the generation
2019-
2020- # detect if we have an a priori location for the output:
2021- if 'Cards' in os.listdir('.'):
2022- self.__export_dir = os.path.split(os.path.realpath('.'))[-1]
2023- elif 'Cards' in os.listdir('..'):
2024- self.__export_dir = os.path.split(os.path.realpath('..'))[-1]
2025- elif self.stdin != sys.stdin:
2026- input_path = os.path.realpath(self.stdin.name).split(os.path.sep)
2027- if input_path[-2] == 'Cards':
2028- self.__export_dir = os.path.sep.join(input_path[:-2])
2029- else:
2030- self.__export_dir = None
2031- else:
2032- self.__export_dir = None
2033-
2034- def split_arg(self, line):
2035- """Split a line of arguments"""
2036- return line.split()
2037-
2038- def list_completion(self, text, list):
2039- """Propose completions of text in list"""
2040- if not text:
2041- completions = list
2042- else:
2043- completions = [ f
2044- for f in list
2045- if f.startswith(text)
2046- ]
2047- return completions
2048-
2049- def path_completion(self, text, base_dir=None):
2050- """Propose completions of text to compose a valid path"""
2051-
2052- if base_dir is None:
2053- base_dir = os.getcwd()
2054-
2055- completion = [f
2056- for f in os.listdir(base_dir)
2057- if f.startswith(text) and \
2058- os.path.isfile(os.path.join(base_dir, f))
2059- ]
2060-
2061- completion = completion + \
2062- [f + '/'
2063- for f in os.listdir(base_dir)
2064- if f.startswith(text) and \
2065- os.path.isdir(os.path.join(base_dir, f))
2066- ]
2067-
2068- return completion
2069-
2070-
2071- def preloop(self):
2072- """Initializing before starting the main loop"""
2073-
2074- self.prompt = 'mg5>'
2075-
2076- readline.parse_and_bind("tab: complete")
2077-
2078- # initialize command history
2079- history_file = os.path.join(os.environ['HOME'], '.mg5history')
2080- try:
2081- readline.read_history_file(history_file)
2082- except IOError:
2083- pass
2084- atexit.register(readline.write_history_file, history_file)
2085-
2086- # If possible, build an info line with current version number
2087- # and date, from the VERSION text file
2088-
2089- info = misc.get_pkg_info()
2090- info_line = ""
2091-
2092- if info.has_key('version') and info.has_key('date'):
2093- len_version = len(info['version'])
2094- len_date = len(info['date'])
2095- if len_version + len_date < 30:
2096- info_line = "* VERSION %s %s %s *\n" % \
2097- (info['version'],
2098- (30 - len_version - len_date) * ' ',
2099- info['date'])
2100-
2101- self.intro = \
2102- "************************************************************\n" + \
2103- "* *\n" + \
2104- "* W E L C O M E to M A D G R A P H 5 *\n" + \
2105- "* *\n" + \
2106- "* *\n" + \
2107- "* * * *\n" + \
2108- "* * * * * *\n" + \
2109- "* * * * * 5 * * * * *\n" + \
2110- "* * * * * *\n" + \
2111- "* * * *\n" + \
2112- "* *\n" + \
2113- info_line + \
2114- "* *\n" + \
2115- "* The MadGraph Development Team - Please visit us at *\n" + \
2116- "* https://server06.fynu.ucl.ac.be/projects/madgraph *\n" + \
2117- "* *\n" + \
2118- "* Type 'help' for in-line help. *\n" + \
2119- "* *\n" + \
2120- "************************************************************"
2121-
2122- def precmd(self, line):
2123- """ force the printing of the line if this is executed with an stdin """
2124- # Update the history of this suite of command
2125- self.history.append(line)
2126-
2127- # Print the calling line in the non interactive mode
2128- if not self.use_rawinput:
2129- print line
2130-
2131- #Check if they are a save line:
2132- if self.save_line:
2133- line = self.save_line + line
2134- self.save_line = ''
2135-
2136- #Check that the line is complete
2137- if line.endswith('\\'):
2138- self.save_line = line[:-1]
2139- return '' # do nothing
2140-
2141- #remove comment
2142- if '#' in line:
2143- line = line.split('#')[0]
2144-
2145- # execute the line command
2146- return line
2147-
2148-
2149- def emptyline(self):
2150- """If empty line, do nothing. Default is repeat previous command."""
2151-
2152- pass
2153-
2154- def default(self, line):
2155- """Default action if line is not recognized"""
2156-
2157- if line[0] == "#":
2158- # This is a comment - do nothing
2159- return
2160- else:
2161- # Faulty command
2162- print "Command \"%s\" not recognized, please try again" % \
2163- line.split()[0]
2164-
2165- # Import files
2166- def do_import(self, line):
2167- """Import files with external formats"""
2168-
2169- def import_v4file(self, filepath):
2170- """Helper function to load a v4 file from file path filepath"""
2171- filename = os.path.basename(filepath)
2172- if filename.endswith('particles.dat'):
2173- self.__curr_model.set('particles',
2174- files.read_from_file(
2175- filepath,
2176- import_v4.read_particles_v4))
2177- print "%d particles imported" % \
2178- len(self.__curr_model['particles'])
2179- return True
2180- elif filename.endswith('interactions.dat'):
2181- if len(self.__curr_model['particles']) == 0:
2182- print "No particle list currently active,",
2183- print "please create one first!"
2184- return False
2185- self.__curr_model.set('interactions',
2186- files.read_from_file(
2187- filepath,
2188- import_v4.read_interactions_v4,
2189- self.__curr_model['particles']))
2190- print "%d interactions imported" % \
2191- len(self.__curr_model['interactions'])
2192- return True
2193-
2194-
2195- #not valid File
2196- return False
2197-
2198- args = self.split_arg(line)
2199- if len(args) != 2 or args[0] not in self.__import_formats:
2200- self.help_import()
2201- return False
2202-
2203- if args[0] == 'model_v4':
2204- # Check for a file
2205- if os.path.isfile(args[1]):
2206- suceed = import_v4file(self, args[1])
2207- if not suceed:
2208- print "%s is not a valid v4 file name" % \
2209- os.path.basename(args[1])
2210- else:
2211- self.__model_dir = os.path.dirname(args[1])
2212- return
2213-
2214- # Check for a valid directory
2215- if os.path.isdir(args[1]):
2216- self.__model_dir = args[1]
2217- elif MGME_dir and os.path.isdir(os.path.join(MGME_dir, 'Models', \
2218- args[1])):
2219- self.__model_dir = os.path.join(MGME_dir, 'Models', args[1])
2220- elif not MGME_dir:
2221- print "Path %s is not a valid pathname" % args[1]
2222- print "and no MG_ME installation detected in other to search in Models"
2223- return False
2224- else:
2225- print "Path %s is not a valid pathname" % args[1]
2226- return False
2227-
2228- #Load the directory
2229- if os.path.exists(os.path.join(self.__model_dir, 'model.pkl')):
2230- self.do_load('model %s' % os.path.join(self.__model_dir, \
2231- 'model.pkl'))
2232- return
2233- files_to_import = ('particles.dat', 'interactions.dat')
2234- for filename in files_to_import:
2235- if os.path.isfile(os.path.join(self.__model_dir, filename)):
2236- import_v4file(self, os.path.join(self.__model_dir, \
2237- filename))
2238- else:
2239- print "%s files doesn't exist in %s directory" % \
2240- (filename, os.path.basename(args[1]))
2241- #save model for next usage
2242- self.do_save('model %s ' % os.path.join(self.__model_dir, \
2243- 'model.pkl'))
2244-
2245- elif args[0] == 'proc_v4':
2246- if len(args) == 1 and self.__export_dir:
2247- proc_card = os.path.join(self.__export_dir, '')
2248- elif len(args) == 2:
2249- proc_card = args[1]
2250- else:
2251- logging.error('No default directory are setup')
2252-
2253- self.check_for_export_dir(proc_card)
2254- self.import_mg4_proc_card(proc_card)
2255-
2256- elif args[0] == 'command':
2257- if not os.path.isfile(args[1]):
2258- print "Path %s is not a valid pathname" % args[1]
2259- else:
2260- self.check_for_export_dir(args[1])
2261- self.import_mg5_proc_card(args[1])
2262- else:
2263- self.help_import()
2264- return False
2265-
2266- def complete_import(self, text, line, begidx, endidx):
2267- "Complete the import command"
2268-
2269- # Format
2270- if len(self.split_arg(line[0:begidx])) == 1:
2271- return self.list_completion(text, self.__import_formats)
2272-
2273- # Filename if directory is not given
2274- if len(self.split_arg(line[0:begidx])) == 2:
2275- return self.path_completion(text)
2276-
2277- # Filename if directory is given
2278- if len(self.split_arg(line[0:begidx])) == 3:
2279- return self.path_completion(text,
2280- base_dir=\
2281- self.split_arg(line[0:begidx])[2])
2282-
2283- def import_mg4_proc_card(self, filepath):
2284- """ read a V4 proc card, convert it and run it in mg5"""
2285-
2286- # change the status of this line in the history -> pass in comment
2287- self.history[-1] = '#%s' % self.history[-1]
2288-
2289- # read the proc_card.dat
2290- reader = files.read_from_file(filepath, import_v4.read_proc_card_v4)
2291-
2292- if MGME_dir:
2293- #model_dir = os.path.join(MGME_dir, 'Models')
2294- line = self.onecmd_full('import model_v4 %s' % (reader.model))
2295- else:
2296- logging.error('No MG_ME installation detected')
2297- return
2298-
2299-
2300- # Now that we have the model we can split the information
2301- lines = reader.extract_command_lines(self.__curr_model)
2302- for line in lines:
2303- self.onecmd_full(line)
2304-
2305- return
2306-
2307- def import_mg5_proc_card(self, filepath):
2308- # change the status of this line in the history -> pass in comment
2309- self.history[-1] = '#%s' % self.history[-1]
2310-
2311- # Read the lines of the file and execute them
2312- for line in CmdFile(filepath):
2313- #remove pointless spaces and \n
2314- line = line.replace('\n', '').strip()
2315- # execute the line if this one is not empty
2316- if line:
2317- self.onecmd_full(line)
2318- return
2319-
2320-
2321- def onecmd_full(self, line):
2322- """for third party call, call the line with pre and postfix treatment"""
2323- print line
2324- line = self.precmd(line)
2325- stop = self.onecmd(line)
2326- stop = self.postcmd(stop, line)
2327- return stop
2328-
2329-
2330- def do_save(self, line):
2331- """Save information to file"""
2332-
2333- args = self.split_arg(line)
2334- if len(args) != 2:
2335- self.help_save()
2336- return False
2337-
2338- if args[0] == 'model':
2339- if self.__curr_model:
2340- #save_model.save_model(args[1], self.__curr_model)
2341- if save_load_object.save_to_file(args[1], self.__curr_model):
2342- print 'Saved model to file ', args[1]
2343- else:
2344- print 'No model to save!'
2345- elif args[0] == 'processes':
2346- if self.__curr_amps:
2347- if save_load_object.save_to_file(args[1], self.__curr_amps):
2348- print 'Saved processes to file ', args[1]
2349- else:
2350- print 'No processes to save!'
2351- else:
2352- self.help_save()
2353-
2354- def do_setup(self, line):
2355- """Initialize a new Template or reinitialize one"""
2356-
2357- args = self.split_arg(line)
2358- clean = '-noclean' not in args
2359- force = '-f' in args
2360- dir = '-d' in args
2361- if dir:
2362- mgme_dir = args[args.find('-d') + 1]
2363- else:
2364- mgme_dir = MGME_dir
2365-
2366- if len(args) < 2:
2367- self.help_setup()
2368- return False
2369-
2370- if not self.__model_dir:
2371- print 'No model found. Please import a model first and then retry'
2372- print ' for example do : import model_v4 sm'
2373- return False
2374-
2375- # Check for special directory treatment
2376- if args[1] == '.':
2377- if self.__export_dir:
2378- args[1] = self.__export_dir
2379- else:
2380- print 'No possible working directory are detected'
2381- self.help_setup()
2382- return False
2383- elif args[1] == 'auto':
2384- name_dir = lambda i: 'PROC_%s_%s' % \
2385- (os.path.split(self.__model_dir)[-1], i)
2386- auto_path = lambda i: os.path.join(mgme_dir, name_dir(i))
2387-
2388- for i in range(500):
2389- if os.path.isdir(auto_path(i)):
2390- continue
2391- else:
2392- args[1] = name_dir(i)
2393- break
2394-
2395- dir_path = os.path.join(mgme_dir, args[1])
2396- if not force and os.path.isdir(dir_path):
2397- print 'INFO: directory %s already exists.' % args[1]
2398- if clean:
2399- print 'If you continue this directory will be cleaned'
2400-
2401- answer = raw_input('Do you want to continue? [y/n]')
2402- if answer != 'y':
2403- print 'stop'
2404- return False
2405-
2406- export_v4.copy_v4template(mgme_dir, dir_path, self.__model_dir, clean)
2407- # Import the model
2408- print 'import model files %s in directory %s' % \
2409- (os.path.basename(self.__model_dir), args[1])
2410- export_v4.export_model(self.__model_dir, dir_path)
2411- self.__export_dir = dir_path
2412-
2413-
2414- def complete_setup(self, text, line, begidx, endidx):
2415- "Complete the setup command"
2416-
2417- possible_option = ['-d ', '-f', '-noclean']
2418- possible_option2 = ['d ', 'f', 'noclean']
2419- possible_format = ['madevent_v4']
2420- #don't propose directory use by MG_ME
2421- forbidden_name = ['MadGraphII', 'Template', 'pythia-pgs', 'CVS',
2422- 'Calculators', 'MadAnalysis', 'SimpleAnalysis',
2423- 'mg5', 'DECAY', 'EventConverter', 'Models',
2424- 'ExRootAnalysis', 'HELAS', 'Transfer_Fct']
2425- # Format
2426- if len(self.split_arg(line[0:begidx])) == 1:
2427- return self.list_completion(text, possible_format)
2428-
2429- #name of the run =>proposes old run name
2430- if len(self.split_arg(line[0:begidx])) == 2:
2431- content = [name for name in os.listdir(MGME_dir) if \
2432- name not in forbidden_name and \
2433- os.path.isdir(os.path.join(MGME_dir, name))]
2434- content += ['.', 'auto']
2435- return self.list_completion(text, content)
2436-
2437- # Returning options
2438- if len(self.split_arg(line[0:begidx])) > 2:
2439- if self.split_arg(line[0:begidx])[-1] == '-d':
2440- return self.path_completion(text)
2441- elif self.split_arg(line[0:begidx])[-2] == '-d' and line[-1] != ' ':
2442- return self.path_completion(text, \
2443- self.split_arg(line[0:begidx])[-1])
2444- elif self.split_arg(line[0:begidx])[-1] == '-':
2445- return self.list_completion(text, possible_option2)
2446- else:
2447- return self.list_completion(text, possible_option)
2448-
2449- def do_load(self, line):
2450- """Load information from file"""
2451-
2452- args = self.split_arg(line)
2453- if len(args) != 2:
2454- self.help_load()
2455- return False
2456-
2457- cpu_time1 = time.time()
2458- if args[0] == 'model':
2459- self.__curr_model = save_load_object.load_from_file(args[1])
2460- #save_model.save_model(args[1], self.__curr_model)
2461- if isinstance(self.__curr_model, base_objects.Model):
2462- cpu_time2 = time.time()
2463- print "Loaded model from file in %0.3f s" % \
2464- (cpu_time2 - cpu_time1)
2465- else:
2466- print 'Error: Could not load model from file ', args[1]
2467- elif args[0] == 'processes':
2468- self.__curr_amps = save_load_object.load_from_file(args[1])
2469- if isinstance(self.__curr_amps, diagram_generation.AmplitudeList):
2470- cpu_time2 = time.time()
2471- print "Loaded processes from file in %0.3f s" % \
2472- (cpu_time2 - cpu_time1)
2473- if self.__curr_amps and not self.__curr_model.get('name'):
2474- self.__curr_model = self.__curr_amps[0].\
2475- get('process').get('model')
2476- print "Model set from process."
2477- else:
2478- print 'Error: Could not load processes from file ', args[1]
2479- else:
2480- self.help_save()
2481-
2482- def complete_save(self, text, line, begidx, endidx):
2483- "Complete the save command"
2484-
2485- # Format
2486- if len(self.split_arg(line[0:begidx])) == 1:
2487- return self.list_completion(text, self.__save_opts)
2488-
2489- # Filename if directory is not given
2490- if len(self.split_arg(line[0:begidx])) == 2:
2491- return self.path_completion(text)
2492-
2493- # Filename if directory is given
2494- if len(self.split_arg(line[0:begidx])) == 3:
2495- return self.path_completion(text,
2496- base_dir=\
2497- self.split_arg(line[0:begidx])[2])
2498-
2499- def complete_load(self, text, line, begidx, endidx):
2500- "Complete the load command"
2501-
2502- # Format
2503- if len(self.split_arg(line[0:begidx])) == 1:
2504- return self.list_completion(text, self.__save_opts)
2505-
2506- # Filename if directory is not given
2507- if len(self.split_arg(line[0:begidx])) == 2:
2508- return self.path_completion(text)
2509-
2510- # Filename if directory is given
2511- if len(self.split_arg(line[0:begidx])) == 3:
2512- return self.path_completion(text,
2513- base_dir=\
2514- self.split_arg(line[0:begidx])[2])
2515-
2516- def complete_draw(self, text, line, begidx, endidx):
2517- "Complete the import command"
2518-
2519- # Format
2520- if len(self.split_arg(line[0:begidx])) == 1:
2521- return self.path_completion(text)
2522-
2523-
2524- #option
2525- if len(self.split_arg(line[0:begidx])) >= 2:
2526- option = ['external=', 'horizontal=', 'add_gap=', 'max_size=', \
2527- 'contract_non_propagating=']
2528- return self.list_completion(text, option)
2529-
2530- # Display
2531- def do_display(self, line):
2532- """Display current internal status"""
2533-
2534- args = self.split_arg(line)
2535-
2536- if len(args) != 1:
2537- self.help_display()
2538- return False
2539-
2540- if args[0] == 'particles':
2541- print "Current model contains %i particles:" % \
2542- len(self.__curr_model['particles'])
2543- part_antipart = [part for part in self.__curr_model['particles'] \
2544- if not part['self_antipart']]
2545- part_self = [part for part in self.__curr_model['particles'] \
2546- if part['self_antipart']]
2547- for part in part_antipart:
2548- print part['name'] + '/' + part['antiname'],
2549- print ''
2550- for part in part_self:
2551- print part['name'],
2552- print ''
2553-
2554- elif args[0] == 'interactions':
2555- print "Current model contains %i interactions" % \
2556- len(self.__curr_model['interactions'])
2557- for inter in self.__curr_model['interactions']:
2558- print str(inter['id']) + ':',
2559- for part in inter['particles']:
2560- if part['is_part']:
2561- print part['name'],
2562- else:
2563- print part['antiname'],
2564- print
2565-
2566- elif args[0] == 'processes':
2567- for amp in self.__curr_amps:
2568- print amp.nice_string()
2569- elif args[0] == 'multiparticles':
2570- print 'Multiparticle labels:'
2571- for key in self.__multiparticles:
2572- print key, " = ", self.__multiparticles[key]
2573-
2574- else:
2575- self.help_display()
2576-
2577- def complete_display(self, text, line, begidx, endidx):
2578- "Complete the display command"
2579-
2580- # Format
2581- if len(self.split_arg(line[0:begidx])) == 1:
2582- return self.list_completion(text, self.__display_opts)
2583-
2584- # Access to shell
2585- def do_shell(self, line):
2586- "Run a shell command"
2587-
2588- if line.strip() is '':
2589- self.help_shell()
2590- else:
2591- print "running shell command:", line
2592- subprocess.call(line, shell=True)
2593-
2594- # Generate a new amplitude
2595- def do_generate(self, line):
2596- """Generate an amplitude for a given process"""
2597-
2598- if len(line) < 1:
2599- self.help_generate()
2600- return False
2601-
2602- if len(self.__curr_model['particles']) == 0:
2603- print "No particle list currently active, please create one first!"
2604- return False
2605-
2606- if len(self.__curr_model['interactions']) == 0:
2607- print "No interaction list currently active," + \
2608- " please create one first!"
2609- return False
2610-
2611- # Reset Helas matrix elements
2612- self.__curr_matrix_elements = helas_objects.HelasMultiProcess()
2613- self.__generate_info = line
2614-
2615- try:
2616- if line.find(',') == -1:
2617- myprocdef = self.extract_process(line)
2618- else:
2619- myprocdef, line = self.extract_decay_chain_process(line)
2620- except self.MadGraphCmdError as error:
2621- print "Empty or wrong format process, please try again. Error:\n" \
2622- + str(error)
2623- myprocdef = None
2624-
2625- if myprocdef:
2626-
2627- cpu_time1 = time.time()
2628-
2629- myproc = diagram_generation.MultiProcess(myprocdef)
2630-
2631- self.__curr_amps = myproc.get('amplitudes')
2632-
2633- cpu_time2 = time.time()
2634-
2635- nprocs = len(self.__curr_amps)
2636- ndiags = sum([amp.get_number_of_diagrams() for \
2637- amp in self.__curr_amps])
2638- print "%i processes with %i diagrams generated in %0.3f s" % \
2639- (nprocs, ndiags, (cpu_time2 - cpu_time1))
2640-
2641- else:
2642- print "Empty or wrong format process, please try again."
2643-
2644-
2645- # Helper functions
2646- def extract_decay_chain_process(self, line, level_down=False):
2647- """Recursively extract a decay chain process definition from a
2648- string. Returns a ProcessDefinition."""
2649-
2650- # Start with process number (identified by "@")
2651- proc_number_pattern = re.compile("^(.+)@\s*(\d+)\s*(.*)$")
2652- proc_number_re = proc_number_pattern.match(line)
2653- proc_number = 0
2654- if proc_number_re:
2655- proc_number = int(proc_number_re.group(2))
2656- line = proc_number_re.group(1) + \
2657- proc_number_re.group(3)
2658- print line
2659-
2660- index_comma = line.find(",")
2661- index_par = line.find(")")
2662- min_index = index_comma
2663- if index_par > -1 and (index_par < min_index or min_index == -1):
2664- min_index = index_par
2665-
2666- if min_index > -1:
2667- core_process = self.extract_process(line[:min_index], proc_number)
2668- else:
2669- core_process = self.extract_process(line, proc_number)
2670-
2671- #level_down = False
2672-
2673- while index_comma > -1:
2674- line = line[index_comma + 1:]
2675- index_par = line.find(')')
2676- if line.lstrip()[0] == '(':
2677- # Go down one level in process hierarchy
2678- #level_down = True
2679- line = line.lstrip()[1:]
2680- # This is where recursion happens
2681- decay_process, line = \
2682- self.extract_decay_chain_process(line,
2683- level_down=True)
2684- index_comma = line.find(",")
2685- index_par = line.find(')')
2686- else:
2687- index_comma = line.find(",")
2688- min_index = index_comma
2689- if index_par > -1 and \
2690- (index_par < min_index or min_index == -1):
2691- min_index = index_par
2692- if min_index > -1:
2693- decay_process = self.extract_process(line[:min_index])
2694- else:
2695- decay_process = self.extract_process(line)
2696-
2697- core_process.get('decay_chains').append(decay_process)
2698-
2699- if level_down:
2700- if index_par == -1:
2701- raise self.MadGraphCmdError, \
2702- "Missing ending parenthesis for decay process"
2703-
2704- if index_par < index_comma:
2705- line = line[index_par + 1:]
2706- level_down = False
2707- break
2708-
2709- if level_down:
2710- index_par = line.find(')')
2711- if index_par == -1:
2712- raise self.MadGraphCmdError, \
2713- "Missing ending parenthesis for decay process"
2714- line = line[index_par + 1:]
2715-
2716- # Return the core process (ends recursion when there are no
2717- # more decays)
2718- return core_process, line
2719-
2720- def check_for_export_dir(self, filepath):
2721- """Check if the files is in a valid export directory and assing it to
2722- export path if if is"""
2723-
2724- # keep previous if a previous one is defined
2725- if self.__export_dir:
2726- return
2727-
2728- path_split = filepath.split(os.path.sep)
2729- if path_split[-2] == 'Cards':
2730- self.__export_dir = os.path.sep.join(path_split[:-2])
2731-
2732- def extract_process(self, line, proc_number = 0):
2733- """Extract a process definition from a string. Returns
2734- a ProcessDefinition."""
2735-
2736- # Use regular expressions to extract s-channel propagators,
2737- # forbidden s-channel propagators/particles, coupling orders
2738- # and process number, starting from the back
2739-
2740- # Start with process number (identified by "@")
2741- proc_number_pattern = re.compile("^(.+)@\s*(\d+)\s*(.*)$")
2742- proc_number_re = proc_number_pattern.match(line)
2743- if proc_number_re:
2744- proc_number = int(proc_number_re.group(2))
2745- line = proc_number_re.group(1) + \
2746- proc_number_re.group(3)
2747-
2748- # Start with coupling orders (identified by "=")
2749- order_pattern = re.compile("^(.+)\s+(\w+)\s*=\s*(\d+)\s*$")
2750- order_re = order_pattern.match(line)
2751- orders = {}
2752- while order_re:
2753- orders[order_re.group(2)] = int(order_re.group(3))
2754- line = order_re.group(1)
2755- order_re = order_pattern.match(line)
2756-
2757- # Particle names always lowercase
2758- line = line.lower()
2759-
2760- # Now check for forbidden particles, specified using "/"
2761- slash = line.find("/")
2762- dollar = line.find("$")
2763- forbidden_particles = ""
2764- if slash > 0:
2765- if dollar > slash:
2766- forbidden_particles_re = re.match("^(.+)\s*/\s*(.+\s*)(\$.*)$", line)
2767- else:
2768- forbidden_particles_re = re.match("^(.+)\s*/\s*(.+\s*)$", line)
2769- if forbidden_particles_re:
2770- forbidden_particles = forbidden_particles_re.group(2)
2771- line = forbidden_particles_re.group(1)
2772- if len(forbidden_particles_re.groups()) > 2:
2773- line = line + forbidden_particles_re.group(3)
2774-
2775- # Now check for forbidden schannels, specified using "$"
2776- forbidden_schannels_re = re.match("^(.+)\s*\$\s*(.+)\s*$", line)
2777- forbidden_schannels = ""
2778- if forbidden_schannels_re:
2779- forbidden_schannels = forbidden_schannels_re.group(2)
2780- line = forbidden_schannels_re.group(1)
2781-
2782- # Now check for required schannels, specified using "> >"
2783- required_schannels_re = re.match("^(.+?)>(.+?)>(.+)$", line)
2784- required_schannels = ""
2785- if required_schannels_re:
2786- required_schannels = required_schannels_re.group(2)
2787- line = required_schannels_re.group(1) + ">" + \
2788- required_schannels_re.group(3)
2789-
2790- args = self.split_arg(line)
2791-
2792- myleglist = base_objects.MultiLegList()
2793- state = False
2794-
2795- # Extract process
2796- for part_name in args:
2797-
2798- if part_name == '>':
2799- if not myleglist:
2800- raise self.MadGraphCmdError, \
2801- "No final state particles"
2802- state = True
2803- continue
2804-
2805- mylegids = []
2806- if part_name in self.__multiparticles:
2807- mylegids.extend(self.__multiparticles[part_name])
2808- else:
2809- mypart = self.__curr_model['particles'].find_name(part_name)
2810- if mypart:
2811- mylegids.append(mypart.get_pdg_code())
2812-
2813- if mylegids:
2814- myleglist.append(base_objects.MultiLeg({'ids':mylegids,
2815- 'state':state}))
2816- else:
2817- raise self.MadGraphCmdError, \
2818- "No particle %s in model" % part_name
2819-
2820- if filter(lambda leg: leg.get('state') == True, myleglist):
2821- # We have a valid process
2822-
2823- # Now extract restrictions
2824- forbidden_particle_ids = []
2825- forbidden_schannel_ids = []
2826- required_schannel_ids = []
2827-
2828- #decay_process = len(filter(lambda leg: \
2829- # leg.get('state') == False,
2830- # myleglist)) == 1
2831-
2832- if forbidden_particles:
2833- args = self.split_arg(forbidden_particles)
2834- for part_name in args:
2835- if part_name in self.__multiparticles:
2836- forbidden_particle_ids.extend( \
2837- self.__multiparticles[part_name])
2838- else:
2839- mypart = self.__curr_model['particles'].find_name( \
2840- part_name)
2841- if mypart:
2842- forbidden_particle_ids.append(mypart.get_pdg_code())
2843-
2844- if forbidden_schannels:
2845- args = self.split_arg(forbidden_schannels)
2846- for part_name in args:
2847- if part_name in self.__multiparticles:
2848- forbidden_schannel_ids.extend(\
2849- self.__multiparticles[part_name])
2850- else:
2851- mypart = self.__curr_model['particles'].find_name(\
2852- part_name)
2853- if mypart:
2854- forbidden_schannel_ids.append(mypart.get_pdg_code())
2855-
2856- if required_schannels:
2857- args = self.split_arg(required_schannels)
2858- for part_name in args:
2859- if part_name in self.__multiparticles:
2860- required_schannel_ids.extend(\
2861- self.__multiparticles[part_name])
2862- else:
2863- mypart = self.__curr_model['particles'].find_name(\
2864- part_name)
2865- if mypart:
2866- required_schannel_ids.append(mypart.get_pdg_code())
2867-
2868- return \
2869- base_objects.ProcessDefinition({'legs': myleglist,
2870- 'model': self.__curr_model,
2871- 'id': proc_number,
2872- 'orders': orders,
2873- 'forbidden_particles': forbidden_particle_ids,
2874- 'forbidden_s_channels': forbidden_schannel_ids,
2875- 'required_s_channels': required_schannel_ids
2876- })
2877- # 'is_decay_chain': decay_process\
2878- else:
2879- return None
2880-
2881- # Add a process to the existing multiprocess definition
2882- # Generate a new amplitude
2883- def do_add(self, line):
2884- """Generate an amplitude for a given process and add to
2885- existing amplitudes"""
2886-
2887- if len(line) < 1:
2888- self.help_add()
2889- return False
2890-
2891- if len(self.__curr_model['particles']) == 0:
2892- print "No particle list currently active, please create one first!"
2893- return False
2894-
2895- if len(self.__curr_model['interactions']) == 0:
2896- print "No interaction list currently active," + \
2897- " please create one first!"
2898- return False
2899-
2900- args = self.split_arg(line)
2901- if len(args) < 2:
2902- self.help_import()
2903- return False
2904-
2905- if args[0] == 'process':
2906- # Rejoin line
2907- line = ' '.join(args[1:])
2908-
2909- # store the first process (for the perl script)
2910- if not self.__generate_info:
2911- self.__generate_info = line
2912-
2913- # Reset Helas matrix elements
2914- self.__curr_matrix_elements = helas_objects.HelasMultiProcess()
2915-
2916- try:
2917- if line.find(',') == -1:
2918- myprocdef = self.extract_process(line)
2919- else:
2920- myprocdef, line = self.extract_decay_chain_process(line)
2921- except self.MadGraphCmdError as error:
2922- print "Empty or wrong format process, please try again. Error:"
2923- print error
2924- myprocdef = None
2925-
2926- if myprocdef:
2927-
2928- cpu_time1 = time.time()
2929-
2930- myproc = diagram_generation.MultiProcess(myprocdef)
2931-
2932- for amp in myproc.get('amplitudes'):
2933- if amp not in self.__curr_amps:
2934- self.__curr_amps.append(amp)
2935- else:
2936- print "Warning: Already in processes:"
2937- print amp.nice_string_processes()
2938-
2939- cpu_time2 = time.time()
2940-
2941- nprocs = len(myproc.get('amplitudes'))
2942- ndiags = sum([amp.get_number_of_diagrams() for \
2943- amp in myproc.get('amplitudes')])
2944- print "%i processes with %i diagrams generated in %0.3f s" % \
2945- (nprocs, ndiags, (cpu_time2 - cpu_time1))
2946- ndiags = sum([amp.get_number_of_diagrams() for \
2947- amp in self.__curr_amps])
2948- print "Total: %i processes with %i diagrams" % \
2949- (len(self.__curr_amps), ndiags)
2950- else:
2951- print "Empty or wrong format process, please try again."
2952- else:
2953- self.help_add()
2954-
2955-
2956- def complete_add(self, text, line, begidx, endidx):
2957- "Complete the add command"
2958-
2959- # Format
2960- if len(self.split_arg(line[0:begidx])) == 1:
2961- return self.list_completion(text, self.__add_opts)
2962-
2963- # Write the list of command line use in this session
2964- def do_history(self, line):
2965- """write in a file the suite of command that was used"""
2966-
2967- # Start of the actual routine
2968-
2969- args = self.split_arg(line)
2970-
2971- if len(args) > 1:
2972- self.help_history()
2973- return False
2974-
2975- if len(args) == 0:
2976- print '\n'.join(self.history)
2977- return False
2978- elif args[0] == 'clean':
2979- self.history = []
2980- print 'history is cleaned'
2981- return False
2982-
2983- output_file = open(args[0], 'w')
2984- # Define a simple header for the file
2985- creation_time = time.asctime()
2986- time_info = \
2987- '# automaticaly generated the %s%s*\n' % (creation_time, ' ' * \
2988- (26 - len(creation_time)))
2989- text = \
2990- '#***********************************************************\n' + \
2991- '# MadGraph 5 *\n' + \
2992- '# *\n' + \
2993- "# * * *\n" + \
2994- "# * * * * *\n" + \
2995- "# * * * * 5 * * * * *\n" + \
2996- "# * * * * *\n" + \
2997- "# * * *\n" + \
2998- "# *\n" + \
2999- "# *\n" + \
3000- "# The MadGraph Development Team - Please visit us at *\n" + \
3001- "# https://server06.fynu.ucl.ac.be/projects/madgraph *\n" + \
3002- '# *\n' + \
3003- '#***********************************************************\n' + \
3004- '# *\n' + \
3005- '# Command File for MadGraph 5 *\n' + \
3006- '# *\n' + \
3007- '# run as ./bin/mg5 filename *\n' + \
3008- time_info + \
3009- '# *\n' + \
3010- '#***********************************************************\n'
3011-
3012- #Avoid repetition of header
3013- if self.history[0] == '#'+'*' * 59:
3014- text=''
3015- # Add the comand used
3016- text += '\n'.join(self.history) + '\n'
3017-
3018- #write this information in a file
3019- output_file.write(text)
3020- output_file.close()
3021-
3022- def complete_history(self, text, line, begidx, endidx):
3023- "Complete the add command"
3024-
3025- # Format
3026- if len(self.split_arg(line[0:begidx])) == 1:
3027- return self.path_completion(text)
3028-
3029- # Export a matrix element
3030- def do_export(self, line):
3031- """Export a generated amplitude to file"""
3032-
3033- def generate_matrix_elements(self):
3034- """Helper function to generate the matrix elements before
3035- exporting"""
3036-
3037- cpu_time1 = time.time()
3038- if not self.__curr_matrix_elements.get('matrix_elements'):
3039- self.__curr_matrix_elements = \
3040- helas_objects.HelasMultiProcess(\
3041- self.__curr_amps)
3042- cpu_time2 = time.time()
3043-
3044- ndiags = sum([len(me.get('diagrams')) for \
3045- me in self.__curr_matrix_elements.\
3046- get('matrix_elements')])
3047-
3048- return ndiags, cpu_time2 - cpu_time1
3049-
3050- # Start of the actual routine
3051-
3052- args = self.split_arg(line)
3053-
3054- if len(args) == 0 or (len(args) == 1 and not self.__export_dir) or \
3055- args[0] not in self.__export_formats:
3056- self.help_export()
3057- return False
3058-
3059- if not self.__curr_amps:
3060- print "No process generated, please generate a process!"
3061- return False
3062-
3063- if len(args) == 1:
3064- path = os.path.join(self.__export_dir, 'SubProcesses')
3065- else:
3066- path = args[1]
3067-
3068- if not os.path.isdir(path):
3069- print "%s is not a valid directory for export file" % path
3070- return False
3071-
3072- ndiags, cpu_time = generate_matrix_elements(self)
3073- calls = 0
3074-
3075- if args[0] == 'standalone_v4':
3076- for me in self.__curr_matrix_elements.get('matrix_elements'):
3077- filename = os.path.join(path, 'matrix_' + \
3078- me.get('processes')[0].shell_string() + ".f")
3079- if os.path.isfile(filename):
3080- print "Overwriting existing file %s" % filename
3081- else:
3082- print "Creating new file %s" % filename
3083- calls = calls + files.write_to_file(filename,
3084- export_v4.write_matrix_element_v4_standalone,
3085- me, self.__curr_fortran_model)
3086-
3087-
3088- if args[0] == 'sa_dirs_v4':
3089- for me in self.__curr_matrix_elements.get('matrix_elements'):
3090- calls = calls + \
3091- export_v4.generate_subprocess_directory_v4_standalone(\
3092- me, self.__curr_fortran_model, path)
3093-
3094- if args[0] == 'madevent_v4':
3095- for me in self.__curr_matrix_elements.get('matrix_elements'):
3096- calls = calls + \
3097- export_v4.generate_subprocess_directory_v4_madevent(\
3098- me, self.__curr_fortran_model, path)
3099-
3100- card_path = os.path.join(path, os.path.pardir, 'SubProcesses', \
3101- 'procdef_mg5.dat')
3102- if self.__generate_info:
3103- export_v4.write_procdef_mg5(card_path,
3104- os.path.split(self.__model_dir)[-1],
3105- self.__generate_info)
3106-
3107- print ("Generated helas calls for %d subprocesses " + \
3108- "(%d diagrams) in %0.3f s") % \
3109- (len(self.__curr_matrix_elements.get('matrix_elements')),
3110- ndiags, cpu_time)
3111-
3112- print "Wrote %d helas calls" % calls
3113-
3114- # Replace the amplitudes with the actual amplitudes from the
3115- # matrix elements, which allows proper diagram drawing also of
3116- # decay chain processes
3117- self.__curr_amps = diagram_generation.AmplitudeList(\
3118- [me.get('base_amplitude') for me in \
3119- self.__curr_matrix_elements.get('matrix_elements')])
3120-
3121- def complete_export(self, text, line, begidx, endidx):
3122- "Complete the export command"
3123-
3124- # Format
3125- if len(self.split_arg(line[0:begidx])) == 1:
3126- return self.list_completion(text, self.__export_formats)
3127-
3128- # Filename if directory is not given
3129- if len(self.split_arg(line[0:begidx])) == 2:
3130- return self.path_completion(text)
3131-
3132- # Filename if directory is given
3133- if len(self.split_arg(line[0:begidx])) == 3:
3134- return self.path_completion(text,
3135- base_dir=\
3136- self.split_arg(line[0:begidx])[2])
3137-
3138- # Define a multiparticle label
3139- def do_define(self, line):
3140- """Define a multiparticle"""
3141-
3142- # Particle names always lowercase
3143- line = line.lower()
3144-
3145- args = self.split_arg(line)
3146-
3147- if len(args) < 1:
3148- self.help_define()
3149- return False
3150-
3151- if len(self.__curr_model['particles']) == 0:
3152- print "No particle list currently active, please create one first!"
3153- return False
3154-
3155- label = args[0]
3156- pdg_list = []
3157-
3158- for part_name in args[1:]:
3159-
3160- mypart = self.__curr_model['particles'].find_name(part_name)
3161-
3162- if mypart:
3163- pdg_list.append(mypart.get_pdg_code())
3164- else:
3165- print ("Error: No particle %s in model. " % part_name) + \
3166- "No multiparticle created."
3167- return False
3168-
3169- if not pdg_list:
3170- print """Empty or wrong format for multiparticle.
3171- Please try again."""
3172-
3173- self.__multiparticles[label] = pdg_list
3174-
3175- def do_draw(self, line):
3176- """ draw the Feynman diagram for the given process """
3177-
3178- args = self.split_arg(line)
3179-
3180- if len(args) < 1:
3181- self.help_draw()
3182- return False
3183-
3184- if not self.__curr_amps:
3185- print "No process generated, please generate a process!"
3186- return False
3187-
3188- if not os.path.isdir(args[0]):
3189- print "%s is not a valid directory for export file" % args[1]
3190-
3191- start = time.time()
3192- option = draw_lib.DrawOption()
3193- if len(args) > 1:
3194- for data in args[1:]:
3195- try:
3196- key, value = data.split('=')
3197- except:
3198- print "invalid syntax: '%s'. Please try again" % data
3199- self.help_draw()
3200- return False
3201- option.set(key, value)
3202-
3203- # Collect amplitudes
3204- amplitudes = diagram_generation.AmplitudeList()
3205-
3206- for amp in self.__curr_amps:
3207- amplitudes.extend(amp.get_amplitudes())
3208-
3209- for amp in amplitudes:
3210- filename = os.path.join(args[0], 'diagrams_' + \
3211- amp.get('process').shell_string() + ".eps")
3212- plot = draw.MultiEpsDiagramDrawer(amp['diagrams'],
3213- filename,
3214- model=self.__curr_model,
3215- amplitude='')
3216-
3217- logging.info("Drawing " + \
3218- amp.get('process').nice_string())
3219- plot.draw(opt=option)
3220- print "Wrote file " + filename
3221-
3222- stop = time.time()
3223- print 'time to draw', stop - start
3224-
3225- def do_makehtml(self, line):
3226- """ make the html output for a MAdevent directory """
3227-
3228- args = self.split_arg(line)
3229-
3230- if len(args) < 1:
3231- self.help_makehtml()
3232- return False
3233-
3234- if args[0] != 'madevent_v4':
3235- self.help_makehtml()
3236- return False
3237-
3238- if (len(args) == 1 and not self.__export_dir) or \
3239- (len(args) > 1 and not os.path.isdir(args[1])):
3240- self.help_makehtml()
3241- return False
3242-
3243- if self.__export_dir:
3244- dir_path = self.__export_dir
3245- else:
3246- dir_path = args[1]
3247-
3248- #look if the user ask to bypass the jpeg creation
3249- if '--nojpeg' in args:
3250- makejpg = False
3251- else:
3252- makejpg = True
3253-
3254- export_v4.create_v4_webpage(dir_path, makejpg)
3255- os.system('touch %s/done' % os.path.join(dir_path,'SubProcesses'))
3256-
3257- def complete_makehtml(self, text, line, begidx, endidx):
3258- """ format: makehtlm madevent_v4 [PATH] [--nojpeg]"""
3259-
3260- # Format
3261- if len(self.split_arg(line[0:begidx])) == 1:
3262- return self.list_completion(text, ['madevent_v4'])
3263-
3264- if text.startswith('-'):
3265- return self.list_completion(text, ['--nojpeg'])
3266-
3267- # Filename if directory is not given
3268- if len(self.split_arg(line[0:begidx])) == 2:
3269- return self.path_completion(text)
3270-
3271- # Filename if directory is given
3272- if len(self.split_arg(line[0:begidx])) == 3:
3273- return self.path_completion(text,
3274- base_dir=\
3275- self.split_arg(line[0:begidx])[2])
3276-
3277-
3278- # Quit
3279- def do_quit(self, line):
3280- sys.exit(1)
3281-
3282- # In-line help
3283- def help_save(self):
3284- print "syntax: save %s FILENAME" % "|".join(self.__save_opts)
3285- print "-- save information as file FILENAME"
3286-
3287-
3288- def help_load(self):
3289- print "syntax: load %s FILENAME" % "|".join(self.__save_opts)
3290- print "-- load information from file FILENAME"
3291-
3292- def help_import(self):
3293-
3294- print "syntax: import " + "|".join(self.__import_formats) + \
3295- " FILENAME"
3296- print "-- imports file(s) in various formats"
3297- print
3298- print " import model_v4 MODEL_info :"
3299- print " Import a MG4 Model in MG5 Model"""
3300- print " Model_info could be the name of the model"""
3301- print " or the path to MG4_Model directory"""
3302- print
3303- print " import proc_v4 [PATH] :"
3304- print " Execute MG5 based on a proc_card.dat in MG4 format."""
3305- print " Path to the proc_card is optional if you have setup a"
3306- print " madevent directory"
3307- print
3308- print " import command PATH :"
3309- print " Execute the list of command in the file at PATH"
3310-
3311- def help_display(self):
3312- print "syntax: display " + "|".join(self.__display_opts)
3313- print "-- display a the status of various internal state variables"
3314-
3315- def help_setup(self):
3316- print "syntax madevent_v4 name|.|auto [options]"
3317- print "-- Create a copy of the V4 Template in the MG_ME directory."
3318- print " name will be the name of the copy the madevent Template that"
3319- print " will be use by default in following steps"
3320- print " If you put '.' instead of a name, the code will try to locate"
3321- print " a valid copy of the Template under focus"
3322- print " If you put 'auto' instead an automatic name will be created"
3323- print " options:"
3324- print " -f: force the cleaning of the directory if this one exist"
3325- print " -d PATH: specify the directory where to create name"
3326- print " -noclean: no cleaning perform in name"
3327- print " Example:"
3328- print " setup madevent_v4 MYRUN"
3329- print " setup madevent_v4 MYRUN -d ../MG_ME -f"
3330-
3331- def help_generate(self):
3332-
3333- print "syntax: generate INITIAL STATE > REQ S-CHANNEL > FINAL STATE $ EXCL S-CHANNEL / FORBIDDEN PARTICLES COUP1=ORDER1 COUP2=ORDER2"
3334- print "-- generate diagrams for a given process"
3335- print " Example: u d~ > w+ > m+ vm g $ a / z h QED=3 QCD=0 @1"
3336- print "Decay chain syntax:"
3337- print " core process, decay1, (decay2, (decay3, ...)), ... etc"
3338- print " Example: g g > t~ t @2, (t~ > W- b~, W- > e- ve~), t > W+ b"
3339- print " Note that identical particles will all be decayed"
3340-
3341- def help_add(self):
3342-
3343- print "syntax: add process INITIAL STATE > REQ S-CHANNEL > FINAL STATE $ EXCL S-CHANNEL / FORBIDDEN PARTICLES COUP1=ORDER1 COUP2=ORDER2"
3344- print "-- generate diagrams for a process and add to existing processes"
3345- print " Syntax example: u d~ > w+ > m+ vm g $ a / z h QED=3 QCD=0 @1"
3346- print "Decay chain syntax:"
3347- print " core process, decay1, (decay2, (decay3, ...)), ... etc"
3348- print " Example: g g > t~ t @2, (t~ > W- b~, W- > e- ve~), t > W+ b"
3349- print " Note that identical particles will all be decayed"
3350-
3351- def help_define(self):
3352- print "syntax: define multipart_name [ part_name_list ]"
3353- print "-- define a multiparticle"
3354- print " Example: define p u u~ c c~ d d~ s s~"
3355-
3356- def help_export(self):
3357- print "syntax: export " + "|".join(self.__export_formats) + \
3358- " FILEPATH"
3359- print """-- export matrix elements. For standalone_v4, the resulting
3360- files will be FILEPATH/matrix_\"process_string\".f. For sa_dirs_v4,
3361- the result is a set of complete MG4 Standalone process directories.
3362- For madevent_v4, the path needs to be to a MadEvent SubProcesses
3363- directory, and the result is the Pxxx directories (including the
3364- diagram .ps and .jpg files) for the subprocesses as well as a
3365- correctly generated subproc.mg file. Note that if you have run the
3366- 'setup', FILEPATH is optional."""
3367-
3368- def help_history(self):
3369- print "syntax: history [FILEPATH] [-clean] "
3370- print "-- write in the specified files all the call to MG5 that you have"""
3371- print " perform since that you have open this command line applet."""
3372- print " -clean option will remove all the entry of the history"""
3373-
3374- def help_makehtml(self):
3375- print "syntax: makehtlm madevent_v4 [PATH]"
3376- print "-- create the web page related to the directory PATH"
3377- print " by default PATH is the directory defined with the setup command"
3378-
3379-
3380- def help_draw(self):
3381- print "syntax: draw FILEPATH [option=value]"
3382- print "-- draw the diagrams in eps format"
3383- print " Files will be FILEPATH/diagrams_\"process_string\".eps"
3384- print " Example: draw plot_dir ."
3385- print " Possible option: "
3386- print " horizontal [False]: force S-channel to be horizontal"
3387- print " external [0]: authorizes external particles to end"
3388- print " at top or bottom of diagram. If bigger than zero"
3389- print " this tune the length of those line."
3390- print " max_size [0]: this forbids external line bigger than "
3391- print " max_size."
3392- print " contract_non_propagating [True]:contracts non propagating lines"
3393- print " Example: draw plot_dir external=1 horizontal=1"
3394-
3395- def help_shell(self):
3396- print "syntax: shell CMD (or ! CMD)"
3397- print "-- run the shell command CMD and catch output"
3398-
3399- def help_quit(self):
3400- print "syntax: quit"
3401- print "-- terminates the application"
3402-
3403- def help_help(self):
3404- print "syntax: help"
3405- print "-- access to the in-line help"
3406-
3407- # Aliases
3408-
3409- do_EOF = do_quit
3410- help_EOF = help_quit
3411-
3412-
3413-#===============================================================================
3414-#
3415-#===============================================================================
3416-class CmdFile(file):
3417- """ a class for command input file -in order to debug cmd \n problem"""
3418-
3419- def __init__(self, name, opt):
3420-
3421- file.__init__(self, name, 'rU')
3422- self.text = file.read(self)
3423- self.close()
3424- self.lines = self.text.split('\n')
3425- print self.lines
3426-
3427- def readline(self, *arg, **opt):
3428- """readline method treating correctly a line whithout \n at the end
3429- (add it)
3430- """
3431- if self.lines:
3432- line = self.lines.pop(0)
3433- else:
3434- return ''
3435-
3436- if line.endswith('\n'):
3437- return line
3438- else:
3439- return line + '\n'
3440-
3441-
3442-#===============================================================================
3443-# __main__
3444-#===============================================================================
3445-
3446-if __name__ == '__main__':
3447-
3448- run_option = sys.argv
3449- if len(run_option) > 1:
3450- # The first argument of sys.argv is the name of the program
3451- input_file = open(run_option[1], 'rU')
3452- cmd_line = MadGraphCmd(stdin=input_file)
3453- cmd_line.use_rawinput = False #put it in non interactive mode
3454- cmd_line.cmdloop()
3455- else:
3456- # Interactive mode
3457- MadGraphCmd().cmdloop()
3458
3459=== modified file 'madgraph/iolibs/drawing.py'
3460--- madgraph/iolibs/drawing.py 2010-05-11 13:07:02 +0000
3461+++ madgraph/iolibs/drawing.py 2010-05-19 07:36:39 +0000
3462@@ -1861,7 +1861,7 @@
3463 class DrawingOptionError(Exception):
3464 """Error raising if an invalid entry is set in a option."""
3465
3466- def __init__(self, opt={}):
3467+ def __init__(self, opt=''):
3468 """Fullfill option with standard value."""
3469
3470 #define default
3471@@ -1871,8 +1871,14 @@
3472 self.max_size = 1.5
3473 self.contract_non_propagating = True
3474
3475- for key, value in opt.items():
3476- self.set(key, value)
3477+ if isinstance(opt, dict):
3478+ for key, value in opt.items():
3479+ self.set(key, value)
3480+ else:
3481+ for value in ['external','add_gap','horizontal','max_size',
3482+ 'contract_non_propagating']:
3483+ if hasattr(opt, value):
3484+ self.set(value, getattr(opt, value))
3485
3486 def set(self, key, value):
3487 """Check and attribute the given value."""
3488
3489=== modified file 'madgraph/iolibs/drawing_eps.py'
3490--- madgraph/iolibs/drawing_eps.py 2010-05-11 13:15:30 +0000
3491+++ madgraph/iolibs/drawing_eps.py 2010-05-19 07:36:39 +0000
3492@@ -348,6 +348,7 @@
3493 # Standard method
3494 super(MultiEpsDiagramDrawer, self).draw_diagram(diagram, self.block_nb)
3495 # But keep track how many diagrams are already drawn
3496+
3497 self.block_nb += 1
3498
3499
3500
3501=== modified file 'madgraph/iolibs/export_v4.py'
3502--- madgraph/iolibs/export_v4.py 2010-05-07 13:47:25 +0000
3503+++ madgraph/iolibs/export_v4.py 2010-05-19 07:36:39 +0000
3504@@ -51,7 +51,10 @@
3505 print 'remove old information in %s' % os.path.basename(dir_path)
3506 old_pos = os.getcwd()
3507 os.chdir(dir_path)
3508- subprocess.call([os.path.join('bin', 'clean_template')])
3509+ if os.environ.has_key('MADGRAPH_BASE'):
3510+ subprocess.call([os.path.join('bin', 'clean_template'), '--web'])
3511+ else:
3512+ subprocess.call([os.path.join('bin', 'clean_template')])
3513 os.chdir(old_pos)
3514
3515 #Write version info
3516@@ -77,6 +80,7 @@
3517 #But first ensure that coupling are define whithout spaces:
3518 process_str = process_str.replace(' =', '=')
3519 process_str = process_str.replace('= ', '=')
3520+ process_str = process_str.replace(',',' , ')
3521 #now loop on the element and treat all the coupling
3522 for info in process_str.split():
3523 if '=' in info:
3524@@ -105,7 +109,6 @@
3525 """call the perl script creating the web interface for MadEvent"""
3526
3527 old_pos = os.getcwd()
3528-
3529 os.chdir(os.path.join(dir_path, 'SubProcesses'))
3530 P_dir_list = [proc for proc in os.listdir('.') if os.path.isdir(proc) and \
3531 proc[0] == 'P']
3532@@ -115,11 +118,13 @@
3533 logger.info("Generate jpeg diagrams")
3534 for Pdir in P_dir_list:
3535 os.chdir(Pdir)
3536+ print dir_path
3537 subprocess.call([os.path.join(dir_path, 'bin', 'gen_jpeg-pl')])
3538 os.chdir(os.path.pardir)
3539
3540 logger.info("Generate web pages")
3541 # Create the WebPage using perl script
3542+
3543 devnull = os.open(os.devnull, os.O_RDWR)
3544 subprocess.call([os.path.join(dir_path, 'bin', 'gen_cardhtml-pl')], \
3545 stdout=devnull)
3546@@ -131,11 +136,13 @@
3547 (name.endswith('.html') or name.endswith('.jpg')) and \
3548 name != 'index.html']
3549
3550- subprocess.call([os.path.join(dir_path, 'bin', 'gen_cardhtml-pl')])
3551 if os.path.exists(os.path.join('SubProcesses', 'subproc.mg')):
3552 if os.path.exists('madevent.tar.gz'):
3553 os.remove('madevent.tar.gz')
3554- subprocess.call(['make'])
3555+ subprocess.call(['make'], stdout=devnull)
3556+
3557+
3558+ subprocess.call([os.path.join(dir_path, 'bin', 'gen_cardhtml-pl')])
3559
3560 #return to the initial dir
3561 os.chdir(old_pos)
3562
3563=== modified file 'madgraph/iolibs/import_v4.py'
3564--- madgraph/iolibs/import_v4.py 2010-05-07 12:26:00 +0000
3565+++ madgraph/iolibs/import_v4.py 2010-05-19 07:36:39 +0000
3566@@ -326,9 +326,11 @@
3567 reader = ProcCardv4Reader(fsock)
3568 return reader
3569
3570-
3571-
3572-class ProcCardv4Reader():
3573+class ParticleError(Exception):
3574+ """ A class to carch the error"""
3575+ pass
3576+
3577+class ProcCardv4Reader(object):
3578 """read a proc_card.dat in the mg4 format and creates the equivalent routine
3579 for mg5"""
3580
3581@@ -343,7 +345,7 @@
3582 "# End MULTIPARTICLES # This is TAG. Do not modify this line\n"
3583
3584 # line pattern (remove comment at the end of the line)
3585- pat_line = re.compile(r"""^\s*(?P<info>[^\#]*[\S)])\s*(\#|$)""", re.DOTALL)
3586+ pat_line = re.compile(r"""^\s*(?P<info>[^\#]*[^\s\#])\s*(\#|$)""", re.DOTALL)
3587
3588 def __init__(self, fsock):
3589 """init the variable"""
3590@@ -439,8 +441,7 @@
3591 lines.append('setup madevent_v4 . -f')
3592 lines.append('export madevent_v4')
3593 lines.append('makehtml madevent_v4')
3594- lines.append('history %s' % os.path.relpath(
3595- os.path.join(self.process_path, 'Cards', 'proc_card_mg5.dat')))
3596+ lines.append('history .')
3597
3598 return lines
3599
3600@@ -480,7 +481,8 @@
3601 #Check for infinite loop
3602 if pos == old_pos:
3603 logging.error('Invalid characters: %s' % line[pos:pos + 4])
3604- return
3605+ raise ParticleError('Set of character %s not defined' %
3606+ line[pos:pos + 4])
3607 old_pos = pos
3608 # check for pointless character
3609 if line[pos] in [' ', '\n', '\t']:
3610@@ -496,7 +498,7 @@
3611
3612 return out
3613
3614-class ProcessInfo():
3615+class ProcessInfo(object):
3616 """This is the basic object for storing process information"""
3617
3618 def __init__(self, line):
3619@@ -530,10 +532,14 @@
3620
3621
3622 # check if we have a MG5 format
3623+ if line.startswith('/mg5/'):
3624+ self.line = line[5:]
3625+ self.is_mg5_valid = True
3626+ return
3627 if ',' in line or '=' in line:
3628 self.is_mg5_valid = True
3629 return
3630-
3631+
3632 # extract (S-)forbidden particle
3633 pos_forbid = line.find('/')
3634 pos_sforbid = line.find('$')
3635@@ -573,7 +579,8 @@
3636 level_content = line.split('>')
3637 for level, data in enumerate(level_content):
3638 particles = self.separate_particle(data, particles_name)
3639- [self.particles.append((level, name)) for name in particles]
3640+ if particles:
3641+ [self.particles.append((level, name)) for name in particles]
3642
3643
3644 def treat_decay_chain(self, line, particles_name):
3645
3646=== modified file 'tests/input_files/v4_proc_card.dat'
3647--- tests/input_files/v4_proc_card.dat 2010-05-07 12:26:00 +0000
3648+++ tests/input_files/v4_proc_card.dat 2010-05-19 07:36:39 +0000
3649@@ -32,8 +32,9 @@
3650 # Process(es) requested : mg2 input *
3651 #*********************************************************************
3652 # Begin PROCESS # This is TAG. Do not modify this line
3653+#
3654
3655-pp>e-ve~ @1 # First Process
3656+pp>ve~e- @1 # First Process
3657 QCD=99 # Max QCD couplings
3658 QED=2 # Max QED couplings
3659 end_coup # End the couplings input
3660
3661=== modified file 'tests/test_manager.py'
3662--- tests/test_manager.py 2010-05-06 19:22:46 +0000
3663+++ tests/test_manager.py 2010-05-19 07:36:39 +0000
3664@@ -43,8 +43,23 @@
3665 #sys.path.append(root_path)
3666
3667 root_path = os.path.split(os.path.dirname(os.path.realpath(__file__)))[0]
3668-
3669 sys.path.append(root_path)
3670+
3671+
3672+#position of MG_ME
3673+MGME_dir = None
3674+MGME_dir_possibility = [os.path.join(root_path, os.path.pardir),
3675+ os.path.join(os.getcwd(), os.path.pardir),
3676+ os.getcwd()]
3677+
3678+for position in MGME_dir_possibility:
3679+ if os.path.exists(os.path.join(position, 'MGMEVersion.txt')) and \
3680+ os.path.exists(os.path.join(position, 'UpdateNotes.txt')):
3681+ MGME_dir = os.path.realpath(position)
3682+ break
3683+del MGME_dir_possibility
3684+
3685+
3686 #===============================================================================
3687 # run
3688 #===============================================================================
3689@@ -122,10 +137,11 @@
3690 self.go_to_root()
3691
3692
3693- for name in os.listdir(directory):
3694+ for name in os.listdir(os.path.join(root_path,directory)):
3695 local_check = checking
3696
3697- status = self.status_file(directory + '/' + name)
3698+ status = self.status_file(os.path.join(root_path, directory,name))
3699+ #directory + '/' + name)
3700 if status is None:
3701 continue
3702
3703@@ -228,11 +244,11 @@
3704 @staticmethod
3705 def status_file(name):
3706 """ check if a name is a module/a python file and return the status """
3707- if os.path.isfile(name):
3708+ if os.path.isfile(os.path.join(root_path, name)):
3709 if name.endswith('.py') and '__init__' not in name:
3710 return 'file'
3711- elif os.path.isdir(name):
3712- if os.path.isfile(name + '/__init__.py'):
3713+ elif os.path.isdir(os.path.join(root_path, name)):
3714+ if os.path.isfile(os.path.join(root_path, name , '__init__.py')):
3715 return 'module'
3716
3717 @classmethod
3718@@ -317,7 +333,8 @@
3719 where is launched
3720 """
3721 self.launch_pos = os.path.realpath(os.getcwd())
3722- os.chdir(root_path)
3723+ self.root_path = root_path
3724+ #os.chdir(root_path)
3725
3726 def go_to_initpos(self):
3727 """
3728
3729=== added file 'tests/unit_tests/interface/test_cmd.py'
3730--- tests/unit_tests/interface/test_cmd.py 1970-01-01 00:00:00 +0000
3731+++ tests/unit_tests/interface/test_cmd.py 2010-05-19 07:36:39 +0000
3732@@ -0,0 +1,137 @@
3733+################################################################################
3734+#
3735+# Copyright (c) 2009 The MadGraph Development team and Contributors
3736+#
3737+# This file is a part of the MadGraph 5 project, an application which
3738+# automatically generates Feynman diagrams and matrix elements for arbitrary
3739+# high-energy processes in the Standard Model and beyond.
3740+#
3741+# It is subject to the MadGraph license which should accompany this
3742+# distribution.
3743+#
3744+# For more information, please visit: http://madgraph.phys.ucl.ac.be
3745+#
3746+################################################################################
3747+import unittest
3748+import os
3749+import shutil
3750+
3751+import madgraph.interface.cmd_interface as Cmd
3752+_file_path = os.path.split(os.path.dirname(os.path.realpath(__file__)))[0]
3753+
3754+_pickle_path =os.path.join(_file_path, os.pardir, 'input_files')
3755+
3756+
3757+#===============================================================================
3758+# TestCmd
3759+#===============================================================================
3760+class TestCmdShell1(unittest.TestCase):
3761+ """this treats all the command not related to MG_ME"""
3762+
3763+ def setUp(self):
3764+ """ basic building of the class to test """
3765+
3766+ self.cmd = Cmd.MadGraphCmdShell()
3767+
3768+
3769+ def do(self, line):
3770+ """ exec a line in the cmd under test """
3771+ self.cmd.exec_cmd(line)
3772+
3773+ def test_generate(self):
3774+ """command 'generate' works"""
3775+
3776+ self.do('load model %s' % os.path.join(_pickle_path, 'sm.pkl'))
3777+ self.do('generate e+ e- > e+ e-')
3778+ self.assertTrue(self.cmd._curr_amps)
3779+ self.do('define P Z u')
3780+ self.do('add process e+ e- > P')
3781+ self.assertEqual(len(self.cmd._curr_amps), 2)
3782+ self.do('add process mu+ mu- > P, Z>mu+mu-')
3783+ self.assertEqual(len(self.cmd._curr_amps), 3)
3784+
3785+ def test_draw(self):
3786+ """ command 'draw' works """
3787+
3788+ self.do('import model_v4 %s' % os.path.join(_pickle_path, \
3789+ 'v4_sm_particles.dat'))
3790+ self.do('import model_v4 %s' % os.path.join(_pickle_path, \
3791+ 'v4_sm_interactions.dat'))
3792+ self.do('load processes %s' % os.path.join(_pickle_path,'e+e-_e+e-.pkl'))
3793+ self.do('draw .')
3794+ self.assertTrue(os.path.exists('diagrams_0_e+e-_e+e-.eps'))
3795+ os.remove('diagrams_0_e+e-_e+e-.eps')
3796+
3797+ self.do('generate g g > g g')
3798+ self.do('draw .')
3799+ self.assertTrue(os.path.exists('diagrams_0_gg_gg.eps'))
3800+ os.remove('diagrams_0_gg_gg.eps')
3801+
3802+
3803+class TestCmdShell2(unittest.TestCase):
3804+ """The TestCase class for the test the FeynmanLine"""
3805+
3806+ def setUp(self):
3807+ """ basic building of the class to test """
3808+
3809+
3810+ self.cmd = Cmd.MadGraphCmdShell()
3811+ try:
3812+ self.out_dir = os.path.join(Cmd.MGME_dir, 'AUTO_TEST_MG5')
3813+ except:
3814+ raise Exception, 'NO MG_ME dir for this test'
3815+ self.do('import model_v4 sm')
3816+
3817+
3818+ def tearDown(self):
3819+ """ basic destruction after have run """
3820+ if os.path.exists(self.out_dir):
3821+ shutil.rmtree(self.out_dir)
3822+
3823+ def do(self, line):
3824+ """ exec a line in the cmd under test """
3825+ self.cmd.exec_cmd(line)
3826+
3827+
3828+ def test_standard_chain(self):
3829+ """ command 'setup' works with path"""
3830+
3831+
3832+ self.do('load processes %s' % os.path.join(_pickle_path,'e+e-_e+e-.pkl'))
3833+ self.do('setup madevent_v4 %s' % self.out_dir)
3834+ self.assertTrue(os.path.exists(self.out_dir))
3835+ self.do('export madevent_v4')
3836+ self.assertTrue(os.path.exists(os.path.join(self.out_dir,
3837+ 'SubProcesses', 'P0_e+e-_e+e-')))
3838+ self.do('history .')
3839+ self.assertTrue(os.path.exists(os.path.join(self.out_dir,
3840+ 'Cards', 'proc_card_mg5.dat')))
3841+
3842+ def test_chain2(self):
3843+ """ command 'setup' works with '.' """
3844+ os.system('cp -rf %s %s' % (os.path.join(Cmd.MGME_dir,'Template'),
3845+ self.out_dir))
3846+ os.system('cp -rf %s %s' % (
3847+ os.path.join(_pickle_path,'simple_v4_proc_card.dat'),
3848+ os.path.join(self.out_dir,'Cards','proc_card.dat')))
3849+
3850+ self.do('import proc_v4 %s' % os.path.join(self.out_dir,
3851+ 'Cards','proc_card.dat'))
3852+
3853+ self.assertTrue(os.path.exists(os.path.join(self.out_dir,
3854+ 'SubProcesses', 'P1_e-e+_vevex')))
3855+ self.assertTrue(os.path.exists(os.path.join(self.out_dir,
3856+ 'Cards', 'proc_card_mg5.dat')))
3857+
3858+
3859+ def test_chain3(self):
3860+ """ command 'setup' works with '.' """
3861+
3862+ self.do('setup madevent_v4 %s' % self.out_dir)
3863+ self.do('import proc_v4 %s' % os.path.join(_pickle_path, \
3864+ 'simple_v4_proc_card.dat'))
3865+ self.assertTrue(os.path.exists(os.path.join(self.out_dir,
3866+ 'SubProcesses', 'P1_e-e+_vevex')))
3867+ self.assertTrue(os.path.exists(os.path.join(self.out_dir,
3868+ 'Cards', 'proc_card_mg5.dat')))
3869+
3870
3871=== modified file 'tests/unit_tests/iolibs/test_drawing.py'
3872--- tests/unit_tests/iolibs/test_drawing.py 2010-05-11 13:07:02 +0000
3873+++ tests/unit_tests/iolibs/test_drawing.py 2010-05-19 07:36:39 +0000
3874@@ -1005,7 +1005,6 @@
3875 x_position = [1 / 3, 1 / 3, 2 / 3, 1 / 3, 0.0, 2 / 3, 0.0, 2 / 3, 1.0, 1.0]
3876 y_position = [1 / 6, 5 / 6, 1 / 2, 1 / 2, 0.0, 0.0, 1.0, 1.0, 0.0, 1.0]
3877
3878-
3879 for i in range(0, 10):
3880 self.assertEquals(self.mix_drawing.vertexList[i].level, \
3881 level[i])
3882
3883=== modified file 'tests/unit_tests/iolibs/test_import_v4.py'
3884--- tests/unit_tests/iolibs/test_import_v4.py 2010-05-07 13:47:25 +0000
3885+++ tests/unit_tests/iolibs/test_import_v4.py 2010-05-19 07:36:39 +0000
3886@@ -266,7 +266,6 @@
3887 #the initialization is done in the setUp subroutine
3888
3889 proccard = self.proccard
3890-
3891 self.assertEqual(len(proccard.process), 8)
3892 self.assertEqual(proccard.model, 'sm')
3893 self.assertEqual(len(proccard.multipart), 6)
3894@@ -283,7 +282,7 @@
3895 'define l- e- mu-',
3896 'define vl ve vm',
3897 'define vl~ ve~ vm~',
3898- 'generate p p > e- ve~ @1 ',
3899+ 'generate p p > ve~ e- @1 ',
3900 'add process p p > z @2 , (z > w+ w- , w- > mu- vm ) ',
3901 'add process p p > t t~ $ a QED=0 @3 ',
3902 'add process p p > t t~ $ g / a QED=0 @2 ',
3903@@ -294,7 +293,8 @@
3904 'setup madevent_v4 . -f',
3905 'export madevent_v4',
3906 'makehtml madevent_v4',
3907- 'history tests/Cards/proc_card_mg5.dat']
3908+ 'history .']
3909+
3910 self.assertEqual(len(lines),len(solution))
3911 for i,command in enumerate(lines):
3912 self.assertEqual(command,solution[i])

Subscribers

People subscribed via source and target branches