~maddevelopers/mg5amcnlo/3.0.2-alpha0

« back to all changes in this revision

Viewing changes to madgraph/iolibs/group_subprocs.py

Added SubProcessGroup class which keeps track of necessary information for writing out nice subprocess group directories

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
################################################################################
 
2
#
 
3
# Copyright (c) 2009 The MadGraph Development team and Contributors
 
4
#
 
5
# This file is a part of the MadGraph 5 project, an application which 
 
6
# automatically generates Feynman diagrams and matrix elements for arbitrary
 
7
# high-energy processes in the Standard Model and beyond.
 
8
#
 
9
# It is subject to the MadGraph license which should accompany this 
 
10
# distribution.
 
11
#
 
12
# For more information, please visit: http://madgraph.phys.ucl.ac.be
 
13
#
 
14
################################################################################
 
15
"""Methods and classes to group subprocesses according to initial
 
16
states, and produce the corresponding grouped subprocess directories."""
 
17
 
 
18
import fractions
 
19
import glob
 
20
import logging
 
21
import os
 
22
import re
 
23
import shutil
 
24
import subprocess
 
25
 
 
26
import madgraph.core.base_objects as base_objects
 
27
import madgraph.core.diagram_generation as diagram_generation
 
28
import madgraph.core.helas_objects as helas_objects
 
29
import madgraph.iolibs.drawing_eps as draw
 
30
import madgraph.iolibs.files as files
 
31
import madgraph.iolibs.misc as misc
 
32
import madgraph.iolibs.file_writers as writers
 
33
import madgraph.iolibs.template_files as template_files
 
34
import madgraph.iolibs.ufo_expression_parsers as parsers
 
35
 
 
36
import aloha.create_aloha as create_aloha
 
37
 
 
38
import models.sm.write_param_card as write_param_card
 
39
from madgraph import MadGraph5Error, MG5DIR
 
40
from madgraph.iolibs.files import cp, ln, mv
 
41
_file_path = os.path.split(os.path.dirname(os.path.realpath(__file__)))[0] + '/'
 
42
logger = logging.getLogger('madgraph.export_v4')
 
43
 
 
44
#===============================================================================
 
45
# SubProcessGroup
 
46
#===============================================================================
 
47
 
 
48
class SubProcessGroup(base_objects.PhysicsObject):
 
49
    """Class to group a number of amplitudes with same initial states
 
50
    into a subprocess group"""
 
51
 
 
52
    def default_setup(self):
 
53
        """Define object and give default values"""
 
54
 
 
55
        self['number'] = 0
 
56
        self['name'] = ""
 
57
        self['amplitudes'] = diagram_generation.AmplitudeList()
 
58
        self['mapping_diagrams'] = []
 
59
        self['diagram_maps'] = {}
 
60
        self['matrix_elements'] = helas_objects.HelasMultiProcess()
 
61
 
 
62
    def filter(self, name, value):
 
63
        """Filter for valid property values."""
 
64
 
 
65
        if name == 'number':
 
66
            if not isinstance(value, int):
 
67
                raise self.PhysicsObjectError, \
 
68
                        "%s is not a valid int object" % str(value)
 
69
        if name == 'name':
 
70
            if not isinstance(value, str):
 
71
                raise self.PhysicsObjectError, \
 
72
                        "%s is not a valid str object" % str(value)
 
73
        if name == 'amplitudes':
 
74
            if not isinstance(value, diagram_generation.AmplitudeList):
 
75
                raise self.PhysicsObjectError, \
 
76
                        "%s is not a valid amplitudelist" % str(value)
 
77
        if name == 'mapping_diagrams':
 
78
            if not isinstance(value, list):
 
79
                raise self.PhysicsObjectError, \
 
80
                        "%s is not a valid list" % str(value)
 
81
        if name == 'diagram_maps':
 
82
            if not isinstance(value, dict):
 
83
                raise self.PhysicsObjectError, \
 
84
                        "%s is not a valid dict" % str(value)
 
85
        if name == 'matrix_elements':
 
86
            if not isinstance(value, helas_objects.HelasMultiProcess):
 
87
                raise self.PhysicsObjectError, \
 
88
                        "%s is not a valid HelasMultiProcess" % str(value)
 
89
        return True
 
90
 
 
91
    def get_sorted_keys(self):
 
92
        """Return diagram property names as a nicely sorted list."""
 
93
 
 
94
        return ['number', 'name', 'amplitudes', 'mapping_diagrams',
 
95
                'diagram_maps', 'matrix_elements']
 
96
 
 
97
    # Enhanced get function
 
98
    def get(self, name):
 
99
        """Get the value of the property name."""
 
100
 
 
101
        if name == 'matrix_elements' and not self[name].get('matrix_elements'):
 
102
            self.generate_matrix_elements()
 
103
        
 
104
        if name in ['mapping_diagrams', 'diagram_maps'] and not self[name]:
 
105
            self.set_mapping_diagrams()
 
106
        
 
107
        return super(SubProcessGroup, self).get(name)
 
108
 
 
109
    def set_mapping_diagrams(self):
 
110
        """Set mapping_diagrams and diagram_maps, to prepare for
 
111
        generation of the super-config.inc files."""
 
112
 
 
113
        if not self.get('amplitudes'):
 
114
            raise self.PhysicsObjectError, \
 
115
                  "Need amplitudes to set mapping_diagrams"
 
116
 
 
117
        # All amplitudes are already in the same class
 
118
        process_classes = dict([(i, 0) for i in \
 
119
                                range(len(self.get('amplitudes')))])
 
120
        mapping_diagrams, diagram_maps = \
 
121
              self.get('amplitudes').find_mapping_diagrams(process_classes, 0)
 
122
 
 
123
        self.set('mapping_diagrams', mapping_diagrams)
 
124
        self.set('diagram_maps', diagram_maps)
 
125
 
 
126
    def generate_matrix_elements(self):
 
127
        """Create a HelasMultiProcess corresponding to the amplitudes
 
128
        in self"""
 
129
 
 
130
        if not self.get('amplitudes'):
 
131
            raise self.PhysicsObjectError, \
 
132
                  "Need amplitudes to generate matrix_elements"
 
133
 
 
134
        self.set_mapping_diagrams()
 
135
 
 
136
        self['matrix_elements'] = helas_objects.HelasMultiProcess(\
 
137
            self.get('amplitudes'))
 
138
 
 
139
        self.rearrange_diagram_maps()
 
140
 
 
141
    def rearrange_diagram_maps(self):
 
142
        """Rearrange the diagram_maps according to the matrix elements in
 
143
        the HelasMultiProcess"""
 
144
 
 
145
        amplitude_map = self.get('matrix_elements').get('amplitude_map')
 
146
        new_diagram_maps = {}
 
147
        for key in amplitude_map:
 
148
            new_diagram_maps[amplitude_map[key]] = self.get('diagram_maps')[key]
 
149
 
 
150
        self.set("diagram_maps", new_diagram_maps)
 
151
 
 
152
    @staticmethod
 
153
    def group_amplitudes(amplitudes):
 
154
        """Return a SubProcessGroupList with the amplitudes divided
 
155
        into subprocess groups"""
 
156
 
 
157
        if not isinstance(amplitudes, diagram_generation.AmplitudeList):
 
158
            raise SubProcessGroupList.PhysicsObjectError, \
 
159
                  "Argument to group_amplitudes must be AmplitudeList"
 
160
 
 
161
        process_classes = amplitudes.find_process_classes()
 
162
        ret_list = SubProcessGroupList()
 
163
        process_class_numbers = sorted(list(set(process_classes.values())))
 
164
        for inum, num in enumerate(process_class_numbers):
 
165
            amp_nums = [key for (key, val) in process_classes.items() if \
 
166
                          val == num]
 
167
            group = SubProcessGroup()
 
168
            group.set('number', inum+1)
 
169
            group.set('amplitudes',
 
170
                      diagram_generation.AmplitudeList([amplitudes[i] for i in \
 
171
                                                        amp_nums]))
 
172
            ret_list.append(group)
 
173
 
 
174
        return ret_list
 
175
 
 
176
#===============================================================================
 
177
# SubProcessGroupList
 
178
#===============================================================================
 
179
class SubProcessGroupList(base_objects.PhysicsObjectList):
 
180
    """List of SubProcessGroup objects"""
 
181
 
 
182
    def is_valid_element(self, obj):
 
183
        """Test if object obj is a valid element."""
 
184
 
 
185
        return isinstance(obj, SubProcessGroup)
 
186