Fri, 26 Apr 2013 01:00:15 +0200
Preserving the ordering of blocks, decays, and their their contents if possible, using ordered dicts. Version 1.5.0, since the behaviour has significantly altered.
ChangeLog | file | annotate | diff | comparison | revisions | |
pyslha.py | file | annotate | diff | comparison | revisions |
1.1 --- a/ChangeLog Thu Apr 25 11:43:16 2013 +0200 1.2 +++ b/ChangeLog Fri Apr 26 01:00:15 2013 +0200 1.3 @@ -1,3 +1,10 @@ 1.4 +2013-04-26 Andy Buckley <andy.buckley@cern.ch> 1.5 + 1.6 + * Version 1.5.0, since the behaviour has significantly altered. 1.7 + 1.8 + * Preserving the ordering of blocks, decays, and their their 1.9 + contents if possible, using ordered dicts. 1.10 + 1.11 2013-04-08 Andy Buckley <andy.buckley@cern.ch> 1.12 1.13 * Version 1.4.4
2.1 --- a/pyslha.py Thu Apr 25 11:43:16 2013 +0200 2.2 +++ b/pyslha.py Fri Apr 26 01:00:15 2013 +0200 2.3 @@ -18,7 +18,7 @@ 2.4 user-tweaking of the generated output. 2.5 2.6 TODOs: 2.7 - * Opportunistically use ordereddict to preserve write order 2.8 + * Store dict entries as tuple keys, e.g. myblock.entries[1,2] rather than recursive dicts => v1.6.0 2.9 * Preserve comments from read -> write (needs full-line/inline comment separation?) 2.10 * Split writeSLHA into writeSLHA{Blocks,Decays} 2.11 * Identify HERWIG decay matrix element to use in ISAWIG 2.12 @@ -26,9 +26,21 @@ 2.13 """ 2.14 2.15 __author__ = "Andy Buckley <andy.buckley@cern.ch" 2.16 -__version__ = "1.4.4" 2.17 +__version__ = "1.5.0" 2.18 2.19 2.20 +def _mkdict(): 2.21 + """Try to return an empty ordered dict, but fall back to normal dict if necessary""" 2.22 + try: 2.23 + from collections import OrderedDict 2.24 + return OrderedDict() 2.25 + except: 2.26 + try: 2.27 + from ordereddict import OrderedDict 2.28 + return OrderedDict() 2.29 + except: 2.30 + return dict() 2.31 + 2.32 def _autotype(var): 2.33 """Automatically convert strings to numerical types if possible.""" 2.34 if type(var) is not str: 2.35 @@ -67,20 +79,22 @@ 2.36 """ 2.37 def __init__(self, name, q=None): 2.38 self.name = name 2.39 - self.entries = {} # TODO: Use ordereddict? 2.40 + self.entries = _mkdict() 2.41 self.q = _autotype(q) 2.42 2.43 def add_entry(self, entry): 2.44 #print entry 2.45 nextparent = self.entries 2.46 + if type(entry) is str: 2.47 + raise Exception("Block entries must be tuples or lists") 2.48 if len(entry) < 2: 2.49 - raise Exception("Block entries must be at least a 2-tuple") 2.50 + raise Exception("Block entry tuples must have at least two entries") 2.51 #print "in", entry 2.52 entry = map(_autotype, entry) 2.53 #print "out", entry 2.54 for e in entry[:-2]: 2.55 if e is not entry[-1]: 2.56 - nextparent = nextparent.setdefault(e, {}) # TODO: Use ordereddict? 2.57 + nextparent = nextparent.setdefault(e, _mkdict()) 2.58 nextparent[entry[-2]] = entry[-1] 2.59 #print self.entries 2.60 2.61 @@ -181,8 +195,8 @@ 2.62 If the ignorenobr parameter is True, do not store decay entries with a 2.63 branching ratio of zero. 2.64 """ 2.65 - blocks = {} # TODO: Use ordereddict? 2.66 - decays = {} # TODO: Use ordereddict? 2.67 + blocks = _mkdict() 2.68 + decays = _mkdict() 2.69 # 2.70 import re 2.71 currentblock = None 2.72 @@ -262,14 +276,14 @@ 2.73 sep = " " 2.74 out = "" 2.75 def dict_hier_strs(d, s=""): 2.76 - if type(d) is dict: # TODO: Use ordereddict? 2.77 - for k, v in sorted(d.iteritems()): 2.78 + if isinstance(d, dict): 2.79 + for k, v in d.iteritems(): 2.80 for s2 in dict_hier_strs(v, s + sep + _autostr(k)): 2.81 yield s2 2.82 else: 2.83 yield s + sep + _autostr(d) 2.84 ## Blocks 2.85 - for bname, b in sorted(blocks.iteritems()): 2.86 + for bname, b in blocks.iteritems(): 2.87 namestr = b.name 2.88 if b.q is not None: 2.89 namestr += (" Q= " + fmte) % float(b.q) 2.90 @@ -278,9 +292,9 @@ 2.91 out += sep + s + "\n" 2.92 out += "\n" 2.93 ## Decays 2.94 - for pid, particle in sorted(decays.iteritems()): 2.95 + for pid, particle in decays.iteritems(): 2.96 out += ("DECAY %d " + fmte + "\n") % (particle.pid, particle.totalwidth or -1) 2.97 - for d in sorted(particle.decays): 2.98 + for d in particle.decays: 2.99 if d.br > 0.0 or not ignorenobr: 2.100 products_str = " ".join(map(str, d.ids)) 2.101 out += sep + fmte % d.br + sep + "%d" % len(d.ids) + sep + products_str + "\n" 2.102 @@ -510,8 +524,8 @@ 2.103 branching ratio of zero. 2.104 """ 2.105 2.106 - blocks = {} # TODO: Use ordereddict? 2.107 - decays = {} # TODO: Use ordereddict? 2.108 + blocks = _mkdict() 2.109 + decays = _mkdict() 2.110 LINES = isastr.splitlines() 2.111 2.112 def getnextvalidline():