Merge lp:~maddevelopers/mg5amcnlo/plugin_mode into lp:~maddevelopers/mg5amcnlo/2.5.0
- plugin_mode
- Merge into 2.5.0
Status: | Merged |
---|---|
Merged at revision: | 287 |
Proposed branch: | lp:~maddevelopers/mg5amcnlo/plugin_mode |
Merge into: | lp:~maddevelopers/mg5amcnlo/2.5.0 |
Diff against target: |
9201 lines (+3074/-1601) 116 files modified
UpdateNotes.txt (+15/-0) VERSION (+1/-1) aloha/aloha_writers.py (+15/-16) aloha/template_files/ixxxxx.cc (+7/-7) aloha/template_files/oxxxxx.cc (+12/-12) aloha/template_files/txxxxx.cc (+5/-5) aloha/template_files/vxxxxx.cc (+7/-7) bin/mg5_aMC (+21/-4) madgraph/core/base_objects.py (+11/-7) madgraph/core/diagram_generation.py (+47/-5) madgraph/interface/amcatnlo_interface.py (+7/-4) madgraph/interface/amcatnlo_run_interface.py (+34/-4) madgraph/interface/common_run_interface.py (+276/-84) madgraph/interface/extended_cmd.py (+409/-28) madgraph/interface/loop_interface.py (+315/-17) madgraph/interface/madevent_interface.py (+6/-4) madgraph/interface/madgraph_interface.py (+257/-265) madgraph/interface/master_interface.py (+5/-3) madgraph/interface/reweight_interface.py (+3/-0) madgraph/iolibs/export_cpp.py (+461/-363) madgraph/iolibs/export_fks.py (+38/-6) madgraph/iolibs/export_v4.py (+379/-315) madgraph/iolibs/file_writers.py (+2/-1) madgraph/iolibs/group_subprocs.py (+2/-3) madgraph/iolibs/template_files/read_slha.cc (+24/-26) madgraph/iolibs/template_files/read_slha.h (+20/-18) madgraph/iolibs/ufo_expression_parsers.py (+12/-1) madgraph/loop/loop_diagram_generation.py (+4/-4) madgraph/loop/loop_exporters.py (+70/-57) madgraph/various/banner.py (+12/-5) madgraph/various/misc.py (+90/-8) madgraph/various/process_checks.py (+13/-21) models/__init__.py (+2/-2) models/check_param_card.py (+166/-29) models/import_ufo.py (+2/-2) models/model_reader.py (+19/-2) models/usermod.py (+33/-8) tests/IOTests.py (+3/-2) tests/acceptance_tests/test_cmd.py (+4/-1) tests/acceptance_tests/test_cmd_amcatnlo.py (+6/-1) tests/acceptance_tests/test_cmd_madevent.py (+80/-3) tests/acceptance_tests/test_export_fks.py (+23/-0) tests/acceptance_tests/test_output_files.py (+2/-2) tests/input_files/IOTestsComparison/IOExportFKSTest/test_ppw_fksall/%SubProcesses%P0_dxu_wp%V0_dxu_wp%COLLIER_interface.f (+2/-2) tests/input_files/IOTestsComparison/IOExportFKSTest/test_ppw_fksall/%SubProcesses%P0_dxu_wp%V0_dxu_wp%CT_interface.f (+4/-4) tests/input_files/IOTestsComparison/IOExportFKSTest/test_ppw_fksall/%SubProcesses%P0_dxu_wp%V0_dxu_wp%GOLEM_interface.f (+2/-2) tests/input_files/IOTestsComparison/IOExportFKSTest/test_ppw_fksall/%SubProcesses%P0_dxu_wp%V0_dxu_wp%TIR_interface.f (+4/-50) tests/input_files/IOTestsComparison/IOExportFKSTest/test_ppw_fksall/%SubProcesses%P0_dxu_wp%V0_dxu_wp%born_matrix.f (+4/-4) tests/input_files/IOTestsComparison/IOExportFKSTest/test_ppw_fksall/%SubProcesses%P0_dxu_wp%V0_dxu_wp%loop_matrix.f (+3/-3) tests/input_files/IOTestsComparison/IOExportFKSTest/test_ppw_fksall/%SubProcesses%P0_dxu_wp%V0_dxu_wp%mp_compute_loop_coefs.f (+2/-2) tests/input_files/IOTestsComparison/IOExportFKSTest/test_ppw_fksall/%SubProcesses%P0_udx_wp%V0_udx_wp%COLLIER_interface.f (+2/-2) tests/input_files/IOTestsComparison/IOExportFKSTest/test_ppw_fksall/%SubProcesses%P0_udx_wp%V0_udx_wp%CT_interface.f (+4/-4) tests/input_files/IOTestsComparison/IOExportFKSTest/test_ppw_fksall/%SubProcesses%P0_udx_wp%V0_udx_wp%GOLEM_interface.f (+2/-2) tests/input_files/IOTestsComparison/IOExportFKSTest/test_ppw_fksall/%SubProcesses%P0_udx_wp%V0_udx_wp%TIR_interface.f (+4/-50) tests/input_files/IOTestsComparison/IOExportFKSTest/test_ppw_fksall/%SubProcesses%P0_udx_wp%V0_udx_wp%born_matrix.f (+4/-4) tests/input_files/IOTestsComparison/IOExportFKSTest/test_ppw_fksall/%SubProcesses%P0_udx_wp%V0_udx_wp%loop_matrix.f (+3/-3) tests/input_files/IOTestsComparison/IOExportFKSTest/test_ppw_fksall/%SubProcesses%P0_udx_wp%V0_udx_wp%mp_compute_loop_coefs.f (+2/-2) tests/input_files/IOTestsComparison/IOExportFKSTest/test_tdecay_fksreal/%SubProcesses%P0_t_budx%matrix_1.f (+4/-4) tests/input_files/IOTestsComparison/IOExportFKSTest/test_tdecay_fksreal/%SubProcesses%P0_t_budx%parton_lum_1.f (+2/-2) tests/input_files/IOTestsComparison/LoopSquaredOrder_IOTest/Loop_sqso_uux_ddx/loop_matrix_QCDQEDpert_QCDsq_gt_0_QEDAmpAndQEDsq_gt_2.f (+1/-1) tests/input_files/IOTestsComparison/LoopSquaredOrder_IOTest/Loop_sqso_uux_ddx/loop_matrix_QCDQEDpert_WGTsq_le_10_QEDAmpAndQEDsq_gt_2.f (+1/-1) tests/input_files/IOTestsComparison/MECmdShell/check_html_long_process_strings/info.html (+2/-2) tests/input_files/IOTestsComparison/MadLoop_output_from_the_interface/TIR_output/%ggttx_IOTest%SubProcesses%MadLoopCommons.f (+3/-3) tests/input_files/IOTestsComparison/SquaredOrder_IOTest/sqso_uux_uuxuuxx/matrix_ampOrderQED2_eq_2_WGTsq_le_14_QCDsq_gt_4.f (+2/-2) tests/input_files/IOTestsComparison/long_ML_SMQCD_default/dux_mumvmxg/%..%..%Source%MODEL%couplings.f (+3/-3) tests/input_files/IOTestsComparison/long_ML_SMQCD_default/dux_mumvmxg/CT_interface.f (+1/-1) tests/input_files/IOTestsComparison/long_ML_SMQCD_default/dux_mumvmxg/born_matrix.f (+2/-2) tests/input_files/IOTestsComparison/long_ML_SMQCD_default/dux_mumvmxg/loop_matrix.f (+1/-1) tests/input_files/IOTestsComparison/long_ML_SMQCD_default/dux_mumvmxg/mp_born_amps_and_wfs.f (+1/-1) tests/input_files/IOTestsComparison/long_ML_SMQCD_default/gg_wmtbx/%..%..%Source%MODEL%couplings.f (+3/-3) tests/input_files/IOTestsComparison/long_ML_SMQCD_default/gg_wmtbx/CT_interface.f (+1/-1) tests/input_files/IOTestsComparison/long_ML_SMQCD_default/gg_wmtbx/born_matrix.f (+2/-2) tests/input_files/IOTestsComparison/long_ML_SMQCD_default/gg_wmtbx/loop_matrix.f (+1/-1) tests/input_files/IOTestsComparison/long_ML_SMQCD_default/gg_wmtbx/mp_born_amps_and_wfs.f (+1/-1) tests/input_files/IOTestsComparison/long_ML_SMQCD_optimized/dux_mumvmxg/%..%..%Source%MODEL%couplings.f (+3/-3) tests/input_files/IOTestsComparison/long_ML_SMQCD_optimized/dux_mumvmxg/CT_interface.f (+1/-1) tests/input_files/IOTestsComparison/long_ML_SMQCD_optimized/dux_mumvmxg/TIR_interface.f (+1/-1) tests/input_files/IOTestsComparison/long_ML_SMQCD_optimized/dux_mumvmxg/born_matrix.f (+2/-2) tests/input_files/IOTestsComparison/long_ML_SMQCD_optimized/dux_mumvmxg/loop_matrix.f (+1/-1) tests/input_files/IOTestsComparison/long_ML_SMQCD_optimized/dux_mumvmxg/mp_compute_loop_coefs.f (+1/-1) tests/input_files/IOTestsComparison/long_ML_SMQCD_optimized/gg_wmtbx/%..%..%Source%MODEL%couplings.f (+3/-3) tests/input_files/IOTestsComparison/long_ML_SMQCD_optimized/gg_wmtbx/CT_interface.f (+1/-1) tests/input_files/IOTestsComparison/long_ML_SMQCD_optimized/gg_wmtbx/TIR_interface.f (+1/-1) tests/input_files/IOTestsComparison/long_ML_SMQCD_optimized/gg_wmtbx/born_matrix.f (+2/-2) tests/input_files/IOTestsComparison/long_ML_SMQCD_optimized/gg_wmtbx/loop_matrix.f (+1/-1) tests/input_files/IOTestsComparison/long_ML_SMQCD_optimized/gg_wmtbx/mp_compute_loop_coefs.f (+1/-1) tests/input_files/IOTestsComparison/short_ML_SMQCD_LoopInduced/gg_hh/%..%..%Source%MODEL%couplings.f (+3/-3) tests/input_files/IOTestsComparison/short_ML_SMQCD_LoopInduced/gg_hh/CT_interface.f (+1/-1) tests/input_files/IOTestsComparison/short_ML_SMQCD_LoopInduced/gg_hh/loop_matrix.f (+1/-1) tests/input_files/IOTestsComparison/short_ML_SMQCD_LoopInduced/gg_hh/mp_born_amps_and_wfs.f (+1/-1) tests/input_files/IOTestsComparison/short_ML_SMQCD_default/ddx_ttx/CT_interface.f (+1/-1) tests/input_files/IOTestsComparison/short_ML_SMQCD_default/ddx_ttx/born_matrix.f (+2/-2) tests/input_files/IOTestsComparison/short_ML_SMQCD_default/ddx_ttx/loop_matrix.f (+1/-1) tests/input_files/IOTestsComparison/short_ML_SMQCD_default/ddx_ttx/mp_born_amps_and_wfs.f (+1/-1) tests/input_files/IOTestsComparison/short_ML_SMQCD_default/gg_ttx/%..%..%Source%MODEL%couplings.f (+3/-3) tests/input_files/IOTestsComparison/short_ML_SMQCD_default/gg_ttx/CT_interface.f (+1/-1) tests/input_files/IOTestsComparison/short_ML_SMQCD_default/gg_ttx/born_matrix.f (+2/-2) tests/input_files/IOTestsComparison/short_ML_SMQCD_default/gg_ttx/loop_matrix.f (+1/-1) tests/input_files/IOTestsComparison/short_ML_SMQCD_default/gg_ttx/mp_born_amps_and_wfs.f (+1/-1) tests/input_files/IOTestsComparison/short_ML_SMQCD_optimized/ddx_ttx/CT_interface.f (+1/-1) tests/input_files/IOTestsComparison/short_ML_SMQCD_optimized/ddx_ttx/TIR_interface.f (+1/-1) tests/input_files/IOTestsComparison/short_ML_SMQCD_optimized/ddx_ttx/born_matrix.f (+2/-2) tests/input_files/IOTestsComparison/short_ML_SMQCD_optimized/ddx_ttx/loop_matrix.f (+1/-1) tests/input_files/IOTestsComparison/short_ML_SMQCD_optimized/ddx_ttx/mp_compute_loop_coefs.f (+1/-1) tests/input_files/IOTestsComparison/short_ML_SMQCD_optimized/gg_ttx/%..%..%Source%MODEL%couplings.f (+3/-3) tests/input_files/IOTestsComparison/short_ML_SMQCD_optimized/gg_ttx/CT_interface.f (+1/-1) tests/input_files/IOTestsComparison/short_ML_SMQCD_optimized/gg_ttx/TIR_interface.f (+1/-1) tests/input_files/IOTestsComparison/short_ML_SMQCD_optimized/gg_ttx/born_matrix.f (+2/-2) tests/input_files/IOTestsComparison/short_ML_SMQCD_optimized/gg_ttx/loop_matrix.f (+1/-1) tests/input_files/IOTestsComparison/short_ML_SMQCD_optimized/gg_ttx/mp_compute_loop_coefs.f (+1/-1) tests/unit_tests/core/test_base_objects.py (+1/-1) tests/unit_tests/iolibs/test_export_cpp.py (+22/-22) tests/unit_tests/iolibs/test_export_v4.py (+0/-2) tests/unit_tests/iolibs/test_link_to_ufo.py (+1/-1) tests/unit_tests/loop/test_loop_exporters.py (+3/-3) tests/unit_tests/madweight/test_export_v4.py (+2/-2) |
To merge this branch: | bzr merge lp:~maddevelopers/mg5amcnlo/plugin_mode |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Valentin Hirschi | Approve | ||
Rikkert Frederix | Abstain | ||
marco zaro | Pending | ||
Review via email: mp+302218@code.launchpad.net |
This proposal supersedes a proposal from 2016-06-20.
Commit message
Description of the change
Hi Guys,
Just changing the target branch for this branch to 2.5.0.
For information I would like to have a freeze version of 2.5.0 the first week of September.
Such that we can play with it for a couple of weeks before releasing it a bit later.
So it would be great if we can move forward on this review (was proposed 2 month ago...)
If you do not want to review this, please abstain.
Cheers,
Olivier
Previous information on the merge request:
This is deep branch which only need to be merged in the next feature release (2.5.0 with collier/PY8)
I propose this for the next bug fixing release (2.4.3) just such that we can move forward on this review.
The changes are pretty simple but at the same time pretty deep.
This version has a new directory PLUGIN where the user can put code to modify the behavior of the code (mainly LO so far).
Three types of plugin can be created:
1) code adding/modifying command to the interface [need to run MG5aMC with ./bin/mg5_aMC --mode=PLUGINNAME]
This is a mode which is going to be used by maddm for example
2) code defining one (or more) new output mode.
This is a mode which is used by the MoMenta code (a C++ version of MadWeight develloped in CP3)
This mode does not need any special command.
just the usual "output MODE PATH" [where MODE correspond to one of the keyword defined in the plugin]
3) code defining a new/modifying the cluster support
(just set cluster_type NAME)
So Nothing deep in term of functionality, but it required to re-factorise part of the code in order to have a uniform way to handle the various output mode that we are supporting internally so far.
The details on how to create one of those plugin are available here:
https:/
Cheers,
Olivier
PS: Valentin if you want to open such plugin idea to MadLoop. This is of course possible.
Olivier Mattelaer (olivier-mattelaer) wrote : | # |
Hi Rik,
> I've got a question, though. There seems to be many little changes in vendor/IREGI and vendor/Cuttools. Why? It doesn’t seem related to this branch.
This branch also contains the latest version of 2.4.3 which are missing in 2.5.0.
This should explain those differences (I never touch expel. Valentin can you cross-check those differences?
Cheers,
Olivier
> On Aug 8, 2016, at 08:39, Rikkert Frederix <email address hidden> wrote:
>
> Review: Abstain
>
> Hi Olivier,
>
> I don't think I'm the right person for this review.
> I've got a question, though. There seems to be many little changes in vendor/IREGI and vendor/Cuttools. Why? It doesn't seem related to this branch.
>
> Best,
> Rikkert
>
> --
> https:/
> Your team MadDevelopers is subscribed to branch lp:~maddevelopers/mg5amcnlo/2.5.0.
- 432. By Valentin Hirschi
-
1. Restored the correct version of CutTools and IREGI which links against
their own version of OneLOop with a dedicated namespace. - 433. By Olivier Mattelaer
-
fix a problem with the computation of the dependent parameter in presence of scan/width computation
- 434. By Olivier Mattelaer
-
merge with branch question_
for_reduction_ tools_installat ion - 435. By Olivier Mattelaer
-
re-allow the Auto in the reweight_card
Valentin Hirschi (valentin-hirschi) wrote : | # |
Hi Olivier,
This is a great functionality, especially for the longer term! And if people use it and if there is a clear case for it, we will/should do this as well for NLO/MadLoop indeed.
I tried the examples and it seems to works fine. I would have to develop my own real non-trivial plugin to unravel potential problems, so I only have the following superficial remarks here:
a) For the interface plugin it would be cool if the prompt reflected which plugin the user is in (actually the prompt could be an attribute of the plugin, and if absent it is by default its name).
Maybe also mention on the wiki that people can define their own functions 'complete_
b) For the output plugin, it would be nice if the user could also redefine what 'launch' does. For now the plugin user simply cannot launch on his own output.
c) I has already tested the cluster type of plugin with my implementation for the SLAC-lsf one, and you had fixed what I had noticed as not working, so this should be fine now.
d) Suggestion: It would be interesting to see if you could also automatically "install" a plugin from a repository somewhere.
So basically implement the command 'install --plugin=
This command would look up the repository if the folder '<plugin_name>' exists on the repo and copy it locally in PLUGIN if it does.
e) You should maybe update the wiki page so as to describe the basic plugin 'user_filter.py'.
From the code standpoint, here are my also superficial remarks:
1) Out of curiosity, why was 'using namespace std' not OK for the C++ output?
2) What is the new 'partial_save' of the MG5aMC options?
3) Could we have the plugin user_filter also work for the loops? I can help with this.
If I were to check more detailed things in the code, I'd rather do it live on skype as it is more efficient this way.
Anyway, none of the above is crucial and the unit tests pass (acceptance running now, but so far they're fine).
I therefore accept the merge.
Valentin Hirschi (valentin-hirschi) wrote : | # |
Approved
Sébastien Wertz (sebastien-wertz) wrote : | # |
> I tried the examples and it seems to works fine. I would have to develop my
> own real non-trivial plugin to unravel potential problems, so I only have the
> following superficial remarks here:
> 1) Out of curiosity, why was 'using namespace std' not OK for the C++ output?
Hi Valentin,
If you want to check a "non-trivial" plugin, you can always try out the C++ one we've written for the MEM: https:/
Regarding the 'using namespace' statements in C++, it's a problem if they are used in header files: any code directly or indirectly including those headers will get polluted by the namespace, which can cause collisions. Those statements should always only be included in non-header files.
Cheers,
Sébastien
Olivier Mattelaer (olivier-mattelaer) wrote : | # |
Thanks a lot for this review
> a) For the interface plugin it would be cool if the prompt reflected which
> plugin the user is in (actually the prompt could be an attribute of the
> plugin, and if absent it is by default its name).
sounds too complicated.
> Maybe also mention on the wiki that people can define their own functions
> 'complete_
> the example helloworld.
Done
> b) For the output plugin, it would be nice if the user could also redefine
> what 'launch' does. For now the plugin user simply cannot launch on his own
> output.
Hum for the moment, I would see that as part of the interface plugin.
I also guess that they are less interest since the idea is typically to run externally to MGaMC
> d) Suggestion: It would be interesting to see if you could also automatically
> "install" a plugin from a repository somewhere.
> So basically implement the command 'install --plugin=
> madgraph_interface.
> This command would look up the repository if the folder '<plugin_name>' exists
> on the repo and copy it locally in PLUGIN if it does.
I agree on the interest. So far no one really show interest in that direction.
If this happens then yes this can be done.
> e) You should maybe update the wiki page so as to describe the basic plugin
> 'user_filter.py'.
This is not really a plugin.
I have create another page for it (under the FAQ of the wiki)
https:/
> 2) What is the new 'partial_save' of the MG5aMC options?
Now you can do command like
save options collier
and only collier value will be modified in the mg5_configurati
> 3) Could we have the plugin user_filter also work for the loops? I can help
> with this.
This should be trivial.
But with the level of your loop_filter, I guess that you will want something more refined than my dummy method. If you need help tell me.
> Anyway, none of the above is crucial and the unit tests pass (acceptance
> running now, but so far they're fine).
>
> I therefore accept the merge.
Great thanks.
Cheers,
Olivier
PS: Marco do you plan to review this branch? If not I plan to merge it on Monday. I can obviously wait if you want to take a look.
Preview Diff
1 | === added directory 'PLUGIN' |
2 | === added file 'PLUGIN/__init__.py' |
3 | === modified file 'UpdateNotes.txt' |
4 | --- UpdateNotes.txt 2016-08-01 10:08:21 +0000 |
5 | +++ UpdateNotes.txt 2016-08-18 22:31:39 +0000 |
6 | @@ -1,5 +1,20 @@ |
7 | Update notes for MadGraph5_aMC@NLO (in reverse time order) |
8 | |
9 | +2.5.0 |
10 | + OM: Modify the structure of the output format such that all the internal format have the same structure |
11 | + OM: Adding the Plugin directory. Three kind of plugin are currently supported |
12 | + - plugin defining a new type of output format |
13 | + - plugin defining a new type of cluster handling |
14 | + - plugin modifying the main interface of MG5aMCnlo |
15 | + More informations/examples are available here: |
16 | + https://cp3.irmp.ucl.ac.be/projects/madgraph/wiki/Plugin |
17 | + VH: adding the possibility to install COLLIER and to use it to reduce the loop-matrix element |
18 | + OM+VH: At the first loop/NLO computation, a new question will now be asked to choose which program |
19 | + to install to compute the loop. You can still install additional method later via the "install" command |
20 | + OM: add an automatic update of the param_card to write the correct value for all dependent parameter. |
21 | + OM: add the check that the param_card is compatible with the model restriction. |
22 | + OM+VH: |
23 | + |
24 | 2.4.3 (01/08/16) |
25 | OM: Reduce the amount of log file/output generated for LO run (output can use up to three times less output). |
26 | OM: For the LO combination of events (unweighting) pass to the method previously used for loop-induced. |
27 | |
28 | === modified file 'VERSION' |
29 | --- VERSION 2016-08-01 10:08:21 +0000 |
30 | +++ VERSION 2016-08-18 22:31:39 +0000 |
31 | @@ -1,4 +1,4 @@ |
32 | -version = 2.4.3 |
33 | +version = 2.5.0.alpha |
34 | date = 2016-08-01 |
35 | |
36 | |
37 | |
38 | === modified file 'aloha/aloha_writers.py' |
39 | --- aloha/aloha_writers.py 2016-07-06 08:54:04 +0000 |
40 | +++ aloha/aloha_writers.py 2016-08-18 22:31:39 +0000 |
41 | @@ -468,10 +468,10 @@ |
42 | 'log': 'log(dble(%s))', |
43 | 'asin': 'asin(dble(%s))', |
44 | 'acos': 'acos(dble(%s))', |
45 | - 'abs': 'abs(%s)', |
46 | - 'fabs': 'abs(%s)', |
47 | - 'math.abs': 'abs(%s)', |
48 | - 'cmath.abs': 'abs(%s)', |
49 | + 'abs': 'std::abs(%s)', |
50 | + 'fabs': 'std::abs(%s)', |
51 | + 'math.abs': 'std::abs(%s)', |
52 | + 'cmath.abs': 'std::abs(%s)', |
53 | '':'(%s)' |
54 | } |
55 | |
56 | @@ -1255,14 +1255,14 @@ |
57 | writer = writers.CPPWriter |
58 | |
59 | type2def = {} |
60 | - type2def['int'] = 'int' |
61 | + type2def['int'] = 'int ' |
62 | type2def['double'] = 'double ' |
63 | - type2def['complex'] = 'complex<double> ' |
64 | + type2def['complex'] = 'std::complex<double> ' |
65 | |
66 | #variable overwritten by gpu |
67 | realoperator = '.real()' |
68 | imagoperator = '.imag()' |
69 | - ci_definition = ' complex<double> cI = complex<double>(0.,1.);\n' |
70 | + ci_definition = 'static std::complex<double> cI = std::complex<double>(0.,1.);\n' |
71 | |
72 | |
73 | def change_number_format(self, number): |
74 | @@ -1335,7 +1335,7 @@ |
75 | 'sqrt': 'sqrt(%s)', |
76 | 'complexconjugate': 'conj(dcmplx(%s))', |
77 | '/' : '{0}/%s'.format(one), |
78 | - 'abs': 'abs(%s)' |
79 | + 'abs': 'std::abs(%s)' |
80 | } |
81 | |
82 | if fct in self.fct_format: |
83 | @@ -1375,10 +1375,10 @@ |
84 | args.append('%s%s%s'% (type, argname, list_arg)) |
85 | |
86 | if not self.offshell: |
87 | - output = 'complex<double> & vertex' |
88 | + output = 'std::complex<double> & vertex' |
89 | #self.declaration.add(('complex','vertex')) |
90 | else: |
91 | - output = 'complex<double> %(spin)s%(id)d[]' % { |
92 | + output = 'std::complex<double> %(spin)s%(id)d[]' % { |
93 | 'spin': self.particles[self.outgoing -1], |
94 | 'id': self.outgoing} |
95 | self.declaration.add(('list_complex', output)) |
96 | @@ -1450,7 +1450,7 @@ |
97 | |
98 | for i,type in enumerate(self.particles): |
99 | if self.declaration.is_used('OM%s' % (i+1)): |
100 | - out.write(" OM{0} = {1};\n if (M{0} != {1})\n OM{0}={2}/pow(M{0},2);\n".format( |
101 | + out.write(" OM{0} = {1};\n if (M{0} != {1})\n OM{0}={2}/(M{0}*M{0});\n".format( |
102 | i+1, self.change_number_format(0), self.change_number_format(1))) |
103 | |
104 | if i+1 == self.outgoing: |
105 | @@ -1551,13 +1551,13 @@ |
106 | out.write(' denom = %(COUP)s/(%(denom)s)\n' % {'COUP': coup_name,\ |
107 | 'denom':self.write_obj(self.routine.denominator)}) |
108 | else: |
109 | - out.write(' denom = %(coup)s/(pow(P%(i)s[0],2)-pow(P%(i)s[1],2)-pow(P%(i)s[2],2)-pow(P%(i)s[3],2) - M%(i)s * (M%(i)s -cI* W%(i)s));\n' % \ |
110 | + out.write(' denom = %(coup)s/((P%(i)s[0]*P%(i)s[0])-(P%(i)s[1]*P%(i)s[1])-(P%(i)s[2]*P%(i)s[2])-(P%(i)s[3]*P%(i)s[3]) - M%(i)s * (M%(i)s -cI* W%(i)s));\n' % \ |
111 | {'i': self.outgoing, 'coup': coup_name}) |
112 | else: |
113 | if self.routine.denominator: |
114 | raise Exception, 'modify denominator are not compatible with complex mass scheme' |
115 | |
116 | - out.write(' denom = %(coup)s/(pow(P%(i)s[0],2)-pow(P%(i)s[1],2)-pow(P%(i)s[2],2)-pow(P%(i)s[3],2) - pow(M%(i)s,2));\n' % \ |
117 | + out.write(' denom = %(coup)s/((P%(i)s[0]*P%(i)s[0])-(P%(i)s[1]*P%(i)s[1])-(P%(i)s[2]*P%(i)s[2])-(P%(i)s[3]*P%(i)s[3]) - (M%(i)s*M%(i)s));\n' % \ |
118 | {'i': self.outgoing, 'coup': coup_name}) |
119 | self.declaration.add(('complex','denom')) |
120 | if aloha.loop_mode: |
121 | @@ -1574,7 +1574,7 @@ |
122 | self.write_obj(numerator.get_rep(ind)))) |
123 | return out.getvalue() |
124 | |
125 | - remove_double = re.compile('complex<double> (?P<name>[\w]+)\[\]') |
126 | + remove_double = re.compile('std::complex<double> (?P<name>[\w]+)\[\]') |
127 | def define_symmetry(self, new_nb, couplings=None): |
128 | """Write the call for symmetric routines""" |
129 | number = self.offshell |
130 | @@ -1594,8 +1594,7 @@ |
131 | if not self.mode == 'no_include': |
132 | h_string.write('#ifndef '+ self.name + '_guard\n') |
133 | h_string.write('#define ' + self.name + '_guard\n') |
134 | - h_string.write('#include <complex>\n') |
135 | - h_string.write('using namespace std;\n\n') |
136 | + h_string.write('#include <complex>\n\n') |
137 | |
138 | h_header = self.get_header_txt(mode='no_include__is_h', couplings=couplings) |
139 | h_string.write(h_header) |
140 | |
141 | === modified file 'aloha/template_files/ixxxxx.cc' |
142 | --- aloha/template_files/ixxxxx.cc 2012-06-13 16:40:13 +0000 |
143 | +++ aloha/template_files/ixxxxx.cc 2016-08-18 22:31:39 +0000 |
144 | @@ -10,9 +10,9 @@ |
145 | fi[1] = complex<double> (-p[1]*nsf,-p[2]*nsf); |
146 | nh = nhel*nsf; |
147 | if (fmass != 0.0) { |
148 | - pp = min(p[0],pow((pow(p[1],2)+pow(p[2],2)+pow(p[3],2)),0.5)); |
149 | + pp = min(p[0],sqrt(p[1]*p[1]+p[2]*p[2]+p[3]*p[3])); |
150 | if (pp == 0.0){ |
151 | - sqm[0] = pow(abs(fmass),0.5); |
152 | + sqm[0] = sqrt(std::abs(fmass)); |
153 | sqm[1] = Sgn(sqm[0],fmass); |
154 | ip = (1+nh)/2; |
155 | im = (1-nh)/2; |
156 | @@ -24,19 +24,19 @@ |
157 | else{ |
158 | sf[0] = (1+nsf+(1-nsf)*nh)*0.5; |
159 | sf[1] = (1+nsf-(1-nsf)*nh)*0.5; |
160 | - omega[0] = pow(p[0]+pp,0.5); |
161 | + omega[0] = sqrt(p[0]+pp); |
162 | omega[1] = fmass/omega[0]; |
163 | ip = (1+nh)/2; |
164 | im = (1-nh)/2; |
165 | sfomega[0] = sf[0]*omega[ip]; |
166 | sfomega[1] = sf[1]*omega[im]; |
167 | pp3 = max(pp+p[3], 0.0); |
168 | - chi[0] = complex<double>(pow(pp3*0.5/pp,0.5),0); |
169 | + chi[0] = complex<double>(sqrt(pp3*0.5/pp),0); |
170 | if (pp3 == 0.0){ |
171 | chi[1] = complex<double> (-nh,0); |
172 | } |
173 | else{ |
174 | - chi[1] = complex<double> (nh*p[1],p[2])/pow(2.0*pp*pp3,0.5); |
175 | + chi[1] = complex<double> (nh*p[1],p[2])/sqrt(2.0*pp*pp3); |
176 | } |
177 | fi[2] = sfomega[0]*chi[im]; |
178 | fi[3] = sfomega[0]*chi[ip]; |
179 | @@ -49,10 +49,10 @@ |
180 | sqp0p3 = 0.0; |
181 | } |
182 | else{ |
183 | - sqp0p3 = pow(max(p[0]+p[3],0.0),0.5)*nsf;} |
184 | + sqp0p3 = sqrt(max(p[0]+p[3],0.0))*nsf;} |
185 | chi[0] = complex<double>(sqp0p3,0.0); |
186 | if (sqp0p3 ==0.0){ |
187 | - chi[1] = complex<double>(-nhel*pow(2.0*p[0],0.5),0.0);} |
188 | + chi[1] = complex<double>(-nhel*sqrt(2.0*p[0]),0.0);} |
189 | else{ |
190 | chi[1] = complex<double>(nh*p[1],p[2])/sqp0p3;} |
191 | if (nh == 1) { |
192 | |
193 | === modified file 'aloha/template_files/oxxxxx.cc' |
194 | --- aloha/template_files/oxxxxx.cc 2013-06-06 13:29:17 +0000 |
195 | +++ aloha/template_files/oxxxxx.cc 2016-08-18 22:31:39 +0000 |
196 | @@ -10,34 +10,34 @@ |
197 | fo[1] = complex<double>(p[1]*nsf,p[2]*nsf); |
198 | nh = nhel*nsf; |
199 | if (fmass != 0.000){ |
200 | - pp = min(p[0],pow(pow(p[1],2)+pow(p[2],2)+pow(p[3],2),0.5)); |
201 | + pp = min(p[0],sqrt((p[1]*p[1])+(p[2]*p[2])+(p[3]*p[3]))); |
202 | if (pp == 0.000){ |
203 | - sqm[0] = pow(abs(fmass),0.5); |
204 | + sqm[0] = sqrt(std::abs(fmass)); |
205 | sqm[1] = Sgn(sqm[0],fmass); |
206 | ip = -((1-nh)/2) * nhel ; |
207 | im = (1+nh)/2 * nhel; |
208 | - fo[2] = im *sqm[abs(ip)]; |
209 | - fo[3] = ip*nsf*sqm[abs(ip)]; |
210 | - fo[4] = im*nsf*sqm[abs(im)]; |
211 | - fo[5] = ip*sqm[abs(im)]; |
212 | + fo[2] = im *sqm[std::abs(ip)]; |
213 | + fo[3] = ip*nsf*sqm[std::abs(ip)]; |
214 | + fo[4] = im*nsf*sqm[std::abs(im)]; |
215 | + fo[5] = ip*sqm[std::abs(im)]; |
216 | } |
217 | else{ |
218 | - pp = min(p[0],pow(pow(p[1],2)+pow(p[2],2)+pow(p[3],2),0.5)); |
219 | + pp = min(p[0],sqrt((p[1]*p[1])+(p[2]*p[2])+(p[3]*p[3]))); |
220 | sf[0] = double(1+nsf+(1-nsf)*nh)*0.5; |
221 | sf[1] = double(1+nsf-(1-nsf)*nh)*0.5; |
222 | - omega[0] = pow(p[0]+pp,0.5); |
223 | + omega[0] = sqrt(p[0]+pp); |
224 | omega[1] = fmass/omega[0]; |
225 | ip = (1+nh)/2 ; |
226 | im = (1-nh)/2 ; |
227 | sfomeg[0] = sf[0]*omega[ip]; |
228 | sfomeg[1] = sf[1]*omega[im]; |
229 | pp3 = max(pp+p[3],0.00); |
230 | - chi[0] = complex<double>(pow(pp3*0.5/pp,0.5),0.00); |
231 | + chi[0] = complex<double>(sqrt(pp3*0.5/pp),0.00); |
232 | if (pp3 == 0.00){ |
233 | chi[1] = complex<double>(-nh,0.00); |
234 | } |
235 | else{ |
236 | - chi[1] = complex<double>(nh*p[1],-p[2])/pow(2.0*pp*pp3,0.5); |
237 | + chi[1] = complex<double>(nh*p[1],-p[2])/sqrt(2.0*pp*pp3); |
238 | } |
239 | fo[2] = sfomeg[1]*chi[im]; |
240 | fo[3] = sfomeg[1]*chi[ip]; |
241 | @@ -50,11 +50,11 @@ |
242 | sqp0p3 = 0.00; |
243 | } |
244 | else{ |
245 | - sqp0p3 = pow(max(p[0]+p[3],0.00),0.5)*nsf; |
246 | + sqp0p3 = sqrt(max(p[0]+p[3],0.00))*nsf; |
247 | } |
248 | chi[0] = complex<double>(sqp0p3,0.00); |
249 | if(sqp0p3 == 0.000){ |
250 | - chi[1] = complex<double>(-nhel,0.00)*pow(2.0*p[0],0.5); |
251 | + chi[1] = complex<double>(-nhel,0.00)*sqrt(2.0*p[0]); |
252 | } |
253 | else{ |
254 | chi[1] = complex<double>(nh*p[1],-p[2])/sqp0p3; |
255 | |
256 | === modified file 'aloha/template_files/txxxxx.cc' |
257 | --- aloha/template_files/txxxxx.cc 2013-05-07 06:35:39 +0000 |
258 | +++ aloha/template_files/txxxxx.cc 2016-08-18 22:31:39 +0000 |
259 | @@ -11,12 +11,12 @@ |
260 | double pt, pt2, pp, pzpt, emp, sqh, sqs; |
261 | int i, j; |
262 | |
263 | - sqh = pow( 0.5, 0.5 ); |
264 | - sqs = pow( 0.5/3, 0.5 ); |
265 | + sqh = sqrt( 0.5); |
266 | + sqs = sqrt( 0.5/3); |
267 | |
268 | pt2 = p[1]*p[1] + p[2]*p[2]; |
269 | - pp = min( p[0], pow( pt2+p[3]*p[3], 0.5 ) ); |
270 | - pt = min( pp, pow( pt2, 0.5 ) ); |
271 | + pp = min( p[0], sqrt( pt2+p[3]*p[3]) ); |
272 | + pt = min( pp, sqrt( pt2) ); |
273 | |
274 | ft[4][0] = complex<double>( p[0]*nst, p[3]*nst ); |
275 | ft[5][0] = complex<double>( p[1]*nst, p[2]*nst ); |
276 | @@ -81,7 +81,7 @@ |
277 | } |
278 | |
279 | // construct eps0 |
280 | - if( fabs(nhel) <= 1 ) |
281 | + if( std::labs(nhel) <= 1 ) |
282 | { |
283 | if( pp == 0 ) |
284 | { |
285 | |
286 | === modified file 'aloha/template_files/vxxxxx.cc' |
287 | --- aloha/template_files/vxxxxx.cc 2012-06-13 16:40:13 +0000 |
288 | +++ aloha/template_files/vxxxxx.cc 2016-08-18 22:31:39 +0000 |
289 | @@ -5,16 +5,16 @@ |
290 | void vxxxxx(double p[4],double vmass,int nhel,int nsv, complex<double> vc[6]){ |
291 | double hel,hel0,pt,pt2,pp,pzpt,emp,sqh; |
292 | int nsvahl; |
293 | - sqh = pow(0.5,0.5); |
294 | + sqh = sqrt(0.5); |
295 | hel = double(nhel); |
296 | - nsvahl = nsv*abs(hel); |
297 | - pt2 = pow(p[1],2)+pow(p[2],2); |
298 | - pp = min(p[0],pow(pt2+pow(p[3],2),0.5)); |
299 | - pt =min(pp,pow(pt2,0.5)); |
300 | + nsvahl = nsv*std::abs(hel); |
301 | + pt2 = (p[1]*p[1])+(p[2]*p[2]); |
302 | + pp = min(p[0],sqrt(pt2+(p[3]*p[3]))); |
303 | + pt =min(pp,sqrt(pt2)); |
304 | vc[0] = complex<double>(p[0]*nsv,p[3]*nsv); |
305 | vc[1] = complex<double>(p[1]*nsv,p[2]*nsv); |
306 | if (vmass != 0.0){ |
307 | - hel0 = 1.0-abs(hel); |
308 | + hel0 = 1.0-std::abs(hel); |
309 | if( pp == 0.0 ){ |
310 | vc[2] = complex<double>(0.0,0.0); |
311 | vc[3] = complex<double>(-hel*sqh,0.0); |
312 | @@ -38,7 +38,7 @@ |
313 | } |
314 | else{ |
315 | pp = p[0]; |
316 | - pt = pow(pow(p[1],2)+pow(p[2],2),0.5); |
317 | + pt = sqrt((p[1]*p[1])+(p[2]*p[2])); |
318 | vc[2] = complex<double>(0.0,0.0); |
319 | vc[5] = complex<double>(hel*pt/pp*sqh,0.0); |
320 | if (pt != 0.0) { |
321 | |
322 | === modified file 'bin/mg5_aMC' |
323 | --- bin/mg5_aMC 2016-03-03 16:31:52 +0000 |
324 | +++ bin/mg5_aMC 2016-08-18 22:31:39 +0000 |
325 | @@ -45,6 +45,9 @@ |
326 | help='force to be in secure mode') |
327 | parser.add_option("","--debug", action="store_true", default=False, dest='debug', \ |
328 | help='force to launch debug mode') |
329 | +parser.add_option("-m", "--mode", dest="plugin", |
330 | + help="Define some additional command provide by a PLUGIN") |
331 | + |
332 | (options, args) = parser.parse_args() |
333 | if len(args) == 0: |
334 | args = '' |
335 | @@ -119,6 +122,24 @@ |
336 | pass |
337 | import madgraph.interface.master_interface as interface |
338 | |
339 | +if options.plugin: |
340 | + if not os.path.exists(os.path.join(root_path, 'PLUGIN', options.plugin)): |
341 | + print "ERROR: %s is not present in the PLUGIN directory. Please install it first" |
342 | + __import__('PLUGIN.%s' % options.plugin) |
343 | + plugin = sys.modules['PLUGIN.%s' % options.plugin] |
344 | + if not plugin.new_interface: |
345 | + logging.warning("Plugin: %s do not define dedicated interface and should be used without the --mode options" % options.plugin) |
346 | + sys.exit() |
347 | + import madgraph.various.misc as misc |
348 | + if not misc.is_plugin_supported(plugin): |
349 | + sys.exit() |
350 | + cmd_line = plugin.new_interface(mgme_dir = options.mgme_dir) |
351 | + cmd_line.plugin=options.plugin |
352 | +elif options.web: |
353 | + cmd_line = interface.MasterCmdWeb() |
354 | +else: |
355 | + cmd_line = interface.MasterCmd(mgme_dir = options.mgme_dir) |
356 | + |
357 | # Call the cmd interface main loop |
358 | try: |
359 | if options.file or args: |
360 | @@ -128,14 +149,12 @@ |
361 | else: |
362 | input_file = os.path.realpath(options.file) |
363 | if options.web: |
364 | - cmd_line = interface.MasterCmdWeb() |
365 | cmd_line.debug_output = os.path.join(os.path.dirname(input_file),'generation.log') |
366 | cmd_line.use_rawinput = False |
367 | cmd_line.haspiping = False |
368 | cmd_line.run_cmd('import ' + input_file) |
369 | cmd_line.run_cmd('quit') |
370 | else: |
371 | - cmd_line = interface.MasterCmd(mgme_dir = options.mgme_dir) |
372 | cmd_line.use_rawinput = False |
373 | cmd_line.haspiping = False |
374 | cmd_line.run_cmd('import ' + input_file) |
375 | @@ -147,10 +166,8 @@ |
376 | os.environ['MADGRAPH_DATA'] = root_path |
377 | os.environ['MADGRAPH_BASE'] = os.path.join(root_path,'input') |
378 | os.environ['REMOTE_USER'] = 'webmode' |
379 | - cmd_line = interface.MasterCmdWeb() |
380 | cmd_line.cmdloop() |
381 | else: |
382 | - cmd_line = interface.MasterCmd(mgme_dir = options.mgme_dir) |
383 | cmd_line.cmdloop() |
384 | except KeyboardInterrupt: |
385 | print 'writting history and quit on KeyboardInterrupt' |
386 | |
387 | === modified file 'madgraph/core/base_objects.py' |
388 | --- madgraph/core/base_objects.py 2016-08-14 00:17:23 +0000 |
389 | +++ madgraph/core/base_objects.py 2016-08-18 22:31:39 +0000 |
390 | @@ -1587,15 +1587,19 @@ |
391 | return [c for c in range(1, len(self.get('particles')) + 1) if \ |
392 | c not in self.get('particle_dict').keys()][0] |
393 | |
394 | - def write_param_card(self): |
395 | + def write_param_card(self, filepath=None): |
396 | """Write out the param_card, and return as string.""" |
397 | |
398 | import models.write_param_card as writer |
399 | - out = StringIO.StringIO() # it's suppose to be written in a file |
400 | - param = writer.ParamCardWriter(self) |
401 | - param.define_output_file(out) |
402 | - param.write_card() |
403 | - return out.getvalue() |
404 | + if not filepath: |
405 | + out = StringIO.StringIO() # it's suppose to be written in a file |
406 | + else: |
407 | + out = filepath |
408 | + param = writer.ParamCardWriter(self, filepath=out) |
409 | + if not filepath: |
410 | + return out.getvalue() |
411 | + else: |
412 | + return param |
413 | |
414 | @ staticmethod |
415 | def load_default_name(): |
416 | @@ -3014,7 +3018,7 @@ |
417 | if self['constrained_orders']: |
418 | mystr = mystr + " ".join('%s%s%d' % (key, |
419 | self['constrained_orders'][key][1], self['constrained_orders'][key][0]) |
420 | - for (key,(value,type)) in sorted(self['constrained_orders'].keys())) + ' ' |
421 | + for key in sorted(self['constrained_orders'].keys())) + ' ' |
422 | |
423 | # Add perturbation_couplings |
424 | if self['perturbation_couplings']: |
425 | |
426 | === modified file 'madgraph/core/diagram_generation.py' |
427 | --- madgraph/core/diagram_generation.py 2016-02-27 14:33:01 +0000 |
428 | +++ madgraph/core/diagram_generation.py 2016-08-18 22:31:39 +0000 |
429 | @@ -496,7 +496,7 @@ |
430 | |
431 | return self.get('process').get('perturbation_couplings') |
432 | |
433 | - def generate_diagrams(self, returndiag=False): |
434 | + def generate_diagrams(self, returndiag=False, diagram_filter=False): |
435 | """Generate diagrams. Algorithm: |
436 | |
437 | 1. Define interaction dictionaries: |
438 | @@ -792,6 +792,9 @@ |
439 | if not returndiag and len(res)>0: |
440 | res = self.apply_squared_order_constraints(res) |
441 | |
442 | + if diagram_filter: |
443 | + res = self.apply_user_filter(res) |
444 | + |
445 | # Replace final id=0 vertex if necessary |
446 | if not process.get('is_decay_chain'): |
447 | for diagram in res: |
448 | @@ -884,6 +887,41 @@ |
449 | |
450 | return res |
451 | |
452 | + def apply_user_filter(self, diag_list): |
453 | + """Applies the user specified squared order constraints on the diagram |
454 | + list in argument.""" |
455 | + |
456 | + if True: |
457 | + try: |
458 | + from PLUGIN.user_filter import remove_diag |
459 | + except ImportError: |
460 | + raise MadGraph5Error, 'user filter required to be defined in PLUGIN/user_filter.py with the function remove_diag(ONEDIAG) which returns True if the daigram has to be removed' |
461 | + else: |
462 | + #example and simple tests |
463 | + def remove_diag(diag): |
464 | + for vertex in diag['vertices']: #last |
465 | + if vertex['id'] == 0: #special final vertex |
466 | + continue |
467 | + if vertex['legs'][-1]['number'] < 3: #this means T-channel |
468 | + if abs(vertex['legs'][-1]['id']) <6: |
469 | + return True |
470 | + return False |
471 | + |
472 | + res = diag_list.__class__() |
473 | + nb_removed = 0 |
474 | + for diag in diag_list: |
475 | + if remove_diag(diag): |
476 | + nb_removed +=1 |
477 | + else: |
478 | + res.append(diag) |
479 | + |
480 | + if nb_removed: |
481 | + logger.warning('Diagram filter is ON and removed %s diagrams for this subprocess.' % nb_removed) |
482 | + |
483 | + return res |
484 | + |
485 | + |
486 | + |
487 | def create_diagram(self, vertexlist): |
488 | """ Return a Diagram created from the vertex list. This function can be |
489 | overloaded by daughter classes.""" |
490 | @@ -1526,7 +1564,7 @@ |
491 | |
492 | def __init__(self, argument=None, collect_mirror_procs = False, |
493 | ignore_six_quark_processes = [], optimize=False, |
494 | - loop_filter=None): |
495 | + loop_filter=None, diagram_filter=None): |
496 | """Allow initialization with ProcessDefinition or |
497 | ProcessDefinitionList |
498 | optimize allows to use param_card information. (usefull for 1-.N)""" |
499 | @@ -1548,6 +1586,7 @@ |
500 | self['ignore_six_quark_processes'] = ignore_six_quark_processes |
501 | self['use_numerical'] = optimize |
502 | self['loop_filter'] = loop_filter |
503 | + self['diagram_filter'] = diagram_filter # only True/False so far |
504 | |
505 | if isinstance(argument, base_objects.ProcessDefinition) or \ |
506 | isinstance(argument, base_objects.ProcessDefinitionList): |
507 | @@ -1598,7 +1637,8 @@ |
508 | self.get('collect_mirror_procs'), |
509 | self.get('ignore_six_quark_processes'), |
510 | self['use_numerical'], |
511 | - loop_filter=self['loop_filter'])) |
512 | + loop_filter=self['loop_filter'], |
513 | + diagram_filter=self['diagram_filter'])) |
514 | |
515 | return MultiProcess.__bases__[0].get(self, name) # call the mother routine |
516 | |
517 | @@ -1612,7 +1652,8 @@ |
518 | collect_mirror_procs = False, |
519 | ignore_six_quark_processes = [], |
520 | use_numerical=False, |
521 | - loop_filter=None): |
522 | + loop_filter=None, |
523 | + diagram_filter=False): |
524 | """Generate amplitudes in a semi-efficient way. |
525 | Make use of crossing symmetry for processes that fail diagram |
526 | generation, but not for processes that succeed diagram |
527 | @@ -1682,6 +1723,7 @@ |
528 | sorted_legs = sorted([(l,i+1) for (i,l) in \ |
529 | enumerate(legs.get_outgoing_id_list(model))]) |
530 | permutation = [l[1] for l in sorted_legs] |
531 | + |
532 | sorted_legs = array.array('i', [l[0] for l in sorted_legs]) |
533 | |
534 | # Check for six-quark processes |
535 | @@ -1769,7 +1811,7 @@ |
536 | loop_filter=loop_filter) |
537 | |
538 | try: |
539 | - result = amplitude.generate_diagrams() |
540 | + result = amplitude.generate_diagrams(diagram_filter=diagram_filter) |
541 | except InvalidCmd as error: |
542 | failed_procs.append(sorted_legs) |
543 | else: |
544 | |
545 | === modified file 'madgraph/interface/amcatnlo_interface.py' |
546 | --- madgraph/interface/amcatnlo_interface.py 2016-05-24 09:52:16 +0000 |
547 | +++ madgraph/interface/amcatnlo_interface.py 2016-08-18 22:31:39 +0000 |
548 | @@ -45,9 +45,11 @@ |
549 | import madgraph.fks.fks_helas_objects as fks_helas |
550 | import madgraph.iolibs.export_fks as export_fks |
551 | import madgraph.iolibs.export_v4 as export_v4 |
552 | +import madgraph.iolibs.helas_call_writers as helas_call_writers |
553 | import madgraph.loop.loop_base_objects as loop_base_objects |
554 | import madgraph.core.diagram_generation as diagram_generation |
555 | import madgraph.core.helas_objects as helas_objects |
556 | + |
557 | import madgraph.various.cluster as cluster |
558 | import madgraph.various.misc as misc |
559 | import madgraph.various.banner as banner_mod |
560 | @@ -261,7 +263,7 @@ |
561 | return self.list_completion(text, content) |
562 | |
563 | |
564 | - def complete_launch(self, text, line, begidx, endidx): |
565 | + def complete_launch(self, text, line, begidx, endidx, formatting=True): |
566 | """ complete the launch command""" |
567 | args = self.split_arg(line[0:begidx]) |
568 | |
569 | @@ -299,7 +301,7 @@ |
570 | out['Options'] = self.list_completion(text, opt, line) |
571 | |
572 | |
573 | - return self.deal_multiple_categories(out) |
574 | + return self.deal_multiple_categories(out, formatting) |
575 | |
576 | class HelpFKS(mg_interface.HelpToCmd): |
577 | |
578 | @@ -562,6 +564,7 @@ |
579 | def export(self, nojpeg = False, main_file_name = "", group_processes=False): |
580 | """Export a generated amplitude to file""" |
581 | |
582 | + self._curr_helas_model = helas_call_writers.FortranUFOHelasCallWriter(self._curr_model) |
583 | def generate_matrix_elements(self, group=False): |
584 | """Helper function to generate the matrix elements before |
585 | exporting""" |
586 | @@ -659,14 +662,14 @@ |
587 | #me is a FKSHelasProcessFromReals |
588 | calls = calls + \ |
589 | self._curr_exporter.generate_directories_fks(me, |
590 | - self._curr_fortran_model, |
591 | + self._curr_helas_model, |
592 | ime, len(self._curr_matrix_elements.get('matrix_elements')), |
593 | path,self.options['OLP']) |
594 | self._fks_directories.extend(self._curr_exporter.fksdirs) |
595 | self.born_processes_for_olp.append(me.born_matrix_element.get('processes')[0]) |
596 | else: |
597 | glob_directories_map.append(\ |
598 | - [self._curr_exporter, me, self._curr_fortran_model, |
599 | + [self._curr_exporter, me, self._curr_helas_model, |
600 | ime, len(self._curr_matrix_elements.get('matrix_elements')), |
601 | path, self.options['OLP']]) |
602 | |
603 | |
604 | === modified file 'madgraph/interface/amcatnlo_run_interface.py' |
605 | --- madgraph/interface/amcatnlo_run_interface.py 2016-07-02 20:34:59 +0000 |
606 | +++ madgraph/interface/amcatnlo_run_interface.py 2016-08-18 22:31:39 +0000 |
607 | @@ -87,7 +87,7 @@ |
608 | import madgraph.various.shower_card as shower_card |
609 | import madgraph.various.FO_analyse_card as analyse_card |
610 | import madgraph.various.histograms as histograms |
611 | - from madgraph import InvalidCmd, aMCatNLOError, MadGraph5Error |
612 | + from madgraph import InvalidCmd, aMCatNLOError, MadGraph5Error,MG5DIR |
613 | |
614 | class aMCatNLOError(Exception): |
615 | pass |
616 | @@ -774,7 +774,7 @@ |
617 | opts += opt._long_opts + opt._short_opts |
618 | return self.list_completion(text, opts, line) |
619 | |
620 | - def complete_banner_run(self, text, line, begidx, endidx): |
621 | + def complete_banner_run(self, text, line, begidx, endidx, formatting=True): |
622 | "Complete the banner run command" |
623 | try: |
624 | |
625 | @@ -812,7 +812,7 @@ |
626 | run_list = [n.rsplit('/',2)[1] for n in run_list] |
627 | possibilites['RUN Name'] = self.list_completion(text, run_list) |
628 | |
629 | - return self.deal_multiple_categories(possibilites) |
630 | + return self.deal_multiple_categories(possibilites, formatting) |
631 | |
632 | |
633 | except Exception, error: |
634 | @@ -1247,6 +1247,7 @@ |
635 | with misc.TMP_variable(self, 'allow_notification_center', False): |
636 | for i,card in enumerate(param_card_iterator): |
637 | card.write(pjoin(self.me_dir,'Cards','param_card.dat')) |
638 | + self.check_param_card(pjoin(self.me_dir,'Cards','param_card.dat'), dependent=True) |
639 | if not options['force']: |
640 | options['force'] = True |
641 | if options['run_name']: |
642 | @@ -2127,7 +2128,36 @@ |
643 | """setup the number of cores for multicore, and the cluster-type for cluster runs""" |
644 | if self.cluster_mode == 1: |
645 | cluster_name = self.options['cluster_type'] |
646 | - self.cluster = cluster.from_name[cluster_name](**self.options) |
647 | + try: |
648 | + self.cluster = cluster.from_name[cluster_name](**self.options) |
649 | + except KeyError: |
650 | + if aMCatNLO and ('mg5_path' not in self.options or not self.options['mg5_path']): |
651 | + raise self.InvalidCmd('%s not native cluster type and not MG5aMC found to check for plugin' % cluster_name) |
652 | + elif aMCatNLO: |
653 | + mg5dir = self.options['mg5_path'] |
654 | + if mg5dir not in sys.path: |
655 | + sys.path.append(mg5dir) |
656 | + else: |
657 | + mg5dir = MG5DIR |
658 | + # Check if a plugin define this type of cluster |
659 | + # check for PLUGIN format |
660 | + for plug in os.listdir(pjoin(mg5dir, 'PLUGIN')): |
661 | + if os.path.exists(pjoin(mg5dir, 'PLUGIN', plug, '__init__.py')): |
662 | + try: |
663 | + __import__('PLUGIN.%s' % plug) |
664 | + except Exception, error: |
665 | + logger.critical('plugin directory %s fail to be loaded. Please check it', plug) |
666 | + continue |
667 | + plugin = sys.modules['PLUGIN.%s' % plug] |
668 | + if not hasattr(plugin, 'new_cluster'): |
669 | + continue |
670 | + if not misc.is_plugin_supported(plugin): |
671 | + continue |
672 | + if cluster_name in plugin.new_cluster: |
673 | + logger.info("cluster handling will be done with PLUGIN: %s" % plug,'$MG:color:BLACK') |
674 | + self.cluster = plugin.new_cluster[cluster_name](**self.options) |
675 | + break |
676 | + |
677 | if self.cluster_mode == 2: |
678 | try: |
679 | import multiprocessing |
680 | |
681 | === modified file 'madgraph/interface/common_run_interface.py' |
682 | --- madgraph/interface/common_run_interface.py 2016-07-29 15:27:30 +0000 |
683 | +++ madgraph/interface/common_run_interface.py 2016-08-18 22:31:39 +0000 |
684 | @@ -739,12 +739,25 @@ |
685 | param = param_card['decay'].get((part.pdg_code,)) |
686 | |
687 | if param.value != 0: |
688 | - logger.info('''For gauge cancellation, the width of \'%s\' has been set to zero.''' |
689 | + logger.info('''For gauge cancellation, the width of \'%s\' has been set to zero.'''\ |
690 | % part.name,'$MG:color:BLACK') |
691 | param.value = 0 |
692 | |
693 | param_card.write_inc_file(outfile, ident_card, default) |
694 | |
695 | + def get_model(self): |
696 | + """return the model related to this process""" |
697 | + |
698 | + if self.options['mg5_path']: |
699 | + sys.path.append(self.options['mg5_path']) |
700 | + import models.import_ufo as import_ufo |
701 | + with misc.MuteLogger(['madgraph.model'],[50]): |
702 | + out= import_ufo.import_model(pjoin(self.me_dir,'bin','internal','ufomodel')) |
703 | + return out |
704 | + elif self.mother: |
705 | + return self.mother._curr_model |
706 | + else: |
707 | + return None |
708 | |
709 | def ask_edit_cards(self, cards, mode='fixed', plot=True, first_cmd=None): |
710 | """ """ |
711 | @@ -1685,16 +1698,47 @@ |
712 | if self.cluster_mode == 1: |
713 | opt = self.options |
714 | cluster_name = opt['cluster_type'] |
715 | - self.cluster = cluster.from_name[cluster_name](**opt) |
716 | - |
717 | - |
718 | - def check_param_card(self, path, run=True): |
719 | + if cluster_name in cluster.from_name: |
720 | + self.cluster = cluster.from_name[cluster_name](**opt) |
721 | + else: |
722 | + if MADEVENT and ('mg5_path' not in self.options or not self.options['mg5_path']): |
723 | + raise self.InvalidCmd('%s not native cluster type and not MG5aMC found to check for plugin') |
724 | + elif MADEVENT: |
725 | + mg5dir = self.options['mg5_path'] |
726 | + if mg5dir not in sys.path: |
727 | + sys.path.append(mg5dir) |
728 | + else: |
729 | + mg5dir = MG5DIR |
730 | + # Check if a plugin define this type of cluster |
731 | + # check for PLUGIN format |
732 | + for plug in os.listdir(pjoin(mg5dir, 'PLUGIN')): |
733 | + if os.path.exists(pjoin(mg5dir, 'PLUGIN', plug, '__init__.py')): |
734 | + try: |
735 | + __import__('PLUGIN.%s' % plug) |
736 | + except Exception, error: |
737 | + logger.critical('plugin directory %s fail to be loaded. Please check it', plug) |
738 | + continue |
739 | + plugin = sys.modules['PLUGIN.%s' % plug] |
740 | + if not hasattr(plugin, 'new_cluster'): |
741 | + continue |
742 | + if not misc.is_plugin_supported(plugin): |
743 | + continue |
744 | + if cluster_name in plugin.new_cluster: |
745 | + logger.info("cluster handling will be done with PLUGIN: %s" % plug,'$MG:color:BLACK') |
746 | + self.cluster = plugin.new_cluster[cluster_name](**opt) |
747 | + break |
748 | + else: |
749 | + raise self.InvalidCmd, "%s is not recognized as a supported cluster format." % cluster_name |
750 | + |
751 | + |
752 | + def check_param_card(self, path, run=True, dependent=False): |
753 | """ |
754 | 1) Check that no scan parameter are present |
755 | 2) Check that all the width are define in the param_card. |
756 | - If a scan parameter is define. create the iterator and recall this fonction |
757 | on the first element. |
758 | - - If some width are set on 'Auto', call the computation tools.""" |
759 | + - If some width are set on 'Auto', call the computation tools. |
760 | + 3) if dependent is on True check for dependent parameter (automatic for scan)""" |
761 | |
762 | pattern_scan = re.compile(r'''^(decay)?[\s\d]*scan''', re.I+re.M) |
763 | pattern_width = re.compile(r'''decay\s+(\+?\-?\d+)\s+auto(@NLO|)''',re.I) |
764 | @@ -1709,7 +1753,7 @@ |
765 | self.param_card_iterator = main_card |
766 | first_card = main_card.next(autostart=True) |
767 | first_card.write(path) |
768 | - return self.check_param_card(path, run) |
769 | + return self.check_param_card(path, run, dependent=True) |
770 | |
771 | pdg_info = pattern_width.findall(text) |
772 | if pdg_info: |
773 | @@ -1720,13 +1764,18 @@ |
774 | if not has_nlo: |
775 | self.do_compute_widths('%s %s' % (' '.join(pdg), path)) |
776 | else: |
777 | - self.do_compute_widths('%s %s --nlo' % (' '.join(pdg), path)) |
778 | + self.do_compute_widths('%s %s --nlo' % (' '.join(pdg), path)) |
779 | else: |
780 | logger.info('''Some width are on Auto in the card. |
781 | Those will be computed as soon as you have finish the edition of the cards. |
782 | If you want to force the computation right now and being able to re-edit |
783 | the cards afterwards, you can type \"compute_wdiths\".''') |
784 | - |
785 | + |
786 | + if dependent: |
787 | + card = check_param_card.ParamCard(path) |
788 | + AskforEditCard.update_dependent(self, self.me_dir, card, path, timer=20) |
789 | + |
790 | + return |
791 | |
792 | def add_error_log_in_html(self, errortype=None): |
793 | """If a ME run is currently running add a link in the html output""" |
794 | @@ -2138,7 +2187,7 @@ |
795 | |
796 | |
797 | |
798 | - def complete_compute_widths(self, text, line, begidx, endidx): |
799 | + def complete_compute_widths(self, text, line, begidx, endidx, formatting=True): |
800 | "Complete the compute_widths command" |
801 | |
802 | args = self.split_arg(line[0:begidx]) |
803 | @@ -2158,7 +2207,7 @@ |
804 | ['--path=', '--output=', '--min_br=0.\$', '--nlo', |
805 | '--precision_channel=0.\$', '--body_decay=']) |
806 | |
807 | - return self.deal_multiple_categories(completion) |
808 | + return self.deal_multiple_categories(completion, formatting) |
809 | |
810 | |
811 | def update_make_opts(self): |
812 | @@ -2376,7 +2425,7 @@ |
813 | filename = pdf_info[filename]['filename'] |
814 | |
815 | if os.path.exists(pjoin(pdfsets_dir, filename)): |
816 | - logger.debug('%s is already present in %s', (filename, pdfsets_dir)) |
817 | + logger.debug('%s is already present in %s', filename, pdfsets_dir) |
818 | return |
819 | |
820 | logger.info('Trying to download %s' % filename) |
821 | @@ -2530,38 +2579,76 @@ |
822 | 'fixed_scale': ['run_card fixed_fac_scale T', 'run_card fixed_ren_scale T', 'run_card scale %(0)s', 'run_card dsqrt_q2fact1 %(0)s' ,'run_card dsqrt_q2fact2 %(0)s'], |
823 | } |
824 | |
825 | - def __init__(self, question, cards=[], mode='auto', *args, **opt): |
826 | - |
827 | + def load_default(self): |
828 | + """ define all default variable. No load of card here. |
829 | + This allow to subclass this class and just change init and still have |
830 | + all variables defined.""" |
831 | + |
832 | + self.me_dir = None |
833 | + self.param_card = None |
834 | + self.run_card = {} |
835 | + self.pname2block = {} |
836 | + self.conflict = [] |
837 | + self.restricted_value = {} |
838 | + self.mode = '' |
839 | + self.cards = [] |
840 | + self.run_set = [] |
841 | + self.has_mw = False |
842 | + self.has_ml = False |
843 | + self.has_shower = False |
844 | + self.paths = {} |
845 | + |
846 | + def define_paths(self, **opt): |
847 | + |
848 | # Initiation |
849 | if 'pwd' in opt: |
850 | self.me_dir = opt['pwd'] |
851 | - del opt['pwd'] |
852 | - |
853 | - cmd.OneLinePathCompletion.__init__(self, question, *args, **opt) |
854 | - |
855 | + elif 'mother_interface' in opt: |
856 | + self.mother_interface = opt['mother_interface'] |
857 | if not hasattr(self, 'me_dir') or not self.me_dir: |
858 | self.me_dir = self.mother_interface.me_dir |
859 | - |
860 | - # read the card |
861 | + |
862 | + #define paths |
863 | + self.paths['param'] = pjoin(self.me_dir,'Cards','param_card.dat') |
864 | + self.paths['param_default'] = pjoin(self.me_dir,'Cards','param_card_default.dat') |
865 | + self.paths['run'] = pjoin(self.me_dir,'Cards','run_card.dat') |
866 | + self.paths['run_default'] = pjoin(self.me_dir,'Cards','run_card_default.dat') |
867 | + self.paths['transfer'] =pjoin(self.me_dir,'Cards','transfer_card.dat') |
868 | + self.paths['MadWeight'] =pjoin(self.me_dir,'Cards','MadWeight_card.dat') |
869 | + self.paths['MadWeight_default'] =pjoin(self.me_dir,'Cards','MadWeight_card_default.dat') |
870 | + self.paths['ML'] =pjoin(self.me_dir,'Cards','MadLoopParams.dat') |
871 | + self.paths['shower'] = pjoin(self.me_dir,'Cards','shower_card.dat') |
872 | + self.paths['shower_default'] = pjoin(self.me_dir,'Cards','shower_card_default.dat') |
873 | + self.paths['pythia'] =pjoin(self.me_dir, 'Cards','pythia_card.dat') |
874 | + self.paths['madspin_default'] = pjoin(self.me_dir,'Cards/madspin_card_default.dat') |
875 | + self.paths['madspin'] = pjoin(self.me_dir,'Cards/madspin_card.dat') |
876 | + self.paths['reweight'] = pjoin(self.me_dir,'Cards','reweight_card.dat') |
877 | + self.paths['delphes'] = pjoin(self.me_dir,'Cards','delphes_card.dat') |
878 | + |
879 | + def __init__(self, question, cards=[], mode='auto', *args, **opt): |
880 | + |
881 | + self.load_default() |
882 | + self.define_paths(**opt) |
883 | + cmd.OneLinePathCompletion.__init__(self, question, *args, **opt) |
884 | |
885 | |
886 | try: |
887 | - self.param_card = check_param_card.ParamCard(pjoin(self.me_dir,'Cards','param_card.dat')) |
888 | + self.param_card = check_param_card.ParamCard(self.paths['param']) |
889 | except (check_param_card.InvalidParamCard, ValueError) as e: |
890 | logger.error('Current param_card is not valid. We are going to use the default one.') |
891 | logger.error('problem detected: %s' % e) |
892 | files.cp(pjoin(self.me_dir,'Cards','param_card_default.dat'), |
893 | pjoin(self.me_dir,'Cards','param_card.dat')) |
894 | - self.param_card = check_param_card.ParamCard(pjoin(self.me_dir,'Cards','param_card.dat')) |
895 | - default_param = check_param_card.ParamCard(pjoin(self.me_dir,'Cards','param_card_default.dat')) |
896 | + self.param_card = check_param_card.ParamCard(self.paths['param']) |
897 | + default_param = check_param_card.ParamCard(self.paths['param_default']) |
898 | |
899 | |
900 | try: |
901 | - self.run_card = banner_mod.RunCard(pjoin(self.me_dir,'Cards','run_card.dat')) |
902 | + self.run_card = banner_mod.RunCard(self.paths['run']) |
903 | except IOError: |
904 | self.run_card = {} |
905 | try: |
906 | - run_card_def = banner_mod.RunCard(pjoin(self.me_dir,'Cards','run_card_default.dat')) |
907 | + run_card_def = banner_mod.RunCard(self.paths['run_default']) |
908 | except IOError: |
909 | run_card_def = {} |
910 | |
911 | @@ -2596,7 +2683,7 @@ |
912 | self.do_change_tf = self.mother_interface.do_define_transfer_fct |
913 | self.complete_change_tf = self.mother_interface.complete_define_transfer_fct |
914 | self.help_change_tf = self.mother_interface.help_define_transfer_fct |
915 | - if not os.path.exists(pjoin(self.me_dir,'Cards','transfer_card.dat')): |
916 | + if not os.path.exists(self.paths['transfer']): |
917 | logger.warning('No transfer function currently define. Please use the change_tf command to define one.') |
918 | |
919 | |
920 | @@ -2605,7 +2692,7 @@ |
921 | import madgraph.madweight.Cards as mwcards |
922 | except: |
923 | import internal.madweight.Cards as mwcards |
924 | - self.mw_card = mwcards.Card(pjoin(self.me_dir,'Cards','MadWeight_card.dat')) |
925 | + self.mw_card = mwcards.Card(self.paths['MadWeight']) |
926 | self.mw_card = self.mw_card.info |
927 | self.mw_vars = [] |
928 | for key in self.mw_card: |
929 | @@ -2625,9 +2712,9 @@ |
930 | |
931 | #check if MadLoopParams.dat is present: |
932 | self.has_ml = False |
933 | - if os.path.isfile(pjoin(self.me_dir,'Cards','MadLoopParams.dat')): |
934 | + if os.path.isfile(self.paths['ML']): |
935 | self.has_ml = True |
936 | - self.MLcard = banner_mod.MadLoopParam(pjoin(self.me_dir,'Cards','MadLoopParams.dat')) |
937 | + self.MLcard = banner_mod.MadLoopParam(self.paths['ML']) |
938 | self.MLcardDefault = banner_mod.MadLoopParam() |
939 | |
940 | self.ml_vars = [k.lower() for k in self.MLcard.keys()] |
941 | @@ -2648,7 +2735,7 @@ |
942 | import madgraph.various.shower_card as showercards |
943 | except: |
944 | import internal.shower_card as showercards |
945 | - self.shower_card = showercards.ShowerCard(pjoin(self.me_dir,'Cards','shower_card.dat')) |
946 | + self.shower_card = showercards.ShowerCard(self.paths['shower']) |
947 | self.shower_vars = self.shower_card.keys() |
948 | |
949 | # check for conflict with run_card/param_card |
950 | @@ -2660,7 +2747,7 @@ |
951 | self.conflict.append(var) |
952 | |
953 | |
954 | - def complete_set(self, text, line, begidx, endidx): |
955 | + def complete_set(self, text, line, begidx, endidx, formatting=True): |
956 | """ Complete the set command""" |
957 | |
958 | prev_timer = signal.alarm(0) # avoid timer if any |
959 | @@ -2838,7 +2925,7 @@ |
960 | possibilities['Special value'] = self.list_completion(text, opts) |
961 | possibilities['MadWeight Card id' ] = self.list_completion(text, ids) |
962 | |
963 | - return self.deal_multiple_categories(possibilities) |
964 | + return self.deal_multiple_categories(possibilities, formatting) |
965 | |
966 | def do_set(self, line): |
967 | """ edit the value of one parameter in the card""" |
968 | @@ -2893,7 +2980,7 @@ |
969 | |
970 | # Special case for the qcut value |
971 | if args[0].lower() == 'qcut': |
972 | - pythia_path = pjoin(self.me_dir, 'Cards','pythia_card.dat') |
973 | + pythia_path = self.paths['pythia'] |
974 | if os.path.exists(pythia_path): |
975 | logger.info('add line QCUT = %s in pythia_card.dat' % args[1]) |
976 | p_card = open(pythia_path,'r').read() |
977 | @@ -2907,7 +2994,7 @@ |
978 | return |
979 | # Special case for the showerkt value |
980 | if args[0].lower() == 'showerkt': |
981 | - pythia_path = pjoin(self.me_dir, 'Cards','pythia_card.dat') |
982 | + pythia_path = self.paths['pythia'] |
983 | if os.path.exists(pythia_path): |
984 | logger.info('add line SHOWERKT = %s in pythia_card.dat' % args[1].upper()) |
985 | p_card = open(pythia_path,'r').read() |
986 | @@ -2943,14 +3030,13 @@ |
987 | if args[0] in ['run_card', 'param_card', 'MadWeight_card', 'shower_card']: |
988 | if args[1] == 'default': |
989 | logging.info('replace %s by the default card' % args[0]) |
990 | - files.cp(pjoin(self.me_dir,'Cards','%s_default.dat' % args[0]), |
991 | - pjoin(self.me_dir,'Cards','%s.dat'% args[0])) |
992 | + files.cp(self.paths['%s_default' %args[0][:-5]], self.paths[args[0][:-5]]) |
993 | if args[0] == 'param_card': |
994 | - self.param_card = check_param_card.ParamCard(pjoin(self.me_dir,'Cards','param_card.dat')) |
995 | + self.param_card = check_param_card.ParamCard(self.paths['param']) |
996 | elif args[0] == 'run_card': |
997 | - self.run_card = banner_mod.RunCard(pjoin(self.me_dir,'Cards','run_card.dat')) |
998 | + self.run_card = banner_mod.RunCard(self.paths['run']) |
999 | elif args[0] == 'shower_card': |
1000 | - self.shower_card = shower_card_mod.ShowerCard(pjoin(self.me_dir,'Cards','shower_card.dat')) |
1001 | + self.shower_card = shower_card_mod.ShowerCard(self.paths['shower']) |
1002 | return |
1003 | else: |
1004 | card = args[0] |
1005 | @@ -2963,7 +3049,7 @@ |
1006 | if args[1] == 'default': |
1007 | logging.info('replace MadLoopParams.dat by the default card') |
1008 | self.MLcard = banner_mod.MadLoopParam(self.MLcardDefault) |
1009 | - self.MLcard.write(pjoin(self.me_dir,'Cards','MadLoopParams.dat'), |
1010 | + self.MLcard.write(self.paths['ML'], |
1011 | commentdefault=True) |
1012 | return |
1013 | else: |
1014 | @@ -2975,8 +3061,7 @@ |
1015 | elif args[0] in ['madspin_card']: |
1016 | if args[1] == 'default': |
1017 | logging.info('replace madspin_card.dat by the default card') |
1018 | - files.cp(pjoin(self.me_dir,'Cards/madspin_card_default.dat'), |
1019 | - pjoin(self.me_dir,'Cards/madspin_card.dat')) |
1020 | + files.cp(self.paths['MS_default'], self.paths['madspin']) |
1021 | return |
1022 | else: |
1023 | logger.warning("""Command set not allowed for modifying the madspin_card. |
1024 | @@ -2995,7 +3080,7 @@ |
1025 | logger.warning(text) |
1026 | |
1027 | if args[start+1] == 'default': |
1028 | - default = banner_mod.RunCard(pjoin(self.me_dir,'Cards','run_card_default.dat')) |
1029 | + default = banner_mod.RunCard(self.paths['run_default']) |
1030 | if args[start] in default.keys(): |
1031 | self.setR(args[start],default[args[start]]) |
1032 | else: |
1033 | @@ -3011,8 +3096,7 @@ |
1034 | except NameError: |
1035 | val = args[start+1] |
1036 | self.setR(args[start], val) |
1037 | - self.run_card.write(pjoin(self.me_dir,'Cards','run_card.dat'), |
1038 | - pjoin(self.me_dir,'Cards','run_card_default.dat')) |
1039 | + self.run_card.write(self.paths['run'], self.paths['run_default']) |
1040 | |
1041 | ### PARAM_CARD WITH BLOCK NAME ----------------------------------------- |
1042 | elif (args[start] in self.param_card or args[start] == 'width') \ |
1043 | @@ -3052,7 +3136,7 @@ |
1044 | continue |
1045 | else: |
1046 | self.setP(args[start], key, args[-1]) |
1047 | - self.param_card.write(pjoin(self.me_dir,'Cards','param_card.dat')) |
1048 | + self.param_card.write(self.paths['param']) |
1049 | return |
1050 | logger.warning('invalid set command %s (failed to identify LHA information)' % line) |
1051 | return |
1052 | @@ -3078,7 +3162,7 @@ |
1053 | else: |
1054 | logger.warning('invalid set command %s' % line) |
1055 | return |
1056 | - self.param_card.write(pjoin(self.me_dir,'Cards','param_card.dat')) |
1057 | + self.param_card.write(self.paths['param']) |
1058 | |
1059 | # PARAM_CARD NO BLOCK NAME --------------------------------------------- |
1060 | elif args[start] in self.pname2block and card != 'run_card': |
1061 | @@ -3113,7 +3197,7 @@ |
1062 | name = args[start+1] |
1063 | value = args[start+2:] |
1064 | self.setM(block, name, value) |
1065 | - self.mw_card.write(pjoin(self.me_dir,'Cards','MadWeight_card.dat')) |
1066 | + self.mw_card.write(self.paths['MadWeight']) |
1067 | |
1068 | # MadWeight_card NO Block name ----------------------------------------- |
1069 | elif self.has_mw and args[start] in self.mw_vars \ |
1070 | @@ -3135,7 +3219,7 @@ |
1071 | name = args[start] |
1072 | value = args[start+1:] |
1073 | self.setM(block, name, value) |
1074 | - self.mw_card.write(pjoin(self.me_dir,'Cards','MadWeight_card.dat')) |
1075 | + self.mw_card.write(self.paths['MadWeight']) |
1076 | |
1077 | # MadWeight_card New Block --------------------------------------------- |
1078 | elif self.has_mw and args[start].startswith('mw_') and len(args[start:]) == 3\ |
1079 | @@ -3144,7 +3228,7 @@ |
1080 | name = args[start+1] |
1081 | value = args[start+2] |
1082 | self.setM(block, name, value) |
1083 | - self.mw_card.write(pjoin(self.me_dir,'Cards','MadWeight_card.dat')) |
1084 | + self.mw_card.write(self.paths['MadWeight']) |
1085 | |
1086 | #### SHOWER CARD |
1087 | elif self.has_shower and args[start].lower() in [l.lower() for l in \ |
1088 | @@ -3159,19 +3243,19 @@ |
1089 | return |
1090 | |
1091 | if args[start+1].lower() == 'default': |
1092 | - default = shower_card_mod.ShowerCard(pjoin(self.me_dir,'Cards','shower_card_default.dat')) |
1093 | + default = shower_card_mod.ShowerCard(self.paths['shower_default']) |
1094 | if args[start] in default.keys(): |
1095 | - self.shower_card.set_param(args[start],default[args[start]],pjoin(self.me_dir,'Cards','shower_card.dat')) |
1096 | + self.shower_card.set_param(args[start],default[args[start]], self.paths['shower']) |
1097 | else: |
1098 | logger.info('remove information %s from the shower_card' % args[start]) |
1099 | del self.shower_card[args[start]] |
1100 | elif args[start+1].lower() in ['t','.true.','true']: |
1101 | - self.shower_card.set_param(args[start],'.true.',pjoin(self.me_dir,'Cards','shower_card.dat')) |
1102 | + self.shower_card.set_param(args[start],'.true.',self.paths['shower']) |
1103 | elif args[start+1].lower() in ['f','.false.','false']: |
1104 | - self.shower_card.set_param(args[start],'.false.',pjoin(self.me_dir,'Cards','shower_card.dat')) |
1105 | + self.shower_card.set_param(args[start],'.false.',self.paths['shower']) |
1106 | else: |
1107 | args_str = ' '.join(str(a) for a in args[start+1:len(args)]) |
1108 | - self.shower_card.set_param(args[start],args_str,pjoin(self.me_dir,'Cards','shower_card.dat')) |
1109 | + self.shower_card.set_param(args[start],args_str,self.paths['shower']) |
1110 | |
1111 | # MadLoop Parameter --------------------------------------------------- |
1112 | elif self.has_ml and args[start] in self.ml_vars \ |
1113 | @@ -3189,7 +3273,7 @@ |
1114 | value = args[start+1] |
1115 | default = False |
1116 | self.setML(args[start], value, default=default) |
1117 | - self.MLcard.write(pjoin(self.me_dir,'Cards','MadLoopParams.dat'), |
1118 | + self.MLcard.write(self.paths['ML'], |
1119 | commentdefault=True) |
1120 | |
1121 | #INVALID -------------------------------------------------------------- |
1122 | @@ -3209,7 +3293,7 @@ |
1123 | logger.info('name %s was not present in the block %s for the current MadWeight card. We are adding it' % (name,block),'$MG:color:BLACK') |
1124 | if value == 'default': |
1125 | import madgraph.madweight.Cards as mwcards |
1126 | - mw_default = mwcards.Card(pjoin(self.me_dir,'Cards','MadWeight_card_default.dat')) |
1127 | + mw_default = mwcards.Card(self.paths['MadWeight_default']) |
1128 | try: |
1129 | value = mw_default[block][name] |
1130 | except KeyError: |
1131 | @@ -3227,7 +3311,7 @@ |
1132 | self.mw_card[block][name] = value |
1133 | |
1134 | def setR(self, name, value): |
1135 | - logger.info('modify parameter %s of the run_card.dat to %s' % (name, value)) |
1136 | + logger.info('modify parameter %s of the run_card.dat to %s' % (name, value),'$MG:color:BLACK') |
1137 | self.run_card.set(name, value, user=True) |
1138 | |
1139 | def setML(self, name, value, default=False): |
1140 | @@ -3237,7 +3321,7 @@ |
1141 | except Exception, error: |
1142 | logger.warning("Fail to change parameter. Please Retry. Reason: %s." % error) |
1143 | return |
1144 | - logger.info('modify parameter %s of the MadLoopParam.dat to %s' % (name, value)) |
1145 | + logger.info('modify parameter %s of the MadLoopParam.dat to %s' % (name, value),'$MG:color:BLACK') |
1146 | if default and name.lower() in self.MLcard.user_set: |
1147 | self.MLcard.user_set.remove(name.lower()) |
1148 | |
1149 | @@ -3245,7 +3329,7 @@ |
1150 | if isinstance(value, str): |
1151 | value = value.lower() |
1152 | if value == 'default': |
1153 | - default = check_param_card.ParamCard(pjoin(self.me_dir,'Cards','param_card_default.dat')) |
1154 | + default = check_param_card.ParamCard(self.paths['param_default']) |
1155 | value = default[block].param_dict[lhaid].value |
1156 | |
1157 | elif value in ['auto', 'auto@nlo']: |
1158 | @@ -3288,7 +3372,7 @@ |
1159 | not self.run_card['store_rwgt_info']: |
1160 | #check if a NLO reweighting is required |
1161 | re_pattern = re.compile(r'''^\s*change\s*mode\s* (LO\+NLO|LO|NLO)\s*(?:#|$)''', re.M+re.I) |
1162 | - text = open(pjoin(self.me_dir,'Cards','reweight_card.dat')).read() |
1163 | + text = open(self.paths['reweight']).read() |
1164 | options = re_pattern.findall(text) |
1165 | if any(o in ['NLO', 'LO+NLO'] for o in options): |
1166 | logger.info('NLO reweighting is on ON. Automatically set store_rwgt_info to True', '$MG:color:BLACK' ) |
1167 | @@ -3302,15 +3386,89 @@ |
1168 | logger.warning('No transfer function currently define. Please use the change_tf command to define one.') |
1169 | |
1170 | def postcmd(self, stop, line): |
1171 | - |
1172 | ending_question = cmd.OneLinePathCompletion.postcmd(self,stop,line) |
1173 | + |
1174 | if ending_question: |
1175 | self.check_card_consistency() |
1176 | + self.do_update_dependent('', timer=20) |
1177 | return ending_question |
1178 | |
1179 | + def do_update_dependent(self, line, timer=0): |
1180 | + """Change the mass/width of particles which are not free parameter for the |
1181 | + model.""" |
1182 | + if not self.mother_interface: |
1183 | + logger.warning('Failed to update dependent parameter. This might create trouble for external program (like MadSpin/shower/...)') |
1184 | + |
1185 | + pattern_width = re.compile(r'''decay\s+(\+?\-?\d+)\s+auto(@NLO|)''',re.I) |
1186 | + pattern_scan = re.compile(r'''^(decay)?[\s\d]*scan''', re.I+re.M) |
1187 | + param_text= open(self.paths['param']).read() |
1188 | + |
1189 | + if pattern_scan.search(param_text): |
1190 | + #for block, key in self.restricted_value: |
1191 | + # self.param_card[block].get(key).value = -9.999e-99 |
1192 | + # self.param_card.write(self.paths['param']) |
1193 | + return |
1194 | + elif pattern_width.search(param_text): |
1195 | + self.do_compute_widths('') |
1196 | + self.param_card = check_param_card.ParamCard(self.paths['param']) |
1197 | + |
1198 | + # calling the routine doing the work |
1199 | + self.update_dependent(self.mother_interface, self.me_dir, self.param_card, |
1200 | + self.paths['param'], timer) |
1201 | + |
1202 | + @staticmethod |
1203 | + def update_dependent(mecmd, me_dir, param_card, path ,timer=0): |
1204 | + """static method which can also be called from outside the class |
1205 | + usefull in presence of scan. |
1206 | + return if the param_card was updated or not |
1207 | + """ |
1208 | + modify = True |
1209 | + class TimeOutError(Exception): |
1210 | + pass |
1211 | + def handle_alarm(signum, frame): |
1212 | + raise TimeOutError |
1213 | + signal.signal(signal.SIGALRM, handle_alarm) |
1214 | + if timer: |
1215 | + signal.alarm(timer) |
1216 | + log_level=30 |
1217 | + else: |
1218 | + log_level=20 |
1219 | + # Try to load the model in the limited amount of time allowed |
1220 | + try: |
1221 | + model = mecmd.get_model() |
1222 | + signal.alarm(0) |
1223 | + except TimeOutError: |
1224 | + logger.warning('The model takes too long to load so we bypass the updating of dependent parameter.\n'+\ |
1225 | + 'This might create trouble for external program (like MadSpin/shower/...)\n'+\ |
1226 | + 'The update can be forced without timer by typing \'update_dependent\' at the time of the card edition') |
1227 | + modify =False |
1228 | + except Exception: |
1229 | + logger.warning('Failed to update dependent parameter. This might create trouble for external program (like MadSpin/shower/...)') |
1230 | + signal.alarm(0) |
1231 | + else: |
1232 | + restrict_card = pjoin(me_dir,'Source','MODEL','param_card_rule.dat') |
1233 | + if not os.path.exists(restrict_card): |
1234 | + restrict_card = None |
1235 | + #restrict_card = None |
1236 | + if model: |
1237 | + modify = param_card.update_dependent(model, restrict_card, log_level) |
1238 | + if modify and path: |
1239 | + param_card.write(path) |
1240 | + else: |
1241 | + logger.warning('missing MG5aMC code. Fail to update dependent parameter. This might create trouble for program like MadSpin/shower/...') |
1242 | + |
1243 | + if log_level==20: |
1244 | + logger.info('param_card up to date.') |
1245 | + |
1246 | + return modify |
1247 | + |
1248 | + |
1249 | + |
1250 | + |
1251 | def check_answer_consistency(self): |
1252 | """function called if the code reads a file""" |
1253 | - self.check_card_consistency() |
1254 | + self.check_card_consistency() |
1255 | + self.do_update_dependent('', timer=20) |
1256 | |
1257 | def help_set(self): |
1258 | '''help message for set''' |
1259 | @@ -3354,11 +3512,11 @@ |
1260 | elif os.path.isfile(line): |
1261 | self.copy_file(line) |
1262 | self.value = 'repeat' |
1263 | - elif os.path.exists(pjoin(self.me_dir, line)): |
1264 | + elif self.me_dir and os.path.exists(pjoin(self.me_dir, line)): |
1265 | self.copy_file(pjoin(self.me_dir,line)) |
1266 | self.value = 'repeat' |
1267 | elif line.strip() != '0' and line.strip() != 'done' and \ |
1268 | - str(line) != 'EOF' and line.strip() in self.allow_arg: |
1269 | + str(line) != 'EOF' and line.strip() in self.allow_arg: |
1270 | self.open_file(line) |
1271 | self.value = 'repeat' |
1272 | else: |
1273 | @@ -3369,7 +3527,7 @@ |
1274 | def do_decay(self, line): |
1275 | """edit the madspin_card to define the decay of the associate particle""" |
1276 | signal.alarm(0) # avoid timer if any |
1277 | - path = pjoin(self.me_dir,'Cards','madspin_card.dat') |
1278 | + path = self.paths['madspin'] |
1279 | |
1280 | if 'madspin_card.dat' not in self.cards or not os.path.exists(path): |
1281 | logger.warning("Command decay not valid. Since MadSpin is not available.") |
1282 | @@ -3405,7 +3563,7 @@ |
1283 | |
1284 | def do_compute_widths(self, line): |
1285 | signal.alarm(0) # avoid timer if any |
1286 | - path = pjoin(self.me_dir,'Cards','param_card.dat') |
1287 | + path = self.paths['param'] |
1288 | pattern = re.compile(r'''decay\s+(\+?\-?\d+)\s+auto(@NLO|)''',re.I) |
1289 | text = open(path).read() |
1290 | pdg_info = pattern.findall(text) |
1291 | @@ -3454,7 +3612,7 @@ |
1292 | print ' If you specify some names after the command (i.e. asperge m1 m2) then ASperGe will only' |
1293 | print ' diagonalize the associate mass matrices (here m1 and m2).' |
1294 | |
1295 | - def complete_asperge(self, text, line, begidx, endidx): |
1296 | + def complete_asperge(self, text, line, begidx, endidx, formatting=True): |
1297 | signal.alarm(0) # avoid timer if any |
1298 | |
1299 | blockname = self.pname2block.keys() |
1300 | @@ -3465,7 +3623,7 @@ |
1301 | output = {'Mixing matrices': self.list_completion(text, valid, line), |
1302 | 'Other potential valid input': self.list_completion(text, potential, line)} |
1303 | |
1304 | - return self.deal_multiple_categories(output) |
1305 | + return self.deal_multiple_categories(output, formatting) |
1306 | |
1307 | |
1308 | def do_asperge(self, line): |
1309 | @@ -3489,7 +3647,7 @@ |
1310 | return |
1311 | |
1312 | opts = line.split() |
1313 | - card = pjoin(self.me_dir,'Cards', 'param_card.dat') |
1314 | + card = self.paths['param'] |
1315 | logger.info('running ASperGE') |
1316 | returncode = misc.call([pjoin(path,'ASperGe'), card, '%s.new' % card] + opts) |
1317 | if returncode: |
1318 | @@ -3521,7 +3679,7 @@ |
1319 | logger.warning('Fail to determine the type of the file. Not copied') |
1320 | if card_name != 'banner': |
1321 | logger.info('copy %s as %s' % (path, card_name)) |
1322 | - files.cp(path, pjoin(self.me_dir, 'Cards', card_name)) |
1323 | + files.cp(path, self.paths[card_name.split('_',1)[0]]) |
1324 | elif card_name == 'banner': |
1325 | banner_mod.split_banner(path, self.mother_interface.me_dir, proc_card=False) |
1326 | logger.info('Splitting the banner in it\'s component') |
1327 | @@ -3530,7 +3688,11 @@ |
1328 | |
1329 | def open_file(self, answer): |
1330 | """open the file""" |
1331 | - me_dir = self.mother_interface.me_dir |
1332 | + try: |
1333 | + me_dir = self.mother_interface.me_dir |
1334 | + except: |
1335 | + me_dir = None |
1336 | + |
1337 | if answer.isdigit(): |
1338 | if answer == '9': |
1339 | answer = 'plot' |
1340 | @@ -3540,14 +3702,17 @@ |
1341 | answer = answer.replace('madweight', 'MadWeight') |
1342 | |
1343 | if 'MadLoopParams' in answer: |
1344 | - answer = pjoin(me_dir,'Cards','MadLoopParams.dat') |
1345 | + answer = self.paths['ML'] |
1346 | if not '.dat' in answer and not '.lhco' in answer: |
1347 | if answer != 'trigger': |
1348 | - path = pjoin(me_dir,'Cards','%s_card.dat' % answer) |
1349 | + path = self.paths[answer] |
1350 | else: |
1351 | - path = pjoin(me_dir,'Cards','delphes_trigger.dat') |
1352 | + path = self.paths['delphes'] |
1353 | elif not '.lhco' in answer: |
1354 | - path = pjoin(me_dir, 'Cards', answer) |
1355 | + if '_' in answer: |
1356 | + path = self.paths[answer.split('_')[0]] |
1357 | + else: |
1358 | + path = pjoin(me_dir, 'Cards', answer) |
1359 | else: |
1360 | path = pjoin(me_dir, self.mw_card['mw_run']['inputfile']) |
1361 | if not os.path.exists(path): |
1362 | @@ -3574,7 +3739,7 @@ |
1363 | raise |
1364 | |
1365 | # reload object to have it in sync |
1366 | - if path == pjoin(self.me_dir,'Cards','param_card.dat'): |
1367 | + if path == self.paths['param']: |
1368 | try: |
1369 | self.param_card = check_param_card.ParamCard(path) |
1370 | except (check_param_card.InvalidParamCard, ValueError) as e: |
1371 | @@ -3582,14 +3747,41 @@ |
1372 | logger.error('problem detected: %s' % e) |
1373 | logger.error('Please re-open the file and fix the problem.') |
1374 | logger.warning('using the \'set\' command without opening the file will discard all your manual change') |
1375 | - elif path == pjoin(self.me_dir,'Cards','run_card.dat'): |
1376 | - self.run_card = banner_mod.RunCard(pjoin(self.me_dir,'Cards','run_card.dat')) |
1377 | - elif path == pjoin(self.me_dir,'Cards','MadLoopParams.dat'): |
1378 | - self.MLcard = banner_mod.MadLoopParam(pjoin(self.me_dir,'Cards','MadLoopParams.dat')) |
1379 | - elif path == pjoin(self.me_dir,'Cards','MadWeight_card.dat'): |
1380 | + elif path == self.paths['run']: |
1381 | + self.run_card = banner_mod.RunCard(path) |
1382 | + elif path == self.paths['ML']: |
1383 | + self.MLcard = banner_mod.MadLoopParam(path) |
1384 | + elif path == self.paths['MadWeight']: |
1385 | try: |
1386 | import madgraph.madweight.Cards as mwcards |
1387 | except: |
1388 | import internal.madweight.Cards as mwcards |
1389 | - self.mw_card = mwcards.Card(pjoin(self.me_dir,'Cards','MadWeight_card.dat')) |
1390 | - |
1391 | + self.mw_card = mwcards.Card(path) |
1392 | + return path |
1393 | + |
1394 | +class EditParamCard(AskforEditCard): |
1395 | + """a dedicated module for the param""" |
1396 | + |
1397 | + special_shortcut ={} |
1398 | + |
1399 | + def __init__(self, question, card=[], mode='auto', *args, **opt): |
1400 | + |
1401 | + self.load_default() |
1402 | + cmd.OneLinePathCompletion.__init__(self, question, *args, **opt) |
1403 | + if os.path.isfile(card[0]): |
1404 | + self.param_card = check_param_card.ParamCard(card[0]) |
1405 | + self.paths['param'] = card[0] |
1406 | + if os.path.isfile(card[0].replace('.dat', '_default.dat')): |
1407 | + self.paths['param_default'] = card[0].replace('.dat', '_default.dat') |
1408 | + else: |
1409 | + self.paths['param_default'] = card[0] |
1410 | + else: |
1411 | + raise Exception, 'path %s do not exists' % card[0] |
1412 | + |
1413 | + self.pname2block, self.restricted_value = self.param_card.analyze_param_card() |
1414 | + self.cards=['param'] |
1415 | + |
1416 | + def do_asperge(self, *args, **opts): |
1417 | + "Not available" |
1418 | + logger.warning("asperge not available in this mode") |
1419 | + |
1420 | |
1421 | === modified file 'madgraph/interface/extended_cmd.py' |
1422 | --- madgraph/interface/extended_cmd.py 2016-06-20 10:26:01 +0000 |
1423 | +++ madgraph/interface/extended_cmd.py 2016-08-18 22:31:39 +0000 |
1424 | @@ -15,7 +15,6 @@ |
1425 | """ A file containing different extension of the cmd basic python library""" |
1426 | |
1427 | |
1428 | -import cmd |
1429 | import logging |
1430 | import os |
1431 | import pydoc |
1432 | @@ -68,22 +67,386 @@ |
1433 | return |
1434 | return deco_f |
1435 | return deco_debug |
1436 | - |
1437 | + |
1438 | +import string |
1439 | + |
1440 | +# The following is copy from the standard cmd routine but pass in new class type |
1441 | +__all__ = ["Cmd"] |
1442 | +PROMPT = '(Cmd) ' |
1443 | +IDENTCHARS = string.ascii_letters + string.digits + '_' |
1444 | +class OriginalCmd(object): |
1445 | + """A simple framework for writing line-oriented command interpreters. |
1446 | + |
1447 | + These are often useful for test harnesses, administrative tools, and |
1448 | + prototypes that will later be wrapped in a more sophisticated interface. |
1449 | + |
1450 | + A Cmd instance or subclass instance is a line-oriented interpreter |
1451 | + framework. There is no good reason to instantiate Cmd itself; rather, |
1452 | + it's useful as a superclass of an interpreter class you define yourself |
1453 | + in order to inherit Cmd's methods and encapsulate action methods. |
1454 | + |
1455 | + """ |
1456 | + prompt = PROMPT |
1457 | + identchars = IDENTCHARS |
1458 | + ruler = '=' |
1459 | + lastcmd = '' |
1460 | + intro = None |
1461 | + doc_leader = "" |
1462 | + doc_header = "Documented commands (type help <topic>):" |
1463 | + misc_header = "Miscellaneous help topics:" |
1464 | + undoc_header = "Undocumented commands:" |
1465 | + nohelp = "*** No help on %s" |
1466 | + use_rawinput = 1 |
1467 | + |
1468 | + def __init__(self, completekey='tab', stdin=None, stdout=None,**opt): |
1469 | + """Instantiate a line-oriented interpreter framework. |
1470 | + |
1471 | + The optional argument 'completekey' is the readline name of a |
1472 | + completion key; it defaults to the Tab key. If completekey is |
1473 | + not None and the readline module is available, command completion |
1474 | + is done automatically. The optional arguments stdin and stdout |
1475 | + specify alternate input and output file objects; if not specified, |
1476 | + sys.stdin and sys.stdout are used. |
1477 | + |
1478 | + """ |
1479 | + import sys |
1480 | + if stdin is not None: |
1481 | + self.stdin = stdin |
1482 | + else: |
1483 | + self.stdin = sys.stdin |
1484 | + if stdout is not None: |
1485 | + self.stdout = stdout |
1486 | + else: |
1487 | + self.stdout = sys.stdout |
1488 | + self.cmdqueue = [] |
1489 | + self.completekey = completekey |
1490 | + self.cmd_options = opt |
1491 | + |
1492 | + def cmdloop(self, intro=None): |
1493 | + """Repeatedly issue a prompt, accept input, parse an initial prefix |
1494 | + off the received input, and dispatch to action methods, passing them |
1495 | + the remainder of the line as argument. |
1496 | + |
1497 | + """ |
1498 | + |
1499 | + self.preloop() |
1500 | + if self.use_rawinput and self.completekey: |
1501 | + try: |
1502 | + import readline |
1503 | + self.old_completer = readline.get_completer() |
1504 | + readline.set_completer(self.complete) |
1505 | + readline.parse_and_bind(self.completekey+": complete") |
1506 | + except ImportError: |
1507 | + pass |
1508 | + try: |
1509 | + if intro is not None: |
1510 | + self.intro = intro |
1511 | + if self.intro: |
1512 | + self.stdout.write(str(self.intro)+"\n") |
1513 | + stop = None |
1514 | + while not stop: |
1515 | + if self.cmdqueue: |
1516 | + line = self.cmdqueue.pop(0) |
1517 | + else: |
1518 | + if self.use_rawinput: |
1519 | + try: |
1520 | + line = raw_input(self.prompt) |
1521 | + except EOFError: |
1522 | + line = 'EOF' |
1523 | + else: |
1524 | + self.stdout.write(self.prompt) |
1525 | + self.stdout.flush() |
1526 | + line = self.stdin.readline() |
1527 | + if not len(line): |
1528 | + line = 'EOF' |
1529 | + else: |
1530 | + line = line.rstrip('\r\n') |
1531 | + line = self.precmd(line) |
1532 | + stop = self.onecmd(line) |
1533 | + stop = self.postcmd(stop, line) |
1534 | + self.postloop() |
1535 | + finally: |
1536 | + if self.use_rawinput and self.completekey: |
1537 | + try: |
1538 | + import readline |
1539 | + readline.set_completer(self.old_completer) |
1540 | + except ImportError: |
1541 | + pass |
1542 | + |
1543 | + |
1544 | + def precmd(self, line): |
1545 | + """Hook method executed just before the command line is |
1546 | + interpreted, but after the input prompt is generated and issued. |
1547 | + |
1548 | + """ |
1549 | + return line |
1550 | + |
1551 | + def postcmd(self, stop, line): |
1552 | + """Hook method executed just after a command dispatch is finished.""" |
1553 | + return stop |
1554 | + |
1555 | + def preloop(self): |
1556 | + """Hook method executed once when the cmdloop() method is called.""" |
1557 | + pass |
1558 | + |
1559 | + def postloop(self): |
1560 | + """Hook method executed once when the cmdloop() method is about to |
1561 | + return. |
1562 | + |
1563 | + """ |
1564 | + pass |
1565 | + |
1566 | + def parseline(self, line): |
1567 | + """Parse the line into a command name and a string containing |
1568 | + the arguments. Returns a tuple containing (command, args, line). |
1569 | + 'command' and 'args' may be None if the line couldn't be parsed. |
1570 | + """ |
1571 | + line = line.strip() |
1572 | + if not line: |
1573 | + return None, None, line |
1574 | + elif line[0] == '?': |
1575 | + line = 'help ' + line[1:] |
1576 | + elif line[0] == '!': |
1577 | + if hasattr(self, 'do_shell'): |
1578 | + line = 'shell ' + line[1:] |
1579 | + else: |
1580 | + return None, None, line |
1581 | + i, n = 0, len(line) |
1582 | + while i < n and line[i] in self.identchars: i = i+1 |
1583 | + cmd, arg = line[:i], line[i:].strip() |
1584 | + return cmd, arg, line |
1585 | + |
1586 | + def onecmd(self, line): |
1587 | + """Interpret the argument as though it had been typed in response |
1588 | + to the prompt. |
1589 | + |
1590 | + This may be overridden, but should not normally need to be; |
1591 | + see the precmd() and postcmd() methods for useful execution hooks. |
1592 | + The return value is a flag indicating whether interpretation of |
1593 | + commands by the interpreter should stop. |
1594 | + |
1595 | + """ |
1596 | + cmd, arg, line = self.parseline(line) |
1597 | + if not line: |
1598 | + return self.emptyline() |
1599 | + if cmd is None: |
1600 | + return self.default(line) |
1601 | + self.lastcmd = line |
1602 | + if cmd == '': |
1603 | + return self.default(line) |
1604 | + else: |
1605 | + try: |
1606 | + func = getattr(self, 'do_' + cmd) |
1607 | + except AttributeError: |
1608 | + return self.default(line) |
1609 | + return func(arg) |
1610 | + |
1611 | + def emptyline(self): |
1612 | + """Called when an empty line is entered in response to the prompt. |
1613 | + |
1614 | + If this method is not overridden, it repeats the last nonempty |
1615 | + command entered. |
1616 | + |
1617 | + """ |
1618 | + if self.lastcmd: |
1619 | + return self.onecmd(self.lastcmd) |
1620 | + |
1621 | + def default(self, line): |
1622 | + """Called on an input line when the command prefix is not recognized. |
1623 | + |
1624 | + If this method is not overridden, it prints an error message and |
1625 | + returns. |
1626 | + |
1627 | + """ |
1628 | + self.stdout.write('*** Unknown syntax: %s\n'%line) |
1629 | + |
1630 | + def completedefault(self, *ignored): |
1631 | + """Method called to complete an input line when no command-specific |
1632 | + complete_*() method is available. |
1633 | + |
1634 | + By default, it returns an empty list. |
1635 | + |
1636 | + """ |
1637 | + return [] |
1638 | + |
1639 | + def completenames(self, text, *ignored): |
1640 | + dotext = 'do_'+text |
1641 | + return [a[3:] for a in self.get_names() if a.startswith(dotext)] |
1642 | + |
1643 | + def complete(self, text, state): |
1644 | + """Return the next possible completion for 'text'. |
1645 | + |
1646 | + If a command has not been entered, then complete against command list. |
1647 | + Otherwise try to call complete_<command> to get list of completions. |
1648 | + """ |
1649 | + if state == 0: |
1650 | + import readline |
1651 | + origline = readline.get_line_buffer() |
1652 | + line = origline.lstrip() |
1653 | + stripped = len(origline) - len(line) |
1654 | + begidx = readline.get_begidx() - stripped |
1655 | + endidx = readline.get_endidx() - stripped |
1656 | + if begidx>0: |
1657 | + cmd, args, foo = self.parseline(line) |
1658 | + if cmd == '': |
1659 | + compfunc = self.completedefault |
1660 | + else: |
1661 | + try: |
1662 | + compfunc = getattr(self, 'complete_' + cmd) |
1663 | + except AttributeError: |
1664 | + compfunc = self.completedefault |
1665 | + else: |
1666 | + compfunc = self.completenames |
1667 | + self.completion_matches = compfunc(text, line, begidx, endidx) |
1668 | + try: |
1669 | + return self.completion_matches[state] |
1670 | + except IndexError: |
1671 | + return None |
1672 | + |
1673 | + def get_names(self): |
1674 | + # Inheritance says we have to look in class and |
1675 | + # base classes; order is not important. |
1676 | + names = [] |
1677 | + classes = [self.__class__] |
1678 | + while classes: |
1679 | + aclass = classes.pop(0) |
1680 | + if aclass.__bases__: |
1681 | + classes = classes + list(aclass.__bases__) |
1682 | + names = names + dir(aclass) |
1683 | + return names |
1684 | + |
1685 | + def complete_help(self, *args): |
1686 | + return self.completenames(*args) |
1687 | + |
1688 | + def do_help(self, arg): |
1689 | + if arg: |
1690 | + # XXX check arg syntax |
1691 | + try: |
1692 | + func = getattr(self, 'help_' + arg) |
1693 | + except AttributeError: |
1694 | + try: |
1695 | + doc=getattr(self, 'do_' + arg).__doc__ |
1696 | + if doc: |
1697 | + self.stdout.write("%s\n"%str(doc)) |
1698 | + return |
1699 | + except AttributeError: |
1700 | + pass |
1701 | + self.stdout.write("%s\n"%str(self.nohelp % (arg,))) |
1702 | + return |
1703 | + func() |
1704 | + else: |
1705 | + names = self.get_names() |
1706 | + cmds_doc = [] |
1707 | + cmds_undoc = [] |
1708 | + help = {} |
1709 | + for name in names: |
1710 | + if name[:5] == 'help_': |
1711 | + help[name[5:]]=1 |
1712 | + names.sort() |
1713 | + # There can be duplicates if routines overridden |
1714 | + prevname = '' |
1715 | + for name in names: |
1716 | + if name[:3] == 'do_': |
1717 | + if name == prevname: |
1718 | + continue |
1719 | + prevname = name |
1720 | + cmd=name[3:] |
1721 | + if cmd in help: |
1722 | + cmds_doc.append(cmd) |
1723 | + del help[cmd] |
1724 | + elif getattr(self, name).__doc__: |
1725 | + cmds_doc.append(cmd) |
1726 | + else: |
1727 | + cmds_undoc.append(cmd) |
1728 | + self.stdout.write("%s\n"%str(self.doc_leader)) |
1729 | + self.print_topics(self.doc_header, cmds_doc, 15,80) |
1730 | + self.print_topics(self.misc_header, help.keys(),15,80) |
1731 | + self.print_topics(self.undoc_header, cmds_undoc, 15,80) |
1732 | + |
1733 | + def print_topics(self, header, cmds, cmdlen, maxcol): |
1734 | + if cmds: |
1735 | + self.stdout.write("%s\n"%str(header)) |
1736 | + if self.ruler: |
1737 | + self.stdout.write("%s\n"%str(self.ruler * len(header))) |
1738 | + self.columnize(cmds, maxcol-1) |
1739 | + self.stdout.write("\n") |
1740 | + |
1741 | + def columnize(self, list, displaywidth=80): |
1742 | + """Display a list of strings as a compact set of columns. |
1743 | + |
1744 | + Each column is only as wide as necessary. |
1745 | + Columns are separated by two spaces (one was not legible enough). |
1746 | + """ |
1747 | + if not list: |
1748 | + self.stdout.write("<empty>\n") |
1749 | + return |
1750 | + nonstrings = [i for i in range(len(list)) |
1751 | + if not isinstance(list[i], str)] |
1752 | + if nonstrings: |
1753 | + raise TypeError, ("list[i] not a string for i in %s" % |
1754 | + ", ".join(map(str, nonstrings))) |
1755 | + size = len(list) |
1756 | + if size == 1: |
1757 | + self.stdout.write('%s\n'%str(list[0])) |
1758 | + return |
1759 | + # Try every row count from 1 upwards |
1760 | + for nrows in range(1, len(list)): |
1761 | + ncols = (size+nrows-1) // nrows |
1762 | + colwidths = [] |
1763 | + totwidth = -2 |
1764 | + for col in range(ncols): |
1765 | + colwidth = 0 |
1766 | + for row in range(nrows): |
1767 | + i = row + nrows*col |
1768 | + if i >= size: |
1769 | + break |
1770 | + x = list[i] |
1771 | + colwidth = max(colwidth, len(x)) |
1772 | + colwidths.append(colwidth) |
1773 | + totwidth += colwidth + 2 |
1774 | + if totwidth > displaywidth: |
1775 | + break |
1776 | + if totwidth <= displaywidth: |
1777 | + break |
1778 | + else: |
1779 | + nrows = len(list) |
1780 | + ncols = 1 |
1781 | + colwidths = [0] |
1782 | + for row in range(nrows): |
1783 | + texts = [] |
1784 | + for col in range(ncols): |
1785 | + i = row + nrows*col |
1786 | + if i >= size: |
1787 | + x = "" |
1788 | + else: |
1789 | + x = list[i] |
1790 | + texts.append(x) |
1791 | + while texts and not texts[-1]: |
1792 | + del texts[-1] |
1793 | + for col in range(len(texts)): |
1794 | + texts[col] = texts[col].ljust(colwidths[col]) |
1795 | + self.stdout.write("%s\n"%str(" ".join(texts))) |
1796 | + |
1797 | + |
1798 | + |
1799 | |
1800 | #=============================================================================== |
1801 | # CmdExtended |
1802 | #=============================================================================== |
1803 | -class BasicCmd(cmd.Cmd): |
1804 | +class BasicCmd(OriginalCmd): |
1805 | """Simple extension for the readline""" |
1806 | |
1807 | def preloop(self): |
1808 | if readline and not 'libedit' in readline.__doc__: |
1809 | readline.set_completion_display_matches_hook(self.print_suggestions) |
1810 | |
1811 | - def deal_multiple_categories(self, dico, forceCategory=False): |
1812 | + def deal_multiple_categories(self, dico, formatting=True, forceCategory=False): |
1813 | """convert the multiple category in a formatted list understand by our |
1814 | specific readline parser""" |
1815 | |
1816 | + if not formatting: |
1817 | + return dico |
1818 | + |
1819 | if 'libedit' in readline.__doc__: |
1820 | # No parser in this case, just send all the valid options |
1821 | out = [] |
1822 | @@ -316,7 +679,7 @@ |
1823 | prefix += os.path.sep |
1824 | |
1825 | if only_dirs: |
1826 | - completion = [prefix + f |
1827 | + completion = [prefix + f + os.path.sep |
1828 | for f in os.listdir(base_dir) |
1829 | if f.startswith(text) and \ |
1830 | os.path.isdir(os.path.join(base_dir, f)) and \ |
1831 | @@ -493,7 +856,7 @@ |
1832 | self.log = True |
1833 | self.history = [] |
1834 | self.save_line = '' # for line splitting |
1835 | - cmd.Cmd.__init__(self, *arg, **opt) |
1836 | + super(Cmd, self).__init__(*arg, **opt) |
1837 | self.__initpos = os.path.abspath(os.getcwd()) |
1838 | self.child = None # sub CMD interface call from this one |
1839 | self.mother = None #This CMD interface was called from another one |
1840 | @@ -657,7 +1020,7 @@ |
1841 | else: |
1842 | path_msg = [] |
1843 | |
1844 | - if timeout: |
1845 | + if timeout is True: |
1846 | try: |
1847 | timeout = self.options['timeout'] |
1848 | except Exception: |
1849 | @@ -709,7 +1072,10 @@ |
1850 | if answer in alias: |
1851 | answer = alias[answer] |
1852 | if ask_class: |
1853 | - answer = question_instance.default(answer) |
1854 | + line=answer |
1855 | + answer = question_instance.default(line) |
1856 | + question_instance.postcmd(answer, line) |
1857 | + return question_instance.answer |
1858 | if hasattr(question_instance, 'check_answer_consistency'): |
1859 | question_instance.check_answer_consistency() |
1860 | return answer |
1861 | @@ -723,6 +1089,7 @@ |
1862 | value = alias[value] |
1863 | except TypeError: |
1864 | pass |
1865 | + |
1866 | if value == default and ask_class: |
1867 | value = question_instance.default(default) |
1868 | return value |
1869 | @@ -771,7 +1138,7 @@ |
1870 | logger.info('The answer to the previous question is not set in your input file', '$MG:color:BLACK') |
1871 | logger.info('Use %s value' % default, '$MG:color:BLACK') |
1872 | return str(default) |
1873 | - |
1874 | + |
1875 | line = line.replace('\n','').strip() |
1876 | if '#' in line: |
1877 | line = line.split('#')[0] |
1878 | @@ -839,7 +1206,7 @@ |
1879 | if os.path.exists(self.debug_output): |
1880 | os.remove(self.debug_output) |
1881 | try: |
1882 | - cmd.Cmd.onecmd(self, 'history %s' % self.debug_output.replace(' ', '\ ')) |
1883 | + super(Cmd,self).onecmd('history %s' % self.debug_output.replace(' ', '\ ')) |
1884 | except Exception, error: |
1885 | logger.error(error) |
1886 | |
1887 | @@ -888,7 +1255,7 @@ |
1888 | return self.child.nice_user_error(error, line) |
1889 | # Make sure that we are at the initial position |
1890 | os.chdir(self.__initpos) |
1891 | - if line == self.history[-1]: |
1892 | + if not self.history or line == self.history[-1]: |
1893 | error_text = 'Command \"%s\" interrupted with error:\n' % line |
1894 | else: |
1895 | error_text = 'Command \"%s\" interrupted in sub-command:\n' %line |
1896 | @@ -914,7 +1281,7 @@ |
1897 | error_text = 'Error detected in sub-command %s\n' % self.history[-1] |
1898 | error_text += 'write debug file %s \n' % self.debug_output |
1899 | self.log = False |
1900 | - cmd.Cmd.onecmd(self, 'history %s' % self.debug_output) |
1901 | + super(Cmd,self).onecmd('history %s' % self.debug_output) |
1902 | debug_file = open(self.debug_output, 'a') |
1903 | traceback.print_exc(file=debug_file) |
1904 | error_text += self.config_debug % {'debug' :self.debug_output} |
1905 | @@ -1018,17 +1385,18 @@ |
1906 | pass # dummy function |
1907 | |
1908 | def exec_cmd(self, line, errorhandling=False, printcmd=True, |
1909 | - precmd=False, postcmd=True, **opt): |
1910 | + precmd=False, postcmd=True, |
1911 | + child=True, **opt): |
1912 | """for third party call, call the line with pre and postfix treatment |
1913 | without global error handling """ |
1914 | |
1915 | + |
1916 | if printcmd and not line.startswith('#'): |
1917 | logger.info(line) |
1918 | - if self.child: |
1919 | + if self.child and child: |
1920 | current_interface = self.child |
1921 | else: |
1922 | current_interface = self |
1923 | - |
1924 | if precmd: |
1925 | line = current_interface.precmd(line) |
1926 | if errorhandling: |
1927 | @@ -1061,11 +1429,7 @@ |
1928 | |
1929 | if self.history and self.history[-1] == line: |
1930 | self.history.pop() |
1931 | - |
1932 | - |
1933 | - |
1934 | - |
1935 | - |
1936 | + |
1937 | # Write the list of command line use in this session |
1938 | def do_history(self, line): |
1939 | """write in a file the suite of command that was used""" |
1940 | @@ -1258,7 +1622,7 @@ |
1941 | |
1942 | # if they are an argument use the default help |
1943 | if line: |
1944 | - return cmd.Cmd.do_help(self, line) |
1945 | + return super(Cmd, self).do_help(line) |
1946 | |
1947 | |
1948 | names = self.get_names() |
1949 | @@ -1526,12 +1890,16 @@ |
1950 | class SmartQuestion(BasicCmd): |
1951 | """ a class for answering a question with the path autocompletion""" |
1952 | |
1953 | + allowpath = False |
1954 | def preloop(self): |
1955 | """Initializing before starting the main loop""" |
1956 | self.prompt = '>' |
1957 | self.value = None |
1958 | BasicCmd.preloop(self) |
1959 | |
1960 | + @property |
1961 | + def answer(self): |
1962 | + return self.value |
1963 | |
1964 | def __init__(self, question, allow_arg=[], default=None, |
1965 | mother_interface=None, *arg, **opt): |
1966 | @@ -1541,7 +1909,7 @@ |
1967 | self.history_header = '' |
1968 | self.default_value = str(default) |
1969 | self.mother_interface = mother_interface |
1970 | - cmd.Cmd.__init__(self, *arg, **opt) |
1971 | + super(SmartQuestion, self).__init__(*arg, **opt) |
1972 | |
1973 | def __call__(self, question, reprint_opt=True, **opts): |
1974 | |
1975 | @@ -1604,6 +1972,8 @@ |
1976 | return func(arg, **opt) |
1977 | except Exception as error: |
1978 | logger.warning(error) |
1979 | + if __debug__: |
1980 | + raise |
1981 | |
1982 | def reask(self, reprint_opt=True): |
1983 | pat = re.compile('\[(\d*)s to answer\]') |
1984 | @@ -1620,6 +1990,15 @@ |
1985 | if not prev_timer: |
1986 | self.question = pat.sub('',self.question) |
1987 | print self.question |
1988 | + |
1989 | + if self.mother_interface: |
1990 | + answer = self.mother_interface.check_answer_in_input_file(self, 'EOF', |
1991 | + path=self.allowpath) |
1992 | + if answer: |
1993 | + stop = self.default(answer) |
1994 | + self.postcmd(stop, answer) |
1995 | + return False |
1996 | + |
1997 | return False |
1998 | |
1999 | def default(self, line): |
2000 | @@ -1665,8 +2044,8 @@ |
2001 | return True |
2002 | |
2003 | def cmdloop(self, intro=None): |
2004 | - cmd.Cmd.cmdloop(self, intro) |
2005 | - return self.value |
2006 | + super(SmartQuestion,self).cmdloop(intro) |
2007 | + return self.answer |
2008 | |
2009 | # a function helper |
2010 | def smart_input(input_text, allow_arg=[], default=None): |
2011 | @@ -1681,8 +2060,9 @@ |
2012 | """ a class for answering a question with the path autocompletion""" |
2013 | |
2014 | completion_prefix='' |
2015 | + allowpath=True |
2016 | |
2017 | - def completenames(self, text, line, begidx, endidx): |
2018 | + def completenames(self, text, line, begidx, endidx, formatting=True): |
2019 | prev_timer = signal.alarm(0) # avoid timer if any |
2020 | if prev_timer: |
2021 | nb_back = len(line) |
2022 | @@ -1696,7 +2076,7 @@ |
2023 | out[' Path from ./'] = Cmd.path_completion(text, only_dirs = False) |
2024 | out[' Recognized command'] = BasicCmd.completenames(self, text) |
2025 | |
2026 | - return self.deal_multiple_categories(out) |
2027 | + return self.deal_multiple_categories(out, formatting) |
2028 | except Exception, error: |
2029 | print error |
2030 | |
2031 | @@ -1748,8 +2128,9 @@ |
2032 | % ','.join(self.allow_arg) |
2033 | print 'please retry' |
2034 | reprint_opt = False |
2035 | - |
2036 | - return self.reask(reprint_opt) |
2037 | + |
2038 | + if line != 'EOF': |
2039 | + return self.reask(reprint_opt) |
2040 | |
2041 | |
2042 | # a function helper |
2043 | |
2044 | === modified file 'madgraph/interface/loop_interface.py' |
2045 | --- madgraph/interface/loop_interface.py 2016-05-26 00:13:49 +0000 |
2046 | +++ madgraph/interface/loop_interface.py 2016-08-18 22:31:39 +0000 |
2047 | @@ -25,6 +25,7 @@ |
2048 | import madgraph |
2049 | from madgraph import MG4DIR, MG5DIR, MadGraph5Error |
2050 | import madgraph.interface.madgraph_interface as mg_interface |
2051 | +import madgraph.interface.extended_cmd as cmd |
2052 | import madgraph.interface.launch_ext_program as launch_ext |
2053 | import madgraph.interface.extended_cmd as extended_cmd |
2054 | import madgraph.core.base_objects as base_objects |
2055 | @@ -465,11 +466,11 @@ |
2056 | noclean, output_type=output_type, group_subprocesses=False) |
2057 | |
2058 | if self._export_format in ['standalone', 'matchbox']: |
2059 | - self._curr_exporter.copy_v4template(modelname=self._curr_model.get('name')) |
2060 | + self._curr_exporter.copy_template(self._curr_model) |
2061 | |
2062 | if self._export_format == "standalone_rw": |
2063 | self._export_format = "standalone" |
2064 | - self._curr_exporter.copy_v4template(modelname=self._curr_model.get('name')) |
2065 | + self._curr_exporter.copy_template(self._curr_model) |
2066 | self._export_format = "standalone_rw" |
2067 | |
2068 | # Reset _done_export, since we have new directory |
2069 | @@ -490,11 +491,105 @@ |
2070 | # Put aloha back in its original mode. |
2071 | aloha.mp_precision = aloha_original_quad_mode |
2072 | |
2073 | + |
2074 | + def install_reduction_library(self): |
2075 | + """Code to install the reduction library if needed""" |
2076 | + |
2077 | + opt = self.options |
2078 | + |
2079 | + |
2080 | + # Check if first time: |
2081 | + if (opt['ninja'] is None) or (os.path.isfile(pjoin(opt['ninja'],'libninja.a'))): |
2082 | + return |
2083 | + |
2084 | + logger.info("First output using loop matrix-elements has been detected. Now asking for loop reduction:", '$MG:color:BLACK') |
2085 | + to_install = self.ask('install', '0', ask_class=AskLoopInstaller, timeout=300, |
2086 | + path_msg=' ') |
2087 | + |
2088 | + |
2089 | + for key, value in to_install.items(): |
2090 | + if key in ['cuttools', 'iregi']: |
2091 | + if os.path.sep not in value: |
2092 | + continue |
2093 | + import madgraph.iolibs.files as files |
2094 | + if key == 'cuttools': |
2095 | + if os.path.exists(pjoin(value, 'includects')): |
2096 | + path = pjoin(value, 'includects') |
2097 | + elif os.path.exists(pjoin(value, 'CutTools','includects')): |
2098 | + path = pjoin(value, 'CutTools', 'includects') |
2099 | + elif os.path.exists(pjoin(value, 'vendor','CutTools','includects')): |
2100 | + path = pjoin(value, 'vendor','CutTools', 'includects') |
2101 | + else: |
2102 | + logger.warning('invalid path for cuttools import') |
2103 | + continue |
2104 | + |
2105 | + target = pjoin(MG5DIR,'vendor','CutTools','includects') |
2106 | + if not os.path.exists(target): |
2107 | + os.mkdir(target) |
2108 | + files.cp(pjoin(path,'libcts.a'), target) |
2109 | + files.cp(pjoin(path,'mpmodule.mod'), target, log=True) |
2110 | + if os.path.exists(pjoin(path,'compiler_version.log')): |
2111 | + files.cp(pjoin(path,'compiler_version.log'), target) |
2112 | + |
2113 | + if key == 'iregi': |
2114 | + if os.path.exists(pjoin(value, 'src','IREGI4ML5_interface.f90')): |
2115 | + path = pjoin(value, 'src') |
2116 | + elif os.path.exists(pjoin(value, 'IREGI','src','IREGI4ML5_interface.f90')): |
2117 | + path = pjoin(value, 'IREGI', 'src') |
2118 | + elif os.path.exists(pjoin(value, 'vendor','IREGI','src','IREGI4ML5_interface.f90')): |
2119 | + path = pjoin(value, 'vendor', 'IREGI', 'src') |
2120 | + else: |
2121 | + logger.warning('invalid path for IREGI import') |
2122 | + continue |
2123 | + |
2124 | + target = pjoin(MG5DIR,'vendor','IREGI','src') |
2125 | + files.cp(pjoin(path,'libiregi.a'), target, log=True) |
2126 | + elif value == 'local': |
2127 | + ## LOCAL INSTALLATION OF NINJA/COLLIER |
2128 | + logger.info( |
2129 | +"""MG5aMC will now install the loop reduction tool '%(p)s' from the local offline installer. |
2130 | +Use the command 'install $(p)s' if you want to update to the latest online version. |
2131 | +This installation can take some time but only needs to be performed once.""" %{'p': key},'$MG:color:GREEN') |
2132 | + additional_options = ['--ninja_tarball=%s'%pjoin(MG5DIR,'vendor','%s.tar.gz' % key)] |
2133 | + if key == 'ninja': |
2134 | + additional_options.append('--oneloop_tarball=%s'%pjoin(MG5DIR,'vendor','oneloop.tar.gz')) |
2135 | + |
2136 | + try: |
2137 | + self.do_install(key,paths={'HEPToolsInstaller': |
2138 | + pjoin(MG5DIR,'vendor','OfflineHEPToolsInstaller.tar.gz')}, |
2139 | + additional_options=additional_options) |
2140 | + except self.InvalidCmd: |
2141 | + logger.warning( |
2142 | +"""The offline installation of %(p)s was unsuccessful, and MG5aMC disabled it. |
2143 | +In the future, if you want to reactivate Ninja, you can do so by re-attempting |
2144 | +its online installation with the command 'install %(p)s' or install it on your |
2145 | +own and set the path to its library in the MG5aMC option '%(p)s'.""" % {'p': key}) |
2146 | + self.exec_cmd("set %s ''" % key) |
2147 | + self.exec_cmd('save options') |
2148 | + |
2149 | + # ONLINE INSTALLATION |
2150 | + elif value == 'install': |
2151 | + prog = {'pjfry': 'PJFry', 'golem': 'Golem95'} |
2152 | + if key in prog: |
2153 | + self.exec_cmd('install %s' % prog[key]) |
2154 | + else: |
2155 | + self.exec_cmd('install %s' % key) |
2156 | + # Not install |
2157 | + elif value == 'off': |
2158 | + self.exec_cmd("set %s ''" % key) |
2159 | + self.exec_cmd('save options %s' % key) |
2160 | + else: |
2161 | + self.exec_cmd("set %s %s" % (key,value)) |
2162 | + self.exec_cmd('save options %s' % key) |
2163 | + |
2164 | + |
2165 | + |
2166 | # Export a matrix element |
2167 | - |
2168 | def ML5export(self, nojpeg = False, main_file_name = ""): |
2169 | """Export a generated amplitude to file""" |
2170 | |
2171 | + if not self._curr_helas_model: |
2172 | + self._curr_helas_model = helas_call_writers.FortranUFOHelasCallWriter(self._curr_model) |
2173 | def generate_matrix_elements(self): |
2174 | """Helper function to generate the matrix elements before exporting""" |
2175 | |
2176 | @@ -540,9 +635,8 @@ |
2177 | if self._export_format in self.supported_ML_format: |
2178 | for unique_id, me in enumerate(matrix_elements): |
2179 | calls = calls + \ |
2180 | - self._curr_exporter.generate_subprocess_directory_v4(\ |
2181 | - me, self._curr_fortran_model, (unique_id+1)) |
2182 | - self._curr_exporter.write_global_specs(matrix_elements) |
2183 | + self._curr_exporter.generate_subprocess_directory(\ |
2184 | + me, self._curr_helas_model) |
2185 | # If all ME's do not share the same maximum loop vertex rank and the |
2186 | # same loop maximum wavefunction size, we need to set the maximum |
2187 | # in coef_specs.inc of the HELAS Source. The SubProcesses/P* directory |
2188 | @@ -555,7 +649,6 @@ |
2189 | if len(set(max_lwfspins))>1 or len(set(max_loop_vert_ranks))>1: |
2190 | self._curr_exporter.fix_coef_specs(max(max_lwfspins),\ |
2191 | max(max_loop_vert_ranks)) |
2192 | - self._curr_exporter.write_global_specs(matrix_elements) |
2193 | |
2194 | # Just the matrix.f files |
2195 | if self._export_format == 'matrix': |
2196 | @@ -568,7 +661,7 @@ |
2197 | logger.info("Creating new file %s" % filename) |
2198 | calls = calls + self._curr_exporter.write_matrix_element_v4(\ |
2199 | writers.FortranWriter(filename),\ |
2200 | - me, self._curr_fortran_model) |
2201 | + me, self._curr_helas_model) |
2202 | |
2203 | cpu_time2 = time.time() - cpu_time1 |
2204 | |
2205 | @@ -611,21 +704,22 @@ |
2206 | del self.previous_lorentz |
2207 | del self.previous_couplings |
2208 | |
2209 | - self._curr_exporter.convert_model_to_mg4(self._curr_model, |
2210 | + self._curr_exporter.convert_model(self._curr_model, |
2211 | wanted_lorentz, |
2212 | wanted_couplings) |
2213 | - |
2214 | - compiler = {'fortran': self.options['fortran_compiler'], |
2215 | - 'f2py': self.options['f2py_compiler'], |
2216 | - 'cpp': self.options['cpp_compiler']} |
2217 | |
2218 | if self._export_format in self.supported_ML_format: |
2219 | - self._curr_exporter.finalize_v4_directory( \ |
2220 | + flags = [] |
2221 | + if nojpeg: |
2222 | + flags.append('nojpeg') |
2223 | + if online: |
2224 | + flags.append('online') |
2225 | + |
2226 | + self._curr_exporter.finalize( \ |
2227 | self._curr_matrix_elements, |
2228 | self.history, |
2229 | - not nojpeg, |
2230 | - online, |
2231 | - compiler) |
2232 | + self.options, |
2233 | + flags) |
2234 | |
2235 | if self._export_format in self.supported_ML_format: |
2236 | logger.info('Output to directory ' + self._export_dir + ' done.') |
2237 | @@ -791,3 +885,207 @@ |
2238 | class LoopInterfaceWeb(mg_interface.CheckValidForCmdWeb, LoopInterface): |
2239 | pass |
2240 | |
2241 | + |
2242 | +class AskLoopInstaller(cmd.OneLinePathCompletion): |
2243 | + |
2244 | + local_installer = ['ninja', 'collier'] |
2245 | + required = ['cuttools', 'iregi'] |
2246 | + order = ['cuttools', 'iregi', 'ninja', 'collier', 'golem', 'pjfry'] |
2247 | + |
2248 | + @property |
2249 | + def answer(self): |
2250 | + return self.code |
2251 | + |
2252 | + |
2253 | + def __init__(self, question, *args, **opts): |
2254 | + |
2255 | + import urllib2 |
2256 | + try: |
2257 | + response=urllib2.urlopen('http://madgraph.phys.ucl.ac.be/F1.html', timeout=3) |
2258 | + self.online=True |
2259 | + except urllib2.URLError as err: |
2260 | + self.online=False |
2261 | + |
2262 | + self.code = {'ninja': 'install', |
2263 | + 'collier': 'install', |
2264 | + 'golem': 'off', |
2265 | + 'pjfry':'off', |
2266 | + 'cuttools': 'required', |
2267 | + 'iregi': 'required'} |
2268 | + if not self.online: |
2269 | + self.code['ninja'] = 'local' |
2270 | + self.code['collier'] = 'local' |
2271 | + self.code['pjfry'] = 'fail' |
2272 | + self.code['golem'] = 'fail' |
2273 | + if not misc.which('cmake'): |
2274 | + self.code['collier'] = 'off' |
2275 | + |
2276 | + |
2277 | + |
2278 | + |
2279 | + # 1. create the question |
2280 | + question, allowed_answer = self.create_question(first=True) |
2281 | + |
2282 | + opts['allow_arg'] = allowed_answer |
2283 | + |
2284 | + cmd.OneLinePathCompletion.__init__(self, question, *args, **opts) |
2285 | + |
2286 | + |
2287 | + def create_question(self, first = False): |
2288 | + """ """ |
2289 | + |
2290 | + question = "For loop computations, MadLoop requires dedicated tools to"+\ |
2291 | + " perform the reduction of loop Feynman diagrams using OPP-based and/or TIR approaches.\n"+\ |
2292 | + "\nWhich one do you want to install? (this needs to be done only once)\n" |
2293 | + |
2294 | + allowed_answer = set(['0','done']) |
2295 | + |
2296 | + descript = {'cuttools': ['cuttools','(OPP)','[0711.3596]'], |
2297 | + 'iregi': ['iregi','(TIR)','[1405.0301]'], |
2298 | + 'ninja': ['ninja','(OPP)','[1403.1229]'], |
2299 | + 'pjfry': ['pjfry','(TIR)','[1112.0500]'], |
2300 | + 'golem': ['golem','(TIR)','[0807.0605]'], |
2301 | + 'collier': ['collier','(TIR)','[1604.06792]']} |
2302 | + |
2303 | + |
2304 | + status = {'off': '%(start_red)sdo not install%(stop)s', |
2305 | + 'install': '%(start_green)swill be installed %(stop)s', |
2306 | + 'local': '%(start_green)swill be installed %(stop)s(offline installation from local repository)', |
2307 | + 'fail': 'not available without internet connection', |
2308 | + 'required': 'will be installed (required)'} |
2309 | + |
2310 | + for i,key in enumerate(self.order,1): |
2311 | + if os.path.sep not in self.code[key]: |
2312 | + question += '%s. %%(start_blue)s%-9s %-5s %-13s%%(stop)s : %s%s\n' % \ |
2313 | + tuple([i,]+descript[key]+[status[self.code[key]],]+\ |
2314 | + ['(recommended)' if key in ['ninja','collier'] and self.code[key] in ['install'] else '']) |
2315 | + else: |
2316 | + question += '%s. %%(start_blue)s%-9s %-5s %-13s%%(stop)s : %s\n' % tuple([i,]+descript[key]+[self.code[key],]) |
2317 | + if key in self.required: |
2318 | + continue |
2319 | + allowed_answer.update([str(i), key]) |
2320 | + if key in self.local_installer: |
2321 | + allowed_answer.update(['key=local','key=off']) |
2322 | + if self.online: |
2323 | + allowed_answer.update(['key=on','key=install', 'key=off']) |
2324 | + |
2325 | + question += "You can:\n -> hit 'enter' to proceed\n -> type a number to cycle its options\n -> enter the following command:\n"+\ |
2326 | + ' %(start_blue)s{tool_name}%(stop)s [%(start_blue)sinstall%(stop)s|%(start_blue)snoinstall%(stop)s|'+\ |
2327 | + '%(start_blue)s{prefixed_installation_path}%(stop)s]\n' |
2328 | + if first: |
2329 | + question += '\n%(start_bold)s%(start_red)sIf you are unsure about what this question means, just type enter to proceed. %(stop)s' |
2330 | + |
2331 | + question = question % {'start_green' : '\033[92m', |
2332 | + 'start_red' : '\033[91m', |
2333 | + 'start_blue' : '\033[34m', |
2334 | + 'stop': '\033[0m', |
2335 | + 'start_bold':'\033[1m', |
2336 | + } |
2337 | + return question, allowed_answer |
2338 | + |
2339 | + def default(self, line): |
2340 | + """Default action if line is not recognized""" |
2341 | + |
2342 | + line = line.strip() |
2343 | + args = line.split() |
2344 | + |
2345 | + if line in ['0', 'done','','EOF']: |
2346 | + self.value = 'done' |
2347 | + return self.answer |
2348 | + self.value = 'repeat' |
2349 | + if args: |
2350 | + if len(args) ==1 and '=' in args[0]: |
2351 | + args = args[0].split('=') |
2352 | + args[0] = args[0].lower() |
2353 | + if len(args) == 1: |
2354 | + # loop over the possibility |
2355 | + if args[0].isdigit(): |
2356 | + if len(self.order) < int(args[0]): |
2357 | + logger.warning('Invalid integer %s. Please Retry' % args[0]) |
2358 | + return |
2359 | + args[0] = self.order[int(args[0])-1] |
2360 | + key = args[0] |
2361 | + if key in self.code: |
2362 | + if self.code[key] in ['off']: |
2363 | + if self.online: |
2364 | + self.code[key] = 'install' |
2365 | + elif key in self.local_installer: |
2366 | + self.code[key] = 'local' |
2367 | + elif self.code[key] == 'install': |
2368 | + if key in self.local_installer: |
2369 | + self.code[key] = 'local' |
2370 | + else: |
2371 | + self.code[key] = 'off' |
2372 | + elif self.code[key] == 'local': |
2373 | + self.code[key] = 'off' |
2374 | + else: |
2375 | + logger.warning('Unknown entry \'%s\'. Please retry' % key) |
2376 | + return |
2377 | + elif len(args) == 2: |
2378 | + key = args[0] |
2379 | + if key not in self.code: |
2380 | + logger.warning('unknown %s type of entry. Bypass command.') |
2381 | + return |
2382 | + if os.path.sep not in args[1]: |
2383 | + value = args[1].lower() |
2384 | + if value in ['off', 'not','noinstall']: |
2385 | + self.code[key] = 'off' |
2386 | + elif value in ['on', 'install']: |
2387 | + if self.online: |
2388 | + self.code[key] = 'install' |
2389 | + elif key in self.local_installer: |
2390 | + self.code[key] = 'local' |
2391 | + else: |
2392 | + logger.warning('offline installer not available for %s', key) |
2393 | + self.code[key] = 'off' |
2394 | + elif value in ['local']: |
2395 | + if key in self.local_installer: |
2396 | + self.code[key] = 'local' |
2397 | + else: |
2398 | + logger.warning('offline installer not available for %s', key) |
2399 | + self.code[key] = 'off' |
2400 | + else: |
2401 | + self.code[key] = args[1] |
2402 | + else: |
2403 | + self.value = 0 |
2404 | + self.question,self.allow_arg = self.create_question() |
2405 | + return self.answer |
2406 | + |
2407 | + def apply_name(self, name, line): |
2408 | + |
2409 | + if line.startswith('='): |
2410 | + line = line[1:] |
2411 | + return self.default('%s %s' % (name,line)) |
2412 | + |
2413 | + |
2414 | + do_ninja = lambda self,line : self.apply_name('ninja', line) |
2415 | + do_pjfry = lambda self,line : self.apply_name('pjfry', line) |
2416 | + do_collier = lambda self,line : self.apply_name('collier', line) |
2417 | + do_golem = lambda self,line : self.apply_name('golem', line) |
2418 | + do_cuttools = lambda self,line : self.apply_name('cuttools', line) |
2419 | + do_iregi = lambda self,line : self.apply_name('iregi', line) |
2420 | + |
2421 | + |
2422 | + def complete_prog(self, text, line, begidx, endidx, formatting=True): |
2423 | + |
2424 | + if os.path.sep in line: |
2425 | + args = line[0:begidx].split() |
2426 | + if args[-1].endswith(os.path.sep): |
2427 | + return self.path_completion(text, |
2428 | + pjoin(*[a for a in args if a.endswith(os.path.sep)]), |
2429 | + only_dirs = True) |
2430 | + else: |
2431 | + return self.path_completion(text, '.', only_dirs = True) |
2432 | + else: |
2433 | + return self.list_completion(text, ['install', 'noinstall', 'local'], line) |
2434 | + |
2435 | + complete_ninja = complete_prog |
2436 | + complete_pjfry = complete_prog |
2437 | + complete_collier = complete_prog |
2438 | + complete_golem = complete_prog |
2439 | + complete_cuttools = complete_prog |
2440 | + complete_iregi = complete_prog |
2441 | + |
2442 | + |
2443 | + |
2444 | + |
2445 | |
2446 | === modified file 'madgraph/interface/madevent_interface.py' |
2447 | --- madgraph/interface/madevent_interface.py 2016-08-14 00:17:23 +0000 |
2448 | +++ madgraph/interface/madevent_interface.py 2016-08-18 22:31:39 +0000 |
2449 | @@ -1293,7 +1293,7 @@ |
2450 | else: |
2451 | return self.list_completion(text, ['--threshold='], line) |
2452 | |
2453 | - def complete_banner_run(self, text, line, begidx, endidx): |
2454 | + def complete_banner_run(self, text, line, begidx, endidx, formatting=True): |
2455 | "Complete the banner run command" |
2456 | try: |
2457 | |
2458 | @@ -1331,7 +1331,7 @@ |
2459 | run_list = [n.rsplit('/',2)[1] for n in run_list] |
2460 | possibilites['RUN Name'] = self.list_completion(text, run_list) |
2461 | |
2462 | - return self.deal_multiple_categories(possibilites) |
2463 | + return self.deal_multiple_categories(possibilites, formatting) |
2464 | |
2465 | |
2466 | except Exception, error: |
2467 | @@ -1511,7 +1511,7 @@ |
2468 | else: |
2469 | return self.list_completion(text, self._plot_mode + self.results.keys()) |
2470 | |
2471 | - def complete_syscalc(self, text, line, begidx, endidx): |
2472 | + def complete_syscalc(self, text, line, begidx, endidx, formatting=True): |
2473 | """ Complete the syscalc command """ |
2474 | |
2475 | output = {} |
2476 | @@ -1527,7 +1527,7 @@ |
2477 | tags = ['--tag=%s' % tag['tag'] for tag in self.results[run]] |
2478 | output['options'] += tags |
2479 | |
2480 | - return self.deal_multiple_categories(output) |
2481 | + return self.deal_multiple_categories(output, formatting) |
2482 | |
2483 | def complete_remove(self, text, line, begidx, endidx): |
2484 | """Complete the remove command """ |
2485 | @@ -2035,7 +2035,9 @@ |
2486 | #check if the param_card defines a scan. |
2487 | orig_name = self.run_name |
2488 | for card in param_card_iterator: |
2489 | + path = pjoin(self.me_dir,'Cards','param_card.dat') |
2490 | card.write(pjoin(self.me_dir,'Cards','param_card.dat')) |
2491 | + self.check_param_card(path, dependent=True) |
2492 | next_name = param_card_iterator.get_next_name(self.run_name) |
2493 | try: |
2494 | self.exec_cmd("generate_events -f %s" % next_name, |
2495 | |
2496 | === modified file 'madgraph/interface/madgraph_interface.py' |
2497 | --- madgraph/interface/madgraph_interface.py 2016-08-16 00:19:25 +0000 |
2498 | +++ madgraph/interface/madgraph_interface.py 2016-08-18 22:31:39 +0000 |
2499 | @@ -146,6 +146,33 @@ |
2500 | # Define the Error Class # Define how error are handle |
2501 | InvalidCmd = madgraph.InvalidCmd |
2502 | ConfigurationError = MadGraph5Error |
2503 | + |
2504 | + intro_banner = "************************************************************\n" + \ |
2505 | + "* *\n" + \ |
2506 | + "* W E L C O M E to *\n" + \ |
2507 | + "* M A D G R A P H 5 _ a M C @ N L O *\n" + \ |
2508 | + "* *\n" + \ |
2509 | + "* *\n" + \ |
2510 | + "* * * *\n" + \ |
2511 | + "* * * * * *\n" + \ |
2512 | + "* * * * * 5 * * * * *\n" + \ |
2513 | + "* * * * * *\n" + \ |
2514 | + "* * * *\n" + \ |
2515 | + "* *\n" + \ |
2516 | + "%s" + \ |
2517 | + "* *\n" + \ |
2518 | + "* The MadGraph5_aMC@NLO Development Team - Find us at *\n" + \ |
2519 | + "* https://server06.fynu.ucl.ac.be/projects/madgraph *\n" + \ |
2520 | + "* and *\n" + \ |
2521 | + "* http://amcatnlo.web.cern.ch/amcatnlo/ *\n" + \ |
2522 | + "* *\n" + \ |
2523 | + "* Type 'help' for in-line help. *\n" + \ |
2524 | + "* Type 'tutorial' to learn how MG5 works *\n" + \ |
2525 | + "* Type 'tutorial aMCatNLO' to learn how aMC@NLO works *\n" + \ |
2526 | + "* Type 'tutorial MadLoop' to learn how MadLoop works *\n" + \ |
2527 | + "* *\n" + \ |
2528 | + "************************************************************" |
2529 | + |
2530 | |
2531 | def __init__(self, *arg, **opt): |
2532 | """Init history and line continuation""" |
2533 | @@ -187,32 +214,7 @@ |
2534 | |
2535 | |
2536 | |
2537 | - logger.info(\ |
2538 | - "************************************************************\n" + \ |
2539 | - "* *\n" + \ |
2540 | - "* W E L C O M E to *\n" + \ |
2541 | - "* M A D G R A P H 5 _ a M C @ N L O *\n" + \ |
2542 | - "* *\n" + \ |
2543 | - "* *\n" + \ |
2544 | - "* * * *\n" + \ |
2545 | - "* * * * * *\n" + \ |
2546 | - "* * * * * 5 * * * * *\n" + \ |
2547 | - "* * * * * *\n" + \ |
2548 | - "* * * *\n" + \ |
2549 | - "* *\n" + \ |
2550 | - info_line + \ |
2551 | - "* *\n" + \ |
2552 | - "* The MadGraph5_aMC@NLO Development Team - Find us at *\n" + \ |
2553 | - "* https://server06.fynu.ucl.ac.be/projects/madgraph *\n" + \ |
2554 | - "* and *\n" + \ |
2555 | - "* http://amcatnlo.web.cern.ch/amcatnlo/ *\n" + \ |
2556 | - "* *\n" + \ |
2557 | - "* Type 'help' for in-line help. *\n" + \ |
2558 | - "* Type 'tutorial' to learn how MG5 works *\n" + \ |
2559 | - "* Type 'tutorial aMCatNLO' to learn how aMC@NLO works *\n" + \ |
2560 | - "* Type 'tutorial MadLoop' to learn how MadLoop works *\n" + \ |
2561 | - "* *\n" + \ |
2562 | - "************************************************************") |
2563 | + logger.info(self.intro_banner % info_line) |
2564 | |
2565 | cmd.Cmd.__init__(self, *arg, **opt) |
2566 | |
2567 | @@ -1117,11 +1119,13 @@ |
2568 | def check_install(self, args): |
2569 | """check that the install command is valid""" |
2570 | |
2571 | + hidden_prog = ['Delphes2', 'pythia-pgs'] |
2572 | + |
2573 | if len(args) < 1: |
2574 | self.help_install() |
2575 | raise self.InvalidCmd('install command require at least one argument') |
2576 | |
2577 | - if args[0] not in self._install_opts: |
2578 | + if args[0] not in self._install_opts + hidden_prog: |
2579 | if not args[0].startswith('td'): |
2580 | self.help_install() |
2581 | raise self.InvalidCmd('Not recognize program %s ' % args[0]) |
2582 | @@ -1154,13 +1158,15 @@ |
2583 | if not args: |
2584 | if self._done_export: |
2585 | mode = self.find_output_type(self._done_export[0]) |
2586 | - |
2587 | - if not self._done_export[1].startswith(mode): |
2588 | - print mode, self._done_export[1] |
2589 | + if (self._done_export[1] == 'plugin' and mode not in self._export_formats): |
2590 | + args.append(mode) |
2591 | + args.append(self._done_export[0]) |
2592 | + elif self._done_export[1].startswith(mode): |
2593 | + args.append(self._done_export[1]) |
2594 | + args.append(self._done_export[0]) |
2595 | + else: |
2596 | raise self.InvalidCmd, \ |
2597 | '%s not valid directory for launch' % self._done_export[0] |
2598 | - args.append(self._done_export[1]) |
2599 | - args.append(self._done_export[0]) |
2600 | return |
2601 | else: |
2602 | logger.warning('output command missing, run it automatically (with default argument)') |
2603 | @@ -1306,7 +1312,7 @@ |
2604 | if args[0] == 'options': |
2605 | has_path = None |
2606 | for arg in args[1:]: |
2607 | - if arg in ['--auto', '--all']: |
2608 | + if arg in ['--auto', '--all'] or arg in self.options: |
2609 | continue |
2610 | elif arg.startswith('--'): |
2611 | raise self.InvalidCmd('unknow command for \'save options\'') |
2612 | @@ -1460,6 +1466,28 @@ |
2613 | |
2614 | if args and args[0] in self._export_formats: |
2615 | self._export_format = args.pop(0) |
2616 | + elif args: |
2617 | + # check for PLUGIN format |
2618 | + for plug in os.listdir(pjoin(MG5DIR, 'PLUGIN')): |
2619 | + if os.path.exists(pjoin(MG5DIR, 'PLUGIN', plug, '__init__.py')): |
2620 | + try: |
2621 | + __import__('PLUGIN.%s' % plug) |
2622 | + except Exception, error: |
2623 | + logger.warning("error detected in plugin: %s.", plug) |
2624 | + logger.warning("%s", error) |
2625 | + continue |
2626 | + plugin = sys.modules['PLUGIN.%s' % plug] |
2627 | + if hasattr(plugin, 'new_output'): |
2628 | + if not misc.is_plugin_supported(plugin): |
2629 | + continue |
2630 | + if args[0] in plugin.new_output: |
2631 | + self._export_format = 'plugin' |
2632 | + self._export_plugin = plugin.new_output[args[0]] |
2633 | + logger.info('Output will be done with PLUGIN: %s' % plug ,'$MG:color:BLACK') |
2634 | + args.pop(0) |
2635 | + break |
2636 | + else: |
2637 | + self._export_format = default |
2638 | else: |
2639 | self._export_format = default |
2640 | |
2641 | @@ -1494,7 +1522,7 @@ |
2642 | # Check for special directory treatment |
2643 | if path == 'auto' and self._export_format in \ |
2644 | ['madevent', 'standalone', 'standalone_cpp', 'matchbox_cpp', 'madweight', |
2645 | - 'matchbox']: |
2646 | + 'matchbox', 'plugin']: |
2647 | self.get_default_path() |
2648 | if '-noclean' not in args and os.path.exists(self._export_dir): |
2649 | args.append('-noclean') |
2650 | @@ -1665,6 +1693,11 @@ |
2651 | (self._curr_model['name'], i) |
2652 | auto_path = lambda i: pjoin(self.writing_dir, |
2653 | name_dir(i)) |
2654 | + elif self._export_format in ['plugin']: |
2655 | + name_dir = lambda i: 'PROC_PLUGIN_%s_%s' % \ |
2656 | + (self._curr_model['name'], i) |
2657 | + auto_path = lambda i: pjoin(self.writing_dir, |
2658 | + name_dir(i)) |
2659 | elif self._export_format == 'pythia8': |
2660 | if self.options['pythia8_path']: |
2661 | self._export_dir = self.options['pythia8_path'] |
2662 | @@ -1849,7 +1882,8 @@ |
2663 | return self.list_completion(text, possibilities) |
2664 | |
2665 | def model_completion(self, text, process, line, categories = True, \ |
2666 | - allowed_loop_mode = None): |
2667 | + allowed_loop_mode = None, |
2668 | + formatting=True): |
2669 | """ complete the line with model information. If categories is True, |
2670 | it will use completion with categories. If allowed_loop_mode is |
2671 | specified, it will only complete with these loop modes.""" |
2672 | @@ -1926,9 +1960,9 @@ |
2673 | if len(possibilities.keys())==1: |
2674 | return self.list_completion(text, possibilities.values()[0]) |
2675 | else: |
2676 | - return self.deal_multiple_categories(possibilities) |
2677 | + return self.deal_multiple_categories(possibilities, formatting) |
2678 | |
2679 | - def complete_generate(self, text, line, begidx, endidx): |
2680 | + def complete_generate(self, text, line, begidx, endidx, formatting=True): |
2681 | "Complete the generate command" |
2682 | |
2683 | # Return list of particle names and multiparticle names, as well as |
2684 | @@ -1936,25 +1970,25 @@ |
2685 | args = self.split_arg(line[0:begidx]) |
2686 | |
2687 | valid_sqso_operators=['==','<=','>'] |
2688 | + |
2689 | if any(line.endswith('^2 %s '%op) for op in valid_sqso_operators): |
2690 | return |
2691 | if args[-1].endswith('^2'): |
2692 | return self.list_completion(text,valid_sqso_operators) |
2693 | match_op = [o for o in valid_sqso_operators if o.startswith(args[-1])] |
2694 | - if args[-2].endswith('^2') and len(match_op)>0: |
2695 | + if len(args)>2 and args[-2].endswith('^2') and len(match_op)>0: |
2696 | if args[-1] in valid_sqso_operators: |
2697 | return self.list_completion(text,' ') |
2698 | if len(match_op)==1: |
2699 | return self.list_completion(text,[match_op[0][len(args[-1]):]]) |
2700 | else: |
2701 | return self.list_completion(text,match_op) |
2702 | - |
2703 | if len(args) > 2 and args[-1] == '@' or ( args[-1].endswith('=') and \ |
2704 | (not '[' in line or ('[' in line and ']' in line))): |
2705 | return |
2706 | |
2707 | try: |
2708 | - return self.model_completion(text, ' '.join(args[1:]),line) |
2709 | + return self.model_completion(text, ' '.join(args[1:]),line, formatting) |
2710 | except Exception as error: |
2711 | print error |
2712 | |
2713 | @@ -1966,7 +2000,7 @@ |
2714 | # self._multiparticles.keys() + couplings) |
2715 | |
2716 | |
2717 | - def complete_compute_widths(self, text, line, begidx, endidx): |
2718 | + def complete_compute_widths(self, text, line, begidx, endidx,formatting=True): |
2719 | "Complete the compute_widths command" |
2720 | |
2721 | args = self.split_arg(line[0:begidx]) |
2722 | @@ -1987,11 +2021,11 @@ |
2723 | '--precision_channel=0.\$', '--body_decay=', '--nlo']) |
2724 | completion['particles'] = self.model_completion(text, '', line) |
2725 | |
2726 | - return self.deal_multiple_categories(completion) |
2727 | + return self.deal_multiple_categories(completion,formatting) |
2728 | |
2729 | complete_decay_diagram = complete_compute_widths |
2730 | |
2731 | - def complete_add(self, text, line, begidx, endidx): |
2732 | + def complete_add(self, text, line, begidx, endidx, formatting): |
2733 | "Complete the add command" |
2734 | |
2735 | args = self.split_arg(line[0:begidx]) |
2736 | @@ -2005,9 +2039,9 @@ |
2737 | |
2738 | elif args[1] == 'model': |
2739 | completion_categories = self.complete_import(text, line, begidx, endidx, |
2740 | - allow_restrict=False, treat_completion=False) |
2741 | + allow_restrict=False, formatting=False) |
2742 | completion_categories['options'] = self.list_completion(text,['--modelname=','--recreate']) |
2743 | - return self.deal_multiple_categories(completion_categories) |
2744 | + return self.deal_multiple_categories(completion_categories, formatting) |
2745 | |
2746 | def complete_customize_model(self, text, line, begidx, endidx): |
2747 | "Complete the customize_model command" |
2748 | @@ -2019,7 +2053,7 @@ |
2749 | return self.list_completion(text, ['--save=']) |
2750 | |
2751 | |
2752 | - def complete_check(self, text, line, begidx, endidx): |
2753 | + def complete_check(self, text, line, begidx, endidx, formatting=True): |
2754 | "Complete the check command" |
2755 | |
2756 | out = {} |
2757 | @@ -2053,7 +2087,7 @@ |
2758 | {'Process completion': self.model_completion(text, ' '.join(args[2:]), |
2759 | line, categories = False, allowed_loop_mode=['virt']), |
2760 | 'Param_card.dat path completion:':self.path_completion(text), |
2761 | - 'options': self.list_completion(text,options)}) |
2762 | + 'options': self.list_completion(text,options)}, formatting) |
2763 | |
2764 | #Special rules for check cms completion |
2765 | if cms_check_mode: |
2766 | @@ -2085,7 +2119,7 @@ |
2767 | return self.deal_multiple_categories( |
2768 | {"Examples of completion for option '%s'"%args[-1].split('=')[0]: |
2769 | # ['%d: %s'%(i+1,ex) for i, ex in enumerate(example)]}, |
2770 | - ['%s'%ex for i, ex in enumerate(example)]}, |
2771 | + ['%s'%ex for i, ex in enumerate(example)]},formatting, |
2772 | forceCategory=True) |
2773 | if args[-1]=='--recompute_width=': |
2774 | return self.list_completion(text, |
2775 | @@ -2104,17 +2138,20 @@ |
2776 | line, categories = False, allowed_loop_mode=['virt']), |
2777 | 'Param_card.dat path completion:': self.path_completion(text), |
2778 | 'reanalyze result on disk / save output:':self.list_completion( |
2779 | - text,['-reuse','--analyze='])}) |
2780 | + text,['-reuse','--analyze='])}, |
2781 | + formatting) |
2782 | elif not any(arg.startswith('--') for arg in args): |
2783 | if '>' in args: |
2784 | return self.deal_multiple_categories({'Process completion': |
2785 | self.model_completion(text, ' '.join(args[2:]), |
2786 | line, categories = False, allowed_loop_mode=['virt']), |
2787 | - 'options': self.list_completion(text,options)}) |
2788 | + 'options': self.list_completion(text,options)}, |
2789 | + formatting) |
2790 | else: |
2791 | return self.deal_multiple_categories({'Process completion': |
2792 | self.model_completion(text, ' '.join(args[2:]), |
2793 | - line, categories = False, allowed_loop_mode=['virt'])}) |
2794 | + line, categories = False, allowed_loop_mode=['virt'])}, |
2795 | + formatting) |
2796 | else: |
2797 | return self.list_completion(text,options) |
2798 | |
2799 | @@ -2177,7 +2214,7 @@ |
2800 | 'non_propagating', '--'] |
2801 | return self.list_completion(text, opt) |
2802 | |
2803 | - def complete_launch(self, text, line, begidx, endidx): |
2804 | + def complete_launch(self, text, line, begidx, endidx,formatting=True): |
2805 | """ complete the launch command""" |
2806 | args = self.split_arg(line[0:begidx]) |
2807 | |
2808 | @@ -2211,7 +2248,7 @@ |
2809 | out['Options'] = self.list_completion(text, opt, line) |
2810 | |
2811 | |
2812 | - return self.deal_multiple_categories(out) |
2813 | + return self.deal_multiple_categories(out,formatting) |
2814 | |
2815 | def complete_load(self, text, line, begidx, endidx): |
2816 | "Complete the load command" |
2817 | @@ -2333,7 +2370,7 @@ |
2818 | content += possible_options_full |
2819 | return self.list_completion(text, content) |
2820 | |
2821 | - def aloha_complete_output(self, text, line, begidx, endidx): |
2822 | + def aloha_complete_output(self, text, line, begidx, endidx,formatting=True): |
2823 | "Complete the output aloha command" |
2824 | args = self.split_arg(line[0:begidx]) |
2825 | completion_categories = {} |
2826 | @@ -2372,7 +2409,7 @@ |
2827 | completion_categories['Wavefunctions routines'] = self.list_completion(text, wf_opt) |
2828 | completion_categories['conjugate_routines'] = self.list_completion(text, opt_conjg) |
2829 | |
2830 | - return self.deal_multiple_categories(completion_categories) |
2831 | + return self.deal_multiple_categories(completion_categories,formatting) |
2832 | |
2833 | def complete_set(self, text, line, begidx, endidx): |
2834 | "Complete the set command" |
2835 | @@ -2426,7 +2463,7 @@ |
2836 | only_dirs = True) |
2837 | |
2838 | def complete_import(self, text, line, begidx, endidx, allow_restrict=True, |
2839 | - treat_completion=True): |
2840 | + formatting=True): |
2841 | "Complete the import command" |
2842 | |
2843 | args=self.split_arg(line[0:begidx]) |
2844 | @@ -2569,11 +2606,9 @@ |
2845 | if len(args) >= 3 and mode.startswith('banner') and not '--no_launch' in line: |
2846 | completion_categories['options'] = self.list_completion(text, ['--no_launch']) |
2847 | |
2848 | - if treat_completion: |
2849 | - return self.deal_multiple_categories(completion_categories) |
2850 | - else: |
2851 | - #this means this function is called as a subgroup of another completion |
2852 | - return completion_categories |
2853 | + return self.deal_multiple_categories(completion_categories,formatting) |
2854 | + |
2855 | + |
2856 | def find_restrict_card(self, model_name, base_dir='./', no_restrict=True): |
2857 | """find the restriction file associate to a given model""" |
2858 | |
2859 | @@ -2637,9 +2672,8 @@ |
2860 | _check_opts = ['full', 'timing', 'stability', 'profile', 'permutation', |
2861 | 'gauge','lorentz', 'brs', 'cms'] |
2862 | _import_formats = ['model_v4', 'model', 'proc_v4', 'command', 'banner'] |
2863 | - _install_opts = ['pythia-pgs', 'Delphes', 'MadAnalysis', 'ExRootAnalysis', |
2864 | - 'update', 'Delphes2', 'SysCalc', 'Golem95', 'PJFry', |
2865 | - 'QCDLoop'] |
2866 | + _install_opts = ['Delphes', 'MadAnalysis', 'ExRootAnalysis', |
2867 | + 'update', 'SysCalc', 'Golem95', 'PJFry', 'QCDLoop'] |
2868 | # The targets below are installed using the HEPToolsInstaller.py script |
2869 | _advanced_install_opts = ['ninja','collier'] |
2870 | |
2871 | @@ -2732,8 +2766,7 @@ |
2872 | _curr_model = None #base_objects.Model() |
2873 | _curr_amps = diagram_generation.AmplitudeList() |
2874 | _curr_matrix_elements = helas_objects.HelasMultiProcess() |
2875 | - _curr_fortran_model = None |
2876 | - _curr_cpp_model = None |
2877 | + _curr_helas_model = None |
2878 | _curr_exporter = None |
2879 | _done_export = False |
2880 | _curr_decaymodel = None |
2881 | @@ -2837,6 +2870,11 @@ |
2882 | warning_duplicate = False |
2883 | args.remove('--no_warning=duplicate') |
2884 | |
2885 | + diagram_filter = False |
2886 | + if '--diagram_filter' in args: |
2887 | + diagram_filter = True |
2888 | + args.remove('--diagram_filter') |
2889 | + |
2890 | # Check the validity of the arguments |
2891 | self.check_add(args) |
2892 | |
2893 | @@ -2927,7 +2965,7 @@ |
2894 | myproc = diagram_generation.MultiProcess(myprocdef, |
2895 | collect_mirror_procs = collect_mirror_procs, |
2896 | ignore_six_quark_processes = ignore_six_quark_processes, |
2897 | - optimize=optimize) |
2898 | + optimize=optimize, diagram_filter=diagram_filter) |
2899 | |
2900 | |
2901 | for amp in myproc.get('amplitudes'): |
2902 | @@ -2958,6 +2996,7 @@ |
2903 | |
2904 | model_path = args[0] |
2905 | recreate = ('--recreate' in args) |
2906 | + keep_decay = ('--keep_decay' in args) |
2907 | output_dir = [a.split('=',1)[1] for a in args if a.startswith('--output')] |
2908 | if output_dir: |
2909 | output_dir = output_dir[0] |
2910 | @@ -2998,6 +3037,10 @@ |
2911 | base_model.add_model(path=model_path, identify_particles=identify) |
2912 | base_model.write(output_dir) |
2913 | |
2914 | + if keep_decay and os.path.exists(pjoin(self._curr_model.get('modelpath'), 'decays.py')): |
2915 | + base_model.mod_file(pjoin(pjoin(self._curr_model.get('modelpath'), 'decays.py')), |
2916 | + pjoin(pjoin(output_dir, 'decays.py'))) |
2917 | + |
2918 | new_model_name = output_dir |
2919 | if restrict_name: |
2920 | new_model_name = '%s-%s' % (output_dir, restrict_name) |
2921 | @@ -4904,9 +4947,6 @@ |
2922 | if args[0].endswith('_v4'): |
2923 | self._curr_model, self._model_v4_path = \ |
2924 | import_v4.import_model(args[1], self._mgme_dir) |
2925 | - self._curr_fortran_model = \ |
2926 | - helas_call_writers.FortranHelasCallWriter(\ |
2927 | - self._curr_model) |
2928 | else: |
2929 | # avoid loading the qcd/qed model twice |
2930 | if (args[1].startswith('loop_qcd_qed_sm') or\ |
2931 | @@ -4960,13 +5000,6 @@ |
2932 | self._curr_model = None |
2933 | self.do_set('gauge unitary', log= False) |
2934 | return |
2935 | - |
2936 | - self._curr_fortran_model = \ |
2937 | - helas_call_writers.FortranUFOHelasCallWriter(\ |
2938 | - self._curr_model) |
2939 | - self._curr_cpp_model = \ |
2940 | - helas_call_writers.CPPUFOHelasCallWriter(\ |
2941 | - self._curr_model) |
2942 | |
2943 | if '-modelname' not in args: |
2944 | self._curr_model.pass_particles_name_in_mg_default() |
2945 | @@ -5077,10 +5110,6 @@ |
2946 | """ import the UFO model """ |
2947 | |
2948 | self._curr_model = import_ufo.import_model(model_name) |
2949 | - self._curr_fortran_model = \ |
2950 | - helas_call_writers.FortranUFOHelasCallWriter(self._curr_model) |
2951 | - self._curr_cpp_model = \ |
2952 | - helas_call_writers.CPPUFOHelasCallWriter(self._curr_model) |
2953 | |
2954 | def process_model(self): |
2955 | """Set variables _particle_names and _couplings for tab |
2956 | @@ -5530,7 +5559,6 @@ |
2957 | logger.info(" when using results produced with this tool.", '$MG:color:BLACK') |
2958 | logger.info("------------------------------------------------------", '$MG:color:GREEN') |
2959 | |
2960 | - |
2961 | # Load file with path of the different program: |
2962 | import urllib |
2963 | if paths: |
2964 | @@ -6488,15 +6516,11 @@ |
2965 | if self._curr_model.get('parameters'): |
2966 | # This is a UFO model |
2967 | self._model_v4_path = None |
2968 | - self._curr_fortran_model = \ |
2969 | - helas_call_writers.FortranUFOHelasCallWriter(self._curr_model) |
2970 | else: |
2971 | # This is a v4 model |
2972 | self._model_v4_path = import_v4.find_model_path(\ |
2973 | self._curr_model.get('name').replace("_v4", ""), |
2974 | self._mgme_dir) |
2975 | - self._curr_fortran_model = \ |
2976 | - helas_call_writers.FortranHelasCallWriter(self._curr_model) |
2977 | |
2978 | # Do post-processing of model |
2979 | self.process_model() |
2980 | @@ -6522,14 +6546,8 @@ |
2981 | self._model_v4_path = import_v4.find_model_path(\ |
2982 | model.get('name').replace("_v4", ""), |
2983 | self._mgme_dir) |
2984 | - self._curr_fortran_model = \ |
2985 | - helas_call_writers.FortranHelasCallWriter(\ |
2986 | - model) |
2987 | else: |
2988 | self._model_v4_path = None |
2989 | - self._curr_fortran_model = \ |
2990 | - helas_call_writers.FortranUFOHelasCallWriter(\ |
2991 | - model) |
2992 | # If not exceptions from previous steps, set |
2993 | # _curr_amps and _curr_model |
2994 | self._curr_amps = amps |
2995 | @@ -6649,37 +6667,53 @@ |
2996 | raise self.InvalidCmd('No processes to save!') |
2997 | |
2998 | elif args[0] == 'options': |
2999 | - # First look at options which should be put in MG5DIR/input |
3000 | + partial_save = False |
3001 | to_define = {} |
3002 | - for key, default in self.options_configuration.items(): |
3003 | - if self.options_configuration[key] != self.options[key] and not self.options_configuration[key] is None: |
3004 | - to_define[key] = self.options[key] |
3005 | - |
3006 | - if not '--auto' in args: |
3007 | - for key, default in self.options_madevent.items(): |
3008 | - if self.options_madevent[key] != self.options[key] != None: |
3009 | - if '_path' in key and os.path.basename(self.options[key]) == 'None': |
3010 | - continue |
3011 | - to_define[key] = self.options[key] |
3012 | - elif key == 'cluster_queue' and self.options[key] is None: |
3013 | - to_define[key] = self.options[key] |
3014 | - |
3015 | - if '--all' in args: |
3016 | - for key, default in self.options_madgraph.items(): |
3017 | - if self.options_madgraph[key] != self.options[key] != None and \ |
3018 | - key != 'stdout_level': |
3019 | - to_define[key] = self.options[key] |
3020 | - elif not '--auto' in args: |
3021 | - for key, default in self.options_madgraph.items(): |
3022 | - if self.options_madgraph[key] != self.options[key] != None and key != 'stdout_level': |
3023 | - logger.info('The option %s is modified [%s] but will not be written in the configuration files.' \ |
3024 | - % (key,self.options_madgraph[key]) ) |
3025 | - logger.info('If you want to make this value the default for future session, you can run \'save options --all\'') |
3026 | - if len(args) >1 and not args[1].startswith('--'): |
3027 | + if any(not arg.startswith('--') and arg in self.options |
3028 | + for arg in args): |
3029 | + # store in file only those ones |
3030 | + partial_save = True |
3031 | + all_arg = [arg for arg in args[1:] if not arg.startswith('--') and |
3032 | + arg in self.options] |
3033 | + for key in all_arg: |
3034 | + to_define[key] = self.options[key] |
3035 | + else: |
3036 | + # First look at options which should be put in MG5DIR/input |
3037 | + for key, default in self.options_configuration.items(): |
3038 | + if self.options_configuration[key] != self.options[key] and not self.options_configuration[key] is None: |
3039 | + to_define[key] = self.options[key] |
3040 | + |
3041 | + if not '--auto' in args: |
3042 | + for key, default in self.options_madevent.items(): |
3043 | + if self.options_madevent[key] != self.options[key] != None: |
3044 | + if '_path' in key and os.path.basename(self.options[key]) == 'None': |
3045 | + continue |
3046 | + to_define[key] = self.options[key] |
3047 | + elif key == 'cluster_queue' and self.options[key] is None: |
3048 | + to_define[key] = self.options[key] |
3049 | + |
3050 | + if '--all' in args: |
3051 | + for key, default in self.options_madgraph.items(): |
3052 | + if self.options_madgraph[key] != self.options[key] != None and \ |
3053 | + key != 'stdout_level': |
3054 | + to_define[key] = self.options[key] |
3055 | + elif not '--auto' in args: |
3056 | + for key, default in self.options_madgraph.items(): |
3057 | + if self.options_madgraph[key] != self.options[key] != None and key != 'stdout_level': |
3058 | + logger.info('The option %s is modified [%s] but will not be written in the configuration files.' \ |
3059 | + % (key,self.options_madgraph[key]) ) |
3060 | + logger.info('If you want to make this value the default for future session, you can run \'save options --all\'') |
3061 | + |
3062 | + if len(args) >1 and not args[1].startswith('--') and args[1] not in self.options: |
3063 | filepath = args[1] |
3064 | else: |
3065 | filepath = pjoin(MG5DIR, 'input', 'mg5_configuration.txt') |
3066 | - basefile = pjoin(MG5DIR, 'input', '.mg5_configuration_default.txt') |
3067 | + |
3068 | + if partial_save: |
3069 | + basefile = filepath |
3070 | + else: |
3071 | + basefile = pjoin(MG5DIR, 'input', '.mg5_configuration_default.txt') |
3072 | + |
3073 | basedir = MG5DIR |
3074 | |
3075 | if to_keep: |
3076 | @@ -6813,8 +6847,7 @@ |
3077 | self._curr_model = None |
3078 | self._curr_amps = diagram_generation.AmplitudeList() |
3079 | self._curr_matrix_elements = helas_objects.HelasMultiProcess() |
3080 | - self._curr_fortran_model = None |
3081 | - self._curr_cpp_model = None |
3082 | + self._curr_helas_model = None |
3083 | self._curr_exporter = None |
3084 | self._done_export = False |
3085 | import_ufo._import_once = [] |
3086 | @@ -7074,7 +7107,11 @@ |
3087 | config['matchbox'] = {'check': True, 'exporter': 'v4', 'output': 'Template'} |
3088 | config['madweight'] = {'check': True, 'exporter': 'v4', 'output':'Template'} |
3089 | |
3090 | - options = config[self._export_format] |
3091 | + if self._export_format == 'plugin': |
3092 | + options = {'check': self._export_plugin.check, 'exporter':self._export_plugin.exporter, 'output':self._export_plugin.output} |
3093 | + else: |
3094 | + options = config[self._export_format] |
3095 | + |
3096 | # check |
3097 | if os.path.realpath(self._export_dir) == os.getcwd(): |
3098 | if len(args) == 0: |
3099 | @@ -7137,12 +7174,14 @@ |
3100 | if options['exporter'] == 'v4': |
3101 | self._curr_exporter = export_v4.ExportV4Factory(self, noclean, |
3102 | group_subprocesses=group_processes) |
3103 | - if options['output'] == 'Template': |
3104 | - self._curr_exporter.copy_v4template(modelname=self._curr_model.get('name')) |
3105 | - if options['exporter'] == 'cpp' and options['output'] == 'Template': |
3106 | - export_cpp.setup_cpp_standalone_dir(self._export_dir, self._curr_model) |
3107 | - |
3108 | - if options['output'] == 'dir' and not os.path.isdir(self._export_dir): |
3109 | + elif options['exporter'] == 'cpp': |
3110 | + self._curr_exporter = export_cpp.ExportCPPFactory(self, group_subprocesses=group_processes) |
3111 | + |
3112 | + self._curr_exporter.pass_information_from_cmd(self) |
3113 | + |
3114 | + if options['output'] == 'Template': |
3115 | + self._curr_exporter.copy_template(self._curr_model) |
3116 | + elif options['output'] == 'dir' and not os.path.isdir(self._export_dir): |
3117 | os.makedirs(self._export_dir) |
3118 | |
3119 | # Reset _done_export, since we have new directory |
3120 | @@ -7173,6 +7212,16 @@ |
3121 | args=[]): |
3122 | """Export a generated amplitude to file.""" |
3123 | |
3124 | + # Define the helas call writer |
3125 | + if self._curr_exporter.exporter == 'cpp': |
3126 | + self._curr_helas_model = helas_call_writers.CPPUFOHelasCallWriter(self._curr_model) |
3127 | + elif self._model_v4_path: |
3128 | + assert self._curr_exporter.exporter == 'v4' |
3129 | + self._curr_helas_model = helas_call_writers.FortranHelasCallWriter(self._curr_model) |
3130 | + else: |
3131 | + assert self._curr_exporter.exporter == 'v4' |
3132 | + self._curr_helas_model = helas_call_writers.FortranUFOHelasCallWriter(self._curr_model) |
3133 | + |
3134 | version = [arg[10:] for arg in args if arg.startswith('--version=')] |
3135 | if version: |
3136 | version = version[-1] |
3137 | @@ -7212,16 +7261,18 @@ |
3138 | subproc_groups = group_subprocs.SubProcessGroupList() |
3139 | matrix_elements_opts = {'optimized_output': |
3140 | self.options['loop_optimized_output']} |
3141 | + |
3142 | + grouping_criteria = self._curr_exporter.grouped_mode |
3143 | if non_dc_amps: |
3144 | subproc_groups.extend(\ |
3145 | group_subprocs.SubProcessGroup.group_amplitudes(\ |
3146 | - non_dc_amps, self._export_format, |
3147 | + non_dc_amps,grouping_criteria, |
3148 | matrix_elements_opts=matrix_elements_opts)) |
3149 | |
3150 | if dc_amps: |
3151 | dc_subproc_group = \ |
3152 | group_subprocs.DecayChainSubProcessGroup.\ |
3153 | - group_amplitudes(dc_amps, self._export_format, |
3154 | + group_amplitudes(dc_amps, grouping_criteria, |
3155 | matrix_elements_opts=matrix_elements_opts) |
3156 | subproc_groups.extend(dc_subproc_group.\ |
3157 | generate_helas_decay_chain_subproc_groups()) |
3158 | @@ -7276,11 +7327,7 @@ |
3159 | calls = 0 |
3160 | |
3161 | path = self._export_dir |
3162 | - if self._export_format in ['standalone_cpp', 'madevent', 'standalone', |
3163 | - 'standalone_msP', 'standalone_msF', 'standalone_rw', |
3164 | - 'matchbox_cpp', 'madweight', 'matchbox']: |
3165 | - path = pjoin(path, 'SubProcesses') |
3166 | - |
3167 | + |
3168 | cpu_time1 = time.time() |
3169 | |
3170 | # First treat madevent and pythia8 exports, where we need to |
3171 | @@ -7288,10 +7335,10 @@ |
3172 | |
3173 | # MadEvent |
3174 | if self._export_format == 'madevent': |
3175 | + path = pjoin(path, 'SubProcesses') |
3176 | calls += self._curr_exporter.export_processes(self._curr_matrix_elements, |
3177 | - self._curr_fortran_model) |
3178 | - self._curr_exporter.write_global_specs( |
3179 | - self._curr_matrix_elements.get_matrix_elements()) |
3180 | + self._curr_helas_model) |
3181 | + |
3182 | |
3183 | # Write the procdef_mg5.dat file with process info |
3184 | card_path = pjoin(path, os.path.pardir, 'SubProcesses', \ |
3185 | @@ -7307,21 +7354,21 @@ |
3186 | pass |
3187 | |
3188 | # Pythia 8 |
3189 | - if self._export_format == 'pythia8': |
3190 | + elif self._export_format == 'pythia8': |
3191 | # Output the process files |
3192 | process_names = [] |
3193 | if isinstance(self._curr_matrix_elements, group_subprocs.SubProcessGroupList): |
3194 | for (group_number, me_group) in enumerate(self._curr_matrix_elements): |
3195 | - exporter = export_cpp.generate_process_files_pythia8(\ |
3196 | - me_group.get('matrix_elements'), self._curr_cpp_model, |
3197 | + exporter = self._curr_exporter.generate_process_directory(\ |
3198 | + me_group.get('matrix_elements'), self._curr_helas_model, |
3199 | process_string = me_group.get('name'), |
3200 | - process_number = group_number, path = path, |
3201 | + process_number = group_number, |
3202 | version = version) |
3203 | process_names.append(exporter.process_name) |
3204 | else: |
3205 | - exporter = export_cpp.generate_process_files_pythia8(\ |
3206 | - self._curr_matrix_elements, self._curr_cpp_model, |
3207 | - process_string = self._generate_info, path = path) |
3208 | + exporter = self._curr_exporter.generate_process_directory(\ |
3209 | + self._curr_matrix_elements, self._curr_helas_model, |
3210 | + process_string = self._generate_info, version = version) |
3211 | process_names.append(exporter.process_file_name) |
3212 | |
3213 | # Output the model parameter and ALOHA files |
3214 | @@ -7330,44 +7377,14 @@ |
3215 | |
3216 | # Generate the main program file |
3217 | filename, make_filename = \ |
3218 | - export_cpp.generate_example_file_pythia8(path, |
3219 | + self._curr_exporter.generate_example_file_pythia8(path, |
3220 | model_path, |
3221 | process_names, |
3222 | exporter, |
3223 | main_file_name) |
3224 | - |
3225 | - # Pick out the matrix elements in a list |
3226 | + |
3227 | + |
3228 | matrix_elements = self._curr_matrix_elements.get_matrix_elements() |
3229 | - |
3230 | - # Fortran MadGraph MadWeight |
3231 | - if self._export_format == 'madweight': |
3232 | - |
3233 | - if isinstance(self._curr_matrix_elements, group_subprocs.SubProcessGroupList): |
3234 | - #remove the merging between electron and muon |
3235 | - self._curr_matrix_elements = self._curr_matrix_elements.split_lepton_grouping() |
3236 | - |
3237 | - for (group_number, me_group) in enumerate(self._curr_matrix_elements): |
3238 | - calls = calls + \ |
3239 | - self._curr_exporter.generate_subprocess_directory_v4(\ |
3240 | - me_group, self._curr_fortran_model, |
3241 | - group_number) |
3242 | - else: |
3243 | - for me_number, me in \ |
3244 | - enumerate(self._curr_matrix_elements.get_matrix_elements()): |
3245 | - calls = calls + \ |
3246 | - self._curr_exporter.generate_subprocess_directory_v4(\ |
3247 | - me, self._curr_fortran_model, me_number) |
3248 | - |
3249 | - # Fortran MadGraph5_aMC@NLO Standalone |
3250 | - if self._export_format in ['standalone', 'standalone_msP', |
3251 | - 'standalone_msF', 'standalone_rw', 'matchbox']: |
3252 | - for me in matrix_elements[:]: |
3253 | - new_calls = self._curr_exporter.generate_subprocess_directory_v4(\ |
3254 | - me, self._curr_fortran_model) |
3255 | - if not new_calls: |
3256 | - matrix_elements.remove(me) |
3257 | - calls = calls + new_calls |
3258 | - |
3259 | # Just the matrix.f files |
3260 | if self._export_format == 'matrix': |
3261 | for me in matrix_elements: |
3262 | @@ -7379,15 +7396,31 @@ |
3263 | logger.info("Creating new file %s" % filename) |
3264 | calls = calls + self._curr_exporter.write_matrix_element_v4(\ |
3265 | writers.FortranWriter(filename),\ |
3266 | - me, self._curr_fortran_model) |
3267 | + me, self._curr_helas_model) |
3268 | + elif self._export_format in ['madevent', 'pythia8']: |
3269 | + pass |
3270 | + # grouping mode |
3271 | + elif isinstance(self._curr_matrix_elements, group_subprocs.SubProcessGroupList) and\ |
3272 | + self._curr_exporter.grouped_mode: |
3273 | + modify, self._curr_matrix_elements = self._curr_exporter.modify_grouping(self._curr_matrix_elements) |
3274 | + if modify: |
3275 | + matrix_elements = self._curr_matrix_elements.get_matrix_elements() |
3276 | |
3277 | - # C++ standalone |
3278 | - if self._export_format in ['standalone_cpp', 'matchbox_cpp']: |
3279 | - for me in matrix_elements: |
3280 | - export_cpp.generate_subprocess_directory_standalone_cpp(\ |
3281 | - me, self._curr_cpp_model, |
3282 | - path = path, |
3283 | - format=self._export_format) |
3284 | + for me_number, me in enumerate(self._curr_matrix_elements): |
3285 | + calls = calls + \ |
3286 | + self._curr_exporter.generate_subprocess_directory(\ |
3287 | + me, self._curr_helas_model, me_number) |
3288 | + |
3289 | + # ungroup mode |
3290 | + else: |
3291 | + for nb,me in enumerate(matrix_elements[:]): |
3292 | + new_calls = self._curr_exporter.generate_subprocess_directory(\ |
3293 | + me, self._curr_helas_model, nb) |
3294 | + if isinstance(new_calls, int): |
3295 | + if new_calls ==0: |
3296 | + matrix_elements.remove(me) |
3297 | + else: |
3298 | + calls = calls + new_calls |
3299 | |
3300 | cpu_time2 = time.time() - cpu_time1 |
3301 | |
3302 | @@ -7416,6 +7449,7 @@ |
3303 | # Replace the amplitudes with the actual amplitudes from the |
3304 | # matrix elements, which allows proper diagram drawing also of |
3305 | # decay chain processes |
3306 | + matrix_elements = self._curr_matrix_elements.get_matrix_elements() |
3307 | self._curr_amps = diagram_generation.AmplitudeList(\ |
3308 | [me.get('base_amplitude') for me in \ |
3309 | matrix_elements]) |
3310 | @@ -7428,79 +7462,42 @@ |
3311 | 'cpp': self.options['cpp_compiler'], |
3312 | 'f2py': self.options['f2py_compiler']} |
3313 | |
3314 | - |
3315 | - if self._export_format in ['madevent', 'standalone', 'standalone_msP', |
3316 | - 'standalone_msF', 'standalone_rw', 'NLO', 'madweight', |
3317 | - 'matchbox']: |
3318 | - |
3319 | - # For v4 models, copy the model/HELAS information. |
3320 | - if self._model_v4_path: |
3321 | - logger.info('Copy %s model files to directory %s' % \ |
3322 | + # Handling of the model. |
3323 | + if self._model_v4_path: |
3324 | + logger.info('Copy %s model files to directory %s' % \ |
3325 | (os.path.basename(self._model_v4_path), self._export_dir)) |
3326 | - self._curr_exporter.export_model_files(self._model_v4_path) |
3327 | - self._curr_exporter.export_helas(pjoin(self._mgme_dir,'HELAS')) |
3328 | - else: |
3329 | - logger.info('Export UFO model to MG4 format') |
3330 | - # wanted_lorentz are the lorentz structures which are |
3331 | - # actually used in the wavefunctions and amplitudes in |
3332 | - # these processes |
3333 | - wanted_lorentz = self._curr_matrix_elements.get_used_lorentz() |
3334 | - wanted_couplings = self._curr_matrix_elements.get_used_couplings() |
3335 | - # For a unique output of multiple type of exporter need to store this |
3336 | - # information. |
3337 | - if hasattr(self, 'previous_lorentz'): |
3338 | - wanted_lorentz = list(set(self.previous_lorentz + wanted_lorentz)) |
3339 | - wanted_couplings = list(set(self.previous_couplings + wanted_couplings)) |
3340 | - del self.previous_lorentz |
3341 | - del self.previous_couplings |
3342 | - if 'store_model' in flaglist: |
3343 | - self.previous_lorentz = wanted_lorentz |
3344 | - self.previous_couplings = wanted_couplings |
3345 | - else: |
3346 | - self._curr_exporter.convert_model_to_mg4(self._curr_model, |
3347 | - wanted_lorentz, |
3348 | - wanted_couplings) |
3349 | - if self._export_format in ['standalone_cpp', 'matchbox_cpp']: |
3350 | - logger.info('Export UFO model to C++ format') |
3351 | + self._curr_exporter.export_model_files(self._model_v4_path) |
3352 | + self._curr_exporter.export_helas(pjoin(self._mgme_dir,'HELAS')) |
3353 | + else: |
3354 | # wanted_lorentz are the lorentz structures which are |
3355 | # actually used in the wavefunctions and amplitudes in |
3356 | # these processes |
3357 | wanted_lorentz = self._curr_matrix_elements.get_used_lorentz() |
3358 | wanted_couplings = self._curr_matrix_elements.get_used_couplings() |
3359 | - export_cpp.convert_model_to_cpp(self._curr_model, |
3360 | - pjoin(self._export_dir), |
3361 | - wanted_lorentz, |
3362 | - wanted_couplings) |
3363 | - export_cpp.make_model_cpp(self._export_dir) |
3364 | - |
3365 | - |
3366 | - elif self._export_format in ['NLO']: |
3367 | - ## write fj_lhapdf_opts file |
3368 | - devnull = os.open(os.devnull, os.O_RDWR) |
3369 | - try: |
3370 | - res = misc.call([self.options['lhapdf'], '--version'], \ |
3371 | - stdout=subprocess.PIPE, stderr=subprocess.PIPE) |
3372 | - except Exception: |
3373 | - res = 1 |
3374 | - if res != 0: |
3375 | - logger.info('The value for lhapdf in the current configuration does not ' + \ |
3376 | - 'correspond to a valid executable.\nPlease set it correctly either in ' + \ |
3377 | - 'input/mg5_configuration or with "set lhapdf /path/to/lhapdf-config" ' + \ |
3378 | - 'and regenrate the process. \nTo avoid regeneration, edit the ' + \ |
3379 | - ('%s/Cards/amcatnlo_configuration.txt file.\n' % self._export_dir ) + \ |
3380 | - 'Note that you can still compile and run aMC@NLO with the built-in PDFs\n') |
3381 | - |
3382 | - |
3383 | - |
3384 | - self._curr_exporter.finalize_fks_directory( \ |
3385 | - self._curr_matrix_elements, |
3386 | - self.history, |
3387 | - not nojpeg, |
3388 | - online, |
3389 | - compiler_dict, |
3390 | - output_dependencies = self.options['output_dependencies'], |
3391 | - MG5DIR = MG5DIR) |
3392 | + # For a unique output of multiple type of exporter need to store this |
3393 | + # information. |
3394 | + if hasattr(self, 'previous_lorentz'): |
3395 | + wanted_lorentz = list(set(self.previous_lorentz + wanted_lorentz)) |
3396 | + wanted_couplings = list(set(self.previous_couplings + wanted_couplings)) |
3397 | + del self.previous_lorentz |
3398 | + del self.previous_couplings |
3399 | + if 'store_model' in flaglist: |
3400 | + self.previous_lorentz = wanted_lorentz |
3401 | + self.previous_couplings = wanted_couplings |
3402 | + else: |
3403 | + self._curr_exporter.convert_model(self._curr_model, |
3404 | + wanted_lorentz, |
3405 | + wanted_couplings) |
3406 | + |
3407 | + # move the old options to the flaglist system. |
3408 | + if nojpeg: |
3409 | + flaglist.append('nojpeg') |
3410 | + if online: |
3411 | + flaglist.append('online') |
3412 | |
3413 | + |
3414 | + if self._export_format in ['NLO']: |
3415 | + ## write fj_lhapdf_opts file |
3416 | # Create configuration file [path to executable] for amcatnlo |
3417 | filename = os.path.join(self._export_dir, 'Cards', 'amcatnlo_configuration.txt') |
3418 | opts_to_keep = ['lhapdf', 'fastjet', 'pythia8_path', 'hwpp_path', 'thepeg_path', |
3419 | @@ -7518,15 +7515,12 @@ |
3420 | self.do_save('options %s' % filename.replace(' ', '\ '), check=False, |
3421 | to_keep={'mg5_path':MG5DIR}) |
3422 | |
3423 | - if self._export_format in ['madevent', 'standalone', 'standalone_msP', 'standalone_msF', |
3424 | - 'standalone_rw', 'madweight', 'matchbox']: |
3425 | + # Dedicated finalize function. |
3426 | + self._curr_exporter.finalize(self._curr_matrix_elements, |
3427 | + self.history, |
3428 | + self.options, |
3429 | + flaglist) |
3430 | |
3431 | - self._curr_exporter.finalize_v4_directory( \ |
3432 | - self._curr_matrix_elements, |
3433 | - self.history, |
3434 | - not nojpeg, |
3435 | - online, |
3436 | - compiler_dict) |
3437 | |
3438 | if self._export_format in ['madevent', 'standalone', 'standalone_cpp','madweight', 'matchbox']: |
3439 | logger.info('Output to directory ' + self._export_dir + ' done.') |
3440 | @@ -7593,8 +7587,6 @@ |
3441 | model = import_ufo.import_model(modelname, decay=True) |
3442 | else: |
3443 | self._curr_model = model |
3444 | - self._curr_fortran_model = \ |
3445 | - helas_call_writers.FortranUFOHelasCallWriter(self._curr_model) |
3446 | if not isinstance(model, model_reader.ModelReader): |
3447 | model = model_reader.ModelReader(model) |
3448 | |
3449 | @@ -7663,7 +7655,7 @@ |
3450 | elif value < 0: |
3451 | raise Exception, 'Partial width for %s > %s negative: %s' % \ |
3452 | (particle.get('name'), ' '.join([p.get('name') for p in mode]), value) |
3453 | - elif value < 0.1 and particle['color'] !=1: |
3454 | + elif 0 < value < 0.1 and particle['color'] !=1: |
3455 | logger.warning("partial width of particle %s lower than QCD scale:%s. Set it to zero. (%s)" \ |
3456 | % (particle.get('name'), value, decay_to)) |
3457 | value = 0 |
3458 | @@ -7701,7 +7693,7 @@ |
3459 | decay_dir = pjoin(path,'temp_decay') |
3460 | logger_mg.info('More info in temporary files:\n %s/index.html' % (decay_dir)) |
3461 | with misc.MuteLogger(['madgraph','ALOHA','cmdprint','madevent'], [40,40,40,40]): |
3462 | - self.exec_cmd('output %s -f' % decay_dir) |
3463 | + self.exec_cmd('output %s -f' % decay_dir,child=False) |
3464 | # Need to write the correct param_card in the correct place !!! |
3465 | if os.path.exists(opts['output']): |
3466 | files.cp(opts['output'], pjoin(decay_dir, 'Cards', 'param_card.dat')) |
3467 | @@ -7746,7 +7738,7 @@ |
3468 | for BR in param['decay'].decay_table[pid]: |
3469 | if len(BR.lhacode) == 3 and skip_2body: |
3470 | continue |
3471 | - if BR.value * width <0.1 and particle['color'] !=1: |
3472 | + if 0 < BR.value * width <0.1 and particle['color'] !=1: |
3473 | logger.warning("partial width of particle %s lower than QCD scale:%s. Set it to zero. (%s)" \ |
3474 | % (particle.get('name'), BR.value * width, BR.lhacode[1:])) |
3475 | |
3476 | |
3477 | === modified file 'madgraph/interface/master_interface.py' |
3478 | --- madgraph/interface/master_interface.py 2016-07-20 22:43:24 +0000 |
3479 | +++ madgraph/interface/master_interface.py 2016-08-18 22:31:39 +0000 |
3480 | @@ -80,6 +80,9 @@ |
3481 | def debug_link_to_command(self): |
3482 | """redefine all the command to call directly the appropriate child""" |
3483 | |
3484 | + if hasattr(self, 'plugin') and self.plugin: |
3485 | + return True |
3486 | + |
3487 | correct = True |
3488 | # function which should be self.cmd dependent but which doesn't start |
3489 | # by do_xxxx, help_xxx, check_xxxx or complete_xxx |
3490 | @@ -114,7 +117,7 @@ |
3491 | # in the Switcher or in one of the MasterClass |
3492 | define = {} |
3493 | for mother in MasterCmd.__mro__: |
3494 | - if mother.__name__ in ['Cmd', 'BasicCmd', 'ExtendedCmd']: |
3495 | + if mother.__name__ in ['OriginalCmd', 'BasicCmd', 'CmdExtended', 'Cmd']: |
3496 | continue |
3497 | |
3498 | |
3499 | @@ -134,9 +137,8 @@ |
3500 | # Do the same for the WEb MasterClass |
3501 | define = {} |
3502 | for mother in MasterCmdWeb.__mro__: |
3503 | - if mother.__name__ in ['Cmd', 'BasicCmd', 'ExtendedCmd']: |
3504 | + if mother.__name__ in ['OriginalCmd', 'BasicCmd', 'CmdExtended', 'Cmd']: |
3505 | continue |
3506 | - |
3507 | for data in mother.__dict__: |
3508 | #check if define in Switcher |
3509 | if data in Switcher.__dict__ or data.startswith('__'): |
3510 | |
3511 | === modified file 'madgraph/interface/reweight_interface.py' |
3512 | --- madgraph/interface/reweight_interface.py 2016-07-29 15:27:30 +0000 |
3513 | +++ madgraph/interface/reweight_interface.py 2016-08-18 22:31:39 +0000 |
3514 | @@ -853,6 +853,9 @@ |
3515 | |
3516 | return 0 |
3517 | |
3518 | + def do_compute_widths(self, line): |
3519 | + return self.mother.do_compute_widths(line) |
3520 | + |
3521 | def calculate_weight(self, event, space=None): |
3522 | """space defines where to find the calculator (in multicore)""" |
3523 | |
3524 | |
3525 | === modified file 'madgraph/iolibs/export_cpp.py' |
3526 | --- madgraph/iolibs/export_cpp.py 2016-04-15 11:14:25 +0000 |
3527 | +++ madgraph/iolibs/export_cpp.py 2016-08-18 22:31:39 +0000 |
3528 | @@ -35,9 +35,11 @@ |
3529 | import madgraph.iolibs.file_writers as writers |
3530 | import madgraph.iolibs.template_files as template_files |
3531 | import madgraph.iolibs.ufo_expression_parsers as parsers |
3532 | +import madgraph.various.banner as banner_mod |
3533 | from madgraph import MadGraph5Error, InvalidCmd, MG5DIR |
3534 | from madgraph.iolibs.files import cp, ln, mv |
3535 | |
3536 | +from madgraph.iolibs.export_v4 import VirtualExporter |
3537 | import madgraph.various.misc as misc |
3538 | |
3539 | import aloha.create_aloha as create_aloha |
3540 | @@ -48,132 +50,6 @@ |
3541 | pjoin = os.path.join |
3542 | |
3543 | |
3544 | - |
3545 | -#=============================================================================== |
3546 | -# setup_cpp_standalone_dir |
3547 | -#=============================================================================== |
3548 | -def setup_cpp_standalone_dir(dirpath, model): |
3549 | - """Prepare export_dir as standalone_cpp directory, including: |
3550 | - src (for RAMBO, model and ALOHA files + makefile) |
3551 | - lib (with compiled libraries from src) |
3552 | - SubProcesses (with check_sa.cpp + makefile and Pxxxxx directories) |
3553 | - """ |
3554 | - |
3555 | - cwd = os.getcwd() |
3556 | - |
3557 | - try: |
3558 | - os.mkdir(dirpath) |
3559 | - except os.error as error: |
3560 | - logger.warning(error.strerror + " " + dirpath) |
3561 | - |
3562 | - try: |
3563 | - os.chdir(dirpath) |
3564 | - except os.error: |
3565 | - logger.error('Could not cd to directory %s' % dirpath) |
3566 | - return 0 |
3567 | - |
3568 | - logger.info('Creating subdirectories in directory %s' % dirpath) |
3569 | - |
3570 | - try: |
3571 | - os.mkdir('src') |
3572 | - except os.error as error: |
3573 | - logger.warning(error.strerror + " " + dirpath) |
3574 | - |
3575 | - try: |
3576 | - os.mkdir('lib') |
3577 | - except os.error as error: |
3578 | - logger.warning(error.strerror + " " + dirpath) |
3579 | - |
3580 | - try: |
3581 | - os.mkdir('Cards') |
3582 | - except os.error as error: |
3583 | - logger.warning(error.strerror + " " + dirpath) |
3584 | - |
3585 | - try: |
3586 | - os.mkdir('SubProcesses') |
3587 | - except os.error as error: |
3588 | - logger.warning(error.strerror + " " + dirpath) |
3589 | - |
3590 | - # Write param_card |
3591 | - open(os.path.join("Cards","param_card.dat"), 'w').write(\ |
3592 | - model.write_param_card()) |
3593 | - |
3594 | - src_files = ['rambo.h', 'rambo.cc', 'read_slha.h', 'read_slha.cc'] |
3595 | - |
3596 | - # Copy the needed src files |
3597 | - for f in src_files: |
3598 | - cp(_file_path + 'iolibs/template_files/' + f, 'src') |
3599 | - |
3600 | - # Copy src Makefile |
3601 | - makefile = read_template_file('Makefile_sa_cpp_src') % \ |
3602 | - {'model': ProcessExporterCPP.get_model_name(model.get('name'))} |
3603 | - open(os.path.join('src', 'Makefile'), 'w').write(makefile) |
3604 | - |
3605 | - # Copy SubProcesses files |
3606 | - cp(_file_path + 'iolibs/template_files/check_sa.cpp', 'SubProcesses') |
3607 | - |
3608 | - # Copy SubProcesses Makefile |
3609 | - makefile = read_template_file('Makefile_sa_cpp_sp') % \ |
3610 | - {'model': ProcessExporterCPP.get_model_name(model.get('name'))} |
3611 | - open(os.path.join('SubProcesses', 'Makefile'), 'w').write(makefile) |
3612 | - |
3613 | - # Return to original PWD |
3614 | - os.chdir(cwd) |
3615 | - |
3616 | -#=============================================================================== |
3617 | -# generate_subprocess_directory_standalone_cpp |
3618 | -#=============================================================================== |
3619 | -def generate_subprocess_directory_standalone_cpp(matrix_element, |
3620 | - cpp_helas_call_writer, |
3621 | - path = os.getcwd(), |
3622 | - format='standalone_cpp'): |
3623 | - |
3624 | - """Generate the Pxxxxx directory for a subprocess in C++ standalone, |
3625 | - including the necessary .h and .cc files""" |
3626 | - |
3627 | - cwd = os.getcwd() |
3628 | - # Create the process_exporter |
3629 | - if format == 'standalone_cpp': |
3630 | - process_exporter_cpp = ProcessExporterCPP(matrix_element, |
3631 | - cpp_helas_call_writer) |
3632 | - elif format == 'matchbox_cpp': |
3633 | - process_exporter_cpp = ProcessExporterMatchbox(matrix_element, |
3634 | - cpp_helas_call_writer) |
3635 | - else: |
3636 | - raise Exception, 'Unrecognized format %s' % format |
3637 | - |
3638 | - # Create the directory PN_xx_xxxxx in the specified path |
3639 | - dirpath = os.path.join(path, \ |
3640 | - "P%d_%s" % (process_exporter_cpp.process_number, |
3641 | - process_exporter_cpp.process_name)) |
3642 | - try: |
3643 | - os.mkdir(dirpath) |
3644 | - except os.error as error: |
3645 | - logger.warning(error.strerror + " " + dirpath) |
3646 | - |
3647 | - try: |
3648 | - os.chdir(dirpath) |
3649 | - except os.error: |
3650 | - logger.error('Could not cd to directory %s' % dirpath) |
3651 | - return 0 |
3652 | - |
3653 | - logger.info('Creating files in directory %s' % dirpath) |
3654 | - |
3655 | - process_exporter_cpp.path = dirpath |
3656 | - # Create the process .h and .cc files |
3657 | - process_exporter_cpp.generate_process_files() |
3658 | - |
3659 | - linkfiles = ['check_sa.cpp', 'Makefile'] |
3660 | - |
3661 | - |
3662 | - for file in linkfiles: |
3663 | - ln('../%s' % file) |
3664 | - |
3665 | - # Return to original PWD |
3666 | - os.chdir(cwd) |
3667 | - |
3668 | - return |
3669 | - |
3670 | def make_model_cpp(dir_path): |
3671 | """Make the model library in a C++ standalone directory""" |
3672 | |
3673 | @@ -182,16 +58,16 @@ |
3674 | logger.info("Running make for src") |
3675 | misc.compile(cwd=source_dir) |
3676 | |
3677 | -#=============================================================================== |
3678 | -# ProcessExporterCPP |
3679 | -#=============================================================================== |
3680 | -class ProcessExporterCPP(object): |
3681 | + |
3682 | +class OneProcessExporterCPP(object): |
3683 | """Class to take care of exporting a set of matrix elements to |
3684 | C++ format.""" |
3685 | |
3686 | # Static variables (for inheritance) |
3687 | process_dir = '.' |
3688 | include_dir = '.' |
3689 | + template_path = os.path.join(_file_path, 'iolibs', 'template_files') |
3690 | + __template_path = os.path.join(_file_path, 'iolibs', 'template_files') |
3691 | process_template_h = 'cpp_process_h.inc' |
3692 | process_template_cc = 'cpp_process_cc.inc' |
3693 | process_class_template = 'cpp_process_class.inc' |
3694 | @@ -217,7 +93,7 @@ |
3695 | self.matrix_elements = matrix_elements |
3696 | else: |
3697 | raise base_objects.PhysicsObject.PhysicsObjectError,\ |
3698 | - "Wrong object type for matrix_elements" |
3699 | + "Wrong object type for matrix_elements: %s" % type(matrix_elements) |
3700 | |
3701 | if not self.matrix_elements: |
3702 | raise MadGraph5Error("No matrix elements to export") |
3703 | @@ -305,8 +181,32 @@ |
3704 | self.amplitudes = helas_objects.HelasMatrixElement({\ |
3705 | 'diagrams': helas_objects.HelasDiagramList([diagram])}) |
3706 | |
3707 | + #=============================================================================== |
3708 | + # Global helper methods |
3709 | + #=============================================================================== |
3710 | + @classmethod |
3711 | + def read_template_file(cls, filename, classpath=False): |
3712 | + """Open a template file and return the contents.""" |
3713 | + |
3714 | + if isinstance(filename, tuple): |
3715 | + file_path = filename[0] |
3716 | + filename = filename[1] |
3717 | + elif isinstance(filename, str): |
3718 | + if classpath: |
3719 | + file_path = cls.__template_path |
3720 | + else: |
3721 | + file_path = cls.template_path |
3722 | + else: |
3723 | + raise MadGraph5Error('Argument should be string or tuple.') |
3724 | + |
3725 | + return open(os.path.join(file_path, filename)).read() |
3726 | + |
3727 | + |
3728 | + |
3729 | + |
3730 | + |
3731 | + |
3732 | # Methods for generation of process files for C++ |
3733 | - |
3734 | def generate_process_files(self): |
3735 | """Generate the .h and .cc files needed for C++, for the |
3736 | processes described by multi_matrix_element""" |
3737 | @@ -335,13 +235,14 @@ |
3738 | |
3739 | |
3740 | return replace_dict |
3741 | + |
3742 | #=========================================================================== |
3743 | # write_process_h_file |
3744 | #=========================================================================== |
3745 | def write_process_h_file(self, writer): |
3746 | """Write the class definition (.h) file for the process""" |
3747 | |
3748 | - if not isinstance(writer, writers.CPPWriter): |
3749 | + if writer and not isinstance(writer, writers.CPPWriter): |
3750 | raise writers.CPPWriter.CPPWriterError(\ |
3751 | "writer not CPPWriter") |
3752 | |
3753 | @@ -362,11 +263,12 @@ |
3754 | process_class_definitions = self.get_process_class_definitions() |
3755 | replace_dict['process_class_definitions'] = process_class_definitions |
3756 | |
3757 | - file = read_template_file(self.process_template_h) % replace_dict |
3758 | - |
3759 | - # Write the file |
3760 | - writer.writelines(file) |
3761 | - |
3762 | + if writer: |
3763 | + file = self.read_template_file(self.process_template_h) % replace_dict |
3764 | + # Write the file |
3765 | + writer.writelines(file) |
3766 | + else: |
3767 | + return replace_dict |
3768 | #=========================================================================== |
3769 | # write_process_cc_file |
3770 | #=========================================================================== |
3771 | @@ -374,8 +276,9 @@ |
3772 | """Write the class member definition (.cc) file for the process |
3773 | described by matrix_element""" |
3774 | |
3775 | - if not isinstance(writer, writers.CPPWriter): |
3776 | - raise writers.CPPWriter.CPPWriterError(\ |
3777 | + if writer: |
3778 | + if not isinstance(writer, writers.CPPWriter): |
3779 | + raise writers.CPPWriter.CPPWriterError(\ |
3780 | "writer not CPPWriter") |
3781 | |
3782 | replace_dict = self.get_default_converter() |
3783 | @@ -397,15 +300,17 @@ |
3784 | replace_dict['process_function_definitions'] = \ |
3785 | process_function_definitions |
3786 | |
3787 | - file = read_template_file(self.process_template_cc) % replace_dict |
3788 | - |
3789 | - # Write the file |
3790 | - writer.writelines(file) |
3791 | - |
3792 | + if writer: |
3793 | + file = self.read_template_file(self.process_template_cc) % replace_dict |
3794 | + # Write the file |
3795 | + writer.writelines(file) |
3796 | + else: |
3797 | + return replace_dict |
3798 | + |
3799 | #=========================================================================== |
3800 | # Process export helper functions |
3801 | #=========================================================================== |
3802 | - def get_process_class_definitions(self): |
3803 | + def get_process_class_definitions(self, write=True): |
3804 | """The complete class definition for the process""" |
3805 | |
3806 | replace_dict = {} |
3807 | @@ -472,11 +377,12 @@ |
3808 | replace("0_", "") \ |
3809 | for me in self.matrix_elements]) |
3810 | |
3811 | - |
3812 | - file = read_template_file(self.process_class_template) % replace_dict |
3813 | - |
3814 | - return file |
3815 | - |
3816 | + if write: |
3817 | + file = self.read_template_file(self.process_class_template) % replace_dict |
3818 | + return file |
3819 | + else: |
3820 | + return replace_dict |
3821 | + |
3822 | def get_process_function_definitions(self): |
3823 | """The complete Pythia 8 class definition for the process""" |
3824 | |
3825 | @@ -510,7 +416,7 @@ |
3826 | self.get_all_sigmaKin_lines(color_amplitudes, |
3827 | 'CPPProcess') |
3828 | |
3829 | - file = read_template_file(self.process_definition_template) %\ |
3830 | + file = self.read_template_file(self.process_definition_template) %\ |
3831 | replace_dict |
3832 | |
3833 | return file |
3834 | @@ -584,7 +490,7 @@ |
3835 | return ret_lines |
3836 | |
3837 | |
3838 | - def get_calculate_wavefunctions(self, wavefunctions, amplitudes): |
3839 | + def get_calculate_wavefunctions(self, wavefunctions, amplitudes, write=True): |
3840 | """Return the lines for optimized calculation of the |
3841 | wavefunctions for all subprocesses""" |
3842 | |
3843 | @@ -603,13 +509,15 @@ |
3844 | replace_dict['amplitude_calls'] = "\n".join(\ |
3845 | self.helas_call_writer.get_amplitude_calls(amplitudes)) |
3846 | |
3847 | - file = read_template_file(self.process_wavefunction_template) % \ |
3848 | + if write: |
3849 | + file = self.read_template_file(self.process_wavefunction_template) % \ |
3850 | replace_dict |
3851 | - |
3852 | - return file |
3853 | + return file |
3854 | + else: |
3855 | + return replace_dict |
3856 | |
3857 | |
3858 | - def get_sigmaKin_lines(self, color_amplitudes): |
3859 | + def get_sigmaKin_lines(self, color_amplitudes, write=True): |
3860 | """Get sigmaKin_lines for function definition for Pythia 8 .cc file""" |
3861 | |
3862 | |
3863 | @@ -667,22 +575,27 @@ |
3864 | |
3865 | replace_dict['get_mirror_matrix_lines'] = mirror_matrix_lines |
3866 | |
3867 | - |
3868 | - file = \ |
3869 | - read_template_file(\ |
3870 | + if write: |
3871 | + file = \ |
3872 | + self.read_template_file(\ |
3873 | self.process_sigmaKin_function_template) %\ |
3874 | replace_dict |
3875 | - |
3876 | - return file |
3877 | - |
3878 | + return file |
3879 | + else: |
3880 | + return replace_dict |
3881 | else: |
3882 | ret_lines = "// Call the individual sigmaKin for each process\n" |
3883 | - return ret_lines + \ |
3884 | + ret_lines = ret_lines + \ |
3885 | "\n".join(["sigmaKin_%s();" % \ |
3886 | me.get('processes')[0].shell_string().\ |
3887 | replace("0_", "") for \ |
3888 | me in self.matrix_elements]) |
3889 | - |
3890 | + if write: |
3891 | + return ret_lines |
3892 | + else: |
3893 | + replace_dict['get_mirror_matrix_lines'] = ret_lines |
3894 | + return replace_dict |
3895 | + |
3896 | def get_all_sigmaKin_lines(self, color_amplitudes, class_name): |
3897 | """Get sigmaKin_process for all subprocesses for Pythia 8 .cc file""" |
3898 | |
3899 | @@ -705,7 +618,7 @@ |
3900 | return "\n".join(ret_lines) |
3901 | |
3902 | |
3903 | - def get_sigmaKin_single_process(self, i, matrix_element): |
3904 | + def get_sigmaKin_single_process(self, i, matrix_element, write=True): |
3905 | """Write sigmaKin for each process""" |
3906 | |
3907 | # Write sigmaKin for the process |
3908 | @@ -731,14 +644,16 @@ |
3909 | # Extract denominator |
3910 | replace_dict['den_factor'] = matrix_element.get_denominator_factor() |
3911 | |
3912 | - file = \ |
3913 | - read_template_file('cpp_process_sigmaKin_subproc_function.inc') %\ |
3914 | - replace_dict |
3915 | - |
3916 | - return file |
3917 | - |
3918 | + if write: |
3919 | + file = \ |
3920 | + self.read_template_file('cpp_process_sigmaKin_subproc_function.inc') %\ |
3921 | + replace_dict |
3922 | + return file |
3923 | + else: |
3924 | + return replace_dict |
3925 | + |
3926 | def get_matrix_single_process(self, i, matrix_element, color_amplitudes, |
3927 | - class_name): |
3928 | + class_name, write=True): |
3929 | """Write matrix() for each process""" |
3930 | |
3931 | # Write matrix() for the process |
3932 | @@ -785,11 +700,13 @@ |
3933 | #specific exporter hack |
3934 | replace_dict = self.get_class_specific_definition_matrix(replace_dict, matrix_element) |
3935 | |
3936 | - file = read_template_file(self.single_process_template) % \ |
3937 | + if write: |
3938 | + file = self.read_template_file(self.single_process_template) % \ |
3939 | replace_dict |
3940 | - |
3941 | - return file |
3942 | - |
3943 | + return file |
3944 | + else: |
3945 | + return replace_dict |
3946 | + |
3947 | def get_class_specific_definition_matrix(self, converter, matrix_element): |
3948 | """place to add some specific hack to a given exporter. |
3949 | Please always use Super in that case""" |
3950 | @@ -945,45 +862,9 @@ |
3951 | res_list.append(res) |
3952 | |
3953 | return "\n".join(res_list) |
3954 | - |
3955 | - @staticmethod |
3956 | - def get_model_name(name): |
3957 | - """Replace - with _, + with _plus_ in a model name.""" |
3958 | - |
3959 | - name = name.replace('-', '_') |
3960 | - name = name.replace('+', '_plus_') |
3961 | - return name |
3962 | - |
3963 | -#=============================================================================== |
3964 | -# generate_process_files_pythia8 |
3965 | -#=============================================================================== |
3966 | -def generate_process_files_pythia8(multi_matrix_element, cpp_helas_call_writer, |
3967 | - process_string = "", |
3968 | - process_number = 0, path = os.getcwd(), |
3969 | - version='8.2'): |
3970 | - |
3971 | - """Generate the .h and .cc files needed for Pythia 8, for the |
3972 | - processes described by multi_matrix_element""" |
3973 | - |
3974 | - process_exporter_pythia8 = ProcessExporterPythia8(multi_matrix_element, |
3975 | - cpp_helas_call_writer, |
3976 | - process_string, |
3977 | - process_number, |
3978 | - path, |
3979 | - version=version) |
3980 | - |
3981 | - # Set process directory |
3982 | - model = process_exporter_pythia8.model |
3983 | - model_name = process_exporter_pythia8.model_name |
3984 | - process_exporter_pythia8.process_dir = \ |
3985 | - 'Processes_%(model)s' % {'model': \ |
3986 | - model_name} |
3987 | - process_exporter_pythia8.include_dir = process_exporter_pythia8.process_dir |
3988 | - process_exporter_pythia8.generate_process_files() |
3989 | - return process_exporter_pythia8 |
3990 | - |
3991 | - |
3992 | -class ProcessExporterMatchbox(ProcessExporterCPP): |
3993 | + |
3994 | + |
3995 | +class OneProcessExporterMatchbox(OneProcessExporterCPP): |
3996 | """Class to take care of exporting a set of matrix elements to |
3997 | Matchbox format.""" |
3998 | |
3999 | @@ -1007,7 +888,7 @@ |
4000 | def get_class_specific_definition_matrix(self, converter, matrix_element): |
4001 | """ """ |
4002 | |
4003 | - converter = super(ProcessExporterMatchbox, self).get_class_specific_definition_matrix(converter, matrix_element) |
4004 | + converter = super(OneProcessExporterMatchbox, self).get_class_specific_definition_matrix(converter, matrix_element) |
4005 | |
4006 | # T(....) |
4007 | converter['color_sting_lines'] = \ |
4008 | @@ -1085,7 +966,7 @@ |
4009 | #=============================================================================== |
4010 | # ProcessExporterPythia8 |
4011 | #=============================================================================== |
4012 | -class ProcessExporterPythia8(ProcessExporterCPP): |
4013 | +class OneProcessExporterPythia8(OneProcessExporterCPP): |
4014 | """Class to take care of exporting a set of matrix elements to |
4015 | Pythia 8 format.""" |
4016 | |
4017 | @@ -1096,6 +977,8 @@ |
4018 | process_definition_template = 'pythia8_process_function_definitions.inc' |
4019 | process_wavefunction_template = 'pythia8_process_wavefunctions.inc' |
4020 | process_sigmaKin_function_template = 'pythia8_process_sigmaKin_function.inc' |
4021 | + template_path = os.path.join(_file_path, 'iolibs', 'template_files', 'pythia8') |
4022 | + |
4023 | |
4024 | def __init__(self, *args, **opts): |
4025 | """Set process class name""" |
4026 | @@ -1105,7 +988,7 @@ |
4027 | del opts['version'] |
4028 | else: |
4029 | self.version='8.2' |
4030 | - super(ProcessExporterPythia8, self).__init__(*args, **opts) |
4031 | + super(OneProcessExporterPythia8, self).__init__(*args, **opts) |
4032 | |
4033 | # Check if any processes are not 2->1,2,3 |
4034 | for me in self.matrix_elements: |
4035 | @@ -1135,7 +1018,7 @@ |
4036 | #=========================================================================== |
4037 | # Process export helper functions |
4038 | #=========================================================================== |
4039 | - def get_process_class_definitions(self): |
4040 | + def get_process_class_definitions(self, write=True): |
4041 | """The complete Pythia 8 class definition for the process""" |
4042 | |
4043 | replace_dict = self.get_default_converter() |
4044 | @@ -1199,12 +1082,13 @@ |
4045 | replace("0_", "") \ |
4046 | for me in self.matrix_elements]) |
4047 | |
4048 | - |
4049 | - file = read_template_file('pythia8_process_class.inc') % replace_dict |
4050 | - |
4051 | - return file |
4052 | - |
4053 | - def get_process_function_definitions(self): |
4054 | + if write: |
4055 | + file = self.read_template_file('pythia8_process_class.inc') % replace_dict |
4056 | + return file |
4057 | + else: |
4058 | + return replace_dict |
4059 | + |
4060 | + def get_process_function_definitions(self, write=True): |
4061 | """The complete Pythia 8 class definition for the process""" |
4062 | |
4063 | |
4064 | @@ -1239,11 +1123,12 @@ |
4065 | replace_dict['all_sigmaKin'] = \ |
4066 | self.get_all_sigmaKin_lines(color_amplitudes, |
4067 | self.process_name) |
4068 | - |
4069 | - file = read_template_file('pythia8_process_function_definitions.inc') %\ |
4070 | + if write: |
4071 | + file = self.read_template_file('pythia8_process_function_definitions.inc') %\ |
4072 | replace_dict |
4073 | - |
4074 | - return file |
4075 | + return file |
4076 | + else: |
4077 | + return replace_dict |
4078 | |
4079 | def get_process_influx(self): |
4080 | """Return process file name for the process in matrix_element""" |
4081 | @@ -1292,6 +1177,19 @@ |
4082 | |
4083 | return |
4084 | |
4085 | + #=============================================================================== |
4086 | + # Global helper methods |
4087 | + #=============================================================================== |
4088 | + @classmethod |
4089 | + def read_template_file(cls, filename): |
4090 | + """Open a template file and return the contents.""" |
4091 | + |
4092 | + try: |
4093 | + return super(OneProcessExporterPythia8, cls).read_template_file(filename) |
4094 | + except: |
4095 | + return super(OneProcessExporterPythia8, cls).read_template_file(filename, classpath=True) |
4096 | + |
4097 | + |
4098 | def get_id_masses(self, process): |
4099 | """Return the lines which define the ids for the final state particles, |
4100 | for the Pythia phase space""" |
4101 | @@ -1693,19 +1591,295 @@ |
4102 | |
4103 | |
4104 | #=============================================================================== |
4105 | -# Global helper methods |
4106 | +# ProcessExporterCPP |
4107 | #=============================================================================== |
4108 | -def read_template_file(filename): |
4109 | - """Open a template file and return the contents.""" |
4110 | - try: |
4111 | - return open(os.path.join(_file_path, \ |
4112 | - 'iolibs', 'template_files', 'pythia8', |
4113 | - filename)).read() |
4114 | - except: |
4115 | - return open(os.path.join(_file_path, \ |
4116 | - 'iolibs', 'template_files', |
4117 | - filename)).read() |
4118 | - |
4119 | +class ProcessExporterCPP(VirtualExporter): |
4120 | + """Class to take care of exporting a set of matrix elements to |
4121 | + Fortran (v4) format.""" |
4122 | + |
4123 | + grouped_mode = False |
4124 | + exporter = 'cpp' |
4125 | + |
4126 | + default_opt = {'clean': False, 'complex_mass':False, |
4127 | + 'export_format':'madevent', 'mp': False, |
4128 | + 'v5_model': True |
4129 | + } |
4130 | + |
4131 | + oneprocessclass = OneProcessExporterCPP |
4132 | + s= _file_path + 'iolibs/template_files/' |
4133 | + from_template = {'src': [s+'rambo.h', s+'rambo.cc', s+'read_slha.h', s+'read_slha.cc'], |
4134 | + 'SubProcesses': [s+'check_sa.cpp']} |
4135 | + to_link_in_P = ['check_sa.cpp', 'Makefile'] |
4136 | + template_src_make = pjoin(_file_path, 'iolibs', 'template_files','Makefile_sa_cpp_src') |
4137 | + template_Sub_make = template_src_make |
4138 | + |
4139 | + |
4140 | + |
4141 | + def __init__(self, dir_path = "", opt=None): |
4142 | + """Initiate the ProcessExporterFortran with directory information""" |
4143 | + self.mgme_dir = MG5DIR |
4144 | + self.dir_path = dir_path |
4145 | + self.model = None |
4146 | + |
4147 | + self.opt = dict(self.default_opt) |
4148 | + if opt: |
4149 | + self.opt.update(opt) |
4150 | + |
4151 | + #place holder to pass information to the run_interface |
4152 | + self.proc_characteristic = banner_mod.ProcCharacteristic() |
4153 | + |
4154 | + def copy_template(self, model): |
4155 | + """Prepare export_dir as standalone_cpp directory, including: |
4156 | + src (for RAMBO, model and ALOHA files + makefile) |
4157 | + lib (with compiled libraries from src) |
4158 | + SubProcesses (with check_sa.cpp + makefile and Pxxxxx directories) |
4159 | + """ |
4160 | + |
4161 | + try: |
4162 | + os.mkdir(self.dir_path) |
4163 | + except os.error as error: |
4164 | + logger.warning(error.strerror + " " + self.dir_path) |
4165 | + |
4166 | + with misc.chdir(self.dir_path): |
4167 | + logger.info('Creating subdirectories in directory %s' % self.dir_path) |
4168 | + |
4169 | + for d in ['src', 'lib', 'Cards', 'SubProcesses']: |
4170 | + try: |
4171 | + os.mkdir(d) |
4172 | + except os.error as error: |
4173 | + logger.warning(error.strerror + " " + self.dir_path) |
4174 | + |
4175 | + # Write param_card |
4176 | + open(os.path.join("Cards","param_card.dat"), 'w').write(\ |
4177 | + model.write_param_card()) |
4178 | + |
4179 | + |
4180 | + # Copy the needed src files |
4181 | + for key in self.from_template: |
4182 | + for f in self.from_template[key]: |
4183 | + cp(f, key) |
4184 | + |
4185 | + # Copy src Makefile |
4186 | + makefile = self.read_template_file('Makefile_sa_cpp_src') % \ |
4187 | + {'model': self.get_model_name(model.get('name'))} |
4188 | + open(os.path.join('src', 'Makefile'), 'w').write(makefile) |
4189 | + |
4190 | + # Copy SubProcesses Makefile |
4191 | + makefile = self.read_template_file('Makefile_sa_cpp_sp') % \ |
4192 | + {'model': self.get_model_name(model.get('name'))} |
4193 | + open(os.path.join('SubProcesses', 'Makefile'), 'w').write(makefile) |
4194 | + |
4195 | + #=========================================================================== |
4196 | + # Helper functions |
4197 | + #=========================================================================== |
4198 | + def modify_grouping(self, matrix_element): |
4199 | + """allow to modify the grouping (if grouping is in place) |
4200 | + return two value: |
4201 | + - True/False if the matrix_element was modified |
4202 | + - the new(or old) matrix element""" |
4203 | + |
4204 | + return False, matrix_element |
4205 | + |
4206 | + |
4207 | + |
4208 | + def convert_model(self, model, wanted_lorentz = [], |
4209 | + wanted_couplings = []): |
4210 | + # create the model parameter files |
4211 | + model_builder = UFOModelConverterCPP(model, |
4212 | + os.path.join(self.dir_path, 'src'), |
4213 | + wanted_lorentz, |
4214 | + wanted_couplings) |
4215 | + model_builder.write_files() |
4216 | + |
4217 | + def compile_model(self): |
4218 | + make_model_cpp(self.dir_path) |
4219 | + |
4220 | + @classmethod |
4221 | + def read_template_file(cls, *args, **opts): |
4222 | + """Open a template file and return the contents.""" |
4223 | + |
4224 | + return cls.oneprocessclass.read_template_file(*args, **opts) |
4225 | + |
4226 | + #=============================================================================== |
4227 | + # generate_subprocess_directory |
4228 | + #=============================================================================== |
4229 | + def generate_subprocess_directory(self, matrix_element, cpp_helas_call_writer, |
4230 | + proc_number=None): |
4231 | + """Generate the Pxxxxx directory for a subprocess in C++ standalone, |
4232 | + including the necessary .h and .cc files""" |
4233 | + |
4234 | + |
4235 | + process_exporter_cpp = self.oneprocessclass(matrix_element,cpp_helas_call_writer) |
4236 | + |
4237 | + |
4238 | + # Create the directory PN_xx_xxxxx in the specified path |
4239 | + dirpath = pjoin(self.dir_path, 'SubProcesses', "P%d_%s" % (process_exporter_cpp.process_number, |
4240 | + process_exporter_cpp.process_name)) |
4241 | + try: |
4242 | + os.mkdir(dirpath) |
4243 | + except os.error as error: |
4244 | + logger.warning(error.strerror + " " + dirpath) |
4245 | + |
4246 | + with misc.chdir(dirpath): |
4247 | + logger.info('Creating files in directory %s' % dirpath) |
4248 | + process_exporter_cpp.path = dirpath |
4249 | + # Create the process .h and .cc files |
4250 | + process_exporter_cpp.generate_process_files() |
4251 | + for file in self.to_link_in_P: |
4252 | + ln('../%s' % file) |
4253 | + return |
4254 | + |
4255 | + @staticmethod |
4256 | + def get_model_name(name): |
4257 | + """Replace - with _, + with _plus_ in a model name.""" |
4258 | + |
4259 | + name = name.replace('-', '_') |
4260 | + name = name.replace('+', '_plus_') |
4261 | + return name |
4262 | + |
4263 | + def finalize(self, *args, **opts): |
4264 | + """ """ |
4265 | + self.compile_model() |
4266 | + pass |
4267 | + |
4268 | +class ProcessExporterMatchbox(ProcessExporterCPP): |
4269 | + oneprocessclass = OneProcessExporterMatchbox |
4270 | + |
4271 | +class ProcessExporterPythia8(ProcessExporterCPP): |
4272 | + oneprocessclass = OneProcessExporterPythia8 |
4273 | + grouped_mode = 'madevent' |
4274 | + |
4275 | + #=============================================================================== |
4276 | + # generate_process_files_pythia8 |
4277 | + #=============================================================================== |
4278 | + def generate_process_directory(self, multi_matrix_element, cpp_helas_call_writer, |
4279 | + process_string = "", |
4280 | + process_number = 0, |
4281 | + version='8.2'): |
4282 | + |
4283 | + """Generate the .h and .cc files needed for Pythia 8, for the |
4284 | + processes described by multi_matrix_element""" |
4285 | + |
4286 | + process_exporter_pythia8 = OneProcessExporterPythia8(multi_matrix_element, |
4287 | + cpp_helas_call_writer, |
4288 | + process_string, |
4289 | + process_number, |
4290 | + self.dir_path, |
4291 | + version=version) |
4292 | + |
4293 | + # Set process directory |
4294 | + model = process_exporter_pythia8.model |
4295 | + model_name = process_exporter_pythia8.model_name |
4296 | + process_exporter_pythia8.process_dir = \ |
4297 | + 'Processes_%(model)s' % {'model': \ |
4298 | + model_name} |
4299 | + process_exporter_pythia8.include_dir = process_exporter_pythia8.process_dir |
4300 | + process_exporter_pythia8.generate_process_files() |
4301 | + return process_exporter_pythia8 |
4302 | + |
4303 | + #=============================================================================== |
4304 | + # generate_example_file_pythia8 |
4305 | + #=============================================================================== |
4306 | + @staticmethod |
4307 | + def generate_example_file_pythia8(path, |
4308 | + model_path, |
4309 | + process_names, |
4310 | + exporter, |
4311 | + main_file_name = "", |
4312 | + example_dir = "examples", |
4313 | + version="8.2"): |
4314 | + """Generate the main_model_name.cc file and Makefile in the examples dir""" |
4315 | + |
4316 | + filepath = os.path.join(path, example_dir) |
4317 | + if not os.path.isdir(filepath): |
4318 | + os.makedirs(filepath) |
4319 | + |
4320 | + replace_dict = {} |
4321 | + |
4322 | + # Extract version number and date from VERSION file |
4323 | + info_lines = get_mg5_info_lines() |
4324 | + replace_dict['info_lines'] = info_lines |
4325 | + |
4326 | + # Extract model name |
4327 | + replace_dict['model_name'] = exporter.model_name |
4328 | + |
4329 | + # Extract include line |
4330 | + replace_dict['include_lines'] = \ |
4331 | + "\n".join(["#include \"%s.h\"" % proc_name \ |
4332 | + for proc_name in process_names]) |
4333 | + |
4334 | + # Extract setSigmaPtr line |
4335 | + replace_dict['sigma_pointer_lines'] = \ |
4336 | + "\n".join(["pythia.setSigmaPtr(new %s());" % proc_name \ |
4337 | + for proc_name in process_names]) |
4338 | + |
4339 | + # Extract param_card path |
4340 | + replace_dict['param_card'] = os.path.join(os.path.pardir,model_path, |
4341 | + "param_card_%s.dat" % \ |
4342 | + exporter.model_name) |
4343 | + |
4344 | + # Create the example main file |
4345 | + if version =="8.2": |
4346 | + template_path = 'pythia8.2_main_example_cc.inc' |
4347 | + makefile_path = 'pythia8.2_main_makefile.inc' |
4348 | + replace_dict['include_prefix'] = 'Pythia8/' |
4349 | + else: |
4350 | + template_path = 'pythia8_main_example_cc.inc' |
4351 | + makefile_path = 'pythia8_main_makefile.inc' |
4352 | + replace_dict['include_prefix'] = '' |
4353 | + |
4354 | + |
4355 | + file = ProcessExporterPythia8.read_template_file(template_path) % \ |
4356 | + replace_dict |
4357 | + |
4358 | + if not main_file_name: |
4359 | + num = 1 |
4360 | + while os.path.exists(os.path.join(filepath, |
4361 | + 'main_%s_%i.cc' % (exporter.model_name, num))) or \ |
4362 | + os.path.exists(os.path.join(filepath, |
4363 | + 'main_%s_%i' % (exporter.model_name, num))): |
4364 | + num += 1 |
4365 | + main_file_name = str(num) |
4366 | + |
4367 | + main_file = 'main_%s_%s' % (exporter.model_name, |
4368 | + main_file_name) |
4369 | + |
4370 | + main_filename = os.path.join(filepath, main_file + '.cc') |
4371 | + |
4372 | + # Write the file |
4373 | + writers.CPPWriter(main_filename).writelines(file) |
4374 | + |
4375 | + replace_dict = {} |
4376 | + |
4377 | + # Extract version number and date from VERSION file |
4378 | + replace_dict['info_lines'] = get_mg5_info_lines() |
4379 | + |
4380 | + replace_dict['main_file'] = main_file |
4381 | + |
4382 | + replace_dict['process_dir'] = model_path |
4383 | + |
4384 | + replace_dict['include_dir'] = exporter.include_dir |
4385 | + |
4386 | + # Create the makefile |
4387 | + file = ProcessExporterPythia8.read_template_file(makefile_path) % replace_dict |
4388 | + |
4389 | + make_filename = os.path.join(filepath, 'Makefile_%s_%s' % \ |
4390 | + (exporter.model_name, main_file_name)) |
4391 | + |
4392 | + # Write the file |
4393 | + open(make_filename, 'w').write(file) |
4394 | + |
4395 | + logger.info("Created files %s and %s in directory %s" \ |
4396 | + % (os.path.split(main_filename)[-1], |
4397 | + os.path.split(make_filename)[-1], |
4398 | + os.path.split(make_filename)[0])) |
4399 | + return main_file, make_filename |
4400 | + |
4401 | + def convert_model(self,*args,**opts): |
4402 | + pass |
4403 | + def finalize(self, *args, **opts): |
4404 | + pass |
4405 | + |
4406 | def get_mg5_info_lines(): |
4407 | """Return info lines for MG5, suitable to place at beginning of |
4408 | Fortran files""" |
4409 | @@ -1753,21 +1927,6 @@ |
4410 | return res_str + '*' |
4411 | |
4412 | #=============================================================================== |
4413 | -# Routines to export/output UFO models in C++ format |
4414 | -#=============================================================================== |
4415 | - |
4416 | -def convert_model_to_cpp(model, output_dir, wanted_lorentz = [], |
4417 | - wanted_couplings = []): |
4418 | - """Create a full valid Pythia 8 model from an MG5 model (coming from UFO)""" |
4419 | - |
4420 | - # create the model parameter files |
4421 | - model_builder = UFOModelConverterCPP(model, |
4422 | - os.path.join(output_dir, 'src'), |
4423 | - wanted_lorentz, |
4424 | - wanted_couplings) |
4425 | - model_builder.write_files() |
4426 | - |
4427 | -#=============================================================================== |
4428 | # UFOModelConverterCPP |
4429 | #=============================================================================== |
4430 | |
4431 | @@ -1998,9 +2157,9 @@ |
4432 | replace_dict['include_prefix'] = '' |
4433 | |
4434 | |
4435 | - file_h = read_template_file(self.param_template_h) % \ |
4436 | + file_h = self.read_template_file(self.param_template_h) % \ |
4437 | replace_dict |
4438 | - file_cc = read_template_file(self.param_template_cc) % \ |
4439 | + file_cc = self.read_template_file(self.param_template_cc) % \ |
4440 | replace_dict |
4441 | |
4442 | return file_h, file_cc |
4443 | @@ -2109,8 +2268,8 @@ |
4444 | replace_dict['function_declarations'] = '\n'.join(template_h_files) |
4445 | replace_dict['function_definitions'] = '\n'.join(template_cc_files) |
4446 | |
4447 | - file_h = read_template_file(self.aloha_template_h) % replace_dict |
4448 | - file_cc = read_template_file(self.aloha_template_cc) % replace_dict |
4449 | + file_h = self.read_template_file(self.aloha_template_h) % replace_dict |
4450 | + file_cc = self.read_template_file(self.aloha_template_cc) % replace_dict |
4451 | |
4452 | # Write the files |
4453 | writers.CPPWriter(model_h_file).writelines(file_h) |
4454 | @@ -2173,105 +2332,14 @@ |
4455 | |
4456 | return line |
4457 | |
4458 | -#=============================================================================== |
4459 | -# generate_example_file_pythia8 |
4460 | -#=============================================================================== |
4461 | -def generate_example_file_pythia8(path, |
4462 | - model_path, |
4463 | - process_names, |
4464 | - exporter, |
4465 | - main_file_name = "", |
4466 | - example_dir = "examples", |
4467 | - version="8.2"): |
4468 | - """Generate the main_model_name.cc file and Makefile in the examples dir""" |
4469 | - |
4470 | - filepath = os.path.join(path, example_dir) |
4471 | - if not os.path.isdir(filepath): |
4472 | - os.makedirs(filepath) |
4473 | - |
4474 | - replace_dict = {} |
4475 | - |
4476 | - # Extract version number and date from VERSION file |
4477 | - info_lines = get_mg5_info_lines() |
4478 | - replace_dict['info_lines'] = info_lines |
4479 | - |
4480 | - # Extract model name |
4481 | - replace_dict['model_name'] = exporter.model_name |
4482 | - |
4483 | - # Extract include line |
4484 | - replace_dict['include_lines'] = \ |
4485 | - "\n".join(["#include \"%s.h\"" % proc_name \ |
4486 | - for proc_name in process_names]) |
4487 | - |
4488 | - # Extract setSigmaPtr line |
4489 | - replace_dict['sigma_pointer_lines'] = \ |
4490 | - "\n".join(["pythia.setSigmaPtr(new %s());" % proc_name \ |
4491 | - for proc_name in process_names]) |
4492 | - |
4493 | - # Extract param_card path |
4494 | - replace_dict['param_card'] = os.path.join(os.path.pardir,model_path, |
4495 | - "param_card_%s.dat" % \ |
4496 | - exporter.model_name) |
4497 | - |
4498 | - # Create the example main file |
4499 | - if version =="8.2": |
4500 | - template_path = 'pythia8.2_main_example_cc.inc' |
4501 | - makefile_path = 'pythia8.2_main_makefile.inc' |
4502 | - replace_dict['include_prefix'] = 'Pythia8/' |
4503 | - else: |
4504 | - template_path = 'pythia8_main_example_cc.inc' |
4505 | - makefile_path = 'pythia8_main_makefile.inc' |
4506 | - replace_dict['include_prefix'] = '' |
4507 | - |
4508 | - |
4509 | - file = read_template_file(template_path) % \ |
4510 | - replace_dict |
4511 | - |
4512 | - if not main_file_name: |
4513 | - num = 1 |
4514 | - while os.path.exists(os.path.join(filepath, |
4515 | - 'main_%s_%i.cc' % (exporter.model_name, num))) or \ |
4516 | - os.path.exists(os.path.join(filepath, |
4517 | - 'main_%s_%i' % (exporter.model_name, num))): |
4518 | - num += 1 |
4519 | - main_file_name = str(num) |
4520 | - |
4521 | - main_file = 'main_%s_%s' % (exporter.model_name, |
4522 | - main_file_name) |
4523 | - |
4524 | - main_filename = os.path.join(filepath, main_file + '.cc') |
4525 | - |
4526 | - # Write the file |
4527 | - writers.CPPWriter(main_filename).writelines(file) |
4528 | - |
4529 | - replace_dict = {} |
4530 | - |
4531 | - # Extract version number and date from VERSION file |
4532 | - replace_dict['info_lines'] = get_mg5_info_lines() |
4533 | - |
4534 | - replace_dict['main_file'] = main_file |
4535 | - |
4536 | - replace_dict['process_dir'] = model_path |
4537 | - |
4538 | - replace_dict['include_dir'] = exporter.include_dir |
4539 | - |
4540 | - # Create the makefile |
4541 | - file = read_template_file(makefile_path) % replace_dict |
4542 | - |
4543 | - make_filename = os.path.join(filepath, 'Makefile_%s_%s' % \ |
4544 | - (exporter.model_name, main_file_name)) |
4545 | - |
4546 | - # Write the file |
4547 | - open(make_filename, 'w').write(file) |
4548 | - |
4549 | - logger.info("Created files %s and %s in directory %s" \ |
4550 | - % (os.path.split(main_filename)[-1], |
4551 | - os.path.split(make_filename)[-1], |
4552 | - os.path.split(make_filename)[0])) |
4553 | - return main_file, make_filename |
4554 | - |
4555 | - |
4556 | - |
4557 | + #=============================================================================== |
4558 | + # Global helper methods |
4559 | + #=============================================================================== |
4560 | + @classmethod |
4561 | + def read_template_file(cls, filename, classpath=False): |
4562 | + """Open a template file and return the contents.""" |
4563 | + |
4564 | + return OneProcessExporterCPP.read_template_file(filename, classpath) |
4565 | |
4566 | |
4567 | #=============================================================================== |
4568 | @@ -2286,8 +2354,8 @@ |
4569 | namespace = 'Pythia8' |
4570 | |
4571 | # Dictionaries for expression of MG5 SM parameters into Pythia 8 |
4572 | - slha_to_expr = {('SMINPUTS', (1,)): '1./csm->alphaEM(pow(pd->m0(23),2))', |
4573 | - ('SMINPUTS', (2,)): 'M_PI*csm->alphaEM(pow(pd->m0(23),2))*pow(pd->m0(23),2)/(sqrt(2.)*pow(pd->m0(24),2)*(pow(pd->m0(23),2)-pow(pd->m0(24),2)))', |
4574 | + slha_to_expr = {('SMINPUTS', (1,)): '1./csm->alphaEM(((pd->m0(23))*(pd->m0(23))))', |
4575 | + ('SMINPUTS', (2,)): 'M_PI*csm->alphaEM(((pd->m0(23))*(pd->m0(23))))*((pd->m0(23))*(pd->m0(23)))/(sqrt(2.)*((pd->m0(24))*(pd->m0(24)))*(((pd->m0(23))*(pd->m0(23)))-((pd->m0(24))*(pd->m0(24)))))', |
4576 | ('SMINPUTS', (3,)): 'alpS', |
4577 | ('CKMBLOCK', (1,)): 'csm->VCKMgen(1,2)', |
4578 | } |
4579 | @@ -2295,6 +2363,7 @@ |
4580 | # Template files to use |
4581 | param_template_h = 'pythia8_model_parameters_h.inc' |
4582 | param_template_cc = 'pythia8_model_parameters_cc.inc' |
4583 | + template_paths = os.path.join(_file_path, 'iolibs', 'template_files', 'pythia8') |
4584 | |
4585 | def prepare_parameters(self): |
4586 | """Extract the model parameters from Pythia 8, and store them in |
4587 | @@ -2412,7 +2481,7 @@ |
4588 | path = 'pythia8.2_makefile.inc' |
4589 | else: |
4590 | path = 'pythia8_makefile.inc' |
4591 | - makefile = read_template_file(path) % replace_dict |
4592 | + makefile = self.read_template_file(path) % replace_dict |
4593 | |
4594 | # Write the files |
4595 | open(makefilename, 'w').write(makefile) |
4596 | @@ -2433,3 +2502,32 @@ |
4597 | logger.info("Created %s in directory %s" \ |
4598 | % (os.path.split(paramcardname)[-1], |
4599 | os.path.split(paramcardname)[0])) |
4600 | + |
4601 | + #=============================================================================== |
4602 | + # Global helper methods |
4603 | + #=============================================================================== |
4604 | + @classmethod |
4605 | + def read_template_file(cls, *args, **opts): |
4606 | + """Open a template file and return the contents.""" |
4607 | + |
4608 | + return OneProcessExporterPythia8.read_template_file(*args, **opts) |
4609 | + |
4610 | +def ExportCPPFactory(cmd, group_subprocesses=False): |
4611 | + """ Determine which Export class is required. cmd is the command |
4612 | + interface containing all potential usefull information. |
4613 | + """ |
4614 | + |
4615 | + opt = cmd.options |
4616 | + cformat = cmd._export_format |
4617 | + |
4618 | + if cformat == 'pythia8': |
4619 | + return ProcessExporterPythia8(cmd._export_dir, opt) |
4620 | + elif cformat == 'standalone_cpp': |
4621 | + return ProcessExporterCPP(cmd._export_dir, opt) |
4622 | + elif cformat == 'matchbox_cpp': |
4623 | + return ProcessExporterMatchbox(cmd._export_dir, opt) |
4624 | + elif cformat == 'plugin': |
4625 | + return cmd._export_plugin(cmd._export_dir, opt) |
4626 | + |
4627 | + |
4628 | + |
4629 | |
4630 | === modified file 'madgraph/iolibs/export_fks.py' |
4631 | --- madgraph/iolibs/export_fks.py 2016-06-24 01:32:34 +0000 |
4632 | +++ madgraph/iolibs/export_fks.py 2016-08-18 22:31:39 +0000 |
4633 | @@ -285,10 +285,10 @@ |
4634 | cp(pjoin(_file_path,cp_file), |
4635 | pjoin(self.dir_path,'bin','internal',os.path.basename(cp_file))) |
4636 | |
4637 | - def convert_model_to_mg4(self, model, wanted_lorentz = [], |
4638 | + def convert_model(self, model, wanted_lorentz = [], |
4639 | wanted_couplings = []): |
4640 | |
4641 | - super(ProcessExporterFortranFKS,self).convert_model_to_mg4(model, |
4642 | + super(ProcessExporterFortranFKS,self).convert_model(model, |
4643 | wanted_lorentz, wanted_couplings) |
4644 | |
4645 | IGNORE_PATTERNS = ('*.pyc','*.dat','*.py~') |
4646 | @@ -705,12 +705,39 @@ |
4647 | run_card.write(pjoin(self.dir_path, 'Cards', 'run_card.dat')) |
4648 | |
4649 | |
4650 | - def finalize_fks_directory(self, matrix_elements, history, makejpg = False, |
4651 | - online = False, |
4652 | - compiler_dict={'fortran': 'gfortran', 'cpp': 'g++'}, |
4653 | - output_dependencies = 'external', MG5DIR = None): |
4654 | + |
4655 | + def finalize(self, matrix_elements, history, mg5options, flaglist): |
4656 | """Finalize FKS directory by creating jpeg diagrams, html |
4657 | pages,proc_card_mg5.dat and madevent.tar.gz.""" |
4658 | + |
4659 | + devnull = os.open(os.devnull, os.O_RDWR) |
4660 | + try: |
4661 | + res = misc.call([self.options['lhapdf'], '--version'], \ |
4662 | + stdout=subprocess.PIPE, stderr=subprocess.PIPE) |
4663 | + except Exception: |
4664 | + res = 1 |
4665 | + if res != 0: |
4666 | + logger.info('The value for lhapdf in the current configuration does not ' + \ |
4667 | + 'correspond to a valid executable.\nPlease set it correctly either in ' + \ |
4668 | + 'input/mg5_configuration or with "set lhapdf /path/to/lhapdf-config" ' + \ |
4669 | + 'and regenrate the process. \nTo avoid regeneration, edit the ' + \ |
4670 | + ('%s/Cards/amcatnlo_configuration.txt file.\n' % self.dir_path ) + \ |
4671 | + 'Note that you can still compile and run aMC@NLO with the built-in PDFs\n') |
4672 | + |
4673 | + compiler_dict = {'fortran': mg5options['fortran_compiler'], |
4674 | + 'cpp': mg5options['cpp_compiler'], |
4675 | + 'f2py': mg5options['f2py_compiler']} |
4676 | + |
4677 | + if 'nojpeg' in flaglist: |
4678 | + makejpg = False |
4679 | + else: |
4680 | + makejpg = True |
4681 | + if 'online' in flaglist: |
4682 | + online = True |
4683 | + else: |
4684 | + online = False |
4685 | + output_dependencies = mg5options['output_dependencies'] |
4686 | + |
4687 | |
4688 | self.proc_characteristic['grouped_matrix'] = False |
4689 | self.create_proc_charac() |
4690 | @@ -3033,6 +3060,11 @@ |
4691 | """Class to take care of exporting a set of matrix elements to |
4692 | Fortran (v4) format.""" |
4693 | |
4694 | + |
4695 | + def finalize(self, *args, **opts): |
4696 | + ProcessExporterFortranFKS.finalize(self, *args, **opts) |
4697 | + #export_v4.ProcessExporterFortranSA.finalize(self, *args, **opts) |
4698 | + |
4699 | #=============================================================================== |
4700 | # copy the Template in a new directory. |
4701 | #=============================================================================== |
4702 | |
4703 | === modified file 'madgraph/iolibs/export_v4.py' |
4704 | --- madgraph/iolibs/export_v4.py 2016-08-14 00:17:23 +0000 |
4705 | +++ madgraph/iolibs/export_v4.py 2016-08-18 22:31:39 +0000 |
4706 | @@ -68,10 +68,71 @@ |
4707 | 'f2py': 'f2py', |
4708 | 'cpp':'g++'} |
4709 | |
4710 | + |
4711 | +class VirtualExporter(object): |
4712 | + |
4713 | + #exporter variable who modified the way madgraph interacts with this class |
4714 | + |
4715 | + grouped_mode = 'madevent' |
4716 | + # This variable changes the type of object called within 'generate_subprocess_directory' |
4717 | + #functions. |
4718 | + # False to avoid grouping (only identical matrix element are merged) |
4719 | + # 'madevent' group the massless quark and massless lepton |
4720 | + # 'madweight' group the gluon with the massless quark |
4721 | + sa_symmetry = False |
4722 | + # If no grouped_mode=False, uu~ and u~u will be called independently. |
4723 | + #Putting sa_symmetry generates only one of the two matrix-element. |
4724 | + check = True |
4725 | + # Ask madgraph to check if the directory already exists and propose to the user to |
4726 | + #remove it first if this is the case |
4727 | + output = 'Template' |
4728 | + # [Template, None, dir] |
4729 | + # - Template, madgraph will call copy_template |
4730 | + # - dir, madgraph will just create an empty directory for initialisation |
4731 | + # - None, madgraph do nothing for initialisation |
4732 | + exporter = 'v4' |
4733 | + # language of the output 'v4' for Fortran output |
4734 | + # 'cpp' for C++ output |
4735 | + |
4736 | + |
4737 | + def __init__(self, dir_path = "", opt=None): |
4738 | + return |
4739 | + |
4740 | + def copy_template(self, model): |
4741 | + return |
4742 | + |
4743 | + def generate_subprocess_directory(self, subproc_group, helicity_model, me=None): |
4744 | + # generate_subprocess_directory(self, matrix_element, helicity_model, me_number) [for ungrouped] |
4745 | + return 0 # return an integer stating the number of call to helicity routine |
4746 | + |
4747 | + def convert_model(self, model, wanted_lorentz=[], wanted_couplings=[]): |
4748 | + return |
4749 | + |
4750 | + def finalize(self,matrix_element, cmdhistory, MG5options, outputflag): |
4751 | + return |
4752 | + |
4753 | + |
4754 | + def pass_information_from_cmd(self, cmd): |
4755 | + """pass information from the command interface to the exporter. |
4756 | + Please do not modify any object of the interface from the exporter. |
4757 | + """ |
4758 | + return |
4759 | + |
4760 | + def modify_grouping(self, matrix_element): |
4761 | + return False, matrix_element |
4762 | + |
4763 | + def export_model_files(self, model_v4_path): |
4764 | + raise Exception, "V4 model not supported by this type of exporter. Please use UFO model" |
4765 | + return |
4766 | + |
4767 | + def export_helas(self, HELAS_PATH): |
4768 | + raise Exception, "V4 model not supported by this type of exporter. Please use UFO model" |
4769 | + return |
4770 | + |
4771 | #=============================================================================== |
4772 | # ProcessExporterFortran |
4773 | #=============================================================================== |
4774 | -class ProcessExporterFortran(object): |
4775 | +class ProcessExporterFortran(VirtualExporter): |
4776 | """Class to take care of exporting a set of matrix elements to |
4777 | Fortran (v4) format.""" |
4778 | |
4779 | @@ -79,10 +140,11 @@ |
4780 | 'export_format':'madevent', 'mp': False, |
4781 | 'v5_model': True |
4782 | } |
4783 | + grouped_mode = False |
4784 | |
4785 | - def __init__(self, mgme_dir = "", dir_path = "", opt=None): |
4786 | + def __init__(self, dir_path = "", opt=None): |
4787 | """Initiate the ProcessExporterFortran with directory information""" |
4788 | - self.mgme_dir = mgme_dir |
4789 | + self.mgme_dir = MG5DIR |
4790 | self.dir_path = dir_path |
4791 | self.model = None |
4792 | |
4793 | @@ -102,35 +164,29 @@ |
4794 | |
4795 | calls = 0 |
4796 | if isinstance(matrix_elements, group_subprocs.SubProcessGroupList): |
4797 | - unique_id=1 |
4798 | for (group_number, me_group) in enumerate(matrix_elements): |
4799 | - calls = calls + self.generate_subprocess_directory_v4(\ |
4800 | - me_group, fortran_model, group_number, unique_id=unique_id) |
4801 | - unique_id += len(me_group.get('matrix_elements')) |
4802 | + calls = calls + self.generate_subprocess_directory(\ |
4803 | + me_group, fortran_model, group_number) |
4804 | else: |
4805 | for me_number, me in enumerate(matrix_elements.get_matrix_elements()): |
4806 | - calls = calls + self.generate_subprocess_directory_v4(\ |
4807 | + calls = calls + self.generate_subprocess_directory(\ |
4808 | me, fortran_model, me_number) |
4809 | |
4810 | return calls |
4811 | |
4812 | - #=========================================================================== |
4813 | - # Generate an include file with global quantities about all ME's output. |
4814 | - #=========================================================================== |
4815 | - def write_global_specs(self, matrix_elements): |
4816 | - """ Writes the file global_specs.inc which contains general information |
4817 | - about *all* the ME's output in this directory.""" |
4818 | - |
4819 | - # Do nothing here, but daughter classes such as LoopOptimizedExporterFortran |
4820 | - # overwrites this. |
4821 | - pass |
4822 | |
4823 | #=========================================================================== |
4824 | # create the run_card |
4825 | #=========================================================================== |
4826 | def create_run_card(self, matrix_elements, history): |
4827 | """ """ |
4828 | - |
4829 | + |
4830 | + |
4831 | + # bypass this for the loop-check |
4832 | + import madgraph.loop.loop_helas_objects as loop_helas_objects |
4833 | + if isinstance(matrix_elements, loop_helas_objects.LoopHelasMatrixElement): |
4834 | + matrix_elements = None |
4835 | + |
4836 | run_card = banner_mod.RunCard() |
4837 | |
4838 | |
4839 | @@ -157,7 +213,7 @@ |
4840 | #=========================================================================== |
4841 | # copy the Template in a new directory. |
4842 | #=========================================================================== |
4843 | - def copy_v4template(self, modelname): |
4844 | + def copy_template(self, model): |
4845 | """create the directory run_name as a copy of the MadEvent |
4846 | Template, and clean the directory |
4847 | """ |
4848 | @@ -284,27 +340,30 @@ |
4849 | process_str = ' '.join(new_process_content) |
4850 | |
4851 | #format the SubProcess |
4852 | - process_text += process_template.substitute({'process': process_str, \ |
4853 | - 'coupling': coupling}) |
4854 | - |
4855 | - text = proc_card_template.substitute({'process': process_text, |
4856 | + replace_dict = {'process': process_str, |
4857 | + 'coupling': coupling} |
4858 | + process_text += process_template.substitute(replace_dict) |
4859 | + |
4860 | + replace_dict = {'process': process_text, |
4861 | 'model': modelname, |
4862 | - 'multiparticle':''}) |
4863 | - ff = open(file_pos, 'w') |
4864 | - ff.write(text) |
4865 | - ff.close() |
4866 | - |
4867 | + 'multiparticle':''} |
4868 | + text = proc_card_template.substitute(replace_dict) |
4869 | + |
4870 | + if file_pos: |
4871 | + ff = open(file_pos, 'w') |
4872 | + ff.write(text) |
4873 | + ff.close() |
4874 | + else: |
4875 | + return replace_dict |
4876 | + |
4877 | #=========================================================================== |
4878 | # Create jpeg diagrams, html pages,proc_card_mg5.dat and madevent.tar.gz |
4879 | #=========================================================================== |
4880 | - def finalize_v4_directory(self, matrix_elements, history = "", makejpg = False, |
4881 | - online = False, compiler=default_compiler): |
4882 | - """Function to finalize v4 directory, for inheritance. |
4883 | - """ |
4884 | - |
4885 | - self.create_run_card(matrix_elements, history) |
4886 | - |
4887 | - pass |
4888 | + def finalize(self, matrix_elements, history='', mg5options={}, flaglist=[]): |
4889 | + """Function to finalize v4 directory, for inheritance.""" |
4890 | + |
4891 | + self.create_run_card(matrix_elements, history) |
4892 | + |
4893 | |
4894 | #=========================================================================== |
4895 | # Create the proc_characteristic file passing information to the run_interface |
4896 | @@ -471,9 +530,9 @@ |
4897 | # |
4898 | |
4899 | #=========================================================================== |
4900 | - # generate_subprocess_directory_v4 |
4901 | + # generate_subprocess_directory |
4902 | #=========================================================================== |
4903 | - def generate_subprocess_directory_v4(self, matrix_element, |
4904 | + def generate_subprocess_directory(self, matrix_element, |
4905 | fortran_model, |
4906 | me_number): |
4907 | """Routine to generate a subprocess directory (for inheritance)""" |
4908 | @@ -531,9 +590,11 @@ |
4909 | parameter (nincoming_prod=%(ninitial)d)""" % replace_dict |
4910 | |
4911 | # Write the file |
4912 | - writer.writelines(file) |
4913 | - |
4914 | - return True |
4915 | + if writer: |
4916 | + writer.writelines(file) |
4917 | + return True |
4918 | + else: |
4919 | + return replace_dict |
4920 | |
4921 | #=========================================================================== |
4922 | # write_helamp_madspin |
4923 | @@ -552,9 +613,12 @@ |
4924 | common /to_helamp/helamp """ % replace_dict |
4925 | |
4926 | # Write the file |
4927 | - writer.writelines(file) |
4928 | + if writer: |
4929 | + writer.writelines(file) |
4930 | + return True |
4931 | + else: |
4932 | + return replace_dict |
4933 | |
4934 | - return True |
4935 | |
4936 | |
4937 | #=========================================================================== |
4938 | @@ -575,10 +639,11 @@ |
4939 | parameter (nincoming=%(ninitial)d)""" % replace_dict |
4940 | |
4941 | # Write the file |
4942 | - writer.writelines(file) |
4943 | - |
4944 | - return True |
4945 | - |
4946 | + if writer: |
4947 | + writer.writelines(file) |
4948 | + return True |
4949 | + else: |
4950 | + return replace_dict |
4951 | #=========================================================================== |
4952 | # write_pmass_file |
4953 | #=========================================================================== |
4954 | @@ -701,62 +766,12 @@ |
4955 | |
4956 | return True |
4957 | |
4958 | - #=========================================================================== |
4959 | - # write_props_file |
4960 | - #=========================================================================== |
4961 | - def write_props_file(self, writer, matrix_element, s_and_t_channels): |
4962 | - """Write the props.inc file for MadEvent. Needs input from |
4963 | - write_configs_file.""" |
4964 | - |
4965 | - lines = [] |
4966 | - |
4967 | - particle_dict = matrix_element.get('processes')[0].get('model').\ |
4968 | - get('particle_dict') |
4969 | - |
4970 | - for iconf, configs in enumerate(s_and_t_channels): |
4971 | - for vertex in configs[0] + configs[1][:-1]: |
4972 | - leg = vertex.get('legs')[-1] |
4973 | - if leg.get('id') not in particle_dict: |
4974 | - # Fake propagator used in multiparticle vertices |
4975 | - mass = 'zero' |
4976 | - width = 'zero' |
4977 | - pow_part = 0 |
4978 | - else: |
4979 | - particle = particle_dict[leg.get('id')] |
4980 | - # Get mass |
4981 | - if particle.get('mass').lower() == 'zero': |
4982 | - mass = particle.get('mass') |
4983 | - else: |
4984 | - mass = "abs(%s)" % particle.get('mass') |
4985 | - # Get width |
4986 | - if particle.get('width').lower() == 'zero': |
4987 | - width = particle.get('width') |
4988 | - else: |
4989 | - width = "abs(%s)" % particle.get('width') |
4990 | - |
4991 | - pow_part = 1 + int(particle.is_boson()) |
4992 | - |
4993 | - lines.append("prmass(%d,%d) = %s" % \ |
4994 | - (leg.get('number'), iconf + 1, mass)) |
4995 | - lines.append("prwidth(%d,%d) = %s" % \ |
4996 | - (leg.get('number'), iconf + 1, width)) |
4997 | - lines.append("pow(%d,%d) = %d" % \ |
4998 | - (leg.get('number'), iconf + 1, pow_part)) |
4999 | - |
5000 | - # Write the file |
Hi Olivier,
I don't think I'm the right person for this review.
I've got a question, though. There seems to be many little changes in vendor/IREGI and vendor/Cuttools. Why? It doesn't seem related to this branch.
Best,
Rikkert