#########################################################################
#
# Script: particle_info.py
#
# Author: Igor Volobouev, Feb 2005
#
# Purpose: reads a datafile with info about cosmic ray particles and
#          makes particle properties available for use by other scripts
#
#########################################################################

"""This module is used to read particle information from a GAUDI-compatible
particle definition file. Typical usage is like this:

import particle_info as pinf
proton_mass = pinf.info["proton"].mass

Info members are 'idgeant', 'idhep', 'itype', 'charge', 'mass', and 'tlife'.
Location of the particle properties file should be specified via the config
parameter "particle_data_file"."""

import re
import EventGenUtils_config as config

class ParticleInfo:
    "Basic info about particle species"
    argumentParsers = (str,  int,     int,   int,   float,  float, float)
    def __init__(self, name, idgeant, idhep, itype, charge, mass,  tlife):
        self.name = name
        self.idgeant = idgeant
        self.idhep = idhep
        self.itype = itype
        self.charge = charge
        # Convert mass to MeV 
        self.mass = mass * 1000.0
        self.tlife = tlife
    def __repr__(self):
        s = '(' + self.name
        for member in ('idgeant', 'idhep', 'itype', 'charge', 'mass', 'tlife'):
            s += ', '
            s += str(self.__dict__[member])
        s += ')'
        return s

class ParticleDict(dict):
    "Reads particle properties from a file in the GAUDI ParticlePropertySvc format"
    def __init__(self, filename):
        expectedColumns = len(ParticleInfo.argumentParsers)
        r1 = re.compile(r'^\s*($|#)')
        f = open(filename)
        linenum = 0
        errorline = 0
        for line in f:
            linenum += 1
            # Skip empty lines and lines which start with "#"
            if r1.match(line): continue
            # Skip PARTICLE/END PARTICLE declarations
            if (line.find("PARTICLE") >= 0): continue
            # Normal particle spec should be a 7-element list
            data = line.split()
            parsed = list()
            if (len(data) == expectedColumns):
                for parser, item in zip(ParticleInfo.argumentParsers, data):
                    try:
                        parsed.append(parser(item))
                    except ValueError:
                        errorline = linenum
            else:
                errorline = linenum
            if (errorline): break
            # Create the ParticleInfo object and key it by particle name
            self[parsed[0]] = apply(ParticleInfo, parsed)
        f.close()
        if errorline:
            raise SyntaxError, "failed to parse line " + \
                  str(errorline) + " in file " + filename

info = ParticleDict(config.particle_data_file)
