Module relax
[hide private]
[frames] | no frames]

Source Code for Module relax

  1  ############################################################################### 
  2  #                                                                             # 
  3  # Copyright (C) 2001-2014,2019 Edward d'Auvergne                              # 
  4  # Copyright (C) 2006 Chris MacRaild                                           # 
  5  # Copyright (C) 2007 Gary Thompson                                            # 
  6  # Copyright (C) 2008 Sebastien Morin                                          # 
  7  # Copyright (C) 2019 Troels Schwarz-Linnet                                    # 
  8  #                                                                             # 
  9  # This program is free software; you can redistribute it and/or modify        # 
 10  # it under the terms of the GNU General Public License as published by        # 
 11  # the Free Software Foundation, either version 3 of the License, or           # 
 12  # (at your option) any later version.                                         # 
 13  #                                                                             # 
 14  # This program is distributed in the hope that it will be useful,             # 
 15  # but WITHOUT ANY WARRANTY; without even the implied warranty of              # 
 16  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               # 
 17  # GNU Library General Public License for more details.                        # 
 18  #                                                                             # 
 19  # You should have received a copy of the GNU General Public License           # 
 20  # along with this program; if not, write to the Free Software                 # 
 21  #                                                                             # 
 22  ############################################################################### 
 23   
 24  # Module docstring. 
 25  """The main module for relax execution.""" 
 26   
 27  # Dependency checks. 
 28  import dep_check 
 29   
 30  # Eliminate the ^[[?1034h escape code being produced on Linux systems by the import of the readline module. 
 31  import os 
 32  if 'TERM' in os.environ and os.environ['TERM'] == 'xterm': 
 33      os.environ['TERM'] = 'linux' 
 34   
 35  # Set up the Python 2 and 3 work-arounds. 
 36  import lib.compat 
 37   
 38  # Python modules. 
 39  from argparse import ArgumentParser 
 40  import numpy 
 41  from os import F_OK, access, getpid, putenv 
 42  if dep_check.cprofile_module: 
 43      import cProfile as profile 
 44  elif dep_check.profile_module: 
 45      import profile 
 46  import pstats 
 47  from pydoc import pager 
 48  import sys 
 49   
 50  # relax modules. 
 51  from info import Info_box 
 52  import lib.errors 
 53  from lib.io import io_streams_log, io_streams_tee 
 54  import lib.warnings 
 55  from multi import Application_callback, load_multiprocessor 
 56  from prompt import interpreter 
 57  from status import Status; status = Status() 
 58  import user_functions 
 59  import version 
 60   
 61   
 62  # Set up the user functions. 
 63  user_functions.initialise() 
 64   
 65  # Modify the environmental variables. 
 66  putenv('PDBVIEWER', 'vmd') 
 67   
 68   
69 -def start(mode=None, profile_flag=False):
70 """Execute relax. 71 72 @keyword mode: Force a relax mode, overriding the command line. 73 @type mode: str 74 @keyword profile_flag: Change this flag to True for code profiling. 75 @type profile_flag: bool 76 """ 77 78 # Normal relax operation. 79 relax = Relax() 80 81 # Override normal operation. 82 if mode: 83 # Override the mode. 84 relax.mode = mode 85 86 # Some defaults. 87 relax.script_file = None 88 relax.log_file = None 89 relax.tee_file = None 90 relax.multiprocessor_type = 'uni' 91 relax.n_processors = 1 92 93 # Process the command line arguments. 94 else: 95 relax.arguments() 96 97 # Store some start up info in the status object. 98 status.relax_mode = relax.mode 99 100 # Set up the multi-processor elements. 101 callbacks = Application_callback(master=relax) 102 verbosity = 0 103 if status.debug: 104 verbosity = 1 105 processor = load_multiprocessor(relax.multiprocessor_type, callbacks, processor_size=relax.n_processors, verbosity=verbosity) 106 107 # Place the processor fabric intro string into the info box. 108 info = Info_box() 109 info.multi_processor_string = processor.get_intro_string() 110 111 # Normal relax operation. 112 if not profile_flag: 113 # Execute relax in multi-processor mode (this includes the uni-processor for normal operation). 114 processor.run() 115 sys.exit(callbacks.master.exit_code) 116 117 # relax in profiling mode. 118 else: 119 def print_stats(stats, status=0): 120 pstats.Stats(stats).sort_stats('time', 'name').print_stats()
121 122 # No profile module. 123 if not dep_check.profile_module: 124 sys.stderr.write("The profile module is not available, please install the Python development packages for profiling.\n\n") 125 sys.exit() 126 127 # Run relax in profiling mode. 128 profile.Profile.print_stats = print_stats 129 profile.runctx('processor.run()', globals(), locals()) 130 131 132
133 -class Relax:
134 """The main relax class. 135 136 This contains information about the running state, for example the mode of operation of relax, 137 whether debugging is turned on, etc. 138 """ 139
140 - def __init__(self):
141 """The top level class for initialising the program.""" 142 143 # Get and store the PID of this process. 144 self.pid = getpid() 145 146 # Set up default process-management exit code 147 self.exit_code = 0
148 149
150 - def run(self):
151 """Execute relax. 152 153 This is the application callback method executed by the multi-processor framework. 154 """ 155 156 # Set up the warning system. 157 lib.warnings.setup() 158 159 # Logging. 160 if self.log_file: 161 io_streams_log(self.log_file) 162 163 # Tee. 164 elif self.tee_file: 165 io_streams_tee(self.tee_file) 166 167 # Show the version number and exit. 168 if self.mode == 'version': 169 print('relax ' + version.version_full()) 170 return 171 172 # Show the relax info and exit. 173 if self.mode == 'info': 174 # Initialise the information box. 175 info = Info_box() 176 177 # Print the program intro. 178 print(info.intro_text()) 179 180 # Print the system info. 181 print(info.sys_info()) 182 183 # Stop execution. 184 return 185 186 # Run the interpreter for the prompt or script modes. 187 if self.mode == 'prompt' or self.mode == 'script': 188 # Run the interpreter. 189 self.interpreter = interpreter.Interpreter() 190 self.interpreter.run(self.script_file) 191 192 # Execute the relax GUI. 193 elif self.mode == 'gui': 194 # Dependency check. 195 if not dep_check.wx_module: 196 sys.stderr.write("Please install the wx Python module to access the relax GUI.\n\n") 197 return 198 199 # Only import the module in this mode (to improve program start up speeds). 200 import gui 201 202 # Set the GUI flag in the status object. 203 status.show_gui = True 204 205 # Start the relax GUI wx application. 206 app = gui.App(script_file=self.script_file) 207 app.MainLoop() 208 209 # Execute the relax test suite 210 elif self.mode == 'test suite': 211 # Only import the module in the test modes (to improve program start up speeds). 212 from test_suite.test_suite_runner import Test_suite_runner 213 214 # Load the interpreter and turn intros on. 215 self.interpreter = interpreter.Interpreter(show_script=False, raise_relax_error=True) 216 self.interpreter.on() 217 218 # Run the tests. 219 runner = Test_suite_runner(self.tests, timing=self.test_timings, io_capture=self.io_capture, list_tests=self.list_tests) 220 self.exit_code = int(not runner.run_all_tests()) 221 222 # Execute the relax system tests. 223 elif self.mode == 'system tests': 224 # Only import the module in the test modes (to improve program start up speeds). 225 from test_suite.test_suite_runner import Test_suite_runner 226 227 # Load the interpreter and turn intros on. 228 self.interpreter = interpreter.Interpreter(show_script=False, raise_relax_error=True) 229 self.interpreter.on() 230 231 # Run the tests. 232 runner = Test_suite_runner(self.tests, timing=self.test_timings, io_capture=self.io_capture, list_tests=self.list_tests) 233 self.exit_code = int(not runner.run_system_tests()) 234 235 # Execute the relax unit tests. 236 elif self.mode == 'unit tests': 237 # Only import the module in the test modes (to improve program start up speeds). 238 from test_suite.test_suite_runner import Test_suite_runner 239 240 # Run the tests. 241 runner = Test_suite_runner(self.tests, timing=self.test_timings, io_capture=self.io_capture, list_tests=self.list_tests) 242 self.exit_code = int(not runner.run_unit_tests()) 243 244 # Execute the relax GUI tests. 245 elif self.mode == 'GUI tests': 246 # Only import the module in the test modes (to improve program start up speeds). 247 from test_suite.test_suite_runner import Test_suite_runner 248 249 # Run the tests. 250 runner = Test_suite_runner(self.tests, timing=self.test_timings, io_capture=self.io_capture, list_tests=self.list_tests) 251 self.exit_code = int(not runner.run_gui_tests()) 252 253 # Execute the relax verification tests. 254 elif self.mode == 'verification tests': 255 # Only import the module in the test modes (to improve program start up speeds). 256 from test_suite.test_suite_runner import Test_suite_runner 257 258 # Run the tests. 259 runner = Test_suite_runner(self.tests, timing=self.test_timings, io_capture=self.io_capture, list_tests=self.list_tests) 260 self.exit_code = int(not runner.run_verification_tests()) 261 262 # Test mode. 263 elif self.mode == 'test': 264 self.test_mode() 265 266 # Licence mode. 267 elif self.mode == 'licence': 268 self.licence() 269 270 # Unknown mode. 271 else: 272 raise lib.errors.RelaxError("The '%s' mode is unknown." % self.mode)
273 274
275 - def arguments(self):
276 """Process the command line arguments.""" 277 278 # Parser object. 279 parser = RelaxParser(description="Molecular dynamics by NMR data analysis.") 280 281 # Recognised command line arguments for the UI. 282 group = parser.add_argument_group('UI arguments', description="The arguments for selecting between the different user interfaces (UI) of relax. If none of these arguments are supplied relax will default into prompt mode or, if a script is supplied, into script mode.") 283 group.add_argument('-p', '--prompt', action='store_true', dest='prompt', default=0, help='launch relax in prompt mode after running any optionally supplied scripts') 284 group.add_argument('-g', '--gui', action='store_true', dest='gui', default=0, help='launch the relax graphical user interface (GUI)') 285 group.add_argument('-i', '--info', action='store_true', dest='info', default=0, help='display information about this version of relax') 286 group.add_argument('-v', '--version', action='store_true', dest='version', default=0, help='show the version number and exit') 287 group.add_argument('--licence', action='store_true', dest='licence', default=0, help='display the licence') 288 group.add_argument('--test', action='store_true', dest='test', default=0, help='run relax in test mode') 289 290 # Recognised command line arguments for the multiprocessor. 291 group = parser.add_argument_group('Multi-processor arguments', description="The arguments allowing relax to run in multi-processor environments.") 292 group.add_argument('-m', '--multi', action='store', type=str, dest='multiprocessor', default='uni', help='set multi processor method to one of \'uni\' or \'mpi4py\'') 293 group.add_argument('-n', '--processors', action='store', type=int, dest='n_processors', default=-1, help='set number of processors (may be ignored)') 294 295 # Recognised command line arguments for IO redirection. 296 group = parser.add_argument_group('IO redirection arguments', description="The arguments for sending relax output into a file.") 297 group.add_argument('-l', '--log', action='store', type=str, dest='log', help='log relax output to the file LOG_FILE', metavar='LOG_FILE') 298 group.add_argument('-t', '--tee', action='store', type=str, dest='tee', help='tee relax output to both stdout and the file LOG_FILE', metavar='LOG_FILE') 299 300 # Recognised command line arguments for the test suite. 301 group = parser.add_argument_group('Test suite arguments', description="The arguments for activating the relax test suite. A subset of tests can be selected by providing the name of one or more test classes, test modules, or individual tests. The names of the tests are shown if the test fails, errors, when the test timings are active, or when IO capture is disabled.") 302 group.add_argument('-x', '--test-suite', action='store_true', dest='test_suite', default=0, help='execute the full relax test suite') 303 group.add_argument('-s', '--system-tests', action='store_true', dest='system_tests', default=0, help='execute the system/functional tests') 304 group.add_argument('-u', '--unit-tests', action='store_true', dest='unit_tests', default=0, help='execute the unit tests') 305 group.add_argument('--gui-tests', action='store_true', dest='gui_tests', default=0, help='execute the GUI tests') 306 group.add_argument('--verification-tests', action='store_true', dest='verification_tests', default=0, help='execute the software verification tests') 307 group.add_argument('--time', action='store_true', dest='tt', default=0, help='print out the timings of individual tests in the test suite') 308 group.add_argument('--no-capt', '--no-capture', action='store_true', dest='no_capture', default=0, help='disable IO capture in the test suite') 309 group.add_argument('--no-skip', action='store_true', dest='no_skip', default=0, help='a debugging option for relax developers to turn on all blacklisted tests, even those that will fail') 310 group.add_argument('--list-tests', action='store_true', dest='list_tests', default=0, help='list the selected tests instead of executing them') 311 312 # Recognised command line arguments for debugging. 313 group = parser.add_argument_group('Debugging arguments', "The arguments for helping to debug relax.") 314 group.add_argument('-d', '--debug', action='store_true', dest='debug', default=0, help='enable verbose debugging output') 315 group.add_argument('--error-state', action='store_true', dest='error_state', default=0, help='save a pickled state file when a RelaxError occurs') 316 group.add_argument('--traceback', action='store_true', dest='traceback', default=0, help='show stack tracebacks on all RelaxErrors and RelaxWarnings') 317 group.add_argument('-e', '--escalate', action='store_true', dest='escalate', default=0, help='escalate all warnings into errors') 318 group.add_argument('--numpy-raise', action='store_true', dest='numpy_raise', default=0, help='convert numpy warnings into errors') 319 320 # The script file or tests to run. 321 parser.add_argument('script', nargs='*', help='the script file or one or more test classes or individual tests to run') 322 323 # Parse the arguments. 324 args = parser.parse_args() 325 326 # Debugging arguments: Debugging flag, escalate flag, traceback flag, and numpy warning to error conversion. 327 if args.debug: 328 status.debug = True 329 if args.escalate: 330 lib.warnings.ESCALATE = True 331 if args.traceback: 332 status.traceback = True 333 lib.warnings.TRACEBACK = True 334 if args.numpy_raise: 335 numpy.seterr(all='raise') 336 if args.error_state: 337 lib.errors.SAVE_ERROR_STATE = True 338 339 # Script prompt interactive inspection flag. 340 if args.prompt: 341 status.prompt = True 342 343 # Logging. 344 if args.log: 345 # Exclusive modes. 346 if args.tee: 347 parser.error("The logging and tee arguments cannot be set simultaneously.") 348 349 # The log file. 350 self.log_file = args.log 351 352 # Fail if the file already exists. 353 if access(self.log_file, F_OK): 354 parser.error("The log file '%s' already exists." % self.log_file) 355 else: 356 self.log_file = None 357 358 # Tee. 359 if args.tee: 360 # Exclusive modes. 361 if args.log: 362 parser.error("The tee and logging options cannot be set simultaneously.") 363 364 # The tee file. 365 self.tee_file = args.tee 366 367 # Fail if the file already exists. 368 if access(self.tee_file, F_OK): 369 parser.error("The tee file '%s' already exists." % self.tee_file) 370 else: 371 self.tee_file = None 372 373 # Test suite mode, therefore the args are the tests to run and not a script file. 374 if args.test_suite or args.system_tests or args.unit_tests or args.gui_tests or args.verification_tests: 375 # Store the arguments. 376 self.tests = args.script 377 self.io_capture = not args.no_capture 378 self.list_tests = args.list_tests 379 380 # Test timings. 381 self.test_timings = False 382 if args.tt: 383 self.test_timings = True 384 385 # Run blacklisted tests. 386 status.skip_blacklisted_tests = True 387 if args.no_skip: 388 status.skip_blacklisted_tests = False 389 390 # The argument is a script (or nothing has been supplied). 391 else: 392 # Number of positional arguments should only be 0 or 1. 1 should be the script file. 393 if len(args.script) > 1: 394 parser.error("Incorrect number of arguments.") 395 396 # Script file. 397 self.script_file = None 398 if len(args.script) == 1: 399 self.script_file = args.script[0] 400 401 # Test if the script file exists. 402 if not access(self.script_file, F_OK): 403 parser.error("The script file '%s' does not exist." % self.script_file) 404 405 # Set the multi-processor type and number. 406 if args.multiprocessor not in ['uni', 'mpi4py']: 407 parser.error("The processor type '%s' is not supported.\n" % args.multiprocessor) 408 self.multiprocessor_type = args.multiprocessor 409 self.n_processors = args.n_processors 410 411 # Checks for the multiprocessor mode. 412 if self.multiprocessor_type == 'mpi4py' and not dep_check.mpi4py_module: 413 parser.error(dep_check.mpi4py_message) 414 415 416 # Determine the relax mode and test for mutually exclusive modes. 417 ################################################################# 418 419 # Show the version number. 420 if args.version: 421 self.mode = 'version' 422 423 # Show the info about this relax version. 424 elif args.info: 425 self.mode = 'info' 426 427 # Run the relax tests. 428 elif args.test_suite or args.system_tests or args.unit_tests or args.gui_tests or args.verification_tests: 429 # Exclusive modes. 430 if args.test: 431 parser.error("Executing the relax test suite and running relax in test mode are mutually exclusive.") 432 elif args.licence: 433 parser.error("Executing the relax test suite and running relax in licence mode are mutually exclusive.") 434 435 # Set the mode. 436 if args.test_suite: 437 self.mode = 'test suite' 438 elif args.system_tests: 439 self.mode = 'system tests' 440 elif args.unit_tests: 441 self.mode = 'unit tests' 442 elif args.gui_tests: 443 self.mode = 'GUI tests' 444 elif args.verification_tests: 445 self.mode = 'verification tests' 446 447 # Set the status flag. 448 status.test_mode = True 449 450 # Test mode. 451 elif args.test: 452 # Make sure no script is supplied. 453 if self.script_file: 454 parser.error("A script should not be supplied in test mode.") 455 456 # Exclusive modes. 457 if args.test_suite or args.system_tests or args.unit_tests or args.gui_tests or args.verification_tests: 458 parser.error("The relax test mode and executing the test suite are mutually exclusive.") 459 elif args.licence: 460 parser.error("The relax modes test and licence are mutually exclusive.") 461 462 # Set the mode. 463 self.mode = 'test' 464 465 # Licence mode. 466 elif args.licence: 467 # Make sure no script is supplied. 468 if self.script_file: 469 parser.error("A script should not be supplied in test mode.") 470 471 # Exclusive modes. 472 if args.test_suite or args.system_tests or args.unit_tests or args.gui_tests or args.verification_tests: 473 parser.error("The relax licence mode and executing the test suite are mutually exclusive.") 474 elif args.test: 475 parser.error("The relax modes licence and test are mutually exclusive.") 476 477 # Set the mode. 478 self.mode = 'licence' 479 480 # GUI. 481 elif args.gui: 482 # Exclusive models. 483 if args.test_suite or args.system_tests or args.unit_tests or args.gui_tests or args.verification_tests: 484 parser.error("The relax GUI mode and testing modes are mutually exclusive.") 485 elif args.licence: 486 parser.error("The relax GUI mode and licence mode are mutually exclusive.") 487 488 # Missing wx module. 489 if not dep_check.wx_module: 490 # Not installed. 491 if dep_check.wx_module_message == "No module named 'wx'": 492 parser.error("To use the GUI, the wxPython module must be installed.") 493 494 # Broken. 495 else: 496 parser.error("The wxPython installation is broken:\n%s." % dep_check.wx_module_message) 497 498 # Set the mode. 499 self.mode = 'gui' 500 501 # Script mode. 502 elif self.script_file: 503 self.mode = 'script' 504 505 # Prompt mode (default). 506 else: 507 self.mode = 'prompt'
508 509
510 - def licence(self):
511 """Function for displaying the licence.""" 512 513 # Present the GPL using paging. 514 file = open('docs/COPYING') 515 pager(file.read())
516 517
518 - def test_mode(self):
519 """Relax test mode code.""" 520 521 # Don't actually do anything. 522 return
523 524 525
526 -class RelaxParser(ArgumentParser):
527 """A custom ArgumentParser class.""" 528
529 - def error(self, message):
530 """Replace ArgumentParser.error() with a custom function, enabling the use of RelaxErrors. 531 532 @param message: The error message to output. 533 @type message: str 534 """ 535 536 # Usage message. 537 self.print_usage(sys.stderr) 538 539 # Raise a clean error. 540 try: 541 raise lib.errors.RelaxError(message) 542 except lib.errors.AllRelaxErrors: 543 instance = sys.exc_info()[1] 544 sys.stderr.write(instance.__str__()) 545 546 # Exit with the Unix command line error code of 2. 547 sys.exit(2)
548 549 550 # Start relax if this file is passed to Python. 551 if __name__ == "__main__": 552 start() 553