pyslha.py

changeset 203
ce90a0dace07
parent 202
d3d069f4549a
child 204
bef82eaef56e
     1.1 --- a/pyslha.py	Sun Apr 28 21:56:51 2013 +0200
     1.2 +++ b/pyslha.py	Sun Apr 28 22:13:19 2013 +0200
     1.3 @@ -20,16 +20,14 @@
     1.4  TODOs:
     1.5  
     1.6  For 2.0.0:
     1.7 - * Provide a nice set_value(key=None, val) type function
     1.8   * Provide a Block constructor that takes a dict of entries
     1.9 - * Rename add_entry to add_entry_from_tuple or similar
    1.10   * Output column alignment cosmetics
    1.11   * Precision setting obedience in SLHA output of values
    1.12 - * Split writeSLHA into writeSLHA{Blocks,Decays}
    1.13  
    1.14  For 2.1.0:
    1.15   * Preserve comments from read -> write (needs full-line/inline comment separation?)
    1.16   * Consider whether Block should inherit direct from dict
    1.17 + * Split writeSLHA into writeSLHA{Blocks,Decays}
    1.18  
    1.19  Later/maybe:
    1.20   * Identify HERWIG decay matrix element to use in ISAWIG
    1.21 @@ -89,11 +87,31 @@
    1.22  
    1.23  class Block(object):
    1.24      """
    1.25 -    Object representation of any BLOCK elements read from the SLHA file.  Blocks
    1.26 -    have a name, may have an associated Q value, and contain a collection of data
    1.27 -    entries, each indexed by one or more keys. Types in the dictionary are
    1.28 -    numeric (int or float) when a cast from the string in the file has been
    1.29 -    possible.
    1.30 +    Object representation of any BLOCK elements read from an SLHA file.
    1.31 +
    1.32 +    Blocks have a name, may have an associated Q value, and contain a collection
    1.33 +    of data entries, each indexed by one or more keys. Entries in the dictionary
    1.34 +    are stored as numeric types (int or float) when a cast from the string in
    1.35 +    the file has been possible.
    1.36 +
    1.37 +    Block is closely related to a Python dict (and, in fact, is implemented via
    1.38 +    an OrderedDict when possible). The preferred methods of entry access use the
    1.39 +    dict-like [] operator for getting and setting, and the keys() and items()
    1.40 +    methods for iteration. Purely iterating over the object behaves like keys(),
    1.41 +    as for an ordinary dict.
    1.42 +
    1.43 +    Multiple indices are possible, especially for entries in mixing matrix
    1.44 +    blocks. These are now implemented in the natural way, e.g. for access to the
    1.45 +    (1,2) element of a mxing matrix block, use bmix[1,2] = 0.123 and print
    1.46 +    bmix[1,2]. The value() and set_value() functions behave similarly.
    1.47 +
    1.48 +    It is possible, although not usual, to store unindexed values in a
    1.49 +    block. This is only supported when that entry is the only one in the block,
    1.50 +    and it is stored in the normal fashion but with None as the lookup key. The
    1.51 +    value() method may be used without a key argument to retrieve this value, if
    1.52 +    the is_single_valued() method returns True, and similarly the set_value()
    1.53 +    method may be used to set it if only one argument is supplied and the object
    1.54 +    is compatible.
    1.55      """
    1.56      def __init__(self, name, q=None):
    1.57          self.name = name
    1.58 @@ -101,14 +119,22 @@
    1.59          self.q = _autotype(q)
    1.60  
    1.61      def add_entry(self, entry):
    1.62 -        """Add an entry to the block from an iterable (i.e. list or tuple).
    1.63 +        """Add an entry to the block from an iterable (i.e. list or tuple) or
    1.64 +        whitespace-separated string.
    1.65 +
    1.66          Indexing will be determined automatically such that there is always a
    1.67          single-element value: multi-value or None indices may be constructed
    1.68          implicitly.
    1.69          """
    1.70 +        ## If the argument is a single string, split it and proceed
    1.71 +        if type(entry) is str:
    1.72 +            entry = entry.split()
    1.73 +        ## Check that the arg is an iterable
    1.74          if not hasattr(entry, "__iter__"):
    1.75              raise AccessError("Block entries must be iterable")
    1.76 +        ## Auto-convert the types in the list
    1.77          entry = map(_autotype, entry)
    1.78 +        ## Add the entry to the map, with appropriate indices
    1.79          if len(entry) == 1:
    1.80              self.entries[None] = entry[0]
    1.81          elif len(entry) == 2:
    1.82 @@ -131,6 +157,22 @@
    1.83              raise AccessError("Tried to access unique value of multi-value block")
    1.84          return self.entries[key]
    1.85  
    1.86 +    def set_value(self, *args):
    1.87 +        """Set a value in the block with supplied key, val args (or just val for
    1.88 +        an unindexed block).
    1.89 +
    1.90 +        If no key is given, then the block must contain only one non-indexed
    1.91 +        value otherwise an AccessError exception will be raised.\
    1.92 +        """
    1.93 +        if len(args) == 0:
    1.94 +            raise AccessError("set_value() called without arguments")
    1.95 +        elif len(args) == 1:
    1.96 +            if len(self.entries) > 0 and not self.is_single_valued():
    1.97 +                raise AccessError("Tried to set a unique value on a multi-value block")
    1.98 +            self.entries[None] = args[0]
    1.99 +        else:
   1.100 +            self.entries[tuple(args[:-1])] = args[-1]
   1.101 +
   1.102      def keys(self):
   1.103          """Access the block item keys."""
   1.104          return self.entries.keys()

mercurial