Package gromacs :: Module tools
[hide private]
[frames] | no frames]

Source Code for Module gromacs.tools

  1  # $Id$ 
  2  # Copyright (c) 2009 Oliver Beckstein <orbeckst@gmail.com> 
  3  # Released under the GNU Public License 3 (or higher, your choice) 
  4  # See the file COPYING for details. 
  5   
  6  """ 
  7  :mod:`gromacs.tools` -- Gromacs commands classes 
  8  ================================================ 
  9   
 10  A Gromacs command class can be thought of as a factory function that 
 11  produces an instance of a gromacs command 
 12  (:class:`gromacs.core.GromacsCommand`) with initial default values. 
 13   
 14  By convention, a class has the capitalized name of the corresponding Gromacs 
 15  tool; dots are replaced by underscores to make it a valid python identifier. 
 16   
 17  The list of Gromacs tools to be loaded is configured in 
 18  :data:`gromacs.config.gmx_tool_groups`. 
 19   
 20  It is also possible to extend the basic commands and patch in additional 
 21  functionality. For example, the :class:`GromacsCommandMultiIndex` class makes a 
 22  command accept multiple index files and concatenates them on the fly; the 
 23  behaviour mimics Gromacs' "multi-file" input that has not yet been enabled for 
 24  all tools. 
 25   
 26  .. autoclass:: GromacsCommandMultiIndex 
 27     :members: run, _fake_multi_ndx, __del__ 
 28   
 29  Example 
 30  ------- 
 31   
 32  In this example we create two instances of the :class:`gromacs.tools.Trjconv` command (which 
 33  runs the Gromacs ``trjconv`` command):: 
 34   
 35    import gromacs.tools as tools 
 36   
 37    trjconv = tools.Trjconv() 
 38    trjconv_compact = tools.Trjconv(ur='compact', center=True, boxcenter='tric', pbc='mol', 
 39                                    input=('protein','system'), 
 40                                    doc="Returns a compact representation of the system centered on the protein") 
 41   
 42  The first one, ``trjconv``, behaves as the standard commandline tool but the 
 43  second one, ``trjconv_compact``, will by default create a compact 
 44  representation of the input data by taking into account the shape of the unit 
 45  cell. Of course, the same effect can be obtained by providing the corresponding 
 46  arguments to ``trjconv`` but by naming the more specific command differently 
 47  one can easily build up a library of small tools that will solve a specifi, 
 48  repeatedly encountered problem reliably. This is particularly helpful when doing 
 49  interactive work. 
 50   
 51  Gromacs tools 
 52  ------------- 
 53  .. The docs for the tool classes are auto generated. 
 54  """ 
 55   
 56  __docformat__ = "restructuredtext en" 
 57   
 58  import os.path 
 59  import tempfile 
 60   
 61  import config 
 62  from core import GromacsCommand, Command 
 63  import utilities 
 64   
 65   
 66  #: This dict holds all generated classes. 
 67  registry = {} 
 68   
 69  # Auto-generate classes such as: 
 70  # class g_dist(GromacsCommand): 
 71  #     command_name = 'g_dist' 
 72   
 73  for name in config.load_tools: 
 74      # make names valid python identifiers and use convention that class names are capitalized 
 75      clsname = name.replace('.','_').replace('-','_').capitalize()   
 76      cls = type(clsname, (GromacsCommand,), {'command_name':name, 
 77                                              '__doc__': "Gromacs tool %(name)r." % vars()}) 
 78      registry[clsname] = cls      # registry keeps track of all classes 
 79   
 80   
 81  # modify/fix classes as necessary 
 82  # Note:  
 83  # - check if class was defined in first place 
 84  # - replace class 
 85  # - update local context AND registry as done below 
 86   
87 -class GromacsCommandMultiIndex(GromacsCommand):
88 - def __init__(self, **kwargs):
89 """Initialize instance. 90 91 1) Sets up the combined index file. 92 2) Inititialize :class:`~gromacs.core.GromacsCommand` with the 93 new index file. 94 95 See the documentation for :class:`gromacs.core.GromacsCommand` for details. 96 """ 97 kwargs = self._fake_multi_ndx(**kwargs) 98 super(GromacsCommandMultiIndex, self).__init__(**kwargs)
99
100 - def run(self,*args,**kwargs):
101 """Run the command; make a combined multi-index file if necessary.""" 102 kwargs = self._fake_multi_ndx(**kwargs) 103 return super(GromacsCommandMultiIndex, self).run(*args, **kwargs)
104
105 - def _fake_multi_ndx(self, **kwargs):
106 """Combine multiple index file into a single one and return appropriate kwargs. 107 108 Calling the method combines multiple index files into a a single 109 temporary one so that Gromacs tools that do not (yet) support multi 110 file input for index files can be used transparently as if they did. 111 112 If a temporary index file is required then it is deleted once the 113 object is destroyed. 114 115 :Returns: 116 The method returns the input keyword arguments with the necessary 117 changes to use the temporary index files. 118 119 :Keywords: 120 Only the listed keywords have meaning for the method: 121 122 *n* : filename or list of filenames 123 possibly multiple index files; *n* is replaced by the name of 124 the temporary index file. 125 *s* : filename 126 structure file (tpr, pdb, ...) or ``None``; if a structure file is 127 supplied then the Gromacs default index groups are automatically added 128 to the temporary indexs file. 129 130 :Example: 131 Used in derived classes that replace the standard 132 :meth:`run` (or :meth:`__init__`) methods with something like:: 133 134 def run(self,*args,**kwargs): 135 kwargs = self._fake_multi_ndx(**kwargs) 136 return super(G_mindist, self).run(*args, **kwargs) 137 138 """ 139 ndx = kwargs.get('n') 140 if not (ndx is None or type(ndx) is str): 141 if len(ndx) > 1: 142 # g_mindist cannot deal with multiple ndx files (at least 4.0.5) 143 # so we combine them in a temporary file; it is unlinked in __del__. 144 # self.multi_ndx stores file name for __del__ 145 fd, self.multi_ndx = tempfile.mkstemp(suffix='.ndx', prefix='multi_') 146 make_ndx = Make_ndx(f=kwargs.get('s'), n=ndx) 147 rc,out,err = make_ndx(o=self.multi_ndx, input=['q'], # concatenate all index files 148 stdout=False, stderr=False) 149 self.orig_ndx = ndx 150 kwargs['n'] = self.multi_ndx 151 return kwargs
152
153 - def __del__(self):
154 """Clean up temporary multi-index files if they were used.""" 155 # XXX: does not seem to work when closing the interpreter?! 156 try: 157 from utilities import unlink_gmx 158 # self.multi_ndx <-- _fake_multi_index() 159 unlink_gmx(self.multi_ndx) 160 except (AttributeError, OSError): 161 pass
162 # XXX: type error --- can't use super in __del__? 163 #super(GromacsCommandMultiIndex, self).__del__() 164 165 # patching up... 166 167 if 'G_mindist' in registry: 168 # let G_mindist handle multiple ndx files
169 - class G_mindist(GromacsCommandMultiIndex):
170 """Gromacs tool 'g_mindist' (with patch to handle multiple ndx files).""" 171 command_name = 'g_mindist'
172 registry['G_mindist'] = G_mindist 173 174 if 'G_dist' in registry: 175 # let G_dist handle multiple ndx files
176 - class G_dist(GromacsCommandMultiIndex):
177 """Gromacs tool 'g_dist' (with patch to handle multiple ndx files).""" 178 command_name = 'g_dist'
179 registry['G_dist'] = G_dist 180 181 # TODO: generate multi index classes via type(), not copy&paste as above... 182 183 184 # load additional scripts from config 185 for rec in config.load_scripts: 186 name, clsname, doc = rec 187 exec_name = os.path.basename(name) 188 registry[clsname] = type(clsname, (Command,), 189 {'command_name':name, 190 '__doc__': "External tool %(exec_name)r\n\n%(doc)s." % vars()}) 191 192 193 # finally, add everything 194 globals().update(registry) # add classes to module's scope 195 __all__ = registry.keys() 196 197 # and clean up the module scope 198 cls = clsname = name = rec = doc = None # make sure they exist, because the next line 199 del rec, name, cls, clsname, doc # would throw NameError if no tool was configured 200