Page MenuHomeHEPForge

No OneTemporary

diff --git a/Rosetta/Basis.py b/Rosetta/Basis.py
index 22b0f21..45420ec 100644
--- a/Rosetta/Basis.py
+++ b/Rosetta/Basis.py
@@ -1,518 +1,527 @@
import StringIO
import re, sys, os, math, datetime
from collections import namedtuple,OrderedDict
from query import query_yes_no as Y_or_N
-from Rosetta import PID, default_inputs, default_masses, input_names, particle_names, input_to_PID
-
+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.
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):
# 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
+ 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.
'''
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
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)
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
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
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/HiggsBasis.py b/Rosetta/HiggsBasis.py
index 8ae1a2f..12619db 100644
--- a/Rosetta/HiggsBasis.py
+++ b/Rosetta/HiggsBasis.py
@@ -1,86 +1,86 @@
from Basis import Basis
import math, re
from itertools import combinations_with_replacement as comb
from itertools import product
-from Rosetta import PID
+from __init__ import PID
####################################################################################################
# Higgs basis class
class HiggsBasis(Basis):
independent = ['dCw','dCz','Cgg','Czz','Caa','Cza','CTgg','CTzz','CTaa','CTza',
'dYu11','dYu12','dYu13','dYu22','dYu23','dYu33',
'dYd11','dYd12','dYd13','dYd22','dYd23','dYd33',
'Su11','Su12','Su13','Su22','Su23','Su33',
'Sd11','Sd12','Sd13','Sd22','Sd23','Sd33',
'dYe11','dYe12','dYe13','dYe22','dYe23','dYe33',
'Se11','Se12','Se13','Se22','Se23','Se33',
'dGLze11','dGLze12','dGLze13','dGLze22','dGLze23','dGLze33',
'dGRze11','dGRze12','dGRze13','dGRze22','dGRze23','dGRze33',
'dGLzu11','dGLzu12','dGLzu13','dGLzu22','dGLzu23','dGLzu33',
'dGLzd11','dGLzd12','dGLzd13','dGLzd22','dGLzd23','dGLzd33',
'dGRzu11','dGRzu12','dGRzu13','dGRzu22','dGRzu23','dGRzu33',
'dGRzd11','dGRzd12','dGRzd13','dGRzd22','dGRzd23','dGRzd33',
'dGLwl11','dGLwl12','dGLwl13','dGLwl22','dGLwl23','dGLwl33',
'dGRwq11','dGRwq12','dGRwq13','dGRwq22','dGRwq23','dGRwq33','dM']
dependent = ['Cww','CTww',
'dGLzv11','dGLzv12','dGLzv13','dGLzv22','dGLzv23','dGLzv33',
'dGLwq11','dGLwq12','dGLwq13','dGLwq22','dGLwq23','dGLwq33',
'CLwq11','CLwq12','CLwq13','CLwq22','CLwq23','CLwq33',
'CRwq11','CRwq12','CRwq13','CRwq22','CRwq23','CRwq33',
'CLwl11','CLwl12','CLwl13','CLwl22','CLwl23','CLwl33',
'CLze11','CLze12','CLze13','CLze22','CLze23','CLze33',
'CLzv11','CLzv12','CLzv13','CLzv22','CLzv23','CLzv33',
'CRze11','CRze12','CRze13','CRze22','CRze23','CRze33',
'CLzu11','CLzu12','CLzu13','CLzu22','CLzu23','CLzu33',
'CLzd11','CLzd12','CLzd13','CLzd22','CLzd23','CLzd33',
'CRzu11','CRzu12','CRzu13','CRzu22','CRzu23','CRzu33',
'CRzd11','CRzd12','CRzd13','CRzd22','CRzd23','CRzd33']
required_masses = {1, 2, 3, 4, 5, 6, 11, 12, 13, 14, 15, 16}
required_inputs = {1, 2, 4} # aEWM1, Gf, MZ
def calculate_inputs(self): # calculate a few required EW params from aEWM1, Gf, MZ
self.input['ee2'] = 4.*math.pi/self.input['aEWM1'] # EM coupling squared
self.input['s2w'] = (1.- math.sqrt(1. - self.input['ee2']/(math.sqrt(2.)*self.input['Gf']*self.input['MZ']**2)))/2. #sin^2(theta_W)
self.input['gw2'] = self.input['ee2']/self.input['s2w'] # SU(2) coupling squared
self.input['gp2'] = self.input['gw2']*self.input['s2w']/(1.-self.input['s2w']) # Hypercharge coupling squared
def calculate_dependent(self): # calculate dependent parameters
p = self.par_dict
self.calculate_inputs() # set a few useful EW parameters
s2w, ee2, gw2, gp2 = tuple([self.input[x] for x in ('s2w', 'ee2', 'gw2', 'gp2')]) # get EW params
def hVff(cname): # calculate hVff coeffs [eqn (3.11)]
def T3(f,chi): # return t3
t3 = {'u':0.5,'d':-0.5,'v':0.5,'e':-0.5}
return 0. if chi=='R' else t3[f]
def Y(f,chi): # return hypercharge
y = {'u':{'L':1./6.,'R':2./3.},'d':{'L':1./6.,'R':-1./3.},'v':{'L':-0.5,'R':0.},'e':{'L':-0.5,'R':-1.}}
return y[f][chi]
match = re.match(r'C(\w)(\w)(\w)(\d)(\d)',cname) # parse coefficient name
chi, V, f, i,j = tuple([match.group(i) for i in range(1,6)])
dgV = cname.replace('C','dG') # corresponding V coupling deviation
cVff = p[dgV]
if i==j: # diagonal part
if V=='z':
cVff += ( (p['dCw'] - p['dCz'] - 4*p['dM'])*( T3(f,chi)*gw2/gp2 + Y(f,chi) ) \
+ T3(f,chi)*gw2*( p['Caa']*ee2/(gw2+gp2) + p['Cza']*(gw2-gp2)/(gw2+gp2) -p['Czz'] ))/2.
elif V=='z' and chi=='L':
cVff +=( (p['dCw'] - p['dCz'] - 4*p['dM'])*gw2/gp2 \
+ gw2*( p['Caa']*ee2/(gw2+gp2) + p['Cza']*(gw2-gp2)/(gw2+gp2) - p['Czz'] ))/2.
return cVff
p['Cww'] = p['Czz'] + 2.*s2w*p['Cza'] + s2w**2*p['Caa'] # Cww [eqn (3.9)]
p['CTww'] = p['CTzz'] + 2.*s2w*p['CTza'] + s2w**2*p['CTaa'] # Ctww [eqn (3.9)]
for i,j in comb((1,2,3),2):# dependent dgV coeffs [eqn (3.7)]
p['dGLzv{}{}'.format(i,j)] = p['dGLze{}{}'.format(i,j)] + p['dGLwl{}{}'.format(i,j)]
p['dGLwq{}{}'.format(i,j)] = p['dGLzu{}{}'.format(i,j)] - p['dGLzd{}{}'.format(i,j)]
for f,chi in product(('u','d','e','v'),('L','R')): # hVff 4-point coeffs [eqn (3.11)]
if f=='v' and chi=='R': continue
cvff = 'C{}z{}{}{}'.format(chi,f,i,j)
p[cvff] = hVff(cvff)
for f,chi in (('q','L'),('q','R'),('l','L')):
cvff = 'C{}w{}{}{}'.format(chi,f,i,j)
p[cvff] = hVff(cvff)
####################################################################################################
diff --git a/Rosetta/TemplateBasis.py b/Rosetta/TemplateBasis.py
index 9487754..589ff98 100644
--- a/Rosetta/TemplateBasis.py
+++ b/Rosetta/TemplateBasis.py
@@ -1,46 +1,65 @@
from Basis import Basis
from MassBasis import MassBasis
+from eHDECAY import eHDECAY
+from __init__ import default_masses as dm, default_inputs as di
+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'])
+ B[k] = self.myfunc( A['d'], self.mass[6], self.input['aEWM1'] )
self.newmass[23]=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
+ 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/__init__.py b/Rosetta/__init__.py
index 380a767..7efddc4 100644
--- a/Rosetta/__init__.py
+++ b/Rosetta/__init__.py
@@ -1,17 +1,21 @@
####################################################################################################
# PDG ID dictionary
PID = {'u':{1:1 ,2:4, 3:6},'d':{1:2, 2:3, 3:5},'e':{1:11, 2:13, 3:15},'v':{1:12, 2:14, 3:16}}
-
+# PID:name dictionary for particles
particle_names = {1:'u', 2:'d', 3:'s', 4:'c', 5:'b', 6:'t', 11:'e', 12:'ve', 13:'mu',
14:'vmu', 15:'ta', 16:'vta', 21:'a', 22:'g', 23:'Z', 24:'W', 25:'H'}
-
+# ID:name dictionary for SLHA inputs
input_names = {1:'aEWM1', 2:'Gf', 3:'aS', 4:'MZ', 5:'MB', 6:'MT', 7:'MTAU', 8:'MH'}
-
+# ID:PID dictionary for SLHA inputs that are particle masses
input_to_PID = {4:23, 5:5, 6:6, 7:15, 8:25}
-
-default_masses = {1:0., 2:0., 3:0., 4:0., 5:4.7, 6:173., 11:0., 12:0., 13:0., 14:0., 15:1.77, 16:0.}
-
-default_inputs = {1: 1.325070e+02, 2: 1.166390e-05, 3: 1.180000e-01, 4: 9.118800e+01,
+# PID:value dictionary for default particle masses when undefined
+default_masses = {1:0., 2:0., 3:0., 4:1.42, 5:4.7, 6:173.,
+ 11:0., 12:0., 13:0.105658367, 14:0., 15:1.77, 16:0.,
+ 23:7.982400e+01, 24:9.118800e+01, 25:125.}
+# ID:value dictionary for default SHLA inputs when undefined
+default_inputs = {1: 1.325070e+02, 2: 1.166390e-05, 3: 1.180000e-01, 4: default_masses[24],
5: default_masses[5], 6: default_masses[6], 7: default_masses[15],
- 8:7.982400e+01, 9:1.25e+02 }
+ 8:default_masses[23], 9:default_masses[25] }
####################################################################################################
+eHDECAY_dir = '/Users/Ken/Work/Packages/Higgs/eHDECAY'
+####################################################################################################
\ No newline at end of file
diff --git a/Rosetta/eHDECAY.py b/Rosetta/eHDECAY.py
new file mode 100644
index 0000000..f58751e
--- /dev/null
+++ b/Rosetta/eHDECAY.py
@@ -0,0 +1,158 @@
+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
+
+def eHDECAY(basis):
+ print 'Running eHDECAY'
+ input_dict = basis.eHDECAY_inputs()
+ 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])
+ 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)
+
+
+

File Metadata

Mime Type
text/x-diff
Expires
Tue, Nov 19, 7:07 PM (1 d, 9 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
3800762
Default Alt Text
(45 KB)

Event Timeline