{"action":"created","comment":{"url":"https://api.github.com/repos/Becksteinlab/GromacsWrapper/pulls/comments/47599492","id":47599492,"diff_hunk":"@@ -0,0 +1,1243 @@\n+\n+#\n+# JD: adopted from 'pytopol' from https://github.com/resal81/PyTopol\n+#\n+\n+import logging\n+from . import blocks\n+from collections import OrderedDict as odict\n+\n+module_logger = logging.getLogger('gromacs.fileformats')\n+\n+\n+class TOP(blocks.System):\n+    def __init__(self, fname):\n+\n+        super(TOP, self).__init__()\n+\n+        self.lgr = logging.getLogger('gromacs.fileformats.TOP')\n+        self.fname = fname\n+\n+        self.defaults = {\n+            'nbfunc': None, 'comb-rule':None, 'gen-pairs':None, 'fudgeLJ':None, 'fudgeQQ':None,\n+        }\n+\n+        self.dict_molname_mol = odict()   # contains molname:mol\n+        self.found_sections   = []\n+        self.forcefield       = 'gromacs'\n+\n+        self.molecules = []\n+        self._parse(fname)\n+        self.molecules = tuple(self.molecules)\n+\n+    def write(self, filename):\n+        SystemToGroTop(self, filename)\n+\n+    def __repr__(self):\n+        moltypenames = list(self.dict_molname_mol.keys())\n+        moltypenames.sort()\n+\n+        data = []\n+        data.append('\\n')\n+\n+        main_items = set(['atomtypes', 'pairtypes', 'bondtypes', 'angletypes', 'dihedraltypes'])\n+        other_items = ['%s (%d)' % (m, len(self.information[m])) for m in list(self.information.keys()) if m not in main_items]\n+        other_items = ' '.join(other_items)\n+        nattype = len(self.atomtypes)\n+        nprtype = len(self.pairtypes)\n+        nbndtype= len(self.bondtypes)\n+        nangtype= len(self.angletypes)\n+        ndihtype= len(self.dihedraltypes)\n+        nimptype= len(self.impropertypes)\n+        data.append('{:>20s}  {:>7s} {:>7s} {:>7s} {:>7s} {:>7s} {:>7s}'.format('Param types:', 'atom', 'pair', 'bond', 'ang', 'dih', 'imp'))\n+        msg = '{:20s}  {:7d} {:7d} {:7d} {:7d} {:7d} {:7d}    {:s}'.format('', nattype, nprtype, nbndtype, nangtype, ndihtype, nimptype, other_items)\n+        data.append('=' * 69)\n+        data.append(msg)\n+        data.append('\\n')\n+\n+\n+        main_items = set(['atoms', 'pairs', 'bonds', 'angles', 'dihedrals'])\n+        data.append('{:>20s}  {:>7s} {:>7s} {:>7s} {:>7s} {:>7s} {:>7s}'.format('Params:', 'atom', 'pair', 'bond', 'ang', 'dih', 'imp'))\n+        data.append('=' * 69)\n+        for mname in moltypenames:\n+            mol = self.dict_molname_mol[mname]\n+            other_items = ['%s (%d)' % (m, len(mol.information[m])) for m in list(mol.information.keys()) if m not in main_items]\n+            other_items = ' '.join(other_items)\n+\n+            natoms = len(mol.atoms)\n+            npairs = len(mol.pairs)\n+            nbonds = len(mol.bonds)\n+            nangles= len(mol.angles)\n+            ndih   = len(mol.dihedrals)\n+            nimp   = len(mol.impropers)\n+            msg = '{:20s}  {:7d} {:7d} {:7d} {:7d} {:7d} {:7d}    {:s}'.format(mol.name, natoms, npairs, nbonds, nangles, ndih, nimp, other_items)\n+            data.append(msg)\n+\n+\n+\n+\n+        return '\\n'.join(data)\n+\n+\n+\n+\n+    def _parse(self, fname):\n+\n+        _find_section = lambda line: line.strip('[').strip(']').strip()\n+\n+        def _add_info(sys_or_mol, section, container):\n+            # like (mol, 'atomtypes', mol.atomtypes)\n+            if sys_or_mol.information.get(section, False) is False:\n+                sys_or_mol.information[section] = container\n+\n+        mol        = None   # to hold the current mol\n+        curr_sec   = None\n+        cmap_lines = []\n+\n+        with open(fname) as f:\n+            for i_line, line in enumerate(f):\n+\n+                # trimming\n+                if ';' in line:\n+                    line = line[0:line.index(';')]\n+                line = line.strip()\n+\n+                if line == '':\n+                    continue\n+\n+                if line[0] == '*':\n+                    continue\n+\n+                # the topology must be stand-alone (i.e. no includes)\n+                if line.startswith('#include'):\n+                    msg = 'The topology file has \"#include\" statements.'\n+                    msg+= ' You must provide a processed topology file that grompp creates.'\n+                    raise ValueError(msg)\n+\n+                # find sections\n+                if line[0] == '[':\n+                    curr_sec = _find_section(line)\n+                    self.found_sections.append(curr_sec)\n+                    continue\n+\n+                fields = line.split()\n+\n+                if curr_sec == 'defaults':\n+                    '''\n+                    # ; nbfunc        comb-rule       gen-pairs       fudgeLJ fudgeQQ\n+                    #1               2               yes             0.5     0.8333\n+                    '''\n+\n+                    assert len(fields) == 5\n+\n+                    self.defaults['nbfunc']    = int(fields[0])\n+                    self.defaults['comb-rule'] = int(fields[1])\n+                    self.defaults['gen-pairs'] = fields[2]\n+                    self.defaults['fudgeLJ']   = float(fields[3])\n+                    self.defaults['fudgeQQ']   = float(fields[4])\n+\n+                elif curr_sec == 'atomtypes':\n+                    '''\n+                    # ;name               at.num    mass         charge    ptype  sigma   epsilon\n+                    # ;name   bond_type   at.num    mass         charge    ptype  sigma   epsilon\n+                    '''\n+\n+                    if len(fields) not in (7,8):\n+                        print('skipping atomtype line with neither 7 or 8 fields: \\n %s' % line)\n+                        continue\n+\n+                    shift = 0 if len(fields) == 7 else 1\n+                    at = blocks.AtomType('gromacs')\n+                    at.atype = fields[0]\n+                    if shift == 1: at.bond_type = fields[1]\n+\n+                    at.mass  = float(fields[2+shift])\n+                    at.charge= float(fields[3+shift])\n+\n+                    particletype = fields[4+shift]\n+                    assert particletype in ('A', 'S', 'V', 'D')\n+                    if particletype not in ('A',):\n+                        print('warning: non-atom particletype: \"%s\"' % line)\n+\n+                    sig = float(fields[5+shift])\n+                    eps = float(fields[6+shift])\n+\n+                    at.gromacs= {'param': {'lje':eps, 'ljl':sig, 'lje14':None, 'ljl14':None} }\n+\n+                    self.atomtypes.append(at)\n+\n+                    _add_info(self, curr_sec, self.atomtypes)\n+\n+\n+                # extend system.molecules\n+                elif curr_sec == 'moleculetype':\n+                    assert len(fields) == 2\n+\n+                    mol = blocks.Molecule()\n+\n+                    mol.name = fields[0]\n+                    mol.exclusion_numb = int(fields[1])\n+\n+                    self.dict_molname_mol[mol.name] = mol\n+\n+\n+                elif curr_sec == 'atoms':\n+                    '''\n+                    #id    at_type     res_nr  residu_name at_name  cg_nr  charge   mass  typeB    chargeB      massB\n+                    # 1       OC          1       OH          O1       1      -1.32\n+\n+                    OR\n+\n+                    [ atoms ]\n+                    ; id   at type  res nr  residu name at name     cg nr   charge\n+                    1       OT      1       SOL              OW             1       -0.834\n+\n+                    '''\n+\n+                    aserial = int(fields[0])\n+                    atype   = fields[1]\n+                    resnumb = int(fields[2])\n+                    resname = fields[3]\n+                    aname   = fields[4]\n+                    cgnr    = int(fields[5])\n+                    charge  = float(fields[6])\n+                    rest = fields[7:]\n+\n+                    atom         = blocks.Atom()\n+                    atom.name    = aname\n+                    atom.atomtype= atype\n+                    atom.number  = aserial\n+                    atom.resname = resname\n+                    atom.resnumb = resnumb\n+                    atom.charge  = charge\n+\n+                    if len(rest) >= 1:\n+                        mass = float(rest[0])\n+                        atom.mass = mass\n+\n+                    mol.atoms.append(atom)\n+\n+                    _add_info(mol, curr_sec, mol.atoms)\n+\n+                elif curr_sec in ('pairtypes', 'pairs', 'pairs_nb'):\n+                    '''\n+                    section     #at     fu      #param\n+                    ---------------------------------\n+                    pairs       2       1       V,W\n+                    pairs       2       2       fudgeQQ, qi, qj, V, W\n+                    pairs_nb    2       1       qi, qj, V, W\n+\n+                    '''\n+\n+                    ai, aj = fields[:2]\n+                    fu     = int(fields[2])\n+                    assert fu in (1,2)\n+\n+                    pair = blocks.InteractionType('gromacs')\n+                    if fu == 1:\n+                        if curr_sec=='pairtypes':\n+                            pair.atype1 = ai\n+                            pair.atype2 = aj\n+                            v, w = list(map(float, fields[3:5]))\n+                            pair.gromacs = {'param': {'lje':None, 'ljl':None, 'lje14':w, 'ljl14':v}, 'func':fu }\n+\n+                            self.pairtypes.append(pair)\n+                            _add_info(self, curr_sec, self.pairtypes)\n+\n+                        elif curr_sec == 'pairs':\n+                            ai, aj = list( map(int, [ai,aj]) )\n+                            pair.atom1 = mol.atoms[ai-1]\n+                            pair.atom2 = mol.atoms[aj-1]\n+                            pair.gromacs['func'] = fu\n+\n+                            mol.pairs.append(pair)\n+                            _add_info(mol, curr_sec, mol.pairs)\n+\n+                        else:\n+                            raise ValueError\n+\n+                    else:\n+                        raise NotImplementedError('%s with functiontype %d is not supported' % (curr_sec,fu))\n+\n+                elif curr_sec == 'nonbond_params':\n+                    '''\n+                    ; typei typej  f.type sigma   epsilon\n+                    ; f.type=1 means LJ (not buckingham)\n+                    ; sigma&eps since mixing-rule = 2          \n+                    '''\n+\n+                    assert len(fields) == 5\n+                    ai, aj = fields[:2]\n+                    fu     = int(fields[2])\n+\n+                    assert fu == 1\n+                    sig    = float(fields[3])\n+                    eps    = float(fields[4])\n+\n+                    nonbond_param = blocks.NonbondedParamType('gromacs')\n+                    nonbond_param.atype1 = ai\n+                    nonbond_param.atype2 = aj\n+                    nonbond_param.gromacs['func'] = fu\n+                    nonbond_param.gromacs['param'] = {'eps': eps, 'sig': sig} \n+\n+                    self.nonbond_params.append(nonbond_param)\n+                    _add_info(self, curr_sec, self.nonbond_params)\n+\n+                elif curr_sec in ('bondtypes', 'bonds'):\n+                    '''\n+                    section     #at     fu      #param\n+                    ----------------------------------\n+                    bonds       2       1       2\n+                    bonds       2       2       2\n+                    bonds       2       3       3\n+                    bonds       2       4       2\n+                    bonds       2       5       ??\n+                    bonds       2       6       2\n+                    bonds       2       7       2\n+                    bonds       2       8       ??\n+                    bonds       2       9       ??\n+                    bonds       2       10      4\n+                    '''\n+\n+                    ai, aj = fields[:2]\n+                    fu     = int(fields[2])\n+                    assert fu in (1,2,3,4,5,6,7,8,9,10)\n+\n+                    if fu != 1:\n+                        raise NotImplementedError('function %d is not yet supported' % fu)\n+\n+                    bond = blocks.BondType('gromacs')\n+\n+                    if fu == 1:\n+                        if curr_sec == 'bondtypes':\n+                            bond.atype1 = ai\n+                            bond.atype2 = aj\n+                            b0, kb = list(map(float, fields[3:5]))\n+\n+                            bond.gromacs = {'param':{'kb':kb, 'b0':b0}, 'func':fu}\n+\n+                            self.bondtypes.append(bond)\n+                            _add_info(self, curr_sec, self.bondtypes)\n+\n+                        elif curr_sec == 'bonds':\n+                            ai, aj = list(map(int, [ai, aj]))\n+                            bond.atom1 = mol.atoms[ai-1]\n+                            bond.atom2 = mol.atoms[aj-1]\n+                            bond.gromacs['func'] = fu\n+\n+                            mol.bonds.append(bond)\n+                            _add_info(mol, curr_sec, mol.bonds)\n+\n+                    else:\n+                        raise NotImplementedError\n+\n+                elif curr_sec in ('angletypes', 'angles'):\n+                    '''\n+                    section     #at     fu      #param\n+                    ----------------------------------\n+                    angles      3       1       2\n+                    angles      3       2       2\n+                    angles      3       3       3\n+                    angles      3       4       4\n+                    angles      3       5       4\n+                    angles      3       6       6\n+                    angles      3       8       ??\n+                    '''\n+\n+                    ai, aj , ak = fields[:3]\n+                    fu          = int(fields[3])\n+                    assert fu in (1,2,3,4,5,6,8)  # no 7\n+\n+                    if fu not in (1,5):\n+                        raise NotImplementedError('function %d is not yet supported' % fu)\n+\n+                    ang = blocks.AngleType('gromacs')\n+                    if fu == 1:\n+                        if curr_sec == 'angletypes':\n+                            ang.atype1 = ai\n+                            ang.atype2 = aj\n+                            ang.atype3 = ak\n+\n+                            tetha0, ktetha = list(map(float, fields[4:6]))\n+                            ang.gromacs = {'param':{'ktetha':ktetha, 'tetha0':tetha0, 'kub':None, 's0':None}, 'func':fu}\n+\n+                            self.angletypes.append(ang)\n+                            _add_info(self, curr_sec, self.angletypes)\n+\n+                        elif curr_sec == 'angles':\n+                            ai, aj, ak = list(map(int, [ai, aj, ak]))\n+                            ang.atom1 = mol.atoms[ai-1]\n+                            ang.atom2 = mol.atoms[aj-1]\n+                            ang.atom3 = mol.atoms[ak-1]\n+                            ang.gromacs['func'] = fu\n+\n+                            mol.angles.append(ang)\n+                            _add_info(mol, curr_sec, mol.angles)\n+\n+                        else:\n+                            raise ValueError\n+\n+                    elif fu == 5:\n+                        if curr_sec == 'angletypes':\n+                            ang.atype1 = ai\n+                            ang.atype2 = aj\n+                            ang.atype3 = ak\n+                            tetha0, ktetha, s0, kub = list(map(float, fields[4:8]))\n+\n+                            ang.gromacs = {'param':{'ktetha':ktetha, 'tetha0':tetha0, 'kub':kub, 's0':s0}, 'func':fu}\n+\n+                            self.angletypes.append(ang)\n+                            _add_info(self, curr_sec, self.angletypes)\n+\n+                        elif curr_sec == 'angles':\n+                            ai, aj, ak = list(map(int, [ai, aj, ak]))\n+                            ang.atom1 = mol.atoms[ai-1]\n+                            ang.atom2 = mol.atoms[aj-1]\n+                            ang.atom3 = mol.atoms[ak-1]\n+                            ang.gromacs['func'] = fu\n+\n+                            mol.angles.append(ang)\n+                            _add_info(mol, curr_sec, mol.angles)\n+\n+                        else:\n+                            raise ValueError\n+\n+                    else:\n+                        raise NotImplementedError\n+\n+\n+                elif curr_sec in  ('dihedraltypes', 'dihedrals'):\n+                    '''\n+                    section     #at     fu      #param\n+                    ----------------------------------\n+                    dihedrals   4       1       3\n+                    dihedrals   4       2       2\n+                    dihedrals   4       3       6\n+                    dihedrals   4       4       3\n+                    dihedrals   4       5       4\n+                    dihedrals   4       8       ??\n+                    dihedrals   4       9       3\n+                    '''\n+\n+                    if curr_sec == 'dihedraltypes' and len(fields) == 6:\n+                        # in oplsaa - quartz parameters\n+                        fields.insert(2, 'X')\n+                        fields.insert(0, 'X')\n+\n+                    ai, aj, ak, am = fields[:4]\n+                    fu = int(fields[4])\n+                    assert fu in (1,2,3,4,5,8,9)\n+\n+                    if fu not in (1,2,3,4,9):\n+                        raise NotImplementedError('function %d is not yet supported' % fu)\n+\n+                    dih = blocks.DihedralType('gromacs')\n+                    imp = blocks.ImproperType('gromacs')\n+\n+                    if fu in (1,3,4,9):\n+                        if curr_sec == 'dihedraltypes':\n+                            dih.atype1 = ai\n+                            dih.atype2 = aj\n+                            dih.atype3 = ak\n+                            dih.atype4 = am\n+\n+                            dih.line = i_line + 1  \n+\n+                            if fu == 1:\n+                                delta, kchi, n = list(map(float, fields[5:8]))\n+                                dih.gromacs['param'].append({'kchi':kchi, 'n':n, 'delta':delta})\n+                            elif fu == 3:\n+                                c0, c1, c2, c3, c4, c5 = list(map(float, fields[5:11]))\n+                                m = dict(c0=c0, c1=c1, c2=c2, c3=c3, c4=c4, c5=c5)\n+                                dih.gromacs['param'].append(m)\n+                            elif fu == 4:\n+                                delta, kchi, n = list(map(float, fields[5:8]))\n+                                dih.gromacs['param'].append({'kchi':kchi, 'n':int(n), 'delta':delta})                                                                                               \n+                            elif fu == 9:\n+                                delta, kchi, n = list(map(float, fields[5:8]))\n+                                dih.gromacs['param'].append({'kchi':kchi, 'n':int(n), 'delta':delta})\n+                            else:\n+                                raise ValueError\n+\n+                            dih.gromacs['func'] = fu\n+                            self.dihedraltypes.append(dih)\n+                            _add_info(self, curr_sec, self.dihedraltypes)\n+\n+                        elif curr_sec == 'dihedrals':\n+                            ai, aj, ak, am = list(map(int, fields[:4]))\n+                            dih.atom1 = mol.atoms[ai-1]\n+                            dih.atom2 = mol.atoms[aj-1]\n+                            dih.atom3 = mol.atoms[ak-1]\n+                            dih.atom4 = mol.atoms[am-1]\n+                            dih.gromacs['func'] = fu\n+\n+                            dih.line = i_line + 1\n+\n+                            if fu == 1:\n+                                pass\n+                            elif fu == 3:\n+                                pass\n+                            elif fu == 4:\n+                                pass                                \n+                            elif fu == 9:\n+                                if len(fields[5:8]) == 3:\n+                                    delta, kchi, n = list(map(float, fields[5:8]))\n+                                    dih.gromacs['param'].append({'kchi':kchi, 'n':int(n), 'delta':delta})\n+                            else:\n+                                raise ValueError\n+\n+                            mol.dihedrals.append(dih)\n+                            _add_info(mol, curr_sec, mol.dihedrals)\n+\n+                        else:\n+                            raise ValueError\n+\n+                    elif fu in (2,4):\n+                        if curr_sec == 'dihedraltypes':\n+                            imp.atype1 = ai\n+                            imp.atype2 = aj\n+                            imp.atype3 = ak\n+                            imp.atype4 = am\n+\n+                            imp.line = i_line + 1\n+\n+                            if fu == 2:\n+                                psi0 , kpsi = list(map(float, fields[5:7]))\n+                                imp.gromacs['param'].append({'kpsi':kpsi, 'psi0': psi0})\n+                            elif fu == 4:\n+                                psi0 , kpsi, n = list(map(float, fields[5:8]))\n+                                imp.gromacs['param'].append({'kpsi':kpsi, 'psi0': psi0, 'n':n})\n+                            else:\n+                                raise ValueError\n+\n+                            imp.gromacs['func'] = fu\n+                            self.impropertypes.append(imp)\n+                            _add_info(self, curr_sec, self.impropertypes)\n+\n+                        elif curr_sec == 'dihedrals':\n+                            ai, aj, ak, am = list(map(int, fields[:4]))\n+                            imp.atom1 = mol.atoms[ai-1]\n+                            imp.atom2 = mol.atoms[aj-1]\n+                            imp.atom3 = mol.atoms[ak-1]\n+                            imp.atom4 = mol.atoms[am-1]\n+                            imp.gromacs['func'] = fu\n+\n+                            imp.line = i_line + 1\n+\n+                            if fu == 2:\n+                                pass\n+                            elif fu == 4:\n+                                pass\n+                            else:\n+                                raise ValueError\n+\n+                            mol.impropers.append(imp)\n+                            _add_info(mol, curr_sec, mol.impropers)\n+\n+                        else:\n+                            raise ValueError\n+\n+                    else:\n+                        raise NotImplementedError\n+\n+\n+                elif curr_sec in ('cmaptypes', 'cmap'):\n+\n+                    cmap = blocks.CMapType('gromacs')\n+                    if curr_sec == 'cmaptypes':\n+                        cmap_lines.append(line)\n+                        _add_info(self, curr_sec, self.cmaptypes)\n+                    else:\n+                        ai, aj, ak, am, an = list(map(int, fields[:5]))\n+                        fu = int(fields[5])\n+                        assert fu == 1\n+                        cmap.atom1 = mol.atoms[ai-1]\n+                        cmap.atom2 = mol.atoms[aj-1]\n+                        cmap.atom3 = mol.atoms[ak-1]\n+                        cmap.atom4 = mol.atoms[am-1]\n+                        cmap.atom8 = mol.atoms[an-1]\n+                        cmap.gromacs['func'] = fu\n+\n+                        mol.cmaps.append(cmap)\n+                        _add_info(mol, curr_sec, mol.cmaps)\n+\n+\n+                elif curr_sec == 'settles':\n+                    '''\n+                    section     #at     fu      #param\n+                    ----------------------------------\n+                    '''\n+\n+                    assert len(fields) == 4\n+                    ai = int(fields[0])\n+                    fu = int(fields[1])\n+                    assert fu == 1\n+\n+                    settle = blocks.SettleType('gromacs')\n+                    settle.atom = mol.atoms[ai-1]\n+                    settle.dOH = float(fields[2])\n+                    settle.dHH = float(fields[3])\n+\n+                    mol.settles.append(settle)\n+                    _add_info(mol, curr_sec, mol.settles)\n+\n+                elif curr_sec == \"virtual_sites3\":\n+                    '''\n+                        ; Dummy from            funct   a       b\n+                        4   1   2   3   1   0.131937768 0.131937768                    \n+                    '''\n+                    assert len(fields) == 7\n+                    ai = int(fields[0])\n+                    aj = int(fields[1])\n+                    ak = int(fields[2])\n+                    al = int(fields[3])\n+                    fu = int(fields[4])\n+                    assert fu == 1\n+                    a = float(fields[5])\n+                    b = float(fields[6])\n+\n+                    vs3 = blocks.VirtualSites3Type('gromacs')\n+                    vs3.atom1 = ai\n+                    vs3.atom2 = aj\n+                    vs3.atom3 = ak\n+                    vs3.atom4 = al\n+                    vs3.gromacs['func'] = fu\n+                    vs3.gromacs['param'] = { 'a': a, 'b':b }\n+                    mol.virtual_sites3.append(vs3)\n+                    _add_info(mol, curr_sec, mol.virtual_sites3)\n+\n+\n+                elif curr_sec in ('exclusions',):\n+                    ai = int(fields[0])\n+                    other = list(map(int, fields[1:]))\n+\n+                    exc = blocks.Exclusion()\n+                    exc.main_atom  = mol.atoms[ai-1]\n+                    exc.other_atoms= [mol.atoms[k-1] for k in other]\n+\n+                    mol.exclusions.append(exc)\n+                    _add_info(mol, curr_sec, mol.exclusions)\n+\n+\n+                elif curr_sec in ('constrainttypes', 'constraints'):\n+                    '''\n+                    section     #at     fu      #param\n+                    ----------------------------------\n+                    constraints 2       1       1\n+                    constraints 2       2       1\n+                    '''\n+\n+                    ai, aj = fields[:2]\n+                    fu = int(fields[2])\n+                    assert fu in (1,2)\n+\n+                    cons = blocks.ConstraintType('gromacs')\n+\n+                    # TODO: what's different between 1 and 2\n+                    if fu == 1 or fu == 2:\n+                        if curr_sec == 'constrainttypes':\n+                            cons.atype1 = ai\n+                            cons.atype2 = aj\n+                            b0 = float(fields[3])\n+                            cons.gromacs = {'param':{'b0':b0}, 'func': fu}\n+\n+                            self.constrainttypes.append(cons)\n+                            _add_info(self, curr_sec, self.constrainttypes)\n+\n+                        elif curr_sec == 'constraints':\n+                            ai, aj = list(map(int, fields[:2]))\n+                            cons.atom1 = mol.atoms[ai-1]\n+                            cons.atom2 = mol.atoms[aj-1]\n+                            cons.gromacs['func'] = fu\n+\n+                            mol.constraints.append(cons)\n+                            _add_info(mol, curr_sec, mol.constraints)\n+\n+                        else:\n+                            raise ValueError\n+                    else:\n+                        raise ValueError\n+\n+                elif curr_sec in ('position_restraints',\n+                                  'distance_restraints',\n+                                  'dihedral_restraints',\n+                                  'orientation_restraints',\n+                                  'angle_restraints',\n+                                  'angle_restraints_z'):\n+                    pass\n+\n+\n+                elif curr_sec in ('implicit_genborn_params',):\n+                    '''\n+                    attype   sar     st      pi      gbr      hct\n+                    '''\n+                    pass\n+\n+                elif curr_sec == 'system':\n+                    #assert len(fields) == 1\n+                    self.name = fields[0]\n+\n+\n+                elif curr_sec == 'molecules':\n+                    assert len(fields) == 2\n+                    mname, nmol = fields[0], int(fields[1])\n+\n+                    # if the number of a molecule is more than 1, add copies to system.molecules\n+                    for i in range(nmol):\n+                        self.molecules.append(self.dict_molname_mol[mname])\n+\n+                else:\n+                    print('Uknown section in topology: %s' % curr_sec)\n+        \n+        # process cmap_lines\n+        curr_cons = None\n+        for line in cmap_lines:\n+\n+            # cmaptype opening line\n+            if len(line.split()) == 8:\n+                cons = blocks.CMapType('gromacs')\n+                \n+                atype1, atype2, atype3, atype4, atype8, func, sizeX, sizeY = line.replace(\"\\\\\",\"\").split()\n+                func, sizeX, sizeY = int(func), int(sizeX), int(sizeY)\n+                cons.atype1 = atype1\n+                cons.atype2 = atype2\n+                cons.atype3 = atype3\n+                cons.atype4 = atype4\n+                cons.atype8 = atype8\n+                cons.gromacs = {'param':[], 'func': func}\n+\n+                curr_cons = cons\n+\n+            # cmap body\n+            elif len(line.split()) == 10:\n+                cmap_param = map(float, line.replace(\"\\\\\",\"\").split())\n+                cons.gromacs['param'] += cmap_param\n+\n+            # cmaptype cloning line\n+            elif len(line.split()) == 6:\n+                cmap_param = map(float, line.replace(\"\\\\\",\"\").split())\n+                cons.gromacs['param'] += cmap_param\n+                self.cmaptypes.append(curr_cons)\n+            else:\n+                raise ValueError\n+\n+\n+\n+class SystemToGroTop(object):\n+\n+    formats = {\n+        'atomtypes'      : '{:<7s} {:3s} {:3d} {:>7.6f}   {:4.3f}   {:3s}     {:14.12f}     {:10.9f}  \\n',\n+        'atoms'          : '{:6d} {:>10s} {:6d} {:6s} {:6s} {:6d} {:f} {:11.4f} \\n',\n+        'atoms_nomass'   : '{:6d} {:>10s} {:6d} {:6s} {:6s} {:6d} {:f}\\n',\n+        'nonbond_params' : '{:20s}  {:20s}  {:1d}  {:10.5f}  {:10.5f}\\n',\n+        'bondtypes'      : '{:5s}  {:5s}  {:1d}  {:6.4f}  {:6.1f}\\n',\n+        'bonds'          : '{:3d}  {:3d}   {:1d}\\n',\n+        'settles'        : '{:3d}  {:3d}  {:11.5f} {:11.5f}\\n',\n+        'virtual_sites3' : '{:3d}  {:3d}  {:3d}  {:3d}   {:1d}  {:12.10f}  {:12.10f}\\n',\n+        'exclusions'     : '{:3d}  {:3d}  {:3d}\\n',\n+        'pairtypes'      : '{:6s} {:6s}   {:d}    {:14.12f}     {:14.12f}    \\n',\n+        'pairs'          : '{:3d} {:3d}   {:1d}\\n',\n+        'angletypes_1'   : '{:>8s} {:>8s} {:>8s} {:1d}    {:8.4f}    {:10.5f}\\n',\n+        'angletypes_5'   : '{:>8s} {:>8s} {:>8s} {:1d}    {:8.4f}    {:10.5f}    {:9.5f}    {:11.5f}\\n',\n+        'constrainttypes': '{:6s} {:6s} {:1d}    {:8.6f}\\n',\n+        'angles'         : '{:3d} {:3d} {:3d}   {:1d}\\n',\n+        'dihedraltypes'  : '{:6s} {:6s} {:6s} {:6s}   {:1d}    {:6.2f}    {:f}    {:1d}\\n',\n+        'dihedrals'      : '{:3d} {:3d} {:3d} {:3d}   {:1d}\\n',\n+        'dihedrals_ext'  : '{:3d} {:3d} {:3d} {:3d}   {:1d}    {:6.2f}    {:f}    {:1d}\\n',\n+        'impropertypes'  : '{:6s} {:6s} {:6s} {:6s}   {:1d} {:6.2f} {:8.4f} \\n',\n+        'impropers'      : '{:3d} {:3d} {:3d} {:3d}   {:1d}\\n',\n+        'impropers_ext'  : '{:3d} {:3d} {:3d} {:3d}   {:1d} {:6.2f} {:8.4f} \\n',\n+    }\n+\n+\n+    toptemplate = \"\"\n+    toptemplate += \"[ defaults ]      \\n*DEFAULTS*    \\n\"\n+    toptemplate += \"[ atomtypes ]      \\n*ATOMTYPES*    \\n\"\n+    toptemplate += \"[ nonbond_params ] \\n*NONBOND_PARAM* \\n\"\n+    toptemplate += \"[ pairtypes ]    \\n*PAIRTYPES*    \\n\"\n+    toptemplate += \"[ bondtypes ]    \\n*BONDTYPES*    \\n\"\n+    toptemplate += \"[ angletypes ]   \\n*ANGLETYPES*   \\n\"\n+    toptemplate += \"[ constrainttypes ]   \\n*CONSTRAINTTYPES*   \\n\"\n+    toptemplate += \"[ dihedraltypes ]\\n*DIHEDRALTYPES*\\n\"\n+    toptemplate += \"[ dihedraltypes ]\\n*IMPROPERTYPES*\\n\"\n+    toptemplate += \"[ cmaptypes ]    \\n*CMAPTYPES*\\n\"\n+\n+    itptemplate = \"\"\n+    itptemplate += \"[ moleculetype ] \\n*MOLECULETYPE* \\n\"\n+    itptemplate += \"[ atoms ]        \\n*ATOMS*        \\n\"\n+    itptemplate += \"[ bonds ]        \\n*BONDS*        \\n\"\n+    itptemplate += \"[ pairs ]        \\n*PAIRS*        \\n\"\n+    itptemplate += \"[ settles ]        \\n*SETTLES*        \\n\"\n+    itptemplate += \"[ virtual_sites3 ]        \\n*VIRTUAL_SITES3*        \\n\"\n+    itptemplate += \"[ exclusions ]        \\n*EXCLUSIONS*        \\n\"\n+    itptemplate += \"[ angles ]       \\n*ANGLES*       \\n\"\n+    itptemplate += \"[ dihedrals ]    \\n*DIHEDRALS*    \\n\"\n+    itptemplate += \"[ dihedrals ]    \\n*IMPROPERS*    \\n\"\n+    itptemplate += \"[ cmap ]        \\n*CMAPS*    \\n\"\n+\n+\n+\n+\n+    def __init__(self, psfsystem, outfile=\"top.top\", multiple_output=False):\n+        self.lgr = logging.getLogger('gromacs.fileformats.SystemToGroTop')\n+        self.lgr.debug(\">> entering SystemToGroTop\")\n+\n+        self.system   = psfsystem\n+        self.outfile = outfile\n+        self.multiple_output = multiple_output\n+        self.assemble_topology()\n+\n+        self.lgr.debug(\"<< leaving SystemToGroTop\")\n+\n+\n+    @staticmethod\n+    def _redefine_atomtypes(mol):\n+\n+        i = 1\n+\n+        for atom in mol.atoms:\n+            atom.atomtype = 'at%03d' % i\n+            i += 1\n+\n+\n+    def assemble_topology(self, redefine_atom_types = False):\n+\n+        self.lgr.debug(\"starting to assemble topology...\")\n+\n+        top = '[ defaults ] ; \\n'\n+        top += ';nbfunc    comb-rule    gen-pairs    fudgeLJ    fudgeQQ \\n'\n+\n+        if self.system.forcefield == 'charmm':\n+            top += '1          2           yes          1.0       1.0 \\n'\n+\n+        self.lgr.debug(\"making atom/pair/bond/angle/dihedral/improper types\")\n+        top += self.toptemplate\n+        top = top.replace('*DEFAULTS*',       ''.join( self._make_defaults(self.system)) )\n+        top = top.replace('*ATOMTYPES*',      ''.join( self._make_atomtypes(self.system)) )\n+        top = top.replace('*NONBOND_PARAM*',  ''.join( self._make_nonbond_param(self.system)) )\n+        top = top.replace('*PAIRTYPES*',      ''.join( self._make_pairtypes(self.system)) )\n+        top = top.replace('*BONDTYPES*',      ''.join( self._make_bondtypes(self.system)) )\n+        top = top.replace('*CONSTRAINTTYPES*',''.join( self._make_constrainttypes(self.system)))\n+        top = top.replace('*ANGLETYPES*',     ''.join( self._make_angletypes(self.system)))\n+        top = top.replace('*DIHEDRALTYPES*',  ''.join( self._make_dihedraltypes(self.system)) )\n+        top = top.replace('*IMPROPERTYPES*',  ''.join( self._make_impropertypes(self.system)) )\n+        top = top.replace('*CMAPTYPES*',      ''.join( self._make_cmaptypes(self.system)) )\n+\n+\n+        for i,(molname,m) in enumerate(self.system.dict_molname_mol.items()):\n+\n+            itp = self.itptemplate\n+            itp = itp.replace('*MOLECULETYPE*',  ''.join( self._make_moleculetype(m, molname))  )\n+            itp = itp.replace('*ATOMS*',         ''.join( self._make_atoms(m))  )\n+            itp = itp.replace('*BONDS*',         ''.join( self._make_bonds(m))  )\n+            itp = itp.replace('*PAIRS*',         ''.join( self._make_pairs(m))  )\n+            itp = itp.replace('*SETTLES*',       ''.join( self._make_settles(m))  )\n+            itp = itp.replace('*VIRTUAL_SITES3*',''.join( self._make_virtual_sites3(m))  )\n+            itp = itp.replace('*EXCLUSIONS*',    ''.join( self._make_exclusions(m))  )\n+            itp = itp.replace('*ANGLES*',        ''.join( self._make_angles(m)) )\n+            itp = itp.replace('*DIHEDRALS*',     ''.join( self._make_dihedrals(m)) )\n+            itp = itp.replace('*IMPROPERS*',     ''.join( self._make_impropers(m)) )\n+            itp = itp.replace('*CMAPS*',         ''.join( self._make_cmaps(m)) )\n+            if not self.multiple_output:\n+                top += itp\n+            else:\n+                outfile = \"mol_{}.itp\".format(molname)\n+                top += '#include \"mol_%s.itp\" \\n' % molname                \n+                with open(outfile, \"w\") as f:\n+                    f.writelines([itp])\n+\n+        top += '\\n[system]  \\nConvertedSystem\\n\\n'\n+        top += '[molecules] \\n'\n+        molecules = [(\"\", 0)]\n+\n+        for m in self.system.molecules:\n+            if (molecules[-1][0] != m.name): \n+                molecules.append([m.name, 0])\n+            if molecules[-1][0] == m.name:\n+                molecules[-1][1] += 1\n+\n+        for molname, n in molecules[1:]:\n+            top += '%s     %s\\n' % (molname, n)\n+        top += '\\n'\n+\n+        with open(self.outfile, 'w') as f:\n+            f.writelines([top])\n+\n+        return\n+        for i, m in enumerate(self.system.molecules):\n+            molname = 'mol_%02d' % (i+1)\n+            top += '#include \"itp_%s.itp\" \\n' % molname\n+","path":"gromacs/fileformats/top.py","position":870,"original_position":870,"commit_id":"07d3a24dcf118041d2d9af652aa47ba9efb87f9d","original_commit_id":"07d3a24dcf118041d2d9af652aa47ba9efb87f9d","user":{"login":"orbeckst","id":237980,"avatar_url":"https://avatars.githubusercontent.com/u/237980?v=3","gravatar_id":"","url":"https://api.github.com/users/orbeckst","html_url":"https://github.com/orbeckst","followers_url":"https://api.github.com/users/orbeckst/followers","following_url":"https://api.github.com/users/orbeckst/following{/other_user}","gists_url":"https://api.github.com/users/orbeckst/gists{/gist_id}","starred_url":"https://api.github.com/users/orbeckst/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/orbeckst/subscriptions","organizations_url":"https://api.github.com/users/orbeckst/orgs","repos_url":"https://api.github.com/users/orbeckst/repos","events_url":"https://api.github.com/users/orbeckst/events{/privacy}","received_events_url":"https://api.github.com/users/orbeckst/received_events","type":"User","site_admin":false},"body":"why all the white space?? (Generally, I'd cut down on empty lines and only do 1 line between functions/methods, 2 lines between classes)","created_at":"2015-12-15T06:04:13Z","updated_at":"2015-12-15T06:04:13Z","html_url":"https://github.com/Becksteinlab/GromacsWrapper/pull/25#discussion_r47599492","pull_request_url":"https://api.github.com/repos/Becksteinlab/GromacsWrapper/pulls/25","_links":{"self":{"href":"https://api.github.com/repos/Becksteinlab/GromacsWrapper/pulls/comments/47599492"},"html":{"href":"https://github.com/Becksteinlab/GromacsWrapper/pull/25#discussion_r47599492"},"pull_request":{"href":"https://api.github.com/repos/Becksteinlab/GromacsWrapper/pulls/25"}}},"pull_request":{"url":"https://api.github.com/repos/Becksteinlab/GromacsWrapper/pulls/25","id":53629957,"html_url":"https://github.com/Becksteinlab/GromacsWrapper/pull/25","diff_url":"https://github.com/Becksteinlab/GromacsWrapper/pull/25.diff","patch_url":"https://github.com/Becksteinlab/GromacsWrapper/pull/25.patch","issue_url":"https://api.github.com/repos/Becksteinlab/GromacsWrapper/issues/25","number":25,"state":"open","locked":false,"title":"Itp reader","user":{"login":"jandom","id":395931,"avatar_url":"https://avatars.githubusercontent.com/u/395931?v=3","gravatar_id":"","url":"https://api.github.com/users/jandom","html_url":"https://github.com/jandom","followers_url":"https://api.github.com/users/jandom/followers","following_url":"https://api.github.com/users/jandom/following{/other_user}","gists_url":"https://api.github.com/users/jandom/gists{/gist_id}","starred_url":"https://api.github.com/users/jandom/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jandom/subscriptions","organizations_url":"https://api.github.com/users/jandom/orgs","repos_url":"https://api.github.com/users/jandom/repos","events_url":"https://api.github.com/users/jandom/events{/privacy}","received_events_url":"https://api.github.com/users/jandom/received_events","type":"User","site_admin":false},"body":"hi Oli, \r\n\r\nI've had this feature in gromacs wrapper for a long time now... it's time to push out and give back to the community. it comes with a number of tests (bash scripts and python scripts) that check both the gromacs energies (mdrun-rerun) and consistency of the itp/top files produced\r\n\r\nCheers, \r\n\r\n- Jan","created_at":"2015-12-14T22:13:51Z","updated_at":"2015-12-15T06:04:14Z","closed_at":null,"merged_at":null,"merge_commit_sha":"98f6c4ef74902980650a068d30c1bb9c1c08c7a1","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/Becksteinlab/GromacsWrapper/pulls/25/commits","review_comments_url":"https://api.github.com/repos/Becksteinlab/GromacsWrapper/pulls/25/comments","review_comment_url":"https://api.github.com/repos/Becksteinlab/GromacsWrapper/pulls/comments{/number}","comments_url":"https://api.github.com/repos/Becksteinlab/GromacsWrapper/issues/25/comments","statuses_url":"https://api.github.com/repos/Becksteinlab/GromacsWrapper/statuses/07d3a24dcf118041d2d9af652aa47ba9efb87f9d","head":{"label":"jandom:itp-reader","ref":"itp-reader","sha":"07d3a24dcf118041d2d9af652aa47ba9efb87f9d","user":{"login":"jandom","id":395931,"avatar_url":"https://avatars.githubusercontent.com/u/395931?v=3","gravatar_id":"","url":"https://api.github.com/users/jandom","html_url":"https://github.com/jandom","followers_url":"https://api.github.com/users/jandom/followers","following_url":"https://api.github.com/users/jandom/following{/other_user}","gists_url":"https://api.github.com/users/jandom/gists{/gist_id}","starred_url":"https://api.github.com/users/jandom/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jandom/subscriptions","organizations_url":"https://api.github.com/users/jandom/orgs","repos_url":"https://api.github.com/users/jandom/repos","events_url":"https://api.github.com/users/jandom/events{/privacy}","received_events_url":"https://api.github.com/users/jandom/received_events","type":"User","site_admin":false},"repo":{"id":47986241,"name":"GromacsWrapper","full_name":"jandom/GromacsWrapper","owner":{"login":"jandom","id":395931,"avatar_url":"https://avatars.githubusercontent.com/u/395931?v=3","gravatar_id":"","url":"https://api.github.com/users/jandom","html_url":"https://github.com/jandom","followers_url":"https://api.github.com/users/jandom/followers","following_url":"https://api.github.com/users/jandom/following{/other_user}","gists_url":"https://api.github.com/users/jandom/gists{/gist_id}","starred_url":"https://api.github.com/users/jandom/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jandom/subscriptions","organizations_url":"https://api.github.com/users/jandom/orgs","repos_url":"https://api.github.com/users/jandom/repos","events_url":"https://api.github.com/users/jandom/events{/privacy}","received_events_url":"https://api.github.com/users/jandom/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/jandom/GromacsWrapper","description":"GromacsWrapper is a python package that wraps system calls to Gromacs tools into thin classes. This allows for fairly seamless integration of the gromacs tools into python scripts. This is generally superior to shell scripts because of python’s better error handling and superior data structures. It also allows for modularization and code re-use. In addition, commands, warnings and errors are logged to a file so that there exists a complete history of what has been done.","fork":true,"url":"https://api.github.com/repos/jandom/GromacsWrapper","forks_url":"https://api.github.com/repos/jandom/GromacsWrapper/forks","keys_url":"https://api.github.com/repos/jandom/GromacsWrapper/keys{/key_id}","collaborators_url":"https://api.github.com/repos/jandom/GromacsWrapper/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/jandom/GromacsWrapper/teams","hooks_url":"https://api.github.com/repos/jandom/GromacsWrapper/hooks","issue_events_url":"https://api.github.com/repos/jandom/GromacsWrapper/issues/events{/number}","events_url":"https://api.github.com/repos/jandom/GromacsWrapper/events","assignees_url":"https://api.github.com/repos/jandom/GromacsWrapper/assignees{/user}","branches_url":"https://api.github.com/repos/jandom/GromacsWrapper/branches{/branch}","tags_url":"https://api.github.com/repos/jandom/GromacsWrapper/tags","blobs_url":"https://api.github.com/repos/jandom/GromacsWrapper/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/jandom/GromacsWrapper/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/jandom/GromacsWrapper/git/refs{/sha}","trees_url":"https://api.github.com/repos/jandom/GromacsWrapper/git/trees{/sha}","statuses_url":"https://api.github.com/repos/jandom/GromacsWrapper/statuses/{sha}","languages_url":"https://api.github.com/repos/jandom/GromacsWrapper/languages","stargazers_url":"https://api.github.com/repos/jandom/GromacsWrapper/stargazers","contributors_url":"https://api.github.com/repos/jandom/GromacsWrapper/contributors","subscribers_url":"https://api.github.com/repos/jandom/GromacsWrapper/subscribers","subscription_url":"https://api.github.com/repos/jandom/GromacsWrapper/subscription","commits_url":"https://api.github.com/repos/jandom/GromacsWrapper/commits{/sha}","git_commits_url":"https://api.github.com/repos/jandom/GromacsWrapper/git/commits{/sha}","comments_url":"https://api.github.com/repos/jandom/GromacsWrapper/comments{/number}","issue_comment_url":"https://api.github.com/repos/jandom/GromacsWrapper/issues/comments{/number}","contents_url":"https://api.github.com/repos/jandom/GromacsWrapper/contents/{+path}","compare_url":"https://api.github.com/repos/jandom/GromacsWrapper/compare/{base}...{head}","merges_url":"https://api.github.com/repos/jandom/GromacsWrapper/merges","archive_url":"https://api.github.com/repos/jandom/GromacsWrapper/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/jandom/GromacsWrapper/downloads","issues_url":"https://api.github.com/repos/jandom/GromacsWrapper/issues{/number}","pulls_url":"https://api.github.com/repos/jandom/GromacsWrapper/pulls{/number}","milestones_url":"https://api.github.com/repos/jandom/GromacsWrapper/milestones{/number}","notifications_url":"https://api.github.com/repos/jandom/GromacsWrapper/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/jandom/GromacsWrapper/labels{/name}","releases_url":"https://api.github.com/repos/jandom/GromacsWrapper/releases{/id}","created_at":"2015-12-14T16:14:49Z","updated_at":"2015-12-14T16:14:50Z","pushed_at":"2015-12-14T22:11:48Z","git_url":"git://github.com/jandom/GromacsWrapper.git","ssh_url":"git@github.com:jandom/GromacsWrapper.git","clone_url":"https://github.com/jandom/GromacsWrapper.git","svn_url":"https://github.com/jandom/GromacsWrapper","homepage":"http://gromacswrapper.readthedocs.org","size":10899,"stargazers_count":0,"watchers_count":0,"language":"Python","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"develop"}},"base":{"label":"Becksteinlab:develop","ref":"develop","sha":"ef62459a6772329aa674464c308ea3e169632122","user":{"login":"Becksteinlab","id":11325701,"avatar_url":"https://avatars.githubusercontent.com/u/11325701?v=3","gravatar_id":"","url":"https://api.github.com/users/Becksteinlab","html_url":"https://github.com/Becksteinlab","followers_url":"https://api.github.com/users/Becksteinlab/followers","following_url":"https://api.github.com/users/Becksteinlab/following{/other_user}","gists_url":"https://api.github.com/users/Becksteinlab/gists{/gist_id}","starred_url":"https://api.github.com/users/Becksteinlab/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Becksteinlab/subscriptions","organizations_url":"https://api.github.com/users/Becksteinlab/orgs","repos_url":"https://api.github.com/users/Becksteinlab/repos","events_url":"https://api.github.com/users/Becksteinlab/events{/privacy}","received_events_url":"https://api.github.com/users/Becksteinlab/received_events","type":"Organization","site_admin":false},"repo":{"id":597114,"name":"GromacsWrapper","full_name":"Becksteinlab/GromacsWrapper","owner":{"login":"Becksteinlab","id":11325701,"avatar_url":"https://avatars.githubusercontent.com/u/11325701?v=3","gravatar_id":"","url":"https://api.github.com/users/Becksteinlab","html_url":"https://github.com/Becksteinlab","followers_url":"https://api.github.com/users/Becksteinlab/followers","following_url":"https://api.github.com/users/Becksteinlab/following{/other_user}","gists_url":"https://api.github.com/users/Becksteinlab/gists{/gist_id}","starred_url":"https://api.github.com/users/Becksteinlab/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Becksteinlab/subscriptions","organizations_url":"https://api.github.com/users/Becksteinlab/orgs","repos_url":"https://api.github.com/users/Becksteinlab/repos","events_url":"https://api.github.com/users/Becksteinlab/events{/privacy}","received_events_url":"https://api.github.com/users/Becksteinlab/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/Becksteinlab/GromacsWrapper","description":"GromacsWrapper is a python package that wraps system calls to Gromacs tools into thin classes. This allows for fairly seamless integration of the gromacs tools into python scripts. This is generally superior to shell scripts because of python’s better error handling and superior data structures. It also allows for modularization and code re-use. In addition, commands, warnings and errors are logged to a file so that there exists a complete history of what has been done.","fork":false,"url":"https://api.github.com/repos/Becksteinlab/GromacsWrapper","forks_url":"https://api.github.com/repos/Becksteinlab/GromacsWrapper/forks","keys_url":"https://api.github.com/repos/Becksteinlab/GromacsWrapper/keys{/key_id}","collaborators_url":"https://api.github.com/repos/Becksteinlab/GromacsWrapper/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/Becksteinlab/GromacsWrapper/teams","hooks_url":"https://api.github.com/repos/Becksteinlab/GromacsWrapper/hooks","issue_events_url":"https://api.github.com/repos/Becksteinlab/GromacsWrapper/issues/events{/number}","events_url":"https://api.github.com/repos/Becksteinlab/GromacsWrapper/events","assignees_url":"https://api.github.com/repos/Becksteinlab/GromacsWrapper/assignees{/user}","branches_url":"https://api.github.com/repos/Becksteinlab/GromacsWrapper/branches{/branch}","tags_url":"https://api.github.com/repos/Becksteinlab/GromacsWrapper/tags","blobs_url":"https://api.github.com/repos/Becksteinlab/GromacsWrapper/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/Becksteinlab/GromacsWrapper/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/Becksteinlab/GromacsWrapper/git/refs{/sha}","trees_url":"https://api.github.com/repos/Becksteinlab/GromacsWrapper/git/trees{/sha}","statuses_url":"https://api.github.com/repos/Becksteinlab/GromacsWrapper/statuses/{sha}","languages_url":"https://api.github.com/repos/Becksteinlab/GromacsWrapper/languages","stargazers_url":"https://api.github.com/repos/Becksteinlab/GromacsWrapper/stargazers","contributors_url":"https://api.github.com/repos/Becksteinlab/GromacsWrapper/contributors","subscribers_url":"https://api.github.com/repos/Becksteinlab/GromacsWrapper/subscribers","subscription_url":"https://api.github.com/repos/Becksteinlab/GromacsWrapper/subscription","commits_url":"https://api.github.com/repos/Becksteinlab/GromacsWrapper/commits{/sha}","git_commits_url":"https://api.github.com/repos/Becksteinlab/GromacsWrapper/git/commits{/sha}","comments_url":"https://api.github.com/repos/Becksteinlab/GromacsWrapper/comments{/number}","issue_comment_url":"https://api.github.com/repos/Becksteinlab/GromacsWrapper/issues/comments{/number}","contents_url":"https://api.github.com/repos/Becksteinlab/GromacsWrapper/contents/{+path}","compare_url":"https://api.github.com/repos/Becksteinlab/GromacsWrapper/compare/{base}...{head}","merges_url":"https://api.github.com/repos/Becksteinlab/GromacsWrapper/merges","archive_url":"https://api.github.com/repos/Becksteinlab/GromacsWrapper/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/Becksteinlab/GromacsWrapper/downloads","issues_url":"https://api.github.com/repos/Becksteinlab/GromacsWrapper/issues{/number}","pulls_url":"https://api.github.com/repos/Becksteinlab/GromacsWrapper/pulls{/number}","milestones_url":"https://api.github.com/repos/Becksteinlab/GromacsWrapper/milestones{/number}","notifications_url":"https://api.github.com/repos/Becksteinlab/GromacsWrapper/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/Becksteinlab/GromacsWrapper/labels{/name}","releases_url":"https://api.github.com/repos/Becksteinlab/GromacsWrapper/releases{/id}","created_at":"2010-04-06T14:08:26Z","updated_at":"2015-12-02T22:04:31Z","pushed_at":"2015-12-14T22:13:52Z","git_url":"git://github.com/Becksteinlab/GromacsWrapper.git","ssh_url":"git@github.com:Becksteinlab/GromacsWrapper.git","clone_url":"https://github.com/Becksteinlab/GromacsWrapper.git","svn_url":"https://github.com/Becksteinlab/GromacsWrapper","homepage":"http://gromacswrapper.readthedocs.org","size":10488,"stargazers_count":34,"watchers_count":34,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":8,"mirror_url":null,"open_issues_count":10,"forks":8,"open_issues":10,"watchers":34,"default_branch":"develop"}},"_links":{"self":{"href":"https://api.github.com/repos/Becksteinlab/GromacsWrapper/pulls/25"},"html":{"href":"https://github.com/Becksteinlab/GromacsWrapper/pull/25"},"issue":{"href":"https://api.github.com/repos/Becksteinlab/GromacsWrapper/issues/25"},"comments":{"href":"https://api.github.com/repos/Becksteinlab/GromacsWrapper/issues/25/comments"},"review_comments":{"href":"https://api.github.com/repos/Becksteinlab/GromacsWrapper/pulls/25/comments"},"review_comment":{"href":"https://api.github.com/repos/Becksteinlab/GromacsWrapper/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/Becksteinlab/GromacsWrapper/pulls/25/commits"},"statuses":{"href":"https://api.github.com/repos/Becksteinlab/GromacsWrapper/statuses/07d3a24dcf118041d2d9af652aa47ba9efb87f9d"}}}}