|
1 | 1 | #!/usr/bin/env python |
2 | | -""" |
3 | | -Backward compatibility stub for simuOpt module. |
4 | 2 |
|
5 | | -DEPRECATED: Please use 'from simuPOP.simuOpt import setOptions' instead. |
6 | | - This import path will be removed in a future version. |
7 | | -""" |
| 3 | +# |
| 4 | +# $File: simuOpt.py $ |
| 5 | +# $LastChangedDate$ |
| 6 | +# $Rev$ |
| 7 | +# |
| 8 | +# This file is part of simuPOP, a forward-time population genetics |
| 9 | +# simulation environment. Please visit https://github.com/BoPeng/simuPOP |
| 10 | +# for details. |
| 11 | +# |
| 12 | +# Copyright (C) 2004 - 2010 Bo Peng (Bo.Peng@bcm.edu) |
| 13 | +# |
| 14 | +# This program is free software: you can redistribute it and/or modify |
| 15 | +# it under the terms of the GNU General Public License as published by |
| 16 | +# the Free Software Foundation, either version 3 of the License, or |
| 17 | +# (at your option) any later version. |
| 18 | +# |
| 19 | +# This program is distributed in the hope that it will be useful, |
| 20 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 21 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 22 | +# GNU General Public License for more details. |
| 23 | +# |
| 24 | +# You should have received a copy of the GNU General Public License |
| 25 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
| 26 | +# |
8 | 27 |
|
9 | | -import warnings |
| 28 | +''' |
| 29 | +Module ``simuOpt`` provides a function ``simuOpt.setOptions`` to control which |
| 30 | +simuPOP module to load, and how it is loaded, and a class ``simuOpt.Params`` |
| 31 | +that helps users manage simulation parameters. |
10 | 32 |
|
11 | | -warnings.warn( |
12 | | - "Importing 'simuOpt' directly is deprecated. " |
13 | | - "Please use 'from simuPOP.simuOpt import setOptions' instead. " |
14 | | - "This import path will be removed in a future version.", |
15 | | - DeprecationWarning, |
16 | | - stacklevel=2 |
17 | | -) |
| 33 | +When simuPOP is loaded, it checkes a few environmental variables |
| 34 | +(``SIMUOPTIMIZED``, ``SIMUALLELETYPE``, and ``SIMUDEBUG``) to determine which |
| 35 | +simuPOP module to load, and how to load it. More options can be set using the |
| 36 | +``simuOpt.setOptions`` function. For example, you can suppress the banner |
| 37 | +message when simuPOP is loaded and require a minimal version of simuPOP for |
| 38 | +your script. simuPOP recognize the following commandline arguments |
18 | 39 |
|
19 | | -from simuPOP.simuOpt import * |
| 40 | +``--optimized`` |
| 41 | + Load the optimized version of a simuPOP module. |
| 42 | +
|
| 43 | +``--gui=None|batch|interactive|True|wxPython|Tkinter`` |
| 44 | + Whether or not use a graphical toolkit and which one to use. |
| 45 | + ``--gui=batch`` is usually used to run a script in batch mode (do not start |
| 46 | + a parameter input dialog and use all default values unless a parameter is |
| 47 | + specified from command line or a configuraiton file. If |
| 48 | + ``--gui=interactive``, an interactive shell will be used to solicit input |
| 49 | + from users. Otherwise, simuPOP will try to use a graphical parameter input |
| 50 | + dialog, and falls to an interactive mode when no graphical Toolkit is |
| 51 | + available. Please refer to parameter ``gui`` for ``simuOpt.setOptions`` |
| 52 | + for details. |
| 53 | +
|
| 54 | +class ``params.Params`` provides a powerful way to handle commandline |
| 55 | +arguments. Briefly speaking, a ``Params`` object can be created from a list |
| 56 | +of parameter specification dictionaries. The parameters are then become |
| 57 | +attributes of this object. A number of functions are provided to determine |
| 58 | +values of these parameters using commandline arguments, a configuration |
| 59 | +file, or a parameter input dialog (using ``Tkinter`` or ``wxPython``). |
| 60 | +Values of these parameters can be accessed as attributes, or extracted |
| 61 | +as a list or a dictionary. Note that the ``Params.getParam`` function |
| 62 | +automatically handles the following commandline arguments. |
| 63 | +
|
| 64 | +``-h`` or ``--help`` |
| 65 | + Print usage message. |
| 66 | +
|
| 67 | +``--config=configFile`` |
| 68 | + Read parameters from a configuration file *configFile*. |
| 69 | +
|
| 70 | +''' |
| 71 | + |
| 72 | + |
| 73 | +__all__ = [ |
| 74 | + 'simuOptions', |
| 75 | + 'setOptions' |
| 76 | +] |
| 77 | + |
| 78 | +import os, sys, re, time, textwrap |
| 79 | +# |
| 80 | +# simuOptions that will be checked when simuPOP is loaded. This structure |
| 81 | +# can be changed by function setOptions |
| 82 | +# |
| 83 | + |
| 84 | +simuOptions = { |
| 85 | + 'Optimized': False, |
| 86 | + 'AlleleType': 'short', |
| 87 | + 'Debug': [], |
| 88 | + 'Quiet': False, |
| 89 | + 'Version': None, |
| 90 | + 'Revision': None, |
| 91 | + 'GUI': True, |
| 92 | + 'Plotter': None, |
| 93 | + 'NumThreads': 1, |
| 94 | +} |
| 95 | + |
| 96 | +# Optimized: command line option --optimized or environmental variable SIMUOPTIMIZED |
| 97 | +if '--optimized' in sys.argv or os.getenv('SIMUOPTIMIZED') is not None: |
| 98 | + simuOptions['Optimized'] = True |
| 99 | + |
| 100 | +# AlleleType: from environmental variable SIMUALLELETYPE |
| 101 | +if os.getenv('SIMUALLELETYPE') in ['short', 'long', 'binary', 'mutant', 'lineage']: |
| 102 | + simuOptions['AlleleType'] = os.getenv('SIMUALLELETYPE') |
| 103 | +elif os.getenv('SIMUALLELETYPE') is not None: |
| 104 | + print('Environmental variable SIMUALLELETYPE can only be short, long, binary, mutant, or lineage.') |
| 105 | + |
| 106 | +# Debug: from environmental variable SIMUDEBUG |
| 107 | +if os.getenv('SIMUDEBUG') is not None: |
| 108 | + simuOptions['Debug'].extend(os.getenv('SIMUDEBUG').split(',')) |
| 109 | + |
| 110 | +# openMP number of threads |
| 111 | +if os.getenv('OMP_NUM_THREADS') is not None: |
| 112 | + try: |
| 113 | + simuOptions['NumThreads'] = int(os.getenv('OMP_NUM_THREADS')) |
| 114 | + except: |
| 115 | + print('Ignoring invalid value for environmental variable OMP_NUM_THREADS') |
| 116 | + |
| 117 | +# GUI: from environmental variable SIMUGUI |
| 118 | +if os.getenv('SIMUGUI') is not None: |
| 119 | + _gui = os.getenv('SIMUGUI') |
| 120 | +elif '--gui' in sys.argv: |
| 121 | + if sys.argv[-1] == '--gui': |
| 122 | + raise ValueError('An value is expected for command line option --gui') |
| 123 | + _gui = sys.argv[sys.argv.index('--gui') + 1] |
| 124 | +elif True in [x.startswith('--gui=') for x in sys.argv]: |
| 125 | + _gui = sys.argv[[x.startswith('--gui=') for x in sys.argv].index(True)][len('--gui='):] |
| 126 | +else: |
| 127 | + _gui = None |
| 128 | + |
| 129 | +if _gui in ['True', 'true', '1']: |
| 130 | + simuOptions['GUI'] = True |
| 131 | +elif _gui in ['False', 'false', '0']: |
| 132 | + simuOptions['GUI'] = False |
| 133 | +elif _gui in ['wxPython', 'Tkinter', 'batch', 'interactive']: |
| 134 | + simuOptions['GUI'] = _gui |
| 135 | +elif _gui is not None: |
| 136 | + print("Invalid value '%s' for environmental variable SIMUGUI or commandline option --gui." % _gui) |
| 137 | + |
| 138 | +def setOptions(alleleType=None, optimized=None, gui=None, quiet=None, |
| 139 | + debug=None, version=None, revision=None, numThreads=None, plotter=None): |
| 140 | + '''Set options before simuPOP is loaded to control which simuPOP module to |
| 141 | + load, and how the module should be loaded. |
| 142 | +
|
| 143 | + alleleType |
| 144 | + Use the standard, binary,long or mutant allele version of the simuPOP |
| 145 | + module if ``alleleType`` is set to 'short', 'binary', 'long', 'mutant', |
| 146 | + or 'lineage' respectively. If this parameter is not set, this function |
| 147 | + will try to get its value from environmental variable ``SIMUALLELETYPE``. |
| 148 | + The standard (short) module will be used if the environmental variable |
| 149 | + is not defined. |
| 150 | +
|
| 151 | + optimized |
| 152 | + Load the optimized version of a module if this parameter is set to |
| 153 | + ``True`` and the standard version if it is set to ``False``. If this |
| 154 | + parameter is not set (``None``), the optimized version will be used |
| 155 | + if environmental variable ``SIMUOPTIMIZED`` is defined. The standard |
| 156 | + version will be used otherwise. |
| 157 | +
|
| 158 | + gui |
| 159 | + Whether or not use graphical user interfaces, which graphical toolkit |
| 160 | + to use and how to process parameters in non-GUI mode. If this parameter |
| 161 | + is ``None`` (default), this function will check environmental variable |
| 162 | + ``SIMUGUI`` or commandline option ``--gui`` for a value, and assume |
| 163 | + ``True`` if such an option is unavailable. If ``gui=True``, simuPOP |
| 164 | + will use ``wxPython``-based dialogs if ``wxPython`` is available, and |
| 165 | + use ``Tkinter``-based dialogs if ``Tkinter`` is available and use an |
| 166 | + interactive shell if no graphical toolkit is available. |
| 167 | + ``gui='Tkinter'`` or ``'wxPython'`` can be used to specify the |
| 168 | + graphical toolkit to use. If ``gui='interactive'``, a simuPOP script |
| 169 | + prompt users to input values of parameters. If ``gui='batch'``, |
| 170 | + default values of unspecified parameters will be used. In any case, |
| 171 | + commandline arguments and a configuration file specified by parameter |
| 172 | + --config will be processed. This option is usually left to ``None`` so |
| 173 | + that the same script can be run in both GUI and batch mode using |
| 174 | + commandline option ``--gui``. |
| 175 | +
|
| 176 | + plotter |
| 177 | + (Deprecated) |
| 178 | +
|
| 179 | + quiet |
| 180 | + If set to ``True``, suppress the banner message when a simuPOP module |
| 181 | + is loaded. |
| 182 | +
|
| 183 | + debug |
| 184 | + A list of debug code (as string) that will be turned on when simuPOP |
| 185 | + is loaded. If this parameter is not set, a list of comma separated |
| 186 | + debug code specified in environmental variable ``SIMUDEBUG``, if |
| 187 | + available, will be used. Note that setting ``debug=[]`` will remove |
| 188 | + any debug code that might have been by variable ``SIMUDEBUG``. |
| 189 | +
|
| 190 | + version |
| 191 | + A version string (e.g. 1.0.0) indicating the required version number |
| 192 | + for the simuPOP module to be loaded. simuPOP will fail to load if the |
| 193 | + installed version is older than the required version. |
| 194 | +
|
| 195 | + revision |
| 196 | + Obsolete with the introduction of parameter version. |
| 197 | +
|
| 198 | + numThreads |
| 199 | + Number of Threads that will be used to execute a simuPOP script. The |
| 200 | + values can be a positive number (number of threads) or 0 (all available |
| 201 | + cores of the computer, or whatever number set by environmental variable |
| 202 | + ``OMP_NUM_THREADS``). If this parameter is not set, the number of |
| 203 | + threads will be set to 1, or a value set by environmental variable |
| 204 | + ``OMP_NUM_THREADS``. |
| 205 | + ''' |
| 206 | + # if the module has already been imported, check which module |
| 207 | + # was imported |
| 208 | + try: |
| 209 | + _imported = sys.modules['simuPOP'].moduleInfo() |
| 210 | + except Exception as e: |
| 211 | + _imported = {} |
| 212 | + # Allele type |
| 213 | + if alleleType in ['long', 'binary', 'short', 'mutant', 'lineage']: |
| 214 | + # if simuPOP has been imported and re-imported with a different module name |
| 215 | + # the existing module will be used so moduleInfo() will return a different |
| 216 | + # module type from what is specified in simuOptions. |
| 217 | + if _imported and _imported['alleleType'] != alleleType: |
| 218 | + raise ImportError(('simuPOP has already been imported with allele type %s (%s) and cannot be ' |
| 219 | + 're-imported with allele type %s. Please make sure you import module simuOpt before ' |
| 220 | + 'any simuPOP module is imported.') % ( |
| 221 | + _imported['alleleType'], ('optimized' if _imported['optimized'] else 'standard'), |
| 222 | + alleleType)) |
| 223 | + simuOptions['AlleleType'] = alleleType |
| 224 | + elif alleleType is not None: |
| 225 | + raise TypeError('Parameter alleleType can be either short, long, binary, mutant or lineage.') |
| 226 | + # Optimized |
| 227 | + if optimized in [True, False]: |
| 228 | + # if simuPOP has been imported and re-imported with a different module name |
| 229 | + # the existing module will be used so moduleInfo() will return a different |
| 230 | + # module type from what is specified in simuOptions. |
| 231 | + if _imported and _imported['optimized'] != optimized: |
| 232 | + raise ImportError(('simuPOP has already been imported with allele type %s (%s) and cannot be ' |
| 233 | + 're-imported in %s mode. Please make sure you import module simuOpt before ' |
| 234 | + 'any simuPOP module is imported.') % ( |
| 235 | + _imported['alleleType'], ('optimized' if _imported['optimized'] else 'standard'), |
| 236 | + 'optimized' if optimized else 'standard')) |
| 237 | + simuOptions['Optimized'] = optimized |
| 238 | + elif optimized is not None: |
| 239 | + raise TypeError('Parameter optimized can be either True or False.') |
| 240 | + # Graphical toolkit |
| 241 | + if gui in [True, False, 'wxPython', 'Tkinter', 'batch']: |
| 242 | + simuOptions['GUI'] = gui |
| 243 | + elif gui is not None: |
| 244 | + raise TypeError('Parameter gui can be True/False, wxPython or Tkinter.') |
| 245 | + # Quiet |
| 246 | + if quiet in [True, False]: |
| 247 | + simuOptions['Quiet'] = quiet |
| 248 | + elif quiet is not None: |
| 249 | + raise TypeError('Parameter quiet can be either True or False.') |
| 250 | + # Debug |
| 251 | + if debug is not None: |
| 252 | + if type(debug) == str: |
| 253 | + simuOptions['Debug'] = [debug] |
| 254 | + else: |
| 255 | + simuOptions['Debug'] = debug |
| 256 | + # Version |
| 257 | + if type(version) == str: |
| 258 | + try: |
| 259 | + major, minor, release = [int(x) for x in re.sub('\D', ' ', version).split()] |
| 260 | + except: |
| 261 | + print('Invalid version string %s' % simuOptions['Version']) |
| 262 | + simuOptions['Version'] = version |
| 263 | + elif version is not None: |
| 264 | + raise TypeError('A version string is expected for parameter version.') |
| 265 | + # Revision |
| 266 | + if type(revision) == int: |
| 267 | + simuOptions['Revision'] = revision |
| 268 | + elif revision is not None: |
| 269 | + raise TypeError('A revision number is expected for parameter revision.') |
| 270 | + # NumThreads |
| 271 | + if type(numThreads) == int: |
| 272 | + simuOptions['NumThreads'] = numThreads |
| 273 | + elif numThreads is not None: |
| 274 | + raise TypeError('An integer number is expected for parameter numThreads.') |
| 275 | + if plotter is not None: |
| 276 | + sys.stderr.write('WARNING: plotter option is deprecated because of the removal of rpy/rpy2 support\n') |
0 commit comments