#!/usr/bin/env python

# pmx  Copyright Notice
# ============================
#
# The pmx source code is copyrighted, but you can freely use and
# copy it as long as you don't change or remove any of the copyright
# notices.
#
# ----------------------------------------------------------------------
# pmx is Copyright (C) 2006-2013 by Daniel Seeliger
#
#                        All Rights Reserved
#
# Permission to use, copy, modify, distribute, and distribute modified
# versions of this software and its documentation for any purpose and
# without fee is hereby granted, provided that the above copyright
# notice appear in all copies and that both the copyright notice and
# this permission notice appear in supporting documentation, and that
# the name of Daniel Seeliger not be used in advertising or publicity
# pertaining to distribution of the software without specific, written
# prior permission.
#
# DANIEL SEELIGER DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
# SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
# FITNESS.  IN NO EVENT SHALL DANIEL SEELIGER BE LIABLE FOR ANY
# SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
# RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
# CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
# ----------------------------------------------------------------------

"""docs to be added
"""

import sys
from .library import _aliases, pmx_data_file
from .parser import parseList, kickOutComments, readSection


class RTPParser:

    def __init__(self, filename=None):
        self.keys = []
        self.entries = {}
        self.lines = []
        self.filename = ''
        self.__cur_id = 0
        if filename is not None:
            self.parse(filename)

    def parse(self, filename):
        filename = pmx_data_file(filename)
        self.filename = filename
        l = open(filename).readlines()
        self.lines = kickOutComments(l, ';')
        self.__get_residue_names()
        for key in self.keys:
            rtp_lines = self.__read_residue_entry(key)
            # read atoms
            al = readSection(rtp_lines, '[ atoms ]', '[')
            atoms = self.__read_rtp_atoms(key, al)
            # read bonds
            bl = readSection(rtp_lines, '[ bonds ]', '[')
            bonds = self.__read_rtp_bonds(key, bl)
            # read dihedrals
            dl = readSection(rtp_lines, '[ dihedrals ]', '[')
            diheds = self.__read_rtp_dihedrals(key, dl)
            # read impropers
            il = readSection(rtp_lines, '[ impropers ]', '[')
            improps = self.__read_rtp_impropers(key, il)
            # read cmap (only for charmm)
            cmap = readSection(rtp_lines, '[ cmap ]', '[')

            self.entries[key] = {
                'atoms': atoms,
                'bonds': bonds,
                'diheds': diheds,
                'improps': improps,
                'cmap': cmap
                }

    def __str__(self):
        s = '<%s | "%s" |  %d residue entries >' % (self.__class__,
                                                    self.filename,
                                                    len(self.keys))
        return s

    def __getitem__(self, item):
        return self.entries[item]

    def __delitem__(self, item):
        del self.entries[item]
        self.keys.remove(item)

    def add_entry(self, name, rtp_dic):
        if name in self.keys:
            del self.entries[name]
        else:
            self.keys.append(name)
        self.entries[name] = rtp_dic

    def __contains__(self, key):
        return key in self.keys

    def __iter__(self):
        return self

    def next(self):
        if self.__cur_id >= len(self.keys):
            self.__cur_id = 0
            raise StopIteration
        name = self.keys[self.__cur_id]
        entr = self.entries[self.keys[self.__cur_id]]
        self.__cur_id += 1
        return name, entr

    def write(self, out_file):
        if not hasattr(out_file, "write"):
            fp = open(out_file, "w")
        else:
            fp = out_file
        for key in self.keys:
            entr = self.entries[key]
            print('[ %s ]' % key, file=fp)
            print(' [ atoms ]', file=fp)
            for atom in entr['atoms']:
                print("%6s   %-15s  %8.5f  %d" % (atom[0], atom[1], atom[2], atom[3]), file=fp)
            if entr['bonds']:
                print(' [ bonds ]', file=fp)
                for bond in entr['bonds']:
                    print("%6s  %6s" % (bond[0], bond[1]), file=fp)
            if entr['diheds']:
                print(' [ dihedrals ]', file=fp)
                for dih in entr['diheds']:
                    print("%6s  %6s  %6s  %6s  %-25s" % (dih[0], dih[1], dih[2], dih[3], dih[4]), file=fp)
            if entr['improps']:
                print(' [ impropers ]', file=fp)
                for dih in entr['improps']:
                    try:
                        print("%6s  %6s  %6s  %6s  %-25s" % (dih[0], dih[1], dih[2], dih[3], dih[4]), file=fp)
                    except:
                        print("%6s  %6s  %6s  %6s " % (dih[0], dih[1], dih[2], dih[3]), file=fp)
            print('', file=fp)

    def __check_residue_tree(self, model):
        for c in model.chains:
            if not c.residue_tree_ok:
                print('pmx_Error_> Broken residue tree in chain ', c.id, file=sys.stderr)
                sys.exit(1)

    def assign_params(self, model):
        self.__check_residue_tree(model)
        self.__assign_atom_params(model)
        self.__make_bonds(model)
        self.__make_angles(model)
        self.__make_dihedrals(model)
        self.__make_impropers(model)

    def assign_dihedral_params(self, model, directives):
        for dih in model.dihedral_list:
            a1, a2, a3, a4 = dih[:4]
            resid = a2.resnr  # FIXME: variable not used
            rtp_d = self.entries[a2.resname]  # FIXME: variable not used
            name2 = a2.name
            if a1.resnr == a2.resnr:
                name1 = a1.name
            elif a1.resnr == a2.resnr - 1:
                name1 = '-'+a1.name
            elif a1.resnr == a2.resnr + 1:
                name1 = '+'+a1.name
            if a3.resnr == a2.resnr:
                name3 = a3.name
            elif a3.resnr == a2.resnr - 1:
                name3 = '-'+a3.name
            elif a3.resnr == a2.resnr + 1:
                name3 = '+'+a3.name
            if a4.resnr == a2.resnr:
                name4 = a4.name
            elif a4.resnr == a2.resnr - 1:
                name4 = '-'+a4.name
            elif a1.resnr == a2.resnr + 1:
                name4 = '+'+a4.name
            d = self.__find_rtp_dihedral(a2.resname, name1, name2, name3, name4)
            if d is not None:
                if d[4] in directives:
                    dih = dih[:5]+directives[d[4]]
                else:
                    raise ValueError('No directive found')

    def __assign_atom_params(self, model):
        for residue in model.residues:
            rtp_atoms = self.entries[residue.resname]['atoms']
            for atom_entry in rtp_atoms:
                name = atom_entry[0]
                atom = residue[name]
                atom.atomtype = atom_entry[1]
                atom.q = atom_entry[2]
                atom.cgnr = atom_entry[3]

    def __make_bonds(self, model):
        model.bond_list = []
        for residue in model.residues:
            rtp_bonds = self.entries[residue.resname]['bonds']
            for a1, a2 in rtp_bonds:
                if a1[0] not in ['+', '-'] and a2[0] not in ['+', '-']:
                    atom1 = residue[a1]
                    atom2 = residue[a2]
                    atom1.bonds.append(atom2)
                    atom2.bonds.append(atom1)
                    model.bond_list.append([atom1, atom2])
                else:
                    if a1[0] == '-':
                        atom1 = residue.previous[a1[1:]]
                    elif a1[0] == '+':
                        atom1 = residue.next[a1[1:]]
                    else:
                        atom1 = residue[a1]
                    if a2[0] == '-':
                        atom2 = residue.previous[a2[1:]]
                    elif a2[0] == '+':
                        atom2 = residue.next[a2[1:]]
                    else:
                        atom2 = residue[a2]
                    if atom2 not in atom1.bonds:
                        atom1.bonds.append(atom2)
                        atom2.bonds.append(atom1)
                        model.bond_list.append([atom1, atom2])

        # cys
        for residue in model.residues:
            if residue.resname in ['CYS2', 'CCYX']:
                for r in model.residues:
                    if r.resname in ['CYS2', 'CCYX'] and r.id < residue.id:
                        sg1 = residue['SG']
                        sg2 = r['SG']
                        d = sg1 - sg2
                        if d < 2.5:
                            print('pmx__> Disulfid bond between residue', sg1.resnr, 'and', sg2.resnr, file=sys.stderr)
                            sg1.bonds.append(sg2)
                            sg2.bonds.append(sg1)
                            model.bond_list.append([sg1, sg2])

        for atom in model.atoms:
            for b in atom.bonds:
                atom.connected.append(b)

    def __make_angles(self, model):
        model.angle_list = []
        for atom in model.atoms:
            for b in atom.bonds:
                for bb in b.bonds:
                    if bb.id < atom.id:
                        atom.b13.append(bb)
                        bb.b13.append(atom)
                        atom.connected.append(bb)
                        bb.connected.append(atom)
                        model.angle_list.append([atom, b, bb])

    def __make_dihedrals(self, model):
        model.dihedral_list = []
        for atom in model.atoms:
            for b in atom.bonds:
                for bb in b.bonds:
                    if bb.id != atom.id:
                        for bbb in bb.bonds:
                            if atom.id < bbb.id:
                                if bbb not in atom.bonds:
                                    model.dihedral_list.append([atom, b, bb, bbb])
                                    if bbb not in atom.connected:
                                        atom.b14.append(bbb)
                                        bbb.b14.append(atom)
                                        atom.connected.append(bbb)
                                        bbb.connected.append(atom)

    def __make_impropers(self, model):
        model.improper_list = []
        for residue in model.residues:
            rtp_imp = self.entries[residue.resname]['improps']

            for imp in rtp_imp:
                atoms = []
                for name in imp[:4]:
                    if name[0] == '+':
                        atom = residue.next[name[1:]]
                    elif name[0] == '-':
                        atom = residue.previous[name[1:]]
                    else:
                        atom = residue[name]
                    atoms.append(atom)
                assert len(atoms) == 4
                model.improper_list.append(atoms + [imp[4]])

    def __get_residue_names(self):
        self.keys = []
        for line in self.lines:
            if line.strip().startswith('['):
                if line.strip()[1:-1].strip() not in \
                       ['atoms', 'bonds', 'dihedrals', 'impropers',
                        'bondedtypes']:
                    self.keys.append(line.strip()[1:-1].strip())

    def __read_residue_entry(self, key):
        r = []
        for line in self.lines:
            if line.strip()[1:-1].strip() == key:
                idx = self.lines.index(line)
        for line in self.lines[idx+1:]:
            if line.strip().startswith('['):
                if line.strip()[1:-1].strip() not in \
                       ['atoms', 'bonds', 'dihedrals', 'impropers', 'cmap']:
                    break
                else:
                    r.append(line)
            else:
                r.append(line)
        return r

    def __read_rtp_atoms(self, resname, lines):
        atoms = []
        for line in lines:
            entr = line.split()
            if resname in _aliases:
                if entr[0] in _aliases[resname]:
                    entr[0] = _aliases[resname][entr[0]]
            entr[2] = float(entr[2])
            entr[3] = int(entr[3])
            atoms.append(entr)
        return atoms

    def __read_rtp_bonds(self, resname, lines):
        bonds = []
        for line in lines:
            entr = line.split()
            if entr[0] not in ['+', '-']:
                if resname in _aliases:
                    if entr[0] in _aliases[resname]:
                        entr[0] = _aliases[resname][entr[0]]
            if entr[1] not in ['+', '-']:
                if resname in _aliases:
                    if entr[1] in _aliases[resname]:
                        entr[1] = _aliases[resname][entr[1]]
            bonds.append(entr)
        return bonds

    def __read_rtp_dihedrals(self, resname, lines):
        diheds = []
        for line in lines:
            entr = line.split()
            if entr[0] not in ['+', '-']:
                if resname in _aliases:
                    if entr[0] in _aliases[resname]:
                        entr[0] = _aliases[resname][entr[0]]
            if entr[1] not in ['+', '-']:
                if resname in _aliases:
                    if entr[1] in _aliases[resname]:
                        entr[1] = _aliases[resname][entr[1]]
            if entr[2] not in ['+', '-']:
                if resname in _aliases:
                    if entr[2] in _aliases[resname]:
                        entr[2] = _aliases[resname][entr[2]]
            if entr[3] not in ['+', '-']:
                if resname in _aliases:
                    if entr[3] in _aliases[resname]:
                        entr[3] = _aliases[resname][entr[3]]
            if len(entr) == 5:
                diheds.append(entr)
            else:
                diheds.append(entr+[''])
        return diheds

    def __read_rtp_impropers(self, resname, lines):
        improps = []
        for line in lines:
            entr = line.split()
            if entr[0] not in ['+', '-']:
                if resname in _aliases:
                    if entr[0] in _aliases[resname]:
                        entr[0] = _aliases[resname][entr[0]]
            if entr[1] not in ['+', '-']:
                if resname in _aliases:
                    if entr[1] in _aliases[resname]:
                        entr[1] = _aliases[resname][entr[1]]
            if entr[2] not in ['+', '-']:
                if resname in _aliases:
                    if entr[2] in _aliases[resname]:
                        entr[2] = _aliases[resname][entr[2]]
            if entr[3] not in ['+', '-']:
                if resname in _aliases:
                    if entr[3] in _aliases[resname]:
                        entr[3] = _aliases[resname][entr[3]]
            if len(entr) == 5:
                improps.append(entr)
            else:
                improps.append(entr+[''])
        return improps

    def __find_rtp_dihedral(self, key, name1, name2, name3, name4):
        rtp_d = self.entries[key]['diheds']
        for d in rtp_d:
            if (d[0] == name1 and d[1] == name2 and
                d[2] == name3 and d[3] == name4) or \
                (d[0] == name4 and d[1] == name3 and
                 d[2] == name2 and d[3] == name1):
                return d
        return None

    def __find_rtp_improper(self, key, name1, name2, name3, name4):
        rtp_i = self.entries[key]['improps']
        for d in rtp_i:
            if (d[0] == name1 and d[1] == name2 and
                d[2] == name3 and d[3] == name4) or \
                (d[0] == name4 and d[1] == name3 and
                 d[2] == name2 and d[3] == name1):
                return d
        return None


class BondedParser:

    def __init__(self, filename=None, version='old'):
        self.lines = []
        self.filename = ''
        self.directives = {}
        self.bondtypes = []
        self.angletypes = []
        self.dihedraltypes = []
        if filename:
            self.parse(filename)

    def parse(self, filename):
        if not hasattr(filename, "append"):  # not a list
            filename = pmx_data_file(filename)
            self.filename = filename
            l = open(filename).readlines()
        else:
            l = filename
            self.filename = '< from list >'
        self.lines = kickOutComments(l, ';')
        self.__parse_directives()
        self.__parse_bondtypes()
        self.__parse_angletypes()
        self.__parse_dihedraltypes()

    def __str__(self):
        s = '< %s | %s >' % (self.__class__, self.filename)
        return s

    def assign_params(self, model):
        for bond in model.bond_list:
            params = self.get_bond_param(bond[0].bond_type, bond[1].bond_type)
            bond.extend(params)
        for angle in model.angle_list:
            params = self.get_angle_param(angle[0].bond_type,
                                          angle[1].bond_type,
                                          angle[2].bond_type)
            angle.extend(params)
        for dih in model.dihedral_list:
            params = self.get_dihedral_param(dih[0].bond_type,
                                             dih[1].bond_type,
                                             dih[2].bond_type,
                                             dih[3].bond_type,
                                             3)
            dih.extend(params)

        for dih in model.improper_list:
            if dih[4] == '':
                params = self.get_dihedral_param(dih[0].bond_type,
                                                 dih[1].bond_type,
                                                 dih[2].bond_type,
                                                 dih[3].bond_type,
                                                 1)
                dih.extend(params[1:])
            else:
                dih = dih[:4] + [1] + self.directives[dih[4]]

    def get_bond_param(self, type1, type2):
        for entr in self.bondtypes:
            if (type1 == entr[0] and type2 == entr[1]) or \
               (type1 == entr[1] and type2 == entr[0]):
                return entr[2:]
        return None

    def get_angle_param(self, type1, type2, type3):
        for entr in self.angletypes:
            if (type1 == entr[0] and type2 == entr[1] and type3 == entr[2]) or \
               (type1 == entr[2] and type2 == entr[1] and type3 == entr[0]):
                return entr[3:]
        return None

    def get_dihedral_param(self, type1, type2, type3, type4, func):

        self.result = []
        found = 0
        for entr in self.dihedraltypes:
            if (type1 == entr[0] and
                type2 == entr[1] and
                type3 == entr[2] and
                type4 == entr[3] and func == entr[4]) or \
                (type1 == entr[3] and
                 type2 == entr[2] and
                 type3 == entr[1] and
                 type4 == entr[0] and func == entr[4]):
                self.result.append(entr[4:])
                found = 1
                if(func != 9):
                    return self.result

        if found == 1:
            return self.result

        for entr in self.dihedraltypes:
            if ('X' == entr[0] and
                type2 == entr[1] and
                type3 == entr[2] and
                type4 == entr[3] and func == entr[4]) or \
                (type1 == entr[0] and
                 type2 == entr[1] and
                 type3 == entr[2] and
                 'X' == entr[3] and func == entr[4]):
                self.result.append(entr[4:])
                if(func != 9):
                    return self.result
            if ('X' == entr[3] and
                type2 == entr[2] and
                type3 == entr[1] and
                type4 == entr[0] and func == entr[4]) or \
                (type1 == entr[3] and
                 type2 == entr[2] and
                 type3 == entr[1] and
                 'X' == entr[0] and func == entr[4]):
                self.result.append(entr[4:])
                found = 1
                if(func != 9):
                    return self.result

        if found == 1:
            return self.result

        for entr in self.dihedraltypes:
            if ('X' == entr[0] and
                type2 == entr[1] and
                type3 == entr[2] and
                'X' == entr[3] and func == entr[4]) or \
                ('X' == entr[3] and
                 type2 == entr[2] and
                 type3 == entr[1] and
                 'X' == entr[0] and func == entr[4]):
                self.result.append(entr[4:])
                found = 1
                if(func != 9):
                    return self.result

        if found == 1:
            return self.result

        for entr in self.dihedraltypes:
            if ('X' == entr[0] and
                'X' == entr[1] and
                type3 == entr[2] and
                type4 == entr[3] and func == entr[4]) or \
                (type1 == entr[3] and
                 type2 == entr[2] and
                 'X' == entr[1] and
                 'X' == entr[0] and func == entr[4]):
                self.result.append(entr[4:])
                found = 1
                if(func != 9):
                    return self.result

        if found == 1:
            return self.result

        for entr in self.dihedraltypes:  # exchange 1 -> 3
            if ('X' == entr[0] and
                'X' == entr[1] and
                type3 == entr[2] and
                type2 == entr[3] and func == entr[4]) or \
                (type1 == entr[3] and
                 type4 == entr[2] and
                 'X' == entr[1] and
                 'X' == entr[0] and func == entr[4]):
                self.result.append(entr[4:])
                if(func != 9):
                    return self.result

        for entr in self.dihedraltypes:
            if (type1 == entr[0] and
                'X' == entr[1] and
                'X' == entr[2] and
                type4 == entr[3] and func == entr[4]) or \
                (type1 == entr[3] and
                 'X' == entr[1] and
                 'X' == entr[2] and
                 type4 == entr[0] and func == entr[4]):
                self.result.append(entr[4:])
                if(func != 9):
                    return self.result

        return self.result

    def __parse_directives(self):
        for line in self.lines:
            if line.startswith('#define'):
                entr = line.split()
                name = entr[1]
                params = [float(x) for x in entr[2:]]
                self.directives[name] = params
        self.lines = kickOutComments(self.lines, '#')

    def __parse_bondtypes(self):
        res = []
        starts = []
        for i, line in enumerate(self.lines):
            if line.strip().startswith('[ bondtypes ]'):
                starts.append(i)
        for s in starts:
            lst = readSection(self.lines[s:], '[ bondtypes ]', '[')
            lst = parseList('ssiff', lst)
            res.extend(lst)
        self.bondtypes = res

    def __parse_angletypes(self):
        res = []
        starts = []
        for i, line in enumerate(self.lines):
            if line.strip().startswith('[ angletypes ]'):
                starts.append(i)
        for s in starts:
            lst = readSection(self.lines[s:], '[ angletypes ]', '[')
            try:
                lst = parseList('sssiff', lst)
            except:
                try:
                    lst = parseList('sssiffff', lst)
                except:
                    raise ValueError("Unkown Angle type")
            res.extend(lst)
        self.angletypes = res

    def __parse_dihedraltypes(self):
        res = []
        starts = []
        for i, line in enumerate(self.lines):
            if line.strip().startswith('[ dihedraltypes ]'):
                starts.append(i)
        for s in starts:
            lst = readSection(self.lines[s:], '[ dihedraltypes ]', '[')
            try:
                lst = parseList('ssssiffffff', lst)
            except:
                try:
                    lst = parseList('ssssiffi', lst)
                except:
                    try:
                        lst = parseList('ssiffi', lst)
                    except:
                        lst = parseList('ssssiff', lst)
            res.extend(lst)
        self.dihedraltypes = res


class NBParser:

    def __init__(self, filename=None, version='new', ff='amber'):
        self.lines = []
        self.ff = ff
        self.filename = ''
        self.atomtypes = {}
        if filename is not None:
            self.parse(filename, version)

    def parse(self, filename, version):
        if not hasattr(filename, "append"):  # not a list
            filename = pmx_data_file(filename)
            l = open(filename).readlines()
            self.filename = filename
        else:
            l = filename
            self.filename = '< from list >'
        self.lines = kickOutComments(l, ';')
        self.__parse_atomtypes(version)

    def __str__(self):
        s = '< %s | %s >' % (self.__class__, self.filename)
        return s

    def __parse_atomtypes(self, version):

        self.atomtypes = {}
        lst = readSection(self.lines, '[ atomtypes ]', '[')
        ffnamelower = self.ff.lower()
        if version == 'old':
            if ffnamelower.startswith('amber'):
                lst = parseList('ssffsff', lst)
                for entr in lst:
                    self.atomtypes[entr[0]] = {
                        'bond_type': entr[1],
                        'mass': float(entr[2]),
                        'sigma': entr[5]*10,  # nm -> A
                        'eps': entr[6]
                        }
            elif ffnamelower.startswith('opls'):
                lst = parseList('ssiffsff', lst)
                for entr in lst:
                    self.atomtypes[entr[0]] = {
                        'bond_type': entr[1],
                        'mass': float(entr[3]),
                        'sigma': entr[6]*10,  # nm -> A
                        'eps': entr[7]
                        }

        elif version == 'new':
            if ffnamelower.startswith('amber') or ffnamelower.startswith('charmm'):
                lst = parseList('siffsff', lst)
                for entr in lst:
                    self.atomtypes[entr[0]] = {
                        'bond_type': entr[0],
                        'mass': float(entr[2]),
                        'sigma': entr[5]*10,  # nm -> A
                        'eps': entr[6]
                        }
            elif ffnamelower.startswith('opls'):
                lst = parseList('ssiffsff', lst)
                for entr in lst:
                    self.atomtypes[entr[0]] = {
                        'bond_type': entr[1],
                        'mass': float(entr[3]),
                        'sigma': entr[6]*10,  # nm -> A
                        'eps': entr[7]
                        }
            elif ffnamelower.startswith('gaff'):
                try:
                    lst = parseList('sffsff', lst)
                    for entr in lst:
                        self.atomtypes[entr[0]] = {
                            'bond_type': entr[1],
                            'mass': float(entr[2]),
                            # 'charge':float(entr[3]),
                            'sigma': entr[4]*10,  # nm -> A
                            'eps': entr[5]
                            }
                except:
                    lst = parseList('ssffsff', lst)
                    for entr in lst:
                        self.atomtypes[entr[0]] = {
                            'bond_type': entr[1],
                            'mass': float(entr[2]),
                            'charge': float(entr[3]),
                            'sigma': entr[5]*10,  # nm -> A
                            'eps': entr[6]
                            }

    def assign_params(self, model):
        for atom in model.atoms:
            atom.bond_type = self.atomtypes[atom.atomtype]['bond_type']
            atom.sigma = self.atomtypes[atom.atomtype]['sigma']
            atom.eps = self.atomtypes[atom.atomtype]['eps']


class ATPParser:

    def __init__(self,  fn='ffamber99sb.atp'):
        self.fn = fn
        self.dic = {}
        if fn is not None:
            self.parse()

    def parse(self):
        lst = open(self.fn).readlines()
        lst = kickOutComments(lst, ';')
        lst = parseList('sf', lst)
        for tp,  mass in lst:
            self.dic[tp] = mass

    def __getitem__(self,  item):
        return self.dic[item]
