Page MenuHomeHEPForge

No OneTemporary

diff --git a/Cards/param_card_TemplateBasis.dat b/Cards/param_card_TemplateBasis.dat
index 1d44392..578bb7c 100644
--- a/Cards/param_card_TemplateBasis.dat
+++ b/Cards/param_card_TemplateBasis.dat
@@ -1,130 +1,130 @@
######################################################################
## PARAM_CARD AUTOMATICALY GENERATED BY MG5 FOLLOWING UFO MODEL ####
######################################################################
## ##
## Width set on Auto will be computed following the information ##
## present in the decay.py files of the model. ##
## See arXiv:1402.1178 for more details. ##
## ##
######################################################################
###################################
## INFORMATION FOR LOOP
###################################
Block loop
1 9.118800e+01 # MU_R
###################################
## INFORMATION FOR MASS
###################################
Block mass
5 4.700000e+00 # MB
6 1.730000e+02 # MT
- 15 1.730000e+02 # MTAU
+ 15 1.770000e+00 # MTAU
23 9.118800e+01 # MZ
25 1.250000e+02 # MH
## Dependent parameters, given by model restrictions.
## Those values should be edited following the
## analytical expression. MG5 ignores those values
## but they are important for interfacing the output of MG5
## to external program such as Pythia.
1 0.000000 # d : 0.0
2 0.000000 # u : 0.0
3 0.000000 # s : 0.0
4 0.000000 # c : 0.0
11 0.000000 # e- : 0.0
12 0.000000 # ve : 0.0
13 0.000000 # mu- : 0.0
14 0.000000 # vm : 0.0
# 15 0.000000 # ta- : 0.0
16 0.000000 # vt : 0.0
21 0.000000 # g : 0.0
22 0.000000 # a : 0.0
###################################
## INFORMATION FOR NEWCOUP
###################################
Block basis
0 Template
Block newcoup
0 0.1 # a
1 -0.2 # b
2 0.3 # c
###################################
## INFORMATION FOR SMINPUTS
###################################
Block sminputs
1 1.325070e+02 # aEWM1
###################################
## INFORMATION FOR YUKAWA
###################################
Block yukawa
5 4.700000e+00 # ymb
6 1.730000e+02 # ymt
15 1.777000e+00 # ymtau
###################################
## INFORMATION FOR DECAY
###################################
DECAY 6 1.491500e+00 # WT
DECAY 23 2.441404e+00 # WZ
DECAY 24 2.047600e+00 # WW
-DECAY 25 6.382339e-03 # WH
+DECAY 25 6.382339e-03 # WH
# BR NDA ID1 ID2
- 0.e+01 2 13 13 # BR(H -> mu mu)
- 0.e+01 2 21 21 # BR(H -> a a)
- 0.e+01 2 5 5 # BR(H -> b b)
- 0.e+01 2 4 4 # BR(H -> c c)
+ 0.e+01 2 13 13 # BR(H -> mu mu)
+ 0.e+01 2 21 21 # BR(H -> a a)
+ 0.e+01 2 5 5 # BR(H -> b b)
+ 0.e+01 2 4 4 # BR(H -> c c)
## Dependent parameters, given by model restrictions.
## Those values should be edited following the
## analytical expression. MG5 ignores those values
## but they are important for interfacing the output of MG5
## to external program such as Pythia.
DECAY 1 0.000000 # d : 0.0
DECAY 2 0.000000 # u : 0.0
DECAY 3 0.000000 # s : 0.0
DECAY 4 0.000000 # c : 0.0
DECAY 5 0.000000 # b : 0.0
DECAY 11 0.000000 # e- : 0.0
DECAY 12 0.000000 # ve : 0.0
DECAY 13 0.000000 # mu- : 0.0
DECAY 14 0.000000 # vm : 0.0
DECAY 15 0.000000 # ta- : 0.0
DECAY 16 0.000000 # vt : 0.0
DECAY 21 0.000000 # g : 0.0
DECAY 22 0.000000 # a : 0.0
DECAY 82 0.000000 # ghg : 0.0
DECAY 9000001 0.000000 # gha : 0.0
DECAY 9000002 2.495200 # ghz : WZ
DECAY 9000003 2.085000 # ghwp : WW
DECAY 9000004 2.085000 # ghwm : WW
#===========================================================
# QUANTUM NUMBERS OF NEW STATE(S) (NON SM PDG CODE)
#===========================================================
Block QNUMBERS 9000001 # gha
1 0 # 3 times electric charge
2 1 # number of spin states (2S+1)
3 1 # colour rep (1: singlet, 3: triplet, 8: octet)
4 1 # Particle/Antiparticle distinction (0=own anti)
Block QNUMBERS 9000002 # ghz
1 0 # 3 times electric charge
2 1 # number of spin states (2S+1)
3 1 # colour rep (1: singlet, 3: triplet, 8: octet)
4 1 # Particle/Antiparticle distinction (0=own anti)
Block QNUMBERS 9000003 # ghwp
1 3 # 3 times electric charge
2 1 # number of spin states (2S+1)
3 1 # colour rep (1: singlet, 3: triplet, 8: octet)
4 1 # Particle/Antiparticle distinction (0=own anti)
Block QNUMBERS 9000004 # ghwm
1 -3 # 3 times electric charge
2 1 # number of spin states (2S+1)
3 1 # colour rep (1: singlet, 3: triplet, 8: octet)
4 1 # Particle/Antiparticle distinction (0=own anti)
Block QNUMBERS 82 # ghg
1 0 # 3 times electric charge
2 1 # number of spin states (2S+1)
3 8 # colour rep (1: singlet, 3: triplet, 8: octet)
4 1 # Particle/Antiparticle distinction (0=own anti)
diff --git a/README b/README
index 44a16fc..76112b7 100644
--- a/README
+++ b/README
@@ -1,329 +1,409 @@
################################################################################
Rosetta: A Higgs Effective Field Theory basis translator
Benjamin Fuks, Fabio Maltoni, Kentarou Mawatari, Ken Mimasu, Veronica Sanz
Version 0, March 2015
################################################################################
Rosetta is a translation tool to aid in the Monte Carlo generation of events for
Higgs Effective Field Theory. The idea is to provide a simple way to map
different parametrisations of the deviations of Higgs couplings from SM
expectations to a single 'basis' of Wilson coefficients corresponding to
operators up to dimension 6.
Given an LHA style input parameter card in the users basis of choice, Rosetta
has the capability to read in the parameters, calculate any dependent
parameters, perform a number of consistency checks with respect to required and
derived inputs and finally write out a new parameter card in the target basis
which can be used as input to the associated UFO model in e.g.
MadGraph5_aMC@NLO.
The tool consists of a Python package containing implementations of
Higgs Effective Theory bases and a command line tool 'translate' that performs
the task of mapping a given basis to a target output basis. The core of the
package is based on the contents of the LHCHiggs Cross Section Working Group
(HXSWG) draft. The slides at
https://indico.cern.ch/event/375176/contribution/5/material/slides/0.pdf
provide a more detailed description of the tool as well as some examples of
usage and the code structure (see backup slides).
################################################################################
-Contact
+README Contents
+################################################################################
+1) Contact
+2) Prerequisites
+3) Usage
+4) Input cards
+5) Implementing your own basis
+6) eHDECAY interface
+
+################################################################################
+1) Contact
################################################################################
Feel free to contact the authors with requests for features, bugs
etc.through k.mimasu@sussex.ac.uk.
################################################################################
-Prerequisites
+2) Prerequisites
################################################################################
Python 2.7 or above
################################################################################
-Package Contents
+3) Package Contents
################################################################################
Rosetta/ # Python package containing implementation of the basis
# translation machinery.
__init__.py # Stores a dictionary of fermion PIDs and a few
# default values for SM input parameters and particle
# masses in case they are undefined by the user.
Basis.py # Base basis class implementing internal methods
# such as reading/writing param cards and checking
# for required/calculated inputs. All basis classes
# are derived from this one.
--> MassBasis.py # Basis class corresponding to the target basis
# for output parameter cards, corresponds to the
# redundant set of operators defined in
# HiggsBasis.py without imposing any dependency
# conditions. There are 169 coefficients.
--> HiggsBasis.py # Basis class corresponding to the Higgs Basis as
# defined in the HXSWG draft. Using this basis as
# input calculates the dependent coefficients.
# There are 95 independent coefficients and 74
# dependent coefficients.
--> WarsawBasis.py # Basis class corresponding to the Warsaw Basis
# defined arXiv:1008.4884. Using this basis
# input calculates the Mass Basis coefficients
# as per the formulae in the HXSWG draft. There are
# 95 independent coefficients.
--> TemplateBasis.py # Template for a user-defined Basis class
# implemented in the Rosetta package. Toy versions
# of the calculate_dependent() and translate()
# methods are implemented.
implemeted.py # A file defining a dictionary that logs the set of
# implemented bases for the translate tool.
+ eHDECAY.py # Interface with eHDECAY program (arXiv:1403.3381),
+ # discussed later.
+
query.py # Yes/no query function borrowed from
# http://code.activestate.com/recipes/577058/
Cards/ # Sample MG5-style parameter cards to be used as input.
param_card_HiggsBasis.dat # Sample HiggsBasis input parameter card
param_card_MassBasis.dat # Sample MassBasis parameter card, needn't
# be used as input
param_card_TemplateBasis.dat # Sample TemplateBasis input parameter card
param_card_WarsawBasis.dat # Sample WarsawBasis input parameter card
translate # Command line tool to perform basis translation based on the
# implementations in Rosetta.py
################################################################################
-Usage
+3) Usage
################################################################################
The translate command line tool takes an LHA-style param card (see sample
cards provided in Cards/ directory) in a particular basis and outputs a new
card in the specified basis (default is Mass Basis). So far, only the Mass
Basis can be takes as the target basis.
The options BLOCKIN and BLOCKOUT allow the user to specify the name of the LHA
block that contains the new couplings. The names of these couplings, specified
as the first non-whitespace characters following a hash ("#") character after
the numerical value of the parameter, should match those defined in the
'independent' list of the specified input basis.
Command line documentation:
>> ./translate --help
-
- usage: translate [-h] [-o OUTPUT] [-b BLOCKIN] [-B BLOCKOUT]
- [-t TARGETBASIS] [-w]
- PARAMCARD BASIS
-
- Read in an LHA format parameter card in a particular basis and write a new
- param card in the mass basis.
-
- positional arguments:
- PARAMCARD Input parameter card.
- BASIS Basis of coefficients in parameter card (one of:
- higgs, mass, template, warsaw).
-
- optional arguments:
- -h, --help show this help message and exit
- -o OUTPUT, --output OUTPUT
- Output file name. Default: [PARAMCARD]_new
- -b BLOCKIN, --blockin BLOCKIN
- New coupling block to be read in. Default: newcoup
- -B BLOCKOUT, --blockout BLOCKOUT
- New coupling block to be written out. Default:
- newcoup
- -t TARGETBASIS, --target TARGETBASIS
- Basis into which to translate (one of: higgs, mass,
- template, warsaw). Default: mass
- -w, --overwrite Overwrite any pre-existing output file.
+ >>
+ >> usage: translate [-h] [-o OUTPUT] [-b BLOCKIN] [-B BLOCKOUT]
+ >> [-t TARGETBASIS] [-w] [-e]
+ >> PARAMCARD BASIS
+ >>
+ >> Read in an LHA format parameter card in a particular basis and write a
+ >> new param card in the mass basis.
+ >>
+ >> positional arguments:
+ >> PARAMCARD Input parameter card.
+ >> BASIS Basis of coefficients in parameter card (one of:
+ >> higgs, mass, template, warsaw).
+ >>
+ >> optional arguments:
+ >> -h, --help show this help message and exit
+ >> -o OUTPUT, --output OUTPUT
+ >> Output file name. Default: [PARAMCARD]_new
+ >> -b BLOCKIN, --blockin BLOCKIN
+ >> New coupling block to be read in. Default:
+ >> newcoup
+ >> -B BLOCKOUT, --blockout BLOCKOUT
+ >> New coupling block to be written out. Default:
+ >> newcoup
+ >> -t TARGETBASIS, --target TARGETBASIS
+ >> Basis into which to translate (one of: higgs,
+ >> mass, template, warsaw). Default: mass
+ >> -w, --overwrite Overwrite any pre-existing output file.
+ >> -e, --ehdecay Interface with eHDECAY
################################################################################
-Input cards
+4) Input cards
################################################################################
Rosetta is designed to read input cards in a format similar to the SUSY Les
Houches Accord (SLHA) detailed in http://arxiv.org/abs/hep-ph/0311123. It
coincides with the input format read in by Madgraph5_aMC@NLO. Sample cards can
be found in the Cards/ directory.
The reader looks for block structures in a case insensitive way i.e.
>>BLOCK MYBLOCK
Specifically it will search for blocks MASS, SMINPUTS and BASIS. For the
Higgs Effective Theory couplings, it will also search for a block 'newcoup' or
any other string BLOCKIN specified by the '-b BLOCKIN' option of translate.
The main difference between the input format of Rosetta and SLHA is that names
of parameters are required as this is what the translator uses to identify them
in applying the translation formulae. This was deemed to be clearer than the
usual numerical ordering that would be more suitable for automatically
generated input cards. Therefore each parameter in blocks SMINPUTS and BLOCKIN
should be accompanied by a name following a '#' character (usually reserved for
comments describing the parameter).
>>BLOCK MYBLOCK
>> 0 3.14159E+00 # pi
>> 1 1.97327E-01 # hbarc_GeVfm
>> Block sminputs
>> 1 1.325070e+02 # aEWM1 (white space doesn't matter)
ETC.
The reader reads all lines until the next occurrence of 'BLOCK' or 'DECAY',
ignoring leading and trailing white space and all lines beginning with a '#' as
well as lines that do not match the expected pattern detailed above. For blocks
BLOCKIN and SMINPUTS, the reader stores a name:value pair in the ordered
dictionaries self.par_dict and self.input respectively. For block MASS, a
PID:mass pair is stored in self.mass
>> block mass
>> 5 4.700000e+00 # MB
>> 6 1.730000e+02 # MT
>> 15 1.730000e+02 # MTAU
>> 23 9.118800e+01 # MZ
>> 25 1.250000e+02 # MH
Block basis should have one element and is simply a label for the users input
basis, it is not essential but is used when writing out the new to remind the
user from which basis they translated.
>> block BASIS
>> 0 MyBasis # name of basis
If the reader can't find block basis, it will print a warning and ask to
continue with the default value which is the input basis class name.
+
################################################################################
-Implementing your own basis
+5) Implementing your own basis
################################################################################
Users who wish to implement their own basis should have a minimal understanding
of implementing formulae and assigning variables in python dictionaries. The
TemplateBasis.py class illustrates a toy implementation of a basis containing
the main ingredients necessary.
The base class Basis.py implements a number of reading and writing functions
designed to remain 'under the hood'.These include reading and writing parameter
cards, cross checking inputs read in against required inputs, storing the old
parameter card and writing out a new one with the coefficients of the target
basis. In general, the only variables needed in a derived class will be the
following useful data members:
self.independent # A list of coefficients required to be defined
# in the input parameter card.
self.dependent # A list of dependent coefficients to be assigned
# by the calculate_dependent() function. These
# should not be declared in the input parameter
# card.
self.required_inputs # A set of required input parameters in block
# SMINPUTS
self.required_masses # A set of required article masses in block MASS
self.par_dict # dictionary with keys defined by self.independent
# and self.dependent. The parameters in
# self.independent will be read in from the
# input parameter card while those in self.dependent
# should be calculated and assigned by the user in
# calculate_dependent().
self.input # dictionary with names and values of parameters
# defined in block SMINPUTS. Cross checked with
# self.required_inputs
self.mass # dictionary with PIDs and particle masses defined
# in block MASS. Cross checked with elements of
# self.required_masses
self.newpar # dictionary of coefficients to be filled in
# translate() function. The contents of this
# dictionary are written out to the output parameter
# card in place of the old basis coefficients of the
# input parameter card.
self.newmass # dictionary of parameters to be filled in
# translate() function
The basic steps are as follows:
1) Create a new file MyBasis.py declaring a class MyBasis inheriting from the
Basis class (these names need not coincide). The target basis class can
also be imported in order to initialise an empty container to fill in the
translate function.
>>from Basis import Basis # base class
>>from MassBasis import MassBasis # target basis
>>
>>class TemplateBasis(Basis):
2) Minimally, a list of strings called 'independent' should be declared
containing the names of the coefficients to be read in the input parameter
card and used to calculate the coefficients in the target basis.
- Additionally, a list named 'dependent' can also (optionally) be defined
+ Additionally, a list named 'dependent' can also optionally be defined
containing the names of coefficients to calculate internally before
translating to the target basis.
+ The set, 'transalte_to' can also be declared to list the existing bases to
+ which the implementation provides a translation. The default is {'mass'},
+ assuming that the translation is implemented to the mass basis.
For more consistency, the sets 'required_inputs' and 'required_masses'
can also be declared. These tell the basis class to check that the masses
of particles with certain PIDs and certain SM input parameters are defined
in the blocks MASS and SMINPUTS respectively. If default values exist for
these parameters in __init__.py, the user is asked if they wish to continue
using those when calling ./translate.
>>class MyBasis(Basis):
>> independent = ['a','b','c',...] # list of required parameters
>> dependent = ['d','e','f',...] # list of derived parameters
>> required_masses = {1,2,3,4,5,6,...} # PIDs of required particle masses
>> required_inputs = {'aEWM1','MZ',...} # required SMINPUT parameters
+ >> translate_to = {'mass','my_other_basis'} # available translations
3) At least the function translate() should be defined that applies the map
from the input coefficients to those in the output basis. This can be done
by creating and instance of the target basis class and filling its par_dict
data member. The function should ultimately assign the dictionary to
self.newpar. self.newname can also be assigned.
The function calculate_dependent() can also be defined which to calculate
values of the coefficients declared in 'dependent' and assign them in
self.par_dict.The dictionary self.newmass can also be modified at any
stage if modifications to particle masses occur. This should be a
dictionary of PID:mass pairs that will replace the entries in self.mass.
>> def calculate_dependent(self):
>> '''
>> Calculate dependent parameters here by assigning values
>> to self.par_dict corresponding to the keys in self.dependent.
>> '''
>> p = self.par_dict
>> p['d'] = p['a']+ p['b']*p['c'] # set a value for 'd' coefficient
>>
>> def translate(self):
>> '''
>> Translate to the mass basis by creating an empty MassBasis
>> and modifying its par_dict or coeffs._asdict().
>> Set self.newpar with resulting dictionary
>> '''
>> A = self.coeffs._asdict()
>> # initialise empty par_dict of the target basis instance
>> B = MassBasis().coeffs._asdict()
>> # set all values of coeffs according to nonsense formula:
>> # C = coeff_d * m_top / a_EW
>> for k in B.keys():
>> B[k]=A['d']*self.mass[6]/self.input['aEWM1']
>> self.newpar = B
>> self.newname = 'Mass'
4) Once the translate() function has been defined, the implementation is
complete and can be tested with the translate tool. The new basis should be
added to the dictionary 'bases' in implemented.py in order to make the tool
aware of its existence. This is done by importing the new module and
appending it to the dictionary.
In implemented.py:
- >>import WarsawBasis, HiggsBasis, MassBasis, TemplateBasis
- >>import MyBasis
+ >> import WarsawBasis, HiggsBasis, MassBasis, TemplateBasis
+ >> import MyBasis
>> bases['mybasis'] = MyBasis.MyBasis
The options for ./translate -h should now include "mybasis" as a possible
BASIS argument.
################################################################################
+6) eHDECAY interface
+################################################################################
+A useful program based on HDECAY (arXiv:hep-ph/9704448) for calculating the
+Higgs total width was developed in 2014 and is described in arXiv:1403.3381.
+The program takes as input a number of parameters in the SILH basis to calculate
+the width and branching ratios to SM particles optionally including Electroweak
+corrections. In order to have this working correctly the user must:
+
+1) Modify the variable eHDECAY_dir in __init__.py to have it pointing to the
+ location of your installation of eHDECAY
+
+ In __init__.py:
+
+ >> eHDECAY_dir = '/PATH/TO/eHDECAY'
+
+2) Define the member function eHDECAY_inputs() in their basis implementation.
+
+ In MyBasis.py:
+
+ >> def eHDECAY_inputs(self):
+ >> inputs = dict() # populate with values for inputs defined below
+ >> ..
+ >> ..
+ >> return inputs
+
+ Currently, the translations to and from SILH basis have not yet been implemented
+ and so the user will be required to provide the necessary inputs via the
+ definition of the eHDECAY_inputs() function. The required SM and SILH basis
+ inputs are listed in eHDECAY.py and are as follows:
+
+ SM inputs: # ALL masses must be nonzero for eHDECAY to give a finite result
+ 'MC', 'MB', 'MT', 'MMU', 'MTAU, # SM fermion masses
+ 'MH', 'MZ', 'MW', 'aEWM1' 'Gf', # EW input masses, (alpha_EW)^-1, G_Fermi
+ 'aSMZ' # alpha_S(MZ)
+
+ SILH coefficients:
+ 'CHbar' , 'CTbar' , 'Ctaubar', 'Cmubar', 'Ctbar',
+ 'Cbbar' , 'Ccbar' , 'Csbar' , 'CWbar' , 'CBbar',
+ 'CHWbar', 'CHBbar', 'Cgambar', 'Cgbar'
+
+ eHDECAY option:
+ 'IELW' # Electroweak corrections switch (1:on, 0:off)
+
+An example of a toy implementation is given in TemplateBasis.py which uses the
+default values for the SM inputs and sets the SILH coefficients.
+eHDECAY_inputs() should return a dictionary of name:value pairs for the
+parameters listed above.
+
+Rosetta will take the inputs and run eHDECAY in a temporary directory and read
+the relevant branching ratios, updating or creating the DECAY block in the
+output card.
+
+################################################################################
+Rosetta: A Higgs Effective Field Theory basis translator
+################################################################################
+
+
+
+
+
diff --git a/Rosetta/Basis.py b/Rosetta/Basis.py
index 73a3134..0530f21 100644
--- a/Rosetta/Basis.py
+++ b/Rosetta/Basis.py
@@ -1,570 +1,582 @@
import StringIO
import re, sys, os, math, datetime
from collections import namedtuple,OrderedDict
from query import query_yes_no as Y_or_N
from __init__ import PID, default_inputs, default_masses, input_names, particle_names, input_to_PID
from eHDECAY import eHDECAY
####################################################################################################
# Base Basis class
class Basis(object):
'''
Base class from which to derive other Higgs EFT basis classes.
Designed to be instantiated with an SLHA format parameter card using
read_param_card(). The contents of the parameter card are stored in
self.param_card, while relevant information from blocks "basis",
"newcoup", "mass" and "sminput" are stored in self.name, self.par_dict,
self.mass and self.input respectively.
self.name - string storing the value of the 0th element of Block basis.
self.par_dict - ``OrderedDict`` of (name,value) pairs with the name taken to be
the first non-whitespace characters after a "#" character
in a parameter definition within Block newcoup.
self.mass - ``OrderedDict`` of (PID,value) pairs within Block mass
self.input - ``OrderedDict`` as for self.par_dict but within Block sminput.
self.independent and self.dependent should be defined in accordance
with the contents of Block newcoup, as well as self.required_inputs and
self.required_masses with Blocks sminput and mass respectively
(the Z ahd Higgs masses are also stored in SM input). A number of checks
related to these definitions are performed by check_param_data() on the
data read in from the parameter card.
Basis also stores the coefficients in self.coeffs as a ``namedtuple``
which stores the coefficients as data members and from which an ``OrderedDict``
can also be recovered with self.coeffs._asdict()
type(self.par_dict)==type(self.coeffs._asdict()) # True
self.par_dict['myvar'] = 10.
self.coeffs._asdict()['myvar'] == 10. # True
self.coeffs.myvar == 10. # True
The user should define methods calculate_dependent() and translate() to
firstly calculate any dependent parameters and then translate the coefficients
into the mass basis and populate self.newpar, a template of which can be
obtained by creating an instance of HEFTRosetta.MassBasis.MassBasis() without
the optional param_card argument.
from MassBasis import MassBasis
new_instance = MassBasis() # Empty MassBasis instance with all coeffs set to 0
new_dict = new_instance.coeffs._asdict()
set_newcard() uses the contents of self.newpar to write a modified parameter card
in the mass basis and write_param_card() saves it to file.
Users should call translate() and set_newcard() in the __init__ of their derived class
should they choose to overload the constructor.
Derived classes can be used by the command line script "translate"
'''
independent, dependent=[], []
required_inputs, required_masses = set(),set()
translate_to = {'mass'}
- def __init__(self, param_card=None, block_in='newcoup', block_out='newcoup', output_basis='mass', keep_old=True):
+ def __init__(self, param_card=None, block_in='newcoup', block_out='newcoup', output_basis='mass', keep_old=True, ehdecay=False):
# Check that target basis has a translation implemented
if output_basis in self.translate_to:
self.target_basis = output_basis
else:
raise ValueError('''
{}.translate_to does not contain "{}".
Rosetta doesn't know of an implemented translation in {}
'''.format(self.__class__.__name__,output_basis, self.__class__))
self.param_card = param_card
self.block_in, self.block_out, self.keep_old = block_in, block_out, keep_old # other options
self.card, self.newcard = StringIO.StringIO(), StringIO.StringIO()
self.SLHA_sminputs = OrderedDict()
self.input, self.mass, self.par_dict = OrderedDict(), OrderedDict(), OrderedDict()
self.newinput, self.newmass, self.newpar = dict(), dict(), dict()
self.newname = 'Basis'
self.all_coeffs = self.independent + self.dependent
if param_card is not None: # read param card (sets self.par_dict, self.input, self.mass, self.name, self.card)
assert os.path.exists(self.param_card), '{} does not exist!'.format(self.param_card)
self.read_param_card() # read
self.check_param_data() # consistency check on inputs
self.calculate_dependent() # calculate dependent parameters (User defined)
self.check_calculated_data() # consistency check on dependent parameters
coeffclass = namedtuple(self.name, self.all_coeffs) # declare coefficient namedtuple
self.coeffs = coeffclass(**self.par_dict) # store coefficients
self.translate() # translate to new basis (User defined)
self.check_new() # consistency check between self.newinput and self.newmass
self.set_new_masses() # set new masses in self.newinput
try: # run eHDECAY if eHDECAY_input() is implemented
- self.BRs = eHDECAY(self)
- print self.BRs
+ if ehdecay: self.BRs = eHDECAY(self) # Call to eHDECAY will raise NotImplementedError if eHDECAY_inputs() is not defined
except NotImplementedError:
pass
self.set_newcard() # set new param_card
else: # if param_card option not given, instatiate with class name and all coeffs set
# to 0 (used for creating an empty basis instance for use in translate() method)
self.name=self.__class__.__name__
coeffclass = namedtuple(self.name, self.all_coeffs)
self.coeffs = coeffclass(**{k:0. for k in self.all_coeffs})
def read_param_card(self):
'''
Reads SLHA style param card and stores values of parameters.
Looks for Blocks "basis", "mass", "newcoup" and "sminput" and
updates self.name, self.mass (by PDG number), self.par_dict (name, value)
and self.input (name, value)/self.SLHA_sminputs (SLHA ID, value) respectively.
The whole param_card is also stored in self.card for later use.
'''
def read_pattern(plines, patt, pdict, ikey=2, ival=1, convert_key=str, convert_val=float):
'''Takes a list of lines and looks for regexp pattern "patt" assuming the pattern captures 2 groups.
"key" and "val" refer to the index of the resulting group (1 or 2).
"convert_val" and "convert_key" specify a functions with which to treat the resulting string match e.g. convert to float.
If pdict is None, function returns convert_val( match.group(val) ) (used to assign one variable).
Otherwise, pdict is appended with a key value pair ( convert_key(match.group(key)), convert_val(match.group(val)) ).
'''
for pline in plines[:-1]:
try:
match = re.match(patt,pline)
if pdict is not None:
key, val = convert_key(match.group(ikey)), convert_val(match.group(ival))
if key in pdict: # check if variable has already been assigned
label = 'PDG mass' if type(key)==int else 'variable'
print 'Warning: {} "{}" assigned more than once, kept value {}'.format( label,key,val )
pdict[key]= val
else:
return convert_val(match.group(ival))
except AttributeError:
pass
return None
with open(self.param_card,'r') as card:
relevant_blocks =['mass','basis',self.block_in,'sminputs']
lines = iter(card)
for line in lines:
line, block = self.line_is_block(line)
while block in relevant_blocks:
if block=='mass': # Get masses
print >> self.card, line.strip('\n')
param_lines = self.read_until(lines,'Block','DECAY') # lines in block mass
read_pattern(param_lines, r'\s*(\d+)\s+(\S+)\s+.*', self.mass, ikey=1, ival=2, convert_key=int) # by PDG number
for pline in param_lines[:-1]: print >> self.card, pline.strip('\n')
line, block = self.line_is_block(param_lines[-1]) # set last line read to current line
relevant_blocks.remove('mass')
elif block=='basis': # Get basis name
print >> self.card, line.strip('\n')
param_lines = self.read_until(lines,'Block','DECAY') # lines in block basis
self.name = read_pattern(param_lines,r'\s*0\s+(\S+).*', None, convert_val=str).strip()
for pline in param_lines[:-1]: print >> self.card, pline.strip('\n')
line, block = self.line_is_block(param_lines[-1]) # set last line read to current line
relevant_blocks.remove('basis')
elif block==self.block_in: # Get basis coefficients
print >> self.card, line.strip('\n')
param_lines = self.read_until(lines,'Block', 'DECAY') # lines in block newcoup
read_pattern(param_lines, r'\s*\d+\s+(\S+)\s+#+\s+(\S+)', self.par_dict)
for pline in param_lines[:-1]: print >> self.card, pline.strip('\n')
line, block = self.line_is_block(param_lines[-1]) # set last line read to current line
relevant_blocks.remove(self.block_in)
elif block=='sminputs': # Get SM inputs
print >> self.card, line.strip('\n')
param_lines = self.read_until(lines,'Block', 'DECAY') # lines in block sminputs
read_pattern(param_lines, r'\s*(\d+)\s+(\S+)\s+#+\s+\S+', self.SLHA_sminputs, ikey=1, ival=2, convert_key = int)
read_pattern(param_lines, r'\s*\d+\s+(\S+)\s+#+\s+(\S+)', self.input)
for pline in param_lines[:-1]: print >> self.card, pline.strip('\n')
line, block = self.line_is_block(param_lines[-1]) # set last line read to current line
relevant_blocks.remove('sminputs')
if not block or (block not in relevant_blocks): print >> self.card, line.strip('\n')
if relevant_blocks: # checks if all relevant block were found
if relevant_blocks==['basis']: # only optional basis block unread
print 'Warning: block basis not found.'
carry_on = Y_or_N('Continue assuming default value "{}"?'.format(self.__class__.__name__))
if carry_on:
self.name=self.__class__.__name__
else:
print 'Exit'
sys.exit()
else:
raise IOError("Required block(s) ({}) not found in {}".format(', '.join(relevant_blocks), self.param_card))
# Add MH,MW,MZ,mt,mb,mtau,aEWM1 to SLHA_sminputs
for inID,PID in input_to_PID.iteritems():
if inID in self.required_inputs:
try:
input_mass = self.mass[PID]
self.input[input_names[inID]] = input_mass
self.SLHA_sminputs[inID] =input_mass
except KeyError:
pass
def check_param_data(self):
'''
Compares lists of coefficients declared in self.independent and self.dependent to those read in from self.param_card.
1) Deals with unrecognised names by removing them from self.par_dict
2) Prints a warning if coefficients declared as dependent are assigned values in param_card.
If so, the user is asked whether or not they wish to continue.
3) Checks if all coefficients declared as independent are assigned values.
If not, the user is given the option to continue with them set to 0.
4) Ensures all fermion masses declared in self.required_masses are defined.
If not, the user is given the option to continue with them set to 0.
5) Ensures all sm imputs declared in self.required_inputs are defined.
If not, the user is given the option to continue with them set to default
values defined in Rosetta.default_inputs.
'''
unknown_coeffs = set(self.par_dict.keys()).difference( self.all_coeffs )
if unknown_coeffs: # Check for unrecognised coeff names
print 'Warning: you have declared coefficients undefined in {}.'.format(self.__class__)
print 'The following will be ignored: {}'.format(','.join(unknown_coeffs))
for c in unknown_coeffs: del self.par_dict[c]
defined_dependent = set(self.dependent).intersection( set(self.par_dict.keys()) )
if defined_dependent: # Check if coefficients defined as dependent have been assigned values
print 'Warning: you have assigned values to some coefficients defined as dependent in {}.'.format(self.__class__)
print 'Coefficients: {}'.format(','.join(defined_dependent))
print 'These may be overwritten by an implementation of {}.translate()'.format(self.__class__.__name__)
carry_on = Y_or_N('Continue?')
if carry_on:
pass
else:
print 'Exit'
sys.exit()
missing_coeffs = set(self.independent).difference( set(self.par_dict.keys()) )
if missing_coeffs: # Deal with unassigned independent coefficients
print 'Warning: Set of independent coefficients read from {} does not match those specified in {}.'.format(self.param_card,self.__class__)
print 'Undefined: {}'.format(', '.join(missing_coeffs))
carry_on = Y_or_N('Continue assuming unspecified coefficients are Zero?')
if carry_on:
for m in missing_coeffs: self.par_dict[m]=0.
else:
print 'Exit'
sys.exit()
missing_masses = set(self.required_masses).difference(self.mass.keys())
repr_default_masses = ['{}={:.5e}'.format(k,default_masses.get(k,0.)) for k in missing_masses]
if missing_masses: # Deal with unassigned fermion masses
print 'Warning: Not all required fermion masses are defined in {}.'.format(self.param_card)
print 'Required PIDs: {}'.format(', '.join([str(x) for x in self.required_masses]))
print 'Missing PIDs: {}'.format(', '.join([str(x) for x in missing_masses]))
carry_on = Y_or_N('Continue assuming default values for unspecified masses? ({})'.format(', '.join(repr_default_masses)))
if carry_on: # assigns a data member for unspecified inputs for writing to self.newcard
self.missing_masses=dict()
for m in missing_masses:
self.mass[m]=default_masses[m]
self.missing_masses[m]=default_masses[m]
else:
print 'Exit'
sys.exit()
missing_inputs = set(self.required_inputs).difference(self.SLHA_sminputs.keys())
repr_default_inputs = ['{}={:.5e}'.format(input_names[k],default_inputs.get(k,0.)) for k in missing_inputs]
if missing_inputs: # Deal with unassigned SM inputs
print 'Warning: Not all required SM inputs are defined in {}.'.format(self.param_card)
print 'Required inputs: {}'.format(', '.join(['{} ({})'.format(input_names[x],x) for x in self.required_inputs]))
print 'Missing inputs: {}'.format(', '.join([str(x) for x in missing_inputs]))
carry_on = Y_or_N('Continue with default values for unspecified inputs? ({})'.format(', '.join(repr_default_inputs)))
if carry_on:# assigns a data member for unspecified inputs for writing to self.newcard
self.missing_inputs=dict()
for m in missing_inputs:
self.SLHA_sminputs[m]=default_inputs[m]
self.input[input_names[m]]=default_inputs[m]
self.missing_inputs[m]=default_inputs[m]
else:
print 'Exit'
sys.exit()
print 'Param card data are OK.'
def check_calculated_data(self):
'''
Compares self.dependent and self.par_dict keys to see if all dependent coefficients have been calculated.
If not, asks whether the user wants to continue assuming they are zero.
'''
missing_dependents = set(self.dependent).difference(self.par_dict.keys())
if missing_dependents and self.dependent:
print 'Warning: Set of dependent coefficients calculated by {0}.calculate_dependent() does not match those specified in {0}.'.format(self.__class__)
print 'Undefined: {}'.format(', '.join(missing_dependents))
carry_on = Y_or_N('Continue assuming coefficients are Zero?')
if carry_on:
for m in missing_dependents: self.par_dict[m]=0.
else:
print 'Exit'
sys.exit()
print 'Calculated coefficients match those defined in {}.dependent.'.format(self.__class__.__name__)
def check_new(self):
'''
Check consistency of modifications to mass parameters defined as possible SHLA inputs:
MZ (PID = 23, SLHA key = 4)
MW (PID = 24, SLHA key = 7)
MH (PID = 25, SLHA key = 8)
Compares self.newinput to self.newmass and makes sure user hasn't specified different new values
'''
for ID_input, ID_mass in input_to_PID.iteritems():
try:
ipar, mpar = self.newinput[ID_input],self.newmass[ID_mass]
if not ipar==mpar:
print 'Warning: modified mass {} in self.newinput ({}) does not match value in self.newmass ({})'.format(input_name[ID_input],ipar,mpar)
carry_on = Y_or_N('Continue using values in self.newmass?')
if carry_on:
pass
else:
print 'Exit'
sys.exit()
except KeyError as e:
pass
def set_new_masses(self):
'''
If the user modifies a mass input parameter, appends the change to self.mass
'''
for inID, PID in input_to_PID.iteritems():
if inID in self.newinput and PID not in self.newmass: self.newmass[PID] = self.newinput[inID]
def set_newcard(self):
'''
Generates a new param card in self.newcard from self.card, adding the new set of coefficients in self.newpar after "Block newcoup".
If self.keep_old is True, the original names and values of newcoup variables are included, commented out.
'''
+ def new_higgs_width(lines):
+ totalwidth = float(self.BRs['WTOT'])
+ if lines is None:
+ print >> self.newcard, '###################################'
+ print >> self.newcard, '## Higgs decay info from eHDECAY'
+ print >> self.newcard, '###################################'
+ print >> self.newcard, 'DECAY 25 {} # New Higgs total width'.format(totalwidth)
+ print >> self.newcard, '# BR NDA ID1 ID2'.format(totalwidth)
+ particle_IDs = {v:k for k,v in particle_names.iteritems()}
+ for channel,BR in self.BRs.iteritems():
+ if channel!='WTOT':
+ p1, p2 = channel[:len(channel)/2], channel[len(channel)/2:]
+ id1, id2 = particle_IDs[p1], particle_IDs[p2]
+ print >> self.newcard, ' {:.5e} 2 {: <2} {: <2} # BR(H -> {} {})'.format(BR, id1, id2, p1, p2)
+ if lines is None:
+ print >> self.newcard, '###################################'
+ return
+ param_lines = self.read_until(lines, 'Block', 'DECAY')[:-1] # read old BR values
+ for i,pline in enumerate(param_lines):
+ if i==0:
+ print >> self.newcard, '# Old BR info'
+ print >> self.newcard, '# '+line.strip('\n')
+ if self.keep_old:
+ comment_out = (pline and not pline.startswith('#'))
+ print >> self.newcard, '# ' + pline.strip('\n') if comment_out else pline.strip('\n')
+ else:
+ if not pline.strip() or pline.startswith('#'): print >> self.newcard, pline.strip('\n')
+ return self.line_is_block(param_lines[-1]) # return last line read and whether it is a BLOCK line
+
print >> self.newcard, '######################################################################'
print >> self.newcard, '############# COEFFICIENTS TRANSLATED BY ROSETTA MODULE #############'
print >> self.newcard, '########### PARAM_CARD GENERATED {} ###########'.format(datetime.datetime.now().ctime().upper())
print >> self.newcard, '######################################################################'
blocks_to_modify =('basis', self.block_in, 'mass', 'sminputs')
lines = iter(self.card.getvalue().splitlines()) # Lines of old param card
+ done_width=False
for line in lines:
-
-
-
line, block = self.line_is_block(line)
if block==self.block_in: # Add line to self.newcard, modify block name
print >> self.newcard, line.strip('\n').replace(self.block_in,self.block_out)
elif self.line_is_decay(line)=='25': # special case for modified higgs width and BRs
try:
- totalwidth = float(self.BRs['WTOT'])
- print >> self.newcard, 'DECAY 25 {} # New Higgs total width'.format(totalwidth)
- print >> self.newcard, '# BR NDA ID1 ID2'.format(totalwidth)
- particle_IDs = {v:k for k,v in particle_names.iteritems()}
- for channel,BR in self.BRs.iteritems():
- if channel!='WTOT':
- p1, p2 = channel[:len(channel)/2], channel[len(channel)/2:]
- id1, id2 = particle_IDs[p1], particle_IDs[p2]
- print >> self.newcard, ' {:.5e} 2 {: <2} {: <2} # BR(H -> {} {})'.format(BR, id1, id2, p1, p2)
- param_lines = self.read_until(lines, 'Block', 'DECAY')[:-1] # read old BR values
- for i,pline in enumerate(param_lines):
- if i==0:
- print >> self.newcard, '# Old BR info'
- print >> self.newcard, '#'+line.strip('\n')
- if self.keep_old:
- comment_out = (pline and not pline.startswith('#'))
- print >> self.newcard, '#' + pline.strip('\n') if comment_out else pline.strip('\n')
- else:
- if not pline.strip() or pline.startswith('#'): print >> self.newcard, pline.strip('\n')
- line, block = self.line_is_block(param_lines[-1]) # set last line read to current line
+ line, block = new_higgs_width(lines)
+ done_width = True
except AttributeError:
print >> self.newcard, line.strip('\n')
else: # Add line to self.newcard
print >> self.newcard, line.strip('\n')
while block in blocks_to_modify: # Slightly different actions for each block
if block=='basis': # When Block basis is reached
print >> self.newcard, ' 0 {} # translated basis'.format(self.newname)
param_lines = self.read_until(lines, 'Block', 'DECAY')
for pline in param_lines[:-1]:
if self.keep_old:
comment_out = (pline and not pline.startswith('#'))
print >> self.newcard, '#' + pline.strip('\n') if comment_out else pline.strip('\n')
else:
if not pline.strip() or pline.startswith('#'): print >> self.newcard, pline.strip('\n')
line, block = self.line_is_block(param_lines[-1]) # set last line read to current line
elif block==self.block_in: # When Block self.block_in is reached,
for i,(par,val) in enumerate(self.newpar.items()): # write out new couplings
print >> self.newcard, ' {} {:.5e} # {}'.format(i,val,par)
param_lines = self.read_until(lines,'Block', 'DECAY')
if self.keep_old: # write old parameters
print >> self.newcard, ''
print >> self.newcard, '###################################'
print >> self.newcard, '## COEFFICIENTS IN {} BASIS'.format(self.name.upper())
print >> self.newcard, '###################################'
for pline in param_lines[:-1]:
comment_out = (pline and not pline.startswith('#'))
print >> self.newcard, '#' + pline.strip('\n') if comment_out else pline.strip('\n')
else:
for pline in param_lines[:-1]:
if not pline.strip() or pline.startswith('#'): print >> self.newcard, pline.strip('\n')
line, block = self.line_is_block(param_lines[-1]) # set last line read to current line
elif block=='sminputs':# When block sminputs is reached
try: # add missing inputs
for i,(ID, inpt) in enumerate(self.missing_inputs.items()):
if i==0: print >> self.newcard, '# missing inputs'
if ID in self.newinput:
print >> self.newcard, ' {} {:.5e} # {} '.format(ID, self.newinput[ID], input_names[ID])
print >> self.newcard, '# {} {:.5e} # {} old value'.format(ID, inpt, input_names[ID])
else:
print >> self.newcard, ' {} {:.5e} # {} '.format(ID, inpt, input_names[ID])
except AttributeError as e:
pass
# add additional new inputs
input_names_reversed={v:k for k,v in input_names.iteritems()}
for i,(ID, inpt) in enumerate(self.newinput.items()):
if i==0: print >> self.newcard, '# additional inputs'
if not ID in self.SLHA_sminputs:
if type(ID)==int:
print >> self.newcard, ' {} {:.5e} # {} '.format(ID, inpt, input_names.get(ID,''))
elif type(ID)==str:
print >> self.newcard, ' {} {:.5e} # {} '.format(input_names_reversed.get(ID,99), inpt,ID )
print >> self.newcard, '# original inputs'
param_lines = self.read_until(lines,'Block', 'DECAY')
for pline in param_lines[:-1]:
match = re.match(r'\s*(\d+)\s+(\S+)\s+.*',pline.strip()) # read old inputs
try: # do if match
ID, inpt = int(match.group(1)), match.group(2)
try: # if a new value exists
print >> self.newcard, pline.replace(inpt, '{:.5e}'.format(self.newinput[ID])).strip('\n')
if self.keep_old: print >> self.newcard, '# '+pline.strip('\n')+' # old value'
except KeyError as e:
print >> self.newcard, pline.strip('\n')
except AttributeError as e:
print >> self.newcard, pline.strip('\n')
line, block = self.line_is_block(param_lines[-1]) # set last line read to current line
elif block=='mass': # When block mass is reached
try: # add missing masses
for i,(ID, mass) in enumerate(self.missing_masses.items()):
if i==0: print >> self.newcard, '# missing masses'
if ID in self.newmass:
print >> self.newcard, ' {} {:.5e} # M{} '.format(ID, self.newmass[ID], particle_names[ID])
print >> self.newcard, '# {} {:.5e} # M{} old value'.format(ID, mass, particle_names[ID])
else:
print >> self.newcard, ' {} {:.5e} # M{} '.format(ID, mass, particle_names[ID])
except AttributeError as e: # self.missing_masses may not exist
pass
try: # add missing inputs that are masses
for inID, PID in input_to_PID.iteritems():
try:
print >> self.newcard, ' {} {:.5e} # {} '.format(PID,self.missing_inputs[inID],input_names[inID])
except KeyError:
pass
except AttributeError as e: # self.missing_inputs may not exist
pass
print >> self.newcard, '# original masses'
param_lines = self.read_until(lines,'Block', 'DECAY')
for pline in param_lines[:-1]:
match = re.match(r'\s*(\d+)\s+(\S+)\s+.*',pline.strip()) # read old mass
try: # do if match
ID, mass = int(match.group(1)), match.group(2)
try: # if a new value exists
print >> self.newcard, pline.replace(mass, '{:.5e}'.format(self.newmass[ID])).strip('\n')
if self.keep_old: print >> self.newcard, '# '+pline.strip('\n')+' # old value'
except KeyError:
print >> self.newcard, pline.strip('\n')
except AttributeError:
print >> self.newcard, pline.strip('\n')
line, block = self.line_is_block(param_lines[-1]) # set last line read to current line
if block==self.block_in:
print >> self.newcard, line.strip('\n').replace(self.block_in,self.block_out) # Add line to self.newcard, modify block name
else:
print >> self.newcard, line.strip('\n') # Add line to self.newcard
-
+ if not done_width:
+ try:
+ new_higgs_width(None)
+ except AttributeError:
+ pass
return None
def write_param_card(self,filename,overwrite=False):
'''Write contents of self.newcard to filename'''
contents = self.newcard.getvalue()
if not contents:
print '{}.newcard is empty, nothing done.'.format(self)
return None
if os.path.exists(filename) and not overwrite:
print '{} already exists.'.format(filename)
carry_on = Y_or_N('Overwrite?')
else:
carry_on=True
if carry_on:
with open(filename,'w') as param_card:
param_card.write(contents)
return True
else:
return False
-
+
@staticmethod
def read_until(lines, here, *args):
'''Loops through an iterator of strings by calling next() until
it reaches a line starting with a particular string.
Case insensitive.
Args:
lines - iterator of strings
here - string (plus any further argumnts). Reading will end if the line matches any of these.
Return:
lines_read - list of lines read
line - last line that was read (containing string "here")
'''
end_strings = [here.lower()]+[a.lower() for a in args]
lines_read = []
line = ''
while not any([line.strip().lower().startswith(x) for x in end_strings]):
line = lines.next()
lines_read.append(line.strip('\n'))
return lines_read
@staticmethod
def line_is_block(line):
'''
Looks for "BLOCK XXXX" pattern in line.
returns (line, XXXX) if line matches.
returns (line, False) if line doesn't match
'''
try:
return line, re.match(r'block\s+(\S+).*',line.strip().lower()).group(1)
except AttributeError:
return line, False
@staticmethod
def line_is_decay(line):
'''
Looks for "DECAY XXXX YYYY" pattern in line.
returns XXXX if line matches.
returns None if line doesn't match
'''
match = re.match(r'decay\s+(\S+)\s+.*',line.strip().lower())
try:
return match.group(1)
except AttributeError:
return None
def calculate_dependent(self):
print 'Nothing done for {}.calculate_dependent()'.format(self.__class__.__name__)
def translate(self): # default behaviour for translate()
self.keep_old=False
self.newpar = self.coeffs._asdict()
def eHDECAY_inputs(self):
raise NotImplementedError
####################################################################################################
\ No newline at end of file
diff --git a/Rosetta/TemplateBasis.py b/Rosetta/TemplateBasis.py
index 589ff98..967104b 100644
--- a/Rosetta/TemplateBasis.py
+++ b/Rosetta/TemplateBasis.py
@@ -1,65 +1,97 @@
from Basis import Basis
from MassBasis import MassBasis
from eHDECAY import eHDECAY
-from __init__ import default_masses as dm, default_inputs as di
+from __init__ import default_masses, default_inputs
import os
####################################################################################################
# Template basis class
class TemplateBasis(Basis):
independent = ['a','b','c']
dependent=['d']
required_masses = {1,2,3,4,5,6}
required_inputs = {1, 4} # aEWM1, MZ
def __init__(self,*args,**kwargs): # This can be overridden if you want
super(TemplateBasis, self).__init__(*args,**kwargs) # ensure a call to the base class constructor is made as so
# additional instructions can live here
def calculate_dependent(self):
'''
Calculate dependent parameters here by assigning values to self.par_dict
corresponding to the keys in self.dependent.
'''
p = self.par_dict
p['d'] = p['a']+ p['b']*p['c']
def translate(self):
'''
Translate to the mass basis by creating an empty MassBasis and modifying its par_dict or coeffs._asdict()
set self.newpar with resulting par_dict
'''
A = self.coeffs._asdict()
B = MassBasis().coeffs._asdict()
for k in B.keys(): # set all values of mass basis coeffs according to nonsense formula coeff_a*m_top/a_EW
B[k] = self.myfunc( A['d'], self.mass[6], self.input['aEWM1'] )
- self.newmass[23]=91.19 # MZ in newmass
+ self.newmass[24]=91.19 # MZ in newmass
self.newinput[8]=126. # MH in newinput
self.newpar = B
self.newname = 'Mass'
def eHDECAY_inputs(self):
- inputs = {'MH':dm[25],'aSMZ':di[3],'MC':dm[4],'MB':dm[5],
- 'MT':dm[6],'MTAU':dm[15],'MMU':dm[13],'aEWM1':di[1],
- 'Gf':di[2],'MZ':dm[24],'MW':dm[23]} # inputs set to default values defined in __init__.py
+
+ def try_default_mass(PID):
+ try:
+ if self.newmass[PID] > 0.:
+ return self.newmass[PID]
+ elif self.mass[PID] > 0.:
+ return self.mass[PID]
+ else:
+ raise KeyError
+ except KeyError:
+ return default_masses[PID]
+
+ def try_default_inpt(ID):
+ try:
+ return self.newinput[ID]
+ except KeyError:
+ try:
+ return self.SLHA_sminputs[ID]
+ except KeyError:
+ return default_inputs[ID]
+
+ inputs = dict()
+ inputs['MH'] = try_default_mass(25)
+ inputs['MZ'] = try_default_mass(24)
+ inputs['MW'] = try_default_mass(23)
+ inputs['MC'] = try_default_mass(4)
+ inputs['MB'] = try_default_mass(5)
+ inputs['MT'] = try_default_mass(6)
+ inputs['MMU'] = try_default_mass(13)
+ inputs['MTAU'] = try_default_mass(15)
+ inputs['aEWM1'] = try_default_inpt(1)
+ inputs['Gf'] = try_default_inpt(2)
+ inputs['aSMZ'] = try_default_inpt(3)
+
inputs['IELW'] = 1 # electroweak corrections on
+
SILH_coeffs = ['CHbar','CTbar','Ctaubar','Cmubar',
'Ctbar','Cbbar','Ccbar','Csbar','CWbar',
'CBbar','CHWbar','CHBbar','Cgambar','Cgbar']
inputs.update({ci:0.001 for ci in SILH_coeffs}) # all input SILH coeffs set to 0.001
return inputs
@staticmethod # pure function, no access to class instance
def myfunc(x,y,z):
return x*y/z
def myfunc2(self,x,y,z): # access to class instance
my_one = self.SLHA_sminputs[4]/self.SLHA_sminputs[4]
return x*y/z*my_one
####################################################################################################
if __name__=='__main__':
instance = TemplateBasis('../Cards/param_card_TemplateBasis.dat')
inputs = instance.eHDECAY_inputs()
print eHDECAY(inputs)
\ No newline at end of file
diff --git a/Rosetta/eHDECAY.py b/Rosetta/eHDECAY.py
index f58751e..b9e303f 100644
--- a/Rosetta/eHDECAY.py
+++ b/Rosetta/eHDECAY.py
@@ -1,158 +1,174 @@
from __init__ import eHDECAY_dir
import os
from tempfile import mkdtemp
import subprocess as sub
from collections import namedtuple
-
+####################################################################################################
SM_inputs = ['MH','aSMZ','MC','MB','MT','MTAU',
'MMU','aEWM1','Gf','MZ','MW','IELW']
SILH_inputs = ['CHbar','CTbar','Ctaubar','Cmubar',
'Ctbar','Cbbar','Ccbar','Csbar','CWbar',
'CBbar','CHWbar','CHBbar','Cgambar','Cgbar']
executable = '{}/run'.format(eHDECAY_dir) # eHDECAY executable
SILH = namedtuple('SILH', SM_inputs+SILH_inputs) # Required inputs for eHDECAY
-
+####################################################################################################
+__doc__='''
+Interface with eHDECAY program (arXiv:1403.3381) to calculate new Higgs width and branching ratio
+to SM particles. Currently takes inputs via a dictionary of parameter:value pairs to be returned by
+the eHDECAY_inputs() function of a basis class.
+These should contain the following SM inputs:
+{}
+They should also contain the values of the following coefficients of the SILH basis:
+{}
+This module will create a temporary directory to write out the input and output files, call the
+eHDECAY exectuable and store the output so that it may be written to the new parameter card.
+'''.format(', '.join(SM_inputs),', '.join(SILH_inputs))
+####################################################################################################
+
+
+
def eHDECAY(basis):
print 'Running eHDECAY'
input_dict = basis.eHDECAY_inputs()
+ print input_dict
inp = SILH(**input_dict)
# create temporary directory
tmpdir = mkdtemp(prefix='eHDECAY_',dir = os.getcwd())
# write out eHDECAY input file
with open('{}/ehdecay.in'.format(tmpdir),'w') as infile:
infile.write( create_input(inp) )
process = sub.Popen(executable, stdout = sub.PIPE, stderr = sub.PIPE, cwd = tmpdir)
out, err = process.communicate()
if err:
raise RuntimeError('eHDECAY error: {}'.format(err))
print 'eHDECAY output:\n{}'.format(out)
# read BRs and total width
result = read_output(tmpdir)
# clean up temp directory
- sub.call(['rm','-r',tmpdir])
+ # sub.call(['rm','-r',tmpdir])
return result
def read_output(workdir):
with open('{}/br.eff1'.format(workdir),'r') as br1, open('{}/br.eff2'.format(workdir),'r') as br2:
br1_dat, br2_dat = br1.readlines()[3], br2.readlines()[3]
MH, BB, TATA, MUMU, SS, CC, TT = tuple(map(float,br1_dat.split()))
__, GG, AA, ZA, WW, ZZ, WTOT = tuple(map(float,br2_dat.split()))
BR = { 'bb':BB, 'tata':TATA, 'mumu':MUMU,
'ss':SS, 'cc':CC, 'tt':TT , 'gg':GG,
'aa':AA, 'Za':ZA, 'WW':WW, 'ZZ':ZZ,
'WTOT':WTOT}
return BR
def create_input(inp):
values = inp._asdict().values()
return \
'''SLHAIN = 0
SLHAOUT = 0
COUPVAR = 1
HIGGS = 0
SM4 = 0
FERMPHOB = 0
MODEL = 1
TGBET = 1.D0
MABEG = {}
MAEND = 1000.D0
NMA = 1
ALS(MZ) = {}
MSBAR(2) = 0.100D0
MC = {}
MB = {}
MT = {}
MTAU = {}
MMUON = {}
1/ALPHA = {}
GF = {}
GAMW = 2.08856D0
GAMZ = 2.49581D0
MZ = {}
MW = {}
VUS = 0.2253D0
VCB = 0.0410D0
VUB/VCB = 0.0846D0
********************* 4TH GENERATION *************************************
SCENARIO FOR ELW. CORRECTIONS TO H -> GG (EVERYTHING IN GEV):
GG_ELW = 1: MTP = 500 MBP = 450 MNUP = 375 MEP = 450
GG_ELW = 2: MBP = MNUP = MEP = 600 MTP = MBP+50*(1+LOG(M_H/115)/5)
GG_ELW = 1
MTP = 500.D0
MBP = 450.D0
MNUP = 375.D0
MEP = 450.D0
**************************************************************************
SUSYSCALE= 1000.D0
MU = 1000.D0
M2 = 1000.D0
MGLUINO = 1000.D0
MSL1 = 1000.D0
MER1 = 1000.D0
MQL1 = 1000.D0
MUR1 = 1000.D0
MDR1 = 1000.D0
MSL = 1000.D0
MER = 1000.D0
MSQ = 1000.D0
MUR = 1000.D0
MDR = 1000.D0
AL = 1000.D0
AU = 1000.D0
AD = 1000.D0
NNLO (M) = 0
ON-SHELL = 0
ON-SH-WZ = 0
IPOLE = 0
OFF-SUSY = 0
INDIDEC = 0
NF-GG = 5
IGOLD = 0
MPLANCK = 2.4D18
MGOLD = 1.D-13
************** LAGRANGIAN 0 - chiral 1 - SILH 2 - MCHM4/5 **************
LAGPARAM = 1
**** Turn off (0) or on (1) the elw corrections for LAGPARAM = 1 or 2 ****
IELW = {}
******************* VARIATION OF HIGGS COUPLINGS *************************
CW = 0D0
CZ = 0D0
Ctau = 0D0
Cmu = 0D0
Ct = 0D0
Cb = 0D0
Cc = 0D0
Cs = 0D0
Cgaga = 0D0
Cgg = 0D0
CZga = 0D0
CWW = 0D0
CZZ = 0D0
CWdW = 0D0
CZdZ = 0D0
**************************** SILH Lagrangian *****************************
CHbar = {}
CTbar = {}
Ctaubar = {}
Cmubar = {}
Ctbar = {}
Cbbar = {}
Ccbar = {}
Csbar = {}
CWbar = {}
CBbar = {}
CHWbar = {}
CHBbar = {}
Cgambar = {}
Cgbar = {}
******** MCHM4 (fermrepr=1), MCHM5 (fermrepr=2) parametrisation ********
fermrepr = 2
xi = 0.D0
'''.format(*values)
diff --git a/translate b/translate
index 3be4332..475d43e 100755
--- a/translate
+++ b/translate
@@ -1,41 +1,46 @@
#!/usr/bin/env python
################################################################################
import Rosetta as HEFT
from Rosetta.implemented import bases
import StringIO, os, argparse, sys
import subprocess as sub
################################################################################
parser = argparse.ArgumentParser(description="Read in an LHA format parameter card in a particular basis and write a new param card in the mass basis.")
parser.add_argument("param_card", metavar="PARAMCARD", type=str, help="Input parameter card.")
parser.add_argument("basis", metavar="BASIS", type=str, help="Basis of coefficients in parameter card (one of: {}).".format(', '.join(bases.keys())))
parser.add_argument("-o","--output", metavar="OUTPUT", type=str, default='', help="Output file name. Default: [PARAMCARD]_new")
parser.add_argument("-b","--blockin", metavar="BLOCKIN", type=str, default='newcoup', help="New coupling block to be read in. Default: newcoup")
parser.add_argument("-B","--blockout", metavar="BLOCKOUT", type=str, default='newcoup', help="New coupling block to be written out. Default: newcoup")
parser.add_argument("-t","--target", metavar="TARGETBASIS", type=str, default='mass', help="Basis into which to translate (one of: {}). Default: mass".format(', '.join(bases.keys())))
parser.add_argument("-w","--overwrite", action='store_true', help="Overwrite any pre-existing output file.")
+parser.add_argument("-e","--ehdecay", action='store_true', help="Interface with eHDECAY")
################################################################################
args = parser.parse_args()
mybasis = bases[args.basis.lower()] # Set basis class, must be defined in Rosetta.implemented.bases
if not args.output: # output file name
if '.' in args.param_card:
new_name = args.param_card.split('.')
new_name.insert(-1,'_new.')
new_param_card = ''.join(new_name)
else:
new_name = args.param_card+'_new'
else:
new_param_card = args.output
print ''
print '########## Rosetta ##########'
print 'Basis class used to read in param card: {}'.format(mybasis)
-basis_instance = mybasis(param_card=args.param_card, block_in=args.blockin, block_out=args.blockout, output_basis=args.target) # create instance of mybasis
+basis_instance = mybasis(param_card=args.param_card,
+ block_in=args.blockin,
+ block_out=args.blockout,
+ output_basis=args.target,
+ ehdecay=args.ehdecay) # create instance of mybasis
print 'Basis name: {}'.format(basis_instance.name)
if basis_instance.write_param_card(new_param_card, overwrite=args.overwrite): # write out new param card
print 'Wrote new param card to {}.'.format(new_param_card)
print '#############################'
print ''
else:
print 'Exit'
################################################################################

File Metadata

Mime Type
text/x-diff
Expires
Tue, Nov 19, 3:03 PM (1 d, 14 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
3804899
Default Alt Text
(74 KB)

Event Timeline