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