"Fossies" - the Fresh Open Source Software Archive

Member "relax-5.0.0/relax.py" (6 Dec 2019, 23607 Bytes) of package /linux/privat/relax-5.0.0.src.tar.bz2:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Python source code syntax highlighting (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file. For more information about "relax.py" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 4.1.3_vs_5.0.0.

    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         @keyword mode:          Force a relax mode, overriding the command line.
  144         @type mode:             str
  145         """
  146 
  147         # Get and store the PID of this process.
  148         self.pid = getpid()
  149 
  150         # Set up default process-management exit code
  151         self.exit_code = 0
  152 
  153     def run(self):
  154         """Execute relax.
  155 
  156         This is the application callback method executed by the multi-processor framework.
  157         """
  158 
  159         # Set up the warning system.
  160         lib.warnings.setup()
  161 
  162         # Logging.
  163         if self.log_file:
  164             io_streams_log(self.log_file)
  165 
  166         # Tee.
  167         elif self.tee_file:
  168             io_streams_tee(self.tee_file)
  169 
  170         # Show the version number and exit.
  171         if self.mode == 'version':
  172             print('relax ' + version.version_full())
  173             return
  174 
  175         # Show the relax info and exit.
  176         if self.mode == 'info':
  177             # Initialise the information box.
  178             info = Info_box()
  179 
  180             # Print the program intro.
  181             print(info.intro_text())
  182 
  183             # Print the system info.
  184             print(info.sys_info())
  185 
  186             # Stop execution.
  187             return
  188 
  189         # Run the interpreter for the prompt or script modes.
  190         if self.mode == 'prompt' or self.mode == 'script':
  191             # Run the interpreter.
  192             self.interpreter = interpreter.Interpreter()
  193             self.interpreter.run(self.script_file)
  194 
  195         # Execute the relax GUI.
  196         elif self.mode == 'gui':
  197             # Dependency check.
  198             if not dep_check.wx_module:
  199                 sys.stderr.write("Please install the wx Python module to access the relax GUI.\n\n")
  200                 return
  201 
  202             # Only import the module in this mode (to improve program start up speeds).
  203             import gui
  204 
  205             # Set the GUI flag in the status object.
  206             status.show_gui = True
  207 
  208             # Start the relax GUI wx application.
  209             app = gui.App(script_file=self.script_file)
  210             app.MainLoop()
  211 
  212         # Execute the relax test suite
  213         elif self.mode == 'test suite':
  214             # Only import the module in the test modes (to improve program start up speeds).
  215             from test_suite.test_suite_runner import Test_suite_runner
  216 
  217             # Load the interpreter and turn intros on.
  218             self.interpreter = interpreter.Interpreter(show_script=False, raise_relax_error=True)
  219             self.interpreter.on()
  220 
  221             # Run the tests.
  222             runner = Test_suite_runner(self.tests, timing=self.test_timings, io_capture=self.io_capture, list_tests=self.list_tests)
  223             self.exit_code = int(not runner.run_all_tests())
  224 
  225         # Execute the relax system tests.
  226         elif self.mode == 'system tests':
  227             # Only import the module in the test modes (to improve program start up speeds).
  228             from test_suite.test_suite_runner import Test_suite_runner
  229 
  230             # Load the interpreter and turn intros on.
  231             self.interpreter = interpreter.Interpreter(show_script=False, raise_relax_error=True)
  232             self.interpreter.on()
  233 
  234             # Run the tests.
  235             runner = Test_suite_runner(self.tests, timing=self.test_timings, io_capture=self.io_capture, list_tests=self.list_tests)
  236             self.exit_code = int(not runner.run_system_tests())
  237 
  238         # Execute the relax unit tests.
  239         elif self.mode == 'unit tests':
  240             # Only import the module in the test modes (to improve program start up speeds).
  241             from test_suite.test_suite_runner import Test_suite_runner
  242 
  243             # Run the tests.
  244             runner = Test_suite_runner(self.tests, timing=self.test_timings, io_capture=self.io_capture, list_tests=self.list_tests)
  245             self.exit_code = int(not runner.run_unit_tests())
  246 
  247         # Execute the relax GUI tests.
  248         elif self.mode == 'GUI tests':
  249             # Only import the module in the test modes (to improve program start up speeds).
  250             from test_suite.test_suite_runner import Test_suite_runner
  251 
  252             # Run the tests.
  253             runner = Test_suite_runner(self.tests, timing=self.test_timings, io_capture=self.io_capture, list_tests=self.list_tests)
  254             self.exit_code = int(not runner.run_gui_tests())
  255 
  256         # Execute the relax verification tests.
  257         elif self.mode == 'verification tests':
  258             # Only import the module in the test modes (to improve program start up speeds).
  259             from test_suite.test_suite_runner import Test_suite_runner
  260 
  261             # Run the tests.
  262             runner = Test_suite_runner(self.tests, timing=self.test_timings, io_capture=self.io_capture, list_tests=self.list_tests)
  263             self.exit_code = int(not runner.run_verification_tests())
  264 
  265         # Test mode.
  266         elif self.mode == 'test':
  267             self.test_mode()
  268 
  269         # Licence mode.
  270         elif self.mode == 'licence':
  271             self.licence()
  272 
  273         # Unknown mode.
  274         else:
  275             raise lib.errors.RelaxError("The '%s' mode is unknown." % self.mode)
  276 
  277 
  278     def arguments(self):
  279         """Process the command line arguments."""
  280 
  281         # Parser object.
  282         parser = RelaxParser(description="Molecular dynamics by NMR data analysis.")
  283 
  284         # Recognised command line arguments for the UI.
  285         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.")
  286         group.add_argument('-p', '--prompt', action='store_true', dest='prompt', default=0, help='launch relax in prompt mode after running any optionally supplied scripts')
  287         group.add_argument('-g', '--gui', action='store_true', dest='gui', default=0, help='launch the relax graphical user interface (GUI)')
  288         group.add_argument('-i', '--info', action='store_true', dest='info', default=0, help='display information about this version of relax')
  289         group.add_argument('-v', '--version', action='store_true', dest='version', default=0, help='show the version number and exit')
  290         group.add_argument('--licence', action='store_true', dest='licence', default=0, help='display the licence')
  291         group.add_argument('--test', action='store_true', dest='test', default=0, help='run relax in test mode')
  292 
  293         # Recognised command line arguments for the multiprocessor.
  294         group = parser.add_argument_group('Multi-processor arguments', description="The arguments allowing relax to run in multi-processor environments.")
  295         group.add_argument('-m', '--multi', action='store', type=str, dest='multiprocessor', default='uni', help='set multi processor method to one of \'uni\' or \'mpi4py\'')
  296         group.add_argument('-n', '--processors', action='store', type=int, dest='n_processors', default=-1, help='set number of processors (may be ignored)')
  297 
  298         # Recognised command line arguments for IO redirection.
  299         group = parser.add_argument_group('IO redirection arguments', description="The arguments for sending relax output into a file.")
  300         group.add_argument('-l', '--log', action='store', type=str, dest='log', help='log relax output to the file LOG_FILE', metavar='LOG_FILE')
  301         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')
  302 
  303         # Recognised command line arguments for the test suite.
  304         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.")
  305         group.add_argument('-x', '--test-suite', action='store_true', dest='test_suite', default=0, help='execute the full relax test suite')
  306         group.add_argument('-s', '--system-tests', action='store_true', dest='system_tests', default=0, help='execute the system/functional tests')
  307         group.add_argument('-u', '--unit-tests', action='store_true', dest='unit_tests', default=0, help='execute the unit tests')
  308         group.add_argument('--gui-tests', action='store_true', dest='gui_tests', default=0, help='execute the GUI tests')
  309         group.add_argument('--verification-tests', action='store_true', dest='verification_tests', default=0, help='execute the software verification tests')
  310         group.add_argument('--time', action='store_true', dest='tt', default=0, help='print out the timings of individual tests in the test suite')
  311         group.add_argument('--no-capt', '--no-capture', action='store_true', dest='no_capture', default=0, help='disable IO capture in the test suite')
  312         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')
  313         group.add_argument('--list-tests', action='store_true', dest='list_tests', default=0, help='list the selected tests instead of executing them')
  314 
  315         # Recognised command line arguments for debugging.
  316         group = parser.add_argument_group('Debugging arguments', "The arguments for helping to debug relax.")
  317         group.add_argument('-d', '--debug', action='store_true', dest='debug', default=0, help='enable verbose debugging output')
  318         group.add_argument('--error-state', action='store_true', dest='error_state', default=0, help='save a pickled state file when a RelaxError occurs')
  319         group.add_argument('--traceback', action='store_true', dest='traceback', default=0, help='show stack tracebacks on all RelaxErrors and RelaxWarnings')
  320         group.add_argument('-e', '--escalate', action='store_true', dest='escalate', default=0, help='escalate all warnings into errors')
  321         group.add_argument('--numpy-raise', action='store_true', dest='numpy_raise', default=0, help='convert numpy warnings into errors')
  322 
  323         # The script file or tests to run.
  324         parser.add_argument('script', nargs='*', help='the script file or one or more test classes or individual tests to run')
  325 
  326         # Parse the arguments.
  327         args = parser.parse_args()
  328 
  329         # Debugging arguments:  Debugging flag, escalate flag, traceback flag, and numpy warning to error conversion.
  330         if args.debug:
  331             status.debug = True
  332         if args.escalate:
  333             lib.warnings.ESCALATE = True
  334         if args.traceback:
  335             status.traceback = True
  336             lib.warnings.TRACEBACK = True
  337         if args.numpy_raise:
  338             numpy.seterr(all='raise')
  339         if args.error_state:
  340             lib.errors.SAVE_ERROR_STATE = True
  341 
  342         # Script prompt interactive inspection flag.
  343         if args.prompt:
  344             status.prompt = True
  345 
  346         # Logging.
  347         if args.log:
  348             # Exclusive modes.
  349             if args.tee:
  350                 parser.error("The logging and tee arguments cannot be set simultaneously.")
  351 
  352             # The log file.
  353             self.log_file = args.log
  354 
  355             # Fail if the file already exists.
  356             if access(self.log_file, F_OK):
  357                 parser.error("The log file '%s' already exists." % self.log_file)
  358         else:
  359             self.log_file = None
  360 
  361         # Tee.
  362         if args.tee:
  363             # Exclusive modes.
  364             if args.log:
  365                 parser.error("The tee and logging options cannot be set simultaneously.")
  366 
  367             # The tee file.
  368             self.tee_file = args.tee
  369 
  370             # Fail if the file already exists.
  371             if access(self.tee_file, F_OK):
  372                 parser.error("The tee file '%s' already exists." % self.tee_file)
  373         else:
  374             self.tee_file = None
  375 
  376         # Test suite mode, therefore the args are the tests to run and not a script file.
  377         if args.test_suite or args.system_tests or args.unit_tests or args.gui_tests or args.verification_tests:
  378             # Store the arguments.
  379             self.tests = args.script
  380             self.io_capture = not args.no_capture
  381             self.list_tests = args.list_tests
  382 
  383             # Test timings.
  384             self.test_timings = False
  385             if args.tt:
  386                 self.test_timings = True
  387 
  388             # Run blacklisted tests.
  389             status.skip_blacklisted_tests = True
  390             if args.no_skip:
  391                 status.skip_blacklisted_tests = False
  392 
  393         # The argument is a script (or nothing has been supplied).
  394         else:
  395             # Number of positional arguments should only be 0 or 1.  1 should be the script file.
  396             if len(args.script) > 1:
  397                 parser.error("Incorrect number of arguments.")
  398 
  399             # Script file.
  400             self.script_file = None
  401             if len(args.script) == 1:
  402                 self.script_file = args.script[0]
  403 
  404                 # Test if the script file exists.
  405                 if not access(self.script_file, F_OK):
  406                     parser.error("The script file '%s' does not exist." % self.script_file)
  407 
  408         # Set the multi-processor type and number.
  409         if args.multiprocessor not in ['uni', 'mpi4py']:
  410             parser.error("The processor type '%s' is not supported.\n" % args.multiprocessor)
  411         self.multiprocessor_type = args.multiprocessor
  412         self.n_processors = args.n_processors
  413 
  414         # Checks for the multiprocessor mode.
  415         if self.multiprocessor_type == 'mpi4py' and not dep_check.mpi4py_module:
  416             parser.error(dep_check.mpi4py_message)
  417 
  418 
  419         # Determine the relax mode and test for mutually exclusive modes.
  420         #################################################################
  421 
  422         # Show the version number.
  423         if args.version:
  424             self.mode = 'version'
  425 
  426         # Show the info about this relax version.
  427         elif args.info:
  428             self.mode = 'info'
  429 
  430         # Run the relax tests.
  431         elif args.test_suite or args.system_tests or args.unit_tests or args.gui_tests or args.verification_tests:
  432             # Exclusive modes.
  433             if args.test:
  434                 parser.error("Executing the relax test suite and running relax in test mode are mutually exclusive.")
  435             elif args.licence:
  436                 parser.error("Executing the relax test suite and running relax in licence mode are mutually exclusive.")
  437 
  438             # Set the mode.
  439             if args.test_suite:
  440                 self.mode = 'test suite'
  441             elif args.system_tests:
  442                 self.mode = 'system tests'
  443             elif args.unit_tests:
  444                 self.mode = 'unit tests'
  445             elif args.gui_tests:
  446                 self.mode = 'GUI tests'
  447             elif args.verification_tests:
  448                 self.mode = 'verification tests'
  449 
  450             # Set the status flag.
  451             status.test_mode = True
  452 
  453         # Test mode.
  454         elif args.test:
  455             # Make sure no script is supplied.
  456             if self.script_file:
  457                 parser.error("A script should not be supplied in test mode.")
  458 
  459             # Exclusive modes.
  460             if args.test_suite or args.system_tests or args.unit_tests or args.gui_tests or args.verification_tests:
  461                 parser.error("The relax test mode and executing the test suite are mutually exclusive.")
  462             elif args.licence:
  463                 parser.error("The relax modes test and licence are mutually exclusive.")
  464 
  465             # Set the mode.
  466             self.mode = 'test'
  467 
  468         # Licence mode.
  469         elif args.licence:
  470             # Make sure no script is supplied.
  471             if self.script_file:
  472                 parser.error("A script should not be supplied in test mode.")
  473 
  474             # Exclusive modes.
  475             if args.test_suite or args.system_tests or args.unit_tests or args.gui_tests or args.verification_tests:
  476                 parser.error("The relax licence mode and executing the test suite are mutually exclusive.")
  477             elif args.test:
  478                 parser.error("The relax modes licence and test are mutually exclusive.")
  479 
  480             # Set the mode.
  481             self.mode = 'licence'
  482 
  483         # GUI.
  484         elif args.gui:
  485             # Exclusive models.
  486             if args.test_suite or args.system_tests or args.unit_tests or args.gui_tests or args.verification_tests:
  487                 parser.error("The relax GUI mode and testing modes are mutually exclusive.")
  488             elif args.licence:
  489                 parser.error("The relax GUI mode and licence mode are mutually exclusive.")
  490 
  491             # Missing wx module.
  492             if not dep_check.wx_module:
  493                 # Not installed.
  494                 if dep_check.wx_module_message == "No module named 'wx'":
  495                     parser.error("To use the GUI, the wxPython module must be installed.")
  496 
  497                 # Broken.
  498                 else:
  499                     parser.error("The wxPython installation is broken:\n%s." % dep_check.wx_module_message)
  500 
  501             # Set the mode.
  502             self.mode = 'gui'
  503 
  504         # Script mode.
  505         elif self.script_file:
  506             self.mode = 'script'
  507 
  508         # Prompt mode (default).
  509         else:
  510             self.mode = 'prompt'
  511 
  512 
  513     def licence(self):
  514         """Function for displaying the licence."""
  515 
  516         # Present the GPL using paging.
  517         file = open('docs/COPYING')
  518         pager(file.read())
  519 
  520 
  521     def test_mode(self):
  522         """Relax test mode code."""
  523 
  524         # Don't actually do anything.
  525         return
  526 
  527 
  528 
  529 class RelaxParser(ArgumentParser):
  530     """A custom ArgumentParser class."""
  531 
  532     def error(self, message):
  533         """Replace ArgumentParser.error() with a custom function, enabling the use of RelaxErrors.
  534 
  535         @param message: The error message to output.
  536         @type message:  str
  537         """
  538 
  539         # Usage message.
  540         self.print_usage(sys.stderr)
  541 
  542         # Raise a clean error.
  543         try:
  544             raise lib.errors.RelaxError(message)
  545         except lib.errors.AllRelaxErrors:
  546             instance = sys.exc_info()[1]
  547             sys.stderr.write(instance.__str__())
  548 
  549         # Exit with the Unix command line error code of 2.
  550         sys.exit(2)
  551 
  552 
  553 # Start relax if this file is passed to Python.
  554 if __name__ == "__main__":
  555     start()