From cf3fb6f065491ecc82086ea08ae3b60e4ebf400f Mon Sep 17 00:00:00 2001 From: Xavier Robin <xavalias-github@xavier.robin.name> Date: Thu, 11 May 2023 15:59:58 +0200 Subject: [PATCH] feat: SCHWED-5913 setup compound lib with import ost This sets up the compound lib upon calling import ost. It simplifies the ost_startup.py script accordingly. It is now possible to override the compound lib with an environment variable: OST_COMPOUNDS_CHEMLIB --- modules/base/pymod/__init__.py.in | 75 ++++++++++++++++++++++++++++++- modules/conop/doc/compoundlib.rst | 15 +++++-- modules/doc/install.rst | 16 +++++++ scripts/ost_config.in | 1 + scripts/ost_startup.py.in | 13 ------ 5 files changed, 102 insertions(+), 18 deletions(-) diff --git a/modules/base/pymod/__init__.py.in b/modules/base/pymod/__init__.py.in index 7b39730af..2d6f85a73 100644 --- a/modules/base/pymod/__init__.py.in +++ b/modules/base/pymod/__init__.py.in @@ -16,12 +16,13 @@ # along with this library; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA #------------------------------------------------------------------------------ - +import os __all__=['CharList','Correl', 'FileLogSink', 'FloatList', 'FloatMatrix', 'FloatMatrix3', 'FloatMatrix4', 'GetCurrentLogSink', 'GetPrefixPath', 'GetSharedDataPath', 'GetVerbosityLevel', 'Histogram', 'IntList', 'LogDebug', 'LogError', 'LogInfo', 'LogScript', 'LogSink', 'LogTrace', 'LogVerbose', 'LogWarning', 'Max', 'Mean', 'Median', 'Min', 'MultiLogSink', 'PopLogSink', 'PopVerbosityLevel', 'PushLogSink', 'PushVerbosityLevel', 'Range', 'SetPrefixPath', 'StdDev', 'StreamLogSink', 'StringList', 'StringLogSink', 'Units', 'VERSION', 'VERSION_MAJOR', 'VERSION_MINOR', 'VERSION_PATCH', 'WITH_NUMPY', 'conop', 'geom', 'io', 'mol', 'seq', 'stutil' @ALL_ADDITIONAL_MODULES@] from ._ost_base import * from .stutil import * +from ost import conop class StreamLogSink(LogSink): def __init__(self, stream): @@ -29,3 +30,75 @@ class StreamLogSink(LogSink): self._stream=stream def LogMessage(self, message, level): self._stream.write(message) + + +def _SetupOstPrefix(): + """ This function attempts to set the OST prefix path if $OST_ROOT was not + set already. + + It does so by assuming that the __init__.py file is located under + $OST_ROOT/lib(64)?/pythonX.XX/site-packages/ost. This might not be the case + in all settings (conda, pip?). In that case this function should be + adapted. + """ + + try: + # $OST_ROOT was set + GetPrefixPath() + except RuntimeError: + # Setup from this file's path + prefix_path = __file__ + for _ in range(5): + prefix_path = os.path.dirname(prefix_path) + SetPrefixPath(prefix_path) + + +def _TrySetCompoundsLib(path): + """Tries to set the compound lib to 'path', or raises a ValueError.""" + if path is not None and os.path.exists(path): + compound_lib = conop.CompoundLib.Load(path) + if compound_lib is not None: + conop.SetDefaultLib(compound_lib) + return + raise ValueError("Could not load %s" % path) + + +def _SetupCompoundsLib(): + """ This function sets up the compound lib. + + By order of priority, the following heuristics are used: + + 1. The $OST_COMPOUNDS_CHEMLIB environment variable + 2. The 'compounds.chemlib' file in the shared path under the folder pointed + by the $OST_ROOT environment variable + + If no compound library can be loaded with any of these strategies, a warning + message is issued. + + """ + # Try with the $OST_COMPOUNDS_CHEMLIB environment variable + compound_lib_path = os.getenv("OST_COMPOUNDS_CHEMLIB") + try: + _TrySetCompoundsLib(compound_lib_path) + except ValueError: + pass + else: + return + + # Try from GetSharedDataPath() - requires $OST_ROOT to be set. + try: + compound_lib_path = os.path.join(GetSharedDataPath(), 'compounds.chemlib') + _TrySetCompoundsLib(compound_lib_path) + except (RuntimeError, ValueError): + pass + else: + return + + LogWarning("Compound library not available. Some functionality may not " \ + "work as expected.") + + +# Setup OST +PushVerbosityLevel(LogLevel.Script) +_SetupOstPrefix() +_SetupCompoundsLib() diff --git a/modules/conop/doc/compoundlib.rst b/modules/conop/doc/compoundlib.rst index b454ff98d..fed70b637 100644 --- a/modules/conop/doc/compoundlib.rst +++ b/modules/conop/doc/compoundlib.rst @@ -21,10 +21,17 @@ build the compound library manually. .. function:: GetDefaultLib() - :return: Default compound library set by :func:`SetDefaultLib`. If you got - OpenStructure as a bundle or you :ref:`compiled <cmake-flags>` it - with a specified ``COMPOUND_LIB`` flag, this will return a compound - library when executing scripts with ``ost``. + Get the default compound library. This is set by :func:`SetDefaultLib`. + + If you obtained OpenStructure as a container or you + :ref:`compiled <cmake-flags>` it with a specified ``COMPOUND_LIB`` flag, + this function will return a compound library. + + You can override the default compound library by pointing the + ``OST_COMPOUNDS_CHEMLIB`` environment variable to a valid compound library + file. + + :return: Default compound library. :rtype: :class:`CompoundLib` or None if no library set .. function:: SetDefaultLib(lib) diff --git a/modules/doc/install.rst b/modules/doc/install.rst index d840eeab2..dd4d4d5e1 100644 --- a/modules/doc/install.rst +++ b/modules/doc/install.rst @@ -420,6 +420,22 @@ or, to start the command-line interpreter: If you repeatedly use OpenStructure, it is recommended to add /path/to/ost/stage/bin to your path. +You can also import OpenStructure directly into your existing python scripts, +jupyter notebooks etc. Simply make sure to point the following environment +variables to the right folders: + +.. code-block:: bash + + export OST_ROOT=/path/to/ost/stage + export PYTHONPATH=$OST_ROOT/lib64/python3.10/site-packages/:$PYTHONPATH + python + +And then you can simply import ost as a module: + +.. code-block:: python + + import ost + Getting the newest changes -------------------------------------------------------------------------------- diff --git a/scripts/ost_config.in b/scripts/ost_config.in index d0ba65da0..69e792960 100644 --- a/scripts/ost_config.in +++ b/scripts/ost_config.in @@ -25,6 +25,7 @@ export DNG_ROOT=`cd "$BIN_DIR/..";pwd` export DNG_BINDIR="$DNG_ROOT/bin" export DNG_LIBDIR="$DNG_ROOT/@LIBDIR@" export DNG_INITDIR="$DNG_LIBDIR/@PYTHON_MODULE_PATH@/ost/" +export OST_ROOT="$DNG_ROOT" export PATH="$DNG_BINDIR:${PATH}" export DYLD_FRAMEWORK_PATH="$DNG_LIBDIR:${DYLD_FRAMEWORK_PATH}" diff --git a/scripts/ost_startup.py.in b/scripts/ost_startup.py.in index 3d22c7e7e..c451bec38 100644 --- a/scripts/ost_startup.py.in +++ b/scripts/ost_startup.py.in @@ -44,23 +44,10 @@ parser.disable_interspersed_args() _site_packs='python%d.%d/site-packages' % sys.version_info[0:2] _base_dir=os.getenv('DNG_ROOT') sys.path.insert(0, os.path.join(_base_dir, '@LIBDIR@', _site_packs)) - -from ost import SetPrefixPath, GetSharedDataPath, conop -SetPrefixPath(_base_dir) - -def _InitRuleBasedProcessor(): - compound_lib_path=os.path.join(GetSharedDataPath(), 'compounds.chemlib') - if os.path.exists(compound_lib_path): - compound_lib=conop.CompoundLib.Load(compound_lib_path) - conop.SetDefaultLib(compound_lib) - -# switch to rule-based processor, if compound library is available -_InitRuleBasedProcessor() from ost import * import ost -import os.path HistoryFile=os.path.expanduser('~/.ost_history') # we are not in GUI mode. -- GitLab