diff --git a/parser/parser-dl_poly/ManualDL_POLYParser.py b/parser/parser-dl_poly/ManualDL_POLYParser.py
index 296470d4bba19b429842549bd1f8306e93272104..017069c17ab3c8201aca815216237f1a6d0a4668 100644
--- a/parser/parser-dl_poly/ManualDL_POLYParser.py
+++ b/parser/parser-dl_poly/ManualDL_POLYParser.py
@@ -45,8 +45,28 @@ def parse(output_file_name):
     o  = open_section
     p.startedParsingSession(output_file_name, parser_info)
     
+    # PARSE CONTROLS
+    ctrl_file_name = 'CONTROL'
+    terminal_ctrls = DlPolyControls(osio)
+    terminal_ctrls.ParseControls(ctrl_file_name)
+    
+    # PARSE OUTPUT / TOPOLOGY
+    output_file_name = 'OUTPUT'
     terminal = DlPolyParser(osio)
     terminal.ParseOutput(output_file_name)
+    
+    # PARSE TRAJECTORY
+    cfg_file_name = 'CONFIG'
+    terminal_trj = DlPolyConfig(osio)
+    terminal_trj.ParseConfig(cfg_file_name)    
+    
+    # SUMMARIZE KEY-TABLE DEFAULTS
+    terminal.SummarizeKeyDefaults()
+    terminal.topology.SummarizeKeyDefaults()
+    terminal_ctrls.SummarizeKeyDefaults()
+    terminal_trj.SummarizeKeyDefaults()
+    
+    osio.okquit()
 
     with o(p, 'section_run'):
         p.addValue('program_name', 'DL_POLY')
@@ -81,6 +101,7 @@ if __name__ == '__main__':
 
     log("Parsing ...", green)
     output_file_name = sys.argv[1]
-    parse(output_file_name)
+    parse(output_file_name)    
     log("... Done.", green)
+    
 
diff --git a/parser/parser-dl_poly/libDL_POLYParser.py b/parser/parser-dl_poly/libDL_POLYParser.py
index a7c607077a46f928686e36c39bb0246541c6cd56..9eefc69b808c61a2d182ef463c549123b61a9d0d 100644
--- a/parser/parser-dl_poly/libDL_POLYParser.py
+++ b/parser/parser-dl_poly/libDL_POLYParser.py
@@ -2,7 +2,9 @@ import os
 import sys
 import re
 
-
+# =================
+# TRANSLATION RULES
+# =================
 
 KEY_TRANSFORM_SIM_CTRL = {
 'simulation_temperature_k' : 'thermostat_T',
@@ -36,8 +38,43 @@ KEY_TRANSFORM_SIM_CTRL = {
 KEY_TRANSFORM_SYS_SPEC = {
 'energy_units' : 'energy_units',
 'number_of_molecular_types' : 'n_molecular_types'
-}       
+}
+
+KEY_TRANSFORM_MOL_GLOBAL = {
+'molecular_species_type' : 'molecule_type_id',
+'name_of_species' : 'molecule_type_name',
+'number_of_molecules' : 'n_instances_molecule_type'
+}
+
+KEY_RULES_CONTROLS = {
+'ensemble' :    lambda l: [ s.lower() for s in l[1:] ],
+'temperature' : lambda l: l[-1],
+'pressure' :    lambda l: l[-1],
+'timestep' :    lambda l: l[-1],
+'steps':        lambda l: l[-1],
+'equilibration':lambda l: l[-1],
+'cutoff':       lambda l: l[-1]
+}
+
+KEY_RULES_CONTROLS_EXPAND_KEY = {
+'ensemble':'ensemble',
+'temp':'temperature',
+'temperature':'temperature',
+'pres':'pressure',
+'pressure':'pressure',
+'timestep':'timestep',
+'steps':'steps',
+'equilibration':'equilibration',
+'equil':'equilibration',
+'cut':'cutoff',
+'rcut':'cutoff',
+'cutoff':'cutoff'
+}
+
 
+# ===================
+# FILE & BLOCK STREAM
+# ===================
 
 class FileStream(object):
     def __init__(self, filename=None):
@@ -45,11 +82,14 @@ class FileStream(object):
             self.ifs = open(filename, 'r')
         else:
             self.ifs = None
+        return
     def SkipTo(self, expr):
         while True:
             ln = self.ifs.readline()
             if expr in ln:
                 break
+            if self.all_read():
+                break
         return ln
     def SkipToMatch(self, expr):
         while True:            
@@ -145,6 +185,8 @@ class FileStream(object):
         return self.ifs.tell() == os.fstat(self.ifs.fileno()).st_size
     def readline(self):
         return ifs.readline()
+    def close(self):
+        self.ifs.close()
     def nextline(self):
         while True:
             ln = self.ifs.readline()
@@ -192,6 +234,9 @@ class BlockStream(FileStream):
                 cat += ln
         return cat
 
+# ================
+# DLPOLY TERMINALS
+# ================
 
 class DlPolyParser(object):
     def __init__(self, log=None):
@@ -200,12 +245,19 @@ class DlPolyParser(object):
         self.data = {}
         self.topology = None
         self.logtag = 'sim'
-        
+        # KEY DEFAULT DICTIONARIES
         self.missing_keys_lh = [] # Transform keys that were not found in output
         self.missing_keys_rh = []
         self.ignored_keys = [] # Raw keys that did not have a transform
         self.keys_not_found = [] # Searches that failed
         return
+    def __getitem__(self, key):
+        self.selected_data_item = self.data[key]
+        return self
+    def As(self, typ=None):
+        if typ == None:
+            typ = type(self.selected_data_item)
+        return typ(self.selected_data_item)
     def SummarizeKeyDefaults(self):
         if not self.log: return
         if len(self.missing_keys_lh):
@@ -292,8 +344,6 @@ class DlPolyParser(object):
         return
     def ParseOutput(self, output_file):        
         if self.log: 
-            self.log << self.log.endl << self.log.endl
-            self.log << "DlPolyParser::ParseOutput" << self.log.endl
             self.log << self.log.mg << "Start simulation method ..." << self.log.endl
         
         ifs = FileStream(output_file)
@@ -320,27 +370,99 @@ class DlPolyParser(object):
         expr_molecule = 'molecular species type'
         expr_config = 'configuration file name'
         expr_vdw = 'number of specified vdw potentials'
-        expr_new = [ expr_molecule, expr_vdw, expr_config ]
+        expr_total = 'total number of molecules'
+        expr_new = [ expr_molecule, expr_vdw, expr_config, expr_total ]
         expr_end = 'all reading and connectivity checks DONE'
         blocks = ifs.GetBlockSequence(expr_start, expr_new, expr_end)
         # Sanity checks ...
         assert len(blocks[expr_vdw]) == len(blocks[expr_start]) == len(blocks[expr_config]) == 1
         assert len(blocks[expr_molecule]) >= 1
+        assert len(blocks[expr_total]) == 1
         block_sys_spec = blocks[expr_start][0]
         block_config = blocks[expr_config][0]
         block_molecules = blocks[expr_molecule]
         block_vdw = blocks[expr_vdw][0]
         # Generate ...  
-        self.topology = DlPolyTopology(block_sys_spec, block_config, block_molecules, block_vdw, self)
-        
-        
-        self.SummarizeKeyDefaults()
-        self.topology.SummarizeKeyDefaults()
-        self.log.okquit()
-        
+        self.topology = DlPolyTopology(block_sys_spec, block_config, block_molecules, block_vdw, self)        
+        ifs.close()
         return
 
-        
+
+class DlPolyControls(DlPolyParser):
+    def __init__(self, log=None):
+        super(DlPolyControls, self).__init__(log)
+        self.logtag = 'ctr'
+        return
+    def ParseControls(self, ctrl_file):
+        if self.log: 
+            self.log << self.log.endl << self.log.mg << "Start controls ..." << self.log.endl        
+        ifs = FileStream(ctrl_file)
+        while not ifs.all_read():
+            ln = ifs.ln()
+            if ln[0:1] == '#': continue
+            sp = ln.split()
+            key = sp[0]
+            try:
+                key_long = KEY_RULES_CONTROLS_EXPAND_KEY[key]
+                self.Set(key_long, KEY_RULES_CONTROLS[key_long](sp))
+            except KeyError:
+                self.ignored_keys.append(key)
+                pass
+        ifs.close()
+        return
+
+
+class DlPolyConfig(DlPolyParser):
+    def __init__(self, log=None):
+        super(DlPolyConfig, self).__init__(log)
+        self.logtag = 'cfg'
+        self.atoms = []
+        return
+    def ParseConfig(self, trj_file):
+        if self.log:
+            self.log << self.log.mg << "Start configuration ..." << self.log.endl
+        ifs = FileStream(trj_file)
+        # Title
+        title = ifs.ln().replace('\n','').strip()
+        self.Set('title', title)
+        # Directives: logging, pbc
+        directives = ifs.ln().split()
+        self.Set('log_level', directives[0]) # 0 -> 1 -> 2: coords -> + vel. -> + forces
+        self.Set('pbc_type', directives[1])  # 0 / ... / 6: no / cubic / orthorhom. / par.-epiped / xy
+        self.Set('n_atoms', directives[2])
+        # Box
+        if self['pbc_type'].As(int) > 0:
+            a = map(float, ifs.ln().split())
+            b = map(float, ifs.ln().split())
+            c = map(float, ifs.ln().split())
+            self.Set('box_a', a)
+            self.Set('box_b', b)
+            self.Set('box_c', c)
+        # Atom records
+        n_atoms = self['n_atoms'].As(int)
+        log_level = self['log_level'].As(int)
+        for i in range(n_atoms):
+            atom_name, atom_id = tuple(ifs.ln().split())
+            xyz = map(float, ifs.ln().split())
+            records = [atom_name, atom_id, xyz]
+            record_labels = ['atom_name', 'atom_id', 'xyz']
+            if log_level > 0:
+                vel = map(float, ifs.ln().split())
+                records.append(vel)
+                record_labels.append('vel')
+                if log_level > 1:
+                    force = map(float, ifs.ln().split())
+                    records.append(force)
+                    record_labels.append('force')
+            new_atom = DlPolyAtom(records, record_labels, self)
+            self.atoms.append(new_atom)
+        assert len(self.atoms) == n_atoms
+        return
+
+# =======================
+# DLPOLY TOPOLOGY OBJECTS
+# =======================
+
 class DlPolyTopology(DlPolyParser):
     def __init__(self, block_sys_spec, block_config, block_mols, block_vdw, parser):
         super(DlPolyTopology, self).__init__(parser.log)
@@ -359,36 +481,33 @@ class DlPolyTopology(DlPolyParser):
         triple_str='\s*([0-9a-zA-Z_.]*)'*3+'\n'
         search_str = 'simulation cell vectors\s*\n' + 3*triple_str
         self.SearchMapKeys(search_str, config_str, ['box_ax', 'box_ay', 'box_az', 'box_bx', 'box_by', 'box_bz', 'box_cx', 'box_cy', 'box_cz'])
-        self.SearchMapKeys('system volume\s*([-+0-9.eEdD]*)\s*\n', config_str, ['box_volume'])
+        self.SearchMapKeys('system volume\s*([-+0-9.eEdD]*)\s*\n', config_str, ['box_volume'])        
         
-        self.molecules = []
         # Molecule specification
+        self.molecules = []
         for block_mol in block_mols:
             if self.log: self.log << self.log.mg << "Start molecule ..." << self.log.endl
-            new_mol = DlPolyMolecule(block_mol, self)
-            
+            new_mol = DlPolyMolecule(block_mol, self)            
         return
 
 
-KEY_TRANSFORM_MOL_GLOBAL = {
-'molecular_species_type' : 'molecule_type_id',
-'name_of_species' : 'molecule_type_name',
-'number_of_molecules' : 'n_instances_molecule_type'
-}
-
 class DlPolyMolecule(DlPolyParser):
     def __init__(self, mol_stream, parser):
         super(DlPolyMolecule, self).__init__(parser.log)
         self.logtag = 'mol'
+        self.atoms = []
         
         # PARTITION ONTO BLOCKS
         expr_global = 'molecular species type'
+        # Atoms ...
         expr_atoms = 'number of atoms/sites'
+        # Interactions ...
         expr_bonds = 'number of bonds'
         expr_bond_constraints = 'number of bond constraints'
         expr_angles = 'number of bond angles'
         expr_dihedrals = 'number of dihedral angles'
-        expr_inv_angles = 'number of inversion angles'        
+        expr_inv_angles = 'number of inversion angles'
+        # Block definitions ...
         expr_start = expr_global
         expr_new = [ expr_atoms, expr_bonds, expr_bond_constraints, expr_angles, expr_dihedrals, expr_inv_angles ]
         expr_end = None        
@@ -398,21 +517,57 @@ class DlPolyMolecule(DlPolyParser):
             assert len(blocks[key]) <= 1
         assert len(blocks[expr_atoms]) == 1
         
-        # PARSE GLOBAL
+        # PARSE GLOBALS
         block = blocks[expr_global][0]
         block_data = self.ReadBlockXy(block)
         self.ApplyBlockXyData(block_data, KEY_TRANSFORM_MOL_GLOBAL)
         
         # PARSE ATOMS
+        if self.log: self.log << self.log.mg << "Start atoms ..." << self.log.endl
         block = blocks[expr_atoms][0]
+        n_atoms = int(block.ln().split()[-1])
+        self.Set('n_atoms_in_molecule', n_atoms)
+        assert 'atomic characteristics' in block.ln()
+        # Determine atom properties        
+        atom_property_labels = block.ln().split()
+        assert atom_property_labels[0] == 'site'
+        atom_property_labels[0] = 'id'
+        atom_property_labels = [ 'atom_%s' % l.lower() for l in atom_property_labels ]
+        atom_count = 0
+        # Read atom lines & create atoms
         while not block.all_read():
-            print block.ln()
+            atom_properties = block.ln().split()
+            new_atom = DlPolyAtom(atom_properties, atom_property_labels, parser)
+            self.atoms.append(new_atom)
+            # Atom may repeat - make these repititions explicit
+            atom_id = new_atom['atom_id'].As(int)
+            atom_repeat = new_atom['atom_repeat'].As(int)
+            for i in range(atom_repeat-1):
+                next_id = atom_id+i+1
+                assert int(atom_properties[0]) == next_id-1
+                atom_properties[0] = atom_id+i+1
+                new_atom = DlPolyAtom(atom_properties, atom_property_labels, parser)
+                self.atoms.append(new_atom)
+            # Keep track of total count
+            atom_count += atom_repeat
+            assert atom_count <= n_atoms
+            if atom_count == n_atoms:
+                break
+        assert atom_count == n_atoms
         
+        # TODO Parse interactions
+        return
+
+
+class DlPolyAtom(DlPolyParser):
+    def __init__(self, atom_properties, atom_property_labels, parser):
+        super(DlPolyAtom, self).__init__(parser.log)
+        if not self.log.debug: self.log = None
+        self.logtag = 'atm'
+        for value, label in zip(atom_properties, atom_property_labels):
+            self.Set(label, value)
         return
         
         
         
-        
-        
-        
-        
+