From 5b04798ecf6faa8ba91df6ca607884cbbdc3e816 Mon Sep 17 00:00:00 2001
From: James Graham <J.A.Graham@soton.ac.uk>
Date: Fri, 16 Dec 2016 15:33:09 +0000
Subject: [PATCH] CFG parser use OrderedDict Small amounts of tidying elsewhere

---
 data/atom_masses.json   |  7 ++++---
 doc/source/tutorial.rst |  2 +-
 pycgtool/frame.py       |  2 +-
 pycgtool/mapping.py     | 14 +++++++++-----
 pycgtool/parsers/cfg.py | 25 ++++++++-----------------
 5 files changed, 23 insertions(+), 27 deletions(-)

diff --git a/data/atom_masses.json b/data/atom_masses.json
index e344c37..cea07cf 100644
--- a/data/atom_masses.json
+++ b/data/atom_masses.json
@@ -1,7 +1,8 @@
 {
+ "H":  1.0080,
  "C": 12.0110,
- "O": 15.9994,
  "N": 14.0067,
- "H":  1.0080,
- "P": 30.9738
+ "O": 15.9994,
+ "P": 30.9738,
+ "S": 32.0600
 }
diff --git a/doc/source/tutorial.rst b/doc/source/tutorial.rst
index c7f83e1..af620ff 100644
--- a/doc/source/tutorial.rst
+++ b/doc/source/tutorial.rst
@@ -2,7 +2,7 @@ PyCGTOOL Tutorial
 =================
 
 This tutorial follows the complete process of parametrising a new molecule within the MARTINI forcefield, covering aspects of mapping design, model generation and model validation.
-PyCGTOOL is used at multiple stages, showing its use in several different situations
+PyCGTOOL is used at multiple stages, showing its use in several different situations.
 All files required to follow this tutorial are present in the ``doc/tutorial_files`` directory.
 
 The molecule chosen as a target for this parametrisation is the :math:`\beta_1` antagonist atenolol.
diff --git a/pycgtool/frame.py b/pycgtool/frame.py
index 3a6191b..b7a959b 100644
--- a/pycgtool/frame.py
+++ b/pycgtool/frame.py
@@ -358,7 +358,7 @@ class Frame:
         atoms = []
         for res in self.residues:
             for atom in res:
-                atoms.append(repr(atom.coords))
+                atoms.append(repr(atom))
         rep += "\n".join(atoms)
         return rep
 
diff --git a/pycgtool/mapping.py b/pycgtool/mapping.py
index 0a6794e..64abd39 100644
--- a/pycgtool/mapping.py
+++ b/pycgtool/mapping.py
@@ -84,7 +84,6 @@ class Mapping:
         :return: Instance of Mapping
         """
         self._mappings = {}
-
         self._map_center = options.map_center
         self._masses_are_set = False
 
@@ -127,6 +126,8 @@ class Mapping:
                         else:
                             bead.charge += atoms[atom][0]
 
+                self._masses_are_set = True
+
     def __len__(self):
         return len(self._mappings)
 
@@ -153,7 +154,6 @@ class Mapping:
                 if bead.mass == 0:
                     mass_array = np.zeros((len(bead.atoms), 1), dtype=np.float32)
                     for i, atom in enumerate(bead.atoms):
-                        mass = 0
                         try:
                             mass = mass_dict[atom[:2]]
                         except KeyError:
@@ -185,6 +185,7 @@ class Mapping:
         cgframe.name = name
 
         missing_mappings = set()
+        cg_bead_num = 1
 
         for aares in aa_residues:
             try:
@@ -196,12 +197,15 @@ class Mapping:
                 continue
 
             cgres = Residue(name=aares.name, num=aares.num)
-            cgres.atoms = [Atom(name=bead.name, type=bead.type, charge=bead.charge, mass=bead.mass) for bead in molmap]
+            cgres.atoms = [Atom(name=bmap.name, type=bmap.type, charge=bmap.charge, mass=bmap.mass, coords=np.zeros(3)) for bmap in molmap]
 
             for i, (bead, bmap) in enumerate(zip(cgres, molmap)):
                 cgres.name_to_num[bead.name] = i
                 bead.charge = bmap.charge
                 bead.mass = bmap.mass
+                bead.num = cg_bead_num
+
+                cg_bead_num += 1
 
             cgframe.add_residue(cgres)
             cgframe.natoms += len(cgres)
@@ -229,7 +233,7 @@ class Mapping:
         cgframe.box = frame.box
 
         select_predicate = lambda res: res.name in self._mappings and not (exclude is not None and res.name in exclude)
-        aa_residues = (aares for aares in frame if select_predicate(aares))
+        aa_residues = filter(select_predicate, frame)
 
         for aares, cgres in zip(aa_residues, cgframe):
             molmap = self._mappings[aares.name]
@@ -249,7 +253,7 @@ class Mapping:
         return cgframe
 
 
-@numba.jit(nopython=True)
+@numba.jit
 def calc_coords_weight(ref_coords, coords, box, weights):
     """
     Calculate the coordinates of a single CG bead from weighted component atom coordinates.
diff --git a/pycgtool/parsers/cfg.py b/pycgtool/parsers/cfg.py
index 9e4d452..87695b3 100644
--- a/pycgtool/parsers/cfg.py
+++ b/pycgtool/parsers/cfg.py
@@ -5,6 +5,8 @@ Format is based upon GROMACS .itp files but does not support nesting of sections
 """
 import os
 
+from collections import OrderedDict
+
 
 class Section:
     """
@@ -48,7 +50,7 @@ class CFG:
 
     Contains a dictionary of Sections.
     """
-    __slots__ = ["filename", "_sections", "_section_names", "_iter_section"]
+    __slots__ = ["filename", "_sections"]
 
     def __init__(self, filename=None, allow_duplicate=False):
         """
@@ -59,13 +61,12 @@ class CFG:
         :return: Instance of CFG
         """
         self.filename = filename
-        self._sections = {}
-        self._section_names = []
+        self._sections = OrderedDict()
 
         with open(self.filename) as f:
             curr_section = None
             for line in f:
-                line = line.strip(" \t\n")
+                line = line.strip()
                 if not line or line.startswith(";"):
                     continue
 
@@ -73,14 +74,12 @@ class CFG:
                     cfg2 = CFG(os.path.join(os.path.dirname(self.filename),
                                             line.split()[1]))
                     self._sections.update(cfg2._sections)
-                    self._section_names += cfg2._section_names
                     continue
 
                 elif line.startswith("["):
                     curr_section = line.strip("[ ]")
                     if curr_section in self._sections and not allow_duplicate:
                         raise DuplicateSectionError(curr_section, self.filename)
-                    self._section_names.append(curr_section)
                     self._sections[curr_section] = Section(name=curr_section)
                     continue
 
@@ -94,21 +93,13 @@ class CFG:
         pass
 
     def __len__(self):
-        return len(self._section_names)
+        return len(self._sections)
 
     def __iter__(self):
-        self._iter_section = -1
-        return self
-
-    def __next__(self):
-        self._iter_section += 1
-        if self._iter_section >= len(self._section_names):
-            raise StopIteration
-        sec = self._section_names[self._iter_section]
-        return self._sections[sec]
+        return iter(self._sections.values())
 
     def __contains__(self, item):
-        return item in self._section_names
+        return item in self._sections
 
     def __getitem__(self, item):
         return self._sections[item]
-- 
GitLab