Package generic_fns :: Module pipes
[hide private]
[frames] | no frames]

Source Code for Module generic_fns.pipes

  1  ############################################################################### 
  2  #                                                                             # 
  3  # Copyright (C) 2004-2012 Edward d'Auvergne                                   # 
  4  #                                                                             # 
  5  # This file is part of the program relax (http://www.nmr-relax.com).          # 
  6  #                                                                             # 
  7  # This program is free software: you can redistribute it and/or modify        # 
  8  # it under the terms of the GNU General Public License as published by        # 
  9  # the Free Software Foundation, either version 3 of the License, or           # 
 10  # (at your option) any later version.                                         # 
 11  #                                                                             # 
 12  # This program is distributed in the hope that it will be useful,             # 
 13  # but WITHOUT ANY WARRANTY; without even the implied warranty of              # 
 14  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               # 
 15  # GNU General Public License for more details.                                # 
 16  #                                                                             # 
 17  # You should have received a copy of the GNU General Public License           # 
 18  # along with this program.  If not, see <http://www.gnu.org/licenses/>.       # 
 19  #                                                                             # 
 20  ############################################################################### 
 21   
 22  # Module docstring. 
 23  """Module for manipulating data pipes.""" 
 24   
 25   
 26  # Python module imports 
 27  try: 
 28      import __builtin__ as builtins    # Python 2 import. 
 29  except ImportError: 
 30      import builtins    # Python 3 import. 
 31  import sys 
 32   
 33  # relax module imports. 
 34  from data import Relax_data_store; ds = Relax_data_store() 
 35  from dep_check import C_module_exp_fn, scipy_module 
 36  from relax_errors import RelaxError, RelaxNoPipeError, RelaxPipeError 
 37  from status import Status; status = Status() 
 38   
 39   
 40  # List of valid data pipe types and descriptions. 
 41  VALID_TYPES = ['ct', 'frame order', 'jw', 'hybrid', 'mf', 'N-state', 'noe', 'relax_fit'] 
 42  PIPE_DESC = { 
 43      'ct':  'Consistency testing', 
 44      'frame order':  'Frame Order theories', 
 45      'jw':  'Reduced spectral density mapping', 
 46      'hybrid':  'Special hybrid pipe', 
 47      'mf':  'Model-free analysis', 
 48      'N-state':  'N-state model or ensemble analysis', 
 49      'noe':  'Steady state NOE calculation', 
 50      'relax_fit':  'Relaxation curve fitting' 
 51  } 
 52  PIPE_DESC_LIST = [] 
 53  for name in VALID_TYPES: 
 54      PIPE_DESC_LIST.append(PIPE_DESC[name]) 
 55   
 56   
57 -def bundle(bundle=None, pipe=None):
58 """Add the data pipe to the given bundle, created the bundle as needed. 59 60 @keyword bundle: The name of the data pipe bundle. 61 @type bundle: str 62 @keyword pipe: The name of the data pipe to add to the bundle. 63 @type pipe: str 64 """ 65 66 # Check that the data pipe exists. 67 test(pipe) 68 69 # Check that the pipe is not in another bundle. 70 for key in ds.pipe_bundles.keys(): 71 if pipe in ds.pipe_bundles[key]: 72 raise RelaxError("The data pipe is already within the '%s' bundle." % key) 73 74 # Create a new bundle if needed. 75 if bundle not in ds.pipe_bundles.keys(): 76 ds.pipe_bundles[bundle] = [] 77 78 # Add the pipe to the bundle. 79 ds.pipe_bundles[bundle].append(pipe) 80 81 # Notify observers that something has occurred. 82 status.observers.pipe_alteration.notify()
83 84
85 -def bundle_names():
86 """Return the list of all data pipe bundles. 87 88 @return: The list of data pipe bundles. 89 @rtype: list of str 90 """ 91 92 return list(ds.pipe_bundles.keys())
93 94
95 -def copy(pipe_from=None, pipe_to=None, bundle_to=None):
96 """Copy the contents of the source data pipe to a new target data pipe. 97 98 If the 'pipe_from' argument is None then the current data pipe is assumed as the source. The 99 data pipe corresponding to 'pipe_to' cannot exist. 100 101 @param pipe_from: The name of the source data pipe to copy the data from. 102 @type pipe_from: str 103 @param pipe_to: The name of the target data pipe to copy the data to. 104 @type pipe_to: str 105 @keyword bundle_to: The optional data pipe bundle to associate the new data pipe with. 106 @type bundle_to: str or None 107 """ 108 109 # Test if the pipe already exists. 110 if pipe_to in list(ds.keys()): 111 raise RelaxPipeError(pipe_to) 112 113 # Both pipe arguments cannot be None. 114 if pipe_from == None and pipe_to == None: 115 raise RelaxError("The pipe_from and pipe_to arguments cannot both be set to None.") 116 117 # Acquire the pipe lock (data modifying function), and make sure it is finally released. 118 status.pipe_lock.acquire(sys._getframe().f_code.co_name) 119 try: 120 # The current data pipe. 121 if pipe_from == None: 122 pipe_from = cdp_name() 123 124 # Copy the data. 125 ds[pipe_to] = ds[pipe_from].__clone__() 126 127 # Bundle the pipe. 128 if bundle_to: 129 bundle(bundle=bundle_to, pipe=pipe_to) 130 131 # Release the lock. 132 finally: 133 status.pipe_lock.release(sys._getframe().f_code.co_name) 134 135 # Notify observers that a pipe change has occurred. 136 status.observers.pipe_alteration.notify()
137 138
139 -def create(pipe_name=None, pipe_type=None, bundle=None, switch=True):
140 """Create a new data pipe. 141 142 The current data pipe will be changed to this new data pipe. 143 144 145 @keyword pipe_name: The name of the new data pipe. 146 @type pipe_name: str 147 @keyword pipe_type: The new data pipe type which can be one of the following: 148 'ct': Consistency testing, 149 'frame order': The Frame Order theories. 150 'jw': Reduced spectral density mapping, 151 'hybrid': The hybridised data pipe. 152 'mf': Model-free analysis, 153 'N-state': N-state model of domain dynamics, 154 'noe': Steady state NOE calculation, 155 'relax_fit': Relaxation curve fitting, 156 'relax_disp': Relaxation dispersion, 157 @type pipe_type: str 158 @keyword bundle: The optional data pipe bundle to associate the data pipe with. 159 @type bundle: str or None 160 @keyword switch: If True, this new pipe will be switched to, otherwise the current data pipe will remain as is. 161 @type switch: bool 162 """ 163 164 # Test if pipe_type is valid. 165 if not pipe_type in VALID_TYPES: 166 raise RelaxError("The data pipe type " + repr(pipe_type) + " is invalid and must be one of the strings in the list " + repr(VALID_TYPES) + ".") 167 168 # Test that the C modules have been loaded. 169 if pipe_type == 'relax_fit' and not C_module_exp_fn: 170 raise RelaxError("Relaxation curve fitting is not available. Try compiling the C modules on your platform.") 171 172 # Test that the scipy is installed for the frame order analysis. 173 if pipe_type == 'frame order' and not scipy_module: 174 raise RelaxError("The frame order analysis is not available. Please install the scipy Python package.") 175 176 # Acquire the pipe lock (data modifying function), and make sure it is finally released. 177 status.pipe_lock.acquire(sys._getframe().f_code.co_name) 178 try: 179 # Add the data pipe. 180 ds.add(pipe_name=pipe_name, pipe_type=pipe_type, bundle=bundle, switch=switch) 181 182 # Release the lock. 183 finally: 184 status.pipe_lock.release(sys._getframe().f_code.co_name)
185 186
187 -def cdp_name():
188 """Return the name of the current data pipe. 189 190 @return: The name of the current data pipe. 191 @rtype: str 192 """ 193 194 return ds.current_pipe
195 196
197 -def current():
198 """Print the name of the current data pipe.""" 199 200 print(cdp_name())
201 202
203 -def delete(pipe_name=None):
204 """Delete a data pipe. 205 206 @param pipe_name: The name of the data pipe to delete. 207 @type pipe_name: str 208 """ 209 210 # Acquire the pipe lock (data modifying function), and make sure it is finally released. 211 status.pipe_lock.acquire(sys._getframe().f_code.co_name) 212 try: 213 # Pipe name is supplied. 214 if pipe_name != None: 215 # Test if the data pipe exists. 216 test(pipe_name) 217 218 # Convert to a list. 219 pipes = [pipe_name] 220 221 # All pipes. 222 else: 223 pipes = ds.keys() 224 225 # Loop over the pipes. 226 for pipe in pipes: 227 # Clean up the pipe bundle, if needed. 228 bundle = get_bundle(pipe) 229 if bundle: 230 # Remove the pipe from the bundle, if needed. 231 ds.pipe_bundles[bundle].remove(pipe) 232 233 # Clean up the bundle. 234 if ds.pipe_bundles[bundle] == []: 235 ds.pipe_bundles.pop(bundle) 236 237 # Delete the data pipe. 238 del ds[pipe] 239 240 # Set the current data pipe to None if it is the deleted data pipe. 241 if ds.current_pipe == pipe: 242 ds.current_pipe = None 243 builtins.cdp = None 244 245 # Release the lock. 246 finally: 247 status.pipe_lock.release(sys._getframe().f_code.co_name) 248 249 # Notify observers that the switch has occurred. 250 status.observers.pipe_alteration.notify()
251 252
253 -def display():
254 """Print the details of all the data pipes.""" 255 256 # Acquire the pipe lock, and make sure it is finally released. 257 status.pipe_lock.acquire(sys._getframe().f_code.co_name) 258 try: 259 # Heading. 260 print("%-20s%-20s%-20s%-20s" % ("Data pipe name", "Data pipe type", "Bundle", "Current")) 261 262 # Loop over the data pipes. 263 for pipe_name in ds: 264 # The current data pipe. 265 current = '' 266 if pipe_name == cdp_name(): 267 current = '*' 268 269 # Print out. 270 print("%-20s%-20s%-20s%-20s" % (repr(pipe_name), get_type(pipe_name), repr(get_bundle(pipe_name)), current)) 271 272 # Release the lock. 273 finally: 274 status.pipe_lock.release(sys._getframe().f_code.co_name)
275 276
277 -def get_bundle(pipe=None):
278 """Return the name of the bundle that the given pipe belongs to. 279 280 @keyword pipe: The name of the data pipe to find the bundle of. 281 @type pipe: str 282 @return: The name of the bundle that the pipe is located in. 283 @rtype: str or None 284 """ 285 286 # Check that the data pipe exists. 287 test(pipe) 288 289 # Find and return the bundle. 290 for key in ds.pipe_bundles.keys(): 291 if pipe in ds.pipe_bundles[key]: 292 return key
293 294
295 -def get_pipe(name=None):
296 """Return a data pipe. 297 298 @keyword name: The name of the data pipe to return. If None, the current data pipe is 299 returned. 300 @type name: str or None 301 @return: The current data pipe. 302 @rtype: PipeContainer instance 303 """ 304 305 # The name of the data pipe. 306 if name == None: 307 name = cdp_name() 308 309 # Test if the data pipe exists. 310 test(name) 311 312 return ds[name]
313 314
315 -def get_type(name=None):
316 """Return the type of the data pipe. 317 318 @keyword name: The name of the data pipe. If None, the current data pipe is used. 319 @type name: str or None 320 @return: The current data pipe type. 321 @rtype: str 322 """ 323 324 # The name of the data pipe. 325 if name == None: 326 name = cdp_name() 327 328 # Get the data pipe. 329 pipe = get_pipe(name) 330 331 return pipe.pipe_type
332 333
334 -def has_bundle(bundle=None):
335 """Determine if the relax data store contains the data pipe bundle. 336 337 @keyword bundle: The name of the data pipe bundle. 338 @type bundle: str 339 @return: The answer to the question. 340 @rtype: bool 341 """ 342 343 # Is the bundle in the keys. 344 if bundle in ds.pipe_bundles.keys(): 345 return True 346 else: 347 return False
348 349
350 -def has_pipe(name):
351 """Determine if the relax data store contains the data pipe. 352 353 @param name: The name of the data pipe. 354 @type name: str 355 @return: True if the data pipe exists, False otherwise. 356 @rtype: bool 357 """ 358 359 # Check. 360 if name in ds: 361 return True 362 else: 363 return False
364 365
366 -def pipe_loop(name=False):
367 """Generator function for looping over and yielding the data pipes. 368 369 @keyword name: A flag which if True will cause the name of the pipe to be returned. 370 @type name: bool 371 @return: The data pipes, and optionally the pipe names. 372 @rtype: PipeContainer instance or tuple of PipeContainer instance and str if name=True 373 """ 374 375 # Acquire the pipe lock, and make sure it is finally released. 376 status.pipe_lock.acquire(sys._getframe().f_code.co_name) 377 try: 378 # Loop over the keys. 379 for key in list(ds.keys()): 380 # Return the pipe and name. 381 if name: 382 yield ds[key], key 383 384 # Return just the pipe. 385 else: 386 yield ds[key] 387 388 # Release the lock (in a Python 2.4 and lower compatible way, see http://stackoverflow.com/questions/2339358/workaround-for-python-2-4s-yield-not-allowed-in-try-block-with-finally-clause). 389 except: 390 status.pipe_lock.release(sys._getframe().f_code.co_name) 391 raise 392 status.pipe_lock.release(sys._getframe().f_code.co_name)
393 394
395 -def pipe_names(bundle=None):
396 """Return the list of all data pipes. 397 398 @keyword bundle: If supplied, the pipe names will be restricted to those of the bundle. 399 @type bundle: str or None 400 @return: The list of data pipes. 401 @rtype: list of str 402 """ 403 404 # Initialise. 405 names = [] 406 pipes = sorted(ds.keys()) 407 408 # Loop over the pipes. 409 for pipe in pipes: 410 # The bundle restriction. 411 if bundle and get_bundle(pipe) != bundle: 412 continue 413 414 # Add the pipe. 415 names.append(pipe) 416 417 # Return the pipe list. 418 return names
419 420
421 -def switch(pipe_name=None):
422 """Switch the current data pipe to the given data pipe. 423 424 @param pipe_name: The name of the data pipe to switch to. 425 @type pipe_name: str 426 """ 427 428 # Acquire the pipe lock (data modifying function), and make sure it is finally released. 429 status.pipe_lock.acquire(sys._getframe().f_code.co_name) 430 try: 431 # Test if the data pipe exists. 432 test(pipe_name) 433 434 # Switch the current data pipe. 435 ds.current_pipe = pipe_name 436 builtins.cdp = get_pipe() 437 438 # Release the lock. 439 finally: 440 status.pipe_lock.release(sys._getframe().f_code.co_name) 441 442 # Notify observers that the switch has occurred. 443 status.observers.pipe_alteration.notify()
444 445
446 -def test(pipe_name=None):
447 """Function for testing the existence of the current or supplied data pipe. 448 449 @param pipe_name: The name of the data pipe to switch to. 450 @type pipe_name: str 451 @return: The answer to the question of whether the pipe exists. 452 @rtype: Boolean 453 """ 454 455 # No supplied data pipe and no current data pipe. 456 if pipe_name == None: 457 # Get the current pipe. 458 pipe_name = cdp_name() 459 460 # Still no luck. 461 if pipe_name == None: 462 raise RelaxNoPipeError 463 464 # Test if the data pipe exists. 465 if pipe_name not in ds: 466 raise RelaxNoPipeError(pipe_name)
467