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

Source Code for Module pipe_control.pipes

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