diff --git a/CHANGELOG.txt b/CHANGELOG.txt index c19df24e2213c955cf3d29f9db4236431baf114b..4151f7269f101d4cc37d7d97d5bafff65945cc65 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -1,4 +1,23 @@ +Changes in Release 1.2.1 +-------------------------------------------------------------------------------- + + * Use RPATH for linux bundles. No longer requires LD_LIBRARY_PATH to be set for + chemdict_tool and lddt [BZDNG-385] + * "install command line tools" also symlinks lddt, and chemdict_tool [BZDNG-386] + * Fixed broken the_hammer.py example [BZDNG-387] + * MacOS X: Make sure to use python2.6, not python as pyexec [BZDNG-388] + * Fix example directory path for MacOS X bundle [BZDNG-389] + * PDBWriter: Insert newline after END [BZDNG-391] + * Added missing documentation for a few AlignmentHandle methods + * Workaround for naccess which was failing when directory contains dots. + * Fixed superposition dialog for unnamed chains + * Fixed byte-swapping issue for DCD trajectories + * Fixed FFT panel update after switching data in main viewer + * Added missing pdbx_struct_assembly.id export + * lDDT: Updated default angle and bond tolerance parameters from 8 stddev to 12 + stddev. + Changes in Release 1.2 (since 1.1) -------------------------------------------------------------------------------- diff --git a/CMakeLists.txt b/CMakeLists.txt index ea8c6ac05f5b3099bb09a9dcde33d878e0d7ee9d..e6d4dbbfe8758fa119ce22f3c98d995d08105963 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,7 +6,7 @@ cmake_minimum_required(VERSION 2.6.4 FATAL_ERROR) project(OpenStructure CXX C) set (OST_VERSION_MAJOR 1) set (OST_VERSION_MINOR 2) -set (OST_VERSION_PATCH 0) +set (OST_VERSION_PATCH 1) set (OST_VERSION_STRING ${OST_VERSION_MAJOR}.${OST_VERSION_MINOR}.${OST_VERSION_PATCH} ) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${PROJECT_SOURCE_DIR}/cmake_support) include(OST) @@ -275,7 +275,7 @@ if (UNIX) SET(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE) if(USE_RPATH) set(_USE_RPATH ON) - SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${LIB_DIR}") + SET(CMAKE_INSTALL_RPATH "$ORIGIN/../${LIB_DIR}") SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) else() set(_USE_RPATH OFF) diff --git a/cmake_support/FindPython.cmake b/cmake_support/FindPython.cmake index 66c62f51cd8fcf5fc26af7f5e3f60dbed35a1713..c3b6f7dfdf3da9f18f05561be504928a52dfe2f3 100644 --- a/cmake_support/FindPython.cmake +++ b/cmake_support/FindPython.cmake @@ -42,7 +42,7 @@ endmacro() macro(_find_python PYTHON_ROOT VERSION) - string(REPLACE "." "" _VERSION_NO_DOTS ${VERSION}) + string(REPLACE "." "" _VERSION_NO_DOTS "${VERSION}") if(PYTHON_ROOT) find_library(PYTHON_LIBRARIES NAMES "python${_VERSION_NO_DOTS}" "python${VERSION}" @@ -69,17 +69,17 @@ macro(_find_python PYTHON_ROOT VERSION) endmacro() macro(_find_python_bin PYTHON_ROOT VERSION) - string(REPLACE "." "" _VERSION_NO_DOTS ${VERSION}) + string(REPLACE "." "" _VERSION_NO_DOTS "${VERSION}") if(PYTHON_ROOT) find_program(PYTHON_BINARY - NAMES "python" "python${_VERSION_NO_DOTS}" "python${VERSION}" + NAMES "python${_VERSION_NO_DOTS}" "python${VERSION}" HINTS "${PYTHON_ROOT}" PATH_SUFFIXES bin NO_SYSTEM_ENVIRONMENT_PATH NO_DEFAULT_PATH ) else() find_program(PYTHON_BINARY - NAMES "python" "python${_VERSION_NO_DOTS}" "python${VERSION}" + NAMES "python${_VERSION_NO_DOTS}" "python${VERSION}" HINTS "${CMAKE_PREFIX_PATH}" PATH_SUFFIXES bin ) @@ -105,6 +105,10 @@ macro(check_for_python_lib) endif() endforeach() endif() + # fallback to non-versioned naming scheme + if (NOT $PYTHON_LIBRARIES) + _find_python("${PYTHON_ROOT}" "") + endif() endmacro() macro(check_for_python_binary) @@ -114,13 +118,19 @@ macro(check_for_python_binary) foreach(_VERSION ${PYTHON_VERSIONS}) if(${PYTHON_MIN_VERSION} VERSION_LESS ${_VERSION}) _find_python_bin("${PYTHON_ROOT}" "${_VERSION}") - if(PYTHON_LIBRARIES) + if(PYTHON_BINARY) set(PYTHON_VERSION "${_VERSION}") + # disallow all versions except for the one we just found. This makes + # sure we don't mismatch the python binary and the libraries. + set(PYTHON_VERSIONS "${_VERSION}") break() endif() endif() endforeach() endif() + if (NOT PYTHON_BINARY) + _find_python("${PYTHON_ROOT}" "") + endif() endmacro() if(NOT PYTHON_ROOT) @@ -134,11 +144,13 @@ if(APPLE AND NOT PYTHON_IGNORE_FRAMEWORKS) check_for_python_framework() endif() +# first check for python binary. +check_for_python_binary() + if(NOT PYTHON_FRAMEWORK_FOUND) check_for_python_lib() endif() -check_for_python_binary() mark_as_advanced( PYTHON_LIBRARIES PYTHON_INCLUDE_PATH @@ -159,6 +171,8 @@ if(PYTHON_LIBRARIES) endif() if (PYTHON_BINARY) + set(PYTHON_VERSION "${PYTHON_VERSION}" + CACHE STRING "Python Version" FORCE) set(PYTHON_BINARY "${PYTHON_BINARY}" CACHE FILEPATH "Python Binary" FORCE) endif() diff --git a/deployment/linux/create_bundle_lucid.py b/deployment/linux/create_bundle_lucid.py index 21a1dfcbb63c21c624740fff13c34c23b9b8b842..aec419bd5d17043c6a273044ad14e20abacec3f7 100644 --- a/deployment/linux/create_bundle_lucid.py +++ b/deployment/linux/create_bundle_lucid.py @@ -73,7 +73,7 @@ subprocess.call('sed "s/\#export PYTHONHOME/ export PYTHONHOME/g" scripts/ost_co subprocess.call('sed "s/\#export PYTHONPATH/ export PYTHONPATH/g" scripts/ost_config.in.prepre > scripts/ost_config.in.pre',shell=True,cwd='../../') subprocess.call('sed "s/\#export QT_PLUGIN_PATH/ export QT_PLUGIN_PATH/g" scripts/ost_config.in.pre > scripts/ost_config.in',shell=True,cwd='../../') print 'Compiling Openstructure' -subprocess.call('cmake ./ -DCMAKE_BUILD_TYPE=Release -DPREFIX='+directory_name+' -DCOMPOUND_LIB='+chemlib_dictionary_location+' -DENABLE_IMG=ON -DENABLE_GUI=ON -DENABLE_GFX=ON -DOPTIMIZE=ON',shell=True,cwd='../../') +subprocess.call('cmake ./ -DCMAKE_BUILD_TYPE=Release -DPREFIX='+directory_name+' -DCOMPOUND_LIB='+chemlib_dictionary_location+' -DENABLE_IMG=ON -DUSE_RPATH=ON -DENABLE_GUI=ON -DENABLE_GFX=ON -DOPTIMIZE=ON',shell=True,cwd='../../') subprocess.call('make -j2',shell=True,cwd='../../') print 'Removing obsolete packages and package directory' subprocess.call('rm -fr openstructure-linux*',shell=True,cwd='../../') @@ -87,6 +87,8 @@ subprocess.call('cp -pRL '+system_python_libs+' stage/'+libdir+'/',shell=True,cw subprocess.call('rm -fr stage/'+libdir+'/'+system_python_executable+'/dist-packages',shell=True,cwd='../../') subprocess.call('cp -pRL '+sip_module_location+'/sip* stage/'+libdir+'/'+system_python_executable+'/',shell=True,cwd='../../') subprocess.call('cp -pRL '+qt4_module_location+' stage/'+libdir+'/'+system_python_executable+'/',shell=True,cwd='../../') +print 'Copy boost program option libraries into the stage for dependency detection' +subprocess.call('cp -pRL /usr/lib/libboost_program_options.so* stage/'+libdir+'/',shell=True,cwd='../../') print 'Creating new dependency list' so_list=[] walk_list=os.walk('../../stage') @@ -138,6 +140,7 @@ subprocess.call('ln -sf bin/lddt ./lddt',shell=True,cwd='../../'+directory_name) print 'Copying additional libraries in the package directory structure' subprocess.call('cp '+ssl_crypto_location+'/libssl.so* '+directory_name+'/'+libdir,shell=True,cwd='../../') subprocess.call('cp '+ssl_crypto_location+'/libcrypto.so* '+directory_name+'/'+libdir,shell=True,cwd='../../') +subprocess.call('cp -pRL /usr/lib/libboost_program_options.so* '+directory_name+'/'+libdir+'/',shell=True,cwd='../../') print 'Copying python headers in the package directory structure' subprocess.call('mkdir -p '+directory_name+'/local/include/',shell=True,cwd='../../') subprocess.call('cp -r /usr/include/'+system_python_executable+' '+directory_name+'/local/include/',shell=True,cwd='../../') diff --git a/deployment/linux/create_bundle_precise.py b/deployment/linux/create_bundle_precise.py index b59409ffffc7d099c31f7d8437eae8a72e49e50a..9ffeff82463112f79e857ecc8f7bf202deef91da 100644 --- a/deployment/linux/create_bundle_precise.py +++ b/deployment/linux/create_bundle_precise.py @@ -73,7 +73,7 @@ subprocess.call('sed "s/\#export PYTHONHOME/ export PYTHONHOME/g" scripts/ost_co subprocess.call('sed "s/\#export PYTHONPATH/ export PYTHONPATH/g" scripts/ost_config.in.prepre > scripts/ost_config.in.pre',shell=True,cwd='../../') subprocess.call('sed "s/\#export QT_PLUGIN_PATH/ export QT_PLUGIN_PATH/g" scripts/ost_config.in.pre > scripts/ost_config.in',shell=True,cwd='../../') print 'Compiling Openstructure' -subprocess.call('cmake ./ -DCMAKE_BUILD_TYPE=Release -DPREFIX='+directory_name+' -DCOMPOUND_LIB='+chemlib_dictionary_location+' -DENABLE_IMG=ON -DENABLE_GUI=ON -DENABLE_GFX=ON -DOPTIMIZE=ON',shell=True,cwd='../../') +subprocess.call('cmake ./ -DCMAKE_BUILD_TYPE=Release -DPREFIX='+directory_name+' -DCOMPOUND_LIB='+chemlib_dictionary_location+' -DUSE_RPATH=ON -DENABLE_IMG=ON -DENABLE_GUI=ON -DENABLE_GFX=ON -DOPTIMIZE=ON',shell=True,cwd='../../') subprocess.call('make -j2',shell=True,cwd='../../') print 'Removing obsolete packages and package directory' subprocess.call('rm -fr openstructure-linux*',shell=True,cwd='../../') @@ -87,6 +87,8 @@ subprocess.call('cp -pRL '+system_python_libs+' stage/'+libdir+'/',shell=True,cw subprocess.call('rm -fr stage/'+libdir+'/'+system_python_executable+'/dist-packages',shell=True,cwd='../../') subprocess.call('cp -pRL '+sip_module_location+'/sip* stage/'+libdir+'/'+system_python_executable+'/',shell=True,cwd='../../') subprocess.call('cp -pRL '+qt4_module_location+' stage/'+libdir+'/'+system_python_executable+'/',shell=True,cwd='../../') +print 'Copy boost program option libraries into the stage for dependency detection' +subprocess.call('cp -pRL /usr/lib/libboost_program_options.so* stage/'+libdir+'/',shell=True,cwd='../../') print 'Creating new dependency list' so_list=[] walk_list=os.walk('../../stage') @@ -138,6 +140,7 @@ subprocess.call('ln -sf bin/lddt ./lddt',shell=True,cwd='../../'+directory_name) print 'Copying additional libraries in the package directory structure' subprocess.call('cp '+ssl_crypto_location+'/libssl.so* '+directory_name+'/'+libdir,shell=True,cwd='../../') subprocess.call('cp '+ssl_crypto_location+'/libcrypto.so* '+directory_name+'/'+libdir,shell=True,cwd='../../') +subprocess.call('cp -pRL /usr/lib/libboost_program_options.so* '+directory_name+'/'+libdir+'/',shell=True,cwd='../../') print 'Copying python headers in the package directory structure' subprocess.call('mkdir -p '+directory_name+'/local/include/',shell=True,cwd='../../') subprocess.call('cp -r /usr/include/'+system_python_executable+' '+directory_name+'/local/include/',shell=True,cwd='../../') diff --git a/deployment/macos/deploy.py b/deployment/macos/deploy.py index de10ec84cfcce14a8a158f15338b7366caad9a05..611cad64698dd8b3730a63585abb7300c77279c2 100644 --- a/deployment/macos/deploy.py +++ b/deployment/macos/deploy.py @@ -29,6 +29,7 @@ if opts.bundle: shutil.copytree('../../examples', 'DNG.app/Contents/examples') os.system('rm `find DNG.app/Contents/examples/ -name "*.pyc"` 2> /dev/null') os.system('rm -rf DNG.app/Contents/examples/code_fragments/') + os.system('rm -rf DNG.app/Contents/examples/gfx/') if opts.dmg: os.system('rm -rf openstructure-%s.dmg' % ost.VERSION) os.system('hdiutil create -srcFolder DNG.app openstructure-%s.dmg' % ost.VERSION) diff --git a/deployment/macos/deps.py b/deployment/macos/deps.py index 65474472153ea460b9e91860b58af7bf7277dbb4..2693db881eac8a5c648019ae79d56c46846aa43a 100644 --- a/deployment/macos/deps.py +++ b/deployment/macos/deps.py @@ -71,7 +71,7 @@ def collect_deps(stage_dir, components, binaries, libexec_binaries, LIBEXEC_SCRIPTS=['ost_config'] LIBEXEC_BINARIES=[] GUI_LIBEXEC_BINARIES=['gosty'] -BINARIES=['ldt', 'chemdict_tool', 'tmalign', 'tmscore'] +BINARIES=['lddt', 'chemdict_tool', 'tmalign', 'tmscore'] GUI_BINARIES=[] GUI_COMPONENTS=['gfx', 'gui', 'info'] COMPONENTS=['mol', 'geom', 'conop', 'seq_alg', 'seq', diff --git a/modules/bindings/pymod/naccess.py b/modules/bindings/pymod/naccess.py index afb58c4bac3c59190ff4c5a3a1c880dfb1be2455..f9f2e5703e99cf9a12740c89a192ce95119338a3 100644 --- a/modules/bindings/pymod/naccess.py +++ b/modules/bindings/pymod/naccess.py @@ -35,16 +35,22 @@ def _GetExecutable(naccess_exe): # # \param entity EntityHandle or EntityView to calculate surface # \param selection Calculate surface for subset of entity +# \param scratch_dir Directory for temporary files (NACCESS is sensitive to "." in directory names +# \param max_number_of_atoms Max Number of atoms in the entity (i.e. is limited in the default NACCESS version to 50 000) # \return array containing temporary directory, input filename for naccess and directory of the input file # \exception RuntimeError if selection is not valid -def _SetupFiles(entity, selection): +def _SetupFiles(entity, selection, scratch_dir, max_number_of_atoms): # create temporary directory - tmp_dir_name=tempfile.mkdtemp() + tmp_dir_name="" + if scratch_dir!=None: + tmp_dir_name=tempfile.mkdtemp(dir=scratch_dir) + else: + tmp_dir_name=tempfile.mkdtemp() # select only heavy atoms if no_hydrogens is true entity_view=entity.Select(selection) - if len(entity_view.atoms) > 50000: - raise RuntimeError, "Too much atoms for NACCESS (> 50 000)" + if len(entity_view.atoms) > max_number_of_atoms: + raise RuntimeError, "Too much atoms for NACCESS (> %s)" % max_number_of_atoms if not entity_view.IsValid(): raise RuntimeError, "Could not create view for selection (%s)"%(selection) @@ -184,11 +190,14 @@ def _RunNACCESS(command, temp_dir): # \param asa_abs Attaches per residue absolute SASA to specified FloatProp on residue level # \param asa_rel Attaches per residue relative SASA to specified FloatProp on residue level # \param asa_atom Attaches per atom SASA to specified FloatProp at atom level +# \param scratch_dir Directory for temporary files (NACCESS is sensitive to "." in directory names +# \param max_number_of_atoms Max Number of atoms in the entity (i.e. is limited in the default NACCESS version to 50 000) + # \return absolute SASA calculated using asa_atom def CalculateSurfaceArea(entity, radius=1.4, include_hydrogens=False, include_hetatm = False, include_water = False, selection="", - naccess_exe=None, keep_files=False , asa_abs= "asaAbs", asa_rel="asaRel", asa_atom="asaAtom"): + naccess_exe=None, keep_files=False , asa_abs= "asaAbs", asa_rel="asaRel", asa_atom="asaAtom", scratch_dir = None, max_number_of_atoms=50000): import re # check if msms executable is specified @@ -196,7 +205,7 @@ def CalculateSurfaceArea(entity, radius=1.4, # parse selection # setup files for msms - (naccess_data_dir, naccess_data_file,naccess_data_base )=_SetupFiles(entity, selection) + (naccess_data_dir, naccess_data_file,naccess_data_base )=_SetupFiles(entity, selection, scratch_dir) # set command line command="%s %s -p %f " % \ diff --git a/modules/doc/install.rst b/modules/doc/install.rst index 31dde6035c90c854871f957cbb54ed47b4c4beea..b92727bed28fe9e9885ac5f940f8b92ab3a768b5 100644 --- a/modules/doc/install.rst +++ b/modules/doc/install.rst @@ -48,7 +48,7 @@ If you would like to use the graphical user interface, also install: * `PyQt4 <http://www.riverbankcomputing.co.uk/software/pyqt/download>`_. In case you are compiling under Windows you have to install `Visualstudio -2008 <http://www.microsoft.com/express/Downloads>`_. to compile the dependecies +2008 <http://www.microsoft.com/express/Downloads>`_. to compile the dependencies and OpenStructure. We recommend to compile the dependecies manually. Enter the directories where the dependencies are located in Tools->Options->Projects and Solutions->VC++ directories. Choose 'bin' directories to enter program paths to @@ -68,11 +68,11 @@ OpenStructure uses `git` as the revision control system. The main repository can git clone https://dng.biozentrum.unibas.ch/git/ost.git <directory-name> -The above command will clone OpenStructre into the directory called `directory-name`. If omitted, the directory will be called ost. Alternatively, you might consider getting one of the nightly source code snapshots from the `downloads section <http://www.openstructure.org/download/>`_. +The above command will clone OpenStructure into the directory called `directory-name`. If omitted, the directory will be called ost. .. note:: - Some version of curl have have trouble with the certificate of the + Some versions of curl have have trouble with the certificate of the OpenStructure git server and fail to clone the repository. To work around this, disable the SSL certificate verification with the following command: @@ -103,14 +103,14 @@ OpenStructure uses `CMake <http://cmake.org>`_ for compiling and building the pr There are two kinds of options: Options that let you control the building behaviour, enabling and disabling the compilation of certain modules and options that let you tell CMake where to find the dependencies. All of them are passed to CMake with via `-D<opt>=<value>`. -On Windows, use Tools -> VisualStudio commandline prompt from within VisualStudio) +On Windows, use Tools -> VisualStudio -> commandline prompt from within VisualStudio Flag to choose build generator ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -CMake supports different build generators. On UNIX, that is MacOS X and Linux, the default build generator is Makefiles, but it is also possible to use other programs. For a list of supported build generators on your platform, start cmake without parameters. +CMake supports different build generators. On UNIX, i.e. MacOS X and Linux, the default build generator is Makefiles, but it is also possible to use other programs. For a list of supported build generators on your platform, start cmake without parameters. -On Windows you have to explicitly set the buil generator to "Visual Studio 9 2008": +On Windows you have to explicitly set the build generator to "Visual Studio 9 2008"(or a later version): .. code-block:: bash @@ -133,12 +133,28 @@ By default, `CMake <http://cmake.org>`_ searches the standard directories for de * `SYS_ROOT` controls the general prefix for searching libraries and headers. By default, it is set to `/`. + + * `COMPOUND_LIB` specifies the location of the compound library and + activates the rule-based-builder. The compound library is based on + the component dictionary released by the PDB, and it specifies atoms + of a certain residue or connectivities between atoms etc. The + :doc:`conop/compoundlib` compound library itself is created from the + component dictionary by calling the OpenStructure chemdict_tool. + By default this is switched off. + + * `COMPILE_TMTOOLS` will activate bindings for TMAlign and TMScore, which are + then available at python level. This option requires a Fortran compiler. + By default this option is switched off. + + * `USE_NUMPY` allows OpenStructure to pass back data in NumPy format. By + default this is switched off. Build Options ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - * `ENABLE_UI` controls whether to build the graphical user interface module. By + * `ENABLE_GUI` controls whether to build the graphical user interface module. By default it is set to true. + * `ENABLE_IMG` controls whether to build the image processing module. This will enable support for density maps, and general image processing in 1, 2 an 3 dimensions. By default it is set to true. @@ -151,6 +167,17 @@ Build Options * If `OPTIMIZE` is set to 1, an optimized version of OpenStructure is built. + * `PREFIX` specifies the location on the file system where to install + OpenStructure + + * `USE_DOUBLE_PRECISION` will switch on double precision within OpenStructure. + By default this is switched off. + + * `ENABLE_STATIC` allows some parts of OpenStructure to be statically linked + and thus can be used more easily across a heterogeneous setup, e.g. older + systems and newer systems. + + Example Configurations ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -209,3 +236,4 @@ To get the newest changes from the central git repository, enter git pull in your terminal. This will fetch the newest changes. + diff --git a/modules/gui/pymod/dng/termuse.py b/modules/gui/pymod/dng/termuse.py index 8f90c4c47f785f571771bc9a5e09c913f87b71e0..a1fed90ddf2c9fdbc7bc74c2e172ebd9edcc43c8 100644 --- a/modules/gui/pymod/dng/termuse.py +++ b/modules/gui/pymod/dng/termuse.py @@ -45,7 +45,7 @@ class TerminalUsageDialog(QDialog): return str(self.path_combo.currentText()) def _CreateLinks(bin_dir, sel_dir): - for bin in ('ost', 'dng',): + for bin in ('ost', 'dng','lddt', 'chemdict_tool'): if os.path.exists(os.path.join(sel_dir, bin)): os.unlink(os.path.join(sel_dir, bin)) os.system('ln -s "%s" "%s"' % (os.path.join(bin_dir, bin), @@ -63,7 +63,7 @@ def InstallTerminalPrograms(): if not os.access(sel_path, os.W_OK): admin_rights=AdminRights() if admin_rights.Acquire(): - for bin in ('ost', 'dng'): + for bin in ('ost', 'dng', 'lddt', 'chemdict_tool'): admin_rights.CreateLink(os.path.join(bin_dir, bin), os.path.join(sel_path, bin)) admin_rights.Release() diff --git a/modules/gui/src/file_browser.cc b/modules/gui/src/file_browser.cc index a6bf49fb31a33d77c318191e046347b4df3436ec..a41ff0a293f864c6a43f67382d5acf4236dedeb2 100644 --- a/modules/gui/src/file_browser.cc +++ b/modules/gui/src/file_browser.cc @@ -81,6 +81,7 @@ FileBrowser::FileBrowser(QWidget* parent): if (QDir(example_path).exists()) { path=example_path; } else{ + dir.cdUp(); dir.cdUp(); example_path=dir.path()+"/examples"; if (QDir(example_path).exists()) { diff --git a/modules/io/doc/mmcif.rst b/modules/io/doc/mmcif.rst index 7e1c330a4dc4f0efd72e8eb424ef43539c4d4352..855ed0ea208cfd8cd77ef537edd736144f6260ff 100644 --- a/modules/io/doc/mmcif.rst +++ b/modules/io/doc/mmcif.rst @@ -4,7 +4,7 @@ mmCIF File Format The mmCIF file format is an alternate container for structural entities, also provided by the PDB. Here we describe how to load those files and how to deal with information provided above the common PDB format (:class:`MMCifInfo`, -:class:`MMCifInfoCitation`, :class:`MMCifInfoTransOperation`, +:class:`MMCifInfoCitation`, :class:`MMCifInfoTransOp`, :class:`MMCifInfoBioUnit`, :class:`MMCifInfoStructDetails`). @@ -343,7 +343,7 @@ of the annotation available. See :attr:`authors` -.. class:: MMCifInfoTransOperation +.. class:: MMCifInfoTransOp This stores operations needed to transform an :class:`entity <ost.mol.EntityHandle>` into a bio unit. @@ -411,6 +411,14 @@ of the annotation available. This stores information how a structure is to be assembled to form the bio unit. + .. attribute:: id + + The id of a bio unit as given by the original mmCIF file. + + Also available as :meth:`GetID`. May also be modified by :meth:`SetID`. + + :type: :class:`str` + .. attribute:: details Special aspects of the biological assembly. If not provided, resembles an @@ -429,11 +437,19 @@ of the annotation available. .. attribute:: operations Translations and rotations needed to create the bio unit. Filled with - objects of class :class:`MMCifInfoTransOperation`. + objects of class :class:`MMCifInfoTransOp`. Also available as :meth:`GetOperations`. May be modified by :meth:`AddOperations` + .. method:: GetID() + + See :attr:`id` + + .. method:: SetID(id) + + See :attr:`id` + .. method:: GetDetails() See :attr:`details` @@ -682,14 +698,14 @@ of the annotation available. See :attr:`replace_pdb_id` -.. class:: MMCifINfoStructRef +.. class:: MMCifInfoStructRef Holds the information of the struct_ref category. The category describes the link of polymers in the mmCIF file to sequences stored in external databases such as uniprot. The related categories ``struct_ref_seq`` and ``struct_ref_seq_dif`` also list differences between the sequences of the - deposited structure and the sequences in the database. A promintent example of - such differences include point mutations and/or expression tags. + deposited structure and the sequences in the database. Two prominent examples + of such differences are point mutations and/or expression tags. .. attribute:: db_name @@ -734,6 +750,7 @@ of the annotation available. .. attribute:: seq_begin seq_end + The starting point (1-based) and end point of the aligned range in the deposited sequence, respectively. @@ -741,6 +758,7 @@ of the annotation available. .. attribute:: db_begin db_end + The starting point (1-based) and end point of the aligned range in the database sequence, respectively. @@ -769,8 +787,10 @@ of the annotation available. .. attribute:: details A textual description of the difference, e.g. point mutation, - expressiontag, purification artifact. + expression tag, purification artifact. :type: :class:`str` + .. LocalWords: cas isbn pubmed asu seqres conop ConnectAll casp COMPND OBSLTE -.. LocalWords: SPRSDE pdb func +.. LocalWords: SPRSDE pdb func autofunction exptl attr pdbx oper conf spr dif +.. LocalWords: biounits biounit uniprot UNP seqs diff --git a/modules/io/pymod/export_mmcif_io.cc b/modules/io/pymod/export_mmcif_io.cc index 70e6b46590148293e396cd5dc28b9766fdda3ce5..6654393be01fefaefa346b9f86bcdef5f63e9c7e 100644 --- a/modules/io/pymod/export_mmcif_io.cc +++ b/modules/io/pymod/export_mmcif_io.cc @@ -181,12 +181,15 @@ void export_mmcif_io() .def("AddOperations", &MMCifInfoBioUnit::AddOperations) .def("GetOperations", make_function(&MMCifInfoBioUnit::GetOperations, return_value_policy<copy_const_reference>())) + .def("SetID", &MMCifInfoBioUnit::SetID) + .def("GetID", &MMCifInfoBioUnit::GetID) .add_property("details", &MMCifInfoBioUnit::GetDetails, &MMCifInfoBioUnit::SetDetails) .add_property("chains", make_function(&MMCifInfoBioUnit::GetChainList, return_value_policy<copy_const_reference>())) .add_property("operations", make_function(&MMCifInfoBioUnit::GetOperations, return_value_policy<copy_const_reference>())) + .add_property("id", &MMCifInfoBioUnit::GetID, &MMCifInfoBioUnit::SetID) ; class_<MMCifInfoStructRefs>("MMCifInfoStructRefs", init<>()) diff --git a/modules/io/src/mol/mmcif_info.hh b/modules/io/src/mol/mmcif_info.hh index 38e49f58bec9420e353088d8a7858908be887456..b240e5a1c86eedaddd76de2ba71bbe009b590f3d 100644 --- a/modules/io/src/mol/mmcif_info.hh +++ b/modules/io/src/mol/mmcif_info.hh @@ -238,7 +238,16 @@ typedef boost::shared_ptr<MMCifInfoTransOp> MMCifInfoTransOpPtr; class DLLEXPORT_OST_IO MMCifInfoBioUnit { public: /// \brief Create a biounit. - MMCifInfoBioUnit(): details_("") {}; + MMCifInfoBioUnit(): id_(""), details_("") {}; + + /// \brief Set id + /// + /// \param id id + void SetID(String id) { id_ = id; } + /// \brief Get id + /// + /// \return id + String GetID() const { return id_; } /// \brief Set details /// @@ -274,6 +283,9 @@ public: } bool operator==(const MMCifInfoBioUnit& bu) const { + if (this->id_ != bu.id_) { + return false; + } if (this->details_ != bu.details_) { return false; } @@ -314,6 +326,7 @@ public: } private: + String id_; ///< pdbx_struct_assembly.id String details_; ///< pdbx_struct_assembly.details std::vector<String> chains_; ///< chains involved in this assembly std::vector<std::vector<MMCifInfoTransOpPtr> > operations_; diff --git a/modules/io/src/mol/mmcif_reader.cc b/modules/io/src/mol/mmcif_reader.cc index 409902ab4391a66860aeed24d9b9aa3d6a9720a9..2bcdee810c013971aec9f1c9f631320bbfe719b6 100644 --- a/modules/io/src/mol/mmcif_reader.cc +++ b/modules/io/src/mol/mmcif_reader.cc @@ -975,7 +975,7 @@ void MMCifReader::ParsePdbxStructAssemblyGen(const std::vector<StringRef>& colum MMCifBioUAssembly assembly; assembly.biounit = MMCifInfoBioUnit(); - assembly.biounit.SetDetails(columns[indices_[ASSEMBLY_ID]].str()); + assembly.biounit.SetID(columns[indices_[ASSEMBLY_ID]].str()); std::vector<StringRef> tmp_chains=columns[indices_[ASYM_ID_LIST]].split(','); std::vector<StringRef>::const_iterator tc_it; @@ -1586,14 +1586,15 @@ void MMCifReader::OnEndData() bua_it != bu_assemblies_.end(); ++bua_it) { // pair with pdbx_struct_assembly entry - buom_it = bu_origin_map_.find(bua_it->biounit.GetDetails()); + buom_it = bu_origin_map_.find(bua_it->biounit.GetID()); if (buom_it == bu_origin_map_.end()) { throw IOException(this->FormatDiagnostic(STAR_DIAG_ERROR, "No pdbx_struct_assembly.id '"+ - bua_it->biounit.GetDetails() + + bua_it->biounit.GetID() + "' found as requested by pdbx_struct_assembly_gen.")); } bua_it->biounit.SetDetails(buom_it->second); + bua_it->biounit.SetID(buom_it->first); // pair with pdbx_struct_oper_list for (aol_it = bua_it->operations.begin(); diff --git a/modules/io/src/mol/pdb_writer.cc b/modules/io/src/mol/pdb_writer.cc index 3be9390b7d7a3763345364004cbe39853de4579c..d06a5228c5890f593c40c86ac9ceb4617f6ee379 100644 --- a/modules/io/src/mol/pdb_writer.cc +++ b/modules/io/src/mol/pdb_writer.cc @@ -443,7 +443,7 @@ void PDBWriter::Write(const mol::AtomHandleList& atoms) PDBWriter::~PDBWriter() { - out_ << "END "; + out_ << "END " << std::endl; } }} diff --git a/modules/io/tests/test_mmcif_reader.cc b/modules/io/tests/test_mmcif_reader.cc index 953ac31323ea774278d94aead1d66c078df70cc8..b17b22ea8042231aab785d6bf960f3d8146e018b 100644 --- a/modules/io/tests/test_mmcif_reader.cc +++ b/modules/io/tests/test_mmcif_reader.cc @@ -1254,9 +1254,11 @@ BOOST_AUTO_TEST_CASE(mmcif_testreader) BOOST_MESSAGE(" done."); BOOST_MESSAGE(" reading data fields which should not fail..."); + BOOST_MESSAGE(mmcif_p.GetInfo().GetBioUnits().back().GetID()); BOOST_CHECK(mmcif_p.GetInfo().GetMethod().str() == "Deep-fry"); BOOST_CHECK(mmcif_p.GetInfo().GetBioUnits().back().GetDetails() == "author_defined_assembly"); + BOOST_CHECK(mmcif_p.GetInfo().GetBioUnits().back().GetID() == "2"); BOOST_CHECK(mmcif_p.GetInfo().GetBioUnits().back().GetChainList().back() == "F"); MMCifInfoBioUnit bu = mmcif_p.GetInfo().GetBioUnits().back(); diff --git a/modules/mol/alg/doc/molalg.rst b/modules/mol/alg/doc/molalg.rst index 29f3750b70d3d1aedd50bfc4f23790d2ed3c8cc1..9455d58dee59c029ea8d37e3d82804f63b625021 100644 --- a/modules/mol/alg/doc/molalg.rst +++ b/modules/mol/alg/doc/molalg.rst @@ -89,12 +89,17 @@ :returns: the Local Distance Difference Test score -.. function:: LDTHA(model, distance_list, sequence_separation=0); +.. function:: LDDTHA(model, distance_list, sequence_separation=0); This function calculates the Local Distance Difference Test - High Accuracy score (see previous functions). The High Accuracy name comes from the fact that the tolerance levels used by this function are the same as the thresholds used by GDT-HA (0.5, 1, 2, and 4 Angstrom). + The function only compares the input distance list to the first chain of the model structure + + The local Local Distance Difference Test score values are stored in the ResidueHandles of the model passed to the + function in a float property called "locallddt" + A sequence separation parameter can be passed to the function. If this happens, only distances between residues whose separation is higher than the provided parameter are considered when computing the score @@ -209,6 +214,9 @@ The following function detects steric clashes in atomic structures. Two atoms ar the sidechain, only the sidechain atoms are removed. This behavior is changed by the always_remove_bb flag: when the flag is set to True the whole residue is removed even if a clash is just detected in the side-chain. + + The function performs the filtering directly on the the entity which is passed as an argument. The entity + gets altered by the function. Two atoms are defined as clashing if their distance is shorter than the reference distance minus a tolerance threshold. The information about the clashing distances and the tolerance thresholds for all possible pairs of @@ -231,6 +239,9 @@ The following function detects steric clashes in atomic structures. Two atoms ar part of the sidechain, only the sidechain is removed. This behavior is changed by the always_remove_bb flag: when the flag is set to True the whole residue is removed even if a violation is just detected in the side-chain + + The function performs the filtering directly on the the entity which is passed as an argument. The entity + gets altered by the function. A violation is defined as a bond length that lies outside of the range: [mean_length-std_dev*bond_tolerance <-> meanlength+std_dev*bond_tolerance] or an angle width lying outside of the range [mean_width-std_dev*angle_tolerance <-> mean_width+std_dev*angle_tolerance ]. The information about the mean lengths and widths and the corresponding standard deviations is passed to the function using two parameters. diff --git a/modules/mol/alg/pymod/wrap_mol_alg.cc b/modules/mol/alg/pymod/wrap_mol_alg.cc index 770bcf423094b4f77e179f5cea9a652cc8e518fd..72a67e4d09299d1e0ce88c0d839e2fe1b599492a 100644 --- a/modules/mol/alg/pymod/wrap_mol_alg.cc +++ b/modules/mol/alg/pymod/wrap_mol_alg.cc @@ -96,6 +96,7 @@ BOOST_PYTHON_MODULE(_ost_mol_alg) export_svdSuperPose(); export_TrajectoryAnalysis(); export_StructureAnalysis(); + export_Clash(); #if OST_IMG_ENABLED export_entity_to_density(); #endif diff --git a/modules/mol/alg/src/lddt.cc b/modules/mol/alg/src/lddt.cc index f619bd52f651824e191c3404e7091b9290149055..2142989048973aaec76da73470c078e69e212c16 100644 --- a/modules/mol/alg/src/lddt.cc +++ b/modules/mol/alg/src/lddt.cc @@ -109,8 +109,8 @@ int main (int argc, char **argv) { // sets some default values for parameters String version = "1.2"; - Real bond_tolerance = 8.0; - Real angle_tolerance = 8.0; + Real bond_tolerance = 15.0; + Real angle_tolerance = 15.0; Real radius=15.0; int sequence_separation = 0; @@ -325,10 +325,22 @@ int main (int argc, char **argv) exit(-1); } // performs structural checks and filters the structure - v=alg::CheckStereoChemistry(v,bond_table,angle_table,bond_tolerance,angle_tolerance); + try { + v=alg::CheckStereoChemistry(v,bond_table,angle_table,bond_tolerance,angle_tolerance); + } catch (std::exception& e) { + std::cout << "An error occurred during the structure quality checks, stage 1:" << std::endl; + std::cout << e.what() << std::endl; + exit(-1); + } cov = compute_coverage(v,glob_dist_list); std::cout << "Coverage after stereo-chemical checks: " << (float(cov.first)/float(cov.second)) << " (" << cov.first << " out of " << cov.second << " residues)" << std::endl; - v=alg::FilterClashes(v,nonbonded_table); + try { + v=alg::FilterClashes(v,nonbonded_table); + } catch (std::exception& e) { + std::cout << "An error occurred during the structure quality checks, stage 2:" << std::endl; + std::cout << e.what() << std::endl; + exit(-1); + } cov = compute_coverage(v,glob_dist_list); std::cout << "Coverage after clashing checks: " << (float(cov.first)/float(cov.second)) << " (" << cov.first << " out of " << cov.second << " residues)" << std::endl; } diff --git a/modules/seq/base/doc/seq.rst b/modules/seq/base/doc/seq.rst index 99f4c6b737c015ccfec384d030ce203e45b156ac..042f1d09c9811d0b7f42650576ec604cfa9d8fce 100644 --- a/modules/seq/base/doc/seq.rst +++ b/modules/seq/base/doc/seq.rst @@ -388,3 +388,47 @@ an alignment: :raises: In case one of the two sequences doesn't have an attached view, a :exc:`RuntimeError` is raised. + + .. method:: AddSequence(sequence) + + Append a sequence to the alignment. The sequence must have the same length as + sequences already present in the alignment. + + :raises: :exc:`RuntimeError` if the sequence length does not match + :param sequence: Sequence to be added + :type sequence: :class:`ConstSequenceHandle` + + .. method:: GetSequenceOffset(index) + SetSequenceOffset(index, offset) + + Get/set the offset for sequence at *index*. + + :param index: The index of the sequence + :type index: :class:`int` + :param offset: The new offset + :type offset: :class:`int` + :rtype: :class:`int` + + .. method:: GetSequenceRole(index) + SetSequenceRole(index, role) + + Get/Set the sequence role for sequence at *index*. + + :param index: The index of the sequence + :type index: :class:`int` + :param role: The new role + :type role: :class:`str` + :rtype: :class:`str` + + .. method:: GetCoverage(index) + + Get coverage of sequence at *index* to the first sequence. + + :param index: The index of the sequence + :type index: :class:`int` + :returns: Coverage as a number between 0 and 1. + + .. method:: RemoveSequence(index) + + Remove sequence at *index* from the alignment. +