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

Source Code for Module pipe_control.pipes

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