From 35daeffd5e2480da10f63ec7bf8a1179028f9f32 Mon Sep 17 00:00:00 2001
From: "Ewelina.Maria.Lobodzinska" <ewelina.maria.lobodzinska@cern.ch>
Date: Tue, 25 Jan 2022 14:08:31 +0100
Subject: [PATCH] PowhegControl: add by hand the changes from !49858

---
 .../python/parameters/registry.py             |   1 +
 .../python/processes/powheg/__init__.py       |   3 +-
 .../python/processes/powheg/fourtops.py       | 194 ++++++++++++++++++
 .../python/processes/powheg/tt.py             |   2 +-
 .../python/processes/powheg/ttj_MiNNLO.py     |   2 +-
 .../control/PowhegControl_fourtops_Common.py  |   6 +
 .../mc.PhPy8EG_A14NNPDF23_fourtops_example.py |  51 +++++
 7 files changed, 256 insertions(+), 3 deletions(-)
 create mode 100644 Generators/PowhegControl/python/processes/powheg/fourtops.py
 create mode 100644 Generators/PowhegControl/share/control/PowhegControl_fourtops_Common.py
 create mode 100644 Generators/PowhegControl/share/example/processes/fourtops/mc.PhPy8EG_A14NNPDF23_fourtops_example.py

diff --git a/Generators/PowhegControl/python/parameters/registry.py b/Generators/PowhegControl/python/parameters/registry.py
index a4d5eff90bcf..df75a2a03415 100644
--- a/Generators/PowhegControl/python/parameters/registry.py
+++ b/Generators/PowhegControl/python/parameters/registry.py
@@ -108,6 +108,7 @@ class Registry(metaclass=Singleton):
         self.add_default("dec3", -1, hidden=True, description="Weakino decay 3. UNUSED")
         self.add_default("dec4", -1, hidden=True, description="Weakino decay 4. UNUSED")
         self.add_default("decaymode", 0, description="Dark matter decay mode")
+        self.add_default("decay_signature", "0", description="4tops decay signature")
         self.add_default("delg1_g", 0, description="Delta_g1(Gamma)")
         self.add_default("delg1_z", 0, description="Delta_g1(Z)")
         self.add_default("delk_g", 0, description="Delta_K(Gamma)")
diff --git a/Generators/PowhegControl/python/processes/powheg/__init__.py b/Generators/PowhegControl/python/processes/powheg/__init__.py
index b1e9074c79b1..ac281cf6480c 100644
--- a/Generators/PowhegControl/python/processes/powheg/__init__.py
+++ b/Generators/PowhegControl/python/processes/powheg/__init__.py
@@ -1,4 +1,4 @@
-# Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
+# Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration
 # flake8: noqa
 
 from .bb import bb
@@ -10,6 +10,7 @@ from .chi1chi1 import chi1chi1
 from .DMGG import DMGG
 from .DMS_tloop import DMS_tloop
 from .DMV import DMV
+from .fourtops import fourtops
 from .ggF_H import ggF_H
 from .ggF_HH import ggF_HH
 from .ggF_HZ import ggF_HZ
diff --git a/Generators/PowhegControl/python/processes/powheg/fourtops.py b/Generators/PowhegControl/python/processes/powheg/fourtops.py
new file mode 100644
index 000000000000..6482752df3d9
--- /dev/null
+++ b/Generators/PowhegControl/python/processes/powheg/fourtops.py
@@ -0,0 +1,194 @@
+# Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration
+
+from AthenaCommon import Logging
+from ...parameters import powheg_atlas_common
+from ..powheg_V2 import PowhegV2
+from ..external import ExternalMadSpin
+
+## Get handle to Athena logging
+logger = Logging.logging.getLogger("PowhegControl")
+
+
+# Dictionary to convert the PowhegControl decay mode names to the appropriate
+# decay mode numbers understood by Powheg
+_decay_mode_lookup = {
+    "t t~ t t~ > all [MadSpin]" : "00000", # switch off decays in Powheg and let MadSpin handle them!
+    "t t~ t t~ > all": "44444", # all decays
+    "t t~ t t~ > 4l": "44400", # exactly 4 leptons
+    "t t~ t t~ > 3l4l": "4", # at least 3 leptons
+    "t t~ t t~ > 2lSS": "3", # exactly 2 leptons, same sign
+    "t t~ t t~ > 2lOS": "2", # exactly 2 leptons, opposite sign
+    "t t~ t t~ > 1l": "1", # exactly 1 lepton
+    "t t~ t t~ > allhad": "00044", # fully-hadronic
+    "t t~ t t~ > undecayed": "00000" # undecayed (e.g. to produce a lhe file)
+                        }
+_signature_lookup = [ "4", "3", "2", "1" ] # these values are for the 4tops-specific #decay_signature keyword
+
+class fourtops(PowhegV2):
+    """! Default Powheg configuration for 4 tops production.
+
+    Create a configurable object with all applicable Powheg options.
+
+    @author James Robinson  <tpelzer@cern.ch>
+    """
+
+    def __init__(self, base_directory, **kwargs):
+        """! Constructor: all process options are set here.
+
+        @param base_directory: path to PowhegBox code.
+        @param kwargs          dictionary of arguments from Generate_tf.
+        """
+        super(fourtops, self).__init__(base_directory, "fourtops", **kwargs)
+
+        # Add algorithms to the sequence
+        self.add_algorithm(ExternalMadSpin(process="generate p p > t t~ t t~ [QCD]"))
+
+        # Add parameter validation functions
+        self.validation_functions.append("validate_decays")
+
+        # List of allowed decay modes
+        # (The sorting of the list is just to increase readability when it's printed)
+        self.allowed_decay_modes = sorted(_decay_mode_lookup.keys())
+
+        # Add all keywords for this process, overriding defaults if required
+        self.add_keyword("bmass_lhe")
+        self.add_keyword("bornktmin", 5.0)
+        self.add_keyword("bornonly")
+        self.add_keyword("bornsuppfact")
+        self.add_keyword("bornzerodamp")
+        self.add_keyword("bottomthr")
+        self.add_keyword("bottomthrpdf")
+        self.add_keyword("btildeborn")
+        self.add_keyword("btildecoll")
+        self.add_keyword("btildereal")
+        self.add_keyword("btildevirt")
+        self.add_keyword("btlscalect")
+        self.add_keyword("btlscalereal")
+        self.add_keyword("charmthr")
+        self.add_keyword("charmthrpdf")
+        self.add_keyword("check_bad_st2")
+        self.add_keyword("clobberlhe")
+        self.add_keyword("cmass_lhe")
+        self.add_keyword("colltest")
+        self.add_keyword("compress_lhe")
+        self.add_keyword("compress_upb")
+        self.add_keyword("compute_rwgt")
+        self.add_keyword("decay_signature", "0")
+        self.add_keyword("doublefsr")
+        self.add_keyword("evenmaxrat")
+        self.add_keyword("facscfact", self.default_scales[0])
+        self.add_keyword("fastbtlbound")
+        self.add_keyword("fixedgrid")
+        self.add_keyword("fixedscale")
+        self.add_keyword("flg_debug")
+        self.add_keyword("foldcsi")
+        self.add_keyword("foldphi")
+        self.add_keyword("foldy")
+        self.add_keyword("fullrwgt")
+        self.add_keyword("fullrwgtmode")
+        self.add_keyword("hdamp")
+        self.add_keyword("hfact")
+        self.add_keyword("icsimax")
+        self.add_keyword("ih1")
+        self.add_keyword("ih2")
+        self.add_keyword("itmx1")
+        self.add_keyword("itmx1rm")
+        self.add_keyword("itmx2", 8)
+        self.add_keyword("itmx2rm")
+        self.add_keyword("iupperfsr")
+        self.add_keyword("iupperisr")
+        self.add_keyword("iymax")
+        self.add_keyword("lhans1", self.default_PDFs)
+        self.add_keyword("lhans2", self.default_PDFs)
+        self.add_keyword("lhapdf6maxsets")
+        self.add_keyword("lhrwgt_descr")
+        self.add_keyword("lhrwgt_group_combine")
+        self.add_keyword("lhrwgt_group_name")
+        self.add_keyword("lhrwgt_id")
+        self.add_keyword("LOevents")
+        self.add_keyword("manyseeds")
+        self.add_keyword("max_io_bufsize")
+        self.add_keyword("maxseeds")
+        self.add_keyword("minlo")
+        self.add_keyword("mintupbratlim")
+        self.add_keyword("mintupbxless")
+        self.add_keyword("ncall1", 500)
+        self.add_keyword("ncall1rm")
+        self.add_keyword("ncall2", 50000)
+        self.add_keyword("ncall2rm")
+        self.add_keyword("ncallfrominput")
+        self.add_keyword("noevents")
+        self.add_keyword("novirtual")
+        self.add_keyword("nubound", 800000)
+        self.add_keyword("olddij")
+        self.add_keyword("par_2gsupp")
+        self.add_keyword("par_diexp")
+        self.add_keyword("par_dijexp")
+        self.add_keyword("parallelstage")
+        self.add_keyword("pdfreweight")
+        self.add_keyword("ptsqmin")
+        self.add_keyword("ptsupp")
+        self.add_keyword("tmass", powheg_atlas_common.mass.t, name="mass_t", description="top quark mass in GeV")
+        self.add_keyword("radregion")
+        self.add_keyword("rand1")
+        self.add_keyword("rand2")
+        self.add_keyword("renscfact", self.default_scales[1])
+        self.add_keyword("rwl_add")
+        self.add_keyword("rwl_file")
+        self.add_keyword("rwl_format_rwgt")
+        self.add_keyword("rwl_group_events")
+        self.add_keyword("skipextratests")
+        self.add_keyword("smartsig")
+        self.add_keyword("softtest")
+        self.add_keyword("stage2init")
+        self.add_keyword("storeinfo_rwgt")
+        self.add_keyword("storemintupb")
+        self.add_keyword("tdec/bmass")
+        self.add_keyword("tdec/cmass")
+        self.add_keyword("tdec/dmass")
+        self.add_keyword("tdec/elbranching")
+        self.add_keyword("tdec/emass")
+        self.add_keyword("tdec/mumass")
+        self.add_keyword("tdec/sin2cabibbo")
+        self.add_keyword("tdec/smass")
+        self.add_keyword("tdec/taumass")
+        self.add_keyword("tdec/twidth")
+        self.add_keyword("tdec/umass")
+        self.add_keyword("tdec/wmass")
+        self.add_keyword("tdec/wwidth")
+        self.add_keyword("testplots")
+        self.add_keyword("testsuda")
+        self.add_keyword("topdecaymode", "t t~ > all", name="decay_mode")
+        self.add_keyword("ubexcess_correct")
+        self.add_keyword("ubsigmadetails")
+        self.add_keyword("use-old-grid")
+        self.add_keyword("use-old-ubound")
+        self.add_keyword("withdamp")
+        self.add_keyword("withnegweights")
+        self.add_keyword("withsubtr")
+        self.add_keyword("xgriditeration")
+        self.add_keyword("xupbound", 10)
+
+    def validate_decays(self):
+        """
+        Validate semileptonic and topdecaymode keywords and translate them from ATLAS input to Powheg input
+        """
+        self.expose() # convenience call to simplify syntax
+        if self.decay_mode not in self.allowed_decay_modes:
+            error_message = "Decay mode '{given}' not recognised, valid choices are: '{choices}'!".format(given=self.decay_mode, choices="', '".join(self.allowed_decay_modes))
+            logger.warning(error_message)
+            raise ValueError(error_message)
+
+        # Check if MadSpin decays are requested.
+        # Accordingly, MadSpin will run or not run.
+        if "MadSpin" in self.decay_mode:
+            self.externals["MadSpin"].parameters_by_keyword("powheg_top_decays_enabled")[0].value = False
+            self.externals["MadSpin"].parameters_by_keyword("MadSpin_model")[0].value = "loop_sm-no_b_mass"
+            self.externals["MadSpin"].parameters_by_keyword("MadSpin_nFlavours")[0].value = 5
+
+        if _decay_mode_lookup[self.decay_mode] in _signature_lookup: # special handling of decays with #decay_signature keyword
+            self.parameters_by_keyword("decay_signature")[0].value = _decay_mode_lookup[self.decay_mode]
+            self.parameters_by_keyword("topdecaymode")[0].value = "00000"
+        else: # usual handling of decays with #topdecaymode keyword
+            self.parameters_by_keyword("decay_signature")[0].value = "0"
+            self.parameters_by_keyword("topdecaymode")[0].value = _decay_mode_lookup[self.decay_mode]
diff --git a/Generators/PowhegControl/python/processes/powheg/tt.py b/Generators/PowhegControl/python/processes/powheg/tt.py
index 1c7e6134313a..857e2652efa9 100644
--- a/Generators/PowhegControl/python/processes/powheg/tt.py
+++ b/Generators/PowhegControl/python/processes/powheg/tt.py
@@ -10,7 +10,7 @@ logger = Logging.logging.getLogger("PowhegControl")
 
 
 class tt(PowhegV2):
-    """! Default Powheg configuration for for top pair production.
+    """! Default Powheg configuration for top-pair production.
 
     Create a configurable object with all applicable Powheg options.
 
diff --git a/Generators/PowhegControl/python/processes/powheg/ttj_MiNNLO.py b/Generators/PowhegControl/python/processes/powheg/ttj_MiNNLO.py
index 6df09ab61dac..ecbd5b00b18c 100644
--- a/Generators/PowhegControl/python/processes/powheg/ttj_MiNNLO.py
+++ b/Generators/PowhegControl/python/processes/powheg/ttj_MiNNLO.py
@@ -45,7 +45,7 @@ class ttj_MiNNLO(PowhegV2):
         warnings = super(ttj_MiNNLO, self).hoppet_warning()
         infos = super(ttj_MiNNLO, self).hoppet_info()
         
-        super(ttj_MiNNLO, self).__init__(base_directory, "ttJ_MiNNLOPS_v1.0_beta1", powheg_executable="pwhg_main-gnu", warning_output=warnings, info_output=infos, error_output=errors, **kwargs)
+        super(ttj_MiNNLO, self).__init__(base_directory, "ttJ_MiNNLO", powheg_executable="pwhg_main-gnu", warning_output=warnings, info_output=infos, error_output=errors, **kwargs)
 
         # defining ttjMiNNLOPATH environment variable to bypass file path problems in fortran code
         # this is definitly a hack, see discussion in AGENE-2055
diff --git a/Generators/PowhegControl/share/control/PowhegControl_fourtops_Common.py b/Generators/PowhegControl/share/control/PowhegControl_fourtops_Common.py
new file mode 100644
index 000000000000..a4d97ccf40e6
--- /dev/null
+++ b/Generators/PowhegControl/share/control/PowhegControl_fourtops_Common.py
@@ -0,0 +1,6 @@
+import PowhegControl
+transform_runArgs = runArgs if "runArgs" in dir() else None
+transform_opts = opts if "opts" in dir() else None
+PowhegConfig = PowhegControl.PowhegControl(process_name="fourtops", run_args=transform_runArgs, run_opts=transform_opts)
+
+
diff --git a/Generators/PowhegControl/share/example/processes/fourtops/mc.PhPy8EG_A14NNPDF23_fourtops_example.py b/Generators/PowhegControl/share/example/processes/fourtops/mc.PhPy8EG_A14NNPDF23_fourtops_example.py
new file mode 100644
index 000000000000..198a7d502e70
--- /dev/null
+++ b/Generators/PowhegControl/share/example/processes/fourtops/mc.PhPy8EG_A14NNPDF23_fourtops_example.py
@@ -0,0 +1,51 @@
+# Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration
+
+#--------------------------------------------------------------
+# This is an example joboption to generate events with Powheg
+# using ATLAS' interface. Users should optimise and carefully
+# validate the settings before making an official sample request.
+#--------------------------------------------------------------
+
+#--------------------------------------------------------------
+# EVGEN configuration
+#--------------------------------------------------------------
+evgenConfig.description = "POWHEG+Pythia8 4 tops production with A14 NNPDF2.3 tune."
+evgenConfig.keywords = ["SM", "top"]
+evgenConfig.contact = ["tpelzer@cern.ch"]
+
+# --------------------------------------------------------------
+# Load ATLAS defaults for the Powheg 4 tops process
+# --------------------------------------------------------------
+include("PowhegControl/PowhegControl_fourtops_Common.py")
+
+# --------------------------------------------------------------
+# Settings
+# --------------------------------------------------------------
+# define the decay mode
+PowhegConfig.decay_mode = "t t~ t t~ > all" # inclusive is the default
+#PowhegConfig.decay_mode = "t t~ t t~ > 4l" # exactly 4 leptons
+#PowhegConfig.decay_mode = "t t~ t t~ > 3l4l" # at least 3 leptons
+#PowhegConfig.decay_mode = "t t~ t t~ > 2lSS" # exactly 2 leptons, same sign
+#PowhegConfig.decay_mode = "t t~ t t~ > 2lOS" # exactly 2 leptons, opposite sign
+#PowhegConfig.decay_mode = "t t~ t t~ > 1l" # exactly 1 lepton
+#PowhegConfig.decay_mode = "t t~ t t~ > allhad" # fully-hadronic
+#PowhegConfig.decay_mode = "t t~ > undecayed" # undecayed (e.g. to produce a lhe file)
+## for handling decays with MadSpin
+#PowhegConfig.decay_mode = "t t~ > all [MadSpin]"
+#PowhegConfig.MadSpin_decays= ["decay t > w+ b, w+ > all all", "decay t~ > w- b~, w- > all all"]
+#PowhegConfig.MadSpin_process= "generate p p > t t~ t t~ [QCD]" # this process is default - can be changed (for studies)
+
+# --------------------------------------------------------------
+# Generate events
+# --------------------------------------------------------------
+PowhegConfig.generate()
+
+#--------------------------------------------------------------
+# Pythia8 showering with the A14 NNPDF2.3 tune, main31 routine
+#--------------------------------------------------------------
+include("Pythia8_i/Pythia8_A14_NNPDF23LO_EvtGen_Common.py")
+include("Pythia8_i/Pythia8_Powheg_Main31.py")
+# Setting the appropriate number of final state particles for the main31 routine
+genSeq.Pythia8.Commands += [ 'Powheg:NFinal = 4' ]
+
+
-- 
GitLab