Top

ScanLHA.config module

Maps (S)LHA syntax onto YAML as well as stores configs for scanning and plotting.

"""
Maps (S)LHA syntax onto YAML as well as stores configs for scanning and plotting.
"""
from numpy import linspace, logspace, geomspace, arange
from numpy.random import uniform, normal
import logging
import re
from sys import exit
import yaml
# scientific notation, see
# https://stackoverflow.com/questions/30458977/yaml-loads-5e-6-as-string-and-not-a-number
yaml.add_implicit_resolver(
    u'tag:yaml.org,2002:float',
    re.compile(u'''^(?:
     [-+]?(?:[0-9][0-9_]*)\\.[0-9_]*(?:[eE][-+]?[0-9]+)?
    |[-+]?(?:[0-9][0-9_]*)(?:[eE][-+]?[0-9]+)
    |\\.[0-9_]+(?:[eE][-+][0-9]+)?
    |[-+]?[0-9][0-9_]*(?:[0-5]?[0-9])+\\.[0-9_]*
    |[-+]?\\.(?:inf|Inf|INF)
    |\\.(?:nan|NaN|NAN))$''', re.X),
    list(u'-+0123456789.'))

def intersect(list1,list2):
    """ Returns intersection of two lists """
    return list(set(list1) & set(list2))
__all__ = ['Config']
class Config(dict):
    """
    A dict-like object that carries information about LHA file(s), programs that import/export LHA files, and plots.

      1. LHA blocks are stored in the key `'blocks'`.

      2. Information about the scan to perform and used programs is stored in the key `'runner'`.

      3. Information about the plots is stored in the key `'scatterplot'`.

    Example for accessing LHA entries:

        In [1]: from ScanLHA import Config
        In [2]: c=Config('SPheno.yml')
        In [3]: c.parameters # contains all LHA entries using unique parameter identifiers
        In [4]: c['MODSEL'] # returns the whole MODSEL block
        In [5]: c['MODSEL.1'] # line with LHA id=1 from block MODSEL
        In [6]: c['MODSEL.values.1'] # value to which the LHA id=1 in the block MODSEL is set
        In [7]: c['TanBeta'] # return the line which is associated with the parameter TanBeta
        Out[7]:
        {'id': 4,
         'latex': '$\\tan\\beta$',
         'lha': 'MINPAR.values.4',
         'parameter': 'TanBeta',
         'values': [1,2,3,4]}

    Example for `'runner'` (more see `ScanLHA.runner`):

        ---
        runner:
        binaries:
            - [ '/home/user/SPheno/bin/SPhenoMSSM', '{input_file}', '{output_file}']
            - [ '/home/user/HiggsBounds-4.3.1/HiggsBounds',  'LandH', 'SLHA', '3', '0', '{output_file}']
        micromegas:
            src: '/home/user/micrOMEGAS/src'
            modelname: 'MSSM'
            main: 'CalcOmegaDD.cpp'
            exec: ['CalcOmegaDD', '{output_file}']
        type: MicrOmegas
        cleanup: false
        keep_log: true
        remove_slha: true

    Example for `'blocks'`:

        ---
        blocks:
        - block: MINPAR
          lines:
              - parameter: 'MSUSY'
                id: 1
                scan:  [2e3, 2e4, 100]
                distribution: 'geom'
              - parameter: 'TanBeta'
                latex: '$\\tan\\beta$'
                id: 2
                value: 4
              - ..

    Example for `'scatterplot'` (more see `ScanLHA.PlotLHA`):

        ---
        scatterplot:
            conf:
                datafile: "results.h5"
                newfields:
                    TanBeta: "DATA['HMIX.values.11'].apply(abs).apply(tan)"
                    M1: "DATA['MASS.values.1000022'].apply(abs)"
                    M2: "DATA['MASS.values.1000023'].apply(abs)"
                    Mdiff: "DATA['MASS.values.1000023'].apply(abs)-DATA['MASS.values.1000022'].apply(abs)"
                dpi: 200
                x-axis: {
                    field: 'MSUSY',
                    lognorm: True,
                    label: "$m_{SUSY}$ [TeV]",
                    ticks: [[2000, 3000, 6000, 10000, 20000], ['$2$','$3$', '$6$', '$10$', '$20$']]
                    }
            plots:
                - filename: 'masses.png'
                  alpha: 0.8
                  legend: {'loc':'right'}
                  y-axis: {label: '$Mass$ [GeV]', lognorm: True }
                  textbox: {x: 0.94, y: 0.35, text: 'some info text', fontsize: 12}
                  plots:
                      - {y-axis: 'M1', label: '$m_{\chi_1^0}$'}
                      - {y-axis: 'M2', label: '$m_{\chi_2^0}$'}
                      - {vline: True, x-field: 3000, lw: 2, color: 'black', alpha: 1}
                      - {vline: True, x-field: 6000, lw: 2, color: 'black', alpha: 1}
                - filename: diff.png
                  x-axis: {field: M1, label: 'm_{\chi_1^0}'}
                  y-axis: {field: M2, label: 'm_{\chi_2^0}'}
                  z-axis: {field: Mdiff, label: '\delta_m'}

    """

    def __init__(self,src):
        self.src = src
        self['runner'] = {}
        self['blocks'] = []
        self.distribution = {
                'linear': linspace,
                'log': logspace,
                'geom': geomspace,
                'arange': arange,
                'uniform': uniform,
                'normal': normal
                }
        self.valid = True
        self.parameters = {} # directly access a block item via 'parameter'
        self.load()

    def __getitem__(self, key):
        if key in self.keys():
            return self.get(key)
        if self.getBlock(key):
            return self.getBlock(key)
        if key in self.parameters:
            return self.parameters[key]
        dots = key.split('.') # access line e.g. via Config["MINPAR.1"]
        if len(dots) == 2:
            return self.getLine(dots[0], dots[1])
        if len(dots) == 3: # or value/scan/values via Config["MINPAR.values.1"]
            line = self.getLine(dots[0], int(dots[2]))
            if line and dots[1] in line.keys():
                return line.get(dots[1])
        raise KeyError('No valid config parameter: {}'.format(key))

    def load(self, src = None):
        """Load config from source file `src`.

        If the `ScanLHA.config.Config` instance was already loaded, information from the old `src` file is overwritten.

        After successfully loading the `ScanLHA.config.Config` instance it gets validated using `ScanLHA.config.Config.validate`.
        """
        src = self.src if not src else src
        try:
            with open(src, 'r') as c:
                new = yaml.safe_load(c)
                for i in intersect(new.keys(), self.keys()):
                    logging.debug('Overwriting config "{}".'.format(i))
                self.update(new)
                if not self.validate():
                    logging.error('Errorenous config file.')
                    exit(1)
        except FileNotFoundError:
            logging.error('File {} not found.'.format(src))
            self.valid = False
            return -2
        except Exception as e:
            logging.error("failed to load config file {}".format(src))
            logging.error(str(e))
            self.valid = False

    def save(self, dest = None):
        """Save `ScanLHA.config.Config` instance to destination file `dest`.
        If `dest==None` (default), `Config.src` is used."""
        dest = self.src if not dest else dest
        with open(dest, 'w') as f:
            f.write(yaml.dump(self))

    def append(self, c):
        """ Append information from another ScanLHA.Config instance <c>. """
        for b in ['runner', 'scatterplot']:
            if b in c and b in self:
                self[b].update(c[b])
            elif b in c and b not in self:
                self[b] = c[b]
        for b in c['blocks']:
            if not self.getBlock(b['block']):
                self.setBlock(b['block'], b['lines'])
            else:
                for l in b['lines']:
                    self.setLine(b['block'], l)
        return self.validate()

    def getBlock(self, block):
        """ Blocks are stored in a list of dicts. This method is to access blocks by their name.

        Example:

            In [1]: from ScanLHA import Config
            In [2]: c=Config('SPheno.yml')
            In [3]: c.getBlock('MODSEL')
            Out[3]:
            {'block': 'MODSEL',
               'lines': [{'id': 1,
                 'value': 1,
                 'parameter': 'MODSEL.1',
                 'latex': 'MODSEL.1',
                 'lha': 'MODSEL.values.1'},
                {'id': 2,
                 'value': 1,
                 'parameter': 'MODSEL.2',
                 'latex': 'MODSEL.2',
                 'lha': 'MODSEL.values.2'},
                {'id': 6,
                 'value': 1,
                 'parameter': 'MODSEL.6',
                 'latex': 'MODSEL.6',
                 'lha': 'MODSEL.values.6'}]}
        """
        blockpos = [i for i,b in enumerate(self['blocks']) if b['block'] == block]
        if not blockpos:
            return
        return self['blocks'][blockpos[0]]

    def getLine(self, block, id):
        """ Returns the line with the SLHA id `id` from the block `block`

        Example:

            In [1]: from ScanLHA import Config
            In [2]: c=Config('SPheno.yml')
            In [3]: c.getLine('MODSEL', 1)
            Out[3]:
            {'id': 1,
            'value': 1,
            'parameter': 'MODSEL.1',
            'latex': 'MODSEL.1',
            'lha': 'MODSEL.values.1'}
        """
        b = self.getBlock(block)
        if not b:
            logging.error('Block {} not present in config.'.format(block))
            return
        lines = b['lines']
        linepos = [i for i,l in enumerate(lines) if 'id' in l and l['id'] == id]
        if not linepos:
            return
        return lines[linepos[0]]

    def setBlock(self, block, lines=[]):
        """ Defines a SLHA block `block` with optional lines `lines`

        Example:

            In [1]: from ScanLHA import Config
            In [1]: c=Config('SPheno.yml')
            In [1]: Config.setBlock('MINPAR', lines=[{'id': 1, 'value': 1, 'parameter': 'TanBeta', 'latex': '\\tan\\beta'}, ...])
        """
        b = self.getBlock(block)
        if b:
            b['lines'] = lines
        else:
            self['blocks'].append({'block':block, 'lines': lines})
        return self.validate()

    def setLine(self, block, line):
        """ Add the `line` to the LHA `block`

        If the line already exists, the given keys are updated.

        Example:

            In [1]: from ScanLHA import Config
            In [2]: c=Config('SPheno.yml')
            In [3]: # use 1-loop RGEs
            In [4]: c.setLine('SPhenoInput', {'id': 38, 'value': 1})
        """
        b = self.getBlock(block)
        linepos = [i for i,l in enumerate(b['lines']) if 'id' in l and l['id'] == line['id']]
        if not b:
            return
        if not linepos:
            logging.debug('Appending new line with ID %d.' % line['id'])
            b['lines'].append(line)
        else:
            logging.debug('Updating line with ID %d.' % line['id'])
            b['lines'][linepos[0]] = line
        return self.validate()

    def validate(self):
        """ Validates the `ScanLHA.config.Config` instance and prepares further information attributes such as latex output.

        This method is applied after `ScanLHA.config.Config.load`, `ScanLHA.config.Config.setBlock`, `ScanLHA.config.Config.setLine` and `ScanLHA.config.Config.append`.
        """
        self.valid = True
        if 'blocks' not in self:
            logging.error("No 'blocks' section in config ")
            self.valid = False
        # check for double entries
        lines_seen = []
        self.parameters = {}
        for block in self['blocks']:
            if block['block'].count('.') > 0:
                logging.error('Block {} contains forbiddeni character "."!'.format(block['block']))
                self.valid = False
            for line in block['lines']:
                if 'id' not in line:
                    logging.error('No ID set for line entry!')
                    self.valid = False
                if [block['block'],line['id']] in lines_seen:
                    logging.error('Parameter {} in block {} set twice! Taking the first occurence.'.format(line['id'], block['block']))
                    self.valid = False
                if 'parameter' not in line:
                    line['parameter'] = '{}.{}'.format(block['block'],line['id'])
                elif line['parameter'] in self.parameters.keys():
                        para = line['parameter'] + '1'
                        logging.error('Parameter {} set twice! Renaming to {}.'.format(line['parameter'], para))
                        line['parameter'] = para
                        self.valid = False
                self.parameters[line['parameter']] = line
                if 'value' in line and line.get('dependent', False) and type(line['value']) != str:
                    print(line.get('dependent', False))
                    logging.error("'value' with attribute 'dependent' must be string not {} ({}, {}).".format(type(line['value']), block['block'], line['id']))
                    self.valid = False
                if 'value' in line and not line.get('dependent', False):
                    try:
                        float(line['value'])
                    except ValueError:
                        logging.error("'value' must be a number not {} ({}, {}).".format(str(type(line['value'])), block['block'], line['id']))
                        self.valid = False
                if 'values' in line and type(line['values']) != list and len(line['values']) < 1:
                    logging.error("'values' must be a nonemtpy list ({}, {}).".format(block['block'], line['id']))
                    self.valid = False
                if 'scan' in line and type(line['scan']) != list and len(line['scan']) < 2:
                    logging.error("'scan' must be a nonemtpy list ({}, {}).".format(block['block'], line['id']))
                    self.valid = False
                if 'latex' not in line:
                    line['latex'] = line['parameter']
                if 'lha' not in line:
                    line['lha'] = '{}.values.{}'.format(block['block'],line['id'])
                lines_seen.append([block['block'], line['id']])
        return self.valid

Classes

class Config

A dict-like object that carries information about LHA file(s), programs that import/export LHA files, and plots.

  1. LHA blocks are stored in the key 'blocks'.

  2. Information about the scan to perform and used programs is stored in the key 'runner'.

  3. Information about the plots is stored in the key 'scatterplot'.

Example for accessing LHA entries:

In [1]: from ScanLHA import Config
In [2]: c=Config('SPheno.yml')
In [3]: c.parameters # contains all LHA entries using unique parameter identifiers
In [4]: c['MODSEL'] # returns the whole MODSEL block
In [5]: c['MODSEL.1'] # line with LHA id=1 from block MODSEL
In [6]: c['MODSEL.values.1'] # value to which the LHA id=1 in the block MODSEL is set
In [7]: c['TanBeta'] # return the line which is associated with the parameter TanBeta
Out[7]:
{'id': 4,
 'latex': '$\tan\beta$',
 'lha': 'MINPAR.values.4',
 'parameter': 'TanBeta',
 'values': [1,2,3,4]}

Example for 'runner' (more see ScanLHA.runner):

---
runner:
binaries:
    - [ '/home/user/SPheno/bin/SPhenoMSSM', '{input_file}', '{output_file}']
    - [ '/home/user/HiggsBounds-4.3.1/HiggsBounds',  'LandH', 'SLHA', '3', '0', '{output_file}']
micromegas:
    src: '/home/user/micrOMEGAS/src'
    modelname: 'MSSM'
    main: 'CalcOmegaDD.cpp'
    exec: ['CalcOmegaDD', '{output_file}']
type: MicrOmegas
cleanup: false
keep_log: true
remove_slha: true

Example for 'blocks':

---
blocks:
- block: MINPAR
  lines:
      - parameter: 'MSUSY'
        id: 1
        scan:  [2e3, 2e4, 100]
        distribution: 'geom'
      - parameter: 'TanBeta'
        latex: '$\tan\beta$'
        id: 2
        value: 4
      - ..

Example for 'scatterplot' (more see ScanLHA.PlotLHA):

---
scatterplot:
    conf:
        datafile: "results.h5"
        newfields:
            TanBeta: "DATA['HMIX.values.11'].apply(abs).apply(tan)"
            M1: "DATA['MASS.values.1000022'].apply(abs)"
            M2: "DATA['MASS.values.1000023'].apply(abs)"
            Mdiff: "DATA['MASS.values.1000023'].apply(abs)-DATA['MASS.values.1000022'].apply(abs)"
        dpi: 200
        x-axis: {
            field: 'MSUSY',
            lognorm: True,
            label: "$m_{SUSY}$ [TeV]",
            ticks: [[2000, 3000, 6000, 10000, 20000], ['$2$','$3$', '$6$', '$10$', '$20$']]
            }
    plots:
        - filename: 'masses.png'
          alpha: 0.8
          legend: {'loc':'right'}
          y-axis: {label: '$Mass$ [GeV]', lognorm: True }
          textbox: {x: 0.94, y: 0.35, text: 'some info text', fontsize: 12}
          plots:
              - {y-axis: 'M1', label: '$m_{\chi_1^0}$'}
              - {y-axis: 'M2', label: '$m_{\chi_2^0}$'}
              - {vline: True, x-field: 3000, lw: 2, color: 'black', alpha: 1}
              - {vline: True, x-field: 6000, lw: 2, color: 'black', alpha: 1}
        - filename: diff.png
          x-axis: {field: M1, label: 'm_{\chi_1^0}'}
          y-axis: {field: M2, label: 'm_{\chi_2^0}'}
          z-axis: {field: Mdiff, label: '\delta_m'}
class Config(dict):
    """
    A dict-like object that carries information about LHA file(s), programs that import/export LHA files, and plots.

      1. LHA blocks are stored in the key `'blocks'`.

      2. Information about the scan to perform and used programs is stored in the key `'runner'`.

      3. Information about the plots is stored in the key `'scatterplot'`.

    Example for accessing LHA entries:

        In [1]: from ScanLHA import Config
        In [2]: c=Config('SPheno.yml')
        In [3]: c.parameters # contains all LHA entries using unique parameter identifiers
        In [4]: c['MODSEL'] # returns the whole MODSEL block
        In [5]: c['MODSEL.1'] # line with LHA id=1 from block MODSEL
        In [6]: c['MODSEL.values.1'] # value to which the LHA id=1 in the block MODSEL is set
        In [7]: c['TanBeta'] # return the line which is associated with the parameter TanBeta
        Out[7]:
        {'id': 4,
         'latex': '$\\tan\\beta$',
         'lha': 'MINPAR.values.4',
         'parameter': 'TanBeta',
         'values': [1,2,3,4]}

    Example for `'runner'` (more see `ScanLHA.runner`):

        ---
        runner:
        binaries:
            - [ '/home/user/SPheno/bin/SPhenoMSSM', '{input_file}', '{output_file}']
            - [ '/home/user/HiggsBounds-4.3.1/HiggsBounds',  'LandH', 'SLHA', '3', '0', '{output_file}']
        micromegas:
            src: '/home/user/micrOMEGAS/src'
            modelname: 'MSSM'
            main: 'CalcOmegaDD.cpp'
            exec: ['CalcOmegaDD', '{output_file}']
        type: MicrOmegas
        cleanup: false
        keep_log: true
        remove_slha: true

    Example for `'blocks'`:

        ---
        blocks:
        - block: MINPAR
          lines:
              - parameter: 'MSUSY'
                id: 1
                scan:  [2e3, 2e4, 100]
                distribution: 'geom'
              - parameter: 'TanBeta'
                latex: '$\\tan\\beta$'
                id: 2
                value: 4
              - ..

    Example for `'scatterplot'` (more see `ScanLHA.PlotLHA`):

        ---
        scatterplot:
            conf:
                datafile: "results.h5"
                newfields:
                    TanBeta: "DATA['HMIX.values.11'].apply(abs).apply(tan)"
                    M1: "DATA['MASS.values.1000022'].apply(abs)"
                    M2: "DATA['MASS.values.1000023'].apply(abs)"
                    Mdiff: "DATA['MASS.values.1000023'].apply(abs)-DATA['MASS.values.1000022'].apply(abs)"
                dpi: 200
                x-axis: {
                    field: 'MSUSY',
                    lognorm: True,
                    label: "$m_{SUSY}$ [TeV]",
                    ticks: [[2000, 3000, 6000, 10000, 20000], ['$2$','$3$', '$6$', '$10$', '$20$']]
                    }
            plots:
                - filename: 'masses.png'
                  alpha: 0.8
                  legend: {'loc':'right'}
                  y-axis: {label: '$Mass$ [GeV]', lognorm: True }
                  textbox: {x: 0.94, y: 0.35, text: 'some info text', fontsize: 12}
                  plots:
                      - {y-axis: 'M1', label: '$m_{\chi_1^0}$'}
                      - {y-axis: 'M2', label: '$m_{\chi_2^0}$'}
                      - {vline: True, x-field: 3000, lw: 2, color: 'black', alpha: 1}
                      - {vline: True, x-field: 6000, lw: 2, color: 'black', alpha: 1}
                - filename: diff.png
                  x-axis: {field: M1, label: 'm_{\chi_1^0}'}
                  y-axis: {field: M2, label: 'm_{\chi_2^0}'}
                  z-axis: {field: Mdiff, label: '\delta_m'}

    """

    def __init__(self,src):
        self.src = src
        self['runner'] = {}
        self['blocks'] = []
        self.distribution = {
                'linear': linspace,
                'log': logspace,
                'geom': geomspace,
                'arange': arange,
                'uniform': uniform,
                'normal': normal
                }
        self.valid = True
        self.parameters = {} # directly access a block item via 'parameter'
        self.load()

    def __getitem__(self, key):
        if key in self.keys():
            return self.get(key)
        if self.getBlock(key):
            return self.getBlock(key)
        if key in self.parameters:
            return self.parameters[key]
        dots = key.split('.') # access line e.g. via Config["MINPAR.1"]
        if len(dots) == 2:
            return self.getLine(dots[0], dots[1])
        if len(dots) == 3: # or value/scan/values via Config["MINPAR.values.1"]
            line = self.getLine(dots[0], int(dots[2]))
            if line and dots[1] in line.keys():
                return line.get(dots[1])
        raise KeyError('No valid config parameter: {}'.format(key))

    def load(self, src = None):
        """Load config from source file `src`.

        If the `ScanLHA.config.Config` instance was already loaded, information from the old `src` file is overwritten.

        After successfully loading the `ScanLHA.config.Config` instance it gets validated using `ScanLHA.config.Config.validate`.
        """
        src = self.src if not src else src
        try:
            with open(src, 'r') as c:
                new = yaml.safe_load(c)
                for i in intersect(new.keys(), self.keys()):
                    logging.debug('Overwriting config "{}".'.format(i))
                self.update(new)
                if not self.validate():
                    logging.error('Errorenous config file.')
                    exit(1)
        except FileNotFoundError:
            logging.error('File {} not found.'.format(src))
            self.valid = False
            return -2
        except Exception as e:
            logging.error("failed to load config file {}".format(src))
            logging.error(str(e))
            self.valid = False

    def save(self, dest = None):
        """Save `ScanLHA.config.Config` instance to destination file `dest`.
        If `dest==None` (default), `Config.src` is used."""
        dest = self.src if not dest else dest
        with open(dest, 'w') as f:
            f.write(yaml.dump(self))

    def append(self, c):
        """ Append information from another ScanLHA.Config instance <c>. """
        for b in ['runner', 'scatterplot']:
            if b in c and b in self:
                self[b].update(c[b])
            elif b in c and b not in self:
                self[b] = c[b]
        for b in c['blocks']:
            if not self.getBlock(b['block']):
                self.setBlock(b['block'], b['lines'])
            else:
                for l in b['lines']:
                    self.setLine(b['block'], l)
        return self.validate()

    def getBlock(self, block):
        """ Blocks are stored in a list of dicts. This method is to access blocks by their name.

        Example:

            In [1]: from ScanLHA import Config
            In [2]: c=Config('SPheno.yml')
            In [3]: c.getBlock('MODSEL')
            Out[3]:
            {'block': 'MODSEL',
               'lines': [{'id': 1,
                 'value': 1,
                 'parameter': 'MODSEL.1',
                 'latex': 'MODSEL.1',
                 'lha': 'MODSEL.values.1'},
                {'id': 2,
                 'value': 1,
                 'parameter': 'MODSEL.2',
                 'latex': 'MODSEL.2',
                 'lha': 'MODSEL.values.2'},
                {'id': 6,
                 'value': 1,
                 'parameter': 'MODSEL.6',
                 'latex': 'MODSEL.6',
                 'lha': 'MODSEL.values.6'}]}
        """
        blockpos = [i for i,b in enumerate(self['blocks']) if b['block'] == block]
        if not blockpos:
            return
        return self['blocks'][blockpos[0]]

    def getLine(self, block, id):
        """ Returns the line with the SLHA id `id` from the block `block`

        Example:

            In [1]: from ScanLHA import Config
            In [2]: c=Config('SPheno.yml')
            In [3]: c.getLine('MODSEL', 1)
            Out[3]:
            {'id': 1,
            'value': 1,
            'parameter': 'MODSEL.1',
            'latex': 'MODSEL.1',
            'lha': 'MODSEL.values.1'}
        """
        b = self.getBlock(block)
        if not b:
            logging.error('Block {} not present in config.'.format(block))
            return
        lines = b['lines']
        linepos = [i for i,l in enumerate(lines) if 'id' in l and l['id'] == id]
        if not linepos:
            return
        return lines[linepos[0]]

    def setBlock(self, block, lines=[]):
        """ Defines a SLHA block `block` with optional lines `lines`

        Example:

            In [1]: from ScanLHA import Config
            In [1]: c=Config('SPheno.yml')
            In [1]: Config.setBlock('MINPAR', lines=[{'id': 1, 'value': 1, 'parameter': 'TanBeta', 'latex': '\\tan\\beta'}, ...])
        """
        b = self.getBlock(block)
        if b:
            b['lines'] = lines
        else:
            self['blocks'].append({'block':block, 'lines': lines})
        return self.validate()

    def setLine(self, block, line):
        """ Add the `line` to the LHA `block`

        If the line already exists, the given keys are updated.

        Example:

            In [1]: from ScanLHA import Config
            In [2]: c=Config('SPheno.yml')
            In [3]: # use 1-loop RGEs
            In [4]: c.setLine('SPhenoInput', {'id': 38, 'value': 1})
        """
        b = self.getBlock(block)
        linepos = [i for i,l in enumerate(b['lines']) if 'id' in l and l['id'] == line['id']]
        if not b:
            return
        if not linepos:
            logging.debug('Appending new line with ID %d.' % line['id'])
            b['lines'].append(line)
        else:
            logging.debug('Updating line with ID %d.' % line['id'])
            b['lines'][linepos[0]] = line
        return self.validate()

    def validate(self):
        """ Validates the `ScanLHA.config.Config` instance and prepares further information attributes such as latex output.

        This method is applied after `ScanLHA.config.Config.load`, `ScanLHA.config.Config.setBlock`, `ScanLHA.config.Config.setLine` and `ScanLHA.config.Config.append`.
        """
        self.valid = True
        if 'blocks' not in self:
            logging.error("No 'blocks' section in config ")
            self.valid = False
        # check for double entries
        lines_seen = []
        self.parameters = {}
        for block in self['blocks']:
            if block['block'].count('.') > 0:
                logging.error('Block {} contains forbiddeni character "."!'.format(block['block']))
                self.valid = False
            for line in block['lines']:
                if 'id' not in line:
                    logging.error('No ID set for line entry!')
                    self.valid = False
                if [block['block'],line['id']] in lines_seen:
                    logging.error('Parameter {} in block {} set twice! Taking the first occurence.'.format(line['id'], block['block']))
                    self.valid = False
                if 'parameter' not in line:
                    line['parameter'] = '{}.{}'.format(block['block'],line['id'])
                elif line['parameter'] in self.parameters.keys():
                        para = line['parameter'] + '1'
                        logging.error('Parameter {} set twice! Renaming to {}.'.format(line['parameter'], para))
                        line['parameter'] = para
                        self.valid = False
                self.parameters[line['parameter']] = line
                if 'value' in line and line.get('dependent', False) and type(line['value']) != str:
                    print(line.get('dependent', False))
                    logging.error("'value' with attribute 'dependent' must be string not {} ({}, {}).".format(type(line['value']), block['block'], line['id']))
                    self.valid = False
                if 'value' in line and not line.get('dependent', False):
                    try:
                        float(line['value'])
                    except ValueError:
                        logging.error("'value' must be a number not {} ({}, {}).".format(str(type(line['value'])), block['block'], line['id']))
                        self.valid = False
                if 'values' in line and type(line['values']) != list and len(line['values']) < 1:
                    logging.error("'values' must be a nonemtpy list ({}, {}).".format(block['block'], line['id']))
                    self.valid = False
                if 'scan' in line and type(line['scan']) != list and len(line['scan']) < 2:
                    logging.error("'scan' must be a nonemtpy list ({}, {}).".format(block['block'], line['id']))
                    self.valid = False
                if 'latex' not in line:
                    line['latex'] = line['parameter']
                if 'lha' not in line:
                    line['lha'] = '{}.values.{}'.format(block['block'],line['id'])
                lines_seen.append([block['block'], line['id']])
        return self.valid

Ancestors (in MRO)

  • Config
  • builtins.dict
  • builtins.object

Static methods

def __init__(

self, src)

Initialize self. See help(type(self)) for accurate signature.

def __init__(self,src):
    self.src = src
    self['runner'] = {}
    self['blocks'] = []
    self.distribution = {
            'linear': linspace,
            'log': logspace,
            'geom': geomspace,
            'arange': arange,
            'uniform': uniform,
            'normal': normal
            }
    self.valid = True
    self.parameters = {} # directly access a block item via 'parameter'
    self.load()

def append(

self, c)

Append information from another ScanLHA.Config instance .

def append(self, c):
    """ Append information from another ScanLHA.Config instance <c>. """
    for b in ['runner', 'scatterplot']:
        if b in c and b in self:
            self[b].update(c[b])
        elif b in c and b not in self:
            self[b] = c[b]
    for b in c['blocks']:
        if not self.getBlock(b['block']):
            self.setBlock(b['block'], b['lines'])
        else:
            for l in b['lines']:
                self.setLine(b['block'], l)
    return self.validate()

def getBlock(

self, block)

Blocks are stored in a list of dicts. This method is to access blocks by their name.

Example:

In [1]: from ScanLHA import Config
In [2]: c=Config('SPheno.yml')
In [3]: c.getBlock('MODSEL')
Out[3]:
{'block': 'MODSEL',
   'lines': [{'id': 1,
     'value': 1,
     'parameter': 'MODSEL.1',
     'latex': 'MODSEL.1',
     'lha': 'MODSEL.values.1'},
    {'id': 2,
     'value': 1,
     'parameter': 'MODSEL.2',
     'latex': 'MODSEL.2',
     'lha': 'MODSEL.values.2'},
    {'id': 6,
     'value': 1,
     'parameter': 'MODSEL.6',
     'latex': 'MODSEL.6',
     'lha': 'MODSEL.values.6'}]}
def getBlock(self, block):
    """ Blocks are stored in a list of dicts. This method is to access blocks by their name.
    Example:
        In [1]: from ScanLHA import Config
        In [2]: c=Config('SPheno.yml')
        In [3]: c.getBlock('MODSEL')
        Out[3]:
        {'block': 'MODSEL',
           'lines': [{'id': 1,
             'value': 1,
             'parameter': 'MODSEL.1',
             'latex': 'MODSEL.1',
             'lha': 'MODSEL.values.1'},
            {'id': 2,
             'value': 1,
             'parameter': 'MODSEL.2',
             'latex': 'MODSEL.2',
             'lha': 'MODSEL.values.2'},
            {'id': 6,
             'value': 1,
             'parameter': 'MODSEL.6',
             'latex': 'MODSEL.6',
             'lha': 'MODSEL.values.6'}]}
    """
    blockpos = [i for i,b in enumerate(self['blocks']) if b['block'] == block]
    if not blockpos:
        return
    return self['blocks'][blockpos[0]]

def getLine(

self, block, id)

Returns the line with the SLHA id id from the block block

Example:

In [1]: from ScanLHA import Config
In [2]: c=Config('SPheno.yml')
In [3]: c.getLine('MODSEL', 1)
Out[3]:
{'id': 1,
'value': 1,
'parameter': 'MODSEL.1',
'latex': 'MODSEL.1',
'lha': 'MODSEL.values.1'}
def getLine(self, block, id):
    """ Returns the line with the SLHA id `id` from the block `block`
    Example:
        In [1]: from ScanLHA import Config
        In [2]: c=Config('SPheno.yml')
        In [3]: c.getLine('MODSEL', 1)
        Out[3]:
        {'id': 1,
        'value': 1,
        'parameter': 'MODSEL.1',
        'latex': 'MODSEL.1',
        'lha': 'MODSEL.values.1'}
    """
    b = self.getBlock(block)
    if not b:
        logging.error('Block {} not present in config.'.format(block))
        return
    lines = b['lines']
    linepos = [i for i,l in enumerate(lines) if 'id' in l and l['id'] == id]
    if not linepos:
        return
    return lines[linepos[0]]

def load(

self, src=None)

Load config from source file src.

If the Config instance was already loaded, information from the old src file is overwritten.

After successfully loading the Config instance it gets validated using validate.

def load(self, src = None):
    """Load config from source file `src`.
    If the `ScanLHA.config.Config` instance was already loaded, information from the old `src` file is overwritten.
    After successfully loading the `ScanLHA.config.Config` instance it gets validated using `ScanLHA.config.Config.validate`.
    """
    src = self.src if not src else src
    try:
        with open(src, 'r') as c:
            new = yaml.safe_load(c)
            for i in intersect(new.keys(), self.keys()):
                logging.debug('Overwriting config "{}".'.format(i))
            self.update(new)
            if not self.validate():
                logging.error('Errorenous config file.')
                exit(1)
    except FileNotFoundError:
        logging.error('File {} not found.'.format(src))
        self.valid = False
        return -2
    except Exception as e:
        logging.error("failed to load config file {}".format(src))
        logging.error(str(e))
        self.valid = False

def save(

self, dest=None)

Save Config instance to destination file dest. If dest==None (default), Config.src is used.

def save(self, dest = None):
    """Save `ScanLHA.config.Config` instance to destination file `dest`.
    If `dest==None` (default), `Config.src` is used."""
    dest = self.src if not dest else dest
    with open(dest, 'w') as f:
        f.write(yaml.dump(self))

def setBlock(

self, block, lines=[])

Defines a SLHA block block with optional lines lines

Example:

In [1]: from ScanLHA import Config
In [1]: c=Config('SPheno.yml')
In [1]: Config.setBlock('MINPAR', lines=[{'id': 1, 'value': 1, 'parameter': 'TanBeta', 'latex': '\tan\beta'}, ...])
def setBlock(self, block, lines=[]):
    """ Defines a SLHA block `block` with optional lines `lines`
    Example:
        In [1]: from ScanLHA import Config
        In [1]: c=Config('SPheno.yml')
        In [1]: Config.setBlock('MINPAR', lines=[{'id': 1, 'value': 1, 'parameter': 'TanBeta', 'latex': '\\tan\\beta'}, ...])
    """
    b = self.getBlock(block)
    if b:
        b['lines'] = lines
    else:
        self['blocks'].append({'block':block, 'lines': lines})
    return self.validate()

def setLine(

self, block, line)

Add the line to the LHA block

If the line already exists, the given keys are updated.

Example:

In [1]: from ScanLHA import Config
In [2]: c=Config('SPheno.yml')
In [3]: # use 1-loop RGEs
In [4]: c.setLine('SPhenoInput', {'id': 38, 'value': 1})
def setLine(self, block, line):
    """ Add the `line` to the LHA `block`
    If the line already exists, the given keys are updated.
    Example:
        In [1]: from ScanLHA import Config
        In [2]: c=Config('SPheno.yml')
        In [3]: # use 1-loop RGEs
        In [4]: c.setLine('SPhenoInput', {'id': 38, 'value': 1})
    """
    b = self.getBlock(block)
    linepos = [i for i,l in enumerate(b['lines']) if 'id' in l and l['id'] == line['id']]
    if not b:
        return
    if not linepos:
        logging.debug('Appending new line with ID %d.' % line['id'])
        b['lines'].append(line)
    else:
        logging.debug('Updating line with ID %d.' % line['id'])
        b['lines'][linepos[0]] = line
    return self.validate()

def validate(

self)

Validates the Config instance and prepares further information attributes such as latex output.

This method is applied after load, setBlock, setLine and append.

def validate(self):
    """ Validates the `ScanLHA.config.Config` instance and prepares further information attributes such as latex output.
    This method is applied after `ScanLHA.config.Config.load`, `ScanLHA.config.Config.setBlock`, `ScanLHA.config.Config.setLine` and `ScanLHA.config.Config.append`.
    """
    self.valid = True
    if 'blocks' not in self:
        logging.error("No 'blocks' section in config ")
        self.valid = False
    # check for double entries
    lines_seen = []
    self.parameters = {}
    for block in self['blocks']:
        if block['block'].count('.') > 0:
            logging.error('Block {} contains forbiddeni character "."!'.format(block['block']))
            self.valid = False
        for line in block['lines']:
            if 'id' not in line:
                logging.error('No ID set for line entry!')
                self.valid = False
            if [block['block'],line['id']] in lines_seen:
                logging.error('Parameter {} in block {} set twice! Taking the first occurence.'.format(line['id'], block['block']))
                self.valid = False
            if 'parameter' not in line:
                line['parameter'] = '{}.{}'.format(block['block'],line['id'])
            elif line['parameter'] in self.parameters.keys():
                    para = line['parameter'] + '1'
                    logging.error('Parameter {} set twice! Renaming to {}.'.format(line['parameter'], para))
                    line['parameter'] = para
                    self.valid = False
            self.parameters[line['parameter']] = line
            if 'value' in line and line.get('dependent', False) and type(line['value']) != str:
                print(line.get('dependent', False))
                logging.error("'value' with attribute 'dependent' must be string not {} ({}, {}).".format(type(line['value']), block['block'], line['id']))
                self.valid = False
            if 'value' in line and not line.get('dependent', False):
                try:
                    float(line['value'])
                except ValueError:
                    logging.error("'value' must be a number not {} ({}, {}).".format(str(type(line['value'])), block['block'], line['id']))
                    self.valid = False
            if 'values' in line and type(line['values']) != list and len(line['values']) < 1:
                logging.error("'values' must be a nonemtpy list ({}, {}).".format(block['block'], line['id']))
                self.valid = False
            if 'scan' in line and type(line['scan']) != list and len(line['scan']) < 2:
                logging.error("'scan' must be a nonemtpy list ({}, {}).".format(block['block'], line['id']))
                self.valid = False
            if 'latex' not in line:
                line['latex'] = line['parameter']
            if 'lha' not in line:
                line['lha'] = '{}.values.{}'.format(block['block'],line['id'])
            lines_seen.append([block['block'], line['id']])
    return self.valid

Instance variables

var distribution

var parameters

var src

var valid