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

Source Code for Module pipe_control.pipes

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