~maddevelopers/mg5amcnlo/new_clustering

« back to all changes in this revision

Viewing changes to tests/unit_tests/fks/test_extra_ew.py

  • Committer: Rikkert Frederix
  • Date: 2021-09-09 15:51:40 UTC
  • mfrom: (78.75.502 3.2.1)
  • Revision ID: frederix@physik.uzh.ch-20210909155140-rg6umfq68h6h47cf
merge with 3.2.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
##############################################################################
 
2
#
 
3
# Copyright (c) 2010 The MadGraph5_aMC@NLO Development team and Contributors
 
4
#
 
5
# This file is a part of the MadGraph5_aMC@NLO 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 MadGraph5_aMC@NLO license which should accompany this 
 
10
# distribution.
 
11
#
 
12
# For more information, visit madgraph.phys.ucl.ac.be and amcatnlo.web.cern.ch
 
13
#
 
14
################################################################################
 
15
from __future__ import absolute_import
 
16
from __future__ import print_function
 
17
from cmd import Cmd
 
18
from six.moves import zip
 
19
""" Basic test of the command interface """
 
20
 
 
21
import unittest
 
22
import madgraph
 
23
import madgraph.interface.master_interface as mgcmd
 
24
import madgraph.interface.extended_cmd as ext_cmd
 
25
import madgraph.interface.amcatnlo_interface as amcatnlocmd
 
26
import os
 
27
import madgraph.fks.fks_helas_objects as fks_helas
 
28
import copy
 
29
import madgraph.iolibs.save_load_object as save_load_object
 
30
 
 
31
 
 
32
root_path = os.path.split(os.path.dirname(os.path.realpath( __file__ )))[0]
 
33
root_path = os.path.dirname(root_path)
 
34
# root_path is ./tests
 
35
pjoin = os.path.join
 
36
 
 
37
class TestAMCatNLOEW(unittest.TestCase):
 
38
    """ a suite of extra tests for the ew stuff """
 
39
    
 
40
    def setUp(self):
 
41
        self.interface = mgcmd.MasterCmd()
 
42
 
 
43
    def test_generate_fks_ew(self):
 
44
        """check that the generate command works as expected.
 
45
        In particular the correct number of born diagrams, real-emission processes
 
46
        and diagrams is checked"""
 
47
        cmd_list = [
 
48
            'u u~ > d d~ QED^2=0 QCD^2=4 [real=QCD]',
 
49
            'u u~ > d d~ QED^2=0 QCD^2=4 [real=QED]',
 
50
            'u u~ > d d~ QED^2=0 QCD^2=4 [real=QED QCD]',
 
51
            'u u~ > d d~ QCD^2=4 QED^2=4 [real=QCD]',
 
52
            'u u~ > d d~ QCD^2=4 QED^2=4 [real=QED]',
 
53
            'u u~ > d d~ QCD^2=4 QED^2=4 [real=QED QCD]']
 
54
 
 
55
        # exp[ected splitting types
 
56
        split_type_list = [['QCD'],
 
57
                           ['QED','QCD'],
 
58
                           ['QED','QCD'],
 
59
                           ['QED','QCD'],
 
60
                           ['QED','QCD'],
 
61
                           ['QED','QCD']]
 
62
 
 
63
        # expected born_orders
 
64
        born_orders_list = [{'QED':0, 'QCD':4},
 
65
                            {'QED':0, 'QCD':4},
 
66
                            {'QED':0, 'QCD':4},
 
67
                            {'QED':4, 'QCD':4},
 
68
                            {'QED':4, 'QCD':4},
 
69
                            {'QED':4, 'QCD':4}]
 
70
 
 
71
        # perturbation couplings (always set to [QED, QCD]
 
72
        pert_couplings_list = 9*[['QCD','QED']]
 
73
 
 
74
        # expected squared_orders (should take into
 
75
        #  account the perturbation
 
76
        squared_orders_list = [{'QED':0, 'QCD':6},
 
77
                            {'QED':2, 'QCD':4},
 
78
                            {'QED':2, 'QCD':6},
 
79
                            {'QED':4, 'QCD':6},
 
80
                            {'QED':6, 'QCD':4},
 
81
                            {'QED':6, 'QCD':6}]
 
82
 
 
83
        # number of expected born diagrams
 
84
        # 1 QCD diagram and 3 EW ones
 
85
        nborndiag_list = [1, 4, 4, 4, 4, 4]
 
86
 
 
87
        # number of expected real emission processes
 
88
        # for QED perturbations also the gluon emissions have to be generated, 
 
89
        # as their alpha x alpha_s^2 contribution has to be included
 
90
        nrealproc_list = [3, 6, 6, 6, 6, 6]
 
91
 
 
92
        # number of expected real emission diagrams
 
93
        # u u~ > d d~ g has 5 with QED^2=0, 17 with QED^2=4
 
94
        # u u~ > d d~ a has 4 with QED^2=2, 17 with QED^2=6
 
95
        #
 
96
        # for e.g. 'u u~ > d d~ QED^2=0 QCD^2=2 [real=QED]'
 
97
        # the real emissions are ordered as follows:
 
98
        #   u u~ > d d~ a [ QED ] QED^2=4 QCD^2=8
 
99
        #   a u~ > d d~ u~ [ QED ] QED^2=4 QCD^2=8
 
100
        #   u u~ > d d~ g [ QED ] QED^2=4 QCD^2=8
 
101
        #   g u~ > d d~ u~ [ QED ] QED^2=4 QCD^2=8
 
102
        #   u a > d d~ u [ QED ] QED^2=4 QCD^2=8
 
103
        #   u g > d u d~ [ QED ] QED^2=4 QCD^2=8
 
104
        nrealdiags_list = [[5, 5, 5],
 
105
                           [4, 4, 17, 17, 4, 17],
 
106
                           [4, 4, 17, 17, 4, 17],
 
107
                           [17, 17, 17, 17, 17, 17],
 
108
                           [17, 17, 17, 17, 17, 17],
 
109
                           [17, 17, 17, 17, 17, 17]]
 
110
 
 
111
        for cmd, born_orders, squared_orders, pert_couplings, nborndiag, nrealproc, nrealdiags, split in \
 
112
                zip(cmd_list, born_orders_list, squared_orders_list, pert_couplings_list, nborndiag_list, 
 
113
                        nrealproc_list, nrealdiags_list, split_type_list):
 
114
            self.interface.do_generate(cmd)
 
115
 
 
116
            fksprocess = self.interface._fks_multi_proc['born_processes'][0]
 
117
 
 
118
            # check that the extra_cnt_amp_list is empty
 
119
            self.assertEqual(0, len(fksprocess.extra_cnt_amp_list))
 
120
 
 
121
            self.assertEqual(born_orders, fksprocess.born_amp['process']['born_sq_orders'])
 
122
            self.assertEqual(squared_orders, fksprocess.born_amp['process']['squared_orders'])
 
123
            self.assertEqual(sorted(pert_couplings), sorted(fksprocess.born_amp['process']['perturbation_couplings']))
 
124
 
 
125
            self.assertEqual(len(fksprocess.born_amp['diagrams']), nborndiag)
 
126
            self.assertEqual(len(fksprocess.real_amps), nrealproc)
 
127
            for amp, n in zip(fksprocess.real_amps, nrealdiags):
 
128
                # check that the fks_j_from i have also been set 
 
129
                self.assertNotEqual(amp.fks_j_from_i, {})
 
130
                self.assertEqual(n, len(amp.amplitude['diagrams']))
 
131
                # and that no extra counterterm is needed
 
132
                for info in amp.fks_infos:
 
133
                    self.assertEqual(info['extra_cnt_index'], -1)
 
134
                    self.assertEqual(len(info['underlying_born']), 1)
 
135
                    self.assertEqual(len(info['splitting_type']), 1)
 
136
 
 
137
 
 
138
    def test_generate_fks_ew_noorders(self):
 
139
        """check that the generate command works as expected when no (or just some)
 
140
        orders are set.
 
141
        """
 
142
        cmd_list = [
 
143
            'u u~ > d d~ QED^2=0 QCD^2=4 [real=QED]',
 
144
            'u u~ > d d~ QCD^2=4 [real=QED]',
 
145
            'u u~ > d d~ [real=QED]',
 
146
            \
 
147
            'u u~ > d d~ QED^2=0 QCD^2=4 [real=QED QCD]',
 
148
            'u u~ > d d~ QCD^2=4 [real=QED QCD]',
 
149
            'u u~ > d d~ [real=QED QCD]',
 
150
            \
 
151
            'u u~ > d d~ QED^2=0 QCD^2=4 [real=QCD]',
 
152
            'u u~ > d d~ QCD^2=4 [real=QCD]',
 
153
            'u u~ > d d~ [real=QCD]']
 
154
 
 
155
        # expected born_orders
 
156
        born_orders_list = 9*[{'QED':0, 'QCD':4}]
 
157
 
 
158
        # perturbation couplings (always set to [QED, QCD]
 
159
        pert_couplings_list = 9*[['QCD','QED']]
 
160
 
 
161
        # expected squared_orders (should take into
 
162
        #  account the perturbation
 
163
        squared_orders_list = 3*[{'QED':2, 'QCD':4}] + \
 
164
                              3*[{'QED':2, 'QCD':6}] + \
 
165
                              3*[{'QED':0, 'QCD':6}]
 
166
 
 
167
        # number of expected born diagrams
 
168
        # 1 QCD diagram and 3 EW ones
 
169
        nborndiag_list = [4, 4, 4, 4, 4, 4, 1, 1, 1]
 
170
 
 
171
        # number of expected real emission processes
 
172
        # for QED perturbations also the gluon emissions have to be generated, 
 
173
        # as their alpha x alpha_s^2 contribution has to be included
 
174
        nrealproc_list = [6, 6, 6, 6, 6, 6, 3, 3, 3]
 
175
 
 
176
        # number of expected real emission diagrams
 
177
        # u u~ > d d~ g has 5 with QED^2=0, 17 with QED^2=4
 
178
        # u u~ > d d~ a has 4 with QED^2=2, 17 with QED^2=6
 
179
        #
 
180
        # for e.g. 'u u~ > d d~ QED^2=0 QCD^2=4 [real=QED]'
 
181
        # the real emissions are ordered as follows:
 
182
        #   u u~ > d d~ a [ QED ] QED^2=4 QCD^2=8
 
183
        #   a u~ > d d~ u~ [ QED ] QED^2=4 QCD^2=8
 
184
        #   u u~ > d d~ g [ QED ] QED^2=4 QCD^2=8
 
185
        #   g u~ > d d~ u~ [ QED ] QED^2=4 QCD^2=8
 
186
        #   u a > d d~ u [ QED ] QED^2=4 QCD^2=8
 
187
        #   u g > d u d~ [ QED ] QED^2=4 QCD^2=8
 
188
        nrealdiags_list = 3*[[4, 4, 17, 17, 4, 17]] + \
 
189
                          3*[[4, 4, 17, 17, 4, 17]] + \
 
190
                          3*[[5, 5, 5]]
 
191
 
 
192
        for cmd, born_orders, squared_orders, pert_couplings, nborndiag, nrealproc, nrealdiags in \
 
193
                zip(cmd_list, born_orders_list, squared_orders_list, pert_couplings_list, nborndiag_list, 
 
194
                        nrealproc_list, nrealdiags_list):
 
195
            self.interface.do_generate(cmd)
 
196
 
 
197
            fksprocess = self.interface._fks_multi_proc['born_processes'][0]
 
198
 
 
199
            # no orders should be specified, only squared orders
 
200
            self.assertEqual(fksprocess.born_amp['process']['orders'], {})
 
201
 
 
202
            # check that the extra_cnt_amp_list is empty
 
203
            self.assertEqual(0, len(fksprocess.extra_cnt_amp_list))
 
204
 
 
205
            self.assertEqual(born_orders, fksprocess.born_amp['process']['born_sq_orders'])
 
206
            self.assertEqual(squared_orders, fksprocess.born_amp['process']['squared_orders'])
 
207
            self.assertEqual(sorted(pert_couplings), sorted(fksprocess.born_amp['process']['perturbation_couplings']))
 
208
 
 
209
            self.assertEqual(len(fksprocess.born_amp['diagrams']), nborndiag)
 
210
            self.assertEqual(len(fksprocess.real_amps), nrealproc)
 
211
            for amp, n in zip(fksprocess.real_amps, nrealdiags):
 
212
                # check that the fks_j_from i have also been set 
 
213
                self.assertNotEqual(amp.fks_j_from_i, {})
 
214
                self.assertEqual(n, len(amp.amplitude['diagrams']))
 
215
                # and that no extra counterterm is needed
 
216
                for info in amp.fks_infos:
 
217
                    self.assertEqual(info['extra_cnt_index'], -1)
 
218
                    self.assertEqual(len(info['underlying_born']), 1)
 
219
                    self.assertEqual(len(info['splitting_type']), 1)
 
220
 
 
221
 
 
222
 
 
223
    def test_generate_fks_ew_extra_cnts_ttx_full(self):
 
224
        """check that the generate command works as expected.
 
225
        for processes which feature g/a > qqbar splitting.
 
226
        Check if the extra countertersm are found when needed"""
 
227
 
 
228
        self.interface.do_set('include_lepton_initiated_processes True')
 
229
        self.interface.do_define('p p a')
 
230
        self.interface.do_generate('p p > t t~ QED^2=4 QCD^2=4 [real=QCD QED]')
 
231
        quarks = [-1,-2,-3,-4,1,2,3,4]
 
232
 
 
233
        #there should be 12 processes: 4 qqbar + 4qbarq + gg + ga + ag + aa  
 
234
        self.assertEqual(len(self.interface._fks_multi_proc['born_processes']),12 )
 
235
        for proc in self.interface._fks_multi_proc['born_processes']:
 
236
            init_id = [l['id'] for l in proc.born_amp['process']['legs'] if not l['state']]
 
237
            # gg initial state, 2 extra cnts
 
238
            if init_id == [21, 21]:
 
239
                self.assertEqual(len(proc.extra_cnt_amp_list), 2)
 
240
                # 18 real emission MEs
 
241
                self.assertEqual(len(proc.real_amps), 18)
 
242
                # 22 real FKS configurations
 
243
                self.assertEqual(len(sum([real.fks_infos for real in proc.real_amps], [])), 22)
 
244
                for real in proc.real_amps:
 
245
                    init_real_id = real.pdgs[:2]
 
246
                    if any([idd in quarks for idd in init_real_id]):
 
247
                        self.assertNotEqual(real.fks_infos[0]['extra_cnt_index'], -1)
 
248
                    else:
 
249
                        self.assertEqual(real.fks_infos[0]['extra_cnt_index'], -1)
 
250
            # ag initial state, 1 extra cnt
 
251
            elif init_id == [21, 22] or init_id == [22, 21]:
 
252
                self.assertEqual(len(proc.extra_cnt_amp_list), 1)
 
253
                # 14 real emission MEs (add mu/e leptons, photon splitting into quarks
 
254
                # must not be incuded here)
 
255
                self.assertEqual(len(proc.real_amps), 14)
 
256
                # 17 real FKS configurations
 
257
                self.assertEqual(len(sum([real.fks_infos for real in proc.real_amps], [])), 17)
 
258
                for real in proc.real_amps:
 
259
                    init_real_id = real.pdgs[:2]
 
260
                    # the gluon has to split in order to need for an extra cnt
 
261
                    if any([idd in quarks for idd in init_real_id]) and 22 in init_real_id:
 
262
                        self.assertNotEqual(real.fks_infos[0]['extra_cnt_index'], -1)
 
263
                    else:
 
264
                        self.assertEqual(real.fks_infos[0]['extra_cnt_index'], -1)
 
265
            # all others no cnts
 
266
            # aa 
 
267
            elif init_id == [22, 22]:
 
268
                self.assertEqual(len(proc.extra_cnt_amp_list), 0)
 
269
                # 14 real emission MEs (add mu/e leptons, photon splitting into quarks
 
270
                # must not be incuded here)
 
271
                self.assertEqual(len(proc.real_amps), 10)
 
272
                for real in proc.real_amps:
 
273
                    self.assertEqual(real.fks_infos[0]['extra_cnt_index'], -1)
 
274
            # qq
 
275
            else:
 
276
                self.assertEqual(len(proc.extra_cnt_amp_list), 0)
 
277
                for real in proc.real_amps:
 
278
                    self.assertEqual(real.fks_infos[0]['extra_cnt_index'], -1)
 
279
        # avoid border effects
 
280
        self.interface.do_set('include_lepton_initiated_processes False')
 
281
 
 
282
 
 
283
    def test_generate_fks_ew_extra_cnts_ttx_qed2qcd1(self):
 
284
        """check that the generate command works as expected.
 
285
        for processes which feature g/a > qqbar splitting.
 
286
        Check if the extra countertersm are found when needed.
 
287
        In this case the extra counterterms/splittings should not be 
 
288
        included in the gg since it is only needed for counterterms"""
 
289
 
 
290
        self.interface.do_set('include_lepton_initiated_processes True')
 
291
        self.interface.do_define('p p a')
 
292
        self.interface.do_generate('p p > t t~ QED^2=4 QCD^2=2 [real=QCD QED]')
 
293
        quarks = [-1,-2,-3,-4,1,2,3,4]
 
294
 
 
295
        #there should be 12 processes: 4 qqbar + 4qbarq + gg + ga + ag + aa  
 
296
        self.assertEqual(len(self.interface._fks_multi_proc['born_processes']),12 )
 
297
        for proc in self.interface._fks_multi_proc['born_processes']:
 
298
            init_id = [l['id'] for l in proc.born_amp['process']['legs'] if not l['state']]
 
299
            # gg initial state, no extra cnts
 
300
            if init_id == [21, 21]:
 
301
                self.assertEqual(len(proc.extra_cnt_amp_list), 0)
 
302
                # 1 real emission MEs (only extra photon radiation
 
303
                self.assertEqual(len(proc.real_amps), 1)
 
304
                # 2 real FKS configurations
 
305
                self.assertEqual(len(sum([real.fks_infos for real in proc.real_amps], [])), 2)
 
306
                for real in proc.real_amps:
 
307
                    self.assertEqual(real.fks_infos[0]['extra_cnt_index'], -1)
 
308
            # ag initial state, 1 extra cnt
 
309
            elif init_id == [21, 22] or init_id == [22, 21]:
 
310
                self.assertEqual(len(proc.extra_cnt_amp_list), 1)
 
311
                # 22 real emission MEs (add mu/e leptons, photon splitting into quarks
 
312
                # MUST be incuded here)
 
313
                self.assertEqual(len(proc.real_amps), 22)
 
314
                # 25 real FKS configurations
 
315
                self.assertEqual(len(sum([real.fks_infos for real in proc.real_amps], [])), 25)
 
316
                for real in proc.real_amps:
 
317
                    init_real_id = real.pdgs[:2]
 
318
                    # the gluon has to split in order to need for an extra cnt
 
319
                    if any([idd in quarks for idd in init_real_id]) and 22 in init_real_id:
 
320
                        self.assertNotEqual(real.fks_infos[0]['extra_cnt_index'], -1)
 
321
                    else:
 
322
                        self.assertEqual(real.fks_infos[0]['extra_cnt_index'], -1)
 
323
            # all others no cnts
 
324
            # aa 
 
325
            elif init_id == [22, 22]:
 
326
                self.assertEqual(len(proc.extra_cnt_amp_list), 0)
 
327
                # 14 real emission MEs (add mu/e leptons, photon splitting into quarks
 
328
                # must not be incuded here)
 
329
                self.assertEqual(len(proc.real_amps), 10)
 
330
                for real in proc.real_amps:
 
331
                    self.assertEqual(real.fks_infos[0]['extra_cnt_index'], -1)
 
332
            # qq
 
333
            else:
 
334
                self.assertEqual(len(proc.extra_cnt_amp_list), 0)
 
335
                for real in proc.real_amps:
 
336
                    self.assertEqual(real.fks_infos[0]['extra_cnt_index'], -1)
 
337
        # avoid border effects
 
338
        self.interface.do_set('include_lepton_initiated_processes False')
 
339
 
 
340
 
 
341
# other tests for the extra cnts for dijet
 
342
# integrate one LO contribution with one kind of correction
 
343
    def test_generate_fks_ew_dijet_qed0qcd2_qcd(self):
 
344
        """check that the generate command works as expected.
 
345
        for processes which feature g/a > qqbar splitting.
 
346
        Check if the extra countertersm are found when needed.
 
347
        Here we will use a simplified dijet case, u u~ > g/a g/a
 
348
        considering the NLO QCD corrections to the leftmost blob.
 
349
        No extra cnts should be there"""
 
350
 
 
351
        self.interface.do_set('include_lepton_initiated_processes False')
 
352
        self.interface.do_define('jj = g a')
 
353
        self.interface.do_generate('u u~ > jj jj QED^2=0 QCD^2=4 [real=QCD]')
 
354
        quarks = [-1,-2,-3,-4,1,2,3,4]
 
355
        # just one born processes u u~ > g g
 
356
        self.assertEqual(len(self.interface._fks_multi_proc['born_processes']), 1)
 
357
        for proc in self.interface._fks_multi_proc['born_processes']:
 
358
            final_id = [l['id'] for l in proc.born_amp['process']['legs'] if l['state']]
 
359
            self.assertEqual(final_id, [21, 21])
 
360
 
 
361
            # there should never be extra cnts
 
362
            self.assertEqual(len(proc.extra_cnt_amp_list), 0) #( 21, 22)
 
363
            # make sure there are qqbar splittings in the fs
 
364
            foundqq = False
 
365
            for real in proc.real_amps:
 
366
                final_real_id = real.pdgs[2:]
 
367
                # the gluon has to split in order to need for an extra cnt
 
368
                if any([idd in quarks for idd in final_real_id]) and real.fks_infos[0]['ij'] > 2:
 
369
                    foundqq = True
 
370
                self.assertEqual(real.fks_infos[0]['extra_cnt_index'], -1)
 
371
            self.assertTrue(foundqq)
 
372
 
 
373
 
 
374
    def test_generate_fks_ew_dijet_qed2qcd0_qed(self):
 
375
        """check that the generate command works as expected.
 
376
        for processes which feature g/a > qqbar splitting.
 
377
        Check if the extra countertersm are found when needed.
 
378
        Here we will use a simplified dijet case, u u~ > g/a g/a
 
379
        considering the NLO QED corrections to the rightmost blob.
 
380
        No extra cnts should be there"""
 
381
 
 
382
        self.interface.do_set('include_lepton_initiated_processes False')
 
383
        self.interface.do_define('jj = g a')
 
384
        self.interface.do_generate('u u~ > jj jj QED^2=4 QCD^2=0 [real=QED]')
 
385
        quarks = [-1,-2,-3,-4,1,2,3,4]
 
386
        # just one born processes u u~ > a a 
 
387
        self.assertEqual(len(self.interface._fks_multi_proc['born_processes']), 1)
 
388
        for proc in self.interface._fks_multi_proc['born_processes']:
 
389
            final_id = [l['id'] for l in proc.born_amp['process']['legs'] if l['state']]
 
390
            self.assertEqual(final_id, [22, 22])
 
391
 
 
392
            # there should never be extra cnts
 
393
            self.assertEqual(len(proc.extra_cnt_amp_list), 0) 
 
394
            # make sure there are qqbar splittings in the fs
 
395
            foundqq = False
 
396
            for real in proc.real_amps:
 
397
                final_real_id = real.pdgs[2:]
 
398
                # the gluon has to split in order to need for an extra cnt
 
399
                if any([idd in quarks for idd in final_real_id]) and real.fks_infos[0]['ij'] > 2:
 
400
                    foundqq = True
 
401
                self.assertEqual(real.fks_infos[0]['extra_cnt_index'], -1)
 
402
            self.assertTrue(foundqq)
 
403
 
 
404
 
 
405
    def test_generate_fks_ew_dijet_qed0qcd2_qed(self):
 
406
        """check that the generate command works as expected.
 
407
        for processes which feature g/a > qqbar splitting.
 
408
        Check if the extra countertersm are found when needed.
 
409
        Here we will use a simplified dijet case, u u~ > g/a g/a
 
410
        considering the NLO QED corrections to the leftmost blob,
 
411
        or, equivalently, QCD corrections to the central blob
 
412
        No extra cnts should be there"""
 
413
 
 
414
        self.interface.do_set('include_lepton_initiated_processes False')
 
415
        self.interface.do_define('jj = g a')
 
416
        quarks = [-1,-2,-3,-4,1,2,3,4]
 
417
 
 
418
        for orders in ['QED^2=0 QCD^2=4 [real=QED]', 'QED^2=2 QCD^2=2 [real=QCD]']:
 
419
            self.interface.do_generate('u u~ > jj jj %s' % orders) 
 
420
            # two born processes u u~ > g g and g a
 
421
            self.assertEqual(len(self.interface._fks_multi_proc['born_processes']), 2)
 
422
            target_ids = [[21,21], [22,21]]
 
423
            for ids, proc in zip(target_ids, self.interface._fks_multi_proc['born_processes']):
 
424
                final_id = [l['id'] for l in proc.born_amp['process']['legs'] if l['state']]
 
425
                self.assertEqual(ids, final_id)
 
426
 
 
427
                # there should never be extra cnts
 
428
                if final_id == [21, 21]:
 
429
                    # there should never be extra cnts
 
430
                    self.assertEqual(len(proc.extra_cnt_amp_list), 0) 
 
431
                    # make sure there are qqbar splittings in the fs
 
432
                    foundqq = False
 
433
                    for real in proc.real_amps:
 
434
                        final_real_id = real.pdgs[2:]
 
435
                        # the gluon has to split
 
436
                        if any([idd in quarks for idd in final_real_id]) and real.fks_infos[0]['ij'] > 2:
 
437
                            foundqq = True
 
438
                        self.assertEqual(real.fks_infos[0]['extra_cnt_index'], -1)
 
439
                    self.assertTrue(foundqq)
 
440
 
 
441
                elif final_id == [22, 21]:
 
442
                    self.assertEqual(len(proc.extra_cnt_amp_list), 0)
 
443
                    # make sure there are qqbar splittings in the fs
 
444
                    foundqq = False
 
445
                    for real in proc.real_amps:
 
446
                        # check that real emissions with qqbar splitting has only one fks info
 
447
                        if len(real.fks_infos) > 1:
 
448
                            self.assertTrue(not any([real.pdgs[ii['i']-1] in quarks for ii in real.fks_infos]))
 
449
                        final_real_id = real.pdgs[2:]
 
450
                        # the gluon has to split
 
451
                        if any([idd in quarks for idd in final_real_id]) and real.fks_infos[0]['ij'] == 4:
 
452
                            foundqq=True
 
453
                        self.assertEqual(real.fks_infos[0]['extra_cnt_index'], -1)
 
454
                        # make sure no qqbar splitting comes from the photon. 
 
455
                        if real.fks_infos[0]['ij'] == 3:
 
456
                            self.assertTrue(not real.pdgs[real.fks_infos[0]['i']-1] in quarks)
 
457
                            self.assertTrue(not real.pdgs[real.fks_infos[0]['j']-1] in quarks)
 
458
                    self.assertTrue(foundqq)
 
459
 
 
460
 
 
461
    def test_generate_fks_ew_dijet_qed1qcd1_qed(self):
 
462
        """check that the generate command works as expected.
 
463
        for processes which feature g/a > qqbar splitting.
 
464
        Check if the extra countertersm are found when needed.
 
465
        Here we will use a simplified dijet case, u u~ > g/a g/a
 
466
        considering the NLO QED corrections to the central blob,
 
467
        or, equivalently, QCD corrections to the rightmost blob
 
468
        No extra cnts should be there"""
 
469
 
 
470
        self.interface.do_set('include_lepton_initiated_processes False')
 
471
        self.interface.do_define('jj = g a')
 
472
        quarks = [-1,-2,-3,-4,1,2,3,4]
 
473
 
 
474
        for orders in ['QED^2=2 QCD^2=2 [real=QED]', 'QED^2=4 QCD^2=0 [real=QCD]']:
 
475
            self.interface.do_generate('u u~ > jj jj %s' % orders) 
 
476
            # two born processes u u~ > g a and a a
 
477
            self.assertEqual(len(self.interface._fks_multi_proc['born_processes']), 2)
 
478
            target_ids = [[22,21], [22,22]]
 
479
            for ids, proc in zip(target_ids, self.interface._fks_multi_proc['born_processes']):
 
480
                final_id = [l['id'] for l in proc.born_amp['process']['legs'] if l['state']]
 
481
                self.assertEqual(ids, final_id)
 
482
 
 
483
                # there should never be extra cnts
 
484
                if final_id == [22, 21]:
 
485
                    # there should never be extra cnts
 
486
                    self.assertEqual(len(proc.extra_cnt_amp_list), 0) 
 
487
                    # make sure there are qqbar splittings in the fs
 
488
                    foundqq = False
 
489
                    for real in proc.real_amps:
 
490
                        final_real_id = real.pdgs[2:]
 
491
                        # the gluon has to split
 
492
                        if any([idd in quarks for idd in final_real_id]) and real.fks_infos[0]['ij'] > 2:
 
493
                            foundqq = True
 
494
                        self.assertEqual(real.fks_infos[0]['extra_cnt_index'], -1)
 
495
                    self.assertTrue(foundqq)
 
496
 
 
497
                elif final_id == [22, 22]:
 
498
                    self.assertEqual(len(proc.extra_cnt_amp_list), 0)
 
499
                    # make sure there are qqbar splittings in the fs
 
500
                    foundqq = False
 
501
                    for real in proc.real_amps:
 
502
                        # check that real emissions with qqbar splitting has only one fks info
 
503
                        if len(real.fks_infos) > 1:
 
504
                            self.assertTrue(not any([real.pdgs[ii['i']-1] in quarks for ii in real.fks_infos]))
 
505
                        self.assertEqual(real.fks_infos[0]['extra_cnt_index'], -1)
 
506
                        # make sure no qqbar splitting comes from the photon. 
 
507
                        if real.fks_infos[0]['ij'] > 2:
 
508
                            self.assertTrue(not real.pdgs[real.fks_infos[0]['i']-1] in quarks)
 
509
                            self.assertTrue(not real.pdgs[real.fks_infos[0]['j']-1] in quarks)
 
510
 
 
511
 
 
512
# integrate one LO contribution with both corrections
 
513
    def test_generate_fks_ew_dijet_qed0qcd2_qedqcd(self):
 
514
        """check that the generate command works as expected.
 
515
        for processes which feature g/a > qqbar splitting.
 
516
        Check if the extra countertersm are found when needed.
 
517
        Here we will use a simplified dijet case, u u~ > g/a g/a
 
518
        considering the NLO QED and QCD corrections to the leftmost blob
 
519
        No extra cnts should be there"""
 
520
 
 
521
        self.interface.do_set('include_lepton_initiated_processes False')
 
522
        self.interface.do_define('jj = g a')
 
523
        quarks = [-1,-2,-3,-4,1,2,3,4]
 
524
 
 
525
        self.interface.do_generate('u u~ > jj jj QED^2=0 QCD^2=4 [real=QED QCD]') 
 
526
        # two born processes u u~ > g g and g a
 
527
        self.assertEqual(len(self.interface._fks_multi_proc['born_processes']), 2)
 
528
        target_ids = [[21,21], [22,21]]
 
529
        for ids, proc in zip(target_ids, self.interface._fks_multi_proc['born_processes']):
 
530
            final_id = [l['id'] for l in proc.born_amp['process']['legs'] if l['state']]
 
531
            self.assertEqual(ids, final_id)
 
532
 
 
533
            # there should never be extra cnts
 
534
            if final_id == [21, 21]:
 
535
                # there should never be extra cnts
 
536
                self.assertEqual(len(proc.extra_cnt_amp_list), 0) 
 
537
                # make sure there are qqbar splittings in the fs
 
538
                foundqq = False
 
539
                for real in proc.real_amps:
 
540
                    final_real_id = real.pdgs[2:]
 
541
                    # the gluon has to split
 
542
                    if any([idd in quarks for idd in final_real_id]) and real.fks_infos[0]['ij'] > 2:
 
543
                        foundqq = True
 
544
                    self.assertEqual(real.fks_infos[0]['extra_cnt_index'], -1)
 
545
                self.assertTrue(foundqq)
 
546
 
 
547
            elif final_id == [22, 21]:
 
548
                self.assertEqual(len(proc.extra_cnt_amp_list), 0)
 
549
                # make sure there are qqbar splittings in the fs
 
550
                foundqq = False
 
551
                for real in proc.real_amps:
 
552
                    # check that real emissions with qqbar splitting has only one fks info
 
553
                    if len(real.fks_infos) > 1:
 
554
                        self.assertTrue(not any([real.pdgs[ii['i']-1] in quarks for ii in real.fks_infos]))
 
555
                    final_real_id = real.pdgs[2:]
 
556
                    # the gluon has to split
 
557
                    if any([idd in quarks for idd in final_real_id]) and real.fks_infos[0]['ij'] == 4:
 
558
                        foundqq=True
 
559
                    self.assertEqual(real.fks_infos[0]['extra_cnt_index'], -1)
 
560
                    # make sure no qqbar splitting comes from the photon. 
 
561
                    if real.fks_infos[0]['ij'] == 3:
 
562
                        self.assertTrue(not real.pdgs[real.fks_infos[0]['i']-1] in quarks)
 
563
                        self.assertTrue(not real.pdgs[real.fks_infos[0]['j']-1] in quarks)
 
564
                self.assertTrue(foundqq)
 
565
 
 
566
 
 
567
    def test_generate_fks_ew_dijet_qed1qcd1_qedqcd(self):
 
568
        """check that the generate command works as expected.
 
569
        for processes which feature g/a > qqbar splitting.
 
570
        Check if the extra countertersm are found when needed.
 
571
        Here we will use a simplified dijet case, u u~ > g/a g/a
 
572
        considering the NLO QED and QCD corrections to the central blob
 
573
        No extra cnts should be there"""
 
574
 
 
575
        self.interface.do_set('include_lepton_initiated_processes False')
 
576
        self.interface.do_define('jj = g a')
 
577
        quarks = [-1,-2,-3,-4,1,2,3,4]
 
578
 
 
579
        self.interface.do_generate('u u~ > jj jj QED^2=2 QCD^2=2 [real=QED QCD]') 
 
580
        # all three born processes u u~ > g g, g a and a a
 
581
        self.assertEqual(len(self.interface._fks_multi_proc['born_processes']), 3)
 
582
        target_ids = [[21,21], [22,21], [22,22]]
 
583
        for ids, proc in zip(target_ids, self.interface._fks_multi_proc['born_processes']):
 
584
            final_id = [l['id'] for l in proc.born_amp['process']['legs'] if l['state']]
 
585
            self.assertEqual(ids, final_id)
 
586
 
 
587
            # there should never be extra cnts
 
588
            # for g g and a a no qqbar splitting should be there
 
589
            if final_id in [[21, 21], [22, 22]]:
 
590
                # there should never be extra cnts
 
591
                self.assertEqual(len(proc.extra_cnt_amp_list), 0) 
 
592
                # make sure there are no qqbar splittings in the fs
 
593
                foundqq = False
 
594
                for real in proc.real_amps:
 
595
                    final_real_id = real.pdgs[2:]
 
596
                    # the gluon has to split
 
597
                    if any([idd in quarks for idd in final_real_id]) and real.fks_infos[0]['ij'] > 2:
 
598
                        foundqq = True
 
599
                    self.assertEqual(real.fks_infos[0]['extra_cnt_index'], -1)
 
600
                self.assertTrue(not foundqq)
 
601
 
 
602
            elif final_id == [22, 21]:
 
603
                self.assertEqual(len(proc.extra_cnt_amp_list), 0)
 
604
                # make sure there are qqbar splittings in the fs
 
605
                foundqqg = False
 
606
                foundqqa = False
 
607
                for real in proc.real_amps:
 
608
                    # check that real emissions with qqbar splitting has only one fks info
 
609
                    if len(real.fks_infos) > 1:
 
610
                        self.assertTrue(not any([real.pdgs[ii['i']-1] in quarks for ii in real.fks_infos]))
 
611
                    final_real_id = real.pdgs[2:]
 
612
                    # the gluon has to split
 
613
                    if any([idd in quarks for idd in final_real_id]) and real.fks_infos[0]['ij'] == 3:
 
614
                        foundqqa=True
 
615
                    if any([idd in quarks for idd in final_real_id]) and real.fks_infos[0]['ij'] == 4:
 
616
                        foundqqg=True
 
617
                    self.assertEqual(real.fks_infos[0]['extra_cnt_index'], -1)
 
618
                # make sure qqbar splittings come from both the photon and the gluon
 
619
                self.assertTrue(foundqqg)
 
620
                self.assertTrue(foundqqa)
 
621
 
 
622
 
 
623
    def test_generate_fks_ew_dijet_qed2qcd0_qedqcd(self):
 
624
        """check that the generate command works as expected.
 
625
        for processes which feature g/a > qqbar splitting.
 
626
        Check if the extra countertersm are found when needed.
 
627
        Here we will use a simplified dijet case, u u~ > g/a g/a
 
628
        considering the NLO QED and QCD corrections to the rightmost blob,
 
629
        No extra cnts should be there"""
 
630
 
 
631
        self.interface.do_set('include_lepton_initiated_processes False')
 
632
        self.interface.do_define('jj = g a')
 
633
        quarks = [-1,-2,-3,-4,1,2,3,4]
 
634
 
 
635
        self.interface.do_generate('u u~ > jj jj QED^2=4 QCD^2=0 [real=QCD QED]') 
 
636
        # two born processes u u~ > g a and a a
 
637
        self.assertEqual(len(self.interface._fks_multi_proc['born_processes']), 2)
 
638
        target_ids = [[22,21], [22,22]]
 
639
        for ids, proc in zip(target_ids, self.interface._fks_multi_proc['born_processes']):
 
640
            final_id = [l['id'] for l in proc.born_amp['process']['legs'] if l['state']]
 
641
            self.assertEqual(ids, final_id)
 
642
 
 
643
            # there should never be extra cnts
 
644
            if final_id == [22, 21]:
 
645
                # there should never be extra cnts
 
646
                self.assertEqual(len(proc.extra_cnt_amp_list), 0) 
 
647
                # make sure there are qqbar splittings in the fs
 
648
                foundqq = False
 
649
                for real in proc.real_amps:
 
650
                    final_real_id = real.pdgs[2:]
 
651
                    # the gluon has to split
 
652
                    if any([idd in quarks for idd in final_real_id]) and real.fks_infos[0]['ij'] > 2:
 
653
                        foundqq = True
 
654
                    self.assertEqual(real.fks_infos[0]['extra_cnt_index'], -1)
 
655
                    # make sure no qqbar splitting comes from the gluon. 
 
656
                    if real.fks_infos[0]['ij'] == 4:
 
657
                        self.assertTrue(not real.pdgs[real.fks_infos[0]['i']-1] in quarks)
 
658
                        self.assertTrue(not real.pdgs[real.fks_infos[0]['j']-1] in quarks)
 
659
                self.assertTrue(foundqq)
 
660
 
 
661
            elif final_id == [22, 22]:
 
662
                self.assertEqual(len(proc.extra_cnt_amp_list), 0)
 
663
                # make sure there are qqbar splittings in the fs
 
664
                foundqq = False
 
665
                for real in proc.real_amps:
 
666
                    # check that real emissions with qqbar splitting has only one fks info
 
667
                    if len(real.fks_infos) > 1:
 
668
                        self.assertTrue(not any([real.pdgs[ii['i']-1] in quarks for ii in real.fks_infos]))
 
669
                    self.assertEqual(real.fks_infos[0]['extra_cnt_index'], -1)
 
670
 
 
671
 
 
672
# integrate two LO contributions together with one kind of correction 
 
673
    def test_generate_fks_ew_dijet_qed1qcd2_qcd(self):
 
674
        """check that the generate command works as expected.
 
675
        for processes which feature g/a > qqbar splitting.
 
676
        Check if the extra countertersm are found when needed.
 
677
        Here we will use a simplified dijet case, u u~ > g/a g/a
 
678
        considering the NLO QCD corrections to the leftmost and central blobs
 
679
        No extra cnts should be there"""
 
680
 
 
681
        self.interface.do_set('include_lepton_initiated_processes False')
 
682
        self.interface.do_define('jj = g a')
 
683
        quarks = [-1,-2,-3,-4,1,2,3,4]
 
684
 
 
685
        self.interface.do_generate('u u~ > jj jj QED^2=2 QCD^2=4 [real=QCD]') 
 
686
        # two born processes u u~ > g g and g a
 
687
        self.assertEqual(len(self.interface._fks_multi_proc['born_processes']), 2)
 
688
        target_ids = [[21,21], [22,21]]
 
689
        for ids, proc in zip(target_ids, self.interface._fks_multi_proc['born_processes']):
 
690
            final_id = [l['id'] for l in proc.born_amp['process']['legs'] if l['state']]
 
691
            self.assertEqual(ids, final_id)
 
692
 
 
693
            # there should never be extra cnts
 
694
            if final_id == [21, 21]:
 
695
                # there should never be extra cnts
 
696
                self.assertEqual(len(proc.extra_cnt_amp_list), 0) 
 
697
                # make sure there are qqbar splittings in the fs
 
698
                foundqq = False
 
699
                for real in proc.real_amps:
 
700
                    final_real_id = real.pdgs[2:]
 
701
                    # the gluon has to split
 
702
                    if any([idd in quarks for idd in final_real_id]) and real.fks_infos[0]['ij'] > 2:
 
703
                        foundqq = True
 
704
                    self.assertEqual(real.fks_infos[0]['extra_cnt_index'], -1)
 
705
                self.assertTrue(foundqq)
 
706
 
 
707
            elif final_id == [22, 21]:
 
708
                self.assertEqual(len(proc.extra_cnt_amp_list), 0)
 
709
                # make sure there are qqbar splittings in the fs
 
710
                foundqq = False
 
711
                for real in proc.real_amps:
 
712
                    # check that real emissions with qqbar splitting has only one fks info
 
713
                    if len(real.fks_infos) > 1:
 
714
                        self.assertTrue(not any([real.pdgs[ii['i']-1] in quarks for ii in real.fks_infos]))
 
715
                    final_real_id = real.pdgs[2:]
 
716
                    # the gluon has to split
 
717
                    if any([idd in quarks for idd in final_real_id]) and real.fks_infos[0]['ij'] == 4:
 
718
                        foundqq=True
 
719
                    self.assertEqual(real.fks_infos[0]['extra_cnt_index'], -1)
 
720
                    # make sure no qqbar splitting comes from the photon. 
 
721
                    if real.fks_infos[0]['ij'] == 3:
 
722
                        self.assertTrue(not real.pdgs[real.fks_infos[0]['i']-1] in quarks)
 
723
                        self.assertTrue(not real.pdgs[real.fks_infos[0]['j']-1] in quarks)
 
724
                self.assertTrue(foundqq)
 
725
 
 
726
 
 
727
    def test_generate_fks_ew_dijet_qed1qcd2_qed(self):
 
728
        """check that the generate command works as expected.
 
729
        for processes which feature g/a > qqbar splitting.
 
730
        Check if the extra countertersm are found when needed.
 
731
        Here we will use a simplified dijet case, u u~ > g/a g/a
 
732
        considering the NLO QED corrections to the leftmost and central blobs
 
733
        or, equivalently, QCD corrections to the rightmost and central blob
 
734
        No extra cnts should be there"""
 
735
 
 
736
        self.interface.do_set('include_lepton_initiated_processes False')
 
737
        self.interface.do_define('jj = g a')
 
738
        quarks = [-1,-2,-3,-4,1,2,3,4]
 
739
 
 
740
        for orders in ['QED^2=2 QCD^2=4 [real=QED]', 'QED^2=4 QCD^2=2 [real=QCD]']:
 
741
            self.interface.do_generate('u u~ > jj jj %s' % orders) 
 
742
            # all three born processes u u~ > g g , g a , aa
 
743
            self.assertEqual(len(self.interface._fks_multi_proc['born_processes']), 3)
 
744
            target_ids = [[21,21], [22,21], [22,22]]
 
745
            for ids, proc in zip(target_ids, self.interface._fks_multi_proc['born_processes']):
 
746
                final_id = [l['id'] for l in proc.born_amp['process']['legs'] if l['state']]
 
747
                self.assertEqual(ids, final_id)
 
748
 
 
749
                # there should never be extra cnts
 
750
                if final_id == [21, 21]:
 
751
                    # there should never be extra cnts
 
752
                    self.assertEqual(len(proc.extra_cnt_amp_list), 0) 
 
753
                    # make sure there  are no qqbar splittings in the fs
 
754
                    foundqq = False
 
755
                    for real in proc.real_amps:
 
756
                        final_real_id = real.pdgs[2:]
 
757
                        # there should not be any g > qq splitting here (it should be inside g a)
 
758
                        if any([idd in quarks for idd in final_real_id]) and real.fks_infos[0]['ij'] > 2:
 
759
                            foundqq = True
 
760
                        self.assertEqual(real.fks_infos[0]['extra_cnt_index'], -1)
 
761
                    self.assertTrue(not foundqq)
 
762
 
 
763
                elif final_id == [22, 21]:
 
764
                    # there should never be extra cnts
 
765
                    self.assertEqual(len(proc.extra_cnt_amp_list), 0)
 
766
                    # make sure there are qqbar splittings in the fs
 
767
                    foundqq = False
 
768
                    for real in proc.real_amps:
 
769
                        # check that real emissions with qqbar splitting has only one fks info
 
770
                        if len(real.fks_infos) > 1:
 
771
                            self.assertTrue(not any([real.pdgs[ii['i']-1] in quarks for ii in real.fks_infos]))
 
772
                        final_real_id = real.pdgs[2:]
 
773
                        # both the gluon and photon have to split
 
774
                        if any([idd in quarks for idd in final_real_id]) and real.fks_infos[0]['ij'] == 3:
 
775
                            foundqqa=True
 
776
                        if any([idd in quarks for idd in final_real_id]) and real.fks_infos[0]['ij'] == 4:
 
777
                            foundqqg=True
 
778
                        self.assertEqual(real.fks_infos[0]['extra_cnt_index'], -1)
 
779
                    self.assertTrue(foundqqa)
 
780
                    self.assertTrue(foundqqg)
 
781
 
 
782
                elif final_id == [22, 22]:
 
783
                    # there should never be extra cnts
 
784
                    self.assertEqual(len(proc.extra_cnt_amp_list), 0)
 
785
                    foundqq = False
 
786
                    for real in proc.real_amps:
 
787
                        final_real_id = real.pdgs[2:]
 
788
                        # there should not be any g > qq splitting here (it should be inside g a)
 
789
                        if any([idd in quarks for idd in final_real_id]) and real.fks_infos[0]['ij'] > 2:
 
790
                            foundqq = True
 
791
                        self.assertEqual(real.fks_infos[0]['extra_cnt_index'], -1)
 
792
                    self.assertTrue(not foundqq)
 
793
 
 
794
 
 
795
    def test_generate_fks_ew_dijet_qed2qcd1_qed(self):
 
796
        """check that the generate command works as expected.
 
797
        for processes which feature g/a > qqbar splitting.
 
798
        Check if the extra countertersm are found when needed.
 
799
        Here we will use a simplified dijet case, u u~ > g/a g/a
 
800
        considering the NLO QED corrections to the rightmost and central blobs,
 
801
        No extra cnts should be there"""
 
802
 
 
803
        self.interface.do_set('include_lepton_initiated_processes False')
 
804
        self.interface.do_define('jj = g a')
 
805
        quarks = [-1,-2,-3,-4,1,2,3,4]
 
806
 
 
807
        self.interface.do_generate('u u~ > jj jj QED^2=4 QCD^2=2 [real=QED]') 
 
808
        # two born processes u u~ > g a and a a
 
809
        self.assertEqual(len(self.interface._fks_multi_proc['born_processes']), 2)
 
810
        target_ids = [[22,21], [22,22]]
 
811
        for ids, proc in zip(target_ids, self.interface._fks_multi_proc['born_processes']):
 
812
            final_id = [l['id'] for l in proc.born_amp['process']['legs'] if l['state']]
 
813
            self.assertEqual(ids, final_id)
 
814
 
 
815
            # there should never be extra cnts
 
816
            if final_id == [22, 21]:
 
817
                # there should never be extra cnts
 
818
                self.assertEqual(len(proc.extra_cnt_amp_list), 0) 
 
819
                # make sure there are qqbar splittings in the fs
 
820
                foundqq = False
 
821
                for real in proc.real_amps:
 
822
                    final_real_id = real.pdgs[2:]
 
823
                    # the gluon has to split
 
824
                    if any([idd in quarks for idd in final_real_id]) and real.fks_infos[0]['ij'] > 2:
 
825
                        foundqq = True
 
826
                    self.assertEqual(real.fks_infos[0]['extra_cnt_index'], -1)
 
827
                    # make sure no qqbar splitting comes from the gluon. 
 
828
                    if real.fks_infos[0]['ij'] == 4:
 
829
                        self.assertTrue(not real.pdgs[real.fks_infos[0]['i']-1] in quarks)
 
830
                        self.assertTrue(not real.pdgs[real.fks_infos[0]['j']-1] in quarks)
 
831
                self.assertTrue(foundqq)
 
832
 
 
833
            elif final_id == [22, 22]:
 
834
                self.assertEqual(len(proc.extra_cnt_amp_list), 0)
 
835
                # make sure there are qqbar splittings in the fs
 
836
                foundqq = False
 
837
                for real in proc.real_amps:
 
838
                    # check that real emissions with qqbar splitting has only one fks info
 
839
                    if len(real.fks_infos) > 1:
 
840
                        self.assertTrue(not any([real.pdgs[ii['i']-1] in quarks for ii in real.fks_infos]))
 
841
                    self.assertEqual(real.fks_infos[0]['extra_cnt_index'], -1)
 
842
 
 
843
 
 
844
# integrate three LO contributions together with one kind of correction 
 
845
    def test_generate_fks_ew_dijet_qed2qcd2_qcd(self):
 
846
        """check that the generate command works as expected.
 
847
        for processes which feature g/a > qqbar splitting.
 
848
        Check if the extra countertersm are found when needed.
 
849
        Here we will use a simplified dijet case, u u~ > g/a g/a
 
850
        considering the NLO QCD corrections to the three blobs
 
851
        No extra cnts should be there"""
 
852
 
 
853
        self.interface.do_set('include_lepton_initiated_processes False')
 
854
        self.interface.do_define('jj = g a')
 
855
        quarks = [-1,-2,-3,-4,1,2,3,4]
 
856
 
 
857
        self.interface.do_generate('u u~ > jj jj QED^2=4 QCD^2=4 [real=QCD]') 
 
858
        self.assertEqual(len(self.interface._fks_multi_proc['born_processes']), 3)
 
859
        target_ids = [[21,21], [22,21], [22,22]]
 
860
        for ids, proc in zip(target_ids, self.interface._fks_multi_proc['born_processes']):
 
861
            final_id = [l['id'] for l in proc.born_amp['process']['legs'] if l['state']]
 
862
            self.assertEqual(ids, final_id)
 
863
 
 
864
            if final_id == [21, 21]:
 
865
                # gg state, should have extra_cnts with g a in the final state
 
866
                self.assertEqual(len(proc.extra_cnt_amp_list), 1) #( 21, 22)
 
867
                # make sure there are qqbar splittings in the fs
 
868
                foundqq = False
 
869
                for real in proc.real_amps:
 
870
                    final_real_id = real.pdgs[2:]
 
871
                    # the gluon has to split in order to need for an extra cnt
 
872
                    if any([idd in quarks for idd in final_real_id]) and real.fks_infos[0]['ij'] > 2:
 
873
                        foundqq = True
 
874
                        self.assertNotEqual(real.fks_infos[0]['extra_cnt_index'], -1)
 
875
                    else:
 
876
                        self.assertEqual(real.fks_infos[0]['extra_cnt_index'], -1)
 
877
                self.assertTrue(foundqq)
 
878
 
 
879
            elif final_id == [22, 21]:
 
880
                # ag state, should not have extra_cnts with a a in the final state 
 
881
                #(it should appear at order alpha^3, which is not inlcuded here
 
882
                self.assertEqual(len(proc.extra_cnt_amp_list), 0) #( 21, 22)
 
883
                # make sure there are qqbar splittings in the fs
 
884
                foundqq = False
 
885
                for real in proc.real_amps:
 
886
                    # check that real emissions with qqbar splitting has only one fks info
 
887
                    if len(real.fks_infos) > 1:
 
888
                        self.assertTrue(not any([real.pdgs[ii['i']-1] in quarks for ii in real.fks_infos]))
 
889
                    final_real_id = real.pdgs[2:]
 
890
                    # the gluon has to split in order to need for an extra cnt
 
891
                    if any([idd in quarks for idd in final_real_id]) and real.fks_infos[0]['ij'] == 4:
 
892
                        foundqq=True
 
893
                    self.assertEqual(real.fks_infos[0]['extra_cnt_index'], -1)
 
894
                    # make sure no qqbar splitting comes from the photon. 
 
895
                    if real.fks_infos[0]['ij'] == 3:
 
896
                        self.assertTrue(not real.pdgs[real.fks_infos[0]['i']-1] in quarks)
 
897
                        self.assertTrue(not real.pdgs[real.fks_infos[0]['j']-1] in quarks)
 
898
                self.assertTrue(foundqq)
 
899
 
 
900
            elif final_id == [22, 22]:
 
901
                # aa state, should have no extra_cnts
 
902
                self.assertEqual(len(proc.extra_cnt_amp_list), 0) #( 22, 22)
 
903
                for real in proc.real_amps:
 
904
                    # check that real emissions with qqbar splitting has only one fks info
 
905
                    if len(real.fks_infos) > 1:
 
906
                        self.assertTrue(not any([real.pdgs[ii['i']-1] in quarks for ii in real.fks_infos]))
 
907
                    final_real_id = real.pdgs[2:]
 
908
                    self.assertEqual(real.fks_infos[0]['extra_cnt_index'], -1)
 
909
                    # make sure no qqbar splitting comes from final state photons. 
 
910
                    if real.fks_infos[0]['ij'] in [3, 4]:
 
911
                        self.assertTrue(not real.pdgs[real.fks_infos[0]['i']-1] in quarks)
 
912
                        self.assertTrue(not real.pdgs[real.fks_infos[0]['j']-1] in quarks)
 
913
 
 
914
 
 
915
    def test_generate_fks_ew_dijet_qed2qcd2_qed(self):
 
916
        """check that the generate command works as expected.
 
917
        for processes which feature g/a > qqbar splitting.
 
918
        Check if the extra countertersm are found when needed.
 
919
        Here we will use a simplified dijet case, u u~ > g/a g/a
 
920
        considering the NLO QCD corrections to the tree blobs
 
921
        No extra cnts should be there"""
 
922
 
 
923
        self.interface.do_set('include_lepton_initiated_processes False')
 
924
        self.interface.do_define('jj = g a')
 
925
        quarks = [-1,-2,-3,-4,1,2,3,4]
 
926
 
 
927
        self.interface.do_generate('u u~ > jj jj QED^2=4 QCD^2=4 [real=QED]') 
 
928
        self.assertEqual(len(self.interface._fks_multi_proc['born_processes']), 3)
 
929
        target_ids = [[21,21], [22,21], [22,22]]
 
930
        for ids, proc in zip(target_ids, self.interface._fks_multi_proc['born_processes']):
 
931
            final_id = [l['id'] for l in proc.born_amp['process']['legs'] if l['state']]
 
932
            self.assertEqual(ids, final_id)
 
933
 
 
934
            if final_id == [22, 22]:
 
935
                # aa state, should have no extra_cnts (it goes into g a)
 
936
                self.assertEqual(len(proc.extra_cnt_amp_list), 0) #( 21, 22)
 
937
                # make sure there are no qqbar splittings in the fs
 
938
                foundqq = False
 
939
                for real in proc.real_amps:
 
940
                    final_real_id = real.pdgs[2:]
 
941
                    # the gluon has to split in order to need for an extra cnt
 
942
                    if any([idd in quarks for idd in final_real_id]) and real.fks_infos[0]['ij'] > 2:
 
943
                        foundqq = True
 
944
                    self.assertEqual(real.fks_infos[0]['extra_cnt_index'], -1)
 
945
                self.assertTrue(not foundqq)
 
946
 
 
947
            elif final_id == [22, 21]:
 
948
                # ag state, should not have extra_cnts with a a in the final state 
 
949
                #(it should appear at order alpha^3, which is not inlcuded here
 
950
                self.assertEqual(len(proc.extra_cnt_amp_list), 1) #( 21, 22)
 
951
                # make sure there are qqbar splittings in the fs
 
952
                foundqqg = False
 
953
                foundqqa = False
 
954
                for real in proc.real_amps:
 
955
                    # check that real emissions with qqbar splitting has only one fks info
 
956
                    if len(real.fks_infos) > 1:
 
957
                        self.assertTrue(not any([real.pdgs[ii['i']-1] in quarks for ii in real.fks_infos]))
 
958
                    final_real_id = real.pdgs[2:]
 
959
                    # the gluon has to split in order to need for an extra cnt
 
960
                    if any([idd in quarks for idd in final_real_id]) and real.fks_infos[0]['ij'] == 4:
 
961
                        foundqqg=True
 
962
                        self.assertNotEqual(real.fks_infos[0]['extra_cnt_index'], -1)
 
963
                    # make sure no qqbar splitting comes from the photon. 
 
964
                    if real.fks_infos[0]['ij'] == 3:
 
965
                        self.assertEqual(real.fks_infos[0]['extra_cnt_index'], -1)
 
966
                        if any([idd in quarks for idd in final_real_id]):
 
967
                            foundqqa=True
 
968
                self.assertTrue(foundqqg)
 
969
                self.assertTrue(foundqqa)
 
970
 
 
971
            elif final_id == [21, 21]:
 
972
                # gg state, should have no extra_cnts
 
973
                self.assertEqual(len(proc.extra_cnt_amp_list), 0) 
 
974
                for real in proc.real_amps:
 
975
                    # check that real emissions with qqbar splitting has only one fks info
 
976
                    if len(real.fks_infos) > 1:
 
977
                        self.assertTrue(not any([real.pdgs[ii['i']-1] in quarks for ii in real.fks_infos]))
 
978
                    final_real_id = real.pdgs[2:]
 
979
                    self.assertEqual(real.fks_infos[0]['extra_cnt_index'], -1)
 
980
                    # make sure no qqbar splitting comes from final state photons. 
 
981
                    if real.fks_infos[0]['ij'] in [3, 4]:
 
982
                        self.assertTrue(not real.pdgs[real.fks_infos[0]['i']-1] in quarks)
 
983
                        self.assertTrue(not real.pdgs[real.fks_infos[0]['j']-1] in quarks)
 
984
 
 
985
 
 
986
# integrate all LO and NLO contributions together
 
987
    def test_generate_fks_ew_dijet_qed2qcd2_qedqcd(self):
 
988
        """check that the generate command works as expected.
 
989
        for processes which feature g/a > qqbar splitting.
 
990
        Check if the extra countertersm are found when needed.
 
991
        Here we will use a simplified dijet case, u u~ > g/a g/a
 
992
        with all born orders and all corrections"""
 
993
 
 
994
        self.interface.do_set('include_lepton_initiated_processes False')
 
995
        self.interface.do_define('jj = g a')
 
996
        quarks = [-1,-2,-3,-4,1,2,3,4]
 
997
 
 
998
        self.interface.do_generate('u u~ > jj jj QED^2=4 QCD^2=4 [real=QCD QED]')
 
999
        # three born processes u u~ > g g ; a g ; a a
 
1000
        self.assertEqual(len(self.interface._fks_multi_proc['born_processes']), 3)
 
1001
        target_ids = [[21,21], [22,21], [22,22]]
 
1002
        for ids, proc in zip(target_ids, self.interface._fks_multi_proc['born_processes']):
 
1003
            final_id = [l['id'] for l in proc.born_amp['process']['legs'] if l['state']]
 
1004
            self.assertEqual(ids, final_id)
 
1005
 
 
1006
            if final_id == [21, 21]:
 
1007
                # gg state, should have extra_cnts with g a in the final state
 
1008
                self.assertEqual(len(proc.extra_cnt_amp_list), 1) #( 21, 22)
 
1009
                # make sure there are qqbar splittings in the fs
 
1010
                foundqq = False
 
1011
                for real in proc.real_amps:
 
1012
                    final_real_id = real.pdgs[2:]
 
1013
                    # the gluon has to split in order to need for an extra cnt
 
1014
                    if any([idd in quarks for idd in final_real_id]) and real.fks_infos[0]['ij'] > 2:
 
1015
                        foundqq = True
 
1016
                        self.assertNotEqual(real.fks_infos[0]['extra_cnt_index'], -1)
 
1017
                    else:
 
1018
                        self.assertEqual(real.fks_infos[0]['extra_cnt_index'], -1)
 
1019
                self.assertTrue(foundqq)
 
1020
 
 
1021
            elif final_id == [22, 21]:
 
1022
                # ag state, should have extra_cnts with a a in the final state
 
1023
                self.assertEqual(len(proc.extra_cnt_amp_list), 1) #( 21, 22)
 
1024
                # make sure there are qqbar splittings in the fs
 
1025
                foundqq = False
 
1026
                for real in proc.real_amps:
 
1027
                    # check that real emissions with qqbar splitting has only one fks info
 
1028
                    if len(real.fks_infos) > 1:
 
1029
                        self.assertTrue(not any([real.pdgs[ii['i']-1] in quarks for ii in real.fks_infos]))
 
1030
                    final_real_id = real.pdgs[2:]
 
1031
                    # the gluon has to split in order to need for an extra cnt
 
1032
                    if any([idd in quarks for idd in final_real_id]) and real.fks_infos[0]['ij'] == 4:
 
1033
                        self.assertNotEqual(real.fks_infos[0]['extra_cnt_index'], -1)
 
1034
                        foundqq=True
 
1035
                    else:
 
1036
                        self.assertEqual(real.fks_infos[0]['extra_cnt_index'], -1)
 
1037
                    # make sure no qqbar splitting comes from the photon. 
 
1038
                    if real.fks_infos[0]['ij'] == 3:
 
1039
                        self.assertTrue(not real.pdgs[real.fks_infos[0]['i']-1] in quarks)
 
1040
                        self.assertTrue(not real.pdgs[real.fks_infos[0]['j']-1] in quarks)
 
1041
                self.assertTrue(foundqq)
 
1042
 
 
1043
            elif final_id == [22, 22]:
 
1044
                # aa state, should have no extra_cnts
 
1045
                self.assertEqual(len(proc.extra_cnt_amp_list), 0) #( 22, 22)
 
1046
                for real in proc.real_amps:
 
1047
                    # check that real emissions with qqbar splitting has only one fks info
 
1048
                    if len(real.fks_infos) > 1:
 
1049
                        self.assertTrue(not any([real.pdgs[ii['i']-1] in quarks for ii in real.fks_infos]))
 
1050
                    final_real_id = real.pdgs[2:]
 
1051
                    self.assertEqual(real.fks_infos[0]['extra_cnt_index'], -1)
 
1052
                    # make sure no qqbar splitting comes from final state photons. 
 
1053
                    if real.fks_infos[0]['ij'] in [3, 4]:
 
1054
                        self.assertTrue(not real.pdgs[real.fks_infos[0]['i']-1] in quarks)
 
1055
                        self.assertTrue(not real.pdgs[real.fks_infos[0]['j']-1] in quarks)
 
1056
 
 
1057
    def test_generate_fks_2to1_no_finalstate_confs(self):
 
1058
        """check that in the case of a 2->1 process no final state 
 
1059
        FKS configurations are generated
 
1060
        """
 
1061
        self.interface.do_set('include_lepton_initiated_processes False')
 
1062
        self.interface.do_generate('u d~ > w+ [QED]')
 
1063
        self.assertEqual(len(self.interface._fks_multi_proc['born_processes']), 1)
 
1064
 
 
1065
        # there should be 4 configurations, all due to initial-state splitting
 
1066
        nconfs = 0
 
1067
        for real in self.interface._fks_multi_proc['born_processes'][0].real_amps:
 
1068
            for info in real.fks_infos:
 
1069
                self.assertTrue(info['j'] in [1,2])
 
1070
                nconfs+= 1
 
1071
        self.assertEqual(nconfs, 4)
 
1072
 
 
1073
 
 
1074
    def test_combine_equal_processes_qcd_qed(self):
 
1075
        """check that two processes with the same matrix-elements are equal
 
1076
        and check that the add_process function works as expected"""
 
1077
        newinterface = mgcmd.MasterCmd()
 
1078
        newinterface2 = mgcmd.MasterCmd()
 
1079
        # generate the processes
 
1080
        self.interface.do_generate('u u~ > t t~ QED^2=0 QCD^2=4 [real=QCD QED]')
 
1081
        newinterface.do_generate('c c~ > t t~ QED^2=0 QCD^2=4 [real=QCD QED]')
 
1082
        newinterface2.do_generate('d d~ > t t~ QED^2=0 QCD^2=4 [real=QCD QED]')
 
1083
 
 
1084
        fksproc1 = self.interface._fks_multi_proc
 
1085
        fksproc2 = newinterface._fks_multi_proc
 
1086
        fksproc3 = newinterface2._fks_multi_proc
 
1087
        fksme1 = fks_helas.FKSHelasMultiProcess(fksproc1)['matrix_elements'][0]
 
1088
        fksme2 = fks_helas.FKSHelasMultiProcess(fksproc2)['matrix_elements'][0]
 
1089
        fksme3 = fks_helas.FKSHelasMultiProcess(fksproc3)['matrix_elements'][0]
 
1090
 
 
1091
        self.assertNotEqual(fksme2,fksme3)
 
1092
        
 
1093
        # check the reals, they should be in the same order
 
1094
        for i1, r1, in enumerate(fksme1.real_processes): 
 
1095
            for i2, r2, in enumerate(fksme2.real_processes): 
 
1096
                if i1 == i2:
 
1097
                    self.assertEqual(r1,r2)
 
1098
                else:
 
1099
                    self.assertNotEqual(r1,r2)
 
1100
        self.assertEqual(fksme1, fksme2)
 
1101
 
 
1102
        fksme1.add_process(fksme2)
 
1103
 
 
1104
        self.assertEqual(len(fksme1.born_me['processes']), 2)
 
1105
        for real in fksme1.real_processes:
 
1106
            self.assertEqual(len(real.matrix_element['processes']), 2)
 
1107
 
 
1108
    def load_fksME(self, save_name, model_name, process_def, force=False):
 
1109
        """tries to recover the fksME from a pickle file, otherwise regenerate it."""
 
1110
 
 
1111
        if not force and os.path.isfile(pjoin(root_path,'input_files',save_name)):
 
1112
            return save_load_object.load_from_file(pjoin(root_path,'input_files',save_name))
 
1113
        else:
 
1114
            self.interface.do_import('model %s'%model_name)
 
1115
            print(( "Regenerating %s ..."%process_def))
 
1116
            self.interface.do_generate(process_def)
 
1117
            proc = copy.copy(self.interface._fks_multi_proc)
 
1118
            me = fks_helas.FKSHelasMultiProcess(proc)['matrix_elements'][0]
 
1119
            save_load_object.save_to_file(pjoin(root_path,'input_files',save_name),me)
 
1120
            return me
 
1121
 
 
1122
    def notest_special_dijet_equal_process_qcd_qed_virt_test(self):
 
1123
        fksme1 = self.load_fksME('aa_emep_dijet.pkl','loop_qcd_qed_sm-no_widths','a a > e- e+ QED^2=4 QCD^2=4 [QCD QED]')
 
1124
        fksme2 = self.load_fksME('aa_mummup_dijet.pkl','loop_qcd_qed_sm-no_widths','a a > mu- mu+ QED^2=4 QCD^2=4 [QCD QED]')
 
1125
        self.assertEqual(fksme1,fksme2)
 
1126
 
 
1127
    def test_combine_equal_processes_dijet_qcd_qed_virt(self):
 
1128
        """check that two processes with the same matrix-elements are equal
 
1129
        and check that the add_process function works as expected. 
 
1130
        This test also cehck that equality works for virtuals.
 
1131
        In particular b-initiate processes have same trees but different loops (w/top)"""
 
1132
        # generate the processes
 
1133
 
 
1134
        self.interface.do_import('model loop_qcd_qed_sm-no_widths')
 
1135
 
 
1136
        self.interface.do_generate('u u~ > g g QED^2=0 QCD^2=4 [QCD QED]')
 
1137
        fksproc1 = copy.copy(self.interface._fks_multi_proc)
 
1138
 
 
1139
        self.interface.do_generate('c c~ > g g QED^2=0 QCD^2=4 [QCD QED]')
 
1140
        fksproc2 = copy.copy(self.interface._fks_multi_proc)
 
1141
 
 
1142
        self.interface.do_generate('d d~ > g g QED^2=0 QCD^2=4 [QCD QED]')
 
1143
        fksproc3 = copy.copy(self.interface._fks_multi_proc)
 
1144
 
 
1145
        self.interface.do_generate('b b~ > g g QED^2=0 QCD^2=4 [QCD QED]')
 
1146
        fksproc4 = copy.copy(self.interface._fks_multi_proc)
 
1147
 
 
1148
        fksme1 = fks_helas.FKSHelasMultiProcess(fksproc1)['matrix_elements'][0]
 
1149
        fksme2 = fks_helas.FKSHelasMultiProcess(fksproc2)['matrix_elements'][0]
 
1150
        fksme3 = fks_helas.FKSHelasMultiProcess(fksproc3)['matrix_elements'][0]
 
1151
        fksme4 = fks_helas.FKSHelasMultiProcess(fksproc4)['matrix_elements'][0]
 
1152
 
 
1153
##        fksme1 = self.load_fksME('uux_gg_dijet.pkl','loop_qcd_qed_sm-no_widths','u u~ > g g QED^2=0 QCD^2=4 [QCD QED]')
 
1154
##        fksme2 = self.load_fksME('ccx_gg_dijet.pkl','loop_qcd_qed_sm-no_widths','c c~ > g g QED^2=0 QCD^2=4 [QCD QED]')
 
1155
##        fksme3 = self.load_fksME('ddx_gg_dijet.pkl','loop_qcd_qed_sm-no_widths','d d~ > g g QED^2=0 QCD^2=4 [QCD QED]')
 
1156
##        fksme4 = self.load_fksME('bbx_gg_dijet.pkl','loop_qcd_qed_sm-no_widths','b b~ > g g QED^2=0 QCD^2=4 [QCD QED]')
 
1157
        # check that the u and d initiated are not equal
 
1158
        self.assertNotEqual(fksme2,fksme3)
 
1159
 
 
1160
        # check that the b-initiated is different from all other processes
 
1161
        self.assertNotEqual(fksme1,fksme4)
 
1162
        self.assertNotEqual(fksme2,fksme4)
 
1163
        self.assertNotEqual(fksme3,fksme4)
 
1164
        
 
1165
        # check that the u and c initiated are equal
 
1166
        self.assertEqual(fksme1, fksme2)
 
1167
 
 
1168
        # this is to avoid effects on other tests
 
1169
        self.interface.do_import('model sm')
 
1170
 
 
1171
    def notest_combine_equal_processes_pp_hpwmbbx_virt(self):
 
1172
        """Makes sure the uux and ccx channel of the process can be merged."""
 
1173
 
 
1174
        if os.path.isfile(pjoin(root_path,'input_files','uux_hpwmbbx.pkl')) and\
 
1175
           os.path.isfile(pjoin(root_path,'input_files','ccx_hpwmbbx.pkl')) and\
 
1176
           os.path.isfile(pjoin(root_path,'input_files','ddx_hpwmbbx.pkl')):
 
1177
            uux_me = save_load_object.load_from_file(pjoin(root_path,'input_files','uux_hpwmbbx.pkl'))
 
1178
            ccx_me = save_load_object.load_from_file(pjoin(root_path,'input_files','ccx_hpwmbbx.pkl'))
 
1179
            ddx_me = save_load_object.load_from_file(pjoin(root_path,'input_files','ddx_hpwmbbx.pkl'))            
 
1180
        else:
 
1181
            self.interface.do_set('complex_mass_scheme True')
 
1182
            self.interface.do_import('model 2HDMCMStIIymbMSbar')
 
1183
            print ("Regenerating u u~ > h+ w- b b~ / h1 h2 h3 QED^2=2 YB=1 YT=1 QCD^2=2 [QCD] ...")
 
1184
            self.interface.do_generate('u u~ > h+ w- b b~ / h1 h2 h3 QED^2=2 YB=1 YT=1 QCD^2=2 [QCD]')
 
1185
            uux_proc = copy.copy(self.interface._fks_multi_proc)
 
1186
            uux_me = fks_helas.FKSHelasMultiProcess(uux_proc)['matrix_elements'][0]
 
1187
            save_load_object.save_to_file(pjoin(root_path,'input_files','uux_hpwmbbx.pkl'),uux_me)            
 
1188
            print ("Regenerating c c~ > h+ w- b b~ / h1 h2 h3 QED^2=2 YB=1 YT=1 QCD^2=2 [QCD] ...")
 
1189
            self.interface.do_generate('c c~ > h+ w- b b~ / h1 h2 h3 QED^2=2 YB=1 YT=1 QCD^2=2 [QCD]')
 
1190
            ccx_proc = copy.copy(self.interface._fks_multi_proc)
 
1191
            ccx_me = fks_helas.FKSHelasMultiProcess(ccx_proc)['matrix_elements'][0]
 
1192
            save_load_object.save_to_file(pjoin(root_path,'input_files','ccx_hpwmbbx.pkl'),ccx_me)
 
1193
            uux_me = save_load_object.load_from_file(pjoin(root_path,'input_files','uux_hpwmbbx.pkl'))
 
1194
            ccx_me = save_load_object.load_from_file(pjoin(root_path,'input_files','ccx_hpwmbbx.pkl'))
 
1195
            print ("Regenerating d d~ > h+ w- b b~ / h1 h2 h3 QED^2=2 YB=1 YT=1 QCD^2=2 [QCD] ...") 
 
1196
            self.interface.do_generate('d d~ > h+ w- b b~ / h1 h2 h3 QED^2=2 YB=1 YT=1 QCD^2=2 [QCD]')
 
1197
            ddx_proc = copy.copy(self.interface._fks_multi_proc)
 
1198
            ddx_me = fks_helas.FKSHelasMultiProcess(ddx_proc)['matrix_elements'][0]
 
1199
            save_load_object.save_to_file(pjoin(root_path,'input_files','ddx_hpwmbbx.pkl'),ddx_me)  
 
1200
 
 
1201
        self.assertEqual(uux_me,ccx_me)
 
1202
        self.assertEqual(uux_me,ddx_me)
 
1203
 
 
1204
    def test_combine_equal_processes_dy_qed_virt(self):
 
1205
        """check that two processes with the same matrix-elements are equal
 
1206
        and check that the add_process function works as expected. 
 
1207
        This test also cehck that equality works for virtuals.
 
1208
        In particular b-initiate processes have same trees but different loops (w/top)"""
 
1209
        # generate the processes
 
1210
 
 
1211
        self.interface.do_import('model loop_qcd_qed_sm-no_widths')
 
1212
 
 
1213
        self.interface.do_generate('u u~ > e+ e- QED^2=4 QCD^2=0 [QED]')
 
1214
        fksproc1 = copy.copy(self.interface._fks_multi_proc)
 
1215
 
 
1216
        self.interface.do_generate('c c~ > e+ e- QED^2=4 QCD^2=0 [QED]')
 
1217
        fksproc2 = copy.copy(self.interface._fks_multi_proc)
 
1218
 
 
1219
        self.interface.do_generate('d d~ > e+ e- QED^2=4 QCD^2=0 [QED]')
 
1220
        fksproc3 = copy.copy(self.interface._fks_multi_proc)
 
1221
 
 
1222
        self.interface.do_generate('b b~ > e+ e- QED^2=4 QCD^2=0 [QED]')
 
1223
        fksproc4 = copy.copy(self.interface._fks_multi_proc)
 
1224
 
 
1225
        self.interface.do_generate('s s~ > e+ e- QED^2=4 QCD^2=0 [QED]')
 
1226
        fksproc5 = copy.copy(self.interface._fks_multi_proc)
 
1227
 
 
1228
        fksme1 = fks_helas.FKSHelasMultiProcess(fksproc1)['matrix_elements'][0]
 
1229
        fksme2 = fks_helas.FKSHelasMultiProcess(fksproc2)['matrix_elements'][0]
 
1230
        fksme3 = fks_helas.FKSHelasMultiProcess(fksproc3)['matrix_elements'][0]
 
1231
        fksme4 = fks_helas.FKSHelasMultiProcess(fksproc4)['matrix_elements'][0]
 
1232
        fksme5 = fks_helas.FKSHelasMultiProcess(fksproc5)['matrix_elements'][0]
 
1233
 
 
1234
        # check that the u and d initiated are not equal
 
1235
        self.assertNotEqual(fksme2,fksme3)
 
1236
 
 
1237
        # check that the b-initiated is different from all other processes
 
1238
        self.assertNotEqual(fksme1,fksme4)
 
1239
        self.assertNotEqual(fksme2,fksme4)
 
1240
        self.assertNotEqual(fksme3,fksme4)
 
1241
        
 
1242
        # check that the u and c initiated are equal
 
1243
        self.assertEqual(fksme1, fksme2)
 
1244
 
 
1245
        # check that the d and s initiated are equal
 
1246
        self.assertEqual(fksme3, fksme5)
 
1247
 
 
1248
        # this is to avoid effects on other tests
 
1249
        self.interface.do_import('model sm')
 
1250
 
 
1251
 
 
1252
    def test_combine_equal_processes_qcd(self):
 
1253
        """check that two processes with the same matrix-elements are equal
 
1254
        and check that the add_process function works as expected"""
 
1255
        newinterface = mgcmd.MasterCmd()
 
1256
        newinterface2 = mgcmd.MasterCmd()
 
1257
        # generate the processes
 
1258
        self.interface.do_generate('u u~ > t t~ QED^2=0 QCD^2=4 [real=QCD]')
 
1259
        newinterface.do_generate('d d~ > t t~ QED^2=0 QCD^2=4 [real=QCD]')
 
1260
 
 
1261
        fksproc1 = self.interface._fks_multi_proc
 
1262
        fksproc2 = newinterface._fks_multi_proc
 
1263
        fksme1 = fks_helas.FKSHelasMultiProcess(fksproc1)['matrix_elements'][0]
 
1264
        fksme2 = fks_helas.FKSHelasMultiProcess(fksproc2)['matrix_elements'][0]
 
1265
        
 
1266
        # check the reals, they should be in the same order
 
1267
        for i1, r1, in enumerate(fksme1.real_processes): 
 
1268
            for i2, r2, in enumerate(fksme2.real_processes): 
 
1269
                if i1 == i2:
 
1270
                    self.assertEqual(r1,r2)
 
1271
                else:
 
1272
                    self.assertNotEqual(r1,r2)
 
1273
        self.assertEqual(fksme1, fksme2)
 
1274
 
 
1275
        fksme1.add_process(fksme2)
 
1276
 
 
1277
        self.assertEqual(len(fksme1.born_me['processes']), 2)
 
1278
        for real in fksme1.real_processes:
 
1279
            self.assertEqual(len(real.matrix_element['processes']), 2)
 
1280
 
 
1281
 
 
1282
    def test_include_lep_split(self):
 
1283
        """test that the include_lepton_initiated_processes options works as expected"""
 
1284
        interface = mgcmd.MasterCmd()
 
1285
        leptons=[11,13,15]
 
1286
        quarks=[1,2,3,4,5]
 
1287
        # default should be set to false
 
1288
        # initial state leptons
 
1289
        self.interface.do_generate('a a > w+ w- QED^2=4 QCD^2=0 [real=QED]')
 
1290
        fksproc = self.interface._fks_multi_proc['born_processes'][0]
 
1291
        reals=fksproc.reals
 
1292
        for real in reals[0]+reals[1]:
 
1293
            self.assertTrue(all([lep not in [abs(l['id']) for l in real['leglist']] for lep in leptons]))
 
1294
 
 
1295
        # chack that this does not affect final state photons
 
1296
        self.interface.do_generate('u u~ > g a QED^2=2 QCD^2=2 [real=QCD]')
 
1297
        fksproc = self.interface._fks_multi_proc['born_processes'][0]
 
1298
        reals=fksproc.reals
 
1299
        self.assertTrue(any([leptons[0] in [abs(l['id']) for l in real['leglist']] for real in reals[2]]))
 
1300
 
 
1301
        # now set it to true
 
1302
        self.interface.do_set('include_lepton_initiated_processes True')
 
1303
        # initial state leptons
 
1304
        self.interface.do_generate('a a > w+ w- QED^2=4 QCD^2=0 [real=QED]')
 
1305
        fksproc = self.interface._fks_multi_proc['born_processes'][0]
 
1306
        reals=fksproc.reals
 
1307
        self.assertTrue(any([leptons[0] in [abs(l['id']) for l in real['leglist']] for real in reals[0]]))
 
1308
        self.assertTrue(any([leptons[0] in [abs(l['id']) for l in real['leglist']] for real in reals[1]]))
 
1309
        # avoid border effects
 
1310
        self.interface.do_set('include_lepton_initiated_processes False')