Merge lp:~madteam/mg5amcnlo/MG5_on_web into lp:~madteam/mg5amcnlo/trunk
- MG5_on_web
- Merge into trunk
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 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
MadTeam | Pending | ||
Review via email: mp+25285@code.launchpad.net |
Commit message
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://
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.
Johan Alwall (johan-alwall) wrote : | # |
Johan Alwall (johan-alwall) wrote : | # |
Hi again Olivier,
I tried choosing MG5 syntax, but also that went wrong, see
http://<email address hidden>
All the best,
Johan
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
- 140. By Olivier Mattelaer
-
correct bug when choosing mg5 format and specifying orders/decay chains
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>
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>
>>?
>>(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...
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>
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>
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>
>>>?
>
> This is quite strange... I'll take a look but I simply don't understand what happen...
Ok thanks!
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>
>>>?
>
> 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>
http://<email address hidden>
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)
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>
> http://<email address hidden>
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>
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
- 141. By Olivier Mattelaer
-
Correct the bug (and test) find by johan
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>
> 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
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>
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
- 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
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
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
- 144. By Olivier Mattelaer
-
wrong help 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
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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]) |
Hi Olivier!
This is really cool! Great job!
I made some tests, and have a few questions: /PROC11/ index.html
- What happened here:
http://<email address hidden>
?
(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