diff --git a/parser/parser-dl_poly/dlPolyParser.py b/parser/parser-dl_poly/dlPolyParser.py
index 3e4c0a0b3275232ea9094d463ea3f119c2fee03e..7f45b5e36e88c7d151841433b50b1c82e94cbb83 100644
--- a/parser/parser-dl_poly/dlPolyParser.py
+++ b/parser/parser-dl_poly/dlPolyParser.py
@@ -12,8 +12,8 @@ from contextlib import contextmanager
 from libDlPolyParser import *
 
 try:
-    from momo import osio, endl, flush
-    #osio.ConnectToFile('dl_poly.log')
+    from libMomo import osio, endl, flush
+    osio.ConnectToFile('parser.osio.log')
     green = osio.mg
 except:
     osio = endl = flush = None
@@ -27,8 +27,9 @@ parser_info = {
 }
 
 # LOGGING
-def log(msg, highlight=osio.ww, enter=endl):
+def log(msg, highlight=None, enter=endl):
     if osio:
+        if highlight==None: hightlight = osio.ww
         osio << highlight << msg << enter
     return
 
@@ -36,7 +37,7 @@ def log(msg, highlight=osio.ww, enter=endl):
 @contextmanager
 def open_section(p, name):
     gid = p.openSection(name)
-    yield
+    yield gid
     p.closeSection(name, gid)   
 
 def push(jbe, terminal, key1, fct=lambda x: x.As(), key2=None):
@@ -45,6 +46,10 @@ def push(jbe, terminal, key1, fct=lambda x: x.As(), key2=None):
     jbe.addValue(key1, value)
     return value
 
+def push_value(jbe, value, key):
+    jbe.addValue(key, value)
+    return value
+
 def parse(output_file_name):
     jbe = JsonParseEventsWriterBackend(meta_info_env)
     jbe.startedParsingSession(output_file_name, parser_info)
@@ -54,13 +59,12 @@ def parse(output_file_name):
     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)    
+    terminal_trj.ParseConfig(cfg_file_name)
     # SUMMARIZE KEY-TABLE DEFAULTS ...
     terminal.SummarizeKeyDefaults()
     terminal.topology.SummarizeKeyDefaults()
@@ -72,7 +76,7 @@ def parse(output_file_name):
     top = terminal.topology
     trj = terminal_trj
     
-    ofs = open('keys.log', 'w')
+    ofs = open('parser.keys.log', 'w')
     terminals = [ctr, out, top, trj]
     for t in terminals:
         keys = sorted(t.data.keys())
@@ -82,35 +86,74 @@ def parse(output_file_name):
     ofs.close()
     
     # PUSH TO BACKEND
-    with open_section(jbe, 'section_run'):
+    with open_section(jbe, 'section_run') as gid_run:
         push(jbe, out, 'program_name')
         push(jbe, out, 'program_version')
         push(jbe, out, 'program_info', key2='program_version_date')
-
-        with open_section(jbe, 'section_topology'):
+        
+        # TOPOLOGY SECTION
+        with open_section(jbe, 'section_topology') as gid_top:
+            # Cross-referencing is done on-the-fly (as gid's become available)
+            # a) <molecule_to_molecule_type> :         shape=(number_of_topology_molecules, [<gid>])
+            # b) <atom_in_molecule_to_atom_type_ref> : shape=(number_of_atoms_in_molecule, [<gid>])
+            # c) <atom_to_molecule> :                  shape=(number_of_topology_atoms, [<molidx>, <atomidx>])
             push(jbe, top, 'number_of_topology_molecules', lambda s: s.As(int))
-            push(jbe, top, 'number_of_topology_atoms', lambda s: s.As(int))
-            # Molecule types
-            for mol in top.molecules:
-                with open_section(jbe, 'section_molecule_type'):
-                    push(jbe, mol, 'molecule_type_name')
-                    push(jbe, mol, 'number_of_atoms_in_molecule', lambda s: s.As(int))
-                    # TODO settings_atom_... is abstract type => set atom_in_molecule_charge via list,
-                    # TODO same for atom_in_molecule_name
-                    # TODO atom_to_molecule, molecule_to_molecule_type, atom_in_molecule_to_atom_type_ref
-                    for atom in mol.atoms:
-                        with open_section(jbe, 'settings_atom_in_molecule'):
-                            push(jbe, atom, 'atom_in_molecule_charge', lambda s: s.As(float), 'atom_charge')
-                            push(jbe, atom, 'atom_in_molecule_name', lambda s: s.As(), 'atom_name')
+            push(jbe, top, 'number_of_topology_atoms', lambda s: s.As(int))            
             # Atom types
+            mol_type_atom_type_id_to_atom_type_gid = {}
             for mol in top.molecules:
+                mol_name = mol['molecule_type_name'].As()
+                mol_type_atom_type_id_to_atom_type_gid[mol_name] = {}
                 for atom in mol.atoms:
-                    with open_section(jbe, 'section_atom_type'):
+                    # Add type
+                    with open_section(jbe, 'section_atom_type') as gid_atom:
+                        atom_id = atom['atom_id'].As(int)
+                        mol_type_atom_type_id_to_atom_type_gid[mol_name][atom_id] = gid_atom
                         push(jbe, atom, 'atom_type_name', lambda s: s.As(), 'atom_name')
                         push(jbe, atom, 'atom_type_mass', lambda s: s.As(float), 'atom_mass')
-                        push(jbe, atom, 'atom_type_charge', lambda s: s.As(float), 'atom_charge')
-            
-
+                        push(jbe, atom, 'atom_type_charge', lambda s: s.As(float), 'atom_charge')           
+            # Molecule types
+            molecule_type_name_to_type_gid = {}
+            for mol in top.molecules:
+                mol_name = mol['molecule_type_name'].As()
+                # Extract references of atoms to atom types
+                atom_type_id_to_atom_type_gid = mol_type_atom_type_id_to_atom_type_gid[mol_name]
+                atom_gid_list = []
+                for atom in mol.atoms:
+                    atom_id = atom['atom_id'].As(int)
+                    atom_gid_list.append(atom_type_id_to_atom_type_gid[atom_id])
+                # Add molecule                    
+                with open_section(jbe, 'section_molecule_type') as gid_mol:
+                    molecule_type_name_to_type_gid[mol['molecule_type_name'].As()] = gid_mol
+                    push(jbe, mol, 'molecule_type_name')
+                    push(jbe, mol, 'number_of_atoms_in_molecule', lambda s: s.As(int))
+                    push(jbe, mol, 'atom_in_molecule_name')
+                    push(jbe, mol, 'atom_in_molecule_charge')
+                    push_value(jbe, atom_gid_list, 'atom_in_molecule_to_atom_type_ref')
+            # Global molecule type map
+            molecule_to_molecule_type = []
+            for mol in top.molecules:
+                type_name_this_mol = mol['molecule_type_name'].As()
+                type_gid_this_mol = molecule_type_name_to_type_gid[type_name_this_mol]
+                n_this_mol = mol['number_of_molecules'].As(int)
+                for i in range(n_this_mol):
+                    molecule_to_molecule_type.append(type_gid_this_mol)
+            push_value(jbe, molecule_to_molecule_type, 'molecule_to_molecule_type_map')
+            # Global atom map
+            atoms_to_molidx_atomidx = []
+            molidx = 0
+            for mol in top.molecules:
+                n_mol = mol['number_of_molecules'].As(int)
+                for i in range(n_mol):
+                    atomidx = 0
+                    for atom in mol.atoms:
+                        molidx_atomidx = [ molidx, atomidx ]
+                        atoms_to_molidx_atomidx.append(molidx_atomidx)
+                        atomidx += 1
+                    molidx += 1
+            push_value(jbe, atoms_to_molidx_atomidx, 'atom_to_molecule')
+                        
+        # SAMPLING-METHOD SECTION
         with open_section(jbe, 'section_sampling_method'):
             # Ensemble
             ensemble = push(jbe, out, 'ensemble_type', lambda s: s.As().split()[0].upper())           
@@ -127,7 +170,8 @@ def parse(output_file_name):
                 push(jbe, out, 'barostat_target_pressure', lambda s: s.As(float))
                 push(jbe, out, 'barostat_tau', lambda s: s.As(float))
             pass
-
+        
+        # FRAME-SEQUENCE SECTION
         with open_section(jbe, 'section_frame_sequence'):
             pass
 
@@ -150,9 +194,7 @@ if __name__ == '__main__':
         extraArgsHandling=InfoKindEl.ADD_EXTRA_ARGS,
         uri=None)
 
-    log("Parsing ...", green)
     output_file_name = sys.argv[1]
-    parse(output_file_name)    
-    log("... Done.", green)
+    parse(output_file_name)
     
 
diff --git a/parser/parser-dl_poly/libDlPolyParser.py b/parser/parser-dl_poly/libDlPolyParser.py
index 2e0db546f47156707a3200eb11b5b28e7f122e4c..49553c3def9cd9b911476e9df4d3c7fa57f12e0e 100644
--- a/parser/parser-dl_poly/libDlPolyParser.py
+++ b/parser/parser-dl_poly/libDlPolyParser.py
@@ -404,7 +404,7 @@ class DlPolyControls(DlPolyParser):
         return
     def ParseControls(self, ctrl_file):
         if self.log: 
-            self.log << self.log.endl << self.log.mg << "Start controls ..." << self.log.endl        
+            self.log << self.log.mg << "Start controls ..." << self.log.endl        
         ifs = FileStream(ctrl_file)
         while not ifs.all_read():
             ln = ifs.ln()
@@ -575,6 +575,11 @@ class DlPolyMolecule(DlPolyParser):
                 break
         assert atom_count == n_atoms
         
+        atom_charges = [ atom['atom_charge'].As(float) for atom in self.atoms ]
+        atom_names = [ atom['atom_name'].As() for atom in self.atoms ]
+        self.Set('atom_in_molecule_charge', atom_charges)
+        self.Set('atom_in_molecule_name', atom_names)
+        
         # TODO Parse interactions
         return
 
@@ -582,7 +587,7 @@ class DlPolyMolecule(DlPolyParser):
 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
+        if self.log and not self.log.debug: self.log = None
         self.logtag = 'atm'
         for value, label in zip(atom_properties, atom_property_labels):
             self.Set(label, value)
diff --git a/parser/parser-dl_poly/libMomo.py b/parser/parser-dl_poly/libMomo.py
new file mode 100644
index 0000000000000000000000000000000000000000..aed698e9a107b0966e50f3d2d3d828ee4e9b6de0
--- /dev/null
+++ b/parser/parser-dl_poly/libMomo.py
@@ -0,0 +1,544 @@
+# See git https://github.com/capoe/momo.git
+import os
+import sys
+import commands
+import argparse
+import time
+import numpy as np
+try:
+	from lxml import etree
+except ImportError:
+    pass
+
+boolean_dict = \
+    {'true' : True,   '1' : True,  'yes' : True,
+     'false' : False, '0' : False, 'no' : False, 'none' : False }
+
+# =============================================================================
+# XML WRAPPERS
+# =============================================================================
+
+class ExtendableNamespace(argparse.Namespace):
+	def AddNamespace(self,  **kwargs):
+		for name in kwargs:
+			att = getattr(self, name, None)
+			if att is None:
+				setattr(self, name, kwargs[name])
+			else:
+				setattr(self, name, kwargs[name].As(type(att)))
+		return
+	def Add(self, name, value):
+		att = getattr(self, name, None)
+		if att is None:
+			setattr(self, name, value)
+		else:
+			att.Add(name, value)
+		return value
+
+def GenerateTreeDict(tree, element, path='', paths_rel_to=None):
+	if type(element) == etree._Comment: return [], {}
+	# Update path
+	if path == '':
+		if element.tag != paths_rel_to:
+			path += element.tag
+	else:
+		path += '/' + element.tag
+	# Containers for lower levels
+	tag_node = {}
+	nodes = []
+	# Construct Node
+	xmlnode = XmlNode(element, path) # tree.getpath(element))
+	nodes.append(xmlnode)
+	if len(element) == 0:
+		tag_node[path] = xmlnode
+	#else:
+	#	print "len 0", xmlnode.path
+	#	tag_node[path] = xmlnode
+	# Iterate over children
+	for child in element:
+		child_elements, childtag_element = GenerateTreeDict(tree, child, path)
+		nodes = nodes + child_elements
+		for key in childtag_element.keys():
+			if tag_node.has_key(key):
+				if type(tag_node[key]) != list:
+					tag_node[key] = [ tag_node[key], childtag_element[key] ]
+				else:
+					tag_node[key].append(childtag_element[key])
+			else:
+				tag_node[key] = childtag_element[key]
+	return nodes, tag_node
+
+def NamespaceFromDict(tree_dict):
+	nspace = ExtendableNamespace()
+	for key in tree_dict.keys():
+		#print "NSPACE Path = %s" % key
+		sections = key.split('/')
+		values = [ None for s in sections ]
+		values[-1] = tree_dict[key]
+		add_to_nspace = nspace
+		for s,v in zip(sections, values):
+			if v == None:
+				#print "NSPACE Check for existing"
+				if getattr(add_to_nspace, s, None):
+					#print "NSPACE '%s' already exists" % s
+					add_to_nspace = getattr(add_to_nspace, s, None)
+				else:
+					#print "NSPACE '%s' created" % s
+					sub_nspace = ExtendableNamespace()
+					add_to_nspace = add_to_nspace.Add(s, sub_nspace)
+			else:
+				#print "NSPACE '%s' value added" % s
+				add_to_nspace.Add(s, v)
+	return nspace
+				
+
+class XmlTree(list):
+	def __init__(self, xmlfile, paths_rel_to=None):
+		self.xmlfile = xmlfile
+		self.xtree = etree.parse(xmlfile)
+		self.xroot = self.xtree.getroot()
+		self.nodes, self.tag_node = GenerateTreeDict(self.xtree, self.xroot, '', paths_rel_to)
+		self.xspace = NamespaceFromDict(self.tag_node)
+	def SelectByTag(self, tag):
+		selection = [ e for e in self.nodes if e.tag == tag ]
+		return selection
+	def __getitem__(self, key):
+		return self.tag_node[key]
+	def keys(self):
+		return self.tag_node.keys()
+
+
+class XmlNode(object):
+	def __init__(self, element, path):
+		self.path = path
+		self.node = element
+		self.tag = element.tag		
+		self.value = element.text
+		self.attributes = element.attrib
+	def As(self, typ):
+		if typ == np.array:
+			sps = self.value.split()
+			return typ([ float(sp) for sp in sps ])
+		elif typ == bool:
+			return boolean_dict.get(self.value.lower())
+		else:
+			return typ(self.value)
+	def AsArray(self, typ, sep=' ', rep='\t\n'):
+		for r in rep:
+			self.value = self.value.replace(r, sep)
+		sp = self.value.split(sep)
+		return [ typ(s) for s in sp if str(s) != '' ]
+	def SetNodeValue(self, new_value):
+		self.value = new_value
+		if self.node != None:
+			self.node.firstChild.nodeValue = new_value
+		return
+	def __getitem__(self, key):
+		return self.node.get(key)
+
+
+# =============================================================================
+# COMMAND LINE & XML INPUT INTERFACE
+# =============================================================================
+
+class CLIO_HelpFormatter(argparse.HelpFormatter):
+	def _format_usage(self, usage, action, group, prefix):
+		return "%s : Command Line Interface\n" % sys.argv[0]
+
+
+class OptionsInterface(object):
+	def __init__(self):
+		# COMMAND-LINE ARGUMENTS
+		self.is_connected_to_cmd_ln = False
+		self.cmd_ln_args = None
+		self.cmd_ln_opts = None
+		self.cmd_ln_nicknames = [ '-h' ]
+		self.boolean_translator = boolean_dict
+		self.subtype = str
+		# XML OPTIONS FILE
+		self.is_connected_to_xml = False
+		self.xmlfile = None
+		self.tree = None
+		self.xdict = None
+		self.xspace = None
+		# JOINED OPTIONS
+		self.opts = ExtendableNamespace()
+	def Connect(self, xmlfile=None):
+		self.ConnectToCmdLn()
+		self.ConnectToOptionsFile(xmlfile)
+	def Parse(self, xkey='options'):
+		if self.is_connected_to_cmd_ln:
+			self.ParseCmdLn()
+		if self.is_connected_to_xml:
+			self.ParseOptionsFileXml(xkey)
+		if self.is_connected_to_cmd_ln and not self.is_connected_to_xml:
+			return self.cmd_ln_opts
+		elif self.is_connected_to_xml and not self.is_connected_to_cmd_ln:
+			return self.xspace
+		else:
+			return self.cmd_ln_opts, self.xspace
+	def ParseOptionsFile(self, xmlfile, xkey):
+		self.xmlfile = xmlfile
+		self.is_connected_to_xml = True
+		self.ParseOptionsFileXml(xkey)
+		return self.xspace
+	# COMMAND-LINE CONVENIENCE ================================================
+	def __call__(self):
+		return self.cmd_ln_opts
+	def ConnectToCmdLn(self, prog=sys.argv[0], descr=None):
+		self.cmd_ln_args = argparse.ArgumentParser(prog=sys.argv[0],
+			formatter_class=lambda prog: CLIO_HelpFormatter(prog,max_help_position=70))
+		self.is_connected_to_cmd_ln = True
+		return
+	def ParseCmdLn(self):
+		self.cmd_ln_opts = self.cmd_ln_args.parse_args()
+	def InterpretAsBoolean(self, expr):
+		try:
+			return self.boolean_translator.get(expr.lower())
+		except KeyError:
+			raise ValueError('CLIO does not know how to convert %s into a boolean.' % expr)
+	def InterpretAsNumpyArray(self, expr):
+		print "Interpret", expr
+		array = [ float(e) for e in expr ]
+		array = np.array(array)
+		return array
+	def InterpretAsList(self, expr):
+		array = [ self.subtype(e) for e in expr ]
+		return array
+	def AddArg(self, name, typ=str, nickname=None, 
+			default=None, destination=None, help=None):
+		# Sort out <name> (e.g. --time) vs <destination> (e.g., time)
+		if '--' != name[0:2]:
+			dest = name
+			name = '--' + name
+		else:
+			dest = name[2:]
+		# Sort out <default> vs <required>
+		if default == None: required = True
+		else: required = False
+		# Construct default <help> it not given
+		if help == None: help = str(typ)
+		# Construct <nickname> if not given
+		if nickname == None:
+			nickname = '-'
+			for char in dest:
+				nickname += char
+				if not nickname in self.cmd_ln_nicknames:
+					break
+			if nickname in self.cmd_ln_nicknames:
+				raise ValueError('CLIO could not construct nickname from %s option'\
+					% name)
+			self.cmd_ln_nicknames.append(nickname)
+		# Process type
+		if typ in [int, float, str]:
+			nargs = None
+		elif typ == bool:
+			typ = self.InterpretAsBoolean
+			nargs = None
+		elif typ == np.array:
+			raise NotImplementedError
+			typ = float # self.InterpretAsNumpyArray
+			nargs = 3
+		elif typ == list:
+			typ = str
+			nargs = '*'
+		elif len(typ) == 2 and typ[0] == list:
+			typ = typ[1]
+			nargs = '*'
+		else:
+			raise NotImplementedError("CLIO does not know how to generate type '%s'"\
+				 % typ)
+		self.cmd_ln_args.add_argument(nickname, name, 
+				dest=dest,
+				action='store',
+				nargs=nargs,
+				required=required,
+				type=typ,
+				metavar=dest[0:1].upper(),
+				default=default,
+				help=help)
+		return
+	# COMMAND-LINE CONVENIENCE ================================================
+	def ConnectToOptionsFile(self, xmlfile):
+		if xmlfile == None or xmlfile == '': return
+		self.xmlfile = xmlfile
+		self.is_connected_to_xml = True
+		return
+	def ParseOptionsFileXml(self, xkey='options'):
+		if self.xmlfile == None: return
+		self.tree = XmlTree(self.xmlfile, paths_rel_to=xkey)
+		self.xdict = self.tree.tag_node
+		self.xspace = self.tree.xspace
+		return
+	def __getitem__(self, key):
+		try:
+			return self.xspace.__dict__[key]			
+		except KeyError:
+			return self.cmd_ln_opts.__dict__[key]
+		except KeyError:
+			raise AttributeError('No such option registered: \'%s\'' % key)
+		return None
+		
+
+# =============================================================================
+# OS SHELL INTERFACE
+# =============================================================================
+
+class ShellInterface(object):
+	def __init__(self):
+		# =====================================================================
+		# PRINTER ATTRIBUTES
+		self.color_dict = { \
+			'pp' : '\033[95m',
+			'mb' : '\033[34m',
+			'lb' : '\033[1;34m',
+			'my' : '\033[1;33m',
+			'mg' : '\033[92m',			
+			'mr' : '\033[91m',
+			'ww' : '\033[0;1m',
+			'ok' : '\033[92m',
+			'xx' : '\033[91m',
+			'warning' : '\033[93m',
+			'error' : '\033[95m',
+			'endcolor' : '\033[0;1m' }
+		self.justify_dict = { \
+			'o' : '  o ',
+			'.' : '... ',
+            'r' : '\r',
+			'ro' : '\r  o '}
+		self.pp = OS_COLOR('pp')
+		self.lb = OS_COLOR('lb')
+		self.mb = OS_COLOR('mb')		
+		self.mg = OS_COLOR('mg')
+		self.my = OS_COLOR('my')		
+		self.mr = OS_COLOR('mr')
+		self.ww = OS_COLOR('ww')
+		self.ok = OS_COLOR('ok')
+		self.xx = OS_COLOR('xx')
+		self.colors = [ OS_COLOR(c) for c in sorted(self.color_dict.keys()) ]
+		self.item = '  o '
+		self.iitem = '      - '
+		self.endl = OS_LINE_CHAR('\n')
+		self.flush = OS_LINE_CHAR('')
+		self.back = OS_LINE_CHAR('\r')
+		self.trail = ' '
+		# CURRENT STYLE SELECTION
+		self.sel_color = None
+		self.sel_justify = None
+		self.sel_header = False
+		self.sel_trim = "="
+		# EXE ATTRIBUTES
+		self.catch = OS_EXE_CATCH()
+		self.assert_zero = OS_EXE_ASSERT()
+		self.dev = OS_EXE_DEV('')
+		self.nodev = OS_EXE_DEV('')
+		self.devnull = OS_EXE_DEV()
+		self.devfile = OS_EXE_DEV('')
+		self.os_exe_get = False
+		self.os_exe_assert_zero = False
+		self.os_exe_dev = ''
+		self.os_exe_verbose = False
+		# LOGGING
+		self.logfile = None
+		# DIRECTORY HOPPING
+		self.paths_visited = [ os.getcwd() ]
+		self.exe_root_path = self.paths_visited[0]
+		self.N_store_paths_visited = 1+5
+	def __call__(self, mssg, c=None, j=None, h=False, t="="):
+		# c=color, j=justify, h=header, t=trim, u=upper-case
+		if j:
+			mssg = self.justify_dict[j] + mssg
+		if c != None:
+			mssg = self.color_dict[c] + mssg + self.color_dict['endcolor']
+		if h:
+			mssg = self.os_generate_header(mssg, t)
+		print mssg
+	# LOGFILE ADAPTOR =========================================================
+	def ConnectToFile(self, logfile):
+		self.logfile = logfile
+		sys.stdout = open(logfile, 'w')
+		self.devfile = OS_EXE_DEV(' >> {log} 2>> {log}'.format(log=logfile))
+		return
+	def DisconnectFromFile(self):
+		if self.logfile != None:
+			self.devfile = OS_EXE_DEV('')
+			self.logfile = None
+			sys.stdout = sys.__stdout__
+		else: pass
+		return
+	# PRINTER METHODS =========================================================
+	def __lshift__(self, mssg):
+		if type(mssg) == OS_LINE_CHAR:
+			# <LOG MESSAGE HERE>
+			sys.stdout.write(str(mssg))
+			sys.stdout.flush()
+			self.sel_color = None
+			return self
+		elif type(mssg) == OS_COLOR:
+			self.sel_color = str(mssg)
+			return self
+		mssg = str(mssg)
+		if self.sel_justify != None:
+			mssg = self.justify_dict[j] + mssg
+		mssg += self.trail
+		if self.sel_color != None:
+			mssg = self.color_dict[self.sel_color] \
+				+ mssg + self.color_dict['endcolor']
+		if self.sel_header:
+			mssg = self.os_generate_header(mssg, self.sel_trim)
+		# <LOG MESSAGE HERE>
+		sys.stdout.write(mssg)
+		return self
+	def os_print(self, mssg, c=None, j=None, h=False, t="="):
+		# c=color, j=justify, h=header, t=trim, u=upper-case
+		if j:
+			mssg = OS_JUSTIFY_DICT[j] + mssg
+		if c != None:
+			mssg = OS_COLOR_DICT[c] + mssg + OS_COLOR_DICT['endcolor']
+		if h:
+			mssg = os_generate_header(mssg, t)
+		print mssg
+		return
+	def os_print_config(self, c=None, j=None, h=False, t="=", tl=' '):
+		self.sel_color = c
+		self.sel_justify = j
+		self.sel_header = h
+		self.sel_trim = t
+		self.trail = tl
+		return
+	def os_print_reset(self):
+		self.sel_color = None
+		self.sel_justify = None
+		self.sel_header = False
+		self.sel_trim = "="
+		self.trail = ' '
+		return
+	def os_generate_header(title, trim="="):
+		try:
+		    height, width = os.popen('stty size', 'r').read().split()
+		    width = int(width)
+		    leftright = int((width - len(title)-2)/2)
+		except ValueError:
+		    leftright = 40
+		return trim*leftright + " " + title + " " + trim*leftright
+	# EXECUTE METHODS =========================================================
+	def __rshift__(self, cmmd):
+		if type(cmmd) == OS_EXE_CATCH:
+			self.os_exe_get = True
+			return self
+		elif type(cmmd) == OS_EXE_DEV:
+			self.dev = cmmd
+			return self
+		elif type(cmmd) == OS_EXE_ASSERT:
+			self.os_exe_assert_zero = True
+			return self
+		# Redirect command as requested (not applicable if output is asked for)
+		if not self.os_exe_get:
+			if str(self.dev) != '':
+				cmmd += str(self.dev)
+				self.dev = self.nodev
+			else:
+				cmmd += str(self.devfile)
+		# Execute
+		if self.debug: self << self.my << "exe:" << cmmd << endl
+		if self.os_exe_get:
+			output = commands.getoutput(cmmd)
+			self.os_exe_get = False		
+			return output
+		else:
+			sign = os.system(cmmd)
+		if self.os_exe_assert_zero:
+			if str(sign) != '0':
+				raise RuntimeError("<OSIO> '%s' returned '%s'" % (cmmd, sign))
+			self.os_exe_assert_zero = False
+		return sign
+	# EXIT PROTOCOLS ==========================================================
+	def okquit(self, what=''):
+		if what != '': self << self.ok << what << self.endl
+		self.DisconnectFromFile()
+		sys.exit(0)
+		return
+	def xxquit(self, what=''):
+		if what != '': self << self.xx << "ERROR" << what << self.endl
+		self.DisconnectFromFile()
+		sys.exit(1)
+		return
+	# DIRECTORY HOPPING =======================================================
+	def cd(self, d):
+		# Current working directory, for archiving ... =>
+		cwd = os.getcwd()
+		if type(d) == int:
+			# Change to previously visited path
+			os.chdir(self.paths_visited[d])
+		elif type(d) == str:
+			# Change to path as specified explicitly
+			os.chdir(d)
+		else:
+			raise NotImplementedError
+		# <= ... previous path
+		self.paths_visited.append(cwd)
+		if len(self.paths_visited) > self.N_store_paths_visited:
+			self.paths_visited.pop(1) # 0 stores root
+		if self.debug: self << self.my << "cd: " << os.getcwd() << self.endl
+		return
+	def pwd(self):
+		return self.cwd()
+	def cwd(self):
+		return os.getcwd()
+	def root(self):
+		self.cd(self.exe_root_path)
+		return
+	def abspath(self, file):
+		if not os.path.exists(file):
+			raise IOError("<osio::abspath> No such item in local directory: '%s'" % file)
+		return os.path.join(self.cwd(), file)
+	def mkcd(self, directory):
+		self >> self.assert_zero >> 'mkdir -p %s' % directory
+		self.cd(directory)
+		return directory
+
+class OS_EXE_DEV(object):
+	def __init__(self, dev=' > /dev/null 2> /dev/null'):
+		self.dev = dev
+	def __str__(self):
+		return self.dev
+
+class OS_EXE_CATCH(object):
+	def __init__(self):
+		self.catch = True
+		
+class OS_EXE_ASSERT(object):
+	def __init__(self):
+		self.assert_0 = True
+
+class OS_COLOR(object):
+	def __init__(self, colstr):
+		self.colstr = colstr
+	def __str__(self):
+		return self.colstr
+
+class OS_LINE_CHAR(object):
+	def __init__(self, char):
+		self.char = char
+	def __str__(self):
+		return self.char
+
+
+class OSIO(ShellInterface, OptionsInterface):
+	def __init__(self):
+		self.debug = False
+		ShellInterface.__init__(self)
+		OptionsInterface.__init__(self)
+		return
+	def sleep(self, dt):
+		time.sleep(dt)
+		return
+
+
+osio = OSIO()
+endl = OS_LINE_CHAR('\n')
+flush = OS_LINE_CHAR('')
+back = OS_LINE_CHAR('\r')
+catch = OS_EXE_CATCH()
+devnull = OS_EXE_DEV()
+