diff --git a/.gitignore b/.gitignore index 56410cfa551dd48078e87a6a355fa7eadf1823ab..05c992e3f9ddc3fb38323fbdc356c996822989a0 100644 --- a/.gitignore +++ b/.gitignore @@ -24,6 +24,8 @@ pov_*test.inc *-out.pdb *-out.sdf *-out.crd +*-out.pqr +*-out.png CMakeLists.txt.user OpenStructure.cbp DartConfiguration.tcl @@ -53,4 +55,8 @@ Debug /deployment/win/create_archive.bat /install_manifest.txt *_out.csv +*_out.tab +*_out.pickle /modules/io/tests/temp_img.tmp +PYTEST-*.xml +ost_*_tests_log.xml diff --git a/CMakeLists.txt b/CMakeLists.txt index da42bdb5f5cd2ea93ada1a91137b0685b6220a18..e65ba23237b81453d88e1b85698992d6ca26588f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,9 +12,18 @@ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${PROJECT_SOURCE_DIR}/cmake_support) include(OST) +if (CMAKE_COMPILER_IS_GNUCXX) + exec_program(gcc ARGS --version OUTPUT_VARIABLE CMAKE_C_COMPILER_VERSION) + if(CMAKE_C_COMPILER_VERSION MATCHES ".*4\\.[5-9].*") + set(OST_GCC_45 true) + else() + set(OST_GCC_45 false) + endif() +endif() + option(USE_SHADER "whether to compile with shader support" OFF) -option(SET_RPATH "embed rpath upon make install" +option(USE_RPATH "embed rpath upon make install" OFF) option(COMPILE_TMTOOLS "whether to compile the tmalign and tmscore programs" OFF) @@ -26,6 +35,8 @@ option(ENABLE_GFX "whether graphics support should be enabled" ON) option(ENABLE_IMG "whether the image processing module should be compiled" ON) +option(ENABLE_INFO "whether openstructure should be compiled with support for the info library" + ON) option(USE_NUMPY "whether numpy support is added" OFF) option(USE_DOUBLE_PRECISION "whether to compile in double precision" @@ -51,6 +62,7 @@ if (FORTRAN_COMPILER) endif() + if (PREFIX) set(CMAKE_INSTALL_PREFIX ${PREFIX}) endif() @@ -74,10 +86,20 @@ else() set(_DOUBLE_PREC OFF) endif() +if (NOT ENABLE_INFO) + set(ENABLE_GFX OFF) +endif() + if (NOT ENABLE_GFX) set(ENABLE_GUI OFF) endif() +if (ENABLE_INFO) + set(_INFO ON) +else() + set(_INFO OFF) +endif() + if (ENABLE_GUI) set(_UI ON) else() @@ -154,11 +176,26 @@ setup_compiler_flags() set(CMAKE_LIBRARY_OUTPUT_DIRECTORY) +if (ENABLE_STATIC AND UNIX AND NOT APPLE) + set (CMAKE_FIND_LIBRARY_SUFFIXES .a) +endif() + setup_boost() - -find_package(Qt4 4.5.0 REQUIRED) -find_package(OpenGL REQUIRED) -find_package(PNG REQUIRED) + +if (ENABLE_INFO) + find_package(Qt4 4.5.0 REQUIRED) +endif() + +if (ENABLE_GFX) + find_package(OpenGL REQUIRED) +endif() + +if (ENABLE_IMG OR ENABLE_GFX) + find_package(PNG REQUIRED) +else() + set (PNG_LIBRARY "") +endif() + find_package(Eigen 2.0.0 REQUIRED) find_package(Python 2.4 REQUIRED) @@ -177,10 +214,15 @@ if (ENABLE_STATIC) set(Boost_USE_STATIC_LIBS ON) find_package(Boost ${_BOOST_MIN_VERSION} COMPONENTS filesystem system iostreams regex REQUIRED) - message(${Boost_LIBRARIES}) find_package(ZLIB REQUIRED) - set(STATIC_LIBRARIES ${Boost_LIBRARIES} ${FFTW_LIBRARIES} ${TIFF_LIBRARIES} - ${PNG_LIBRARIES} ${ZLIB_LIBRARIES}) + + if (UNIX AND NOT APPLE) + set(STATIC_LIBRARIES ${Boost_LIBRARIES} ${FFTW_LIBRARIES} ${TIFF_LIBRARIES} + ${PNG_LIBRARY} ${ZLIB_LIBRARY}) + else () + set(STATIC_LIBRARIES ${Boost_LIBRARIES} ${FFTW_LIBRARIES} ${TIFF_LIBRARIES} + ${PNG_LIBRARY} ${ZLIB_LIBRARY}) + endif() endif() if (ENABLE_GUI) @@ -218,13 +260,19 @@ if (UNIX) endif() endif() +if (ENABLE_STATIC) + SET(CMAKE_SKIP_BUILD_RPATH TRUE) + SET(LINK_SEARCH_END_STATIC TRUE) +endif() add_subdirectory(modules) add_subdirectory(scripts) add_subdirectory(deployment) -set(FILES_TO_BE_REMOVED CMakeFiles stage tests) + +set(FILES_TO_BE_REMOVED ${CMAKE_SOURCE_DIR}/stage tests) set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES - "${FILES_TO_BE_REMOVED}") + "${FILES_TO_BE_REMOVED}") + #ost_match_boost_python_version(${PYTHON_LIBRARIES}) @@ -232,6 +280,7 @@ message(STATUS "OpenStructure will be built with the following options:\n" " Install Prefix (-DPREFIX) : ${CMAKE_INSTALL_PREFIX}\n" " RPath in install (-DUSE_RPATH) : ${_USE_RPATH}\n" + " Info support (-DENABLE_INFO) : ${_INFO}\n" " Graphical interface (-DENABLE_GUI) : ${_UI}\n" " OpenGL support (-DENABLE_GFX) : ${_OPENGL}\n" " Image Processing support (-DENABLE_IMG) : ${_IMG}\n" @@ -243,4 +292,5 @@ message(STATUS " Compound Lib (-DCOMPOUND_LIB) : ${_COMP_LIB}\n" " TMAlign and TMScore (-DCOMPILE_TMTOOLS) : ${_TM_TOOLS}\n" " Static Libraries (-DENABLE_STATIC) : ${ENABLE_STATIC}\n" - " Debian-style 'libexec' (-DDEBIAN_STYLE_LIBEXEC) : ${_DEBIAN_STYLE_LIBEXEC}") \ No newline at end of file + " Debian-style 'libexec' (-DDEBIAN_STYLE_LIBEXEC) : ${_DEBIAN_STYLE_LIBEXEC}" ) + diff --git a/build_configs/buildconfig_arch b/build_configs/buildconfig_arch new file mode 100644 index 0000000000000000000000000000000000000000..b0a6494db8715e33c8f0ae7a2f9cfb63c2f97392 --- /dev/null +++ b/build_configs/buildconfig_arch @@ -0,0 +1 @@ +set(PYTHON_BINARY "/usr/bin/python2" CACHE PATH "") diff --git a/build_configs/buildconfig_arch_static b/build_configs/buildconfig_arch_static new file mode 100644 index 0000000000000000000000000000000000000000..15c3ef31600755c4b217e623492e06b58bb44b5e --- /dev/null +++ b/build_configs/buildconfig_arch_static @@ -0,0 +1,4 @@ +set(PYTHON_BINARY "/usr/bin/python2" CACHE PATH "") +set(ZLIB_LIBRARY "/usr/lib/libz.a" CACHE PATH "") +set(PNG_LIBRARY "/usr/lib/libpng12.a" CACHE PATH "") +set(FFTW_LIBRARIES "/usr/lib/libfftw3f.a" CACHE PATH "") diff --git a/build_configs/buildconfig_bc2_locallibs b/build_configs/buildconfig_bc2_locallibs new file mode 100644 index 0000000000000000000000000000000000000000..fbc7a614754b8fba6a35957ba4d71bbb4061380d --- /dev/null +++ b/build_configs/buildconfig_bc2_locallibs @@ -0,0 +1,11 @@ +set(FFTW_INCLUDE_PATH "/import/bc2/soft/app/FFTW/current/Linux/include/" CACHE PATH "") +set(FFTW_LIBRARIES "/import/bc2/soft/app/FFTW/current/Linux/lib/libfftw3f.so" CACHE PATH "") +set(Boost_COMPILER "-gcc41" CACHE PATH "") +set(PYTHON_ROOT "/import/bc2/soft/app/Python/current/Linux/" CACHE PATH "") +set(EIGEN2_INCLUDE_DIR "/import/bc2/soft/app/eigen/current/Linux/include/eigen2" CACHE PATH "") +set(BOOST_ROOT "/import/bc2/soft/app/boost/current/Linux" CACHE PATH "") +set(QT_QMAKE_EXECUTABLE "/import/bc2/soft/app/Qt/current/Linux/bin/qmake" CACHE PATH "") +set(COMPOUND_LIB "/import/bc2/home/schwede/GROUP/OpenStructure/ChemLib/compounds.chemlib" CACHE PATH "") +set(TIFF_LIBRARY "${OST_LOCAL_LIBS}/lib/libtiff.so" CACHE PATH "") +set(TIFF_INCLUDE_DIR "${OST_LOCAL_LIBS}/include/" CACHE PATH "") +set (CMAKE_BUILD_TYPE "Release" CACHE PATH "") diff --git a/build_configs/buildconfig_bc2_static b/build_configs/buildconfig_bc2_static new file mode 100644 index 0000000000000000000000000000000000000000..c26933d8ce996f93da782e919544f06312d57ff3 --- /dev/null +++ b/build_configs/buildconfig_bc2_static @@ -0,0 +1,11 @@ +set(FFTW_INCLUDE_PATH "/import/bc2/soft/app/FFTW/current/Linux/include/" CACHE PATH "") +set(FFTW_LIBRARIES "/import/bc2/soft/app/FFTW/current/Linux/lib/libfftw3f.a" CACHE PATH "") +set(DL_LIBRARIES "/usr/lib64/libdl.a" CACHE PATH "") +set(PTHREAD_LIBRARIES "/usr/lib64/libpthread.a" CACHE PATH "") +set(ZLIB_LIBRARY "/usr/lib64/libz.a" CACHE PATH "") +set(Boost_COMPILER "-gcc41" CACHE PATH "") +set(PYTHON_ROOT "/import/bc2/soft/app/Python/current/Linux/" CACHE PATH "") +set(EIGEN2_INCLUDE_DIR "/import/bc2/soft/app/eigen/current/Linux/include/eigen2" CACHE PATH "") +set(QT_QMAKE_EXECUTABLE "/import/bc2/soft/app/Qt/current/Linux/bin/qmake" CACHE PATH "") +set(COMPOUND_LIB "/import/bc2/home/schwede/GROUP/OpenStructure/ChemLib/compounds.chemlib" CACHE PATH "") +set (CMAKE_BUILD_TYPE "Release" CACHE PATH "") diff --git a/build_configs/buildconfig_bc2_static_locallibs b/build_configs/buildconfig_bc2_static_locallibs new file mode 100644 index 0000000000000000000000000000000000000000..c4ac3df6f76cfc58b2bfc41e5afcdb6a41edfddf --- /dev/null +++ b/build_configs/buildconfig_bc2_static_locallibs @@ -0,0 +1,13 @@ +set(FFTW_INCLUDE_PATH "/import/bc2/soft/app/FFTW/current/Linux/include/" CACHE PATH "") +set(FFTW_LIBRARIES "/import/bc2/soft/app/FFTW/current/Linux/lib/libfftw3f.a" CACHE PATH "") +set(DL_LIBRARIES "/usr/lib64/libdl.a" CACHE PATH "") +set(PTHREAD_LIBRARIES "/usr/lib64/libpthread.a" CACHE PATH "") +set(ZLIB_LIBRARY "/usr/lib64/libz.a" CACHE PATH "") +set(Boost_COMPILER "-gcc41" CACHE PATH "") +set(PYTHON_ROOT "/import/bc2/soft/app/Python/current/Linux/" CACHE PATH "") +set(EIGEN2_INCLUDE_DIR "/import/bc2/soft/app/eigen/current/Linux/include/eigen2" CACHE PATH "") +set(QT_QMAKE_EXECUTABLE "/import/bc2/soft/app/Qt/current/Linux/bin/qmake" CACHE PATH "") +set(COMPOUND_LIB "/import/bc2/home/schwede/GROUP/OpenStructure/ChemLib/compounds.chemlib" CACHE PATH "") +set(TIFF_LIBRARY "${OST_LOCAL_LIBS}/lib/libtiff.a" CACHE PATH "") +set(TIFF_INCLUDE_DIR "${OST_LOCAL_LIBS}/include/" CACHE PATH "") +set (CMAKE_BUILD_TYPE "Release" CACHE PATH "") diff --git a/cmake_support/FindBoost.cmake b/cmake_support/FindBoost.cmake index e5cc004e34fa69b3be7fcb72cb741cefd6e145f8..47019edeb51ac0d09aecbe6859e1bc34d3253f9b 100644 --- a/cmake_support/FindBoost.cmake +++ b/cmake_support/FindBoost.cmake @@ -649,7 +649,6 @@ ${BOOST_ROOT}/lib ${BOOST_ROOT}/lib/boost-${Boost_MAJOR_VERSION}.${Boost_MINOR_VERSION}.${Boost_SUBMINOR_VERSION} ${BOOST_ROOT}/stage/lib ${_boost_LIBRARIES_SEARCH_DIRS}) -message("boost searchdirs:${_boost_LIBRARIES_SEARCH_DIRS}") ENDIF( BOOST_ROOT ) IF( BOOST_LIBRARYDIR ) diff --git a/cmake_support/OST.cmake b/cmake_support/OST.cmake index 297696f4ce0d1468309feed082bc96c68f0fa302..06457ad71f30651589b40be1b94fe7a710b243e4 100644 --- a/cmake_support/OST.cmake +++ b/cmake_support/OST.cmake @@ -142,7 +142,9 @@ macro(module) "invalid use of module(): a module name must be provided") endif() - + if (ENABLE_STATIC AND _ARG_NO_STATIC) + return() + endif() if (_ARG_HEADER_OUTPUT_DIR) set(_HEADER_OUTPUT_DIR ${_ARG_HEADER_OUTPUT_DIR}) else() @@ -162,6 +164,17 @@ macro(module) # create library #----------------------------------------------------------------------------- file(MAKE_DIRECTORY ${LIB_STAGE_PATH}) + file(MAKE_DIRECTORY ${EXECUTABLE_OUTPUT_PATH}) + file(MAKE_DIRECTORY ${LIBEXEC_STAGE_PATH}) + if (NOT TARGET make_stage_lib_dir) + add_custom_target(make_stage_lib_dir COMMAND ${CMAKE_COMMAND} -E make_directory ${LIB_STAGE_PATH}) + endif() + if (NOT TARGET make_executable_output_dir) + add_custom_target(make_executable_output_dir COMMAND ${CMAKE_COMMAND} -E make_directory ${EXECUTABLE_OUTPUT_PATH}) + endif() + if (NOT TARGET make_libexec_dir) + add_custom_target(make_libexec_dir COMMAND ${CMAKE_COMMAND} -E make_directory ${LIBEXEC_STAGE_PATH}) + endif() if (WIN32) set(_ABS_FILE_PATTERN "^[A-Z]:/") else() @@ -177,14 +190,20 @@ macro(module) list(APPEND _ABS_SOURCE_NAMES "${CMAKE_CURRENT_SOURCE_DIR}/${_SOURCE}") endif() endforeach() - add_library(${_LIB_NAME} SHARED ${_ABS_SOURCE_NAMES}) - + if (ENABLE_STATIC AND NOT _ARG_NO_STATIC) + add_library(${_LIB_NAME} STATIC ${_ABS_SOURCE_NAMES}) + else() + add_library(${_LIB_NAME} SHARED ${_ABS_SOURCE_NAMES}) + endif() set_target_properties(${_LIB_NAME} PROPERTIES OUTPUT_NAME ${_LIB_NAME} PROJECT_LABEL ${_ARG_NAME} EchoString ${_ARG_NAME} MODULE_DEPS "${_ARG_DEPENDS_ON}") get_target_property(_DEFS ${_LIB_NAME} COMPILE_DEFINITIONS) + add_dependencies(${_LIB_NAME} make_stage_lib_dir) + add_dependencies(${_LIB_NAME} make_executable_output_dir) + add_dependencies(${_LIB_NAME} make_libexec_dir) set_target_properties(${_LIB_NAME} PROPERTIES COMPILE_DEFINITIONS OST_MODULE_${_UPPER_LIB_NAME}) set_target_properties(${_LIB_NAME} PROPERTIES @@ -194,25 +213,6 @@ macro(module) LIBRARY_OUTPUT_DIRECTORY ${LIB_STAGE_PATH} ARCHIVE_OUTPUT_DIRECTORY ${LIB_STAGE_PATH} RUNTIME_OUTPUT_DIRECTORY ${LIB_STAGE_PATH}) - if (ENABLE_STATIC AND NOT _ARG_NO_STATIC) - add_library(${_LIB_NAME}_static STATIC ${_ABS_SOURCE_NAMES}) - set_target_properties(${_LIB_NAME}_static - PROPERTIES OUTPUT_NAME ${_LIB_NAME} - PROJECT_LABEL ${_ARG_NAME} - EchoString ${_ARG_NAME} - MODULE_DEPS "${_ARG_DEPENDS_ON}") - get_target_property(_DEFS ${_LIB_NAME}_static COMPILE_DEFINITIONS) - set_target_properties(${_LIB_NAME}_static PROPERTIES - COMPILE_DEFINITIONS OST_MODULE_${_UPPER_LIB_NAME}) - set_target_properties(${_LIB_NAME}_static PROPERTIES - LIBRARY_OUTPUT_DIRECTORY ${LIB_STAGE_PATH} - ARCHIVE_OUTPUT_DIRECTORY ${LIB_STAGE_PATH} - RUNTIME_OUTPUT_DIRECTORY ${LIB_STAGE_PATH}) - foreach(_DEPENDENCY ${_ARG_DEPENDS_ON}) - target_link_libraries(${_LIB_NAME}_static ${_DEPENDENCY}_static) - endforeach() - target_link_libraries(${_LIB_NAME} ${ZLIB_LIBRARIES}) - endif() if (APPLE) set_target_properties(${_LIB_NAME} PROPERTIES LINK_FLAGS "-Wl,-rpath,@@loader_path" @@ -222,7 +222,11 @@ macro(module) #set_target_properties(${_LIB_NAME} PROPERTIES PREFIX "../") install(TARGETS ${_LIB_NAME} ARCHIVE DESTINATION "${LIB_DIR}") else() - install(TARGETS ${_LIB_NAME} LIBRARY DESTINATION "${LIB_DIR}") + if (ENABLE_STATIC) + install(TARGETS ${_LIB_NAME} ARCHIVE DESTINATION "${LIB_DIR}") + else() + install(TARGETS ${_LIB_NAME} LIBRARY DESTINATION "${LIB_DIR}") + endif() endif() if (_ARG_LINK) target_link_libraries(${_LIB_NAME} ${_ARG_LINK}) @@ -230,6 +234,10 @@ macro(module) foreach(_DEPENDENCY ${_ARG_DEPENDS_ON}) target_link_libraries(${_LIB_NAME} ${_DEPENDENCY}) endforeach() + if (ENABLE_STATIC) + target_link_libraries(${_LIB_NAME} ${STATIC_LIBRARIES}) + endif() + else() add_custom_target("${_LIB_NAME}" ALL) set_target_properties("${_LIB_NAME}" PROPERTIES HEADER_ONLY 1 @@ -302,13 +310,23 @@ macro(executable) if (_ARG_LINK) target_link_libraries(${_ARG_NAME} ${_ARG_LINK}) endif() + foreach(_DEP ${_ARG_DEPENDS_ON}) + target_link_libraries(${_ARG_NAME} ${_DEP}) + endforeach() if (ENABLE_STATIC AND _ARG_STATIC) - set(TARGET_SUFFIX _static) target_link_libraries(${_ARG_NAME} ${STATIC_LIBRARIES}) + if (UNIX AND NOT APPLE) + if (OST_GCC_45) + set_target_properties(${_ARG_NAME} + PROPERTIES LINK_SEARCH_END_STATIC TRUE + LINK_FLAGS "-static-libgcc -static-libstdc++ -static -pthread") + else() + set_target_properties(${_ARG_NAME} + PROPERTIES LINK_SEARCH_END_STATIC TRUE + LINK_FLAGS "-static-libgcc -static -pthread") + endif() + endif() endif() - foreach(_DEP ${_ARG_DEPENDS_ON}) - target_link_libraries(${_ARG_NAME} ${_DEP}${TARGET_SUFFIX}) - endforeach() install(TARGETS ${_ARG_NAME} DESTINATION bin) endmacro() @@ -338,11 +356,13 @@ macro(executable_libexec) target_link_libraries(${_ARG_NAME} ${_ARG_LINK}) endif() if (ENABLE_STATIC AND _ARG_STATIC) - set(TARGET_SUFFIX _static) target_link_libraries(${_ARG_NAME} ${STATIC_LIBRARIES}) + set_target_properties(${_ARG_NAME} + PROPERTIES LINK_SEARCH_END_STATIC TRUE) + endif() foreach(_DEP ${_ARG_DEPENDS_ON}) - target_link_libraries(${_ARG_NAME} ${_DEP}${TARGET_SUFFIX}) + target_link_libraries(${_ARG_NAME} ${_DEP}) endforeach() install(TARGETS ${_ARG_NAME} DESTINATION ${LIBEXEC_PATH}) endmacro() @@ -472,6 +492,9 @@ macro(pymod) if (NOT _ARG_NAME) message(FATAL_ERROR "invalid use of pymod(): a name must be provided") endif() + if (ENABLE_STATIC) + return() + endif() if (_ARG_OUTPUT_DIR) set(PYMOD_DIR "openstructure/${_ARG_OUTPUT_DIR}") else() @@ -499,14 +522,18 @@ macro(pymod) endif() target_link_libraries("_${_LIB_NAME}" ${_PARENT_LIB_NAME} ${PYTHON_LIBRARIES} ${BOOST_PYTHON_LIBRARIES}) - if (_USE_RPATH) - set_target_properties("_${_LIB_NAME}" - PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${PYMOD_STAGE_DIR} - INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${LIB_DIR}") - else() - set_target_properties("_${_LIB_NAME}" - PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${PYMOD_STAGE_DIR} - INSTALL_RPATH "") + + set_target_properties("_${_LIB_NAME}" + PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${PYMOD_STAGE_DIR}) + + if (NOT ENABLE_STATIC) + if (_USE_RPATH) + set_target_properties("_${_LIB_NAME}" + PROPERTIES INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${LIB_DIR}") + else() + set_target_properties("_${_LIB_NAME}" + PROPERTIES INSTALL_RPATH "") + endif() endif() if (APPLE) file(RELATIVE_PATH _REL_PATH "${PYMOD_STAGE_DIR}" "${LIB_STAGE_PATH}") @@ -582,12 +609,13 @@ macro(pymod) add_dependencies("_${_LIB_NAME}" "_${dep}") endforeach() endif() - endmacro() add_custom_target(check) +add_custom_target(check_xml) if (WIN32) set_target_properties(check PROPERTIES EXCLUDE_FROM_ALL "1") + set_target_properties(check_xml PROPERTIES EXCLUDE_FROM_ALL "1") endif() #------------------------------------------------------------------------------- @@ -630,7 +658,12 @@ macro(ost_unittest) target_link_libraries(${_test_name} ${BOOST_UNIT_TEST_LIBRARIES} "${_ARG_PREFIX}_${_ARG_MODULE}") add_custom_target("${_test_name}_run" - COMMAND OST_ROOT=${STAGE_DIR} ${CMAKE_CURRENT_BINARY_DIR}/${_test_name} || echo + COMMAND OST_ROOT=${STAGE_DIR} ${CMAKE_CURRENT_BINARY_DIR}/${_test_name} || echo + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + COMMENT "running checks for module ${_ARG_MODULE}" + DEPENDS ${_test_name}) + add_custom_target("${_test_name}_run_xml" + COMMAND OST_ROOT=${STAGE_DIR} ${CMAKE_CURRENT_BINARY_DIR}/${_test_name} --log_format=xml --log_level=all > ${_test_name}_log.xml || echo WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} COMMENT "running checks for module ${_ARG_MODULE}" DEPENDS ${_test_name}) @@ -642,6 +675,7 @@ macro(ost_unittest) endif() add_dependencies(check "${_test_name}_run") + add_dependencies(check_xml "${_test_name}_run_xml") set_target_properties(${_test_name} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}") @@ -662,9 +696,15 @@ macro(ost_unittest) sh -c "${PY_TESTS_CMD} ${CMAKE_CURRENT_SOURCE_DIR}/${py_test} || echo" WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} COMMENT "running checks ${py_test}" VERBATIM) + add_custom_target("${py_test}_run_xml" + sh -c "${PY_TESTS_CMD} ${CMAKE_CURRENT_SOURCE_DIR}/${py_test} xml || echo" + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + COMMENT "running checks ${py_test}" VERBATIM) endif() add_dependencies("${py_test}_run" ost_scripts "_${_ARG_PREFIX}_${_ARG_MODULE}") + add_dependencies("${py_test}_run_xml" ost_scripts "_${_ARG_PREFIX}_${_ARG_MODULE}") add_dependencies(check "${py_test}_run") + add_dependencies(check_xml "${py_test}_run_xml") if (WIN32) set_target_properties("${py_test}_run" PROPERTIES EXCLUDE_FROM_ALL "1") endif() @@ -832,7 +872,7 @@ macro(setup_compiler_flags) endif() endif() endmacro() -set(_BOOST_MIN_VERSION 1.37) +set(_BOOST_MIN_VERSION 1.31) macro(setup_boost) find_package(Boost ${_BOOST_MIN_VERSION} COMPONENTS python REQUIRED) diff --git a/examples/dssp_sa.py b/examples/dssp_sa.py new file mode 100644 index 0000000000000000000000000000000000000000..23369a99e7d18b74c2623150773687823666827a --- /dev/null +++ b/examples/dssp_sa.py @@ -0,0 +1,7 @@ +from ost.bindings import dssp +ent=io.LoadMMCIF('1ake.cif') +dssp.AssignDSSP(ent, extract_burial_status=True) +for chain in ent.chains: + if chain.is_polypeptide: + for res in chain.residues: + print res.GetFloatProp('relative_solvent_accessibility') diff --git a/modules/base/doc/base.rst b/modules/base/doc/base.rst index 6e0a6caf5f16b2367498e4284a98a1f067be92dd..72d9ed9dcc547e63247afb10905942c1be04a8b0 100644 --- a/modules/base/doc/base.rst +++ b/modules/base/doc/base.rst @@ -5,3 +5,4 @@ logging settings + testutils diff --git a/modules/base/doc/logging.rst b/modules/base/doc/logging.rst index 1a81d479490ced8accd47006543a4c9c247b6749..2637bd9e2822a32618b15fc341163b17da63325c 100644 --- a/modules/base/doc/logging.rst +++ b/modules/base/doc/logging.rst @@ -14,7 +14,17 @@ OpenStructure has a logging system going beyond what print statements can offer. see :ref:`picking-logging-level`. :param message: The message to be logged - :type message: str + :type message: convertible to string + + Similar to the built-int print function, several arguments can be passed to + the logging functions. The arguments will be converted to string and then + concatenated together, separated by space. For example: + + .. code-block:: python + + LogMessage('here be numbers', 1, 2) + + will be converted to 'here be numbers 1 2'. .. note:: @@ -125,6 +135,10 @@ To change the current log sink you can use the following methods: Change the log sink back to the previous one. It is an error to pop the log sink when there is only one log sink on the stack. +.. method:: GetCurrentLogSink() + + Get the current (active) log sink. + .. _picking-logging-level: Guidelines for picking logging level diff --git a/modules/base/doc/testutils.rst b/modules/base/doc/testutils.rst new file mode 100644 index 0000000000000000000000000000000000000000..649a0b3b350a2b30866f98a11873672acefdc5fa --- /dev/null +++ b/modules/base/doc/testutils.rst @@ -0,0 +1,7 @@ +:mod:`~ost.testutils` -- Utils for Running Python Unittests +================================================================================ + +.. module:: ost.testutils + :synopsis: Helper Functions to Run Python Unittests + +.. autofunction:: ost.testutils.RunTests \ No newline at end of file diff --git a/modules/base/pymod/CMakeLists.txt b/modules/base/pymod/CMakeLists.txt index 3f4f748a509f9e43796cb4bde0edf2c5cc162fc8..6a011018fb032d44e07680e214e9bfcb5c14e454 100644 --- a/modules/base/pymod/CMakeLists.txt +++ b/modules/base/pymod/CMakeLists.txt @@ -4,7 +4,8 @@ set(OST_BASE_PYMOD_SOURCES export_range.cc export_units.cc ) - -pymod(NAME base OUTPUT_DIR ost - CPP ${OST_BASE_PYMOD_SOURCES} - PY __init__.py settings.py stutil.py table.py) +if (NOT ENABLE_STATIC) + pymod(NAME base OUTPUT_DIR ost + CPP ${OST_BASE_PYMOD_SOURCES} + PY __init__.py settings.py stutil.py table.py xmlrunner.py testutils.py) +endif() diff --git a/modules/base/pymod/export_logger.cc b/modules/base/pymod/export_logger.cc index 91baeaea09d1681291592b39ecbc104f5f991d8d..91eccbdec2922ab4b5c1167ef48c3ef6d1d8e301 100644 --- a/modules/base/pymod/export_logger.cc +++ b/modules/base/pymod/export_logger.cc @@ -17,6 +17,7 @@ // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA //------------------------------------------------------------------------------ #include <boost/python.hpp> +#include <boost/python/raw_function.hpp> using namespace boost::python; #include <ost/log.hh> @@ -25,10 +26,11 @@ using namespace boost::python; using namespace ost; +struct PyLogSink: public LogSink { -namespace { +}; -struct WrappedLogSink : public LogSink { +struct WrappedLogSink : public PyLogSink, public wrapper<PyLogSink> { WrappedLogSink(PyObject* self): self_(self) { } virtual void LogMessage(const String& message , int severity) @@ -76,27 +78,72 @@ void pop_log_sink() Logger::Instance().PopSink(); } +LogSinkPtr get_log_sink() +{ + return Logger::Instance().GetCurrentSink(); +} -void log_error(const String& m) {LOG_ERROR(m);} -void log_warning(const String& m) {LOG_WARNING(m);} -void log_script(const String& m) {LOG_SCRIPT(m);} -void log_info(const String& m) {LOG_INFO(m);} -void log_verbose(const String& m) {LOG_VERBOSE(m);} +String args_to_string(tuple args, dict kwargs) +{ + std::stringstream ss; + bool empty=true; + for (size_t i=0, l=len(args); i<l; ++i) { + if (!empty) { + ss << " "; + } + empty=false; + String string_val; + try { + string_val=extract<String>(args[i]); + } catch (...) { + string_val=extract<String>(args[i].attr("__str__")()); + } + ss << string_val; + } + return ss.str(); +} + +object log_error(tuple args, dict kwargs) +{ + LOG_ERROR(args_to_string(args, kwargs)); + return object(); +} +object log_warning(tuple args, dict kwargs) +{ + LOG_WARNING(args_to_string(args, kwargs)); + return object(); +} +object log_script(tuple args, dict kwargs) +{ + LOG_SCRIPT(args_to_string(args, kwargs)); + return object(); +} +object log_info(tuple args, dict kwargs) +{ + LOG_INFO(args_to_string(args, kwargs)); + return object(); +} +object log_verbose(tuple args, dict kwargs) +{ + LOG_VERBOSE(args_to_string(args, kwargs)); + return object(); +} void reset_sinks() { Logger::Instance().ResetSinks(); } -} void export_Logger() { - class_<LogSink, WrappedLogSinkPtr, + class_<LogSink, LogSinkPtr, boost::noncopyable>("_LogSink", no_init) + .def("LogMessage", &LogSink::LogMessage) + ; + class_<PyLogSink, WrappedLogSinkPtr, bases<LogSink>, boost::noncopyable>("LogSink") .def("LogMessage", &WrappedLogSink::LogMessageDefault) ; - class_<MultiLogSink, MultiLogSinkPtr, bases<LogSink>, boost::noncopyable >("MultiLogSink", init<>()) .def("AddSink",&MultiLogSink::AddSink) @@ -109,16 +156,23 @@ void export_Logger() .def("LogMessage", &FileLogSink::LogMessage) ; + class_<StringLogSink, StringLogSinkPtr, bases<LogSink>, + boost::noncopyable >("StringLogSink", init<>()) + .def("LogMessage", &StringLogSink::LogMessage) + .def("GetLog", &StringLogSink::GetLog) + ; + def("PushVerbosityLevel",push_verb); def("PopVerbosityLevel",pop_verb); def("GetVerbosityLevel",get_verb); def("PushLogSink",push_log_sink); + def("GetCurrentLogSink",get_log_sink); def("PopLogSink",pop_log_sink); - def("LogError",log_error); - def("LogWarning",log_warning); - def("LogInfo",log_info); - def("LogScript", log_script); - def("LogVerbose", log_verbose); + def("LogError", raw_function(log_error, 1)); + def("LogWarning",raw_function(log_warning, 1)); + def("LogInfo", raw_function(log_info, 1)); + def("LogScript", raw_function(log_script, 1)); + def("LogVerbose", raw_function(log_verbose, 1)); // this relatively ugly construct is required to work around a problem with // the "ost" command-line interpreter. If we don't remove all the sinks from diff --git a/modules/base/pymod/export_units.cc b/modules/base/pymod/export_units.cc index 1a50040f4ce41877e4cdf52faca60f1e81372553..80fa61862bd49513f2dfcc69013477479d07c59a 100644 --- a/modules/base/pymod/export_units.cc +++ b/modules/base/pymod/export_units.cc @@ -30,8 +30,7 @@ using namespace ost; #ifdef OST_STATIC_PROPERTY_WORKAROUND -namespace { - struct Units_ { +struct Units_ { Real get_m() { return Units::m; } Real get_mm() { return Units::mm; } Real get_nm() { return Units::nm; } @@ -53,9 +52,8 @@ namespace { Real get_kDa() { return Units::kDa; } Real get_Da() { return Units::Da; } Real get_C() { return Units::C; } - }; +}; -} //ns #endif diff --git a/modules/base/pymod/table.py b/modules/base/pymod/table.py index 4d6f3bdd45a6cf0535813f2e576698fca75c9cee..4bd1a9999738a8814554997a7e7ceb6d4e7c6cfe 100644 --- a/modules/base/pymod/table.py +++ b/modules/base/pymod/table.py @@ -1,8 +1,10 @@ import csv import re +import math from ost import stutil import itertools import operator +import cPickle from ost import LogError, LogWarning, LogInfo, LogVerbose def MakeTitle(col_name): @@ -16,7 +18,11 @@ def IsStringLike(value): return True except: return False - + +def IsNullString(value): + value=value.strip().upper() + return value in ('', 'NULL', 'NONE', 'NA') + def IsScalar(value): if IsStringLike(value): return True @@ -28,6 +34,38 @@ def IsScalar(value): except: return True +def GuessColumnType(iterator): + empty=True + possibilities=set(['bool', 'int', 'float']) + for ele in iterator: + str_ele=str(ele).upper() + if IsNullString(str_ele): + continue + empty=False + if 'int' in possibilities: + try: + int(str_ele) + except ValueError: + possibilities.remove('int') + + if 'float' in possibilities: + try: + float(str_ele) + except ValueError: + possibilities.remove('float') + if 'bool' in possibilities: + if str_ele not in set(['YES', 'NO', 'TRUE', 'FALSE']): + possibilities.remove('bool') + + if len(possibilities)==0: + return 'string' + if len(possibilities)==2: + return 'int' + if empty: + return 'string' + # return the last element available + return possibilities.pop() + class BinaryColExpr: def __init__(self, op, lhs, rhs): self.op=op @@ -85,7 +123,7 @@ class TableCol: return BinaryColExpr(operator.div, self, rhs) -class Table: +class Table(object): """ The table class provides convenient access to data in tabular form. An empty @@ -96,7 +134,7 @@ class Table: tab=Table() If you want to add columns directly when creating the table, column names - and column types can be specified as follows + and *column types* can be specified as follows .. code-block:: python @@ -106,6 +144,17 @@ class Table: float and bool, respectively. There will be no data in the table and thus, the table will not contain any rows. + The following *column types* are supported: + + ======= ======== + name abbrev + ======= ======== + string s + float f + int i + bool b + ======= ======== + If you want to add data to the table in addition, use the following: .. code-block:: python @@ -232,11 +281,25 @@ class Table: raise ValueError('Unknown type %s' % ty) def GetColIndex(self, col): + ''' + Returns the column index for the column with the given name. + + :raises: ValueError if no column with the name is found + ''' if col not in self.col_names: raise ValueError('Table has no column named "%s"' % col) return self.col_names.index(col) + def GetColNames(self): + ''' + Returns a list containing all column names. + ''' + return self.col_names + def HasCol(self, col): + ''' + Checks if the column with a given name is present in the table. + ''' return col in self.col_names def __getitem__(self, k): @@ -255,6 +318,14 @@ class Table: r[col_index]=v def ToString(self, float_format='%.3f', int_format='%d', rows=None): + ''' + Convert the table into a string representation. + The output format can be modified for int and float type columns by + specifying a formatting string for the parameters 'float_format' and + 'int_format'. + The option 'rows' specify the range of rows to be printed. The parameter + must be a iterable containing two elements, e.g. [start_row, end_row]. + ''' widths=[len(cn) for cn in self.col_names] sel_rows=self.rows if rows: @@ -294,7 +365,7 @@ class Table: def __str__(self): return self.ToString() - def _AddRowsFromDict(self, d, merge=False): + def _AddRowsFromDict(self, d, overwrite=False): # get column indices idxs = [self.GetColIndex(k) for k in d.keys()] @@ -317,11 +388,11 @@ class Table: new_row[idx] = self._Coerce(v, self.col_types[idx]) # partially overwrite existing row with new data - if merge: - merge_idx = self.GetColIndex(merge) + if overwrite: + overwrite_idx = self.GetColIndex(overwrite) added = False for i,r in enumerate(self.rows): - if r[merge_idx]==new_row[merge_idx]: + if r[overwrite_idx]==new_row[overwrite_idx]: for j,e in enumerate(self.rows[i]): if new_row[j]==None: new_row[j] = e @@ -329,40 +400,49 @@ class Table: added = True break - # if not merge or merge did not find appropriate row - if not merge or not added: + # if not overwrite or overwrite did not find appropriate row + if not overwrite or not added: self.rows.append(new_row) - def AddRow(self, data, merge=None): + def AddRow(self, data, overwrite=None): """ - Add a row to the table. *row* may either a dictionary in which case the keys - in the dictionary must match the column names. Columns not found in the dict - will be initialized to None. Alternatively, if data is a list-like object, - the row is initialized from the values in data. The number of items in data - must match the number of columns in the table. A :class:`ValuerError` is - raised otherwise. + Add a row to the table. + + *row* may either be a dictionary or a list-like object. + In the case of a dictionary the keys in the dictionary must match the column + names. Columns not found in the dict will be initialized to None. + Alternatively, if data is a list-like object, the row is initialized from + the values in data. The number of items in data must match the number of + columns in the table. A :class:`ValuerError` is raised otherwise. The values + are added in the order specified in the list, thus, the order of the data + must match the columns. + + If *overwrite* is set and not None (must be set to an existing column name), + an existing row is overwritten if the value of column *overwrite* matches. + If no matching row is found, a new row is appended to the table. """ if type(data)==dict: - self._AddRowsFromDict(data, merge) + self._AddRowsFromDict(data, overwrite) else: if len(data)!=len(self.col_names): + print data, self.col_names msg='data array must have %d elements, not %d' - raise ValueError(msg % (len(self.col_names), len(self.data))) + raise ValueError(msg % (len(self.col_names), len(data))) new_row = [self._Coerce(v, t) for v, t in zip(data, self.col_types)] # fully overwrite existing row with new data - if merge: - merge_idx = self.GetColIndex(merge) + if overwrite: + overwrite_idx = self.GetColIndex(overwrite) added = False for i,r in enumerate(self.rows): - if r[merge_idx]==new_row[merge_idx]: + if r[overwrite_idx]==new_row[overwrite_idx]: self.rows[i] = new_row added = True break - # if not merge or merge did not find appropriate row - if not merge or not added: + # if not overwrite or overwrite did not find appropriate row + if not overwrite or not added: self.rows.append(new_row) def RemoveCol(self, col): @@ -448,22 +528,9 @@ class Table: return filt_tab @staticmethod - def Load(stream_or_filename): - """ - Load table from stream or file with given name. The file must contain a - header line of the form - - col_name1[type1] <col_name2[type2]>... - - The types given in brackets must be one of the data types the :class:`Table` - class understands. Each following line in the file then must contains exactly - the same number of data items as listed in the header. The data items are - automatically converted to the column format. Lines starting with a '#' and - empty lines are ignored. - - :returns: A new :class:`Table` instance - """ - fieldname_pattern=re.compile(r'(?P<name>[A-Za-z0-9_]+)(\[(?P<type>\w+)\])?') + def _LoadOST(stream_or_filename): + fieldname_pattern=re.compile(r'(?P<name>[^[]+)(\[(?P<type>\w+)\])?') + values_pattern=re.compile("([^\" ]+|\"[^\"]*\")+") if not hasattr(stream_or_filename, 'read'): stream=open(stream_or_filename, 'r') else: @@ -486,16 +553,104 @@ class Table: if match.group('type'): fieldtypes.append(match.group('type')) else: - fieldtypes.append('str') + fieldtypes.append('string') fieldnames.append(match.group('name')) tab=Table(fieldnames, fieldtypes) header=True continue - tab.AddRow(line.split()) + tab.AddRow([x.strip('"') for x in values_pattern.findall(line)]) if num_lines==0: raise IOError("Cannot read table from empty stream") return tab + def _GuessColumnTypes(self): + for col_idx in range(len(self.col_names)): + self.col_types[col_idx]=GuessColumnType(self[self.col_names[col_idx]]) + for row in self.rows: + for idx in range(len(row)): + row[idx]=self._Coerce(row[idx], self.col_types[idx]) + + @staticmethod + def _LoadCSV(stream_or_filename, sep): + if not hasattr(stream_or_filename, 'read'): + stream=open(stream_or_filename, 'r') + else: + stream=stream_or_filename + reader=csv.reader(stream, delimiter=sep) + first=True + for row in reader: + if first: + header=row + types='s'*len(row) + tab=Table(header, types) + first=False + else: + tab.AddRow(row) + if first: + raise IOError('trying to load table from empty CSV stream/file') + + tab._GuessColumnTypes() + return tab + + @staticmethod + def _LoadPickle(stream_or_filename): + if not hasattr(stream_or_filename, 'read'): + stream=open(stream_or_filename, 'rb') + else: + stream=stream_or_filename + return cPickle.load(stream) + + @staticmethod + def Load(stream_or_filename, format='ost', sep=','): + """ + Load table from stream or file with given name. + + By default, the file format is *ost* (see below) and is *not* automatically + determined (e.g. from file extension). Thus, it *format* must be specified + for reading other file formats. + + The following file formats are understood: + + - ost + + This is an ost-specific, but still human readable file format. The file + (stream) must start with header line of the form + + col_name1[type1] <col_name2[type2]>... + + The types given in brackets must be one of the data types the + :class:`Table` class understands. Each following line in the file then must + contains exactly the same number of data items as listed in the header. The + data items are automatically converted to the column format. Lines starting + with a '#' and empty lines are ignored. + + - pickle + + Deserializes the table from a pickled byte stream + + - csv + + Reads the table from comma separated values stream. Since there is no + explicit type information in the csv file, the column types are guessed, + using the following simple rules: + + * if all values are either NA/NULL/NONE the type is set to string + * if all non-null values are convertible to float/int the type is set to + float/int + * if all non-null values are true/false/yes/no, the value is set to bool + * for all other cases, the column type is set to string + + :returns: A new :class:`Table` instance + """ + format=format.lower() + if format=='ost': + return Table._LoadOST(stream_or_filename) + if format=='csv': + return Table._LoadCSV(stream_or_filename, sep=sep) + if format=='pickle': + return Table._LoadPickle(stream_or_filename) + raise ValueError('unknown format ""' % format) + def Sort(self, by, order='+'): """ Performs an in-place sort of the table, based on column. @@ -508,19 +663,34 @@ class Table: return sign*cmp(lhs[key_index], rhs[key_index]) self.rows=sorted(self.rows, _key_cmp) + def GetUnique(self, col, ignore_nan=True): + """ + Extract a list of all unique values from one column + """ + idx = self.GetColIndex(col) + seen = {} + result = [] + for row in self.rows: + item = row[idx] + if item!=None or ignore_nan==False: + if item in seen: continue + seen[item] = 1 + result.append(item) + return result + def Zip(self, *args): """ Allows to conveniently iterate over a selection of columns, e.g. - .. code-block::python + .. code-block:: python tab=Table.Load('...') - for col1, col in tab.Zip('col1', 'col2'): + for col1, col2 in tab.Zip('col1', 'col2'): print col1, col2 is a shortcut for - .. code-block::python + .. code-block:: python tab=Table.Load('...') for col1, col2 in zip(tab['col1'], tab['col2']): @@ -530,8 +700,9 @@ class Table: def Plot(self, x, y=None, z=None, style='.', x_title=None, y_title=None, z_title=None, x_range=None, y_range=None, z_range=None, - num_z_levels=10, diag_line=False, labels=None, title=None, - clear=True, save=False): + color=None, plot_if=None, legend=None, + num_z_levels=10, diag_line=False, labels=None, max_num_labels=None, + title=None, clear=True, save=False, **kwargs): """ Plot x against y using matplot lib """ @@ -543,9 +714,9 @@ class Table: xs = [] ys = [] zs = [] - + if clear: - plt.clf() + plt.figure(figsize=[8, 6]) if x_title: nice_x=x_title @@ -567,12 +738,17 @@ class Table: nice_z = MakeTitle(z) else: nice_z = None - + if color: + kwargs['color']=color + if legend: + kwargs['label']=legend if y and z: idx3 = self.GetColIndex(z) idx2 = self.GetColIndex(y) for row in self.rows: if row[idx1]!=None and row[idx2]!=None and row[idx3]!=None: + if plot_if and not plot_if(self, row): + continue xs.append(row[idx1]) ys.append(row[idx2]) zs.append(row[idx3]) @@ -590,7 +766,7 @@ class Table: xi = np.linspace(min(xs)-0.1,max(xs)+0.1,len(xs)*10) yi = np.linspace(min(ys)-0.1,max(ys)+0.1,len(ys)*10) - zi = mlab.griddata(xs, ys, zs, xi, yi, interp='linear') + zi = mlab.griddata(xs, ys, zs, xi, yi) plt.contour(xi,yi,zi,levels,linewidths=0.5,colors='k') plt.contourf(xi,yi,zi,levels,cmap=plt.cm.jet) @@ -600,9 +776,11 @@ class Table: idx2=self.GetColIndex(y) for row in self.rows: if row[idx1]!=None and row[idx2]!=None: + if plot_if and not plot_if(self, row): + continue xs.append(row[idx1]) ys.append(row[idx2]) - plt.plot(xs, ys, style) + plt.plot(xs, ys, style, **kwargs) else: label_vals=[] @@ -611,14 +789,22 @@ class Table: label_idx=self.GetColIndex(labels) for row in self.rows: if row[idx1]!=None: + if plot_if and not plot_if(self, row): + continue xs.append(row[idx1]) if labels: label_vals.append(row[label_idx]) - plt.plot(xs, style) + plt.plot(xs, style, **kwargs) if labels: - plt.xticks(np.arange(len(xs)), label_vals, rotation=45, size='x-small') + interval = 1 + if max_num_labels: + if len(label_vals)>max_num_labels: + interval = int(math.ceil(float(len(label_vals))/max_num_labels)) + label_vals = label_vals[::interval] + plt.xticks(np.arange(0, len(xs), interval), label_vals, rotation=45, + size='x-small') - if not title: + if title==None: if nice_z: title = '%s of %s vs. %s' % (nice_z, nice_x, nice_y) elif nice_y: @@ -626,7 +812,12 @@ class Table: else: title = nice_x - plt.title(title, size='x-large', fontweight='bold') + plt.title(title, size='x-large', fontweight='bold', + verticalalignment='bottom') + + if legend: + plt.legend(loc=0) + if x and y: plt.xlabel(nice_x, size='x-large') if x_range: @@ -638,7 +829,11 @@ class Table: plt.ylabel(nice_y, size='x-large') else: - plt.ylabel(nice_x, size='x-large') + if y_range: + plt.ylim(y_range[0], y_range[1]) + if x_title: + plt.xlabel(x_title, size='x-large') + plt.ylabel(nice_y, size='x-large') if save: plt.savefig(save) return plt @@ -650,8 +845,8 @@ class Table: histtype='stepfilled', align='mid', x_title=None, y_title=None, title=None, clear=True, save=False): """ - Create a histogram of the data in col for the range x_range, split into - num_bins bins and plot it using matplot lib + Create a histogram of the data in col for the range *x_range*, split into + *num_bins* bins and plot it using matplot lib. """ try: import matplotlib.pyplot as plt @@ -788,11 +983,12 @@ class Table: def Sum(self, col): """ Returns the sum of the given column. Cells with None are ignored. Returns - 0.0, if the column doesn't contain any elements. + 0.0, if the column doesn't contain any elements. Col must be of numeric + column type ('float', 'int') or boolean column type. """ idx = self.GetColIndex(col) col_type = self.col_types[idx] - if col_type!='int' and col_type!='float': + if col_type!='int' and col_type!='float' and col_type!='bool': raise TypeError("Sum can only be used on numeric column types") s = 0.0 for r in self.rows: @@ -803,12 +999,16 @@ class Table: def Mean(self, col): """ Returns the mean of the given column. Cells with None are ignored. Returns - None, if the column doesn't contain any elements. + None, if the column doesn't contain any elements. Col must be of numeric + ('float', 'int') or boolean column type. + + If column type is *bool*, the function returns the ratio of + number of 'Trues' by total number of elements. """ idx = self.GetColIndex(col) col_type = self.col_types[idx] - if col_type!='int' and col_type!='float': - raise TypeError("Mean can only be used on numeric column types") + if col_type!='int' and col_type!='float' and col_type!='bool': + raise TypeError("Mean can only be used on numeric or bool column types") vals=[] for v in self[col]: @@ -819,15 +1019,81 @@ class Table: except: return None + def RowMean(self, mean_col_name, cols): + """ + Adds a new column of type 'float' with a specified name (mean_col), + containing the mean of all specified columns for each row. + + Cols are specified by their names and must be of numeric column + type ('float', 'int') or boolean column type.. Cells with None are ignored. + Adds None if the row doesn't contain any values. + + + == Example == + + Staring with the following table: + + ==== ==== ==== + x y u + ==== ==== ==== + 1 10 100 + 2 15 None + 3 20 400 + ==== ==== ==== + + the code here adds a column with the name 'mean' to yield the table below: + + .. code-block::python + + tab.RowMean('mean', 'x', 'u') + + + ==== ==== ==== ===== + x y u mean + ==== ==== ==== ===== + 1 10 100 50.5 + 2 15 None 2 + 3 20 400 201.5 + ==== ==== ==== ===== + + """ + + if IsScalar(cols): + cols = [cols] + + cols_idxs = [] + for col in cols: + idx = self.GetColIndex(col) + col_type = self.col_types[idx] + if col_type!='int' and col_type!='float' and col_type!='bool': + raise TypeError("RowMean can only be used on numeric column types") + cols_idxs.append(idx) + + mean_rows = [] + for row in self.rows: + vals = [] + for idx in cols_idxs: + v = row[idx] + if v!=None: + vals.append(v) + try: + mean = stutil.Mean(vals) + mean_rows.append(mean) + except: + mean_rows.append(None) + + self.AddCol(mean_col_name, 'f', mean_rows) + def Median(self, col): """ Returns the median of the given column. Cells with None are ignored. Returns - None, if the column doesn't contain any elements. + None, if the column doesn't contain any elements. Col must be of numeric + column type ('float', 'int') or boolean column type. """ idx = self.GetColIndex(col) col_type = self.col_types[idx] - if col_type!='int' and col_type!='float': - raise TypeError("Mean can only be used on numeric column types") + if col_type!='int' and col_type!='float' and col_type!='bool': + raise TypeError("Median can only be used on numeric column types") vals=[] for v in self[col]: @@ -842,12 +1108,13 @@ class Table: def StdDev(self, col): """ Returns the standard deviation of the given column. Cells with None are - ignored. Returns None, if the column doesn't contain any elements. + ignored. Returns None, if the column doesn't contain any elements. Col must + be of numeric column type ('float', 'int') or boolean column type. """ idx = self.GetColIndex(col) col_type = self.col_types[idx] - if col_type!='int' and col_type!='float': - raise TypeError("Mean can only be used on numeric column types") + if col_type!='int' and col_type!='float' and col_type!='bool': + raise TypeError("StdDev can only be used on numeric column types") vals=[] for v in self[col]: @@ -879,6 +1146,9 @@ class Table: there are not enough data points to calculate a correlation coefficient, None is returned. """ + if IsStringLike(col1) and IsStringLike(col2): + col1 = self.GetColIndex(col1) + col2 = self.GetColIndex(col2) vals1, vals2=([],[]) for v1, v2 in zip(self[col1], self[col2]): if v1!=None and v2!=None: @@ -889,10 +1159,72 @@ class Table: except: return None - def Save(self, stream): + def SpearmanCorrel(self, col1, col2): + """ + Calculate the Spearman correlation coefficient between col1 and col2, only + taking rows into account where both of the values are not equal to None. If + there are not enough data points to calculate a correlation coefficient, + None is returned. + + The function depends on the following module: *scipy.stats.mstats* + """ + try: + import scipy.stats.mstats + + if IsStringLike(col1) and IsStringLike(col2): + col1 = self.GetColIndex(col1) + col2 = self.GetColIndex(col2) + vals1, vals2=([],[]) + for v1, v2 in zip(self[col1], self[col2]): + if v1!=None and v2!=None: + vals1.append(v1) + vals2.append(v2) + try: + correl = scipy.stats.mstats.spearmanr(vals1, vals2)[0] + if scipy.isnan(correl): + return None + return correl + except: + return None + + except ImportError: + LogError("Function needs scipy.stats.mstats, but I could not import it.") + raise + + + def Save(self, stream_or_filename, format='ost', sep=','): """ - Save the table to stream or filename + Save the table to stream or filename. For supported file formats, see + :meth:`Load` """ + format=format.lower() + if format=='ost': + return self._SaveOST(stream_or_filename) + if format=='csv': + return self._SaveCSV(stream_or_filename, sep=sep) + if format=='pickle': + return self._SavePickle(stream_or_filename) + raise ValueError('unknown format "%s"' % format) + + def _SavePickle(self, stream): + if not hasattr(stream, 'write'): + stream=open(stream, 'wb') + cPickle.dump(self, stream, cPickle.HIGHEST_PROTOCOL) + + def _SaveCSV(self, stream, sep): + if not hasattr(stream, 'write'): + stream=open(stream, 'wb') + + writer=csv.writer(stream, delimiter=sep) + writer.writerow(['%s' % n for n in self.col_names]) + for row in self.rows: + row=list(row) + for i, c in enumerate(row): + if c==None: + row[i]='NA' + writer.writerow(row) + + def _SaveOST(self, stream): if hasattr(stream, 'write'): writer=csv.writer(stream, delimiter=' ') else: @@ -1020,7 +1352,9 @@ class Table: style='-', title=None, x_title=None, y_title=None, clear=True, save=None): ''' - Plot an enrichment curve using matplotlib + Plot an enrichment curve using matplotlib. + + For more information about parameters, see :meth:`ComputeEnrichment` ''' try: @@ -1120,7 +1454,9 @@ class Table: class_dir='-', class_cutoff=2.0): ''' Computes the area under the curve of the enrichment using the trapezoidal - rule + rule. + + For more information about parameters, see :meth:`ComputeEnrichment` ''' try: import numpy as np @@ -1133,6 +1469,242 @@ class Table: LogError("Function needs numpy, but I could not import it.") raise + def ComputeROC(self, score_col, class_col, score_dir='-', + class_dir='-', class_cutoff=2.0): + ''' + Computes the receiver operating characteristics of one column (e.g. score) + over all data points. + + For this it is necessary, that the datapoints are classified into positive + and negative points. This can be done in two ways: + + - by using one 'bool' column (*class_col*) which contains True for positives + and False for negatives + - by using a non-bool column (*class_col*), a cutoff value (*class_cutoff*) + and the classification columns direction (*class_dir*). This will generate + the classification on the fly + + - if *class_dir* =='-': values in the classification column that are + less than or equal to *class_cutoff* will be counted + as positives + - if *class_dir* =='+': values in the classification column that are + larger than or equal to *class_cutoff* will be + counted as positives + + During the calculation, the table will be sorted according to *score_dir*, + where a '-' values means smallest values first and therefore, the smaller + the value, the better. + + If *class_col* does not contain any positives (i.e. value is True (if column + is of type bool) or evaluated to True (if column is of type int or float + (depending on *class_dir* and *class_cutoff*))) the ROC is not defined and + the function will return *None*. + ''' + + ALLOWED_DIR = ['+','-'] + + score_idx = self.GetColIndex(score_col) + score_type = self.col_types[score_idx] + if score_type!='int' and score_type!='float': + raise TypeError("Score column must be numeric type") + + class_idx = self.GetColIndex(class_col) + class_type = self.col_types[class_idx] + if class_type!='int' and class_type!='float' and class_type!='bool': + raise TypeError("Classifier column must be numeric or bool type") + + if (score_dir not in ALLOWED_DIR) or (class_dir not in ALLOWED_DIR): + raise ValueError("Direction must be one of %s"%str(ALLOWED_DIR)) + + self.Sort(score_col, score_dir) + + x = [0] + y = [0] + tp = 0 + fp = 0 + old_score_val = None + + for i,row in enumerate(self.rows): + class_val = row[class_idx] + score_val = row[score_idx] + if class_val!=None: + if old_score_val==None: + old_score_val = score_val + if score_val!=old_score_val: + x.append(fp) + y.append(tp) + old_score_val = score_val + if class_type=='bool': + if class_val==True: + tp += 1 + else: + fp += 1 + else: + if (class_dir=='-' and class_val<=class_cutoff) or (class_dir=='+' and class_val>=class_cutoff): + tp += 1 + else: + fp += 1 + x.append(fp) + y.append(tp) + + # if no false positives or false negatives values are found return None + if x[-1]==0 or y[-1]==0: + return None + + x = [float(v)/x[-1] for v in x] + y = [float(v)/y[-1] for v in y] + return x,y + + def ComputeROCAUC(self, score_col, class_col, score_dir='-', + class_dir='-', class_cutoff=2.0): + ''' + Computes the area under the curve of the receiver operating characteristics + using the trapezoidal rule. + + For more information about parameters, see :meth:`ComputeROC` + ''' + try: + import numpy as np + + roc = self.ComputeROC(score_col, class_col, score_dir, + class_dir, class_cutoff) + + if not roc: + return None + return np.trapz(roc[1], roc[0]) + except ImportError: + LogError("Function needs numpy, but I could not import it.") + raise + + def PlotROC(self, score_col, class_col, score_dir='-', + class_dir='-', class_cutoff=2.0, + style='-', title=None, x_title=None, y_title=None, + clear=True, save=None): + ''' + Plot an ROC curve using matplotlib. + + For more information about parameters, see :meth:`ComputeROC` + ''' + + try: + import matplotlib.pyplot as plt + + roc = self.ComputeROC(score_col, class_col, score_dir, + class_dir, class_cutoff) + + if not roc: + return None + + enrx, enry = roc + + if not title: + title = 'ROC of %s'%score_col + + if not x_title: + x_title = 'false positive rate' + + if not y_title: + y_title = 'true positive rate' + + if clear: + plt.clf() + + plt.plot(enrx, enry, style) + + plt.title(title, size='x-large', fontweight='bold') + plt.ylabel(y_title, size='x-large') + plt.xlabel(x_title, size='x-large') + + if save: + plt.savefig(save) + + return plt + except ImportError: + LogError("Function needs matplotlib, but I could not import it.") + raise + + def ComputeMCC(self, score_col, class_col, score_dir='-', + class_dir='-', score_cutoff=2.0, class_cutoff=2.0): + ''' + Compute Matthews correlation coefficient (MCC) for one column (*score_col*) + with the points classified into true positives, false positives, true + negatives and false negatives according to a specified classification + column (*class_col*). + + The datapoints in *score_col* and *class_col* are classified into + positive and negative points. This can be done in two ways: + + - by using 'bool' columns which contains True for positives and False + for negatives + + - by using 'float' or 'int' columns and specifying a cutoff value and the + columns direction. This will generate the classification on the fly + + * if *class_dir*/*score_dir*=='-': values in the classification column + that are less than or equal to + *class_cutoff*/*score_cutoff* will be + counted as positives + * if *class_dir*/*score_dir*=='+': values in the classification column + that are larger than or equal to + *class_cutoff*/*score_cutoff* will be + counted as positives + + The two possibilities can be used together, i.e. 'bool' type for one column + and 'float'/'int' type and cutoff/direction for the other column. + ''' + ALLOWED_DIR = ['+','-'] + + score_idx = self.GetColIndex(score_col) + score_type = self.col_types[score_idx] + if score_type!='int' and score_type!='float' and score_type!='bool': + raise TypeError("Score column must be numeric or bool type") + + class_idx = self.GetColIndex(class_col) + class_type = self.col_types[class_idx] + if class_type!='int' and class_type!='float' and class_type!='bool': + raise TypeError("Classifier column must be numeric or bool type") + + if (score_dir not in ALLOWED_DIR) or (class_dir not in ALLOWED_DIR): + raise ValueError("Direction must be one of %s"%str(ALLOWED_DIR)) + + tp = 0 + fp = 0 + fn = 0 + tn = 0 + + for i,row in enumerate(self.rows): + class_val = row[class_idx] + score_val = row[score_idx] + if class_val!=None: + if (class_type=='bool' and class_val==True) or (class_type!='bool' and ((class_dir=='-' and class_val<=class_cutoff) or (class_dir=='+' and class_val>=class_cutoff))): + if (score_type=='bool' and score_val==True) or (score_type!='bool' and ((score_dir=='-' and score_val<=score_cutoff) or (score_dir=='+' and score_val>=score_cutoff))): + tp += 1 + else: + fn += 1 + else: + if (score_type=='bool' and score_val==False) or (score_type!='bool' and ((score_dir=='-' and score_val>score_cutoff) or (score_dir=='+' and score_val<score_cutoff))): + tn += 1 + else: + fp += 1 + + mcc = None + msg = None + if (tp+fn)==0: + msg = 'factor (tp + fn) is zero' + elif (tp+fp)==0: + msg = 'factor (tp + fp) is zero' + elif (tn+fn)==0: + msg = 'factor (tn + fn) is zero' + elif (tn+fp)==0: + msg = 'factor (tn + fp) is zero' + + if msg: + LogWarning("Could not compute MCC: MCC is not defined since %s"%msg) + else: + mcc = ((tp*tn)-(fp*fn)) / math.sqrt((tp+fn)*(tp+fp)*(tn+fn)*(tn+fp)) + return mcc + + def IsEmpty(self, col_name=None, ignore_nan=True): ''' Checks if a table is empty. @@ -1169,12 +1741,52 @@ class Table: return False return True + def Extend(self, tab, overwrite=None): + """ + Append each row of *tab* to the current table. The data is appended based + on the column names, thus the order of the table columns is *not* relevant, + only the header names. + + If there is a column in *tab* that is not present in the current table, + it is added to the current table and filled with *None* for all the rows + present in the current table. + + If the type of any column in *tab* is not the same as in the current table + a *TypeError* is raised. + + If *overwrite* is set and not None (must be set to an existing column name), + an existing row is overwritten if the value of column *overwrite* matches. + If no matching row is found, a new row is appended to the table. + """ + # add column to current table if it doesn't exist + for name,typ in zip(tab.col_names, tab.col_types): + if not name in self.col_names: + self.AddCol(name, typ) + + # check that column types are the same in current and new table + for name in self.col_names: + if name in tab.col_names: + curr_type = self.col_types[self.GetColIndex(name)] + new_type = tab.col_types[tab.GetColIndex(name)] + if curr_type!=new_type: + raise TypeError('cannot extend table, column %s in new '%name +\ + 'table different type (%s) than in '%new_type +\ + 'current table (%s)'%curr_type) + + num_rows = len(tab.rows) + for i in range(0,num_rows): + row = tab.rows[i] + data = dict(zip(tab.col_names,row)) + self.AddRow(data, overwrite) + def Merge(table1, table2, by, only_matching=False): """ Returns a new table containing the data from both tables. The rows are - combined based on the common values in the column by. For example, the two - tables below + combined based on the common values in the column(s) by. The option 'by' can + be a list of column names. When this is the case, merging is based on + multiple columns. + For example, the two tables below ==== ==== x y @@ -1269,4 +1881,4 @@ def Merge(table1, table2, by, only_matching=False): new_tab.AddRow(row) return new_tab - \ No newline at end of file + diff --git a/modules/base/pymod/testutils.py b/modules/base/pymod/testutils.py new file mode 100644 index 0000000000000000000000000000000000000000..fe3e7a024d0c19baea30fa663549f5513489870a --- /dev/null +++ b/modules/base/pymod/testutils.py @@ -0,0 +1,54 @@ +def RunTests(): + ''' + This function behaves as a custom TestLoader for python unittests. + + With no system arguments, the default unittest TestRunner is used. + + If the first system argument (sys.argv[1]) is set to 'xml', a XMLTestRunner + is used, which produces a JUnit compatible XML output file. Within the current + module, each function is identified which is a subclass of unittest.TestCase + and for each TestCase, a test suite is executed, producing an individual + output file for each TestCase. The output file has the name, + 'PYTEST-<TestCaseName>.xml'. + + Example of a Python testcase: + + .. code-block:: python + + import unittest + + class TestRenumber(unittest.TestCase): + + def setUp(self): + # prepare stuff" + pass + + def testSomeFunction(self): + # do some asserts + pass + + if __name__ == "__main__": + from ost import testutils + testutils.RunTests() + + ''' + import unittest + import sys + try: + if len(sys.argv)>1 and sys.argv[1]=='xml': + import inspect + import types + import __main__ + from ost import xmlrunner + for name, obj in inspect.getmembers(__main__): + if (isinstance(obj, (type, types.ClassType)) and + issubclass(obj, unittest.TestCase)): + suite = unittest.TestLoader().loadTestsFromTestCase(obj) + stream = open('PYTEST-%s.xml'%name, 'w') + xmlrunner.XMLTestRunner(stream).run(suite) + stream.close() + + else: + unittest.main() + except Exception, e: + print e \ No newline at end of file diff --git a/modules/base/pymod/wrap_base.cc b/modules/base/pymod/wrap_base.cc index 1ba0b15718baec2fbf014e9301583d052a3d2205..40ad33717f79c38e58c21624b87736f387016f3c 100644 --- a/modules/base/pymod/wrap_base.cc +++ b/modules/base/pymod/wrap_base.cc @@ -21,6 +21,7 @@ #include <vector> #include <ost/geom/export_helper/vector.hh> #include <ost/base.hh> +#include <ost/string_ref.hh> #include <ost/platform.hh> #include <ost/message.hh> #include <ost/version.hh> @@ -38,8 +39,48 @@ void translator(const ost::Error& x) { } +struct stringref_to_python_string +{ + static PyObject* convert(ost::StringRef const& s) + { + return boost::python::incref(boost::python::object(s.str()).ptr()); + } +}; + +struct stringref_from_python_string +{ + stringref_from_python_string() + { + boost::python::converter::registry::push_back(&convertible, + &construct, + boost::python::type_id<ost::StringRef>()); + } + + static void* convertible(PyObject* obj_ptr) + { + if (!PyString_Check(obj_ptr)) return 0; + return obj_ptr; + } + + static void construct(PyObject* obj_ptr, + boost::python::converter::rvalue_from_python_stage1_data* data) + { + const char* value = PyString_AsString(obj_ptr); + if (value == 0) boost::python::throw_error_already_set(); + void* storage = ( + (boost::python::converter::rvalue_from_python_storage<ost::StringRef>*) + data)->storage.bytes; + new (storage) ost::StringRef(value, strlen(value)); + data->convertible = storage; + } +}; + + BOOST_PYTHON_MODULE(_ost_base) { + boost::python::to_python_converter<ost::StringRef, + stringref_to_python_string>(); + stringref_from_python_string(); register_exception_translator<ost::Error>(&translator); def("SetPrefixPath", &ost::SetPrefixPath); @@ -50,6 +91,7 @@ BOOST_PYTHON_MODULE(_ost_base) scope().attr("VERSION_MAJOR")=OST_VERSION_MAJOR; scope().attr("VERSION_MINOR")=OST_VERSION_MINOR; scope().attr("VERSION_PATCH")=OST_VERSION_PATCH; + scope().attr("WITH_NUMPY")= OST_NUMPY_SUPPORT_ENABLED; export_Logger(); export_Range(); export_Units(); @@ -67,5 +109,5 @@ BOOST_PYTHON_MODULE(_ost_base) class_<std::vector<int> >("IntList", init<>()) .def(vector_indexing_suite<std::vector<int> >()) .def(geom::VectorAdditions<IntList>()) - ; + ; } diff --git a/modules/base/pymod/xmlrunner.py b/modules/base/pymod/xmlrunner.py new file mode 100644 index 0000000000000000000000000000000000000000..e2bcae76df26efef15363d6775dca6b8bbd0bc34 --- /dev/null +++ b/modules/base/pymod/xmlrunner.py @@ -0,0 +1,390 @@ +""" +XML Test Runner for PyUnit +""" + +# Written by Sebastian Rittau <srittau@jroger.in-berlin.de> and placed in +# the Public Domain. With contributions by Paolo Borelli and others. + +__version__ = "0.1" + +import os.path +import re +import sys +import time +import traceback +import unittest +from xml.sax.saxutils import escape + +try: + from StringIO import StringIO +except ImportError: + from io import StringIO + + +class _TestInfo(object): + + """Information about a particular test. + + Used by _XMLTestResult. + + """ + + def __init__(self, test, time): + (self._class, self._method) = test.id().rsplit(".", 1) + self._time = time + self._error = None + self._failure = None + + @staticmethod + def create_success(test, time): + """Create a _TestInfo instance for a successful test.""" + return _TestInfo(test, time) + + @staticmethod + def create_failure(test, time, failure): + """Create a _TestInfo instance for a failed test.""" + info = _TestInfo(test, time) + info._failure = failure + return info + + @staticmethod + def create_error(test, time, error): + """Create a _TestInfo instance for an erroneous test.""" + info = _TestInfo(test, time) + info._error = error + return info + + def print_report(self, stream): + """Print information about this test case in XML format to the + supplied stream. + + """ + stream.write(' <testcase classname="%(class)s" name="%(method)s" time="%(time).4f">' % \ + { + "class": self._class, + "method": self._method, + "time": self._time, + }) + if self._failure is not None: + self._print_error(stream, 'failure', self._failure) + if self._error is not None: + self._print_error(stream, 'error', self._error) + stream.write('</testcase>\n') + + def _print_error(self, stream, tagname, error): + """Print information from a failure or error to the supplied stream.""" + text = escape(str(error[1])) + stream.write('\n') + stream.write(' <%s type="%s">%s\n' \ + % (tagname, _clsname(error[0]), text)) + tb_stream = StringIO() + traceback.print_tb(error[2], None, tb_stream) + stream.write(escape(tb_stream.getvalue())) + stream.write(' </%s>\n' % tagname) + stream.write(' ') + + +def _clsname(cls): + return cls.__module__ + "." + cls.__name__ + + +class _XMLTestResult(unittest.TestResult): + + """A test result class that stores result as XML. + + Used by XMLTestRunner. + + """ + + def __init__(self, classname): + unittest.TestResult.__init__(self) + self._test_name = classname + self._start_time = None + self._tests = [] + self._error = None + self._failure = None + + def startTest(self, test): + unittest.TestResult.startTest(self, test) + self._error = None + self._failure = None + self._start_time = time.time() + + def stopTest(self, test): + time_taken = time.time() - self._start_time + unittest.TestResult.stopTest(self, test) + if self._error: + info = _TestInfo.create_error(test, time_taken, self._error) + elif self._failure: + info = _TestInfo.create_failure(test, time_taken, self._failure) + else: + info = _TestInfo.create_success(test, time_taken) + self._tests.append(info) + + def addError(self, test, err): + unittest.TestResult.addError(self, test, err) + self._error = err + + def addFailure(self, test, err): + unittest.TestResult.addFailure(self, test, err) + self._failure = err + + def print_report(self, stream, time_taken, out, err): + """Prints the XML report to the supplied stream. + + The time the tests took to perform as well as the captured standard + output and standard error streams must be passed in.a + + """ + stream.write('<testsuite errors="%(e)d" failures="%(f)d" ' % \ + { "e": len(self.errors), "f": len(self.failures) }) + stream.write('name="%(n)s" tests="%(t)d" time="%(time).3f">\n' % \ + { + "n": self._test_name, + "t": self.testsRun, + "time": time_taken, + }) + for info in self._tests: + info.print_report(stream) + stream.write(' <system-out><![CDATA[%s]]></system-out>\n' % out) + stream.write(' <system-err><![CDATA[%s]]></system-err>\n' % err) + stream.write('</testsuite>\n') + + +class XMLTestRunner(object): + + """A test runner that stores results in XML format compatible with JUnit. + + XMLTestRunner(stream=None) -> XML test runner + + The XML file is written to the supplied stream. If stream is None, the + results are stored in a file called TEST-<module>.<class>.xml in the + current working directory (if not overridden with the path property), + where <module> and <class> are the module and class name of the test class. + + """ + + def __init__(self, stream=None): + self._stream = stream + self._path = "." + + def run(self, test): + """Run the given test case or test suite.""" + class_ = test.__class__ + classname = class_.__module__ + "." + class_.__name__ + if self._stream == None: + filename = "TEST-%s.xml" % classname + stream = file(os.path.join(self._path, filename), "w") + stream.write('<?xml version="1.0" encoding="utf-8"?>\n') + else: + stream = self._stream + + result = _XMLTestResult(classname) + start_time = time.time() + + try: + self._orig_stdout = sys.stdout + self._orig_stderr = sys.stderr + sys.stdout = StringIO() + sys.stderr = StringIO() + test(result) + try: + out_s = sys.stdout.getvalue() + except AttributeError: + out_s = "" + try: + err_s = sys.stderr.getvalue() + except AttributeError: + err_s = "" + finally: + sys.stdout = self._orig_stdout + sys.stderr = self._orig_stderr + + + time_taken = time.time() - start_time + result.print_report(stream, time_taken, out_s, err_s) + if self._stream is None: + stream.close() + + return result + + def _set_path(self, path): + self._path = path + + path = property(lambda self: self._path, _set_path, None, + """The path where the XML files are stored. + + This property is ignored when the XML file is written to a file + stream.""") + + +class _fake_std_streams(object): + + def __enter__(self): + self._orig_stdout = sys.stdout + self._orig_stderr = sys.stderr + sys.stdout = StringIO() + sys.stderr = StringIO() + + def __exit__(self, exc_type, exc_val, exc_tb): + sys.stdout = self._orig_stdout + sys.stderr = self._orig_stderr + + +class XMLTestRunnerTest(unittest.TestCase): + + def setUp(self): + self._stream = StringIO() + + def _try_test_run(self, test_class, expected): + + """Run the test suite against the supplied test class and compare the + XML result against the expected XML string. Fail if the expected + string doesn't match the actual string. All time attributes in the + expected string should have the value "0.000". All error and failure + messages are reduced to "Foobar". + + """ + + runner = XMLTestRunner(self._stream) + runner.run(unittest.makeSuite(test_class)) + + got = self._stream.getvalue() + # Replace all time="X.YYY" attributes by time="0.000" to enable a + # simple string comparison. + got = re.sub(r'time="\d+\.\d+"', 'time="0.000"', got) + # Likewise, replace all failure and error messages by a simple "Foobar" + # string. + got = re.sub(r'(?s)<failure (.*?)>.*?</failure>', r'<failure \1>Foobar</failure>', got) + got = re.sub(r'(?s)<error (.*?)>.*?</error>', r'<error \1>Foobar</error>', got) + # And finally Python 3 compatibility. + got = got.replace('type="builtins.', 'type="exceptions.') + + self.assertEqual(expected, got) + + def test_no_tests(self): + """Regression test: Check whether a test run without any tests + matches a previous run. + + """ + class TestTest(unittest.TestCase): + pass + self._try_test_run(TestTest, """<testsuite errors="0" failures="0" name="unittest.TestSuite" tests="0" time="0.000"> + <system-out><![CDATA[]]></system-out> + <system-err><![CDATA[]]></system-err> +</testsuite> +""") + + def test_success(self): + """Regression test: Check whether a test run with a successful test + matches a previous run. + + """ + class TestTest(unittest.TestCase): + def test_foo(self): + pass + self._try_test_run(TestTest, """<testsuite errors="0" failures="0" name="unittest.TestSuite" tests="1" time="0.000"> + <testcase classname="__main__.TestTest" name="test_foo" time="0.000"></testcase> + <system-out><![CDATA[]]></system-out> + <system-err><![CDATA[]]></system-err> +</testsuite> +""") + + def test_failure(self): + """Regression test: Check whether a test run with a failing test + matches a previous run. + + """ + class TestTest(unittest.TestCase): + def test_foo(self): + self.assert_(False) + self._try_test_run(TestTest, """<testsuite errors="0" failures="1" name="unittest.TestSuite" tests="1" time="0.000"> + <testcase classname="__main__.TestTest" name="test_foo" time="0.000"> + <failure type="exceptions.AssertionError">Foobar</failure> + </testcase> + <system-out><![CDATA[]]></system-out> + <system-err><![CDATA[]]></system-err> +</testsuite> +""") + + def test_error(self): + """Regression test: Check whether a test run with a erroneous test + matches a previous run. + + """ + class TestTest(unittest.TestCase): + def test_foo(self): + raise IndexError() + self._try_test_run(TestTest, """<testsuite errors="1" failures="0" name="unittest.TestSuite" tests="1" time="0.000"> + <testcase classname="__main__.TestTest" name="test_foo" time="0.000"> + <error type="exceptions.IndexError">Foobar</error> + </testcase> + <system-out><![CDATA[]]></system-out> + <system-err><![CDATA[]]></system-err> +</testsuite> +""") + + def test_stdout_capture(self): + """Regression test: Check whether a test run with output to stdout + matches a previous run. + + """ + class TestTest(unittest.TestCase): + def test_foo(self): + sys.stdout.write("Test\n") + self._try_test_run(TestTest, """<testsuite errors="0" failures="0" name="unittest.TestSuite" tests="1" time="0.000"> + <testcase classname="__main__.TestTest" name="test_foo" time="0.000"></testcase> + <system-out><![CDATA[Test +]]></system-out> + <system-err><![CDATA[]]></system-err> +</testsuite> +""") + + def test_stderr_capture(self): + """Regression test: Check whether a test run with output to stderr + matches a previous run. + + """ + class TestTest(unittest.TestCase): + def test_foo(self): + sys.stderr.write("Test\n") + self._try_test_run(TestTest, """<testsuite errors="0" failures="0" name="unittest.TestSuite" tests="1" time="0.000"> + <testcase classname="__main__.TestTest" name="test_foo" time="0.000"></testcase> + <system-out><![CDATA[]]></system-out> + <system-err><![CDATA[Test +]]></system-err> +</testsuite> +""") + + class NullStream(object): + """A file-like object that discards everything written to it.""" + def write(self, buffer): + pass + + def test_unittests_changing_stdout(self): + """Check whether the XMLTestRunner recovers gracefully from unit tests + that change stdout, but don't change it back properly. + + """ + class TestTest(unittest.TestCase): + def test_foo(self): + sys.stdout = XMLTestRunnerTest.NullStream() + + runner = XMLTestRunner(self._stream) + runner.run(unittest.makeSuite(TestTest)) + + def test_unittests_changing_stderr(self): + """Check whether the XMLTestRunner recovers gracefully from unit tests + that change stderr, but don't change it back properly. + + """ + class TestTest(unittest.TestCase): + def test_foo(self): + sys.stderr = XMLTestRunnerTest.NullStream() + + runner = XMLTestRunner(self._stream) + runner.run(unittest.makeSuite(TestTest)) + + +if __name__ == "__main__": + unittest.main() diff --git a/modules/base/src/log_sink.hh b/modules/base/src/log_sink.hh index f4b14d00752935fe7fb307d465d44c5b7f52598c..f06d4ae1c6221c0691a5715cc60bc355b4344431 100644 --- a/modules/base/src/log_sink.hh +++ b/modules/base/src/log_sink.hh @@ -20,6 +20,7 @@ #define OST_LOG_SINK_HH #include <ostream> +#include <sstream> #include <iostream> #include <fstream> #include <stack> @@ -35,7 +36,7 @@ class DLLEXPORT LogSink { public: LogSink(){}; virtual ~LogSink() { } - virtual void LogMessage(const String& message, int severity=0)=0; + virtual void LogMessage(const String& message, int severity=0) {}; }; typedef boost::shared_ptr<LogSink> LogSinkPtr; @@ -51,6 +52,23 @@ private: std::ostream& stream_; }; +class DLLEXPORT StringLogSink : public LogSink { +public: + StringLogSink():LogSink(),stream_(){} + virtual void LogMessage(const String& message, int severity){ + stream_ << message; + } + String GetLog() const + { + return stream_.str(); + } + +private: + std::ostringstream stream_; +}; + +typedef boost::shared_ptr<StringLogSink> StringLogSinkPtr; + class DLLEXPORT FileLogSink : public LogSink { public: FileLogSink(const String& file_name):stream_(file_name.c_str(), std::ios::out){} diff --git a/modules/base/src/string_ref.cc b/modules/base/src/string_ref.cc index 5cc42986b497f65cd9899b971eafbd3bbdd93a45..03209b11fabacadbff82daae3f36c80b1140f898 100644 --- a/modules/base/src/string_ref.cc +++ b/modules/base/src/string_ref.cc @@ -18,6 +18,7 @@ //------------------------------------------------------------------------------ #include <ost/string_ref.hh> +#include <math.h> namespace ost { @@ -53,6 +54,11 @@ std::pair<bool, float> StringRef::to_float() const int sig=1; bool after_dot=false; float factor=0.1; + bool after_exponent=false; + float exponent=0.0; + int exponent_sig=1; + bool after_exponent_sign=false; + for (const char* c=begin_; c!=end_; ++c) { if (*c=='-' && empty) { empty=false; @@ -71,17 +77,41 @@ std::pair<bool, float> StringRef::to_float() const if (after_dot==true) { n+=factor*int(*c-'0'); factor*=0.1; + } else if (after_exponent==true) { + exponent=exponent*10+int(*c-'0'); } else { n=n*10+int(*c-'0'); } continue; } + if ((*c=='+' || *c=='-') && after_exponent==true) { + if (after_exponent_sign==true) { + return std::make_pair(false, 0.0f); + } + if (*c=='-') { + exponent_sig=-1; + } + after_exponent_sign=true; + continue; + } + if (*c=='e' || *c=='E') { + if (after_exponent==true) { + return std::make_pair(false, 0.0f); + } + after_exponent=true; + after_dot=false; + continue; + } return std::make_pair(false, 0.0f); } if (empty) { return std::make_pair(false, 0.0f); } - return std::make_pair(true, sig*n); + if (after_exponent==false) { + return std::make_pair(true, sig*n); + } else { + return std::make_pair(true, sig*n*float(pow(10,exponent_sig*exponent))); + } } std::ostream& operator<<(std::ostream& stream, const StringRef& strref) @@ -113,4 +143,37 @@ std::vector<StringRef> StringRef::split(char p) const return result; } +std::vector<StringRef> StringRef::split() const +{ + std::vector<StringRef> result; + const char* s=begin_; + const char* l=begin_; + while (s!=end_) { + if (isspace(*s)) { + if (l!=s) { + result.push_back(StringRef(l, s-l)); + } + l=s+1; + } + ++s; + } + if (l!=s) { + result.push_back(StringRef(l, s-l)); + } + return result; +} + +std::string StringRef::str_no_whitespace() const +{ + std::string whitespaceless_string; + whitespaceless_string.reserve(this->size()); + for (const char* s=begin_; s!=end_; ++s) { + if (isspace(*s)) { + continue; + } + whitespaceless_string.push_back(*s); + + } + return whitespaceless_string; +} } diff --git a/modules/base/src/string_ref.hh b/modules/base/src/string_ref.hh index cc5661ebaa2c15dc96818d8fb86fbb8a3a7b4696..802dd594069257ba17213a02d73144018e635b32 100644 --- a/modules/base/src/string_ref.hh +++ b/modules/base/src/string_ref.hh @@ -28,7 +28,6 @@ #include <ost/base.hh> #include <string.h> #include <vector> -#include <ost/message.hh> #include <ost/module_config.hh> @@ -60,8 +59,9 @@ public: assert(!this->empty()); return *begin_; } - /// \brief find character in StringRef - /// \return iterator position when found, else iterator pointing to the end + + /// \brief find character in StringRef + /// \return iterator position when found, else iterator pointing to the end const_iterator find(char p) const { const char* s=begin_; while (s!=end_) { @@ -72,7 +72,7 @@ public: } return s; } - + /// \brief returns a substring of the string /// /// \param pos the starting position of the substring @@ -147,10 +147,16 @@ public: /// \brief split string into chunks delimited by \p p std::vector<StringRef> split(char p) const; + + /// \brief split string into chunks delimited by whitespace + std::vector<StringRef> split() const; + + /// \brief returns a new string with all whitespace removed from + /// this StringRef + std::string str_no_whitespace() const; private: const char* begin_; - const char* end_; - + const char* end_; }; //std::stringstream& operator<<(std::stringstream& stream, const StringRef& strref); diff --git a/modules/base/tests/CMakeLists.txt b/modules/base/tests/CMakeLists.txt index c18fcda10eef03664e59767ce1659004689188c1..5a5bce51ae28460c28bc807e824f52af8f593f7a 100644 --- a/modules/base/tests/CMakeLists.txt +++ b/modules/base/tests/CMakeLists.txt @@ -4,6 +4,7 @@ set(OST_BASE_UNIT_TESTS test_pod_vector.cc test_stutil.py test_table.py + test_log.py tests.cc ) diff --git a/modules/base/tests/test_log.py b/modules/base/tests/test_log.py new file mode 100644 index 0000000000000000000000000000000000000000..cec9378edc965174e460c392ee8bf28a69d106e8 --- /dev/null +++ b/modules/base/tests/test_log.py @@ -0,0 +1,43 @@ +import unittest +import ost + +# Altough the logging system might appear to be too simple to be worth writing a +# specific test case for, it actually isn't. The python export is very fragile +# and seemingly trivial changes can break the code in unexpected ways. So let's +# check for some invariants +class TestLog(unittest.TestCase): + def testGetLogSink(self): + logsink=ost.GetCurrentLogSink() + self.assertTrue(hasattr(logsink, 'LogMessage')) + # Check if the return type of logsink is sane + ost.PushLogSink(ost.GetCurrentLogSink()) + def testPushPopLogSink(self): + class MyLogSink(ost.LogSink): + def __init__(self): + ost.LogSink.__init__(self) + ls=MyLogSink() + ost.PushLogSink(ls) + self.assertEqual(ls, ost.GetCurrentLogSink()) + ost.PopLogSink() + self.assertNotEqual(ls, ost.GetCurrentLogSink()) + + def testLogMessage(self): + class CapturingLogSink(ost.LogSink): + def __init__(self): + ost.LogSink.__init__(self) + def LogMessage(self, message, severity): + self.message=message + self.severity=severity + ost.PushLogSink(ls) + ls=CapturingLogSink() + ost.PushLogSink(ls) + ost.LogError('error message') + self.assertEqual(ls.message, 'error message\n') + self.assertEqual(ls.severity, 0) + ost.LogWarning(1, 2, 3) + self.assertEqual(ls.message, '1 2 3\n') + self.assertEqual(ls.severity, 1) + ost.PopLogSink() +if __name__ == "__main__": + from ost import testutils + testutils.RunTests() \ No newline at end of file diff --git a/modules/base/tests/test_string_ref.cc b/modules/base/tests/test_string_ref.cc index 50793bff7f83bde41e88047717d31687b7fbe5f8..05ea7701ec963d2d89f0c6098c9272e2cd59d3f2 100644 --- a/modules/base/tests/test_string_ref.cc +++ b/modules/base/tests/test_string_ref.cc @@ -84,6 +84,55 @@ BOOST_AUTO_TEST_CASE( test_string_ref) BOOST_CHECK(r2.first==false); r2=StringRef("12.34.", 6).to_float(); BOOST_CHECK(r2.first==false); + + // to_float_with_exp + std::pair<bool, Real> r3=StringRef("1", 1).to_float(); + BOOST_CHECK(r3.first==true); + BOOST_CHECK(r3.second=1.0); + r3=StringRef("1.5", 3).to_float(); + BOOST_CHECK(r3.first==true); + BOOST_CHECK(r3.second=1.5); + r3=StringRef("x", 1).to_float(); + BOOST_CHECK(r3.first==false); + r3=StringRef("12.3.4", 6).to_float(); + BOOST_CHECK(r3.first==false); + r3=StringRef("12.34.", 6).to_float(); + BOOST_CHECK(r3.first==false); + r3=StringRef("12.34e5", 7).to_float(); + BOOST_CHECK(r3.first==true); + r3=StringRef("12e4", 4).to_float(); + BOOST_CHECK(r3.first==true); + BOOST_CHECK_CLOSE(Real(120000), Real(r3.second), Real(1e-4)); + r3=StringRef("2e+4", 4).to_float(); + BOOST_CHECK(r3.first==true); + BOOST_CHECK_CLOSE(Real(20000), Real(r3.second), Real(1e-4)); + r3=StringRef("2.3E+4", 6).to_float(); + BOOST_CHECK(r3.first==true); + BOOST_CHECK_CLOSE(Real(23000), Real(r3.second), Real(1e-4)); + r3=StringRef("2.3E-4", 6).to_float(); + BOOST_CHECK(r3.first==true); + BOOST_CHECK_CLOSE(Real(0.00023), Real(r3.second), Real(1e-4)); + r3=StringRef("2.010000e+00", 12).to_float(); + BOOST_CHECK(r3.first==true); + BOOST_CHECK_CLOSE(Real(2.01), Real(r3.second), Real(1e-4)); + r3=StringRef("5e-34", 5).to_float(); + BOOST_CHECK(r3.first==true); + r3=StringRef("5E-34", 5).to_float(); + BOOST_CHECK(r3.first==true); + r3=StringRef("5.34e-34", 8).to_float(); + BOOST_CHECK(r3.first==true); + r3=StringRef("5.34e-34e", 9).to_float(); + BOOST_CHECK(r3.first==false); + r3=StringRef("5.34ee34", 8).to_float(); + BOOST_CHECK(r3.first==false); + r3=StringRef("5.34e--34e", 10).to_float(); + BOOST_CHECK(r3.first==false); + r3=StringRef("5.34e+3+4", 9).to_float(); + BOOST_CHECK(r3.first==false); + r3=StringRef("5.34e-+34e", 10).to_float(); + BOOST_CHECK(r3.first==false); + r3=StringRef("5.34e-3-4", 9).to_float(); + BOOST_CHECK(r3.first==false); } BOOST_AUTO_TEST_SUITE_END() diff --git a/modules/base/tests/test_stutil.py b/modules/base/tests/test_stutil.py index 6cc4570b5605b5eb47c7507e0d0aa7f942f66496..7d5b9f98f9790db63846bfaa934fafa7de1d891b 100644 --- a/modules/base/tests/test_stutil.py +++ b/modules/base/tests/test_stutil.py @@ -86,7 +86,5 @@ class TestStUtils(unittest.TestCase): (stutil.Correl(self.data3, self.data2), self.correl2) if __name__ == "__main__": - try: - unittest.main() - except Exception, e: - print e \ No newline at end of file + from ost import testutils + testutils.RunTests() \ No newline at end of file diff --git a/modules/base/tests/test_table.py b/modules/base/tests/test_table.py index 2baf48934eb8e58f5a0696b48792c9237059033d..7b6b3be222600a86e534eb12c1b3d02cfe1da654 100644 --- a/modules/base/tests/test_table.py +++ b/modules/base/tests/test_table.py @@ -10,20 +10,37 @@ from ost.table import * import ost HAS_NUMPY=True +HAS_SCIPY=True HAS_MPL=True +HAS_PIL=True try: import numpy as np except ImportError: HAS_NUMPY=False + print "Could not find numpy: ignoring some table class unit tests" +try: + import scipy.stats.mstats +except ImportError: + HAS_SCIPY=False + print "Could not find scipy.stats.mstats: ignoring some table class unit tests" + try: import matplotlib matplotlib.use('Agg') except ImportError: HAS_MPL=False + print "Could not find matplotlib: ignoring some table class unit tests" + +try: + import Image + import ImageChops +except ImportError: + HAS_PIL=False + print "Could not find python imagine library: ignoring some table class unit tests" class TestTable(unittest.TestCase): - + def setUp(self): ost.PushVerbosityLevel(3) @@ -45,9 +62,9 @@ class TestTable(unittest.TestCase): self.CompareColCount(tab, 3) self.CompareRowCount(tab, 0) self.CompareColTypes(tab, ['first','second', 'third'], 'sif') - tab.AddRow(['x',3, None], merge=None) - tab.AddRow(['foo',None, 2.2], merge=None) - tab.AddRow([None,9, 3.3], merge=None) + tab.AddRow(['x',3, None], overwrite=None) + tab.AddRow(['foo',None, 2.2], overwrite=None) + tab.AddRow([None,9, 3.3], overwrite=None) return tab def CompareRowCount(self, t, row_count): @@ -95,11 +112,18 @@ class TestTable(unittest.TestCase): ''' self.CompareRowCount(t, len(ref_data)) idx = t.GetColIndex(col_name) + col_type = t.col_types[idx] for i, (row, ref) in enumerate(zip(t.rows, ref_data)): - self.assertEqual(row[idx], - ref, - "data (%s) in col (%s), row (%i) different from expected value (%s)" \ - %(row[idx], col_name, i, ref)) + if (isinstance(ref, float) or isinstance(ref, int)) and (isinstance(row[idx], float) or isinstance(row[idx], int)): + self.assertAlmostEqual(row[idx], + ref, + msg="data (%s) in col (%s), row (%i) different from expected value (%s)" \ + %(row[idx], col_name, i, ref)) + else: + self.assertEqual(row[idx], + ref, + "data (%s) in col (%s), row (%i) different from expected value (%s)" \ + %(row[idx], col_name, i, ref)) def CompareColTypes(self, t, col_names, ref_types): ''' @@ -124,6 +148,17 @@ class TestTable(unittest.TestCase): "column type (%s) at column %i, different from reference col type (%s)" \ %(t.col_types[idx], idx, ref_type)) + def CompareImages(self, img1, img2): + ''' + Compares two images based on all pixel values. This function needs the + python imaging library (PIL) package. + ''' + if not HAS_PIL: + return + diff = ImageChops.difference(img1, img2) + self.assertEqual(diff.getbbox(),None) + + def testZip(self): tab=Table(['col1', 'col2', 'col3', 'col4'], 'sssi') tab.AddRow(['a', 'b', 'c', 1]) @@ -162,6 +197,14 @@ class TestTable(unittest.TestCase): self.CompareRowCount(tab, 0) self.assertRaises(ValueError, tab.GetColIndex, 'a') + def testGuessColumnType(self): + self.assertEqual(GuessColumnType(['1', '1.3', '2']), 'float') + self.assertEqual(GuessColumnType(['1', '1', '2']), 'int') + self.assertEqual(GuessColumnType(['NONE', '1', '1', '2']), 'int') + self.assertEqual(GuessColumnType(['NONE', '1', '1', '2']), 'int') + self.assertEqual(GuessColumnType(['NONE', '1', '1', 'a']), 'string') + self.assertEqual(GuessColumnType(['NONE', 'TRUE', 'False']), 'bool') + self.assertEqual(GuessColumnType(['NONE']), 'string') def testTableInitSingleColEmpty(self): ''' empty table with one float column: @@ -332,7 +375,7 @@ class TestTable(unittest.TestCase): tab = Table(['first'],'i') self.CompareColCount(tab, 1) self.CompareRowCount(tab, 0) - tab.AddRow([2], merge=None) + tab.AddRow([2], overwrite=None) self.CompareColCount(tab, 1) self.CompareRowCount(tab, 1) self.CompareColNames(tab, ['first']) @@ -351,7 +394,7 @@ class TestTable(unittest.TestCase): tab.AddCol('first', 'int') self.CompareColCount(tab, 1) self.CompareRowCount(tab, 0) - tab.AddRow([2], merge=None) + tab.AddRow([2], overwrite=None) self.CompareColCount(tab, 1) self.CompareRowCount(tab, 1) self.CompareColNames(tab, ['first']) @@ -371,7 +414,7 @@ class TestTable(unittest.TestCase): self.CompareColCount(tab, 2) self.CompareRowCount(tab, 0) self.CompareColTypes(tab, ['first','second'], 'si') - tab.AddRow(['x',3], merge=None) + tab.AddRow(['x',3], overwrite=None) self.CompareColCount(tab, 2) self.CompareRowCount(tab, 1) tab.AddCol('third', 'float', 3.141) @@ -398,9 +441,9 @@ class TestTable(unittest.TestCase): self.CompareColCount(tab, 3) self.CompareRowCount(tab, 0) self.CompareColTypes(tab, ['first','second', 'third'], 'sif') - tab.AddRow(['x',3, 1.0], merge=None) - tab.AddRow(['foo',6, 2.2], merge=None) - tab.AddRow(['bar',9, 3.3], merge=None) + tab.AddRow(['x',3, 1.0], overwrite=None) + tab.AddRow(['foo',6, 2.2], overwrite=None) + tab.AddRow(['bar',9, 3.3], overwrite=None) self.CompareColCount(tab, 3) self.CompareRowCount(tab, 3) self.CompareDataFromDict(tab, {'second': [3,6,9], 'first': ['x','foo','bar'], 'third': [1,2.2,3.3]}) @@ -423,9 +466,9 @@ class TestTable(unittest.TestCase): self.CompareColCount(tab, 3) self.CompareRowCount(tab, 0) self.CompareColTypes(tab, ['first','second', 'aaa'], 'sif') - tab.AddRow({'first':'x','second':3, 'aaa':1.0}, merge=None) - tab.AddRow({'aaa':2.2, 'second':6, 'first':'foo'}, merge=None) - tab.AddRow({'second':9, 'aaa':3.3, 'first':'bar'}, merge=None) + tab.AddRow({'first':'x','second':3, 'aaa':1.0}, overwrite=None) + tab.AddRow({'aaa':2.2, 'second':6, 'first':'foo'}, overwrite=None) + tab.AddRow({'second':9, 'aaa':3.3, 'first':'bar'}, overwrite=None) self.CompareColCount(tab, 3) self.CompareRowCount(tab, 3) self.CompareDataFromDict(tab, {'second': [3,6,9], 'first': ['x','foo','bar'], 'aaa': [1,2.2,3.3]}) @@ -447,9 +490,9 @@ class TestTable(unittest.TestCase): self.CompareColCount(tab, 1) self.CompareRowCount(tab, 0) self.CompareColTypes(tab, ['first'], 's') - tab.AddRow(['x'], merge=None) - tab.AddRow(['foo'], merge=None) - tab.AddRow(['bar'], merge=None) + tab.AddRow(['x'], overwrite=None) + tab.AddRow(['foo'], overwrite=None) + tab.AddRow(['bar'], overwrite=None) tab.AddCol('second', 'int') tab.AddCol('third', 'float', 3.141) self.CompareColCount(tab, 3) @@ -458,9 +501,9 @@ class TestTable(unittest.TestCase): 'first': ['x','foo','bar'], 'third': [3.141, 3.141, 3.141]}) - def testAddRowFromDictWithMerge(self): + def testAddRowFromDictWithOverwrite(self): ''' - add rows from dictionary with merge (i.e. overwrite third row with additional data) + add rows from dictionary with overwrite (i.e. overwrite third row with additional data) x foo bar ------------------ @@ -479,14 +522,14 @@ class TestTable(unittest.TestCase): self.CompareDataFromDict(tab, {'x': ['row1', 'row2', 'row3'], 'foo': [True, None, False], 'bar': [1, 2, None]}) - tab.AddRow({'x':'row3', 'bar':3}, merge='x') + tab.AddRow({'x':'row3', 'bar':3}, overwrite='x') self.CompareDataFromDict(tab, {'x': ['row1', 'row2', 'row3'], 'foo': [True, None, False], 'bar': [1, 2, 3]}) - def testAddRowFromListWithMerge(self): + def testAddRowFromListWithOverwrite(self): ''' - add rows from list with merge (i.e. overwrite third row with additional data) + add rows from list with overwrite (i.e. overwrite third row with additional data) x foo bar ------------------ @@ -506,7 +549,7 @@ class TestTable(unittest.TestCase): self.CompareDataFromDict(tab, {'x': ['row1', 'row2', 'row3'], 'foo': [True, None, False], 'bar': [1, 2, None]}) - tab.AddRow(['row3', True, 3], merge='x') + tab.AddRow(['row3', True, 3], overwrite='x') self.CompareDataFromDict(tab, {'x': ['row1', 'row2', 'row3'], 'foo': [True, None, True], 'bar': [1, 2, 3]}) @@ -677,21 +720,32 @@ class TestTable(unittest.TestCase): tab.Sort('third', '+') self.CompareDataFromDict(tab, {'first': [None,'foo','x'], 'second': [9,None,3], 'third': [3.3,2.2,None]}) - def testSaveLoadTable(self): + def testLoadTableOSTUnknownType(self): + self.assertRaises(ValueError, Table.Load, os.path.join('testfiles','ost-table-unknown-type.tab')) + + def testLoadTableOSTNoType(self): + tab = Table.Load(os.path.join('testfiles','ost-table-notype.tab')) + self.CompareDataFromDict(tab, {'first': ['x','foo',None], 'second': [3,None,9], 'third': [None,2.2,3.3]}) + + def testLoadOSTDifficultHeaders(self): + tab = Table.Load(os.path.join('testfiles','ost-table-difficult-headers.tab')) + self.assertEquals(tab.col_types, ['float','float','float','float','float']) + + def testSaveLoadTableOST(self): tab = self.CreateTestTable() self.CompareDataFromDict(tab, {'first': ['x','foo',None], 'second': [3,None,9], 'third': [None,2.2,3.3]}) # write to disc - tab.Save("saveloadtable_filename_out.csv") - out_stream = open("saveloadtable_stream_out.csv", 'w') + tab.Save("saveloadtable_filename_out.tab") + out_stream = open("saveloadtable_stream_out.tab", 'w') tab.Save(out_stream) out_stream.close() # read from disc - in_stream = open("saveloadtable_stream_out.csv", 'r') + in_stream = open("saveloadtable_stream_out.tab", 'r') tab_loaded_stream = Table.Load(in_stream) in_stream.close() - tab_loaded_fname = Table.Load('saveloadtable_filename_out.csv') + tab_loaded_fname = Table.Load('saveloadtable_filename_out.tab') # check content self.CompareDataFromDict(tab_loaded_stream, {'first': ['x','foo',None], 'second': [3,None,9], 'third': [None,2.2,3.3]}) @@ -699,10 +753,61 @@ class TestTable(unittest.TestCase): # check Errors for empty/non existing files self.assertRaises(IOError, Table.Load, 'nonexisting.file') - self.assertRaises(IOError, Table.Load, os.path.join('testfiles','emptytable.csv')) + self.assertRaises(IOError, Table.Load, os.path.join('testfiles','emptytable.tab')) in_stream = open(os.path.join('testfiles','emptytable.csv'), 'r') self.assertRaises(IOError, Table.Load, in_stream) + def testSaveLoadTableOSTWithSpaces(self): + tab = self.CreateTestTable() + tab.AddRow(['hello spaces',10, 10.1], overwrite=None) + self.CompareDataFromDict(tab, {'first': ['x','foo',None,'hello spaces'], 'second': [3,None,9,10], 'third': [None,2.2,3.3,10.1]}) + + # write to disc + tab.Save("saveloadtable_withspaces_filename_out.tab") + + # read from disc + tab_loaded_fname = Table.Load('saveloadtable_withspaces_filename_out.tab') + self.CompareDataFromDict(tab_loaded_fname, {'first': ['x','foo',None,'hello spaces'], 'second': [3,None,9,10], 'third': [None,2.2,3.3,10.1]}) + + def testSaveLoadTableCSV(self): + tab = self.CreateTestTable() + self.CompareDataFromDict(tab, {'first': ['x','foo',None], 'second': [3,None,9], 'third': [None,2.2,3.3]}) + + # write to disc + tab.Save("saveloadtable_filename_out.csv", format='csv') + out_stream = open("saveloadtable_stream_out.csv", 'w') + tab.Save(out_stream, format='csv') + out_stream.close() + + # read from disc + in_stream = open("saveloadtable_stream_out.csv", 'r') + tab_loaded_stream = Table.Load(in_stream, format='csv') + in_stream.close() + tab_loaded_fname = Table.Load('saveloadtable_filename_out.csv', format='csv') + + # check content + self.CompareDataFromDict(tab_loaded_stream, {'first': ['x','foo',None], 'second': [3,None,9], 'third': [None,2.2,3.3]}) + self.CompareDataFromDict(tab_loaded_fname, {'first': ['x','foo',None], 'second': [3,None,9], 'third': [None,2.2,3.3]}) + + def testSaveLoadTablePickle(self): + tab = self.CreateTestTable() + self.CompareDataFromDict(tab, {'first': ['x','foo',None], 'second': [3,None,9], 'third': [None,2.2,3.3]}) + # write to disc + tab.Save("saveloadtable_filename_out.pickle", format='pickle') + out_stream = open("saveloadtable_stream_out.pickle", 'wb') + tab.Save(out_stream, format='pickle') + out_stream.close() + + # read from disc + in_stream = open("saveloadtable_stream_out.pickle", 'rb') + tab_loaded_stream = Table.Load(in_stream, format='pickle') + in_stream.close() + tab_loaded_fname = Table.Load('saveloadtable_filename_out.pickle', format='pickle') + + # check content + self.CompareDataFromDict(tab_loaded_stream, {'first': ['x','foo',None], 'second': [3,None,9], 'third': [None,2.2,3.3]}) + self.CompareDataFromDict(tab_loaded_fname, {'first': ['x','foo',None], 'second': [3,None,9], 'third': [None,2.2,3.3]}) + def testMergeTable(self): ''' Merge the following two tables: @@ -816,42 +921,72 @@ class TestTable(unittest.TestCase): def testSumTable(self): tab = self.CreateTestTable() tab.AddCol('fourth','bool',[False,True,False]) + tab.AddCol('fifth','string',['foo','bar',None]) self.assertRaises(TypeError,tab.Sum,'first') self.assertEquals(tab.Sum('second'),12) self.assertAlmostEquals(tab.Sum('third'),5.5) - self.assertRaises(TypeError,tab.Sum,'fourth') - self.assertRaises(ValueError,tab.Sum,'fifth') + self.assertEquals(tab.Sum('fourth'),1) + self.assertRaises(TypeError,tab.Sum,'fifth') + self.assertRaises(ValueError,tab.Sum,'sixth') def testMedianTable(self): tab = self.CreateTestTable() tab.AddCol('fourth','bool',[False,True,False]) + tab.AddCol('fifth','string',['foo','bar',None]) self.assertRaises(TypeError,tab.Median,'first') self.assertEquals(tab.Median('second'),6.0) self.assertAlmostEquals(tab.Median('third'),2.75) - self.assertRaises(TypeError,tab.Median,'fourth') - self.assertRaises(ValueError,tab.Median,'fifth') + self.assertEquals(tab.Median('fourth'),False) + self.assertRaises(TypeError,tab.Median,'fifth') + self.assertRaises(ValueError,tab.Median,'sixth') def testMeanTable(self): tab = self.CreateTestTable() tab.AddCol('fourth','bool',[False,True,False]) + tab.AddCol('fifth','string',['foo','bar',None]) self.assertRaises(TypeError,tab.Mean,'first') self.assertAlmostEquals(tab.Mean('second'),6.0) self.assertAlmostEquals(tab.Mean('third'),2.75) - self.assertRaises(TypeError,tab.Mean,'fourth') - self.assertRaises(ValueError,tab.Mean,'fifth') + self.assertAlmostEquals(tab.Mean('fourth'),0.33333333) + self.assertRaises(TypeError,tab.Mean,'fifth') + self.assertRaises(ValueError,tab.Mean,'sixth') + + def testRowMeanTable(self): + ''' + first second third fourth + ----------------------------- + x 3 NA 1 + foo NA 2.200 2 + NA 9 3.300 3 + NA NA NA NA + ''' + tab = self.CreateTestTable() + tab.AddCol('fourth','float',[1,2,3]) + tab.AddRow([None, None, None, None]) + + self.assertRaises(TypeError, tab.RowMean, 'mean', ['first', 'second']) + tab.RowMean('mean', ['third', 'second', 'fourth']) + self.CompareDataFromDict(tab, {'mean': [2,2.1,5.1,None], + 'first': ['x','foo',None,None], + 'second': [3,None,9,None], + 'third': [None,2.2,3.3,None], + 'fourth': [1,2,3,None]}) + def testStdDevTable(self): tab = self.CreateTestTable() tab.AddCol('fourth','bool',[False,True,False]) + tab.AddCol('fifth','string',['foo','bar',None]) self.assertRaises(TypeError,tab.StdDev,'first') self.assertAlmostEquals(tab.StdDev('second'),3.0) self.assertAlmostEquals(tab.StdDev('third'),0.55) - self.assertRaises(TypeError,tab.StdDev,'fourth') - self.assertRaises(ValueError,tab.StdDev,'fifth') + self.assertAlmostEquals(tab.StdDev('fourth'),0.47140452079) + self.assertRaises(TypeError,tab.StdDev,'fifth') + self.assertRaises(ValueError,tab.StdDev,'sixth') def testCountTable(self): tab = self.CreateTestTable() @@ -914,7 +1049,7 @@ class TestTable(unittest.TestCase): class_dir='y') def testPlotEnrichment(self): - if not HAS_MPL: + if not HAS_MPL or not HAS_PIL: return tab = Table(['score', 'rmsd', 'classific'], 'ffb', score=[2.64,1.11,2.17,0.45,0.15,0.85,1.13,2.90,0.50,1.03,1.46,2.83,1.15,2.04,0.67,1.27,2.22,1.90,0.68,0.36,1.04,2.46,0.91,0.60], @@ -923,7 +1058,11 @@ class TestTable(unittest.TestCase): pl = tab.PlotEnrichment(score_col='score', score_dir='-', class_col='rmsd', class_cutoff=2.0, - class_dir='-') + class_dir='-', + save=os.path.join("testfiles","enrichment-out.png")) + img1 = Image.open(os.path.join("testfiles","enrichment-out.png")) + #img2 = Image.open(os.path.join("testfiles","enrichment.png")) + #self.CompareImages(img1, img2) #pl.show() def testCalcEnrichmentAUC(self): @@ -940,7 +1079,121 @@ class TestTable(unittest.TestCase): class_dir='-') self.assertAlmostEquals(auc, auc_ref) - + + def testPlotROC(self): + if not HAS_MPL or not HAS_PIL: + return + tab = Table(['classific', 'score'], 'bf', + classific=[True, True, False, True, True, True, False, False, True, False, True, False, True, False, False, False, True, False, True, False], + score=[0.9, 0.8, 0.7, 0.6, 0.55, 0.54, 0.53, 0.52, 0.51, 0.505, 0.4, 0.39, 0.38, 0.37, 0.36, 0.35, 0.34, 0.33, 0.30, 0.1]) + pl = tab.PlotROC(score_col='score', score_dir='+', + class_col='classific', + save=os.path.join("testfiles","roc-out.png")) + img1 = Image.open(os.path.join("testfiles","roc-out.png")) + #img2 = Image.open(os.path.join("testfiles","roc.png")) + #self.CompareImages(img1, img2) + + # no true positives + tab = Table(['classific', 'score'], 'bf', + classific=[False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False], + score=[0.9, 0.8, 0.7, 0.6, 0.55, 0.54, 0.53, 0.52, 0.51, 0.505, 0.4, 0.39, 0.38, 0.37, 0.36, 0.35, 0.34, 0.33, 0.30, 0.1]) + pl = tab.PlotROC(score_col='score', score_dir='+', + class_col='classific', + save=os.path.join("testfiles","roc-out.png")) + self.assertEquals(pl, None) + + def testPlotROCSameValues(self): + if not HAS_MPL or not HAS_PIL: + return + tab = Table(['classific', 'score'], 'bf', + classific=[True, True, False, True, True, True, False, False, True, False, True, False, True, False, False, False, True, False, True, False], + score=[0.9, 0.8, 0.7, 0.7, 0.7, 0.7, 0.53, 0.52, 0.51, 0.505, 0.4, 0.4, 0.4, 0.4, 0.36, 0.35, 0.34, 0.33, 0.30, 0.1]) + pl = tab.PlotROC(score_col='score', score_dir='+', + class_col='classific', + save=os.path.join("testfiles","roc-same-val-out.png")) + img1 = Image.open(os.path.join("testfiles","roc-same-val-out.png")) + #img2 = Image.open(os.path.join("testfiles","roc-same-val.png")) + #self.CompareImages(img1, img2) + #pl.show() + + def testCalcROCAUC(self): + if not HAS_NUMPY: + return + auc_ref = 0.68 + tab = Table(['classific', 'score'], 'bf', + classific=[True, True, False, True, True, True, False, False, True, False, True, False, True, False, False, False, True, False, True, False], + score=[0.9, 0.8, 0.7, 0.6, 0.55, 0.54, 0.53, 0.52, 0.51, 0.505, 0.4, 0.39, 0.38, 0.37, 0.36, 0.35, 0.34, 0.33, 0.30, 0.1]) + auc = tab.ComputeROCAUC(score_col='score', score_dir='+', class_col='classific') + self.assertAlmostEquals(auc, auc_ref) + + # no true positives + tab = Table(['classific', 'score'], 'bf', + classific=[False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False], + score=[0.9, 0.8, 0.7, 0.6, 0.55, 0.54, 0.53, 0.52, 0.51, 0.505, 0.4, 0.39, 0.38, 0.37, 0.36, 0.35, 0.34, 0.33, 0.30, 0.1]) + auc = tab.ComputeROCAUC(score_col='score', score_dir='+', class_col='classific') + self.assertEquals(auc, None) + + def testCalcROCAUCWithCutoff(self): + if not HAS_NUMPY: + return + tab = Table(['classific', 'score'], 'ff', + classific=[0.9, 0.8, 0.7, 0.6, 0.55, 0.54, 0.53, 0.52, 0.51, 0.505, 0.4, 0.39, 0.38, 0.37, 0.36, 0.35, 0.34, 0.33, 0.30, 0.1], + score=[0.9, 0.8, 0.7, 0.6, 0.55, 0.54, 0.53, 0.52, 0.51, 0.505, 0.4, 0.39, 0.38, 0.37, 0.36, 0.35, 0.34, 0.33, 0.30, 0.1]) + auc = tab.ComputeROCAUC(score_col='score', class_col='classific', class_cutoff=0.5) + self.assertEquals(auc, 1.0) + + # no true positives + auc = tab.ComputeROCAUC(score_col='score', class_col='classific', class_cutoff=1.0) + self.assertEquals(auc, None) + + def testCalcROCFromFile(self): + tab = Table.Load(os.path.join('testfiles','roc_table.dat')) + auc = tab.ComputeROCAUC(score_col='prediction', class_col='reference', class_cutoff=0.4) + self.assertEquals(auc, 1.0) + + + def testCalcROCAUCSameValues(self): + if not HAS_NUMPY: + return + auc_ref = 0.685 + tab = Table(['classific', 'score'], 'bf', + classific=[True, True, False, True, True, True, False, False, True, False, True, False, True, False, False, False, True, False, True, False], + score=[0.9, 0.8, 0.7, 0.7, 0.7, 0.7, 0.53, 0.52, 0.51, 0.505, 0.4, 0.4, 0.4, 0.4, 0.36, 0.35, 0.34, 0.33, 0.30, 0.1]) + auc = tab.ComputeROCAUC(score_col='score', score_dir='+', class_col='classific') + self.assertAlmostEquals(auc, auc_ref) + + def testCalcMCC(self): + tab = Table(['score', 'rmsd', 'class_rmsd', 'class_score', 'class_wrong'], 'ffbbb', + score= [2.64, 1.11, 2.17, 0.45,0.15,0.85, 1.13, 2.90, 0.50, 1.03, 1.46, 2.83, 1.15, 2.04, 0.67, 1.27, 2.22, 1.90, 0.68, 0.36,1.04, 2.46, 0.91,0.60], + rmsd=[9.58,1.61,7.48,0.29,1.68,3.52,3.34,8.17,4.31,2.85,6.28,8.78,0.41,6.29,4.89,7.30,4.26,3.51,3.38,0.04,2.21,0.24,7.58,8.40], + class_rmsd= [False,True, False,True,True,False,False,False,False,False,False,False,True, False,False,False,False,False,False,True,False,True,False,False], + class_score=[False,False,False,True,True,True, False,False,True, False,False,False,False,False,True, False,False,False,True, True,False,False,True,True], + class_wrong=[False,False,False,False,False,False, False,False,False, False,False,False,False,False,False, False,False,False,False, False,False,False,False,False]) + + mcc = tab.ComputeMCC(score_col='score', score_dir='-', class_col='rmsd', class_dir='-', score_cutoff=1.0, class_cutoff=2.0) + self.assertAlmostEquals(mcc, 0.1490711984) + mcc = tab.ComputeMCC(score_col='class_score', class_col='class_rmsd') + self.assertAlmostEquals(mcc, 0.1490711984) + mcc = tab.ComputeMCC(score_col='score', score_dir='+', class_col='rmsd', class_dir='+', score_cutoff=1.0, class_cutoff=2.0) + self.assertAlmostEquals(mcc, 0.1490711984) + mcc = tab.ComputeMCC(score_col='score', score_dir='-', class_col='rmsd', class_dir='+', score_cutoff=1.0, class_cutoff=2.0) + self.assertAlmostEquals(mcc, -0.1490711984) + mcc = tab.ComputeMCC(score_col='score', score_dir='+', class_col='rmsd', class_dir='-', score_cutoff=1.0, class_cutoff=2.0) + self.assertAlmostEquals(mcc, -0.1490711984) + mcc = tab.ComputeMCC(score_col='class_wrong', class_col='class_rmsd') + self.assertEquals(mcc,None) + + + def testCalcMCCPreclassified(self): + tab = Table(['reference', 'prediction1', 'prediction2'],'bbb', + reference= [False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, True, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, True, False, True, False, False, True, False, False, True, False, False, False, False, False, False, False, False, False, False, True, False, False, True, False, False, False, False, False, False, False, False], + prediction1=[False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, True, False, True, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, True, False, False, True, False, True, False, False, False, False, False, False], + prediction2=[False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, True, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, True, False, True, False, False, True, False, True, True, False, False, False, False, False, False, False, False, False, False, True, False, False, True, False, False, False, True, False, False, False, False]) + mcc = tab.ComputeMCC(score_col='prediction1', class_col='reference') + self.assertAlmostEquals(mcc, 0.538389277) + mcc = tab.ComputeMCC(score_col='prediction2', class_col='reference') + self.assertAlmostEquals(mcc, 0.882089673321) + def testTableAsNumpyMatrix(self): ''' @@ -1057,9 +1310,131 @@ class TestTable(unittest.TestCase): self.assertFalse(tab.IsEmpty('a', ignore_nan=False)) self.assertFalse(tab.IsEmpty('b', ignore_nan=False)) self.assertFalse(tab.IsEmpty('c', ignore_nan=False)) - + + def testUnique(self): + tab = self.CreateTestTable() + tab.AddRow(['foo',4, 3.3]) + tab.AddRow([None,5, 6.3]) + self.assertEquals(tab.GetUnique('first'), ['x','foo']) + self.assertEquals(tab.GetUnique('first', ignore_nan=False), ['x','foo', None]) + self.assertEquals(tab.GetUnique('second'), [3,9,4,5]) + self.assertEquals(tab.GetUnique('second', ignore_nan=False), [3,None,9,4,5]) + self.assertEquals(tab.GetUnique('third'), [2.2, 3.3, 6.3]) + self.assertEquals(tab.GetUnique('third', ignore_nan=False), [None, 2.2, 3.3, 6.3]) + + def testCorrel(self): + tab = self.CreateTestTable() + self.assertEquals(tab.Correl('second','third'), None) + tab.AddRow(['foo',4, 3.3]) + tab.AddRow([None,5, 6.3]) + tab.AddRow([None,8, 2]) + self.assertAlmostEquals(tab.Correl('second','third'), -0.4954982578) + + def testSpearmanCorrel(self): + if not HAS_SCIPY: + return + tab = self.CreateTestTable() + self.assertEquals(tab.SpearmanCorrel('second','third'), None) + tab.AddRow(['foo',4, 3.3]) + tab.AddRow([None,5, 6.3]) + tab.AddRow([None,8, 2]) + self.assertAlmostEquals(tab.SpearmanCorrel('second','third'), -0.316227766) + + def testExtend(self): + ''' + first second third + ---------------------- + x 3 NA + foo NA 2.200 + NA 9 3.300 + ''' + + # simple extend of the same table + tab = self.CreateTestTable() + self.CompareDataFromDict(tab, {'first': ['x','foo',None], + 'second': [3,None,9], + 'third': [None,2.2,3.3]}) + + tab.Extend(tab) + self.CompareDataFromDict(tab, {'first': ['x','foo',None,'x','foo',None], + 'second': [3,None,9,3,None,9], + 'third': [None,2.2,3.3,None,2.2,3.3]}) + + # simple extend of different tables with the same data + tab = self.CreateTestTable() + tab2 = self.CreateTestTable() + tab.Extend(tab2) + self.CompareDataFromDict(tab, {'first': ['x','foo',None,'x','foo',None], + 'second': [3,None,9,3,None,9], + 'third': [None,2.2,3.3,None,2.2,3.3]}) + self.CompareDataFromDict(tab2, {'first': ['x','foo',None], + 'second': [3,None,9], + 'third': [None,2.2,3.3]}) + + # add additional columns to current table + tab = self.CreateTestTable() + tab2 = self.CreateTestTable() + tab2.AddCol('foo','i',[1,2,3]) + tab.Extend(tab2) + self.CompareDataFromDict(tab, {'first': ['x','foo',None,'x','foo',None], + 'second': [3,None,9,3,None,9], + 'third': [None,2.2,3.3,None,2.2,3.3], + 'foo': [None,None,None,1,2,3]}) + + # different order of the data + tab = self.CreateTestTable() + tab2 = Table(['third','second','first'], + 'fis', + third=[None,2.2,3.3], + first=['x','foo',None], + second=[3, None, 9]) + self.CompareDataFromDict(tab2, {'first': ['x','foo',None], + 'second': [3,None,9], + 'third': [None,2.2,3.3]}) + tab.Extend(tab2) + self.CompareDataFromDict(tab, {'first': ['x','foo',None,'x','foo',None], + 'second': [3,None,9,3,None,9], + 'third': [None,2.2,3.3,None,2.2,3.3]}) + + # with overwrite (additional column) + tab = self.CreateTestTable() + tab2 = self.CreateTestTable() + tab2.AddCol('foo','i',[1,2,3]) + tab.Extend(tab2, overwrite='first') + self.CompareDataFromDict(tab, {'first': ['x','foo',None], + 'second': [3,None,9], + 'third': [None,2.2,3.3], + 'foo': [1,2,3]}) + + # with overwrite (no matching value) + tab = self.CreateTestTable() + tab2 = Table(['third','second','first'], + 'fis', + third=[None,2.2,3.3], + first=['a','bar','bla'], + second=[3, None, 9]) + tab.Extend(tab2, overwrite='first') + self.CompareDataFromDict(tab, {'first': ['x','foo',None,'a','bar','bla'], + 'second': [3,None,9,3,None,9], + 'third': [None,2.2,3.3,None,2.2,3.3]}) + + # with overwrite (with matching values) + tab = self.CreateTestTable() + tab2 = Table(['third','second','first'], + 'fis', + third=[None,2.2,3.4], + first=['a','bar','bla'], + second=[3, None, 9]) + tab.Extend(tab2, overwrite='third') + self.CompareDataFromDict(tab, {'first': ['a','bar',None,'bla'], + 'second': [3,None,9,9], + 'third': [None,2.2,3.3,3.4]}) + + # cannot extend if types are different + tab = Table('aaa','s',a=['a','b']) + tab2 = Table('aaa','i',a=[1,2]) + self.assertRaises(TypeError, tab.Extend, tab2) + if __name__ == "__main__": - try: - unittest.main() - except Exception, e: - print e + from ost import testutils + testutils.RunTests() diff --git a/modules/base/tests/testfiles/enrichment.png b/modules/base/tests/testfiles/enrichment.png new file mode 100644 index 0000000000000000000000000000000000000000..6fa5157f913a556a3d27eccf63479d92f4eb806d Binary files /dev/null and b/modules/base/tests/testfiles/enrichment.png differ diff --git a/modules/base/tests/testfiles/ost-table-difficult-headers.tab b/modules/base/tests/testfiles/ost-table-difficult-headers.tab new file mode 100644 index 0000000000000000000000000000000000000000..792a25971450fa7150964dc540539b8a24cfaf49 --- /dev/null +++ b/modules/base/tests/testfiles/ost-table-difficult-headers.tab @@ -0,0 +1,8 @@ +cut-off[float] a_sangle[float] smoo:thing[float] 3O89.pdb.gz[float] 3P0K;pdbgz[float] +1.0 20.0 0.0 0.5 0.5 +1.0 20.0 2.0 0.600685362782 0.774702862809 +1.0 20.0 4.0 0.749697277923 0.872928615954 +1.0 20.0 6.0 0.775949336433 0.864866900109 +1.0 20.0 8.0 0.673823016565 0.818450326527 +1.0 20.0 10.0 0.528419548581 0.779631093875 +1.0 20.0 12.0 0.463080015499 0.761846789747 diff --git a/modules/base/tests/testfiles/ost-table-notype.tab b/modules/base/tests/testfiles/ost-table-notype.tab new file mode 100644 index 0000000000000000000000000000000000000000..10f59019bc567304bf57520c2f6c0e8f99d308f4 --- /dev/null +++ b/modules/base/tests/testfiles/ost-table-notype.tab @@ -0,0 +1,4 @@ +first second[int] third[float] +x 3 NA +foo NA 2.2 +NA 9 3.3 diff --git a/modules/base/tests/testfiles/ost-table-unknown-type.tab b/modules/base/tests/testfiles/ost-table-unknown-type.tab new file mode 100644 index 0000000000000000000000000000000000000000..69c79442b33df285507c7f42845f73aa09663ed0 --- /dev/null +++ b/modules/base/tests/testfiles/ost-table-unknown-type.tab @@ -0,0 +1,4 @@ +first[unknown] second[int] third[float] +x 3 NA +foo NA 2.2 +NA 9 3.3 diff --git a/modules/base/tests/testfiles/roc-same-val.png b/modules/base/tests/testfiles/roc-same-val.png new file mode 100644 index 0000000000000000000000000000000000000000..b459c553da696100743b9b41dc09e8dcbeaef5a3 Binary files /dev/null and b/modules/base/tests/testfiles/roc-same-val.png differ diff --git a/modules/base/tests/testfiles/roc.png b/modules/base/tests/testfiles/roc.png new file mode 100644 index 0000000000000000000000000000000000000000..d02985dacd945e6dfc57301d99994b098c0879dd Binary files /dev/null and b/modules/base/tests/testfiles/roc.png differ diff --git a/modules/base/tests/testfiles/roc_table.dat b/modules/base/tests/testfiles/roc_table.dat new file mode 100644 index 0000000000000000000000000000000000000000..2de91a2691f99683a6f86658e6f71b136cc57a6d --- /dev/null +++ b/modules/base/tests/testfiles/roc_table.dat @@ -0,0 +1,152 @@ +rnum[int] reference[float] prediction[float] +1 0.0 0.0 +2 0.0 0.0 +3 0.0 0.0 +4 0.0 0.0 +5 0.2 0.2 +6 0.0 0.0 +7 0.0 0.0 +8 1.0 1.0 +9 0.2 0.2 +10 0.2 0.2 +11 0.2 0.2 +12 1.0 1.0 +13 0.0 0.0 +14 0.0 0.0 +15 0.0 0.0 +16 0.0 0.0 +17 0.0 0.0 +18 0.0 0.0 +19 0.0 0.0 +20 0.0 0.0 +21 0.0 0.0 +22 0.0 0.0 +23 0.0 0.0 +24 0.0 0.0 +25 0.0 0.0 +26 0.0 0.0 +27 0.0 0.0 +28 0.0 0.0 +29 0.0 0.0 +30 0.0 0.0 +31 0.0 0.0 +32 0.2 0.2 +33 0.0 0.0 +34 0.0 0.0 +35 0.0 0.0 +36 0.0 0.0 +37 0.0 0.0 +38 0.0 0.0 +39 0.0 0.0 +40 0.0 0.0 +41 0.0 0.0 +42 0.0 0.0 +43 0.0 0.0 +44 0.0 0.0 +45 0.0 0.0 +46 0.0 0.0 +47 0.0 0.0 +48 0.0 0.0 +49 0.0 0.0 +50 0.0 0.0 +51 0.0 0.0 +52 0.0 0.0 +53 0.0 0.0 +54 0.0 0.0 +55 0.0 0.0 +56 0.0 0.0 +57 0.0 0.0 +58 0.0 0.0 +59 0.0 0.0 +60 0.0 0.0 +61 0.0 0.0 +62 0.0 0.0 +63 0.0 0.0 +64 0.0 0.0 +65 0.0 0.0 +66 0.0 0.0 +67 0.0 0.0 +68 0.0 0.0 +69 0.0 0.0 +70 0.0 0.0 +71 0.2 0.2 +72 0.0 0.0 +73 0.2 0.2 +74 0.0 0.0 +75 0.0 0.0 +76 0.0 0.0 +77 0.0 0.0 +78 0.0 0.0 +79 0.0 0.0 +80 0.0 0.0 +81 0.0 0.0 +82 0.0 0.0 +83 0.0 0.0 +84 0.0 0.0 +85 0.0 0.0 +86 0.0 0.0 +87 0.0 0.0 +88 0.0 0.0 +89 0.0 0.0 +90 0.0 0.0 +91 0.2 0.2 +92 0.0 0.0 +93 0.0 0.0 +94 0.0 0.0 +95 0.0 0.0 +96 0.0 0.0 +97 0.0 0.0 +98 0.0 0.0 +99 0.0 0.0 +100 0.0 0.0 +101 0.0 0.0 +102 0.0 0.0 +103 0.2 0.2 +104 0.2 0.2 +105 0.5 0.5 +106 0.0 0.0 +107 0.0 0.0 +108 0.0 0.0 +109 0.0 0.0 +110 0.0 0.0 +111 0.2 0.2 +112 0.0 0.0 +113 0.5 0.5 +114 0.2 0.2 +115 1.0 1.0 +116 0.5 0.5 +117 0.5 0.5 +118 0.5 0.5 +119 1.0 1.0 +120 0.0 0.0 +121 0.0 0.0 +122 0.0 0.0 +123 0.0 0.0 +124 0.0 0.0 +125 0.0 0.0 +126 0.0 0.0 +127 0.0 0.0 +128 0.0 0.0 +129 0.0 0.0 +130 0.0 0.0 +131 0.0 0.0 +132 0.0 0.0 +133 0.0 0.0 +134 0.0 0.0 +135 0.0 0.0 +136 0.0 0.0 +137 0.0 0.0 +138 0.0 0.0 +139 0.0 0.0 +140 0.0 0.0 +141 0.0 0.0 +142 0.0 0.0 +143 0.0 0.0 +144 0.0 0.0 +145 0.0 0.0 +146 0.0 0.0 +147 0.0 0.0 +148 0.0 0.0 +149 0.0 0.0 +150 0.0 0.0 +151 0.0 0.0 diff --git a/modules/bindings/doc/bindings.rst b/modules/bindings/doc/bindings.rst index fc5357608c5a09becf40ba13b0ebed59fe634769..744f6059c6d736c6a2c2eaa57bdae979b9c7c286 100644 --- a/modules/bindings/doc/bindings.rst +++ b/modules/bindings/doc/bindings.rst @@ -17,3 +17,4 @@ So far, the binding module includes: blast msms tmtools + clustalw diff --git a/modules/bindings/doc/clustalw.rst b/modules/bindings/doc/clustalw.rst new file mode 100644 index 0000000000000000000000000000000000000000..a7f738d5e5e3a2fe71e48cb9a07874cc4078ded1 --- /dev/null +++ b/modules/bindings/doc/clustalw.rst @@ -0,0 +1,8 @@ +:mod:`~ost.bindings.clustalw` - Perform multiple sequence alignment +================================================================================ + +.. module:: ost.bindings.clustalw + :synopsis: Perform multiple sequence alignment + + +.. autofunction:: ost.bindings.clustalw.ClustalW diff --git a/modules/bindings/doc/dssp.rst b/modules/bindings/doc/dssp.rst index 61de495e34f920e85bc801800feb24c4ca5a3305..bb9d2b57b0f081bd0f6ec0d7b82e0ef9bcf59089 100644 --- a/modules/bindings/doc/dssp.rst +++ b/modules/bindings/doc/dssp.rst @@ -2,19 +2,22 @@ ================================================================================ .. module:: ost.bindings.dssp - :synopsis: Interface to the DSSP commandline utility + :synopsis: Interface to the DSSP command line utility Introduction -------------------------------------------------------------------------------- -DSSP is a program developed by Wolfgang Kabsch and Chris Sander to assign secondary structure states to protein structures. The assignment is based on hydrogen bonding patterns and geometric features. +DSSP is a program developed by Wolfgang Kabsch and Chris Sander to assign +secondary structure states to protein structures. The assignment is based on +hydrogen bonding patterns and geometric features. The program can be downloaded from `<http://swift.cmbi.ru.nl/gv/dssp/>`_. -Example +Examples -------------------------------------------------------------------------------- -The following example assigns secondary structure states to an entity by using the DSSP program. +The following example assigns secondary structure states to an entity by using +the DSSP program. .. code-block:: python @@ -23,9 +26,27 @@ The following example assigns secondary structure states to an entity by using t ent=io.LoadPDB('1ake.pdb') dssp.AssignDSSP(ent) + +Now we fetch structure information plus solvent accessibility for an entity +using the mmCIF interface. + + +.. code-block:: python + + from ost.bindings import dssp + ent=io.LoadMMCIF('1ake.cif') + dssp.AssignDSSP(ent, extract_burial_status=True) + for chain in ent.chains: + if chain.is_polypeptide: + for res in chain.residues: + print res.GetFloatProp('relative_solvent_accessibility') + + DSSP bindings Usage -------------------------------------------------------------------------------- .. autofunction:: ost.bindings.dssp.AssignDSSP .. autofunction:: ost.bindings.dssp.LoadDSSP + +.. LocalWords: dssp AssignDSSP ent GetFloatProp autofunction diff --git a/modules/bindings/doc/msms.rst b/modules/bindings/doc/msms.rst index 0085571c0a063b15bb78e7ecb6dded7a89ad24ef..d9ed150c26576990b22e7ad7005a5e28914aa701 100644 --- a/modules/bindings/doc/msms.rst +++ b/modules/bindings/doc/msms.rst @@ -6,6 +6,10 @@ .. autoclass:: ost.bindings.msms.MsmsProcessError +.. autofunction:: ost.bindings.msms.CalculateSurface + .. autofunction:: ost.bindings.msms.CalculateSurfaceArea -.. autofunction:: ost.bindings.msms.CalculateSurface +.. autofunction:: ost.bindings.msms.CalculateSurfaceVolume + +.. autofunction:: ost.bindings.msms.GetVersion \ No newline at end of file diff --git a/modules/bindings/pymod/blast.py b/modules/bindings/pymod/blast.py index 054bff58c0575848d08642a6f935c09c7912df98..8f14d64dc27f259c7bd7756d27c7d9313b5e6731 100644 --- a/modules/bindings/pymod/blast.py +++ b/modules/bindings/pymod/blast.py @@ -136,7 +136,8 @@ def Blast(query, database, gap_open=11, gap_ext=1, matrix='BLOSUM62', :type query: :class:`seq.ConstSequenceHandle` :param database: The filename of the sequence database. Make sure that - formatdb has been run on the database and the <database>.pin file exists. + formatdb has been run on the database and the <database>.pin or + <database>.pal file exists. :param matrix: The substitution matrix to be used. Must be one of 'BLOSUM45', 'BLOSUM62', 'BLOSUM80', 'PAM30', 'PAM70'. :param gap_open: Gap opening penalty. Note that only a subset of gap opening @@ -155,7 +156,7 @@ def Blast(query, database, gap_open=11, gap_ext=1, matrix='BLOSUM62', subst_mats=('BLOSUM45', 'BLOSUM62', 'BLOSUM80', 'PAM30', 'PAM70',) if matrix not in subst_mats: raise ValueError('matrix must be one of %s' % ', '.join(subst_mats)) - if not os.path.exists('%s.pin' % database): + if not os.path.exists('%s.pin' % database) and not os.path.exists('%s.pal' % database): raise IOError("Database %s does not exist" % database) blastall_exe=settings.Locate('blastall', explicit_file_name=blast_location) args=[blastall_exe, '-d', database, '-p', 'blastp', diff --git a/modules/bindings/pymod/clustalw.py b/modules/bindings/pymod/clustalw.py index 2c2fd6ebac5cf580dd1a259cb087a0ada9a127c4..0204cd8ccc9a51962ccbef257676341c43b4cd7c 100644 --- a/modules/bindings/pymod/clustalw.py +++ b/modules/bindings/pymod/clustalw.py @@ -5,6 +5,46 @@ import subprocess def ClustalW(seq1, seq2=None, clustalw=None, keep_files=False, nopgap=False, clustalw_option_string=False): + ''' + Runs a clustalw multiple sequence alignment. The results are returned as a + :class:`~ost.seq.AlignmentHandle` instance. + + There are two ways to use this function: + + - align exactly two sequences: + + :param seq1: sequence_one + :type seq1: :class:`~ost.seq.SequenceHandle` or :class:`str` + + :param seq2: sequence_two + :type seq2: :class:`~ost.seq.SequenceHandle` or :class:`str` + + The two sequences can be specified as two separate function parameters + (`seq1`, `seq2`). The type of both parameters can be either + :class:`~ost.seq.SequenceHandle` or :class:`str`, but must be the same for + both parameters. + + - align two or more sequences: + + :param seq1: sequence_list + :type seq1: :class:`~ost.seq.SequenceList` + + :param seq2: must be :class:`None` + + Two or more sequences can be specified by using a + :class:`~ost.seq.SequenceList`. It is then passed as the first function + parameter (`seq1`). The second parameter (`seq2`) must be :class:`None`. + + + :param clustalw: path to clustalw executable (used in :func:`~ost.settings.Locate`) + :type clustalw: :class:`str` + :param nopgap: turn residue-specific gaps off + :type nopgap: :class:`bool` + :param clustalw_option_string: additional clustalw flags (see http://toolkit.tuebingen.mpg.de/clustalw/help_params) + :type clustalw_option_string: :class:`str` + :param keep_files: do not delete temporary files + :type keep_files: :class:`bool` + ''' clustalw_path=settings.Locate(('clustalw', 'clustalw2'), explicit_file_name=clustalw) diff --git a/modules/bindings/pymod/dssp.py b/modules/bindings/pymod/dssp.py index 1cb1db3aa9b21ea17f29aa0348a32d4fc32d1c14..f27aa9db9405357a3221adffb190921092febad5 100644 --- a/modules/bindings/pymod/dssp.py +++ b/modules/bindings/pymod/dssp.py @@ -88,7 +88,10 @@ def AssignDSSP(ent, pdb_path="", extract_burial_status=False, tmp_dir=None, :param ent: The entity for which the secondary structure should be calculated :type ent: :class:`~ost.mol.EntityHandle` or :class:`~ost.mol.EntityView` - :param extract_burial_status: If true, also extract burial status + :param extract_burial_status: If true, also extract burial status and store + as float-property + ``relative_solvent_accessibility`` at residue + level :param tmp_dir: If set, overrides the default tmp directory of the operating system :param dssp_bin: The path to the DSSP executable diff --git a/modules/bindings/pymod/msms.py b/modules/bindings/pymod/msms.py index fc50ff1c7b8081f1774d62fc36712bfb8487b4e7..60009f6070d2592ed6790521359a82684771f647 100644 --- a/modules/bindings/pymod/msms.py +++ b/modules/bindings/pymod/msms.py @@ -100,7 +100,7 @@ def _SetupFiles(entity, selection): return (tmp_dir_name, tmp_file_name) -def _ParseAreaFile(entity,file, asa_prop, esa_prop): +def _ParseAreaFile(entity, selection, file, asa_prop, esa_prop): """ Reads Area file (-af) and attach sasa and sesa per atom to an entitiy @@ -111,16 +111,17 @@ def _ParseAreaFile(entity,file, asa_prop, esa_prop): :param esa_prop: Name of the float property for SESA :raises: :class:`RuntimeError` if number of atoms in file != number of atoms in entity """ + view=entity.Select(selection) area_fh = open(file) area_lines = area_fh.readlines() area_fh.close() # shift first line area_lines = area_lines[1:] - if entity.GetAtomCount() != len(area_lines): - raise RuntimeError, "Atom count (%d) unequeal to number of atoms in area file (%d)" % (entity.GetAtomCount(), len(area_lines)) + if view.GetAtomCount() != len(area_lines): + raise RuntimeError, "Atom count (%d) unequeal to number of atoms in area file (%d)" % (view.GetAtomCount(), len(area_lines)) for l in area_lines: atom_no, sesa, sasa = l.split() - a = entity.atoms[int(atom_no)] + a = view.atoms[int(atom_no)] if asa_prop: a.SetFloatProp(asa_prop, float(sasa)) if esa_prop: @@ -218,14 +219,14 @@ def CalculateSurfaceArea(entity, density=1.0, radius=1.5, all_surf=False, (msms_executable, msms_data_file, msms_data_file, density, radius) if all_surf: command+=" -all" - if attach_asa != None: + if attach_asa != None or attach_esa != None: command+=" -af %s" % os.path.join(msms_data_dir, "asa_atom") # run msms stdout_value=_RunMSMS(command) # add sesa and asa to entity if attach_asa is specified - if attach_asa != None: - _ParseAreaFile(entity, os.path.join(msms_data_dir, "asa_atom.area"), + if attach_asa != None or attach_esa != None: + _ParseAreaFile(entity, selection, os.path.join(msms_data_dir, "asa_atom.area"), attach_asa, attach_esa) # parse MSMS output @@ -248,6 +249,84 @@ def CalculateSurfaceArea(entity, density=1.0, radius=1.5, all_surf=False, return (msms_ases, msms_asas) +def CalculateSurfaceVolume(entity, density=1.0, radius=1.5, all_surf=False, + no_hydrogens=False, no_hetatoms=False, no_waters=False, + selection='', + msms_exe=None, msms_env=None, keep_files=False, + attach_asa=None, attach_esa=None): + """ + Calculates the volume of the solvent excluded surface by using the external MSMS program. + + This method calculates the volume of the molecular surface by invoking the external + program MSMS. First, it is checked if the MSMS executable is present, then, + the necessary files are prepared in a temporary directory and MSMS is + executed. The last step is to remove the temporary directory. + + + :param entity: OST entity to calculate surface + :param density: Surface point density + :param radius: Surface probe radius + :param all_surf: Calculate surface area for all cavities (returns multiple + surfaces areas as a list) + :param no_hydrogens: Calculate surface only for hevy atoms + :param selection: Calculate surface for subset of entity + :param msms_exe: msms executable (full path to executable) + :param msms_env: msms environment variable + :param keep_files: Do not delete temporary files + :param attach_asa: Attaches per atom SASA to specified FloatProp at atom level + :param attach_esa: Attaches per atom SESA to specified FloatProp at atom level + :returns: Tuple of lists for (SES, SAS) + """ + import re + + # check if msms executable is specified + msms_executable=_GetExecutable(msms_exe, msms_env) + + # parse selection + if no_hydrogens: + if selection!='': + selection+=" and " + selection+="ele!=H" + + if no_hetatoms: + if selection!='': + selection+=" and " + selection+="ishetatm=False" + + if no_waters: + if selection!='': + selection+=" and " + selection+="rname!=HOH" + + # setup files for msms + (msms_data_dir, msms_data_file)=_SetupFiles(entity, selection) + + # set command line + command="%s -if %s -of %s -density %s -probe_radius %s " % \ + (msms_executable, msms_data_file, msms_data_file, density, radius) + if all_surf: + command+=" -all" + if attach_asa != None or attach_esa != None: + command+=" -af %s" % os.path.join(msms_data_dir, "asa_atom") + # run msms + stdout_value=_RunMSMS(command) + + # add sesa and asa to entity if attach_asa is specified + if attach_asa != None or attach_esa != None: + _ParseAreaFile(entity, selection, os.path.join(msms_data_dir, "asa_atom.area"), + attach_asa, attach_esa) + + # parse MSMS output + ses_volume=0 + for line in stdout_value.splitlines(): + if re.match(' Total ses_volume:', line): + ses_volume=float(line.split(':')[1]) + + # clean up + if not keep_files: + _CleanupFiles(msms_data_dir) + + return ses_volume def CalculateSurface(entity, density=1.0, radius=1.5, all_surf=False, @@ -269,7 +348,7 @@ def CalculateSurface(entity, density=1.0, radius=1.5, all_surf=False, :param radius: Surface probe radius :param all_surf: Calculate surface for all cavities (returns multiple surfaces as a list) - :param no_hydrogens: Calculate surface only for hevy atoms + :param no_hydrogens: Calculate surface only for heavy atoms :param selection: Calculate surface for subset of entity :param msms_exe: msms executable (full path to executable) :param msms_env: msms environment variable diff --git a/modules/bindings/pymod/tmtools.py b/modules/bindings/pymod/tmtools.py index 2f53fcb350285d907f945c17ef47fb71b8e34079..3c53b9975db978068aaa4397fca2f2e34be74813 100644 --- a/modules/bindings/pymod/tmtools.py +++ b/modules/bindings/pymod/tmtools.py @@ -34,8 +34,17 @@ from ost import settings, io, geom, seq def _SetupFiles(models): # create temporary directory tmp_dir_name=tempfile.mkdtemp() + dia = 'PDB' for index, model in enumerate(models): - io.SavePDB(model, os.path.join(tmp_dir_name, 'model%02d.pdb' % (index+1))) + for chain in model.chains: + if len(chain.name) > 1: + dia = 'CHARMM' + break; + for res in chain.residues: + if len(res.name) > 3: + dia = 'CHARMM' + break; + io.SavePDB(model, os.path.join(tmp_dir_name, 'model%02d.pdb' % (index+1)), dialect=dia) return tmp_dir_name def _CleanupFiles(dir_name): diff --git a/modules/bindings/tests/test_blast.py b/modules/bindings/tests/test_blast.py index e8e151a4ec4a325658df4cee69c4b8d0b30feb47..8b4215faa45d71660a7799f3211885f519745a56 100644 --- a/modules/bindings/tests/test_blast.py +++ b/modules/bindings/tests/test_blast.py @@ -44,7 +44,5 @@ if __name__ == "__main__": except(settings.FileNotFound): print "Could not find blastall executable: ignoring unit tests" sys.exit(0) - try: - unittest.main() - except Exception, e: - print e + from ost import testutils + testutils.RunTests() diff --git a/modules/bindings/tests/test_clustalw.py b/modules/bindings/tests/test_clustalw.py index 0fdb040db2b59f1a1a216a520059fb9d0f3faada..fa5a5e6b5eb44cbe11a0a11a68dc93d7d64cf123 100644 --- a/modules/bindings/tests/test_clustalw.py +++ b/modules/bindings/tests/test_clustalw.py @@ -68,7 +68,5 @@ if __name__ == "__main__": except(settings.FileNotFound): print "Could not find clustalw executable: ignoring unit tests" sys.exit(0) - try: - unittest.main() - except Exception, e: - print e + from ost import testutils + testutils.RunTests() diff --git a/modules/bindings/tests/test_msms.py b/modules/bindings/tests/test_msms.py index 054a63cffa472d01fbef5d5cd20289cd0a409fb6..9041f94fab817441da03ae794fe63d793ad7d208 100755 --- a/modules/bindings/tests/test_msms.py +++ b/modules/bindings/tests/test_msms.py @@ -42,7 +42,5 @@ if __name__ == "__main__": version = msms.GetVersion(msms_exe=None, msms_env='MSMSSERVER') if version!=VERSION_REQUIRED: print "MSMS version (%s) does not match required version %s: ignoring unit tests"%(version, VERSION_REQUIRED) - try: - unittest.main() - except Exception, e: - print e + from ost import testutils + testutils.RunTests() diff --git a/modules/config/CMakeLists.txt b/modules/config/CMakeLists.txt index 617aa51c5b87a2dc03b95d7a92730b097b31d371..1e637d14470c6aa77af76cdd6c58e5ad5561c180 100644 --- a/modules/config/CMakeLists.txt +++ b/modules/config/CMakeLists.txt @@ -21,7 +21,6 @@ if (USE_NUMPY) else() set(numpy_support 0) endif() - if (PROFILE) set(profiling_enabled 1) else() @@ -62,6 +61,11 @@ if (_DEBIAN_STYLE_LIBEXEC) else() set(debian_style_libexec 0) endif() +if (ENABLE_INFO) + set(info_enabled 1) +else() + set(info_enabled 0) +endif() set(config_hh_generator "CMake") set(CONFIG_HH_FILE "${CMAKE_CURRENT_SOURCE_DIR}/config.hh") diff --git a/modules/config/config.hh.in b/modules/config/config.hh.in index a9e33adca707baed39710d3c75f63ca2b210bf0b..c2242500ee2e528294c5beb77a5c650f9adfe288 100644 --- a/modules/config/config.hh.in +++ b/modules/config/config.hh.in @@ -33,5 +33,6 @@ #define OST_FFT_USE_THREADS @fftw_use_threads@ #define OST_NUMPY_SUPPORT_ENABLED @numpy_support@ #define OST_DEBIAN_STYLE_LIBEXEC @debian_style_libexec@ +#define OST_INFO_ENABLED @info_enabled@ #endif diff --git a/modules/conop/doc/cleanup.rst b/modules/conop/doc/cleanup.rst new file mode 100644 index 0000000000000000000000000000000000000000..35b20e5705b248a995ec61c5e06604c53df0767f --- /dev/null +++ b/modules/conop/doc/cleanup.rst @@ -0,0 +1,8 @@ +:mod:`conop.cleanup <ost.conop.cleanup>` -- Sanitize structures +================================================================================ + +.. module:: ost.conop.ceanup + :synopsis: Contains functions to sanitize (cleanup) structures by using + information from the compound library. + +.. autofunction:: ost.conop.cleanup.Cleanup \ No newline at end of file diff --git a/modules/conop/doc/conop.rst b/modules/conop/doc/conop.rst index 8c3f413469872a1d95f9da98e37f4e21ffb24bfc..fb72db2645a92ea70f3db4f686c0f33a35c7e956 100644 --- a/modules/conop/doc/conop.rst +++ b/modules/conop/doc/conop.rst @@ -20,3 +20,4 @@ In this module aminoacid connectivity compoundlib + cleanup \ No newline at end of file diff --git a/modules/conop/pymod/CMakeLists.txt b/modules/conop/pymod/CMakeLists.txt index 5affa4b457d780b7368b34a097bec832d2c3f36c..c1bf89d0e29cda36f4b4bcb9b0b357449aaa8ad7 100644 --- a/modules/conop/pymod/CMakeLists.txt +++ b/modules/conop/pymod/CMakeLists.txt @@ -4,7 +4,10 @@ set(OST_CONOP_PYMOD_SOURCES export_compound.cc export_amino_acids.cc export_conop.cc + export_non_standard.cc export_ring_finder.cc ) -pymod(NAME conop CPP ${OST_CONOP_PYMOD_SOURCES} PY __init__.py) \ No newline at end of file +if (NOT ENABLE_STATIC) + pymod(NAME conop CPP ${OST_CONOP_PYMOD_SOURCES} PY __init__.py cleanup.py) +endif() diff --git a/modules/conop/pymod/__init__.py b/modules/conop/pymod/__init__.py index 44aaed354facbf286933d5e2ff19dd89bf7544e1..a534ea808bf883c616c7eb7165af5b71155fdc5b 100644 --- a/modules/conop/pymod/__init__.py +++ b/modules/conop/pymod/__init__.py @@ -18,6 +18,17 @@ #------------------------------------------------------------------------------ from _ost_conop import * +# The 20 standard amino acids in no particular order +STANDARD_AMINOACIDS=( + 'ALA', 'ARG', 'ASN', + 'ASP', 'GLN', 'GLU', + 'LYS', 'SER', 'CYS', + 'MET', 'TRP', 'TYR', + 'THR', 'VAL', 'ILE', + 'LEU', 'GLY', 'PRO', + 'HIS', 'PHE', +) + def ConnectAll(ent): ''' Uses the current default builder to connect the atoms of the entity, assign diff --git a/modules/conop/pymod/cleanup.py b/modules/conop/pymod/cleanup.py new file mode 100644 index 0000000000000000000000000000000000000000..9ecf9c7ef12b8bb4fce889a5fb8062aab2364eda --- /dev/null +++ b/modules/conop/pymod/cleanup.py @@ -0,0 +1,167 @@ +from ost import conop, mol + +def Cleanup(entity, strip_water=True, canonicalize=True, remove_ligands=True): + """ + This function returns a cleaned-up (simplified) version of the protein + structure. Different parameters affect the behaviour of the function. + + :param strip_water: Whether to remove water from the structure + :param canonicalize: Whether to strip off modifications of amino acids and map + them back to their parent standard amino acid, e.g. selenium methionine to + methionine.For more complex amino acids, where the relation between the + modified and the standard parent amino acid is not known, sidechain atoms + are removed. D-peptide-linking residues are completely removed as well. + :param remove_ligands: Whether to remove ligands from the structure + + :return: a cleaned version of the entity + """ + #setup + builder = conop.GetBuilder() + if not hasattr(builder, "compound_lib") : + raise RuntimeError( "Cannot cleanup structure, since the default builder doesn't use the compound library") + compound_lib = builder.compound_lib + clean_entity = entity.Copy() + ed = clean_entity.EditXCS() + #remove water residues + if strip_water: + _StripWater(clean_entity, ed) + #replace modified residues before removing ligands to avoid removing MSE and others + if canonicalize: + _CanonicalizeResidues(clean_entity, ed, compound_lib) + #remove all hetatoms that are not water + if remove_ligands: + _RemoveLigands(clean_entity, ed) + return clean_entity + + +def _StripWater(clean_entity, ed) : + """ + This function removes water residues from the structure + """ + for res in clean_entity.residues: + if res.IsValid(): + if res.chem_class == mol.WATER: + ed.DeleteResidue(res.handle) + ed.UpdateICS() + return + +def _RemoveLigands(clean_entity, ed) : + """ + This function removes ligands from the structure + """ + for res in clean_entity.residues: + if res.IsValid(): + #WHEN mmCIF WILL BE USED, CHANGE IsPeptideLinking() TO IsProtein() + if not res.IsPeptideLinking() and res.atoms[0].is_hetatom and res.chem_class != mol.WATER: + ed.DeleteResidue(res.handle) + ed.UpdateICS() + return + +def _CanonicalizeResidues(clean_entity, ed, compound_lib) : + """ + This function strips off modifications of amino acids and maps + them back to their parent standard amino acid, e.g. selenium methionine to + methionine.For more complex amino acids, where the relation between the + modified and the standard parent amino acid is not known, sidechain atoms + are removed. D-peptide-linking residues are completely removed as well. + """ + + for res in clean_entity.residues: + if res.IsValid() and res.IsPeptideLinking() : + parent_olc = res.one_letter_code + if parent_olc == "X" : + _DeleteSidechain(res, ed) + for atom in res.atoms: + atom.is_hetatom = False + else: + parent_tlc = conop.OneLetterCodeToResidueName(parent_olc) + parent_res = compound_lib.FindCompound(parent_tlc) + if not parent_res: + _DeleteSidechain(res, ed) + for atom in res.atoms: + atom.is_hetatom = False + print "Removing sidechain of %s, beacuse it has not been found in the compound library"% parent_tlc + else: + #collect atom's names + modif_atom_names = set([atom.name for atom in res.atoms + if atom.element != "H" and atom.element != "D" ]) + #if the res is the first or last take all the atoms from the parent res + if res.FindAtom("OXT").IsValid() : + parent_atom_names = set([atom.name for atom in parent_res.atom_specs + if atom.element != "H" and atom.element != "D" ]) + else: + parent_atom_names = set([atom.name for atom in parent_res.atom_specs + if atom.element != "H" and atom.element != "D" and not atom.is_leaving ]) + additional_parent_atoms = parent_atom_names - modif_atom_names + additional_modif_atoms = modif_atom_names - parent_atom_names + #WHEN mmCIF WILL BE USED, CHANGE IsPeptideLinking() TO IsProtein(), TO EXCLUDE LIGANDS FROM CANONICALISATION + if res.atoms[0].is_hetatom : + old_name = res.name + ed.RenameResidue(res, parent_tlc) + if additional_parent_atoms: + if additional_modif_atoms: + #replacement + _Replacement(res, ed, old_name) + else: + #deletion + _Deletion(res, ed) + elif additional_modif_atoms: + #addition + _Addition(res, ed, additional_modif_atoms) + else: + #unchanged, later check stereochemistry or H atoms + _Unchanged(res, ed) + #the res is a peptide but not a ligand (is a protein res) + else: + if additional_parent_atoms:# if the sidechain is incomplete + _DeleteSidechain(res, ed) + ed.UpdateICS() + return + +def _Replacement(res, ed, old_name) : + #TEMP ONLY MSE + if old_name == "MSE" : + for atom in res.atoms: + atom.is_hetatom = False + sel = res.FindAtom("SE") + if sel.IsValid() : + ed.InsertAtom( res, "SD", sel.pos, "S", sel.occupancy, sel.b_factor ) #S radius=~1;SE=~1.2 + ed.DeleteAtom( sel ) + else: + _DeleteSidechain(res, ed) + else: + _DeleteSidechain(res, ed) + return + +def _Deletion(res, ed) : + _DeleteSidechain(res, ed) + for atom in res.atoms : + atom.is_hetatom = False + return + +def _Addition(res, ed, additional_modif_atoms) : + for add_atom_name in additional_modif_atoms: + add_atom = res.FindAtom( add_atom_name ) + if add_atom.IsValid() : + ed.DeleteAtom( add_atom ) + for atom in res.atoms: + atom.is_hetatom = False + return + +def _Unchanged(res, ed) : + if res.chem_class == mol.D_PEPTIDE_LINKING: + ed.DeleteResidue(res) + else: + _DeleteSidechain(res, ed) + for atom in res.atoms : + atom.is_hetatom = False + return + +def _DeleteSidechain(res, ed) : + for atom in res.atoms: + if not atom.name in ['CA','CB','C','N','O']: + ed.DeleteAtom(atom) + return + +#visible functions +__all__ = [Cleanup] diff --git a/modules/conop/pymod/export_builder.cc b/modules/conop/pymod/export_builder.cc index 4bd468f36b23180c726f661f34a89227ee7168c0..1897983f90b7c4065316633db738732c0ba4b93f 100644 --- a/modules/conop/pymod/export_builder.cc +++ b/modules/conop/pymod/export_builder.cc @@ -36,6 +36,8 @@ void export_Builder() { .add_property("dialect", &Builder::GetDialect, &Builder::SetDialect) .add_property("strict_hydrogens", &Builder::GetStrictHydrogenMode, &Builder::SetStrictHydrogenMode) + .add_property("bond_feasibility_check", &Builder::GetBondFeasibilityCheck, + &Builder::SetBondFeasibilityCheck) .def("GetDialect", &Builder::GetDialect) .def("SetDialect", &Builder::SetDialect) .def("CompleteAtoms", &Builder::CompleteAtoms) @@ -48,6 +50,8 @@ void export_Builder() { .def("AssignTorsionsToResidue", &Builder::AssignTorsionsToResidue) .def("FillAtomProps", &Builder::FillAtomProps) .def("IsResidueComplete", &Builder::IsResidueComplete) + .def("SetBondFeasibilityFlag", &Builder::SetBondFeasibilityCheck) + .def("GetBondFeasibilityFlag", &Builder::GetBondFeasibilityCheck) ; class_<HeuristicBuilder, bases<Builder> >("HeuristicBuilder", init<>()) @@ -56,5 +60,6 @@ void export_Builder() { init<const CompoundLibPtr&>()) .add_property("compound_lib", &RuleBasedBuilder::GetCompoundLib) .def("GetUnknownAtoms", &RuleBasedBuilder::GetUnknownAtoms) + ; } diff --git a/modules/conop/pymod/export_compound.cc b/modules/conop/pymod/export_compound.cc index a2599acf43b004562cd20efd198456a9a577b10a..0b7e0dde8d24422a0758d91019aebf0d1252701b 100644 --- a/modules/conop/pymod/export_compound.cc +++ b/modules/conop/pymod/export_compound.cc @@ -57,11 +57,17 @@ char get_chemclass(CompoundPtr compound) return char(compound->GetChemClass()); } + void set_chemclass(CompoundPtr compound, char cc) { compound->SetChemClass(ChemClass(cc)); } +char get_chemtype(CompoundPtr compound) +{ + return char(compound->GetChemType()); +} + CompoundPtr find_compound(CompoundLibPtr comp_lib, const String& tlc, const String& dialect) { @@ -92,6 +98,7 @@ void export_Compound() { .def("IsPeptideLinking", &Compound::IsPeptideLinking) .add_property("chem_class", &get_chemclass, &set_chemclass) + .add_property("chem_type", &get_chemtype) .add_property("formula",make_function(&Compound::GetFormula, return_value_policy<copy_const_reference>()), &Compound::SetFormula) diff --git a/modules/conop/pymod/export_non_standard.cc b/modules/conop/pymod/export_non_standard.cc new file mode 100644 index 0000000000000000000000000000000000000000..025d2819a100584c85f3b088ce5320fdf02d0762 --- /dev/null +++ b/modules/conop/pymod/export_non_standard.cc @@ -0,0 +1,50 @@ +//------------------------------------------------------------------------------ +// This file is part of the OpenStructure project <www.openstructure.org> +// +// Copyright (C) 2008-2011 by the OpenStructure authors +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License as published by the Free +// Software Foundation; either version 3.0 of the License, or (at your option) +// any later version. +// This library is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this library; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +//------------------------------------------------------------------------------ +#include <boost/python.hpp> +#include <ost/mol/mol.hh> +#include <ost/conop/nonstandard.hh> + +using namespace boost::python; + +using namespace ost::conop; +using namespace ost::mol; + +object copy_conserved_handle(ResidueHandle src_res, ResidueHandle dst_res, + XCSEditor edi) { + bool has_cbeta = false; + bool ret = CopyConserved(src_res, dst_res, edi, has_cbeta); + return make_tuple(ret, has_cbeta); +} + +object copy_non_conserved_handle(ResidueHandle src_res, ResidueHandle dst_res, + XCSEditor edi) { + bool has_cbeta = false; + bool ret = CopyNonConserved(src_res, dst_res, edi, has_cbeta); + return make_tuple(ret, has_cbeta); +} + + + +void export_NonStandard() +{ + def("CopyNonConserved",©_non_conserved_handle); + def("CopyConserved", copy_conserved_handle); + def("CopyResidue", &CopyResidue); + } + diff --git a/modules/conop/pymod/wrap_conop.cc b/modules/conop/pymod/wrap_conop.cc index 2aba86654fb077bc42751b173a5185f22bb18ffc..6573bf41a7e6c8fcb471cbf25a79be77b1b03dfa 100644 --- a/modules/conop/pymod/wrap_conop.cc +++ b/modules/conop/pymod/wrap_conop.cc @@ -25,6 +25,8 @@ void export_Sanitizer(); void export_Conop(); void export_RingFinder(); void export_AminoAcids(); +void export_NonStandard(); + BOOST_PYTHON_MODULE(_ost_conop) { export_Builder(); @@ -32,4 +34,5 @@ BOOST_PYTHON_MODULE(_ost_conop) export_Compound(); export_RingFinder(); export_AminoAcids(); + export_NonStandard(); } diff --git a/modules/conop/src/CMakeLists.txt b/modules/conop/src/CMakeLists.txt index 127bd15ea7757eaaa50abeda7c7e07d3f295f3f0..344f5e00755d3ba733f1d6a877840037c8da802b 100644 --- a/modules/conop/src/CMakeLists.txt +++ b/modules/conop/src/CMakeLists.txt @@ -7,6 +7,7 @@ amino_acids.hh compound.hh compound_lib.hh module_config.hh +nonstandard.hh rule_based_builder.hh ring_finder.hh ) @@ -18,12 +19,13 @@ conop.cc heuristic_builder.cc compound.cc compound_lib.cc +nonstandard.cc rule_based_builder.cc ring_finder.cc ) module(NAME conop SOURCES ${OST_CONOP_SOURCES} - HEADERS ${OST_CONOP_HEADERS} DEPENDS_ON ost_mol ost_geom ost_db) + HEADERS ${OST_CONOP_HEADERS} DEPENDS_ON ost_mol ost_mol_alg ost_geom ost_db) executable(NAME chemdict_tool SOURCES chemdict_tool.cc DEPENDS_ON ost_io STATIC) diff --git a/modules/conop/src/builder.hh b/modules/conop/src/builder.hh index f912aba702cd075768da77c1c837f558877f3fda..4b915681a51d2d47c6d36fe449424f5b189de772 100644 --- a/modules/conop/src/builder.hh +++ b/modules/conop/src/builder.hh @@ -54,7 +54,7 @@ typedef enum { class DLLEXPORT_OST_CONOP Builder { public: - Builder(): dialect_(PDB_DIALECT), strict_(false) { } + Builder(): dialect_(PDB_DIALECT), strict_(false), bond_feasibility_check_(true) { } virtual ~Builder(); /// \brief add any missing atoms to the residue based on its key, @@ -143,9 +143,17 @@ public: /// |brief Connect \p atom with all atoms for whith IsBondFeasible() and /// AreResiduesConsecutive() returns true void DistanceBasedConnect(mol::AtomHandle atom); + + /// \brief Set bond feasibility check flag + void SetBondFeasibilityCheck(bool b_feas_flag) { bond_feasibility_check_ = b_feas_flag; } + + /// \brief Get bond feasibility check flag + bool GetBondFeasibilityCheck() const { return bond_feasibility_check_; } + private: Dialect dialect_; bool strict_; + bool bond_feasibility_check_; }; diff --git a/modules/conop/src/compound.hh b/modules/conop/src/compound.hh index d3f47bd973166a8bdc169729eef1be8db61a9d50..e33a7e38cfb840ebc5e5e050fbd7da55073e2c68 100644 --- a/modules/conop/src/compound.hh +++ b/modules/conop/src/compound.hh @@ -25,6 +25,7 @@ #include <ost/conop/module_config.hh> #include <ost/mol/chem_class.hh> +#include <ost/mol/chem_type.hh> namespace ost { namespace conop { @@ -120,7 +121,7 @@ public: } Dialect; Compound(const String& id) - : olc_('?'), tlc_(id), chem_class_(), dialect_(Compound::PDB) { + : olc_('?'), tlc_(id), chem_class_(), chem_type_(), dialect_(Compound::PDB){ } /// \brief three-letter code that is unique for every compound @@ -166,6 +167,18 @@ public: return chem_class_; } + void SetChemType(mol::ChemType chem_type) { + chem_type_=chem_type; + } + + /// \brief PDB ligand classification from component dictionary + /// + /// The PDB classifies all compounds into 7 categories. This classification + /// is extracted from the PDB component dictionary (field: pdbx_type) + mol::ChemType GetChemType() const { + return chem_type_; + } + bool IsPeptideLinking() const { return chem_class_.IsPeptideLinking(); } @@ -221,6 +234,7 @@ private: AtomSpecList atom_specs_; BondSpecList bond_specs_; mol::ChemClass chem_class_; + mol::ChemType chem_type_; Dialect dialect_; Date creation_date_; Date mod_date_; diff --git a/modules/conop/src/compound_lib.cc b/modules/conop/src/compound_lib.cc index c16c8505a8ca06f703d2d3c4cbf5263d0764c610..c05e60fb6d2ce72343e6ab44d637526c16639707 100644 --- a/modules/conop/src/compound_lib.cc +++ b/modules/conop/src/compound_lib.cc @@ -41,6 +41,7 @@ const char* CREATE_CMD[]={ " olc VARCHAR(1) NOT NULL, " " dialect VARCHAR(1) NOT NULL, " " chem_class VARCHAR(1), " +" chem_type VARCHAR(1), " " formula VARCHAR(64) NOT NULL, " " pdb_initial TIMESTAMP, " " pdb_modified TIMESTAMP " @@ -79,8 +80,8 @@ const char* CREATE_CMD[]={ const char* INSERT_COMPOUND_STATEMENT="INSERT INTO chem_compounds " -" (tlc, olc, dialect, chem_class, formula, pdb_initial, pdb_modified) " -" VALUES (?, ?, ?, ?, ?, DATE(?), DATE(?))"; +" (tlc, olc, dialect, chem_class, chem_type, formula, pdb_initial, pdb_modified) " +" VALUES (?, ?, ?, ?, ?, ?, DATE(?), DATE(?))"; const char* INSERT_ATOM_STATEMENT="INSERT INTO atoms " " (compound_id, name, alt_name, element, is_aromatic, stereo_conf, " @@ -106,11 +107,13 @@ void CompoundLib::AddCompound(const CompoundPtr& compound) compound->GetID().length(), NULL); char olc=compound->GetOneLetterCode(); sqlite3_bind_text(stmt, 2, &olc, 1, NULL); - char chem_type=compound->GetChemClass(); + char chem_class=compound->GetChemClass(); + char chem_type=compound->GetChemType(); char dialect=compound->GetDialect(); sqlite3_bind_text(stmt, 3, &dialect, 1, NULL); - sqlite3_bind_text(stmt, 4, &chem_type, 1, NULL); - sqlite3_bind_text(stmt, 5, compound->GetFormula().c_str(), + sqlite3_bind_text(stmt, 4, &chem_class, 1, NULL); + sqlite3_bind_text(stmt, 5, &chem_type, 1, NULL); + sqlite3_bind_text(stmt, 6, compound->GetFormula().c_str(), compound->GetFormula().length(), NULL); std::stringstream ss; ss << compound->GetCreationDate().year << "-" @@ -121,9 +124,9 @@ void CompoundLib::AddCompound(const CompoundPtr& compound) ss << compound->GetModificationDate().year << "-" << compound->GetModificationDate().month << "-" << compound->GetModificationDate().day; - sqlite3_bind_text(stmt, 6, date.c_str(), date.length(), NULL); + sqlite3_bind_text(stmt, 7, date.c_str(), date.length(), NULL); date=ss.str(); - sqlite3_bind_text(stmt, 7, date.c_str(), date.length(), NULL); + sqlite3_bind_text(stmt, 8, date.c_str(), date.length(), NULL); } else { LOG_ERROR(sqlite3_errmsg(conn_)); sqlite3_finalize(stmt); @@ -242,11 +245,18 @@ CompoundLibPtr CompoundLib::Load(const String& database, bool readonly) int flags=readonly ? SQLITE_OPEN_READONLY : SQLITE_OPEN_READWRITE; CompoundLibPtr lib(new CompoundLib); int retval=sqlite3_open_v2(database.c_str(), &lib->conn_, flags, NULL); - if (SQLITE_OK==retval) { - return lib; + if (SQLITE_OK!=retval) { + LOG_ERROR(sqlite3_errmsg(lib->conn_)); + return CompoundLibPtr(); } - LOG_ERROR(sqlite3_errmsg(lib->conn_)); - return CompoundLibPtr(); + // check if column chem_type exists in database + String aq="SELECT chem_type FROM chem_compounds LIMIT 1"; + sqlite3_stmt* stmt; + retval=sqlite3_prepare_v2(lib->conn_, aq.c_str(), + static_cast<int>(aq.length()), + &stmt, NULL); + lib->chem_type_available_ = retval==SQLITE_OK; + return lib; } void CompoundLib::LoadAtomsFromDB(CompoundPtr comp, int pk) { @@ -308,9 +318,12 @@ CompoundPtr CompoundLib::FindCompound(const String& id, if (i!=compound_cache_.end()) { return i->second; } - String query="SELECT id, tlc, olc, chem_class, dialect, formula " - " FROM chem_compounds" - " WHERE tlc='"+id+"' AND dialect='"+String(1, char(dialect))+"'"; + String query="SELECT id, tlc, olc, chem_class, dialect, formula"; + if(chem_type_available_) { + query+=", chem_type"; + } + query+=" FROM chem_compounds" + " WHERE tlc='"+id+"' AND dialect='"+String(1, char(dialect))+"'"; sqlite3_stmt* stmt; int retval=sqlite3_prepare_v2(conn_, query.c_str(), static_cast<int>(query.length()), @@ -330,6 +343,9 @@ CompoundPtr CompoundLib::FindCompound(const String& id, compound->SetDialect(Compound::Dialect(sqlite3_column_text(stmt, 4)[0])); const char* f=reinterpret_cast<const char*>(sqlite3_column_text(stmt, 5)); compound->SetFormula(f); + if(chem_type_available_) { + compound->SetChemType(mol::ChemType(sqlite3_column_text(stmt, 6)[0])); + } // Load atoms and bonds this->LoadAtomsFromDB(compound, pk); this->LoadBondsFromDB(compound, pk); @@ -348,7 +364,7 @@ CompoundPtr CompoundLib::FindCompound(const String& id, } CompoundLib::CompoundLib() - : conn_(NULL) { + : conn_(NULL), chem_type_available_(false) { } CompoundLib::~CompoundLib() { diff --git a/modules/conop/src/compound_lib.hh b/modules/conop/src/compound_lib.hh index 0db0f763768cdc2870a7289c942d5c4233c999df..a552c5aee7754aea6a6759911389a4931c3ec3d0 100644 --- a/modules/conop/src/compound_lib.hh +++ b/modules/conop/src/compound_lib.hh @@ -52,6 +52,7 @@ private: private: CompoundMap compound_cache_; sqlite3* conn_; + bool chem_type_available_; // weather pdbx_type is available in db }; }} diff --git a/modules/conop/src/heuristic_builder.cc b/modules/conop/src/heuristic_builder.cc index 89b8ad8e1720754b0941e8b1a7d8977e252c14fc..458370078ea9171766bee2013506a170d0ac869d 100644 --- a/modules/conop/src/heuristic_builder.cc +++ b/modules/conop/src/heuristic_builder.cc @@ -209,19 +209,36 @@ void HeuristicBuilder::ConnectivityFromAtomNames(const mol::ResidueHandle& res, << it2->GetName() << ") in connectivity table of " << res.GetKey() << "... "); int conn=centry.Check(it1->GetName(),it2->GetName()); - if (conn==1 && this->IsBondFeasible(*it1, *it2)) { - LOG_TRACE( "found"); - editor.Connect(*it1,*it2); - } else if(conn==2 && this->IsBondFeasible(*it2, *it1)) { - LOG_TRACE( "found (reversed)"); - editor.Connect(*it2,*it1); + if (conn==1) { + if (this->GetBondFeasibilityCheck()==false) { + LOG_TRACE( "found"); + editor.Connect(*it1,*it2); + } else { + if (this->IsBondFeasible(*it1, *it2)) { + LOG_TRACE( "found"); + editor.Connect(*it1,*it2); + } else { + LOG_TRACE( "not found"); + } + } + } else if (conn==2) { + if (this->GetBondFeasibilityCheck()==false) { + LOG_TRACE( "found (reversed)"); + editor.Connect(*it2,*it1); + } else { + if(this->IsBondFeasible(*it2, *it1)) { + LOG_TRACE( "found (reversed)"); + editor.Connect(*it2,*it1); + } + } } else { - LOG_TRACE( "not found"); + LOG_TRACE( "not found"); } } } else { unknown_atoms.push_back(*it1); - } + LOG_TRACE( "atom not found, pushing it to unknown atoms"); + } } } diff --git a/modules/conop/src/nonstandard.cc b/modules/conop/src/nonstandard.cc new file mode 100644 index 0000000000000000000000000000000000000000..5effd8d9014ca886d63bb50f5457cc487fa782f0 --- /dev/null +++ b/modules/conop/src/nonstandard.cc @@ -0,0 +1,265 @@ +//------------------------------------------------------------------------------ +// This file is part of the OpenStructure project <www.openstructure.org> +// +// Copyright (C) 2008-2011 by the OpenStructure authors +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License as published by the Free +// Software Foundation; either version 3.0 of the License, or (at your option) +// any later version. +// This library is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this library; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +//------------------------------------------------------------------------------ + +/* + Author: Marco Biasini, Juergen Haas + */ + +#include <ost/log.hh> +#include <ost/dyn_cast.hh> +#include <ost/conop/conop.hh> +#include <ost/mol/mol.hh> +#include <ost/mol/alg/construct_cbeta.hh> +#include <ost/conop/rule_based_builder.hh> +#include <ost/conop/compound_lib.hh> +#include "nonstandard.hh" +using namespace ost::mol; +using namespace ost; +using namespace ost::conop; + +namespace ost { namespace conop { + +namespace { + +bool CheckBackboneAtoms(ResidueHandle res) +{ + String atom_names[]={"N", "CA", "C", "O"}; + std::vector<String> missing; + for (int i =0; i<4; ++i) { + if (!res.FindAtom(atom_names[i])) { + missing.push_back(atom_names[i]); + } + } + if (!missing.empty()) { + std::stringstream ss; + ss << "residue " << res.GetQualifiedName() << " is missing atoms "; + for (std::vector<String>::const_iterator + i=missing.begin(), e=missing.end(); i!=e; ++i) { + if (i!=missing.begin()) { + ss << ", "; + } + ss << *i; + } + LOG_WARNING(ss.str()); + return false; + } + return true; +} + +bool CheckCalphaAtom(ResidueHandle res) +{ + String atom_names[]={"N", "CA", "C", "O"}; + std::vector<String> missing; + for (int i =0; i<4; ++i) { + if (!res.FindAtom(atom_names[i])) { + missing.push_back(atom_names[i]); + } + } + if (!res.FindAtom("CA")) { + LOG_WARNING("residue " << res.GetQualifiedName() << " is missing CA atom"); + return false; + } + return true; +} + +} + +bool CopyResidue(ResidueHandle src_res, ResidueHandle dst_res, XCSEditor& edi) +{ + bool has_cbeta = false; + bool ret; + if (src_res.GetName()==dst_res.GetName()) { + ret = CopyConserved(src_res, dst_res, edi, has_cbeta); + } else { + ret = CopyNonConserved(src_res, dst_res, edi, has_cbeta); + } + // insert Cbeta, unless dst residue is glycine. + if (!has_cbeta && dst_res.GetName()!="GLY") { + geom::Vec3 cbeta_pos=mol::alg::CBetaPosition(dst_res); + edi.InsertAtom(dst_res, "CB", cbeta_pos, "C"); + } + return ret; +} + +bool CopyConserved(ResidueHandle src_res, ResidueHandle dst_res, XCSEditor& edi, + bool& has_cbeta) +{ + // check if the residue name of dst and src are the same. In the easy + // case, the two residue names match and we just copy over all atoms. + // If they don't match, we are dealing with modified residues. + + //~ return copy_conserved(src_res, dst_res, edi, has_cbeta); + + if (dst_res.GetName()==src_res.GetName()) { + return CopyIdentical(src_res, dst_res, edi, has_cbeta); + } else if (src_res.GetName()=="MSE") { + return CopyMSE(src_res, dst_res, edi, has_cbeta); + } else { + return CopyModified(src_res, dst_res, edi, has_cbeta); + } +} + +bool CopyIdentical(ResidueHandle src_res, ResidueHandle dst_res, XCSEditor& edi, + bool& has_cbeta) +{ + //~ return copy_identical(); + AtomHandleList atoms=src_res.GetAtomList(); + for (AtomHandleList::const_iterator + a=atoms.begin(), e=atoms.end(); a!=e; ++a) { + if (a->GetName()=="CB") { + has_cbeta=true; + } + if (a->GetElement()=="D" || a->GetElement()=="H") { + continue; + } + edi.InsertAtom(dst_res, a->GetName(), a->GetPos(), a->GetElement(), + a->GetOccupancy(), a->GetBFactor()); + } + return true; +} + + +bool CopyMSE(ResidueHandle src_res, ResidueHandle dst_res, XCSEditor& edi, + bool& has_cbeta) +{ + // selenium methionine is easy. We copy all atoms and substitute the SE + // with SD + AtomHandleList atoms=src_res.GetAtomList(); + for (AtomHandleList::const_iterator + a=atoms.begin(), e=atoms.end(); a!=e; ++a) { + if (a->GetName()=="CB") { + has_cbeta=true; + } + if (a->GetElement()=="D" || a->GetElement()=="H") { + continue; + } + if (a->GetName()=="SE") { + edi.InsertAtom(dst_res, "SD", a->GetPos(), "S", + a->GetOccupancy(), a->GetBFactor()); + } else { + edi.InsertAtom(dst_res, a->GetName(), a->GetPos(), a->GetElement(), + a->GetOccupancy(), a->GetBFactor()); + } + } + return true; +} + +bool CopyModified(ResidueHandle src_res, ResidueHandle dst_res, + XCSEditor& edi, bool& has_cbeta) +{ + // FIXME: for now this functions ignores chirality changes of sidechain + // chiral atoms. To detect those changes, we would need to store the + // chirality of those centers in the compound library. + + // For now, this function just handles cases where the src_res contains + // additional atoms, but the dst_res doesn't contain any atoms the src_res + // doesn't have. If these two requirements are not met, we fall back to + // CopyNonConserved. + + // first let's get our hands on the component library + conop::BuilderP builder=conop::Conopology::Instance().GetBuilder("DEFAULT"); + conop::RuleBasedBuilderPtr rbb=dyn_cast<conop::RuleBasedBuilder>(builder); + conop::CompoundLibPtr comp_lib=rbb->GetCompoundLib(); + + CompoundPtr src_compound=comp_lib->FindCompound(src_res.GetName(), + Compound::PDB); + if (!src_compound) { + // OK, that's bad. Let's copy the backbone and be done with it! + return CopyNonConserved(src_res, dst_res, edi, has_cbeta); + } + // since dst_res is one of the 20 amino acids, we don't have to check for + // existence of the compound. We know it is there! + CompoundPtr dst_compound=comp_lib->FindCompound(dst_res.GetName(), + Compound::PDB); + std::set<String> dst_atoms; + std::set<String> src_atoms; + // to compare the atoms of dst_res with those of src_res, let's create two + // sets containing all heavy atoms. + for (AtomSpecList::const_iterator i=dst_compound->GetAtomSpecs().begin(), + e=dst_compound->GetAtomSpecs().end(); i!=e; ++i) { + if (i->element=="H" || i->element=="D") { + continue; + } + dst_atoms.insert(i->name); + } + for (AtomSpecList::const_iterator i=src_compound->GetAtomSpecs().begin(), + e=src_compound->GetAtomSpecs().end(); i!=e; ++i) { + if (i->element=="H" || i->element=="D") { + continue; + } + src_atoms.insert(i->name); + } + for (std::set<String>::const_iterator i=dst_atoms.begin(), + e=dst_atoms.end(); i!=e; ++i) { + if (src_atoms.find(*i)==src_atoms.end()) { + return CopyNonConserved(src_res, dst_res, edi, has_cbeta); + } + } + // Muahaha, all is good. Let's copy the atoms. Muahaha + AtomHandleList atoms=src_res.GetAtomList(); + for (AtomHandleList::const_iterator + a=atoms.begin(), e=atoms.end(); a!=e; ++a) { + if (a->GetName()=="CB") { + if (dst_res.GetName()=="GLY") { + continue; + } + has_cbeta=true; + } + if (a->GetElement()=="D" || a->GetElement()=="H") { + continue; + } + if (dst_atoms.find(a->GetName())==dst_atoms.end()) { + continue; + } + edi.InsertAtom(dst_res, a->GetName(), a->GetPos(), a->GetElement(), + a->GetOccupancy(), a->GetBFactor()); + } + return true; +} + + +bool CopyNonConserved(ResidueHandle src_res, ResidueHandle dst_res, + XCSEditor& edi, bool& has_cbeta) +{ + AtomHandleList atoms=src_res.GetAtomList(); + for (AtomHandleList::const_iterator + a=atoms.begin(), e=atoms.end(); a!=e; ++a) { + String name=a->GetName(); + if (name=="CA" || name=="N" || name=="C" || name=="O" || name=="CB") { + if (name=="CB") { + if (dst_res.GetName()=="GLY") { + continue; + } + has_cbeta=true; + } + if (a->GetElement()=="D" || a->GetElement()=="H") { + continue; + } + edi.InsertAtom(dst_res, a->GetName(), a->GetPos(), a->GetElement(), + a->GetOccupancy(), a->GetBFactor()); + } + } + return false; +} + + + + + +}} diff --git a/modules/conop/src/nonstandard.hh b/modules/conop/src/nonstandard.hh new file mode 100644 index 0000000000000000000000000000000000000000..f8ad1cfa33d07b8d4c51db0b9019de340a882163 --- /dev/null +++ b/modules/conop/src/nonstandard.hh @@ -0,0 +1,97 @@ +//------------------------------------------------------------------------------ +// This file is part of the OpenStructure project <www.openstructure.org> +// +// Copyright (C) 2008-2011 by the OpenStructure authors +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License as published by the Free +// Software Foundation; either version 3.0 of the License, or (at your option) +// any later version. +// This library is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this library; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +//------------------------------------------------------------------------------ + +#ifndef OST_CONOP_NONSTANDARD_HH +#define OST_CONOP_NONSTANDARD_HH +/* + Author: Marco Biasini, Juergen Haas + */ +#include "module_config.hh" + + + + +namespace ost { namespace conop { + + +/// \brief copies all atom of src_res to dst_res +/// \param has_cbeta will be set to true if the src_res has a cbeta and the +/// dst_residue is not a glycine, it will be inserted if in the dst should +/// be one and in src it was not present + + +bool DLLEXPORT_OST_CONOP CopyResidue(ost::mol::ResidueHandle src_res, + ost::mol::ResidueHandle dst_res, + ost::mol::XCSEditor& edi); + +/// \brief copies all atom of src_res to dst_res +/// \param has_cbeta will be set to true if the src_res has a cbeta and the +/// dst_residue is not a glycine + + +bool DLLEXPORT_OST_CONOP CopyIdentical(ost::mol::ResidueHandle src_res, + ost::mol::ResidueHandle dst_res, + ost::mol::XCSEditor& edi, + bool& has_cbeta); + +/// \brief copies atoms of src_res to dst_res +/// +/// src_res and dst_res are thought to be conserved, e.g. the parent standard +/// amino acid of both residues is the same. This includes cases where e.g. the +/// src_rs is and MSE and the dst_res is a MET. This function automatically +/// tries to do the right thing an keep as many atoms as possible from src_res + + + +bool DLLEXPORT_OST_CONOP CopyConserved(ost::mol::ResidueHandle src_res, + ost::mol::ResidueHandle dst_res, + ost::mol::XCSEditor& edi, + bool& has_cbeta); + +/// \brief construct dst_res in case src_res and dst_res are not conserved. +/// +/// This essentially copies the backbone of src_res to dst_res. The CB atom is +/// only copied if dst_res is not equal to glycine. + + +bool DLLEXPORT_OST_CONOP CopyNonConserved(ost::mol::ResidueHandle src_res, + ost::mol::ResidueHandle dst_res, + ost::mol::XCSEditor& edi, + bool& has_cbeta); + +/// \brief construct dst_res from src_res when src_res is an MSE + +bool DLLEXPORT_OST_CONOP CopyMSE(ost::mol::ResidueHandle src_res, + ost::mol::ResidueHandle dst_res, + ost::mol::XCSEditor& edi, + bool& has_cbeta); + +/// \brief construct a dst_res with only atoms matching the standard aminoacid +/// from src_res when src_res is an is modified + +bool DLLEXPORT_OST_CONOP CopyModified(ost::mol::ResidueHandle src_res, + ost::mol::ResidueHandle dst_res, + ost::mol::XCSEditor& edi, + bool& has_cbeta); + + + +}} + +#endif diff --git a/modules/conop/src/rule_based_builder.cc b/modules/conop/src/rule_based_builder.cc index 57c8f515407f89bbcebd8255075b919de2695e6f..33d33c667faebb47593eebe53f28285c448b1956 100644 --- a/modules/conop/src/rule_based_builder.cc +++ b/modules/conop/src/rule_based_builder.cc @@ -121,6 +121,7 @@ void RuleBasedBuilder::FillResidueProps(mol::ResidueHandle residue) if (!last_compound_) return; residue.SetChemClass(last_compound_->GetChemClass()); + residue.SetChemType(last_compound_->GetChemType()); residue.SetOneLetterCode(last_compound_->GetOneLetterCode()); }; @@ -172,6 +173,7 @@ void RuleBasedBuilder::ReorderAtoms(mol::ResidueHandle residue, LOG_WARNING("residue " << residue << " doesn't look like a standard " << residue.GetKey() << " (" << compound->GetFormula() << ")"); residue.SetChemClass(mol::ChemClass(mol::ChemClass::UNKNOWN)); + residue.SetChemType(mol::ChemType(mol::ChemType::UNKNOWN)); residue.SetOneLetterCode('?'); } } @@ -235,12 +237,20 @@ void RuleBasedBuilder::ConnectAtomsOfResidue(mol::ResidueHandle rh) const BondSpec& bond=*j; mol::AtomHandle a1=this->LocateAtom(atoms, bond.atom_one); mol::AtomHandle a2=this->LocateAtom(atoms, bond.atom_two); - if (a1.IsValid() && a2.IsValid() && this->IsBondFeasible(a1, a2)) { - if (this->GetStrictHydrogenMode() && - (a1.GetElement()=="H" || a2.GetElement()=="D")) { - continue; + if (a1.IsValid() && a2.IsValid()) { + if (this->GetBondFeasibilityCheck()==false) { + if (this->GetStrictHydrogenMode() && (a1.GetElement()=="H" || a2.GetElement()=="D")) { + continue; + } + e.Connect(a1, a2, bond.order); + } else { + if (IsBondFeasible(a1, a2)) { + if (this->GetStrictHydrogenMode() && (a1.GetElement()=="H" || a2.GetElement()=="D")) { + continue; + } + e.Connect(a1, a2, bond.order); + } } - e.Connect(a1, a2, bond.order); } } for (mol::AtomHandleList::iterator i=atoms.begin(), e=atoms.end(); i!=e; ++i) { diff --git a/modules/conop/src/rule_based_builder.hh b/modules/conop/src/rule_based_builder.hh index 9ecc45c101cbbb2c6777ff7fb985bb2e9e921db1..71a6fd03453ba9c418a6e39d8c0e011161f13be6 100644 --- a/modules/conop/src/rule_based_builder.hh +++ b/modules/conop/src/rule_based_builder.hh @@ -109,7 +109,7 @@ public: /// by ignoring it or by inserting a dummy atom. virtual void OnMissingAtom(const mol::ResidueHandle& residue, const String& atom_name) { } - + /// \brief Fill in missing information based on atom name. virtual void FillAtomProps(mol::AtomHandle atom, const AtomSpec& spec); @@ -123,6 +123,7 @@ public: virtual bool IsResidueComplete(const mol::ResidueHandle& residue); CompoundLibPtr GetCompoundLib() const { return compound_lib_; } + private: CompoundLibPtr compound_lib_; CompoundPtr last_compound_; @@ -139,7 +140,6 @@ private: void AssignBackBoneTorsionsToResidue(mol::ResidueHandle residue); - }; typedef boost::shared_ptr<RuleBasedBuilder> RuleBasedBuilderPtr; diff --git a/modules/conop/tests/CMakeLists.txt b/modules/conop/tests/CMakeLists.txt index aa06791bf0be4d64640499010893d9db179f3e33..6a832115b5933b66241c9dec5ce23c21dd532c48 100644 --- a/modules/conop/tests/CMakeLists.txt +++ b/modules/conop/tests/CMakeLists.txt @@ -4,6 +4,8 @@ set(OST_CONOP_UNIT_TESTS tests.cc test_builder.cc test_compound.py + test_cleanup.py + test_nonstandard.py ) ost_unittest(MODULE conop diff --git a/modules/conop/tests/sample_noligands.pdb b/modules/conop/tests/sample_noligands.pdb new file mode 100644 index 0000000000000000000000000000000000000000..7fd199276d45124bbe2b2bc6ddf7d47b780d9401 --- /dev/null +++ b/modules/conop/tests/sample_noligands.pdb @@ -0,0 +1,65 @@ +HETATM 1 N MSE A 1 16.152 35.832 19.337 1.00 68.79 N +ANISOU 1 N MSE A 1 9680 7396 9061 1038 -716 -25 N +HETATM 2 CA MSE A 1 16.961 36.379 20.419 1.00 66.57 C +ANISOU 2 CA MSE A 1 9387 7212 8694 1121 -806 40 C +HETATM 3 C MSE A 1 18.345 36.796 19.931 1.00 62.52 C +ANISOU 3 C MSE A 1 8685 6846 8225 1266 -870 -107 C +HETATM 4 O MSE A 1 19.030 36.049 19.227 1.00 60.36 O +ANISOU 4 O MSE A 1 8358 6511 8064 1396 -922 -219 O +HETATM 5 CB MSE A 1 17.100 35.372 21.563 1.00 69.52 C +ANISOU 5 CB MSE A 1 9961 7405 9049 1204 -927 192 C +HETATM 6 CG MSE A 1 17.608 35.983 22.861 1.00 69.50 C +ANISOU 6 CG MSE A 1 9977 7515 8914 1239 -1006 292 C +HETATM 7 SE MSE A 1 16.174 36.321 24.145 0.70149.62 SE +ANISOU 7 SE MSE A 1 20306 17658 18883 1013 -917 492 SE +HETATM 8 CE MSE A 1 16.439 38.231 24.424 1.00101.32 C +ANISOU 8 CE MSE A 1 13992 11855 12651 950 -853 413 C +ATOM 9 N GLY A 2 21.960 55.913 14.093 1.00 32.26 N +ANISOU 9 N GLY A 2 3786 4717 3755 -417 -110 -697 N +ATOM 10 CA GLY A 2 21.067 57.037 14.316 1.00 33.47 C +ANISOU 10 CA GLY A 2 4071 4728 3919 -478 -95 -611 C +ATOM 11 C GLY A 2 20.632 57.066 15.769 1.00 28.81 C +ANISOU 11 C GLY A 2 3536 4062 3349 -382 -126 -599 C +ATOM 12 O GLY A 2 19.474 57.360 16.089 1.00 26.62 O +ANISOU 12 O GLY A 2 3358 3653 3104 -343 -120 -528 O +HETATM 694 N MLY A 3 26.382 48.690 2.460 1.00 30.43 N +ANISOU 694 N MLY A 3 2388 5919 3254 -646 317 -1852 N +HETATM 695 CA MLY A 3 27.776 48.333 2.142 1.00 32.62 C +ANISOU 695 CA MLY A 3 2438 6444 3514 -645 358 -2093 C +HETATM 696 CB MLY A 3 28.523 49.535 1.556 1.00 34.25 C +ANISOU 696 CB MLY A 3 2578 6874 3563 -918 442 -2107 C +HETATM 697 CG MLY A 3 28.053 50.058 0.208 1.00 51.47 C +ANISOU 697 CG MLY A 3 4819 9152 5586 -1157 527 -2046 C +HETATM 698 CD MLY A 3 29.170 50.911 -0.420 1.00 65.96 C +ANISOU 698 CD MLY A 3 6527 11268 7265 -1416 622 -2140 C +HETATM 699 CE MLY A 3 28.648 51.881 -1.478 1.00 78.91 C +ANISOU 699 CE MLY A 3 8300 12955 8728 -1697 684 -1985 C +HETATM 700 NZ MLY A 3 27.996 53.093 -0.885 1.00 83.04 N +ANISOU 700 NZ MLY A 3 9040 13267 9244 -1780 633 -1724 N +HETATM 701 CH1 MLY A 3 27.490 53.898 -2.008 1.00 82.17 C +ANISOU 701 CH1 MLY A 3 9059 13197 8964 -2028 679 -1578 C +HETATM 702 CH2 MLY A 3 29.059 53.885 -0.248 1.00 83.95 C +ANISOU 702 CH2 MLY A 3 9084 13473 9342 -1885 652 -1769 C +HETATM 703 C MLY A 3 28.551 47.875 3.386 1.00 35.38 C +ANISOU 703 C MLY A 3 2698 6760 3986 -436 275 -2175 C +HETATM 704 O MLY A 3 29.262 46.867 3.369 1.00 36.09 O +ANISOU 704 O MLY A 3 2632 6928 4151 -274 255 -2373 O +HETATM 24 N DHA A 4 26.289 27.329 2.438 1.00 21.02 N +HETATM 25 CA DHA A 4 26.295 27.688 3.823 1.00 20.17 C +HETATM 26 CB DHA A 4 27.128 28.481 4.578 1.00 25.40 C +HETATM 27 C DHA A 4 25.128 27.215 4.536 1.00 14.98 C +HETATM 28 O DHA A 4 24.918 27.318 5.770 1.00 15.17 O +ATOM 1454 N CYS A 5 35.381 45.298 39.476 1.00 31.23 N +ATOM 1455 CA CYS A 5 35.559 43.873 39.703 1.00 26.90 C +ATOM 1456 C CYS A 5 34.291 43.354 40.319 1.00 28.31 C +ATOM 1457 OXT CYS A 5 33.569 44.119 40.933 1.00 32.71 O +ATOM 1458 CB CYS A 5 36.760 43.592 40.596 1.00 27.44 C +ATOM 1460 H CYS A 5 34.717 45.766 40.024 1.00 0.00 H +HETATM 1345 N DAL A 6 16.130 53.915 24.417 1.00 8.63 N +HETATM 1346 CA DAL A 6 16.958 55.083 24.235 1.00 24.17 C +HETATM 1347 CB DAL A 6 16.321 56.394 24.733 1.00 30.20 C +HETATM 1348 C DAL A 6 17.335 55.218 22.790 1.00 32.54 C +HETATM 1349 O DAL A 6 16.693 54.552 21.946 1.00 27.41 O +HETATM 1350 OXT DAL A 6 18.286 55.960 22.546 1.00 18.81 O +HETATM 36 O HOH A 19 0.180 48.781 4.764 1.00 23.28 O +END diff --git a/modules/conop/tests/sample_nowater.pdb b/modules/conop/tests/sample_nowater.pdb new file mode 100644 index 0000000000000000000000000000000000000000..0f8c440aa83c10dec2cfffe71cbe524a15d0af15 --- /dev/null +++ b/modules/conop/tests/sample_nowater.pdb @@ -0,0 +1,71 @@ +HETATM 1 N MSE A 1 16.152 35.832 19.337 1.00 68.79 N +ANISOU 1 N MSE A 1 9680 7396 9061 1038 -716 -25 N +HETATM 2 CA MSE A 1 16.961 36.379 20.419 1.00 66.57 C +ANISOU 2 CA MSE A 1 9387 7212 8694 1121 -806 40 C +HETATM 3 C MSE A 1 18.345 36.796 19.931 1.00 62.52 C +ANISOU 3 C MSE A 1 8685 6846 8225 1266 -870 -107 C +HETATM 4 O MSE A 1 19.030 36.049 19.227 1.00 60.36 O +ANISOU 4 O MSE A 1 8358 6511 8064 1396 -922 -219 O +HETATM 5 CB MSE A 1 17.100 35.372 21.563 1.00 69.52 C +ANISOU 5 CB MSE A 1 9961 7405 9049 1204 -927 192 C +HETATM 6 CG MSE A 1 17.608 35.983 22.861 1.00 69.50 C +ANISOU 6 CG MSE A 1 9977 7515 8914 1239 -1006 292 C +HETATM 7 SE MSE A 1 16.174 36.321 24.145 0.70149.62 SE +ANISOU 7 SE MSE A 1 20306 17658 18883 1013 -917 492 SE +HETATM 8 CE MSE A 1 16.439 38.231 24.424 1.00101.32 C +ANISOU 8 CE MSE A 1 13992 11855 12651 950 -853 413 C +ATOM 9 N GLY A 2 21.960 55.913 14.093 1.00 32.26 N +ANISOU 9 N GLY A 2 3786 4717 3755 -417 -110 -697 N +ATOM 10 CA GLY A 2 21.067 57.037 14.316 1.00 33.47 C +ANISOU 10 CA GLY A 2 4071 4728 3919 -478 -95 -611 C +ATOM 11 C GLY A 2 20.632 57.066 15.769 1.00 28.81 C +ANISOU 11 C GLY A 2 3536 4062 3349 -382 -126 -599 C +ATOM 12 O GLY A 2 19.474 57.360 16.089 1.00 26.62 O +ANISOU 12 O GLY A 2 3358 3653 3104 -343 -120 -528 O +HETATM 694 N MLY A 3 26.382 48.690 2.460 1.00 30.43 N +ANISOU 694 N MLY A 3 2388 5919 3254 -646 317 -1852 N +HETATM 695 CA MLY A 3 27.776 48.333 2.142 1.00 32.62 C +ANISOU 695 CA MLY A 3 2438 6444 3514 -645 358 -2093 C +HETATM 696 CB MLY A 3 28.523 49.535 1.556 1.00 34.25 C +ANISOU 696 CB MLY A 3 2578 6874 3563 -918 442 -2107 C +HETATM 697 CG MLY A 3 28.053 50.058 0.208 1.00 51.47 C +ANISOU 697 CG MLY A 3 4819 9152 5586 -1157 527 -2046 C +HETATM 698 CD MLY A 3 29.170 50.911 -0.420 1.00 65.96 C +ANISOU 698 CD MLY A 3 6527 11268 7265 -1416 622 -2140 C +HETATM 699 CE MLY A 3 28.648 51.881 -1.478 1.00 78.91 C +ANISOU 699 CE MLY A 3 8300 12955 8728 -1697 684 -1985 C +HETATM 700 NZ MLY A 3 27.996 53.093 -0.885 1.00 83.04 N +ANISOU 700 NZ MLY A 3 9040 13267 9244 -1780 633 -1724 N +HETATM 701 CH1 MLY A 3 27.490 53.898 -2.008 1.00 82.17 C +ANISOU 701 CH1 MLY A 3 9059 13197 8964 -2028 679 -1578 C +HETATM 702 CH2 MLY A 3 29.059 53.885 -0.248 1.00 83.95 C +ANISOU 702 CH2 MLY A 3 9084 13473 9342 -1885 652 -1769 C +HETATM 703 C MLY A 3 28.551 47.875 3.386 1.00 35.38 C +ANISOU 703 C MLY A 3 2698 6760 3986 -436 275 -2175 C +HETATM 704 O MLY A 3 29.262 46.867 3.369 1.00 36.09 O +ANISOU 704 O MLY A 3 2632 6928 4151 -274 255 -2373 O +HETATM 24 N DHA A 4 26.289 27.329 2.438 1.00 21.02 N +HETATM 25 CA DHA A 4 26.295 27.688 3.823 1.00 20.17 C +HETATM 26 CB DHA A 4 27.128 28.481 4.578 1.00 25.40 C +HETATM 27 C DHA A 4 25.128 27.215 4.536 1.00 14.98 C +HETATM 28 O DHA A 4 24.918 27.318 5.770 1.00 15.17 O +ATOM 1454 N CYS A 5 35.381 45.298 39.476 1.00 31.23 N +ATOM 1455 CA CYS A 5 35.559 43.873 39.703 1.00 26.90 C +ATOM 1456 C CYS A 5 34.291 43.354 40.319 1.00 28.31 C +ATOM 1457 OXT CYS A 5 33.569 44.119 40.933 1.00 32.71 O +ATOM 1458 CB CYS A 5 36.760 43.592 40.596 1.00 27.44 C +ATOM 1460 H CYS A 5 34.717 45.766 40.024 1.00 0.00 H +HETATM 1345 N DAL A 6 16.130 53.915 24.417 1.00 8.63 N +HETATM 1346 CA DAL A 6 16.958 55.083 24.235 1.00 24.17 C +HETATM 1347 CB DAL A 6 16.321 56.394 24.733 1.00 30.20 C +HETATM 1348 C DAL A 6 17.335 55.218 22.790 1.00 32.54 C +HETATM 1349 O DAL A 6 16.693 54.552 21.946 1.00 27.41 O +HETATM 1350 OXT DAL A 6 18.286 55.960 22.546 1.00 18.81 O +HETATM 29 C1 GOL A 17 3.793 59.768 8.209 1.00 31.00 C +HETATM 30 O1 GOL A 17 3.244 58.473 8.337 1.00 27.42 O +HETATM 31 C2 GOL A 17 4.701 60.020 9.406 1.00 26.81 C +HETATM 32 O2 GOL A 17 5.573 58.919 9.512 1.00 26.44 O +HETATM 33 C3 GOL A 17 5.505 61.287 9.156 1.00 24.74 C +HETATM 34 O3 GOL A 17 6.429 61.468 10.222 1.00 31.06 O +HETATM 35 CL CL A 18 11.844 59.221 16.755 0.79 32.84 CL +END diff --git a/modules/conop/tests/sample_test_cleanup.pdb b/modules/conop/tests/sample_test_cleanup.pdb new file mode 100644 index 0000000000000000000000000000000000000000..cce7fe04d4fe753d68c9e73620fea8617ce07059 --- /dev/null +++ b/modules/conop/tests/sample_test_cleanup.pdb @@ -0,0 +1,72 @@ +HETATM 1 N MSE A 1 16.152 35.832 19.337 1.00 68.79 N +ANISOU 1 N MSE A 1 9680 7396 9061 1038 -716 -25 N +HETATM 2 CA MSE A 1 16.961 36.379 20.419 1.00 66.57 C +ANISOU 2 CA MSE A 1 9387 7212 8694 1121 -806 40 C +HETATM 3 C MSE A 1 18.345 36.796 19.931 1.00 62.52 C +ANISOU 3 C MSE A 1 8685 6846 8225 1266 -870 -107 C +HETATM 4 O MSE A 1 19.030 36.049 19.227 1.00 60.36 O +ANISOU 4 O MSE A 1 8358 6511 8064 1396 -922 -219 O +HETATM 5 CB MSE A 1 17.100 35.372 21.563 1.00 69.52 C +ANISOU 5 CB MSE A 1 9961 7405 9049 1204 -927 192 C +HETATM 6 CG MSE A 1 17.608 35.983 22.861 1.00 69.50 C +ANISOU 6 CG MSE A 1 9977 7515 8914 1239 -1006 292 C +HETATM 7 SE MSE A 1 16.174 36.321 24.145 0.70149.62 SE +ANISOU 7 SE MSE A 1 20306 17658 18883 1013 -917 492 SE +HETATM 8 CE MSE A 1 16.439 38.231 24.424 1.00101.32 C +ANISOU 8 CE MSE A 1 13992 11855 12651 950 -853 413 C +ATOM 9 N GLY A 2 21.960 55.913 14.093 1.00 32.26 N +ANISOU 9 N GLY A 2 3786 4717 3755 -417 -110 -697 N +ATOM 10 CA GLY A 2 21.067 57.037 14.316 1.00 33.47 C +ANISOU 10 CA GLY A 2 4071 4728 3919 -478 -95 -611 C +ATOM 11 C GLY A 2 20.632 57.066 15.769 1.00 28.81 C +ANISOU 11 C GLY A 2 3536 4062 3349 -382 -126 -599 C +ATOM 12 O GLY A 2 19.474 57.360 16.089 1.00 26.62 O +ANISOU 12 O GLY A 2 3358 3653 3104 -343 -120 -528 O +HETATM 694 N MLY A 3 26.382 48.690 2.460 1.00 30.43 N +ANISOU 694 N MLY A 3 2388 5919 3254 -646 317 -1852 N +HETATM 695 CA MLY A 3 27.776 48.333 2.142 1.00 32.62 C +ANISOU 695 CA MLY A 3 2438 6444 3514 -645 358 -2093 C +HETATM 696 CB MLY A 3 28.523 49.535 1.556 1.00 34.25 C +ANISOU 696 CB MLY A 3 2578 6874 3563 -918 442 -2107 C +HETATM 697 CG MLY A 3 28.053 50.058 0.208 1.00 51.47 C +ANISOU 697 CG MLY A 3 4819 9152 5586 -1157 527 -2046 C +HETATM 698 CD MLY A 3 29.170 50.911 -0.420 1.00 65.96 C +ANISOU 698 CD MLY A 3 6527 11268 7265 -1416 622 -2140 C +HETATM 699 CE MLY A 3 28.648 51.881 -1.478 1.00 78.91 C +ANISOU 699 CE MLY A 3 8300 12955 8728 -1697 684 -1985 C +HETATM 700 NZ MLY A 3 27.996 53.093 -0.885 1.00 83.04 N +ANISOU 700 NZ MLY A 3 9040 13267 9244 -1780 633 -1724 N +HETATM 701 CH1 MLY A 3 27.490 53.898 -2.008 1.00 82.17 C +ANISOU 701 CH1 MLY A 3 9059 13197 8964 -2028 679 -1578 C +HETATM 702 CH2 MLY A 3 29.059 53.885 -0.248 1.00 83.95 C +ANISOU 702 CH2 MLY A 3 9084 13473 9342 -1885 652 -1769 C +HETATM 703 C MLY A 3 28.551 47.875 3.386 1.00 35.38 C +ANISOU 703 C MLY A 3 2698 6760 3986 -436 275 -2175 C +HETATM 704 O MLY A 3 29.262 46.867 3.369 1.00 36.09 O +ANISOU 704 O MLY A 3 2632 6928 4151 -274 255 -2373 O +HETATM 24 N DHA A 4 26.289 27.329 2.438 1.00 21.02 N +HETATM 25 CA DHA A 4 26.295 27.688 3.823 1.00 20.17 C +HETATM 26 CB DHA A 4 27.128 28.481 4.578 1.00 25.40 C +HETATM 27 C DHA A 4 25.128 27.215 4.536 1.00 14.98 C +HETATM 28 O DHA A 4 24.918 27.318 5.770 1.00 15.17 O +ATOM 1454 N CYS A 5 35.381 45.298 39.476 1.00 31.23 N +ATOM 1455 CA CYS A 5 35.559 43.873 39.703 1.00 26.90 C +ATOM 1456 C CYS A 5 34.291 43.354 40.319 1.00 28.31 C +ATOM 1457 OXT CYS A 5 33.569 44.119 40.933 1.00 32.71 O +ATOM 1458 CB CYS A 5 36.760 43.592 40.596 1.00 27.44 C +ATOM 1460 H CYS A 5 34.717 45.766 40.024 1.00 0.00 H +HETATM 1345 N DAL A 6 16.130 53.915 24.417 1.00 8.63 N +HETATM 1346 CA DAL A 6 16.958 55.083 24.235 1.00 24.17 C +HETATM 1347 CB DAL A 6 16.321 56.394 24.733 1.00 30.20 C +HETATM 1348 C DAL A 6 17.335 55.218 22.790 1.00 32.54 C +HETATM 1349 O DAL A 6 16.693 54.552 21.946 1.00 27.41 O +HETATM 1350 OXT DAL A 6 18.286 55.960 22.546 1.00 18.81 O +HETATM 29 C1 GOL A 17 3.793 59.768 8.209 1.00 31.00 C +HETATM 30 O1 GOL A 17 3.244 58.473 8.337 1.00 27.42 O +HETATM 31 C2 GOL A 17 4.701 60.020 9.406 1.00 26.81 C +HETATM 32 O2 GOL A 17 5.573 58.919 9.512 1.00 26.44 O +HETATM 33 C3 GOL A 17 5.505 61.287 9.156 1.00 24.74 C +HETATM 34 O3 GOL A 17 6.429 61.468 10.222 1.00 31.06 O +HETATM 35 CL CL A 18 11.844 59.221 16.755 0.79 32.84 CL +HETATM 36 O HOH A 19 0.180 48.781 4.764 1.00 23.28 O +END diff --git a/modules/conop/tests/test_cleanup.py b/modules/conop/tests/test_cleanup.py new file mode 100644 index 0000000000000000000000000000000000000000..1dc280f4fbaac9867c7f7a1063217bb4527cfbd0 --- /dev/null +++ b/modules/conop/tests/test_cleanup.py @@ -0,0 +1,164 @@ +import unittest +from ost import geom, conop +from ost.conop import cleanup + +class TestCleanUp(unittest.TestCase): + + def setUp(self): + self.comp_lib=conop.GetBuilder().compound_lib + self.ent = io.LoadPDB("sample_test_cleanup.pdb") + self.ent_no_wat = io.LoadPDB("sample_nowater.pdb") + self.ent_no_lig = io.LoadPDB("sample_noligands.pdb") + + def testStripWater(self): + self.new_ent = cleanup.Cleanup(self.ent, strip_water=True, canonicalize=False, remove_ligands=False) + self.assertEqual( self.new_ent.residue_count, self.ent_no_wat.residue_count ) + self.assertTrue( self.new_ent.residues[0].IsValid() ) + self.assertEqual( self.new_ent.residues[0].qualified_name, self.ent_no_wat.residues[0].qualified_name) + self.assertTrue( self.new_ent.residues[1].IsValid() ) + self.assertEqual( self.new_ent.residues[1].qualified_name, self.ent_no_wat.residues[1].qualified_name) + self.assertTrue( self.new_ent.residues[2].IsValid() ) + self.assertEqual( self.new_ent.residues[2].qualified_name, self.ent_no_wat.residues[2].qualified_name) + self.assertTrue( self.new_ent.residues[3].IsValid() ) + self.assertEqual( self.new_ent.residues[3].qualified_name, self.ent_no_wat.residues[3].qualified_name) + self.assertTrue( self.new_ent.residues[4].IsValid() ) + self.assertEqual( self.new_ent.residues[4].qualified_name, self.ent_no_wat.residues[4].qualified_name) + self.assertTrue( self.new_ent.residues[5].IsValid() ) + self.assertEqual( self.new_ent.residues[5].qualified_name, self.ent_no_wat.residues[5].qualified_name) + self.assertTrue( self.new_ent.residues[6].IsValid() ) + self.assertEqual( self.new_ent.residues[6].qualified_name, self.ent_no_wat.residues[6].qualified_name) + self.assertTrue( self.new_ent.residues[7].IsValid() ) + self.assertEqual( self.new_ent.residues[7].qualified_name, self.ent_no_wat.residues[7].qualified_name) + + def testCanonicalize(self): + self.new_ent = cleanup.Cleanup(self.ent, strip_water=False, canonicalize=True, remove_ligands=False) + #standard residue must be the same + self.gly = self.ent.residues[1] + self.new_gly = self.new_ent.residues[1] + self.assertTrue(self.new_gly.IsValid()) + self.assertTrue(self.new_gly.IsPeptideLinking()) + self.assertEqual(self.gly.atom_count, self.new_gly.atom_count) + #TEMP del sidechain of incomplete residue and OXT if present + self.new_cys = self.new_ent.residues[4] + self.new_cys_atoms = set([atm.name for atm in self.new_cys.atoms]) + self.assertEqual( len(self.new_cys_atoms), 4, msg = repr(self.new_cys_atoms)) + self.assertTrue( "CB" in self.new_cys_atoms) + self.assertTrue( "CA" in self.new_cys_atoms) + self.assertTrue( "C" in self.new_cys_atoms) + self.assertFalse( "OXT" in self.new_cys_atoms) + self.assertTrue( "N" in self.new_cys_atoms) + #test replacement of atoms + self.mse = self.ent.residues[0] +# self.assertTrue( self.mse.IsValid()) +# self.assertTrue( self.mse.IsPeptideLinking()) + self.sel = self.mse.FindAtom("SE") +# self.assertTrue( self.sel.IsValid()) + self.met = self.new_ent.residues[0] + self.assertTrue(self.met.IsValid()) + self.assertEqual(self.mse.atom_count, self.met.atom_count) + self.assertEqual(self.met.name, "MET") + self.assertEqual(self.met.one_letter_code, "M") + self.assertTrue(self.met.IsPeptideLinking()) + self.sul = self.met.FindAtom("SD") + self.assertTrue(self.sul.IsValid()) + self.assertTrue(geom.Equal(self.sul.pos,self.sel.pos), msg = "sul:%s sel:%s"%(str(self.sul.pos), str(self.sel.pos)) ) + self.assertEqual(self.sul.element, "S") +# self.AssertTrue( sul.mass == conop.Conopology.Instance().GetDefaultAtomMass("S")) +# self.AssertTrue( sul.radius == conop.Conopology.Instance().GetDefaultAtomRadius("S")) + for atm in self.met.atoms: + self.assertFalse( atm.is_hetatom) + #test addition + self.mly = self.ent.residues[2] +# self.assertTrue( self.mly.IsValid()) +# self.assertTrue( self.mly.IsPeptideLinking()) + self.new_lys = self.new_ent.residues[2] + self.assertTrue(self.new_lys.IsValid()) + self.assertTrue(self.new_lys.IsPeptideLinking()) + self.assertEqual(self.new_lys.name, "LYS") + self.assertEqual(self.new_lys.one_letter_code, "K") + self.new_lys_atoms = set([atm.name for atm in self.new_lys.atoms]) + self.canon_lys = self.comp_lib.FindCompound("LYS") + self.canon_lys_atoms = set([atom.name for atom in self.canon_lys.atom_specs + if atom.element != "H" and atom.element != "D" and not atom.is_leaving ]) + self.assertEqual(self.canon_lys_atoms, self.new_lys_atoms) + self.assertFalse(self.canon_lys_atoms - self.new_lys_atoms) + self.assertFalse(self.new_lys_atoms - self.canon_lys_atoms) #test the reverse + for atm in self.new_lys.atoms: + self.assertFalse( atm.is_hetatom) + #deletions + self.dha = self.ent.residues[3] +# self.assertTrue( self.dha.IsValid()) +# self.assertTrue( self.dha.IsPeptideLinking()) + self.new_ser = self.new_ent.residues[3] + self.assertTrue(self.new_ser.IsValid()) + self.assertTrue(self.new_ser.IsPeptideLinking()) + self.assertEqual(self.new_ser.name, "SER") + self.assertEqual(self.new_ser.one_letter_code, "S") + self.new_ser_atoms = set([atm.name for atm in self.new_ser.atoms]) + self.canon_ser = self.comp_lib.FindCompound("SER") + self.canon_ser_atoms = set([atom.name for atom in self.canon_ser.atom_specs + if atom.element != "H" and atom.element != "D" and not atom.is_leaving ]) + #TEMP + self.assertEqual( len(self.new_ser_atoms), 5) + self.assertTrue( "CB" in self.new_ser_atoms) + self.assertTrue( "CA" in self.new_ser_atoms) + self.assertTrue( "C" in self.new_ser_atoms) + self.assertTrue( "O" in self.new_ser_atoms) + self.assertTrue( "N" in self.new_ser_atoms) + #AFTER TEMP + #self.assertEqual( self.canon_ser_atoms, self.new_ser_atoms) + #self.assertFalse(self.canon_ser_atoms - self.new_ser_atoms) + #self.assertFalse(self.new_ser_atoms - self.canon_ser_atoms) #test the reverse + for atm in self.new_ser.atoms: + self.assertFalse( atm.is_hetatom) + #test deletion of whole residue + self.assertEqual(self.ent.residues[5].chem_class, "D_PEPTIDE_LINKING") + self.assertNotEqual(self.new_ent.residues[5].name, "DAL") + self.assertNotEqual(self.ent.residue_count, self.new_ent.residue_count) + + def testRemoveLigands(self): + self.new_ent = cleanup.Cleanup(self.ent, strip_water=False, canonicalize=False, remove_ligands=True) + self.assertEqual(self.new_ent.residue_count, self.ent_no_lig.residue_count ) + #MSE + self.assertTrue(self.new_ent.residues[0].IsValid() ) + self.assertEqual(self.new_ent.residues[0].qualified_name, self.ent_no_lig.residues[0].qualified_name) + self.assertTrue(self.new_ent.residues[0].IsPeptideLinking()) + self.assertTrue(self.new_ent.residues[0].atoms[0].is_hetatom) + #GLY + self.assertTrue(self.new_ent.residues[1].IsValid() ) + self.assertEqual(self.new_ent.residues[1].qualified_name, self.ent_no_lig.residues[1].qualified_name) + self.assertTrue(self.new_ent.residues[1].IsPeptideLinking()) + self.assertFalse(self.new_ent.residues[1].atoms[0].is_hetatom) + #MLY + self.assertTrue(self.new_ent.residues[2].IsValid() ) + self.assertEqual(self.new_ent.residues[2].qualified_name, self.ent_no_lig.residues[2].qualified_name) + self.assertTrue(self.new_ent.residues[2].IsPeptideLinking()) + self.assertTrue(self.new_ent.residues[2].atoms[0].is_hetatom) + #DHA + self.assertTrue(self.new_ent.residues[3].IsValid() ) + self.assertEqual(self.new_ent.residues[3].qualified_name, self.ent_no_lig.residues[3].qualified_name) + self.assertTrue(self.new_ent.residues[3].IsPeptideLinking()) + self.assertTrue(self.new_ent.residues[3].atoms[0].is_hetatom) + #CYS + self.assertTrue(self.new_ent.residues[4].IsValid() ) + self.assertEqual(self.new_ent.residues[4].qualified_name, self.ent_no_lig.residues[4].qualified_name) + self.assertTrue(self.new_ent.residues[4].IsPeptideLinking()) + self.assertFalse(self.new_ent.residues[4].atoms[0].is_hetatom) + #DAL + self.assertTrue(self.new_ent.residues[5].IsValid() ) + self.assertEqual(self.new_ent.residues[5].qualified_name, self.ent_no_lig.residues[5].qualified_name) + self.assertTrue(self.new_ent.residues[5].IsPeptideLinking()) + self.assertTrue(self.new_ent.residues[5].atoms[0].is_hetatom) + #HOH + self.assertTrue(self.new_ent.residues[6].IsValid() ) + self.assertEqual(self.new_ent.residues[6].qualified_name, self.ent_no_lig.residues[6].qualified_name) + self.assertFalse(self.new_ent.residues[6].IsPeptideLinking()) # here assertFalse instead of assertTrue + self.assertTrue(self.new_ent.residues[6].atoms[0].is_hetatom) + +if not hasattr(conop.GetBuilder(), 'compound_lib'): + print 'Default builder without compound lib. Ignoring test_cleanup.py tests' + sys.exit() + +if __name__== '__main__': + from ost import testutils + testutils.RunTests() diff --git a/modules/conop/tests/test_compound.py b/modules/conop/tests/test_compound.py index 2c57bce756e0f26deab7e69467807993e96c51aa..a215a78f7a5dd966c2619346aaabf0f084b7bbd7 100644 --- a/modules/conop/tests/test_compound.py +++ b/modules/conop/tests/test_compound.py @@ -26,6 +26,6 @@ if __name__=='__main__': if not hasattr(builder, 'compound_lib'): print 'default builder does not use compound library. ignoring unit tests' else: - suite = unittest.TestLoader().loadTestsFromTestCase(TestCompound) - unittest.TextTestRunner().run(suite) + from ost import testutils + testutils.RunTests() diff --git a/modules/conop/tests/test_heuristic_builder.cc b/modules/conop/tests/test_heuristic_builder.cc index 4220f3110ca1af0ecec5acc183dba6d1ad5b5f11..0e3a811ae922d0d8375fe98ab96163765f5766f4 100644 --- a/modules/conop/tests/test_heuristic_builder.cc +++ b/modules/conop/tests/test_heuristic_builder.cc @@ -65,6 +65,21 @@ ResidueHandle make_leu(ChainHandle chain) return res; } +ResidueHandle make_defective_leu(ChainHandle chain) +{ + XCSEditor e=chain.GetEntity().EditXCS(); + ResidueHandle res=e.AppendResidue(chain, "LEU"); + + e.InsertAtom(res, "N", geom::Vec3(19.003,32.473,60.366)); + e.InsertAtom(res, "CA", geom::Vec3(18.330,32.402,61.664)); + e.InsertAtom(res, "C", geom::Vec3(17.884,33.787,62.117)); + e.InsertAtom(res, "O", geom::Vec3(17.853,34.091,63.308)); + e.InsertAtom(res, "CB", geom::Vec3(19.269,31.793,102.710)); + e.InsertAtom(res, "CG", geom::Vec3(19.695,30.340,62.501)); + e.InsertAtom(res, "CD1", geom::Vec3(20.585,29.897,63.648)); + e.InsertAtom(res, "CD2", geom::Vec3(18.461,29.459,62.420)); + return res; +} void verify_connectivity_x(const ResidueHandle& res) { @@ -154,12 +169,25 @@ BOOST_AUTO_TEST_CASE(name_based_connect) heuristic_builder.FillAtomProps(*i); } + EntityHandle de=CreateEntity(); + ChainHandle dc=de.EditXCS().InsertChain("A"); + ResidueHandle dile=make_defective_leu(dc); + HeuristicBuilder dheuristic_builder; + dheuristic_builder.SetBondFeasibilityCheck(false); + for (AtomHandleIter i=de.AtomsBegin(),x=de.AtomsEnd(); i!=x; ++i) { + dheuristic_builder.FillAtomProps(*i); + } + BOOST_MESSAGE("running distance based checks on arginine"); heuristic_builder.ConnectAtomsOfResidue(arg); verify_connectivity(arg); BOOST_MESSAGE("running distance based checks on leu"); heuristic_builder.ConnectAtomsOfResidue(ile); verify_connectivity(ile); + + BOOST_MESSAGE("running distance based checks on defective leu"); + dheuristic_builder.ConnectAtomsOfResidue(dile); + verify_connectivity(dile); } BOOST_AUTO_TEST_CASE(test_assign_torsions){ diff --git a/modules/conop/tests/test_nonstandard.py b/modules/conop/tests/test_nonstandard.py new file mode 100644 index 0000000000000000000000000000000000000000..170749c6eacd73bc64f4b6826e4df5d80f104512 --- /dev/null +++ b/modules/conop/tests/test_nonstandard.py @@ -0,0 +1,127 @@ +import unittest +from ost import conop + + +class TestNonStandard(unittest.TestCase): + + def test_fastModified(self): + # phoshoserine: test if we correctly strip off modifications + tpl=io.LoadPDB('testfiles/sep.pdb') + new_hdl=mol.CreateEntity(); + ed=new_hdl.EditXCS() + c=ed.InsertChain('A') + ed.AppendResidue(c, 'SER') + + err, has_cbeta=conop.CopyConserved(tpl.residues[0], new_hdl.residues[0], ed) + self.assertTrue(err) + self.assertTrue(has_cbeta) + residues=new_hdl.residues + self.assertEqual(len(residues), 1) + self.assertEqual(len(residues[0].atoms), 6) + self.assertTrue(new_hdl.FindAtom("A", mol.ResNum(1), "N").IsValid()) + self.assertTrue(new_hdl.FindAtom("A", mol.ResNum(1), "CA").IsValid()) + self.assertTrue(new_hdl.FindAtom("A", mol.ResNum(1), "C").IsValid()) + self.assertTrue(new_hdl.FindAtom("A", mol.ResNum(1), "O").IsValid()) + self.assertTrue(new_hdl.FindAtom("A", mol.ResNum(1), "CB").IsValid()) + self.assertTrue(new_hdl.FindAtom("A", mol.ResNum(1), "OG").IsValid()) + + + def test_CBeta(self): + # test if the dst residues contain cbeta, unless they are glycines + tpl=io.LoadPDB('testfiles/cbeta.pdb') + new_hdl=mol.CreateEntity(); + ed=new_hdl.EditXCS() + c=ed.InsertChain('A') + ed.AppendResidue(c, 'MET') + ed.AppendResidue(c, 'GLY') + ed.AppendResidue(c, 'GLY') + ed.AppendResidue(c, 'HIS') + err, has_cbeta=conop.CopyConserved(tpl.residues[0], new_hdl.residues[0], ed) + self.assertTrue(has_cbeta) + self.assertTrue(err) + err, has_cbeta=conop.CopyConserved(tpl.residues[1], new_hdl.residues[1], ed) + self.assertFalse(has_cbeta) + self.assertTrue(err) + err, has_cbeta=conop.CopyConserved(tpl.residues[2], new_hdl.residues[2], ed) + self.assertFalse(has_cbeta) + self.assertTrue(err) + err, has_cbeta=conop.CopyConserved(tpl.residues[3], new_hdl.residues[3], ed) + self.assertTrue(has_cbeta) + self.assertTrue(err) + + residues=new_hdl.residues + self.assertEqual(len(residues), 4) + self.assertTrue(residues[0].FindAtom("CB").IsValid()) + self.assertFalse(residues[1].FindAtom("CB").IsValid()) + self.assertFalse(residues[2].FindAtom("CB").IsValid()) + self.assertTrue(residues[3].FindAtom("CB").IsValid()) + + + def test_CopyResidue(self): + tpl=io.LoadPDB('testfiles/cbeta.pdb') + new_hdl=mol.CreateEntity(); + ed=new_hdl.EditXCS() + c=ed.InsertChain('A') + ed.AppendResidue(c, 'MET') + ed.AppendResidue(c, 'GLY') + ed.AppendResidue(c, 'GLY') + ed.AppendResidue(c, 'HIS') + ed.AppendResidue(c, 'HIS') + ed.AppendResidue(c, 'GLY') + ed.AppendResidue(c, 'HIS') + ed.AppendResidue(c, 'MET') + + # MET to MET + err =conop.CopyResidue(tpl.residues[0], new_hdl.residues[0], ed) + self.assertTrue(err) + #GLY to GLY + err =conop.CopyResidue(tpl.residues[1], new_hdl.residues[1], ed) + self.assertTrue(err) + # GLY to GLY + err =conop.CopyResidue(tpl.residues[2], new_hdl.residues[2], ed) + self.assertTrue(err) + #now we copy a HIS to a HIS + err =conop.CopyResidue(tpl.residues[3], new_hdl.residues[3], ed) + self.assertTrue(err) + # copy a GLY to a HIS + err, has_cbeta=conop.CopyNonConserved(tpl.residues[1], new_hdl.residues[4], ed) + self.assertFalse(has_cbeta) + # copy a MET to a GLY + err =conop.CopyResidue(tpl.residues[0], new_hdl.residues[5], ed) + self.assertFalse(err) + # copy a MET to a HIS + err =conop.CopyResidue(tpl.residues[0], new_hdl.residues[6], ed) + self.assertFalse(err) + # copy a GLY to a MET with adding CB + err=conop.CopyResidue(tpl.residues[1], new_hdl.residues[7], ed) + self.assertFalse(err) + + residues=new_hdl.residues + self.assertEqual(len(residues), 8) + # MET to MET + self.assertTrue(residues[0].FindAtom("CB").IsValid()) + #GLY to GLY + self.assertFalse(residues[1].FindAtom("CB").IsValid()) + #now we copy a GLY to a GLY + self.assertFalse(residues[2].FindAtom("CB").IsValid()) + #now we copy a HIS to a HIS + self.assertTrue(residues[3].FindAtom("CB").IsValid()) + #now we copy a GLY to a HIS without adding CB + self.assertFalse(residues[4].FindAtom("CB").IsValid()) + #now we copy a MET to a GLY + self.assertFalse(residues[5].FindAtom("CB").IsValid()) + # copy a MET to a HIS + self.assertTrue(residues[6].FindAtom("CB").IsValid()) + # copy a GLY to a MET with adding CB + self.assertTrue(residues[7].FindAtom("CB").IsValid()) + + +if __name__ == "__main__": + builder=conop.GetBuilder() + if not hasattr(builder, 'compound_lib'): + print 'default builder does not use compound library. ignoring unit tests' + else: + from ost import testutils + testutils.RunTests() + + diff --git a/modules/conop/tests/test_rule_based_builder.cc b/modules/conop/tests/test_rule_based_builder.cc index 0bc08d4047027a9d7895a6ae6e824b4358155ff0..50e34860a606912aa978fc3429dc1b1f87c2656a 100644 --- a/modules/conop/tests/test_rule_based_builder.cc +++ b/modules/conop/tests/test_rule_based_builder.cc @@ -119,6 +119,35 @@ ResidueHandle make_uracil2(ChainHandle chain) return res; } +ResidueHandle make_defective_uracil2(ChainHandle chain) +{ + XCSEditor e=chain.GetEntity().EditXCS(); + ResidueHandle res = e.AppendResidue(chain, "U"); + + e.InsertAtom(res, "P", geom::Vec3(16.249, 28.254, 44.759)); + e.InsertAtom(res, "OP1", geom::Vec3(16.654, 28.055, 46.181)); + e.InsertAtom(res, "OP2", geom::Vec3(17.115, 27.731, 43.656)); + e.InsertAtom(res, "O5'", geom::Vec3(14.826, 27.572, 44.574)); + e.InsertAtom(res, "C5'", geom::Vec3(14.711, 26.206, 44.216)); + e.InsertAtom(res, "C4'", geom::Vec3(13.279, 25.889, 43.887)); + e.InsertAtom(res, "O4'", geom::Vec3(12.832, 26.793, 42.838)); + e.InsertAtom(res, "C3'", geom::Vec3(13.155, 24.434, 43.329)); + e.InsertAtom(res, "O3'", geom::Vec3(12.269, 23.625, 44.098)); + e.InsertAtom(res, "C2'", geom::Vec3(12.871, 24.595, 41.875)); + e.InsertAtom(res, "O2'", geom::Vec3(11.811, 23.752, 41.462)); + e.InsertAtom(res, "C1'", geom::Vec3(12.424, 26.056, 41.694)); + e.InsertAtom(res, "N1", geom::Vec3(13.030, 26.692, 40.497)); + e.InsertAtom(res, "C2", geom::Vec3(12.517, 26.365, 39.228)); + e.InsertAtom(res, "O2", geom::Vec3(11.579, 25.594, 39.068)); + e.InsertAtom(res, "N3", geom::Vec3(13.141, 26.987, 38.161)); + e.InsertAtom(res, "C4", geom::Vec3(14.197, 27.888, 38.210)); + e.InsertAtom(res, "O4", geom::Vec3(14.627, 28.368, 37.156)); + e.InsertAtom(res, "C5", geom::Vec3(14.671, 28.189, 39.542)); + e.InsertAtom(res, "C6", geom::Vec3(14.087, 27.597, 80.612)); + + return res; +} + void verify_nucleotide_connectivity(const ResidueHandle& res) { BOOST_CHECK(BondExists(res.FindAtom("P"), @@ -217,16 +246,28 @@ BOOST_AUTO_TEST_CASE(nucleotide_based_connect) } RuleBasedBuilder rb_builder = RuleBasedBuilder(compound_lib); + RuleBasedBuilder drb_builder = RuleBasedBuilder(compound_lib); + drb_builder.SetBondFeasibilityCheck(false); + EntityHandle e=CreateEntity(); ChainHandle c=e.EditXCS().InsertChain("A"); ResidueHandle c0=make_cytosine(c); ResidueHandle u1=make_uracil1(c); ResidueHandle u2=make_uracil2(c); + + EntityHandle de=CreateEntity(); + ChainHandle dc=de.EditXCS().InsertChain("A"); + ResidueHandle du2=make_defective_uracil2(dc); + for (AtomHandleIter i=e.AtomsBegin(),x=e.AtomsEnd(); i!=x; ++i) { rb_builder.FillAtomProps(*i); } + for (AtomHandleIter i=de.AtomsBegin(),x=de.AtomsEnd(); i!=x; ++i) { + drb_builder.FillAtomProps(*i); + } + // running positive test BOOST_MESSAGE("running distance based checks on cytosine"); rb_builder.ConnectAtomsOfResidue(c0); @@ -247,6 +288,12 @@ BOOST_AUTO_TEST_CASE(nucleotide_based_connect) BOOST_MESSAGE("connecting cytosine to second uracil"); rb_builder.ConnectResidueToNext(c0, u2); verify_nucleotide_nolink(c0, u2); + + // running positive test + BOOST_MESSAGE("running distance based checks on defective uracil"); + drb_builder.ConnectAtomsOfResidue(du2); + verify_nucleotide_connectivity(du2); + } BOOST_AUTO_TEST_SUITE_END( ) diff --git a/modules/conop/tests/testfiles/cbeta.pdb b/modules/conop/tests/testfiles/cbeta.pdb new file mode 100644 index 0000000000000000000000000000000000000000..fcb59f778ba67b568a83c99605d14f3c8cdc96a4 --- /dev/null +++ b/modules/conop/tests/testfiles/cbeta.pdb @@ -0,0 +1,27 @@ +ATOM 1 N MET A 55 -11.301 11.863 12.812 1.00 46.35 N +ATOM 2 CA MET A 55 -10.174 12.241 13.713 1.00 45.84 C +ATOM 3 C MET A 55 -9.595 11.051 14.465 1.00 44.35 C +ATOM 4 O MET A 55 -10.219 9.989 14.526 1.00 46.54 O +ATOM 5 CB MET A 55 -10.591 13.367 14.670 1.00 48.03 C +ATOM 6 CG MET A 55 -11.911 13.150 15.404 1.00 49.20 C +ATOM 7 SD MET A 55 -12.173 14.422 16.660 1.00 55.85 S +ATOM 8 CE MET A 55 -10.955 13.907 17.875 1.00 52.51 C +ATOM 9 N GLY A 56 -8.383 11.240 14.995 1.00 42.02 N +ATOM 10 CA GLY A 56 -7.611 10.243 15.755 1.00 39.04 C +ATOM 11 C GLY A 56 -7.093 9.042 14.960 1.00 35.73 C +ATOM 12 O GLY A 56 -7.875 8.322 14.336 1.00 35.25 O +ATOM 18 N GLY A 57 -5.757 8.838 14.934 1.00 32.59 N +ATOM 19 CA GLY A 57 -5.167 7.704 14.210 1.00 30.22 C +ATOM 20 C GLY A 57 -5.475 6.389 14.924 1.00 28.03 C +ATOM 21 O GLY A 57 -5.774 6.389 16.125 1.00 25.91 O +ATOM 25 N HIS A 58 -5.434 5.288 14.176 1.00 26.73 N +ATOM 26 CA HIS A 58 -5.705 3.960 14.726 1.00 26.95 C +ATOM 27 C HIS A 58 -4.622 3.524 15.706 1.00 27.12 C +ATOM 28 O HIS A 58 -3.426 3.545 15.366 1.00 27.18 O +ATOM 29 CB HIS A 58 -5.849 2.928 13.607 1.00 26.98 C +ATOM 30 CG HIS A 58 -7.149 3.014 12.872 1.00 27.32 C +ATOM 31 ND1 HIS A 58 -8.359 3.179 13.510 1.00 28.47 N +ATOM 32 CD2 HIS A 58 -7.428 2.948 11.552 1.00 26.86 C +ATOM 33 CE1 HIS A 58 -9.327 3.211 12.613 1.00 28.81 C +ATOM 34 NE2 HIS A 58 -8.789 3.073 11.416 1.00 28.59 N +END diff --git a/modules/conop/tests/testfiles/sep.pdb b/modules/conop/tests/testfiles/sep.pdb new file mode 100644 index 0000000000000000000000000000000000000000..f381b42b76b5bac59fc77925b742811410a8f157 --- /dev/null +++ b/modules/conop/tests/testfiles/sep.pdb @@ -0,0 +1,10 @@ +HETATM 2554 N SEP A 338 22.112 31.452 4.376 1.00 36.83 N +HETATM 2555 CA SEP A 338 21.303 32.489 4.986 1.00 35.62 C +HETATM 2556 CB SEP A 338 20.220 31.868 5.843 1.00 36.98 C +HETATM 2557 OG SEP A 338 19.529 32.909 6.526 1.00 38.75 O +HETATM 2558 C SEP A 338 22.121 33.517 5.710 1.00 36.32 C +HETATM 2559 O SEP A 338 23.245 32.996 6.389 1.00 28.28 O +HETATM 2560 P SEP A 338 18.280 33.605 5.779 1.00 36.73 P +HETATM 2561 O1P SEP A 338 17.256 33.885 6.849 1.00 38.47 O +HETATM 2562 O2P SEP A 338 17.811 32.606 4.750 1.00 39.29 O +HETATM 2563 O3P SEP A 338 18.956 34.824 5.189 1.00 32.24 O \ No newline at end of file diff --git a/modules/db/src/CMakeLists.txt b/modules/db/src/CMakeLists.txt index 7ccafdebd3bd5c0dbea2e72ebef42f05c066af08..8da34460be841e381308fcff5e6ca7e47cd59115 100644 --- a/modules/db/src/CMakeLists.txt +++ b/modules/db/src/CMakeLists.txt @@ -12,7 +12,8 @@ sqlite3.c module(NAME db SOURCES ${OST_DB_SOURCES} HEADERS ${OST_DB_HEADERS} DEPENDS_ON ost_base) +add_definitions(-DSQLITE_OMIT_LOAD_EXTENSION) if(WIN32) set_target_properties(ost_db PROPERTIES LINK_FLAGS "/DEF:sqlite3.def") add_definitions(/DSQLITE_ENABLE_COLUMN_METADATA) -endif(WIN32) \ No newline at end of file +endif(WIN32) diff --git a/modules/geom/pymod/CMakeLists.txt b/modules/geom/pymod/CMakeLists.txt index 240dd87a2465360ea53b669be92eb28ea8b2898a..f79aeac4c2f9c8c127e28b0071c0ef502ba0ac38 100644 --- a/modules/geom/pymod/CMakeLists.txt +++ b/modules/geom/pymod/CMakeLists.txt @@ -16,4 +16,6 @@ set(OST_GEOM_PYMOD_SOURCES export_quat.cc ) -pymod(NAME geom CPP ${OST_GEOM_PYMOD_SOURCES} PY __init__.py) \ No newline at end of file +if (NOT ENABLE_STATIC) + pymod(NAME geom CPP ${OST_GEOM_PYMOD_SOURCES} PY __init__.py) +endif() diff --git a/modules/geom/pymod/export_mat2.cc b/modules/geom/pymod/export_mat2.cc index fa1e382c9c62b7bc7ef789303d41cc88bcca6316..0338f1ddd482fea1c6c5bf0078b262234119374a 100644 --- a/modules/geom/pymod/export_mat2.cc +++ b/modules/geom/pymod/export_mat2.cc @@ -33,6 +33,16 @@ String mat2_repr(const geom::Mat2& m) { << m(1,0) << ", " << m(1,1) << ")"; return ss.str(); } + +list mat2_data(const geom::Mat2& m) +{ + list nrvo; + for(size_t k=0;k<4;++k) { + nrvo.append(m.Data()[k]); + } + return nrvo; +} + void export_Mat2() { using namespace geom; @@ -51,8 +61,11 @@ void export_Mat2() .def(self * self) .def(self * Vec2()) .def(self / Real()) + .def(self == self) + .def(self != self) .def(self_ns::str(self)) .def("__getitem__",Mat2_getitem) .def("__setitem__",Mat2_setitem) + .add_property("data",mat2_data) ; } diff --git a/modules/geom/pymod/export_mat3.cc b/modules/geom/pymod/export_mat3.cc index 4d86381a4db04b747f6834f6e56d5b3890c0de3c..1e543b7d912cb9b20f96f54ba8de2bb902dd5249 100644 --- a/modules/geom/pymod/export_mat3.cc +++ b/modules/geom/pymod/export_mat3.cc @@ -63,6 +63,14 @@ String mat3_repr(const geom::Mat3& m) return ss.str(); } +list mat3_data(const geom::Mat3& m) +{ + list nrvo; + for(size_t k=0;k<9;++k) { + nrvo.append(m.Data()[k]); + } + return nrvo; +} void export_Mat3() { @@ -82,12 +90,15 @@ void export_Mat3() .def(self * self) .def(self *= self) .def(self / Real()) + .def(self == self) + .def(self != self) .def(self_ns::str(self)) .def("__getitem__",Mat3_getitem) .def("__getitem__",Mat3_getslice) .def("__setitem__",Mat3_setitem) .def("__setitem__",Mat3_setslice) .def("GetCol", &Mat3::GetCol) - .def("GetRow", &Mat3::GetRow) + .def("GetRow", &Mat3::GetRow) + .add_property("data",mat3_data) ; } diff --git a/modules/geom/pymod/export_mat4.cc b/modules/geom/pymod/export_mat4.cc index 7a5805dc6c45305fcebc5742428065d9d49f2afe..1745e35b7e64a277eb102497736b343b4089f5d8 100644 --- a/modules/geom/pymod/export_mat4.cc +++ b/modules/geom/pymod/export_mat4.cc @@ -85,6 +85,14 @@ String mat4_repr(const geom::Mat4& m) { return ss.str(); } +list mat4_data(const geom::Mat4& m) +{ + list nrvo; + for(size_t k=0;k<16;++k) { + nrvo.append(m.Data()[k]); + } + return nrvo; +} void export_Mat4() { @@ -104,6 +112,8 @@ void export_Mat4() .def(self *= self) .def(self * Vec4()) .def(self / Real()) + .def(self == self) + .def(self != self) .def(self_ns::str(self)) .def("__repr__", mat4_repr) .def("__getitem__",Mat4_getitem) @@ -115,5 +125,6 @@ void export_Mat4() .def("PasteRotation",&Mat4::PasteRotation) .def("ExtractTranslation",&Mat4::ExtractTranslation) .def("PasteTranslation",&Mat4::PasteTranslation) + .add_property("data",mat4_data) ; } diff --git a/modules/geom/pymod/export_quat.cc b/modules/geom/pymod/export_quat.cc index 7368ede77f65fa3995899c14ebcaecf41add681a..7e233f69c363e9a5c568545c302f8c0a6df3fa1d 100644 --- a/modules/geom/pymod/export_quat.cc +++ b/modules/geom/pymod/export_quat.cc @@ -40,6 +40,7 @@ void export_Quat() .def(self += self) .def(self -= self) .def(self == self) + .def(self != self) .def(-self) .def(self * Real()) .def(self * Quat()) @@ -58,7 +59,6 @@ void export_Quat() ; def("Conjugate",&Conjugate); def("Slerp",&Slerp); - def("Grassman",&Grassmann); def("Normalize",normalize); } diff --git a/modules/geom/pymod/export_vec2.cc b/modules/geom/pymod/export_vec2.cc index eec194418d780663aab9ecfe8e09388067c7f28f..161bda9f6d93b2515d59eb941c785adac4df0d71 100644 --- a/modules/geom/pymod/export_vec2.cc +++ b/modules/geom/pymod/export_vec2.cc @@ -35,6 +35,15 @@ String vec2_repr(const geom::Vec2& v) return ss.str(); } +list vec2_data(const geom::Vec2& v) +{ + list nrvo; + for(size_t k=0;k<2;++k) { + nrvo.append(v.Data()[k]); + } + return nrvo; +} + void export_Vec2() { using namespace geom; @@ -58,6 +67,8 @@ void export_Vec2() .def(self / Real()) .def(self + self) .def(self - self) + .def(self == self) + .def(self != self) .def("__repr__", vec2_repr) .def(self_ns::str(self)) .def("__getitem__",Vec2_getitem) @@ -66,6 +77,7 @@ void export_Vec2() .def("GetY", &Vec2::GetY) .add_property("x", &Vec2::GetX, &Vec2::SetX) .add_property("y", &Vec2::GetY, &Vec2::SetY) + .add_property("data",vec2_data) ; class_<Vec2List>("Vec2List", init<>()) .def(vector_indexing_suite<Vec2List>()) diff --git a/modules/geom/pymod/export_vec3.cc b/modules/geom/pymod/export_vec3.cc index 623671de519d14f73d7843115a5d5b18e74c8da8..aab91add33e3a2fa09378c5e1734789199eb2bfb 100644 --- a/modules/geom/pymod/export_vec3.cc +++ b/modules/geom/pymod/export_vec3.cc @@ -38,6 +38,15 @@ String vec3_repr(const geom::Vec3& v) return ss.str(); } +list vec3_data(const geom::Vec3& v) +{ + list nrvo; + for(size_t k=0;k<3;++k) { + nrvo.append(v.Data()[k]); + } + return nrvo; +} + void export_Vec3() { using namespace geom; @@ -61,6 +70,8 @@ void export_Vec3() .def(self + Real()) .def(Real() + self) .def(self - self) + .def(self == self) + .def(self != self) .def(self_ns::str(self)) .def("__getitem__",Vec3_getitem) .def("__setitem__",Vec3_setitem) @@ -71,6 +82,7 @@ void export_Vec3() .add_property("x", &Vec3::GetX, &Vec3::SetX) .add_property("y", &Vec3::GetY, &Vec3::SetY) .add_property("z", &Vec3::GetZ, &Vec3::SetZ) + .add_property("data",vec3_data) ; def("Normalize", &NormalizeV3); @@ -82,5 +94,7 @@ void export_Vec3() .add_property("center", &Vec3List::GetCenter) .add_property("inertia", &Vec3List::GetInertia) .add_property("principal_axes", &Vec3List::GetPrincipalAxes) + .def("GetODRLine", &Vec3List::GetODRLine) + .def("FitCylinder", &Vec3List::FitCylinder) ; } diff --git a/modules/geom/pymod/export_vec4.cc b/modules/geom/pymod/export_vec4.cc index bb3d80f90cc62205ec40e6fd22a736d05c0b1d20..986fbfa73a8b61b04eb077f75d25026fa0e3dccc 100644 --- a/modules/geom/pymod/export_vec4.cc +++ b/modules/geom/pymod/export_vec4.cc @@ -34,6 +34,15 @@ String vec4_repr(const geom::Vec4& v) return ss.str(); } +list vec4_data(const geom::Vec4& v) +{ + list nrvo; + for(size_t k=0;k<4;++k) { + nrvo.append(v.Data()[k]); + } + return nrvo; +} + void export_Vec4() { using namespace geom; @@ -58,9 +67,16 @@ void export_Vec4() .def(self / Real()) .def(self + self) .def(self - self) + .def(self == self) + .def(self != self) .def(self_ns::str(self)) .def("__getitem__",Vec4_getitem) .def("__setitem__",Vec4_setitem) + .add_property("x", &Vec4::GetX, &Vec4::SetX) + .add_property("y", &Vec4::GetY, &Vec4::SetY) + .add_property("z", &Vec4::GetZ, &Vec4::SetZ) + .add_property("w", &Vec4::GetW, &Vec4::SetW) + .add_property("data",vec4_data) ; } diff --git a/modules/geom/pymod/export_vecmat2_op.cc b/modules/geom/pymod/export_vecmat2_op.cc index 4215e25fdf4cbc28f0dfdc09f5820cb1adc5ea91..8f594681fd9a58b2e50595ece974fa63396fddc9 100644 --- a/modules/geom/pymod/export_vecmat2_op.cc +++ b/modules/geom/pymod/export_vecmat2_op.cc @@ -33,8 +33,11 @@ Real (*Mat2Det)(const Mat2& m) = &Det; Mat2 (*Mat2Invert)(const Mat2& m) = &Invert; Mat2 (*Mat2Transpose)(const Mat2& m) = &Transpose; Real (*Vec2Angle)(const Vec2& v1, const Vec2& v2) = &Angle; +Real (*Vec2SignedAngle)(const Vec2& v1, const Vec2& v2) = &SignedAngle; Vec2 (*Vec2Normalize)(const Vec2& v1) = &Normalize; Vec2 (*Vec2Rotate)(const Vec2& v1,Real ang) = &Rotate; +Vec2 (*Vec2Min)(const Vec2&, const Vec2&) = &Min; +Vec2 (*Vec2Max)(const Vec2&, const Vec2&) = &Max; void export_VecMat2_op() { @@ -51,6 +54,9 @@ void export_VecMat2_op() def("Invert",Mat2Invert); def("Transpose",Mat2Transpose); def("Angle",Vec2Angle); + def("SignedAngle",Vec2SignedAngle); def("Normalize",Vec2Normalize); def("Rotate",Vec2Rotate); + def("Min",Vec2Min); + def("Max",Vec2Max); } diff --git a/modules/geom/pymod/export_vecmat3_op.cc b/modules/geom/pymod/export_vecmat3_op.cc index fe4444b75a176651a700c032895d04a926fc2257..b858001faac7bdaf6485c4433e6acb6b0da69cbd 100644 --- a/modules/geom/pymod/export_vecmat3_op.cc +++ b/modules/geom/pymod/export_vecmat3_op.cc @@ -36,7 +36,10 @@ Mat3 (*Mat3Invert)(const Mat3& m) = &Inver Mat3 (*Mat3Transpose)(const Mat3& m) = &Transpose; Real (*Mat3Comp)(const Mat3& m, unsigned int i, unsigned int j) = &Comp; Real (*Mat3Minor)(const Mat3& m, unsigned int i, unsigned int j) = &Minor; - +Vec3 (*Vec3Min)(const Vec3&, const Vec3&) = &Min; +Vec3 (*Vec3Max)(const Vec3&, const Vec3&) = &Max; +Real (*Vec3Distance2WithPBC)(const Vec3&, const Vec3&, const Vec3&) = &Distance2WithPBC; +Real (*Vec3DistanceWithPBC)(const Vec3&, const Vec3&, const Vec3&) = &DistanceWithPBC; void export_VecMat3_op() { @@ -60,4 +63,12 @@ void export_VecMat3_op() def("EulerTransformation",EulerTransformation); def("AxisRotation",AxisRotation); def("OrthogonalVector",OrthogonalVector); + def("Min",Vec3Min); + def("Max",Vec3Max); + def("Distance2WithPBC",Vec3Distance2WithPBC); + def("DistanceWithPBC",Vec3DistanceWithPBC); + def("MinDistance",MinDistance); + def("MinDistanceWithPBC",MinDistanceWithPBC); + def("WrapVec3",WrapVec3); + def("WrapVec3List",WrapVec3List); } diff --git a/modules/geom/pymod/export_vecmat4_op.cc b/modules/geom/pymod/export_vecmat4_op.cc index 9d91f48bbf9c3e8f6378e6822fdeeeefcd10fd16..af64cef7476c00ee2c31db423ec40af4d3674aa9 100644 --- a/modules/geom/pymod/export_vecmat4_op.cc +++ b/modules/geom/pymod/export_vecmat4_op.cc @@ -36,6 +36,8 @@ Mat4 (*Mat4Transpose)(const Mat4& m) = &Trans Real (*Mat4Comp)(const Mat4& m, unsigned int i, unsigned int j) = &Comp; Real (*Mat4Minor)(const Mat4& m, unsigned int i, unsigned int j) = &Minor; Real (*Vec4Angle)(const Vec4& v1, const Vec4& v2) = &Angle; +Vec4 (*Vec4Min)(const Vec4&, const Vec4&) = &Min; +Vec4 (*Vec4Max)(const Vec4&, const Vec4&) = &Max; void export_VecMat4_op() @@ -55,4 +57,6 @@ void export_VecMat4_op() def("Comp",Mat4Comp); def("Minor",Mat4Minor); def("Angle",Vec4Angle); + def("Min",Vec4Min); + def("Max",Vec4Max); } diff --git a/modules/geom/pymod/wrap_geom.cc b/modules/geom/pymod/wrap_geom.cc index 3c61a57c8b911c6b0a063c8bfedc258529a23011..76bb7930057165463a426f60e133f15314b00618 100644 --- a/modules/geom/pymod/wrap_geom.cc +++ b/modules/geom/pymod/wrap_geom.cc @@ -36,12 +36,12 @@ extern void export_Composite2_op(); extern void export_Composite3_op(); extern void export_Quat(); -namespace { +namespace details { #if (defined(OST_STATIC_PROPERTY_WORKAROUND)) struct Axis_ { - int X() const { return geom::Axis::X; } - int Y() const { return geom::Axis::Y; } - int Z() const { return geom::Axis::Z; } + int X() { return geom::Axis::X; } + int Y() { return geom::Axis::Y; } + int Z() { return geom::Axis::Z; } }; #else struct Axis_ {}; @@ -67,17 +67,17 @@ BOOST_PYTHON_MODULE(_ost_geom) #if (defined(OST_STATIC_PROPERTY_WORKAROUND)) // workaround for a problem with boost python and python 2.6.3/4 - object axis=class_<Axis_>("Axis_") - .add_property("X", &Axis_::X) - .add_property("Y", &Axis_::Y) - .add_property("Z", &Axis_::Z) + class_<details::Axis_> axis("Axis_"); + axis.add_property("X", &details::Axis_::X); + axis.add_property("Y", &details::Axis_::Y); + axis.add_property("Z", &details::Axis_::Z); ; scope().attr("Axis")=axis(); #else - class_<Axis_>("Axis") - .def_readonly("X",geom::Axis::X) - .def_readonly("Y",geom::Axis::Y) - .def_readonly("Z",geom::Axis::Z) + class_<details::Axis_>("Axis") + .def_readonly("X", geom::Axis::X) + .def_readonly("Y", geom::Axis::Y) + .def_readonly("Z", geom::Axis::Z) ; #endif } diff --git a/modules/geom/src/composite3.cc b/modules/geom/src/composite3.cc index 686e843e150c15729acd330cd8bc8d4112249c7f..347629d2c059cd3be0ecdef523ab65363e20adb3 100644 --- a/modules/geom/src/composite3.cc +++ b/modules/geom/src/composite3.cc @@ -224,25 +224,12 @@ Vec3 Rotation3::GetRotationAxis() const } Real Rotation3::GetRotationAngle() const { - return 2.0*acos(q_.GetAngle()); + //return 2.0*acos(q_.GetAngle()); + return q_.GetAngle(); } Mat3 Rotation3::GetRotationMatrix() const { - Real ww = q_.GetAngle()*q_.GetAngle(); - Real wx = q_.GetAngle()*q_.GetAxis().GetX(); - Real wy = q_.GetAngle()*q_.GetAxis().GetY(); - Real wz = q_.GetAngle()*q_.GetAxis().GetZ(); - Real xx = q_.GetAxis().GetX()*q_.GetAxis().GetX(); - Real xy = q_.GetAxis().GetX()*q_.GetAxis().GetY(); - Real xz = q_.GetAxis().GetX()*q_.GetAxis().GetZ(); - Real yy = q_.GetAxis().GetY()*q_.GetAxis().GetY(); - Real yz = q_.GetAxis().GetY()*q_.GetAxis().GetZ(); - Real zz = q_.GetAxis().GetZ()*q_.GetAxis().GetZ(); - - - return Mat3((ww+xx-yy-zz), 2.0*(-wz+xy), 2.0*(wy+xz), - 2.0*(wz+xy), (ww-xx+yy-zz), 2.0*(-wx+yz), - 2.0*(-wy+xz), 2.0*(wx+yz),(ww-xx-yy+zz)); + return q_.ToRotationMatrix(); } void Rotation3::SetOrigin(const Vec3& o) @@ -279,10 +266,7 @@ void Rotation3::SetRotationMatrix(const Mat3& rot) } Vec3 Rotation3::Apply(const Vec3& v) const { - // We can use Conjugate instead of Invert because q is guaranteed to - // be unit Quat - return origin_+(Grassmann(Grassmann(q_,Quat(0,v-origin_)), - Conjugate(q_))).GetAxis(); + return origin_+q_.Rotate(v-origin_); } bool Rotation3::operator==(const Rotation3& rhs) const @@ -299,7 +283,8 @@ Quat Rotation3::generate_from_eulers(Real phi, Real theta, Real psi) } Quat Rotation3::generate_from_axis_angle(const Vec3& axis, Real angle) { - return Quat(cos(angle/2.0),sin(angle/2.0)*Normalize(axis)); + //return Quat(cos(angle/2.0),sin(angle/2.0)*Normalize(axis)); + return Quat(angle, axis); } /* diff --git a/modules/geom/src/composite3_op.cc b/modules/geom/src/composite3_op.cc index 09fb2c72e7430c2fc938534ff4167052485a4b24..87f799d516ab3be540ee287dbb2ceed98fee6d4a 100644 --- a/modules/geom/src/composite3_op.cc +++ b/modules/geom/src/composite3_op.cc @@ -178,5 +178,76 @@ bool IsInSphere(const Sphere& s, const Vec3& v){ return Length(s.GetOrigin()-v)<=s.GetRadius(); } +Line3 Vec3List::FitCylinder(const Vec3 initial_direction, const Vec3 center){ + //This function fits a cylinder to the positions in Vec3List + //It takes as argument an initial guess for the direction and the geometric + //center of the atoms. The center is not changed during optimisation as the + //best fitting cylinder can be shown to have its axis pass through the geometric center + Line3 axis=Line3(center,center+initial_direction), axis_old; + Real radius,res_sum_old,res_sum,delta_0=0.01,prec=0.0000001,err,norm,delta; + unsigned long n_step=1000, n_res=this->size(); + Vec3 v,gradient; + + radius=0.0; + delta=delta_0; + for (Vec3List::const_iterator i=this->begin(),e=this->end(); i!=e; ++i) { + radius+=geom::Distance(axis,(*i)); + } + radius/=Real(n_res); + res_sum=0.0; + for (Vec3List::const_iterator i=this->begin(),e=this->end(); i!=e; ++i) { + res_sum+=pow(Distance(axis,(*i))-radius,2.); + } + unsigned long k=0; + err=2.0*prec; + while (err>prec and k<n_step) { + res_sum_old=res_sum; + axis_old=axis; + radius=0.0; + if (k>50) { + delta=delta_0*pow((50./k),2.0); + } + for (Vec3List::const_iterator i=this->begin(),e=this->end(); i!=e; ++i) { + radius+=Distance(axis,(*i)); + } + radius/=Real(n_res); + for (int j=0; j!=3; ++j){ + res_sum=0.0; + v=Vec3(0.0,0.0,0.0); + v[j]=delta; + axis=Line3(axis_old.GetOrigin(),axis_old.GetOrigin()+axis_old.GetDirection()+v); + radius=0.0; + for (Vec3List::const_iterator i=this->begin(),e=this->end(); i!=e; ++i) { + radius+=Distance(axis,(*i)); + } + radius/=Real(n_res); + for (Vec3List::const_iterator i=this->begin(),e=this->end(); i!=e; ++i) { + res_sum+=pow(Distance(axis,(*i))-radius,2.); + } + gradient[j]=(res_sum-res_sum_old)/delta; + } + norm=Dot(gradient,gradient); + if (norm>1.) { + gradient=Normalize(gradient); + } + axis=Line3(axis_old.GetOrigin(),axis_old.GetOrigin()+axis_old.GetDirection()-delta*gradient); + radius=0.0; + for (Vec3List::const_iterator i=this->begin(),e=this->end(); i!=e; ++i) { + radius+=Distance(axis,(*i)); + } + radius/=Real(n_res); + res_sum=0.0; + for (Vec3List::const_iterator i=this->begin(),e=this->end(); i!=e; ++i) { + res_sum+=pow(Distance(axis,(*i))-radius,2.); + } + err=fabs((res_sum-res_sum_old)/float(n_res)); + k++; + } + if (err>prec) { + std::cout<<"axis fitting did not converge"<<std::endl; + } + return axis; +} + } // ns diff --git a/modules/geom/src/quat.cc b/modules/geom/src/quat.cc index b923a668008fbe908f55bd1a10a584598ea930de..44e39ee2bb71d9c308d07cfb8a43ffa8403e6f8f 100644 --- a/modules/geom/src/quat.cc +++ b/modules/geom/src/quat.cc @@ -287,7 +287,8 @@ Vec3 Quat::GetAxis() const Real Quat::GetAngle() const { - Real ww = std::acos(w/Length(Vec3(x,y,z))); + //Real ww = std::acos(w/Length(Vec3(x,y,z))); + Real ww = 2.0*std::acos(w); return ww; } @@ -454,30 +455,12 @@ Quat Log(const Quat& q) Vec3 Quat::Rotate(const Vec3& vec) const { Quat tmp(0.0, vec[0], vec[1], vec[2]); + // We use Conjugate instead of Invert here because we assume *this to be normalized Quat conj=Conjugate(*this); Quat res=*this*tmp*conj; return Vec3(res.x, res.y, res.z); } -Quat Grassmann(const Quat& lhs, const Quat& rhs) -{ - return Quat(lhs.GetAngle()*rhs.GetAngle()- - lhs.GetAxis().x*rhs.GetAxis().x- - lhs.GetAxis().y*rhs.GetAxis().y- - lhs.GetAxis().z*rhs.GetAxis().z, - lhs.GetAngle()*rhs.GetAxis().x+ - lhs.GetAxis().x*rhs.GetAngle()+ - lhs.GetAxis().y*rhs.GetAxis().z- - lhs.GetAxis().z*rhs.GetAxis().y, - lhs.GetAngle()*rhs.GetAxis().y- - lhs.GetAxis().x*rhs.GetAxis().z+ - lhs.GetAxis().y*rhs.GetAngle()+ - lhs.GetAxis().z*rhs.GetAxis().x, - lhs.GetAngle()*rhs.GetAxis().z+ - lhs.GetAxis().x*rhs.GetAxis().y- - lhs.GetAxis().y*rhs.GetAxis().x+ - lhs.GetAxis().z*rhs.GetAngle()); -} std::ostream& operator<<(std::ostream& str, const Quat& q) { diff --git a/modules/geom/src/quat.hh b/modules/geom/src/quat.hh index 4347952c0068515cfaf7e1ce38714611990fe5bc..881f69b5bdd8a8112eefe3ffc642ceed525efe42 100644 --- a/modules/geom/src/quat.hh +++ b/modules/geom/src/quat.hh @@ -93,6 +93,7 @@ public: Quat& operator/=(const Quat& q); // comparable bool operator==(const Quat& q) const; + bool operator!=(const Quat& q) const { return !this->operator==(q); } // Apply rotation to vector. Vec3 Rotate(const Vec3& vec) const; @@ -115,8 +116,6 @@ Quat DLLEXPORT_OST_GEOM Inv(const Quat& q); Quat DLLEXPORT_OST_GEOM Exp(const Quat& q); Quat DLLEXPORT_OST_GEOM Log(const Quat& q); -Quat DLLEXPORT_OST_GEOM Grassmann(const Quat& lhs, const Quat& rhs); - //normalize quaternion Quat DLLEXPORT_OST_GEOM Normalize(const Quat& q); diff --git a/modules/geom/src/vec3.cc b/modules/geom/src/vec3.cc index 84467ced5a4ddf66dd5ae23e1de054c7cb8e175d..ea07f3cca30b46f4aeef0139d7f4a0a0aab9345b 100644 --- a/modules/geom/src/vec3.cc +++ b/modules/geom/src/vec3.cc @@ -68,5 +68,18 @@ Vec3 Vec3List::GetCenter() const return center/=this->size(); } +Line3 Vec3List::GetODRLine() +{ + Vec3 center=this->GetCenter(); + Vec3 direction=this->GetPrincipalAxes().GetRow(2); + return Line3(center,center+direction); +} +Plane Vec3List::GetODRPlane() +{ + Vec3 origin=this->GetCenter(); + Vec3 normal=this->GetPrincipalAxes().GetRow(0); + return Plane(origin,normal); +} + } diff --git a/modules/geom/src/vec3.hh b/modules/geom/src/vec3.hh index db2b8bb7097dc76d0b74c7906a0ea4a63bda5929..ac3458837fc20245ac7d185a56a58cbf69b8eb08 100644 --- a/modules/geom/src/vec3.hh +++ b/modules/geom/src/vec3.hh @@ -34,7 +34,8 @@ namespace geom { // fw decl class Vec2; class Vec4; - +class Line3; +class Plane; /// \brief Three dimensional vector class, using Real precision. class DLLEXPORT_OST_GEOM Vec3: @@ -193,6 +194,7 @@ inline std::ostream& operator<<(std::ostream& os, const Vec3& v) #include <ost/geom/vec2.hh> #include <ost/geom/vec4.hh> #include <ost/geom/mat3.hh> +#include <ost/geom/composite3.hh> namespace geom { @@ -216,6 +218,10 @@ public: Vec3 GetCenter() const; Mat3 GetPrincipalAxes() const; + Line3 GetODRLine(); + Plane GetODRPlane(); + Line3 FitCylinder(const Vec3 initial_direction, const Vec3 center); + }; diff --git a/modules/geom/src/vecmat2_op.cc b/modules/geom/src/vecmat2_op.cc index 69f2e8e8ce2200b5d6994498b787291ad8b4a247..ea0a4521376d510ccc9db2a0471fe275bd9833cd 100644 --- a/modules/geom/src/vecmat2_op.cc +++ b/modules/geom/src/vecmat2_op.cc @@ -55,11 +55,15 @@ Real Angle(const Vec2& v1, const Vec2& v2) Real SignedAngle(const Vec2& v1, const Vec2& v2) { - Vec3 vc; - vc=Cross(Vec3(v1),Vec3(v2)); - if(Length(v1)==0.0 || Length(v2)==0.0 || Length(vc)==0.0) + if(Length(v1)==0.0 || Length(v2)==0.0){ return 0.0; - return acos(Dot(v1,v2)/Length(v1)/Length(v2))*vc.z/std::fabs(vc.z); + } + Vec3 vc=Cross(Vec3(v1),Vec3(v2)); + Real sign=1.0; + if(vc.z!=0.0){ + sign=vc.z/std::fabs(vc.z); + } + return acos(Dot(v1,v2)/Length(v1)/Length(v2))*sign; } Vec2 Rotate(const Vec2& v,Real ang) diff --git a/modules/geom/src/vecmat3_op.cc b/modules/geom/src/vecmat3_op.cc index 7fb8e2feff5aded2ce280c74e8d9f893465c9b77..50b5b612e939d66e6d8119ddced416ff87e52f99 100644 --- a/modules/geom/src/vecmat3_op.cc +++ b/modules/geom/src/vecmat3_op.cc @@ -142,16 +142,16 @@ Mat3 EulerTransformation(Real theta, Real phi, Real xi) } Vec3 OrthogonalVector(const Vec3& vec) { - if (vec[0] < vec[1]) { - if (vec[0] < vec[2]) + if (std::abs(vec[0]) < std::abs(vec[1])) { + if (std::abs(vec[0]) < std::abs(vec[2])) return Normalize(Cross(vec, Vec3(1, 0, 0)+vec)); else return Normalize(Cross(vec, Vec3(0, 0, 1)+vec)); } else { - if (vec[1] < vec[2]) + if (std::abs(vec[1]) < std::abs(vec[2])) return Normalize(Cross(vec, Vec3(0, 1, 0)+vec)); else - return Normalize(Cross(vec, Vec3(0, 0, 2)+vec)); + return Normalize(Cross(vec, Vec3(0, 0, 1)+vec)); } } @@ -192,19 +192,61 @@ Real DihedralAngle(const Vec3& p1, const Vec3& p2, const Vec3& p3, Dot(r12cross, r23cross)); } + Real MinDistance(const Vec3List& l1, const Vec3List& l2) { // returns the minimal distance between two sets of points (Vec3List) if (l1.size()==0 || l2.size()==0){throw std::runtime_error("cannot calculate minimal distance: empty Vec3List");} - Real min=Distance(*l1.begin(),*l2.begin()); + Real min=Length2(*l1.begin()-*l2.begin()); Real d; for (Vec3List::const_iterator p1=l1.begin(),e1=l1.end(); p1!=e1; p1++) { for (Vec3List::const_iterator p2=l2.begin(),e2=l2.end(); p2!=e2; p2++) { - d=Distance(*p1,*p2); + d=Length2(*p1-*p2); if (d<min) min=d; } } - return min; + return std::sqrt(min); } +Real MinDistanceWithPBC(const Vec3List& l1, const Vec3List& l2, Vec3& basis_vec) +{ + // returns the minimal distance between two sets of points (Vec3List) + // given the periodic boundary condition along x,y,z given in the basis_vec + if (l1.size()==0 || l2.size()==0){throw std::runtime_error("cannot calculate minimal distance: empty Vec3List");} + Real min=Length2(*l1.begin()-*l2.begin()); + Real d; + Vec3 v; + for (int i=0; i<3; i++) { + basis_vec[i]=std::fabs(basis_vec[i]); + } + for (Vec3List::const_iterator p1=l1.begin(),e1=l1.end(); p1!=e1; p1++) { + for (Vec3List::const_iterator p2=l2.begin(),e2=l2.end(); p2!=e2; p2++) { + d=Distance2WithPBC(*p1, *p2, basis_vec); + if (d<min) min=d; + } + } + return std::sqrt(min); +} + +Vec3 WrapVec3(const Vec3& v1,const Vec3& box_center,const Vec3& basis_vec){ + Vec3 v; + Real r; + for (int i=0; i<3; i++) { + r=(v1[i]-box_center[i])/basis_vec[i]; + r=(r > 0.0) ? std::floor(r + 0.5) : std::ceil(r - 0.5); + v[i]=v1[i]-basis_vec[i]*r; + } + return v; +} + +Vec3List WrapVec3List(const Vec3List& vl, const Vec3& box_center,const Vec3& basis_vec){ + Vec3List vl_out; + vl_out.reserve(vl_out.size()); + for (Vec3List::const_iterator v1=vl.begin(),e=vl.end();v1!=e ; v1++) { + vl_out.push_back(WrapVec3(*v1,box_center,basis_vec)); + } + return vl_out; +} + + } // ns diff --git a/modules/geom/src/vecmat3_op.hh b/modules/geom/src/vecmat3_op.hh index 373b9561b1338fe3907e5e37809b4d71b501911f..5489ea9e8f1c48f669053fafa45f14220b52384f 100644 --- a/modules/geom/src/vecmat3_op.hh +++ b/modules/geom/src/vecmat3_op.hh @@ -194,9 +194,34 @@ inline Real Distance(const Vec3& p1, const Vec3& p2) return Length(p1-p2); } + +//! return the squared distance between two points with periodic boundaries in x,y,z given in basis_vec +inline Real Distance2WithPBC(const Vec3& v1, const Vec3& v2, const Vec3& basis_vec){ + Vec3 v; + v=v1-v2; + for (int i=0; i<3; i++) { + if (std::fabs(v[i])>basis_vec[i]/2.){ + v[i]=std::fabs(v[i])-basis_vec[i]*int(std::fabs(v[i])/basis_vec[i]+0.5); + } + } + return Length2(v); +} +//! return the distance between two points with periodic boundaries in x,y,z given in basis_vec +inline Real DistanceWithPBC(const Vec3& v1, const Vec3& v2, const Vec3& basis_vec){ + return sqrt(Distance2WithPBC(v1, v2, basis_vec)); +} //! returns the minimal distance between the points in two Vec3List Real MinDistance(const Vec3List& l1, const Vec3List& l2); +//! returns the minimal distance between the points in two Vec3List +// with periodic boundaries in x,y,z given in basis_vec +Real MinDistanceWithPBC(const Vec3List& l1, const Vec3List& l2, Vec3& basis_vec); + +//!wraps a vector in a box with periodic boundaries +Vec3 WrapVec3(const Vec3& v1,const Vec3& box_center,const Vec3& basis_vec); +//!wraps all the verctors in a Vec3List in a box with periodic boundaries +Vec3List WrapVec3List(const Vec3List& vl,const Vec3& box_center,const Vec3& basis_vec); + } // ns #endif diff --git a/modules/geom/tests/CMakeLists.txt b/modules/geom/tests/CMakeLists.txt index 7a7dace6b3ed006ba13997889693a4b3910949f8..027a167490b6256249a53a4cf1e569a237f3c8af 100644 --- a/modules/geom/tests/CMakeLists.txt +++ b/modules/geom/tests/CMakeLists.txt @@ -7,11 +7,12 @@ set(GEOM_UNITTESTS test_op2.cc test_op3.cc test_op4.cc + test_quat.cc test_vec2.cc test_vec3.cc test_vec4.cc tests.cc - test_repr.py + test_geom.py ) ost_unittest(MODULE geom diff --git a/modules/geom/tests/test_composite3.cc b/modules/geom/tests/test_composite3.cc index 6548b53da1d70c45acb5e39b5ecd5e9584a998a8..f5cd5cf6bfbe0f411490361103e9bf0e13b5c0b9 100644 --- a/modules/geom/tests/test_composite3.cc +++ b/modules/geom/tests/test_composite3.cc @@ -17,6 +17,7 @@ // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA //------------------------------------------------------------------------------ +#include <cmath> #include <ost/geom/geom.hh> #include "helper.hh" @@ -193,4 +194,14 @@ BOOST_AUTO_TEST_CASE(func_composite3) } +BOOST_AUTO_TEST_CASE(rotation3) +{ + Vec3 v(1,0,0); + Rotation3 r(Vec3(0,1,0), 30.0*M_PI/180.0); + Vec3 vrot=r.Apply(v); + BOOST_CHECK_CLOSE(Real(cos(30.0*M_PI/180.0)), Real(vrot[0]), Real(1e-5)); + BOOST_CHECK_SMALL(vrot[1],float(1e-5)); + BOOST_CHECK_CLOSE(Real(-sin(30.0*M_PI/180.0)), Real(vrot[2]), Real(1e-5)); +} + BOOST_AUTO_TEST_SUITE_END() diff --git a/modules/geom/tests/test_geom.py b/modules/geom/tests/test_geom.py new file mode 100644 index 0000000000000000000000000000000000000000..f563add91955b88fcc383b714df2f472a1a9b64e --- /dev/null +++ b/modules/geom/tests/test_geom.py @@ -0,0 +1,85 @@ +#------------------------------------------------------------------------------ +# This file is part of the OpenStructure project <www.openstructure.org> +# +# Copyright (C) 2008-2011 by the OpenStructure authors +# +# This library is free software; you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the Free +# Software Foundation; either version 3.0 of the License, or (at your option) +# any later version. +# This library is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +# details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this library; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +#------------------------------------------------------------------------------ + +import unittest +if __name__== '__main__': + import sys + sys.path.insert(0,"../../../stage/lib64/openstructure/") + sys.path.insert(0,"../../../stage/lib/openstructure/") + +import ost +import ost.geom as geom + +class TestGeom(unittest.TestCase): + def runTest(self): + self.test_repr() + self.test_data() + + def test_repr(self): + v=geom.Vec2(1,2) + v2=eval(repr(v)) + self.assertTrue(geom.Equal(v, v2)) + + v=geom.Vec3(1,2,3) + v2=eval(repr(v)) + self.assertTrue(geom.Equal(v, v2)) + + v=geom.Vec4(1,2,3,4) + v2=eval(repr(v)) + self.assertTrue(geom.Equal(v, v2)) + + m=geom.Mat2(1,2,3,4) + m2=eval(repr(m)) + self.assertTrue(geom.Equal(m, m2)) + + m=geom.Mat3(1,2,3,4,5,6,7,8,9) + m2=eval(repr(m)) + self.assertTrue(geom.Equal(m, m2)) + + m=geom.Mat4(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16) + m2=eval(repr(m)) + self.assertTrue(geom.Equal(m, m2)) + + def test_data(self): + self.assertEqual(geom.Vec2(1,2).data,[1,2]) + self.assertEqual(geom.Vec3(1,2,3).data,[1,2,3]) + self.assertEqual(geom.Vec4(1,2,3,4).data,[1,2,3,4]) + self.assertEqual(geom.Mat2(1,2, + 3,4).data, + [1,2, + 3,4]) + self.assertEqual(geom.Mat3(1,2,3, + 4,5,6, + 7,8,9).data, + [1,2,3, + 4,5,6, + 7,8,9]) + self.assertEqual(geom.Mat4(1,2,3,4, + 5,6,7,8, + 9,10,11,12, + 13,14,15,16).data, + [1,2,3,4, + 5,6,7,8, + 9,10,11,12, + 13,14,15,16]) + +if __name__== '__main__': + from ost import testutils + testutils.RunTests() + diff --git a/modules/geom/tests/test_quat.cc b/modules/geom/tests/test_quat.cc new file mode 100644 index 0000000000000000000000000000000000000000..ccaf9ab2dd4aa7d4730cfd511dcdd7d0ad9fe811 --- /dev/null +++ b/modules/geom/tests/test_quat.cc @@ -0,0 +1,58 @@ +//------------------------------------------------------------------------------ +// This file is part of the OpenStructure project <www.openstructure.org> +// +// Copyright (C) 2008-2011 by the OpenStructure authors +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License as published by the Free +// Software Foundation; either version 3.0 of the License, or (at your option) +// any later version. +// This library is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this library; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +//------------------------------------------------------------------------------ + +#include <ost/geom/geom.hh> + +#include "helper.hh" +using namespace geom; + +#define BOOST_TEST_DYN_LINK +#include <boost/test/unit_test.hpp> + +BOOST_AUTO_TEST_SUITE( geom ) + +BOOST_AUTO_TEST_CASE(init_quat) +{ + // default + Quat q1; + BOOST_CHECK_CLOSE(Real(q1.w), Real(1.0), Real(1.0e-5)); + BOOST_CHECK_CLOSE(Real(q1.x), Real(0.0), Real(1.0e-5)); + BOOST_CHECK_CLOSE(Real(q1.y), Real(0.0), Real(1.0e-5)); + BOOST_CHECK_CLOSE(Real(q1.z), Real(0.0), Real(1.0e-5)); + + Quat q2(2.0,3.0,4.0,5.0); + BOOST_CHECK_CLOSE(Real(q2.w), Real(2.0), Real(1.0e-5)); + BOOST_CHECK_CLOSE(Real(q2.x), Real(3.0), Real(1.0e-5)); + BOOST_CHECK_CLOSE(Real(q2.y), Real(4.0), Real(1.0e-5)); + BOOST_CHECK_CLOSE(Real(q2.z), Real(5.0), Real(1.0e-5)); +} + +BOOST_AUTO_TEST_CASE(quat_rotate) +{ + Vec3 v(1,0,0); + Quat q(30.0*M_PI/180.0,Vec3(0,1,0)); + Vec3 vrot=q.Rotate(v); + BOOST_CHECK_CLOSE(Real(cos(30.0*M_PI/180.0)), Real(vrot[0]), Real(1e-5)); + BOOST_CHECK_SMALL(vrot[1],float(1e-5)); + BOOST_CHECK_CLOSE(Real(-sin(30.0*M_PI/180.0)), Real(vrot[2]), Real(1e-5)); +} + + +BOOST_AUTO_TEST_SUITE_END() + diff --git a/modules/geom/tests/test_repr.py b/modules/geom/tests/test_repr.py deleted file mode 100644 index e69358f20f783c7f8b731de7f13deb569105a0fa..0000000000000000000000000000000000000000 --- a/modules/geom/tests/test_repr.py +++ /dev/null @@ -1,39 +0,0 @@ -import unittest -from ost import geom - -class TestRepr(unittest.TestCase): - def testReprVec2(self): - v=geom.Vec2(1,2) - v2=eval(repr(v)) - assert geom.Equal(v, v2) - - def testReprVec3(self): - v=geom.Vec3(1,2,3) - v2=eval(repr(v)) - assert geom.Equal(v, v2) - - def testReprVec4(self): - v=geom.Vec4(1,2,3,4) - v2=eval(repr(v)) - assert geom.Equal(v, v2) - - def testReprMat2(self): - m=geom.Mat2(1,2,3,4) - m2=eval(repr(m)) - assert geom.Equal(m, m2) - - def testReprMat3(self): - m=geom.Mat3(1,2,3,4,5,6,7,8,9) - m2=eval(repr(m)) - assert geom.Equal(m, m2) - - def testReprMat4(self): - m=geom.Mat4(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16) - m2=eval(repr(m)) - assert geom.Equal(m, m2) - -if __name__ == "__main__": - try: - unittest.main() - except Exception, e: - print e \ No newline at end of file diff --git a/modules/gfx/pymod/CMakeLists.txt b/modules/gfx/pymod/CMakeLists.txt index 210cce509623565695582e20969f818e8f2e042d..a3d8b251dda72f07f6e7394ad4fb3d0996fb4bd4 100644 --- a/modules/gfx/pymod/CMakeLists.txt +++ b/modules/gfx/pymod/CMakeLists.txt @@ -14,13 +14,14 @@ set(OST_GFX_PYMOD_SOURCES export_gradient.cc export_color_ops.cc export_glwin_base.cc + export_exporter.cc ) if (ENABLE_IMG) set(OST_GFX_PYMOD_SOURCES ${OST_GFX_PYMOD_SOURCES} export_map.cc) endif() -pymod(NAME gfx CPP ${OST_GFX_PYMOD_SOURCES} PY __init__.py) +pymod(NAME gfx CPP ${OST_GFX_PYMOD_SOURCES} PY __init__.py py_gfx_obj.py) set(GRADIENT_FILE gradients.xml diff --git a/modules/gfx/pymod/__init__.py b/modules/gfx/pymod/__init__.py index 0cd783f9fa44d36dd8ab1696257b943e1d2732c6..be887c4ab071e3c4f2da12a771e7e1edad6b8b30 100644 --- a/modules/gfx/pymod/__init__.py +++ b/modules/gfx/pymod/__init__.py @@ -17,6 +17,7 @@ # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA #------------------------------------------------------------------------------ from _ost_gfx import * +from py_gfx_obj import PyGfxObj WHITE=Color(1.0,1.0,1.0) BLACK=Color(0.0,0.0,0.0) @@ -243,7 +244,7 @@ def _primlist_add_text(self,text,pos,color=None,point_size=None): if not point_size: point_size=1.0 self._add_text(text,pos,color,point_size) - + PrimList.AddPoint=_primlist_add_point PrimList.AddLine=_primlist_add_line PrimList.AddSphere=_primlist_add_sphere diff --git a/modules/gfx/pymod/export_exporter.cc b/modules/gfx/pymod/export_exporter.cc new file mode 100644 index 0000000000000000000000000000000000000000..655fe54f77282e2d6656142addf51e18006d7f7c --- /dev/null +++ b/modules/gfx/pymod/export_exporter.cc @@ -0,0 +1,38 @@ +//------------------------------------------------------------------------------ +// This file is part of the OpenStructure project <www.openstructure.org> +// +// Copyright (C) 2008-2011 by the OpenStructure authors +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License as published by the Free +// Software Foundation; either version 3.0 of the License, or (at your option) +// any later version. +// This library is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this library; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +//------------------------------------------------------------------------------ +#include <boost/python.hpp> +using namespace boost::python; + +#include <ost/gfx/exporter.hh> +#include <ost/gfx/gost_exporter.hh> +#include <ost/gfx/collada_exporter.hh> + +using namespace ost; +using namespace ost::gfx; + +void export_Exporter() +{ + class_<Exporter, boost::noncopyable>("Exporter", no_init); + + class_<GostExporter, bases<Exporter>, boost::noncopyable>("GostExporter", init<const std::string&>()) + ; + + class_<ColladaExporter, bases<Exporter>, boost::noncopyable>("ColladaExporter", init<const std::string&, optional<float> >()) + ; +} diff --git a/modules/gfx/pymod/export_gfx_obj.cc b/modules/gfx/pymod/export_gfx_obj.cc index 1d2ed62cd446fa5689230ff4eeda73cb5f7d787a..45093dd9bb8927e213c5af627babd19fe9d8f9ce 100644 --- a/modules/gfx/pymod/export_gfx_obj.cc +++ b/modules/gfx/pymod/export_gfx_obj.cc @@ -25,7 +25,6 @@ using namespace ost::gfx; #include "color_by_def.hh" -namespace { // convenience for python void set_mat_amb2(GfxObjBase* b, float c) {b->SetMatAmb(Color(c,c,c,1.0));} void set_mat_diff2(GfxObjBase* b, float c) {b->SetMatDiff(Color(c,c,c,1.0));} @@ -58,7 +57,63 @@ namespace { LOG_INFO("AALines(bool) is deprecated, use SetAALines(bool) instead"); b->SetAALines(f); } -} + + class GfxObjWrap: public GfxObj, public wrapper<GfxObj> + { + public: + GfxObjWrap(const std::string& name): + GfxObj(name) + {} + + virtual geom::AlignedCuboid GetBoundingBox() const + { + if(override f = this->get_override("GetBoundingBox")) { + return f(); + } else { + return GfxObj::GetBoundingBox(); + } + } + + geom::AlignedCuboid default_GetBoundingBox() const { + return GfxObj::GetBoundingBox(); + } + + virtual void CustomRenderGL(RenderPass pass) { + if(override f = this->get_override("_CustomRenderGL")) { + f(pass); + } else { + GfxObj::CustomRenderGL(pass); + } + } + + void default_CustomRenderGL(RenderPass pass) { + GfxObj::CustomRenderGL(pass); + } + + virtual void CustomPreRenderGL(bool rebuild) { + if(override f = this->get_override("_CustomPreRenderGL")) { + f(rebuild); + } else { + GfxObj::CustomPreRenderGL(rebuild); + } + } + + void default_CustomPreRenderGL(bool rebuild) { + GfxObj::CustomPreRenderGL(rebuild); + } + + virtual void InitGL() { + if(override f = this->get_override("_InitGL")) { + f(); + } else { + GfxObj::InitGL(); + } + } + + void default_InitGL() { + GfxObj::InitGL(); + } + }; void export_GfxObj() { @@ -102,9 +157,13 @@ void export_GfxObj() .add_property("opacity",&GfxObjBase::GetOpacity,&GfxObjBase::SetOpacity) COLOR_BY_DEF() ; - //register_ptr_to_python<GfxObjBaseP>(); - class_<GfxObj, boost::shared_ptr<GfxObj>, bases<GfxObjBase>, boost::noncopyable>("GfxObj",no_init) + enum_<RenderPass>("RenderPass") + .value("STANDARD_RENDER_PASS",STANDARD_RENDER_PASS) + .value("TRANSPARENT_RENDER_PASS",TRANSPARENT_RENDER_PASS) + ; + + class_<GfxObjWrap, boost::shared_ptr<GfxObj>, bases<GfxObjBase>, boost::noncopyable>("GfxObj",init<const std::string&>()) .def("GetTF", &GfxObj::GetTF, return_value_policy<copy_const_reference>()) .def("SetTF", &GfxObj::SetTF) .def("FlagRebuild",&GfxObj::FlagRebuild) @@ -116,7 +175,10 @@ void export_GfxObj() .def("GetAALines",&GfxObj::GetAALines) .def("GetLineWidth",&GfxObj::GetLineWidth) .def("GetLineHalo",&GfxObj::GetLineHalo) - ; - //register_ptr_to_python<GfxObjP>(); + .def("GetBoundingBox",&GfxObj::GetBoundingBox, &GfxObjWrap::default_GetBoundingBox) + .def("_CustomRenderGL",&GfxObj::CustomRenderGL, &GfxObjWrap::default_CustomRenderGL) + .def("_CustomPreRenderGL",&GfxObj::CustomPreRenderGL, &GfxObjWrap::default_CustomPreRenderGL) + .def("_InitGL",&GfxObj::InitGL, &GfxObjWrap::default_InitGL) + ; } diff --git a/modules/gfx/pymod/export_gradient.cc b/modules/gfx/pymod/export_gradient.cc index e24cc9cee5fec611fc536b8c0ab5a4e95c3712a1..6cb26cee020a295eb56111aa4101d189470eadc3 100644 --- a/modules/gfx/pymod/export_gradient.cc +++ b/modules/gfx/pymod/export_gradient.cc @@ -26,7 +26,7 @@ using namespace ost; using namespace ost::gfx; namespace { - Gradient* make_gradient(const dict& d) + Gradient* make_gradient_d(const dict& d) { std::auto_ptr<Gradient> grad(new Gradient); list keys = d.keys(); @@ -57,13 +57,42 @@ namespace { } return grad.release(); } + + Gradient* make_gradient_l(const list& l) + { + std::auto_ptr<Gradient> grad(new Gradient); + float mf = len(l)<2 ? 0.0 : 1.0/static_cast<float>(len(l)-1); + for(int i=0;i<len(l);++i) { + float mark = static_cast<float>(i)*mf; + Color col; + object val = l[i]; + extract<Color> cex(val); + if(cex.check()) { + // use gfx.Color + col=cex(); + } else { + // try simple sequence + if(len(val)!=3) { + throw std::runtime_error("expected values of gfx.Color or float triplets"); + } + try { + col=gfx::Color(extract<float>(val[0]),extract<float>(val[1]),extract<float>(val[2])); + } catch (...) { + throw std::runtime_error("expected values of gfx.Color or float triplets"); + } + } + grad->SetColorAt(mark,col); + } + return grad.release(); + } } void export_gradient() { class_<Gradient>("Gradient", init<>()) .def(init<const String&>()) - .def("__init__", make_constructor(make_gradient)) + .def("__init__", make_constructor(make_gradient_d)) + .def("__init__", make_constructor(make_gradient_l)) .def("SetColorAt", &Gradient::SetColorAt) .def("GetColorAt", &Gradient::GetColorAt) .def("GetStops", &Gradient::GetStops) diff --git a/modules/gfx/pymod/export_primitives.cc b/modules/gfx/pymod/export_primitives.cc index 91ce753ed91df2006caf3928438d4ed1937032cc..01b328d7288116ab8c6dcd9e7d86c5c3ad97fb07 100644 --- a/modules/gfx/pymod/export_primitives.cc +++ b/modules/gfx/pymod/export_primitives.cc @@ -25,8 +25,7 @@ using namespace ost::gfx; void export_primitives() { - class_<Primitive, boost::shared_ptr<Primitive>, - bases<GfxNode>, boost::noncopyable>("Primitive", no_init) + class_<Primitive, bases<GfxNode>, boost::noncopyable>("Primitive", no_init) .def("HasOutline", &Primitive::HasOutline) .def("HasFill", &Primitive::HasFill) .def("SetFill", &Primitive::SetFill) @@ -40,10 +39,10 @@ void export_primitives() .def("GetOutlineColor", &Primitive::GetOutlineColor, return_value_policy<copy_const_reference>()) ; - class_<Cuboid, boost::shared_ptr<Cuboid>, bases<Primitive>, + class_<Cuboid, bases<Primitive>, boost::noncopyable>("Cuboid", init<const String&, const geom::Cuboid>()) ; - class_<Quad, boost::shared_ptr<Quad>, bases<Primitive>, + class_<Quad, bases<Primitive>, boost::noncopyable>("Quad", init<const String&, const geom::Vec3&, const geom::Vec3&, const geom::Vec3&, const geom::Vec3&>()) diff --git a/modules/gfx/pymod/export_primlist.cc b/modules/gfx/pymod/export_primlist.cc index b8326509d8ed7065f120ab4760a541b5766e207b..bb986d7e14c1580555d2bb3b4db2fb497c1c9fcc 100644 --- a/modules/gfx/pymod/export_primlist.cc +++ b/modules/gfx/pymod/export_primlist.cc @@ -25,8 +25,90 @@ using namespace boost::python; using namespace ost; using namespace ost::gfx; +#if OST_NUMPY_SUPPORT_ENABLED +#include <numpy/arrayobject.h> +#endif + +namespace { + void add_mesh(PrimList& p, object ova, object ona, object oca, object oia) + { +#if OST_NUMPY_SUPPORT_ENABLED + if(!PyArray_Check(ova.ptr())) { + throw std::runtime_error("ova is not a numpy array"); + } + PyArrayObject* va=reinterpret_cast<PyArrayObject*>(ova.ptr()); + if(!PyArray_ISCONTIGUOUS(va)) { + throw std::runtime_error("expected vertex array to be contiguous"); + } + if(!PyArray_TYPE(va)==NPY_FLOAT) { + throw std::runtime_error("expected vertex array to be of dtype=float32"); + } + size_t v_size=PyArray_SIZE(va); + if(v_size%3!=0) { + throw std::runtime_error("expected vertex array size to be divisible by 3"); + } + size_t v_count=v_size/3; + float* vp=reinterpret_cast<float*>(PyArray_DATA(va)); + float* np=0; + float* cp=0; + if(ona!=object()) { + if(!PyArray_Check(ona.ptr())) { + throw std::runtime_error("ona is not a numpy array"); + } + PyArrayObject* na=reinterpret_cast<PyArrayObject*>(ona.ptr()); + if(!PyArray_ISCONTIGUOUS(na)) { + throw std::runtime_error("expected normal array to be contiguous"); + } + if(!PyArray_TYPE(na)==NPY_FLOAT) { + throw std::runtime_error("expected normal array to be of dtype=float32"); + } + if(PyArray_SIZE(na)!=v_size) { + throw std::runtime_error("expected normal array size to match vertex array size"); + } + np=reinterpret_cast<float*>(PyArray_DATA(na)); + } + if(oca!=object()) { + if(!PyArray_Check(oca.ptr())) { + throw std::runtime_error("oca is not a numpy array"); + } + PyArrayObject* ca=reinterpret_cast<PyArrayObject*>(oca.ptr()); + if(!PyArray_ISCONTIGUOUS(ca)) { + throw std::runtime_error("expected color array to be contiguous"); + } + if(!PyArray_TYPE(ca)==NPY_FLOAT) { + throw std::runtime_error("expected color array to be of dtype=float32"); + } + if(PyArray_SIZE(ca)!=v_count*4) { + throw std::runtime_error("expected color array size to equal vertex-count x 4"); + } + cp=reinterpret_cast<float*>(PyArray_DATA(ca)); + } + if(!PyArray_Check(oia.ptr())) { + throw std::runtime_error("oia is not a numpy array"); + } + PyArrayObject* ia=reinterpret_cast<PyArrayObject*>(oia.ptr()); + if(!PyArray_ISCONTIGUOUS(ia)) { + throw std::runtime_error("expected vertex array to be contiguous"); + } + if(!PyArray_TYPE(ia)==NPY_UINT) { + throw std::runtime_error("expected vertex array to be of dtype=uint32"); + } + size_t i_size=PyArray_SIZE(ia); + unsigned int* ip=reinterpret_cast<unsigned int*>(PyArray_DATA(ia)); + + p.AddMesh(vp,np,cp,v_count,ip,i_size/3); +#else + throw std::runtime_error("AddMesh requires compiled-in numpy support"); +#endif + } +} + void export_primlist() { +#if OST_NUMPY_SUPPORT_ENABLED + import_array(); // magic handshake for numpy module +#endif + class_<PrimList, bases<GfxObj>, boost::shared_ptr<PrimList>, boost::noncopyable>("PrimList", init<const String& >()) .def("Clear",&PrimList::Clear) .def("_add_line",&PrimList::AddLine) @@ -34,6 +116,7 @@ void export_primlist() .def("_add_sphere",&PrimList::AddSphere) .def("_add_cyl",&PrimList::AddCyl) .def("_add_text",&PrimList::AddText) + .def("AddMesh",add_mesh) .def("SetColor",&PrimList::SetColor) .def("SetDiameter",&PrimList::SetDiameter) .def("SetRadius",&PrimList::SetRadius) diff --git a/modules/gfx/pymod/export_scene.cc b/modules/gfx/pymod/export_scene.cc index f5692fad5b197d02c94f024add51392e78f72b2b..8b73a3391ec8a0a8ac5f4e41357b17738320d1d2 100644 --- a/modules/gfx/pymod/export_scene.cc +++ b/modules/gfx/pymod/export_scene.cc @@ -21,6 +21,7 @@ using namespace boost::python; #include <ost/gfx/gfx_object.hh> #include <ost/gfx/scene.hh> +#include <ost/gfx/exporter.hh> using namespace ost; using namespace ost::gfx; @@ -63,6 +64,7 @@ void export_Scene() void (Scene::* export1)(const String&, uint, uint, bool) = &Scene::Export; void (Scene::* export2)(const String&, bool) = &Scene::Export; + void (Scene::* export3)(Exporter*) const = &Scene::Export; void (Scene::*remove1)(const GfxNodeP&) = &Scene::Remove; void (Scene::*remove2)(const String&) = &Scene::Remove; void (Scene::*center_on1)(const String&) = &Scene::CenterOn; @@ -116,6 +118,7 @@ void export_Scene() .def("SetFogColor",&Scene::SetFogColor) .def("GetFogColor",&Scene::GetFogColor) .add_property("fogcol", &Scene::GetFogColor, &Scene::SetFogColor) + .add_property("fog_color", &Scene::GetFogColor, &Scene::SetFogColor) .def("SetFOV",&Scene::SetFOV) .def("GetFOV",&Scene::GetFOV) .add_property("fov", &Scene::GetFOV, &Scene::SetFOV) @@ -159,8 +162,9 @@ void export_Scene() .def("SetLightProp",set_light_prop1) .def("SetLightProp",set_light_prop2) .def("Apply", apply) - .def("Export",export1, arg("transparent")=true) - .def("Export",export2, arg("transparent")=true) + .def("Export",export1, arg("transparent")=false) + .def("Export",export2, arg("transparent")=false) + .def("Export",export3) .def("ExportPov",&Scene::ExportPov, scene_export_pov_overloads()) .def("PushView",&Scene::PushView) @@ -169,14 +173,25 @@ void export_Scene() .def("BlurSnapshot",&Scene::BlurSnapshot) .def("RemoveAll", &Scene::RemoveAll) .def("SetShadow",&Scene::SetShadow) + .add_property("shadow",&Scene::GetShadow,&Scene::SetShadow) .def("SetShadowQuality",&Scene::SetShadowQuality) + .add_property("shadow_quality",&Scene::GetShadowQuality,&Scene::SetShadowQuality) .def("SetShadowWeight",&Scene::SetShadowWeight) + .add_property("shadow_weight",&Scene::GetShadowWeight,&Scene::SetShadowWeight) .def("SetDepthDarkening",&Scene::SetDepthDarkening) .def("SetDepthDarkeningWeight",&Scene::SetDepthDarkeningWeight) .def("SetAmbientOcclusion",&Scene::SetAmbientOcclusion) + .add_property("ambient_occlusion",&Scene::GetAmbientOcclusion,&Scene::SetAmbientOcclusion) + .add_property("ao",&Scene::GetAmbientOcclusion,&Scene::SetAmbientOcclusion) .def("SetAmbientOcclusionWeight",&Scene::SetAmbientOcclusionWeight) + .add_property("ambient_occlusion_weight",&Scene::GetAmbientOcclusionWeight,&Scene::SetAmbientOcclusionWeight) + .add_property("ao_weight",&Scene::GetAmbientOcclusionWeight,&Scene::SetAmbientOcclusionWeight) .def("SetAmbientOcclusionMode",&Scene::SetAmbientOcclusionMode) + .add_property("ambient_occlusion_mode",&Scene::GetAmbientOcclusionMode,&Scene::SetAmbientOcclusionMode) + .add_property("ao_mode",&Scene::GetAmbientOcclusionMode,&Scene::SetAmbientOcclusionMode) .def("SetAmbientOcclusionQuality",&Scene::SetAmbientOcclusionQuality) + .add_property("ambient_occlusion_quality",&Scene::GetAmbientOcclusionQuality,&Scene::SetAmbientOcclusionQuality) + .add_property("ao_quality",&Scene::GetAmbientOcclusionQuality,&Scene::SetAmbientOcclusionQuality) .def("AttachObserver",&Scene::AttachObserver) .def("StartOffscreenMode",&Scene::StartOffscreenMode) .def("StopOffscreenMode",&Scene::StopOffscreenMode) @@ -185,5 +200,7 @@ void export_Scene() .add_property("root_node", &Scene::GetRootNode) .def("SetBeaconOff",&Scene::SetBeaconOff) .def("__getitem__",scene_getitem) + .add_property("show_center",&Scene::GetShowCenter, &Scene::SetShowCenter) + .add_property("fix_center",&Scene::GetFixCenter, &Scene::SetFixCenter) ; } diff --git a/modules/gfx/pymod/py_gfx_obj.py b/modules/gfx/pymod/py_gfx_obj.py new file mode 100644 index 0000000000000000000000000000000000000000..ac91e9073a47b061ee57145e0d3d7b6b6a51dcc5 --- /dev/null +++ b/modules/gfx/pymod/py_gfx_obj.py @@ -0,0 +1,79 @@ +#------------------------------------------------------------------------------ +# This file is part of the OpenStructure project <www.openstructure.org> +# +# Copyright (C) 2008-2011 by the OpenStructure authors +# +# This library is free software; you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the Free +# Software Foundation; either version 3.0 of the License, or (at your option) +# any later version. +# This library is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +# details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this library; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +#------------------------------------------------------------------------------ +import traceback +from _ost_gfx import * + +class PyGfxObj(GfxObj): + def __init__(self,name): + """ + requires a unique name not yet utilized in the Scene; + do not place OpenGL calls in the ctor, use InitGL for + that purpose + """ + GfxObj.__init__(self,name) + self._valid_flag=False + + def _InitGL(self): + try: + self.InitGL() + self._valid_flag=True + except: + traceback.print_exc() + + def InitGL(self): + """ + called once for each OpenGL context (usually one time), + allows one-time OpenGL initialization to be implemented, + such as vbo allocation + """ + pass + + + def _CustomPreRenderGL(self,rebuild): + if not self._valid_flag: + return + try: + self.CustomPreRenderGL(rebuild) + except: + self._valid_flag=False + traceback.print_exc() + + def CustomPreRenderGL(self,rebuild): + """ + called just before CustomRenderGL is called; the flag + indicates that a rebuild is required or was requested + """ + pass + + + def _CustomRenderGL(self,render_pass): + if not self._valid_flag: + return + try: + self.CustomRenderGL(render_pass) + except: + self._valid_flag=False + traceback.print_exc() + + def CustomRenderGL(self,render_pass): + """ + called for each scene refresh + """ + pass + diff --git a/modules/gfx/pymod/scene_observer_proxy.hh b/modules/gfx/pymod/scene_observer_proxy.hh index 63209cb200551e0e9f2f8812374b74c1ef70715c..8ba5faa6be1b1b56c004567dbc6efc3a252f2543 100644 --- a/modules/gfx/pymod/scene_observer_proxy.hh +++ b/modules/gfx/pymod/scene_observer_proxy.hh @@ -16,7 +16,6 @@ using namespace ost; using namespace ost::gfx; -namespace { class SceneObserverProxy: public SceneObserver { public: @@ -75,6 +74,5 @@ private: PyObject* self; }; -} #endif diff --git a/modules/gfx/pymod/wrap_gfx.cc b/modules/gfx/pymod/wrap_gfx.cc index 0198d3a0fb27ae5869ff572b9335e6580737b8e9..28229edf12ada259a25443f363d43db51199291d 100644 --- a/modules/gfx/pymod/wrap_gfx.cc +++ b/modules/gfx/pymod/wrap_gfx.cc @@ -37,6 +37,8 @@ extern void export_primlist(); extern void export_primitives(); extern void export_color(); extern void export_gradient(); +extern void export_Exporter(); + #if OST_IMG_ENABLED extern void export_Map(); #endif @@ -135,6 +137,8 @@ BOOST_PYTHON_MODULE(_ost_gfx) ; #endif + export_primitives(); + export_Exporter(); } diff --git a/modules/gfx/src/CMakeLists.txt b/modules/gfx/src/CMakeLists.txt index 4f23812fd1120c170b45ff54ace477657314d9f2..9309a6af7ebec7fed643e303a732bf1b0c53b4ab 100644 --- a/modules/gfx/src/CMakeLists.txt +++ b/modules/gfx/src/CMakeLists.txt @@ -1,6 +1,7 @@ set(OST_GFX_HEADERS render_pass.hh bitmap_io.hh +collada_exporter.hh color.hh entity.hh entity_fw.hh @@ -37,6 +38,9 @@ module_config.hh primitives.hh povray_fw.hh povray.hh +exporter.hh +exporter_fw.hh +gost_exporter.hh ) set(OST_GFX_COLOR_OPS_HEADERS @@ -89,6 +93,7 @@ endif() set(OST_GFX_SOURCES bitmap_io.cc +collada_exporter.cc color.cc primitives.cc entity.cc @@ -108,6 +113,7 @@ vertex_array.cc vertex_array_helper.cc material.cc povray.cc +gost_exporter.cc texture.cc color_ops/color_op.cc color_ops/by_element_color_op.cc diff --git a/modules/gfx/src/collada_exporter.cc b/modules/gfx/src/collada_exporter.cc new file mode 100644 index 0000000000000000000000000000000000000000..902334f851fc0df651f58f380e3c3771e8ae1e96 --- /dev/null +++ b/modules/gfx/src/collada_exporter.cc @@ -0,0 +1,279 @@ +//------------------------------------------------------------------------------ +// This file is part of the OpenStructure project <www.openstructure.org> +// +// Copyright (C) 2008-2011 by the OpenStructure authors +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License as published by the Free +// Software Foundation; either version 3.0 of the License, or (at your option) +// any later version. +// This library is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this library; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +//------------------------------------------------------------------------------ + +/* + Author: Ansgar Philippsen +*/ + +#include <sstream> +#include <boost/format.hpp> + +#include "collada_exporter.hh" +#include "scene.hh" + +namespace ost { namespace gfx { + +ColladaExporter::ColladaExporter(const std::string& file, float scale): + file_(file), + out_(file_.c_str()), + scale_(scale), + obj_() +{ + out_ << "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"; + out_ << "<COLLADA version=\"1.4.0\" xmlns=\"http://www.collada.org/2005/11/COLLADASchema\">\n"; +} + +ColladaExporter::~ColladaExporter() +{ + out_ << "</COLLADA>\n"; +} + +void ColladaExporter::SceneStart(const Scene* scene) +{ + out_ << " <library_cameras>\n"; + out_ << " <camera id=\"Camera-Camera\" name=\"Camera-Camera\">\n"; + out_ << " <optics>\n"; + out_ << " <technique_common>\n"; + out_ << " <perspective>\n"; + out_ << " <yfov>" << scene->GetFOV() << "</yfov>\n"; + out_ << " <znear>" << scene->GetNear() << "</znear>\n"; + out_ << " <zfar>" << scene->GetFar() << "</zfar>\n"; + out_ << " </perspective>\n"; + out_ << " </technique_common>\n"; + out_ << " </optics>\n"; + out_ << " </camera>\n"; + out_ << " </library_cameras>\n"; + + out_ << " <library_geometries>\n" << std::endl; +} + +void ColladaExporter::SceneEnd(const Scene* scene) +{ + out_ << " </library_geometries>\n" << std::endl; + + out_ << " <library_visual_scenes>\n"; + out_ << " <visual_scene id=\"Scene\" name=\"Scene\">\n"; + + out_ << " <node id=\"Camera\" name=\"Camera\">\n"; + out_ << " <instance_camera url=\"#Camera-Camera\"/>\n"; + out_ << " </node>\n"; + + out_ << " <node id=\"Root\" name=\"Root\">\n"; + out_ << " <matrix>\n"; + geom::Mat4 tm=scene->GetTransform().GetMatrix(); + out_ << " " << tm(0,0) << " " << tm(0,1) << " " << tm(0,2) << " " << tm(0,3) << "\n"; + out_ << " " << tm(1,0) << " " << tm(1,1) << " " << tm(1,2) << " " << tm(1,3) << "\n"; + out_ << " " << tm(2,0) << " " << tm(2,1) << " " << tm(2,2) << " " << tm(2,3) << "\n"; + out_ << " " << tm(3,0) << " " << tm(3,1) << " " << tm(3,2) << " " << tm(3,3) << "\n"; + out_ << " </matrix>\n"; + for(std::vector<std::string>::const_iterator oit=obj_.begin();oit!=obj_.end();++oit) { + out_ << " <node id=\"" << *oit << "\" name=\"" << *oit <<"\">\n"; + out_ << " <instance_geometry url=\"#" << *oit << "\"/>\n"; + out_ << " </node>\n"; + } + out_ << " </node>\n"; + out_ << " </visual_scene>\n"; + out_ << " </library_visual_scenes>\n"; + + out_ << " <scene>\n"; + out_ << " <instance_visual_scene url=\"#Scene\"/>\n"; + out_ << " </scene>\n"; +} + +void ColladaExporter::NodeStart(const std::string& name, NodeType t) +{ + if(name!="Scene") { + obj_.push_back(name); + out_ << "<geometry id=\"" << name << "\" name=\"" << name << "\">\n"; + out_ << " <mesh>\n"; + } +} + +void ColladaExporter::NodeEnd(const std::string& name) +{ + if(name!="Scene") { + out_ << " </mesh>\n"; + out_ << "</geometry>\n"; + } +} + +void ColladaExporter::WriteVertexData(const float* vdata, + const float* ndata, + const float* cdata, + const float* tdata, + size_t stride2, size_t count) +{ + std::string name=obj_.back(); + size_t stride=stride2/sizeof(float); + + out_ << " <source id=\"" << name+"-Positions" << "\">\n"; + out_ << " <float_array count=\"" << count*3 << "\" id=\"" << name+"-Positions-array" << "\">\n"; + if(vdata) { + const float* src=vdata; + for(unsigned int i=0;i<count;++i) { + out_ << scale_*src[0] << " "; + out_ << scale_*src[1] << " "; + out_ << scale_*src[2] << " "; + src+=stride; + } + } else { + for(unsigned int i=0;i<count;++i) { + out_ << "0.0 0.0 0.0 "; + } + } + out_ << " </float_array>\n"; + out_ << " <technique_common>\n"; + out_ << " <accessor count=\"" << count << "\" source=\"#" << name + "-Positions-array" << "\" stride=\"3\">\n"; + out_ << " <param name=\"X\" type=\"float\"/>\n"; + out_ << " <param name=\"Y\" type=\"float\"/>\n"; + out_ << " <param name=\"Z\" type=\"float\"/>\n"; + out_ << " </accessor>\n"; + out_ << " </technique_common>\n"; + out_ << " </source>\n"; + + // normals, lots of code duplication for now + out_ << " <source id=\"" << name+"-Normals" << "\">\n"; + out_ << " <float_array count=\"" << count*3 << "\" id=\"" << name+"-Normals-array" << "\">\n"; + if(ndata) { + const float* src=ndata; + for(unsigned int i=0;i<count;++i) { + out_ << src[0] << " "; + out_ << src[1] << " "; + out_ << src[2] << " "; + src+=stride; + } + } else { + for(unsigned int i=0;i<count;++i) { + out_ << "0.0 0.0 0.0 "; + } + } + out_ << " </float_array>\n"; + out_ << " <technique_common>\n"; + out_ << " <accessor count=\"" << count << "\" source=\"#" << name + "-Normals-array" << "\" stride=\"3\">\n"; + out_ << " <param name=\"X\" type=\"float\"/>\n"; + out_ << " <param name=\"Y\" type=\"float\"/>\n"; + out_ << " <param name=\"Z\" type=\"float\"/>\n"; + out_ << " </accessor>\n"; + out_ << " </technique_common>\n"; + out_ << " </source>\n"; + + // colors, again lots of code duplication + out_ << " <source id=\"" << name+"-Colors" << "\">\n"; + //out_ << " <float_array count=\"" << count*4 << "\" id=\"" << name+"-Colors-array" << "\">\n"; + out_ << " <float_array count=\"" << count*3 << "\" id=\"" << name+"-Colors-array" << "\">\n"; + if(cdata) { + const float* src=cdata; + for(unsigned int i=0;i<count;++i) { + out_ << src[0] << " "; + out_ << src[1] << " "; + out_ << src[2] << " "; + //out_ << src[3] << " "; + src+=stride; + } + } else { + for(unsigned int i=0;i<count;++i) { + out_ << "0.0 0.0 0.0 "; + } + } + out_ << " </float_array>\n"; + out_ << " <technique_common>\n"; + //out_ << " <accessor count=\"" << count << "\" source=\"#" << name + "-Colors-array" << "\" stride=\"4\">\n"; + out_ << " <accessor count=\"" << count << "\" source=\"#" << name + "-Colors-array" << "\" stride=\"3\">\n"; + out_ << " <param name=\"R\" type=\"float\"/>\n"; + out_ << " <param name=\"G\" type=\"float\"/>\n"; + out_ << " <param name=\"B\" type=\"float\"/>\n"; + //out_ << " <param name=\"A\" type=\"float\"/>\n"; + out_ << " </accessor>\n"; + out_ << " </technique_common>\n"; + out_ << " </source>\n"; + + out_ << " <vertices id=\"" << name+"-Vertex" << "\">\n"; + out_ << " <input semantic=\"POSITION\" source =\"#" << name+"-Positions" << "\"/>\n"; + //out_ << " <input semantic=\"NORMAL\" source =\"#" << name+"-Normals" << "\"/>\n"; + //out_ << " <input semantic=\"COLOR\" source =\"#" << name+"-Colors" << "\"/>\n"; + out_ << " </vertices>\n"; +} + +void ColladaExporter::WritePointData(const unsigned int* i, size_t count) +{ +} + +void ColladaExporter::WriteLineData(const unsigned int* ij, size_t count) +{ +} + +void ColladaExporter::WriteTriData(const unsigned int* ijk, size_t count) +{ + std::string name=obj_.back(); + + out_ << " <triangles count=\"" << count << "\">\n"; + out_ << " <input offset=\"0\" semantic=\"VERTEX\" source =\"#" << name+"-Vertex" << "\"/>\n"; + out_ << " <input offset=\"1\" semantic=\"NORMAL\" source =\"#" << name+"-Normals" << "\"/>\n"; + out_ << " <input offset=\"2\" semantic=\"COLOR\" source =\"#" << name+"-Colors" << "\"/>\n"; + out_ << " <p>\n"; + for(unsigned int c=0;c<count*3;c+=3) { + out_ << ijk[c+0] << " "; + out_ << ijk[c+0] << " "; + out_ << ijk[c+0] << " "; + out_ << ijk[c+1] << " "; + out_ << ijk[c+1] << " "; + out_ << ijk[c+1] << " "; + out_ << ijk[c+2] << " "; + out_ << ijk[c+2] << " "; + out_ << ijk[c+2] << " "; + } + out_ << " </p>\n"; + out_ << " </triangles>\n"; +} + +void ColladaExporter::WriteQuadData(const unsigned int* ijkl, size_t count) +{ + std::string name=obj_.back(); + + out_ << " <triangles count=\"" << count << "\">\n"; + out_ << " <input offset=\"0\" semantic=\"VERTEX\" source =\"#" << name+"-Vertex" << "\"/>\n"; + out_ << " <input offset=\"1\" semantic=\"NORMAL\" source =\"#" << name+"-Normals" << "\"/>\n"; + out_ << " <input offset=\"2\" semantic=\"COLOR\" source =\"#" << name+"-Colors" << "\"/>\n"; + out_ << " <p>\n"; + for(unsigned int c=0;c<count*4;c+=4) { + out_ << ijkl[c+0] << " "; + out_ << ijkl[c+0] << " "; + out_ << ijkl[c+0] << " "; + out_ << ijkl[c+1] << " "; + out_ << ijkl[c+1] << " "; + out_ << ijkl[c+1] << " "; + out_ << ijkl[c+2] << " "; + out_ << ijkl[c+2] << " "; + out_ << ijkl[c+2] << " "; + // + out_ << ijkl[c+0] << " "; + out_ << ijkl[c+0] << " "; + out_ << ijkl[c+0] << " "; + out_ << ijkl[c+2] << " "; + out_ << ijkl[c+2] << " "; + out_ << ijkl[c+2] << " "; + out_ << ijkl[c+3] << " "; + out_ << ijkl[c+3] << " "; + out_ << ijkl[c+3] << " "; + } + out_ << " </p>\n"; + out_ << " </triangles>\n"; +} + +}} // ns diff --git a/modules/gfx/src/collada_exporter.hh b/modules/gfx/src/collada_exporter.hh new file mode 100644 index 0000000000000000000000000000000000000000..c0192a10097e6cb0d2b48801431a3be2437509d5 --- /dev/null +++ b/modules/gfx/src/collada_exporter.hh @@ -0,0 +1,62 @@ +//------------------------------------------------------------------------------ +// This file is part of the OpenStructure project <www.openstructure.org> +// +// Copyright (C) 2008-2011 by the OpenStructure authors +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License as published by the Free +// Software Foundation; either version 3.0 of the License, or (at your option) +// any later version. +// This library is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this library; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +//------------------------------------------------------------------------------ +#ifndef OST_GFX_COLLADA_EXPORTER_HH +#define OST_GFX_COLLADA_EXPORTER_HH + +/* + Author: Ansgar Philippsen +*/ + +#include <string> +#include <fstream> +#include <vector> + +#include "module_config.hh" +#include "exporter.hh" + +namespace ost { namespace gfx { + +class DLLEXPORT_OST_GFX ColladaExporter: public Exporter +{ +public: + ColladaExporter(const std::string& collada_file, float scale=1.0); + virtual ~ColladaExporter(); + + // exporter interface + virtual void SceneStart(const Scene* scene); + virtual void SceneEnd(const Scene* scene); + virtual void NodeStart(const std::string& name, NodeType t); + virtual void NodeEnd(const std::string& name); + virtual void WriteVertexData(const float* v, const float* n, const float* c, const float* t, + size_t stride, size_t count); + virtual void WritePointData(const unsigned int* i, size_t count); + virtual void WriteLineData(const unsigned int* ij, size_t count); + virtual void WriteTriData(const unsigned int* ijk, size_t count); + virtual void WriteQuadData(const unsigned int* ijkl, size_t count); + +private: + std::string file_; + std::ofstream out_; + float scale_; + std::vector<std::string> obj_; +}; + +}} // ns + +#endif diff --git a/modules/gfx/src/color.cc b/modules/gfx/src/color.cc index f99de522b962df1c1ce030b74c97a551fb0cd492..f40e69c53629e136a661b380424d4e075419ae50 100644 --- a/modules/gfx/src/color.cc +++ b/modules/gfx/src/color.cc @@ -81,9 +81,9 @@ geom::Vec3 HSVtoRGB(const geom::Vec3& hsv) geom::Vec3 RGBtoHSV(const geom::Vec3& rgb) { geom::Vec3 hsv; - double var_R = ( rgb[0] / 255.0 ); - double var_G = ( rgb[1] / 255.0 ); - double var_B = ( rgb[2] / 255.0 ); + double var_R = ( rgb[0] ); + double var_G = ( rgb[1] ); + double var_B = ( rgb[2] ); double var_Min = std::min(std::min( var_R, var_G), var_B ); double var_Max = std::max(std::max( var_R, var_G), var_B ); @@ -107,13 +107,18 @@ geom::Vec3 RGBtoHSV(const geom::Vec3& rgb) } else if ( var_B == var_Max ){ hsv[0] = ( 2.0 / 3.0 ) + del_G - del_R; } - if ( hsv[0] < 0 ){ - hsv[0] += 1; + if ( hsv[0] < 0.0 ){ + hsv[0] += 1.0; } - if ( hsv[0] > 1 ){ - hsv[0] -= 1; + if ( hsv[0] > 1.0 ){ + hsv[0] -= 1.0; } } + + hsv[0]=hsv[0]*360.0; + hsv[1]=hsv[1]*100.0; + hsv[2]=hsv[2]*100.0; + return hsv; } } // anon ns @@ -126,6 +131,11 @@ geom::Vec3 Color::ToHSV() Color HSV(double h, double s, double v) { + if(h>1.0 || s>1.0 || v>1.0) { + h=h/360.0; + s=s/100.0; + v=v/100.0; + } geom::Vec3 rgb=HSVtoRGB(geom::Vec3(h,s,v)); return Color(rgb[0],rgb[1],rgb[2]); } diff --git a/modules/gfx/src/color.hh b/modules/gfx/src/color.hh index 1fdee9fa64eb146ee45e8a4882e833dc43ee4b0e..533381dbc07d06880f2f2b3ab00a2b1a3e72c0f3 100644 --- a/modules/gfx/src/color.hh +++ b/modules/gfx/src/color.hh @@ -85,6 +85,13 @@ private: float rgba[4]; }; +/*! + \brief HSV color spec + + h: Hue from 0 to 360 (0=red, 120=green, 240=blue) + s: Saturation from 0 (no color) to 100 (full color) + v: Value from 0 (no light, black) to 100 (full light) +*/ Color DLLEXPORT_OST_GFX HSV(double h, double s, double v); DLLEXPORT_OST_GFX std::ostream& operator<<(std::ostream&, const Color& c); diff --git a/modules/gfx/src/entity.cc b/modules/gfx/src/entity.cc index b5f0f6b75c4e6d516caa1bcffa28c26fbbe45ac8..dff4bfa1fb8465036438a59ebdf8f72dc2a3277b 100644 --- a/modules/gfx/src/entity.cc +++ b/modules/gfx/src/entity.cc @@ -54,6 +54,7 @@ #if OST_SHADER_SUPPORT_ENABLED #include "shader.hh" #endif +#include "exporter.hh" namespace ost { @@ -401,6 +402,23 @@ void Entity::CustomRenderPov(PovState& pov) } } +void Entity::Export(Exporter* ex) +{ + ex->NodeStart(GetName(),Exporter::OBJ); + // in the simplest case, just export va + if(rebuild_ || refresh_) { + PreRenderGL(true); + } + + for (RendererMap::iterator it=renderer_.begin(); it!=renderer_.end(); ++it) { + if(it->second->IsEnabled() && it->second->HasDataToRender()){ + it->second->Export(ex); + } + } + + ex->NodeEnd(GetName()); +} + mol::AtomHandle Entity::PickAtom(const geom::Line3& line, Real line_width) { mol::AtomHandle picked_atom; diff --git a/modules/gfx/src/entity.hh b/modules/gfx/src/entity.hh index 7e6d595fa27f0e34c7d4e7eff73732f28dbca6a6..7663fe3782fe053df4eb7f0428d6401da26905c9 100644 --- a/modules/gfx/src/entity.hh +++ b/modules/gfx/src/entity.hh @@ -324,6 +324,8 @@ public: void SetSeqHack(bool b); bool GetSeqHack() const; + virtual void Export(Exporter* ex); + protected: virtual void CustomPreRenderGL(bool flag); diff --git a/modules/gfx/src/exporter.hh b/modules/gfx/src/exporter.hh new file mode 100644 index 0000000000000000000000000000000000000000..20b0601aee6a110a4c713a687db50d4834c5978c --- /dev/null +++ b/modules/gfx/src/exporter.hh @@ -0,0 +1,56 @@ +//------------------------------------------------------------------------------ +// This file is part of the OpenStructure project <www.openstructure.org> +// +// Copyright (C) 2008-2011 by the OpenStructure authors +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License as published by the Free +// Software Foundation; either version 3.0 of the License, or (at your option) +// any later version. +// This library is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this library; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +//------------------------------------------------------------------------------ +#ifndef OST_GFX_EXPORTER_HH +#define OST_GFX_EXPORTER_HH + +#include <ost/gfx/module_config.hh> + +namespace ost { namespace gfx { + +class Scene; + +class DLLEXPORT_OST_GFX Exporter +{ +public: + enum NodeType { + ROOT=1, + GROUP=2, + OBJ=3 + }; + + virtual ~Exporter() {} + virtual void SceneStart(const Scene* scene) {} + virtual void SceneEnd(const Scene* scene) {} + + virtual void NodeStart(const std::string& name, NodeType t) {} + virtual void NodeEnd(const std::string& name) {} + + // this indicates beginning of new data, including a reset of the indices + // may occur more than once for a given node + virtual void WriteVertexData(const float* v, const float* n, const float* c, const float* t, + size_t stride, size_t count) {} + virtual void WritePointData(const unsigned int* i, size_t count) {} + virtual void WriteLineData(const unsigned int* ij, size_t count) {} + virtual void WriteTriData(const unsigned int* ijk, size_t count) {} + virtual void WriteQuadData(const unsigned int* ijkl, size_t count) {} +}; + +}} // ns + +#endif diff --git a/modules/gfx/src/exporter_fw.hh b/modules/gfx/src/exporter_fw.hh new file mode 100644 index 0000000000000000000000000000000000000000..499248014e24d9df5374569c7a66d5227a4c8443 --- /dev/null +++ b/modules/gfx/src/exporter_fw.hh @@ -0,0 +1,28 @@ +//------------------------------------------------------------------------------ +// This file is part of the OpenStructure project <www.openstructure.org> +// +// Copyright (C) 2008-2011 by the OpenStructure authors +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License as published by the Free +// Software Foundation; either version 3.0 of the License, or (at your option) +// any later version. +// This library is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this library; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +//------------------------------------------------------------------------------ +#ifndef OST_GFX_EXPORTER_FW_HH +#define OST_GFX_EXPORTER_FW_HH + +namespace ost { namespace gfx { + + class Exporter; + +}} // ns + +#endif diff --git a/modules/gfx/src/gfx_node.cc b/modules/gfx/src/gfx_node.cc index e7f038a2668e2d4fdd162e00f29e4acd37592881..8d417aeec6660d3ecf3aa689cf68d3e90c781fa7 100644 --- a/modules/gfx/src/gfx_node.cc +++ b/modules/gfx/src/gfx_node.cc @@ -18,9 +18,11 @@ //------------------------------------------------------------------------------ #include <boost/bind.hpp> #include <ost/dyn_cast.hh> + #include "gfx_node.hh" #include "gfx_object.hh" #include "scene.hh" +#include "exporter.hh" namespace ost { namespace gfx { @@ -101,6 +103,16 @@ void GfxNode::RenderPov(PovState& pov) } } +void GfxNode::Export(Exporter* ex) +{ + if(!IsVisible()) return; + ex->NodeStart(GetName(),Exporter::GROUP); + for(GfxNodeVector::iterator it=node_vector_.begin();it!=node_vector_.end();++it) { + (*it)->Export(ex); + } + ex->NodeEnd(GetName()); +} + String GfxNode::GetName() const { return name_; diff --git a/modules/gfx/src/gfx_node.hh b/modules/gfx/src/gfx_node.hh index b211ca8a9ccb7cda837e109a338ac79d33201301..6cff8388518b96924eec6802dad40e5631cf8c4c 100644 --- a/modules/gfx/src/gfx_node.hh +++ b/modules/gfx/src/gfx_node.hh @@ -34,6 +34,7 @@ #include "gfx_object_fw.hh" #include "gfx_node_visitor.hh" #include "povray_fw.hh" +#include "exporter_fw.hh" namespace ost { namespace gfx { @@ -56,10 +57,11 @@ class DLLEXPORT_OST_GFX GfxNode: public boost::enable_shared_from_this<GfxNode> // render all child leaves and nodes virtual void RenderGL(RenderPass pass); - // render all child leaves and nodes into POVray state virtual void RenderPov(PovState& pov); + virtual void Export(Exporter* ex); + // visitor interface virtual void Apply(GfxNodeVisitor& v, GfxNodeVisitor::Stack st); diff --git a/modules/gfx/src/gfx_object.cc b/modules/gfx/src/gfx_object.cc index a7f061e402af59d1a442648a6d238bb4cfc31283..1f0486017c6139adc74134f712d72409486744cd 100644 --- a/modules/gfx/src/gfx_object.cc +++ b/modules/gfx/src/gfx_object.cc @@ -33,6 +33,7 @@ #include "povray.hh" #include "impl/mapped_property.hh" +#include "exporter.hh" #if OST_IMG_ENABLED # include <ost/img/alg/stat.hh> @@ -180,6 +181,9 @@ void GfxObj::RenderGL(RenderPass pass) } } +void GfxObj::InitGL() +{ +} void GfxObj::RenderPov(PovState& pov) { @@ -195,6 +199,20 @@ void GfxObj::RenderPov(PovState& pov) } } + +void GfxObj::Export(Exporter* ex) +{ + if(IsVisible()) { + ex->NodeStart(GetName(),Exporter::OBJ); + // in the simplest case, just export va + if(rebuild_ || refresh_) { + PreRenderGL(true); + } + va_.Export(ex); + ex->NodeEnd(GetName()); + } +} + void GfxObj::Apply(GfxNodeVisitor& v, GfxNodeVisitor::Stack st) { v.VisitObject(this,st); diff --git a/modules/gfx/src/gfx_object.hh b/modules/gfx/src/gfx_object.hh index 1865e7662607ae51624f2c0ec1e5898b41ecb21e..d241be75e19f15158d173554f01384b26cdab15f 100644 --- a/modules/gfx/src/gfx_object.hh +++ b/modules/gfx/src/gfx_object.hh @@ -40,6 +40,7 @@ #include "gfx_prim.hh" #include "vertex_array.hh" #include "input.hh" +#include "exporter_fw.hh" namespace ost { namespace gfx { @@ -56,7 +57,8 @@ public: virtual void DeepSwap(GfxObj& go); virtual void RenderGL(RenderPass pass); virtual void RenderPov(PovState& pov); - virtual void Apply(GfxNodeVisitor& v,GfxNodeVisitor::Stack st); + virtual void Export(Exporter* ex); + virtual void Apply(GfxNodeVisitor& v, GfxNodeVisitor::Stack st); virtual int GetType() const; // @@ -118,6 +120,15 @@ public: */ virtual void CustomRenderGL(RenderPass pass); + // implemented in derived classes to deal with initialization etc + // called just before CustomRenderGL is called + // the boolean flag indicated that a re-build was requested + virtual void CustomPreRenderGL(bool rebuild); + + // implemented in derived classes for first GL initialization + // which should be done here, not in the ctor + virtual void InitGL(); + // implemented in derived classes for the actual POVray export virtual void CustomRenderPov(PovState& pov); @@ -186,7 +197,6 @@ public: protected: void PreRenderGL(bool flag); - virtual void CustomPreRenderGL(bool flag); private: GfxObj(const GfxObj& o); diff --git a/modules/gfx/src/gost_exporter.cc b/modules/gfx/src/gost_exporter.cc new file mode 100644 index 0000000000000000000000000000000000000000..79a6e9b28390f1ce2d1890e88d824de48856e358 --- /dev/null +++ b/modules/gfx/src/gost_exporter.cc @@ -0,0 +1,277 @@ +//------------------------------------------------------------------------------ +// This file is part of the OpenStructure project <www.openstructure.org> +// +// Copyright (C) 2008-2011 by the OpenStructure authors +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License as published by the Free +// Software Foundation; either version 3.0 of the License, or (at your option) +// any later version. +// This library is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this library; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +//------------------------------------------------------------------------------ + +/* + Author: Ansgar Philippsen +*/ + +#include <sstream> + +#include "gost_exporter.hh" +#include "scene.hh" + +namespace ost { namespace gfx { + + namespace { + enum TYPE { + GOST_UNKNOWN=0, + GOST_SCENE=1, + GOST_START_NODE=2, + GOST_END_NODE=3, + GOST_DATA=4, + GOST_FRAME=5 + }; + + enum NODE_TYPE { + GOST_ROOT=1, + GOST_GROUP=2, + GOST_OBJ=3 + }; + + enum DATA_TYPE { + GOST_VDATA=1, + GOST_NDATA=2, + GOST_CDATA=3, + GOST_TDATA=4, + GOST_PINDEX=5, + GOST_LINDEX=6, + GOST_TINDEX=7, + GOST_QINDEX=8 + }; + } + +GostExporter::GostExporter(const std::string& fname): + file_(0) +{ + file_=fopen(fname.c_str(),"w"); + if(!file_) { + std::ostringstream m; + m << "Could not open '" << fname << "' for writing"; + throw Error(m.str()); + } + char headr[]={'G','O','S','T','1','0'}; + fwrite(headr,sizeof(char),6,file_); +} + +GostExporter::~GostExporter() +{ + fclose(file_); + file_=0; +} + +void GostExporter::SceneStart(const Scene* scene) +{ + int type=GOST_SCENE; + int subtype=0; + size_t size=0; + + fwrite(&type,sizeof(int),1,file_); + fwrite(&subtype,sizeof(int),1,file_); + fwrite(&size,sizeof(size_t),1,file_); +} + +void GostExporter::SceneEnd(const Scene* scene) +{} + +void GostExporter::NodeStart(const std::string& name, NodeType t) +{ + int type=GOST_START_NODE; + int subtype=0; + if(t==Exporter::ROOT) subtype=GOST_ROOT; + else if(t==Exporter::GROUP) subtype=GOST_GROUP; + else if(t==Exporter::OBJ) subtype=GOST_OBJ; + size_t size=name.size(); + + fwrite(&type,sizeof(int),1,file_); + fwrite(&subtype,sizeof(int),1,file_); + fwrite(&size,sizeof(size_t),1,file_); + fwrite(name.c_str(),sizeof(char), size,file_); +} + +void GostExporter::NodeEnd(const std::string& name) +{ + int type=GOST_END_NODE; + int subtype=0; + size_t size=0; + + fwrite(&type,sizeof(int),1,file_); + fwrite(&subtype,sizeof(int),1,file_); + fwrite(&size,sizeof(size_t),1,file_); +} + +void GostExporter::WriteVertexData(const float* vdata, const float* ndata, + const float* cdata, const float* tdata, + size_t stride2, size_t count) +{ + std::vector<float> buffer(count*4); + int type=GOST_DATA; + int subtype=0; + size_t size=0; + size_t stride=stride2/sizeof(float); + + if(vdata) { + // positions + subtype=GOST_VDATA; + size=sizeof(float)*3*count+sizeof(size_t); + float* dest=&buffer[0]; + const float* src=vdata; + for(size_t i=0;i<count;++i) { + dest[0]=src[0]; + dest[1]=src[1]; + dest[2]=src[2]; + src+=stride; + dest+=3; + } + fwrite(&type,sizeof(int),1,file_); + fwrite(&subtype,sizeof(int),1,file_); + fwrite(&size,sizeof(size_t),1,file_); + // + fwrite(&count,sizeof(size_t),1,file_); + fwrite(&buffer[0],sizeof(float),3*count,file_); + } + + if(ndata) { + // normals + subtype=GOST_NDATA; + size=sizeof(float)*count*3+sizeof(size_t); + float* dest=&buffer[0]; + const float* src=ndata; + for(size_t i=0;i<count;++i) { + dest[0]=src[0]; + dest[1]=src[1]; + dest[2]=src[2]; + src+=stride; + dest+=3; + } + fwrite(&type,sizeof(int),1,file_); + fwrite(&subtype,sizeof(int),1,file_); + fwrite(&size,sizeof(size_t),1,file_); + // + fwrite(&count,sizeof(size_t),1,file_); + fwrite(&buffer[0],sizeof(float),3*count,file_); + } + + if(cdata) { + // colors + subtype=GOST_CDATA; + size=sizeof(float)*count*4+sizeof(size_t); + float* dest=&buffer[0]; + const float* src=cdata; + for(size_t i=0;i<count;++i) { + dest[0]=src[0]; + dest[1]=src[1]; + dest[2]=src[2]; + dest[3]=src[3]; + src+=stride; + dest+=4; + } + fwrite(&type,sizeof(int),1,file_); + fwrite(&subtype,sizeof(int),1,file_); + fwrite(&size,sizeof(size_t),1,file_); + // + fwrite(&count,sizeof(size_t),1,file_); + fwrite(&buffer[0],sizeof(float),4*count,file_); + } + + if(tdata) { + // texture coordinates + subtype=GOST_TDATA; + size=sizeof(float)*count*2+sizeof(size_t); + float* dest=&buffer[0]; + const float* src=tdata; + for(size_t i=0;i<count;++i) { + dest[0]=src[0]; + dest[1]=src[1]; + src+=stride; + dest+=2; + } + fwrite(&type,sizeof(int),1,file_); + fwrite(&subtype,sizeof(int),1,file_); + fwrite(&size,sizeof(size_t),1,file_); + // + fwrite(&count,sizeof(size_t),1,file_); + fwrite(&buffer[0],sizeof(float),2*count,file_); + } +} + +void GostExporter::WritePointData(const unsigned int* i, size_t count) +{ + int type=GOST_DATA; + int subtype=GOST_PINDEX; + size_t size=sizeof(unsigned int)*count+sizeof(size_t); + fwrite(&type,sizeof(int),1,file_); + fwrite(&subtype,sizeof(int),1,file_); + fwrite(&size,sizeof(size_t),1,file_); + // + fwrite(&count,sizeof(size_t),1,file_); + fwrite(i,sizeof(unsigned int),count,file_); +} + +void GostExporter::WriteLineData(const unsigned int* ij, size_t count) +{ + int type=GOST_DATA; + int subtype=GOST_LINDEX; + size_t size=sizeof(unsigned int)*2*count+sizeof(size_t); + fwrite(&type,sizeof(int),1,file_); + fwrite(&subtype,sizeof(int),1,file_); + fwrite(&size,sizeof(size_t),1,file_); + // + fwrite(&count,sizeof(size_t),1,file_); + fwrite(ij,sizeof(unsigned int),2*count,file_); +} + +void GostExporter::WriteTriData(const unsigned int* ijk, size_t count) +{ + int type=GOST_DATA; + int subtype=GOST_TINDEX; + size_t size=sizeof(unsigned int)*3*count+sizeof(size_t); + fwrite(&type,sizeof(int),1,file_); + fwrite(&subtype,sizeof(int),1,file_); + fwrite(&size,sizeof(size_t),1,file_); + // + fwrite(&count,sizeof(size_t),1,file_); + fwrite(ijk,sizeof(unsigned int),3*count,file_); +} + +void GostExporter::WriteQuadData(const unsigned int* ijkl, size_t count) +{ + int type=GOST_DATA; + int subtype=GOST_QINDEX; + size_t size=sizeof(unsigned int)*4*count+sizeof(size_t); + fwrite(&type,sizeof(int),1,file_); + fwrite(&subtype,sizeof(int),1,file_); + fwrite(&size,sizeof(size_t),1,file_); + // + fwrite(&count,sizeof(size_t),1,file_); + fwrite(ijkl,sizeof(unsigned int),4*count,file_); +} + +void GostExporter::SetFrame(size_t frame) +{ + int type=GOST_FRAME; + int subtype=0; + size_t size=sizeof(size_t); + fwrite(&type,sizeof(int),1,file_); + fwrite(&subtype,sizeof(int),1,file_); + fwrite(&size,sizeof(size_t),1,file_); + // + fwrite(&frame,sizeof(size_t),1,file_); +} + +}} // ns diff --git a/modules/gfx/src/gost_exporter.hh b/modules/gfx/src/gost_exporter.hh new file mode 100644 index 0000000000000000000000000000000000000000..03f47680eeabba9fe36236ff057b5e13f4385c9c --- /dev/null +++ b/modules/gfx/src/gost_exporter.hh @@ -0,0 +1,54 @@ +//------------------------------------------------------------------------------ +// This file is part of the OpenStructure project <www.openstructure.org> +// +// Copyright (C) 2008-2011 by the OpenStructure authors +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License as published by the Free +// Software Foundation; either version 3.0 of the License, or (at your option) +// any later version. +// This library is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this library; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +//------------------------------------------------------------------------------ +#ifndef OST_GFX_GOST_EXPORTER_HH +#define OST_GFX_GOST_EXPORTER_HH + +#include <cstdio> + +#include "exporter.hh" + +namespace ost { namespace gfx { + +class DLLEXPORT_OST_GFX GostExporter: public Exporter +{ +public: + GostExporter(const std::string& fname); + virtual ~GostExporter(); + + // exporter interface + virtual void SceneStart(const Scene* scene); + virtual void SceneEnd(const Scene* scene); + virtual void NodeStart(const std::string& name, NodeType t); + virtual void NodeEnd(const std::string& name); + virtual void WriteVertexData(const float* v, const float* n, const float* c, const float* t, + size_t stride, size_t count); + virtual void WritePointData(const unsigned int* i, size_t count); + virtual void WriteLineData(const unsigned int* ij, size_t count); + virtual void WriteTriData(const unsigned int* ijk, size_t count); + virtual void WriteQuadData(const unsigned int* ijkl, size_t count); + + // gost interface + void SetFrame(size_t f); +private: + FILE* file_; +}; + +}} // ns + +#endif diff --git a/modules/gfx/src/impl/backbone_trace.cc b/modules/gfx/src/impl/backbone_trace.cc index 01bbfb26514dd4118f84c982b0bf93a01a6abf82..ad9e8c961b0cedea3073cdd8183fc636662b5397 100644 --- a/modules/gfx/src/impl/backbone_trace.cc +++ b/modules/gfx/src/impl/backbone_trace.cc @@ -84,11 +84,15 @@ public: // determine atom to add to list mol::AtomHandle ca = res.GetCentralAtom(); if (ca) { + float rad=1.0; + if(ca.HasProp("trace_rad")) { + rad=ca.GetFloatProp("trace_rad"); + } NodeEntry entry={ca, GfxObj::Ele2Color(ca.GetElement()), GfxObj::Ele2Color(ca.GetElement()), geom::Vec3(), // this will be set by the gfx trace obj res.GetCentralNormal(), - 1.0, + rad, geom::Vec3(),geom::Vec3(),geom::Vec3(), // for later use in NA rendering false,id_counter_++}; list_.push_back(entry); @@ -164,7 +168,13 @@ void BackboneTrace::OnUpdatedPositions() for(NodeEntryListList::iterator nitnit=node_list_list_.begin();nitnit!=node_list_list_.end();++nitnit) { NodeEntryList& nlist=*nitnit; for(NodeEntryList::iterator nit=nlist.begin();nit!=nlist.end();++nit) { - nit->normal=nit->atom.GetResidue().GetCentralNormal(); + mol::AtomHandle ca=nit->atom; + nit->normal=ca.GetResidue().GetCentralNormal(); + if(ca.HasProp("trace_rad")) { + nit->rad=ca.GetFloatProp("trace_rad"); + } else { + nit->rad=1.0; + } } PrepList(nlist); } diff --git a/modules/gfx/src/impl/entity_renderer.cc b/modules/gfx/src/impl/entity_renderer.cc index 3464d1292297e3161e3aaed4a1130974b7763fb1..fb22e24a375988bdcb36bf8b9b1b9b0e34695fef 100644 --- a/modules/gfx/src/impl/entity_renderer.cc +++ b/modules/gfx/src/impl/entity_renderer.cc @@ -156,6 +156,11 @@ void EntityRenderer::RenderPov(PovState& pov, const std::string& name) va_.RenderPov(pov,name); } +void EntityRenderer::Export(Exporter* ex) +{ + va_.Export(ex); +} + bool EntityRenderer::HasSelection() const { return (sel_.IsValid() && sel_.GetAtomCount()>0); diff --git a/modules/gfx/src/impl/entity_renderer.hh b/modules/gfx/src/impl/entity_renderer.hh index ceed73fa4d8d2f41a739c949a6e978ae29b18fbc..14c0332c3b5a15d0d0f101b19aad3e9363d03047 100644 --- a/modules/gfx/src/impl/entity_renderer.hh +++ b/modules/gfx/src/impl/entity_renderer.hh @@ -39,8 +39,9 @@ #include <ost/gfx/module_config.hh> #include <ost/gfx/render_pass.hh> #include <ost/gfx/vertex_array.hh> +#include <ost/gfx/exporter_fw.hh> + #include <ost/gfx/render_options/render_options.hh> -#include <ost/gfx/impl/mapped_property.hh> #include <ost/gfx/color_ops/color_op.hh> #include <ost/gfx/color_ops/by_element_color_op.hh> @@ -51,7 +52,9 @@ #if OST_IMG_ENABLED #include <ost/gfx/color_ops/map_handle_color_op.hh> #endif //OST_IMG_ENABLED -#include <ost/gfx/impl/entity_renderer_fw.hh> + +#include "mapped_property.hh" +#include "entity_renderer_fw.hh" namespace ost { namespace gfx { namespace impl { @@ -123,6 +126,9 @@ public: ///\brief povray rendering call virtual void RenderPov(PovState& pov, const std::string& name); + ///\brief scene exporter interface + virtual void Export(Exporter* ex); + virtual bool CanSetOptions(RenderOptionsPtr& render_options)=0; virtual void SetOptions(RenderOptionsPtr& render_options)=0; diff --git a/modules/gfx/src/prim_list.cc b/modules/gfx/src/prim_list.cc index 6113aecfb45e02867496f1c6129a92d9da8db2a1..a9debc0edd67dfa55d9a4057fb9ad0b77bdf4d2f 100644 --- a/modules/gfx/src/prim_list.cc +++ b/modules/gfx/src/prim_list.cc @@ -38,7 +38,8 @@ PrimList::PrimList(const String& name): texts_(), sphere_detail_(4), arc_detail_(4), - simple_va_() + simple_va_(), + vas_() {} void PrimList::Clear() @@ -48,13 +49,14 @@ void PrimList::Clear() spheres_.clear(); cyls_.clear(); texts_.clear(); + vas_.clear(); Scene::Instance().RequestRedraw(); this->FlagRebuild(); } geom::AlignedCuboid PrimList::GetBoundingBox() const { - if(points_.empty() && lines_.empty() && spheres_.empty() && cyls_.empty()) { + if(points_.empty() && lines_.empty() && spheres_.empty() && cyls_.empty() && texts_.empty() && vas_.empty()) { return geom::AlignedCuboid(geom::Vec3(-1,-1,-1),geom::Vec3(1,1,1)); } geom::Vec3 minc(std::numeric_limits<float>::max(), @@ -101,6 +103,11 @@ void PrimList::ProcessLimits(geom::Vec3& minc, geom::Vec3& maxc, minc=geom::Min(minc,tpos); maxc=geom::Max(maxc,tpos); } + for(std::vector<IndexedVertexArray>::const_iterator it=vas_.begin();it!=vas_.end();++it) { + geom::AlignedCuboid bb=it->GetBoundingBox(); + minc=geom::Min(minc,bb.GetMin()); + maxc=geom::Max(maxc,bb.GetMax()); + } minc-=1.0; maxc+=1.0; } @@ -152,12 +159,15 @@ void PrimList::CustomRenderGL(RenderPass pass) va_.RenderGL(); simple_va_.RenderGL(); render_text(); + for(std::vector<IndexedVertexArray>::iterator it=vas_.begin();it!=vas_.end();++it) { + it->RenderGL(); + } } } void PrimList::CustomRenderPov(PovState& pov) { - if(points_.empty() && lines_.empty()) return; + if(points_.empty() && lines_.empty() && spheres_.empty() && cyls_.empty()) return; pov.write_merge_or_union(GetName()); for(SpherePrimList::const_iterator it=points_.begin();it!=points_.end();++it) { @@ -262,6 +272,42 @@ void PrimList::SetColor(const Color& c) FlagRebuild(); } +void PrimList::AddMesh(float* v, float* n, float* c, size_t nv, unsigned int* i, size_t ni) +{ + static float dummy_normal[]={0.0,0.0,1.0}; + static float dummy_color[]={1.0,1.0,1.0,1.0}; + vas_.push_back(IndexedVertexArray()); + IndexedVertexArray& va=vas_.back(); + va.SetLighting(true); + va.SetTwoSided(true); + va.SetColorMaterial(true); + va.SetCullFace(false); + float* vv=v; + float* nn=n; + if(!n) { + nn=dummy_normal; + va.SetLighting(false); + } + float* cc=c; + if(!c) { + cc=dummy_color; + } + for(size_t k=0;k<nv;++k) { + va.Add(geom::Vec3(vv[0],vv[1],vv[2]), + geom::Vec3(nn[0],nn[1],nn[2]), + Color(cc[0],cc[1],cc[2],cc[3])); + vv+=3; + if(n) nn+=3; + if(c) cc+=4; + } + unsigned int* ii=i; + for(size_t k=0;k<ni;++k) { + va.AddTri(ii[0],ii[1],ii[2]); + ii+=3; + } + Scene::Instance().RequestRedraw(); + FlagRebuild(); +} //////////////////////////////// // private methods diff --git a/modules/gfx/src/prim_list.hh b/modules/gfx/src/prim_list.hh index 4e8a4c297ea044eda07d2cc199a4988b3d7e4e23..395e53e2ad22ce359b37281caead22cad1a423e9 100644 --- a/modules/gfx/src/prim_list.hh +++ b/modules/gfx/src/prim_list.hh @@ -139,6 +139,24 @@ class DLLEXPORT_OST_GFX PrimList: public GfxObj // TODO: add point and line pixel width + /*! + \brief add triangle mesh + + v : pointer to nv*3 floats for the positions (mandatory) + n : pointer to nv*3 floats for the normals (may be NULL) + c : pointer to nv*4 floats for the colors (may be NULL) + nv: number of vertices, normals, and colors + i : pointer to ni*3 vertex indices + ni: number of index triplets + + Python interface, using numpy arrays: + + AddMesh(vertex_array, normal_array, color_array, index_array) + + where normal_array and color_array may be None + */ + void AddMesh(float* v, float* n, float* c, size_t nv, unsigned int* i, size_t ni); + protected: virtual void CustomPreRenderGL(bool flag); @@ -152,6 +170,8 @@ class DLLEXPORT_OST_GFX PrimList: public GfxObj unsigned int arc_detail_; IndexedVertexArray simple_va_; + + std::vector<IndexedVertexArray> vas_; void prep_simple_va(); void prep_va(); diff --git a/modules/gfx/src/scene.cc b/modules/gfx/src/scene.cc index 7b7ddce245d1d46502519157a1c65608e1fd4c35..1bd5e460742f0a774bd7e7d46eba5974b4804dd7 100644 --- a/modules/gfx/src/scene.cc +++ b/modules/gfx/src/scene.cc @@ -42,6 +42,7 @@ #include "gl_helper.hh" #include <ost/config.hh> + #include "scene.hh" #include "input.hh" #include "gfx_node.hh" @@ -49,6 +50,7 @@ #include "gfx_test_object.hh" #include "bitmap_io.hh" #include "entity.hh" +#include "exporter.hh" #include "povray.hh" #include "offscreen_buffer.hh" @@ -107,7 +109,8 @@ Scene::Scene(): light_amb_(0.1,0.1,0.1), light_diff_(0.9,0.9,0.9), light_spec_(0.5,0.5,0.5), - axis_flag_(false), + cor_flag_(false), + fix_cor_flag_(true), fog_flag_(true), fog_color_(0.0,0.0,0.0,0.0), auto_autoslab_(true), @@ -194,6 +197,15 @@ void Scene::SetShadowQuality(int q) #endif } +int Scene::GetShadowQuality() const +{ +#if OST_SHADER_SUPPORT_ENABLED + return impl::SceneFX::Instance().shadow_quality; +#else + return 0; +#endif +} + void Scene::SetShadowWeight(float w) { #if OST_SHADER_SUPPORT_ENABLED @@ -202,6 +214,15 @@ void Scene::SetShadowWeight(float w) #endif } +float Scene::GetShadowWeight() const +{ +#if OST_SHADER_SUPPORT_ENABLED + return impl::SceneFX::Instance().shadow_weight; +#else + return 0.0; +#endif +} + void Scene::SetDepthDarkening(bool f) { #if OST_SHADER_SUPPORT_ENABLED @@ -247,6 +268,15 @@ void Scene::SetAmbientOcclusionWeight(float f) #endif } +float Scene::GetAmbientOcclusionWeight() const +{ +#if OST_SHADER_SUPPORT_ENABLED + return impl::SceneFX::Instance().amb_occl_factor; +#else + return 1.0; +#endif +} + void Scene::SetAmbientOcclusionMode(uint m) { #if OST_SHADER_SUPPORT_ENABLED @@ -256,6 +286,15 @@ void Scene::SetAmbientOcclusionMode(uint m) #endif } +uint Scene::GetAmbientOcclusionMode() const +{ +#if OST_SHADER_SUPPORT_ENABLED + return impl::SceneFX::Instance().amb_occl_mode; +#else + return 0; +#endif +} + void Scene::SetAmbientOcclusionQuality(uint m) { #if OST_SHADER_SUPPORT_ENABLED @@ -265,6 +304,15 @@ void Scene::SetAmbientOcclusionQuality(uint m) #endif } +uint Scene::GetAmbientOcclusionQuality() const +{ +#if OST_SHADER_SUPPORT_ENABLED + return impl::SceneFX::Instance().amb_occl_quality; +#else + return 0; +#endif +} + void Scene::SetShadingMode(const std::string& smode) { #if OST_SHADER_SUPPORT_ENABLED @@ -309,12 +357,18 @@ void Scene::SetBeaconOff() namespace { -void set_light_dir(Vec3 ld) -{ - GLfloat l_pos[]={0.0, 0.0, 0.0, 0.0}; - l_pos[0]=-ld[0]; l_pos[1]=-ld[1]; l_pos[2]=-ld[2]; - glLightfv(GL_LIGHT0, GL_POSITION, l_pos); -} + void set_light_dir(Vec3 ld) + { + GLfloat l_pos[]={0.0, 0.0, 0.0, 0.0}; + l_pos[0]=-ld[0]; l_pos[1]=-ld[1]; l_pos[2]=-ld[2]; + glLightfv(GL_LIGHT0, GL_POSITION, l_pos); + } + + struct GfxObjInitGL: public GfxNodeVisitor { + virtual void VisitObject(GfxObj* o, const Stack& st) { + o->InitGL(); + } + }; } @@ -458,6 +512,10 @@ void Scene::InitGL(bool full) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE, GL_REPLACE); + LOG_DEBUG("Scene: calling gl init for all objects"); + GfxObjInitGL initgl; + this->Apply(initgl); + LOG_DEBUG("Scene: gl init done"); gl_init_=true; @@ -776,9 +834,13 @@ void Scene::Add(const GfxNodeP& n, bool redraw) LOG_DEBUG("Scene: graphical object added @" << n.get() << std::endl); - if(root_node_->GetChildCount()==0) { - GfxObjP go = boost::dynamic_pointer_cast<GfxObj>(n); - if(go) { + GfxObjP go = boost::dynamic_pointer_cast<GfxObj>(n); + + if(go) { + if(gl_init_) { + go->InitGL(); + } + if(root_node_->GetChildCount()==0) { SetCenter(go->GetCenter()); } do_autoslab_=true; @@ -957,10 +1019,18 @@ void Scene::OnInput(const InputEvent& e) gluUnProject(wx+2.0,wy+2.0,wz,mm,pm,vp,&ox,&oy,&oz); Vec2 fxy = Vec2(ox,oy); - if(e.GetCommand()==INPUT_COMMAND_TRANSX) { - transform_.ApplyXAxisTranslation(e.GetDelta()*fxy[0]); + if(fix_cor_flag_) { + if(e.GetCommand()==INPUT_COMMAND_TRANSX) { + transform_.SetCenter(transform_.GetCenter()+Transpose(transform_.GetRot())*Vec3(-fxy[0]*e.GetDelta(),0.0,0.0)); + } else { + transform_.SetCenter(transform_.GetCenter()+Transpose(transform_.GetRot())*Vec3(0.0,-fxy[1]*e.GetDelta(),0.0)); + } } else { - transform_.ApplyYAxisTranslation(e.GetDelta()*fxy[1]); + if(e.GetCommand()==INPUT_COMMAND_TRANSX) { + transform_.ApplyXAxisTranslation(e.GetDelta()*fxy[0]); + } else { + transform_.ApplyYAxisTranslation(e.GetDelta()*fxy[1]); + } } } else if(e.GetCommand()==INPUT_COMMAND_TRANSZ) { float currz=transform_.GetTrans()[2]; @@ -1576,6 +1646,13 @@ void Scene::ExportPov(const std::string& fname, const std::string& wdir) pov.write_postamble(); } +void Scene::Export(Exporter* ex) const +{ + ex->SceneStart(this); + root_node_->Export(ex); + ex->SceneEnd(this); +} + void Scene::ResetProjection() { LOG_TRACE("Scene: projection matrix " << fov_ << " " << znear_ << " " << zfar_); @@ -1743,6 +1820,12 @@ void Scene::SetTestMode(bool f) } } +void Scene::SetShowCenter(bool f) +{ + cor_flag_=f; + RequestRedraw(); +} + void Scene::prep_glyphs() { glGenTextures(1,&glyph_tex_id_); @@ -1803,6 +1886,32 @@ void Scene::render_scene() impl::SceneFX::Instance().Preprocess(); #endif + if(cor_flag_) { + geom::Vec3 cen=transform_.GetCenter(); + glPushAttrib(GL_ENABLE_BIT | GL_LIGHTING_BIT | GL_LINE_BIT | GL_CURRENT_BIT); +#if OST_SHADER_SUPPORT_ENABLED + Shader::Instance().PushProgram(); + Shader::Instance().Activate(""); +#endif + glLineWidth(1.5); + glDisable(GL_LIGHTING); + glDisable(GL_COLOR_MATERIAL); + + glBegin(GL_LINES); + glColor3f(0.5,0.5,0.5); + glVertex3f(cen[0]-1.0,cen[1],cen[2]); + glVertex3f(cen[0]+1.0,cen[1],cen[2]); + glVertex3f(cen[0],cen[1]-1.0,cen[2]); + glVertex3f(cen[0],cen[1]+1.0,cen[2]); + glVertex3f(cen[0],cen[1],cen[2]-1.0); + glVertex3f(cen[0],cen[1],cen[2]+1.0); + glEnd(); + glPopAttrib(); +#if OST_SHADER_SUPPORT_ENABLED + Shader::Instance().PopProgram(); +#endif + } + root_node_->RenderGL(STANDARD_RENDER_PASS); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); @@ -1865,7 +1974,7 @@ void Scene::stereo_projection(int view) glFrustum(left,right,bot,top,zn,zf); Real dist = -transform_.GetTrans()[2]+stereo_distance_; glTranslated(0.0,0.0,-dist); - glRotated(180.0/M_PI*atan(0.1*ff/iod),0.0,1.0,0.0); + glRotated(-180.0/M_PI*atan(0.1*ff/iod),0.0,1.0,0.0); glTranslated(0.0,0.0,dist); } else { // correct off-axis frustims @@ -1874,10 +1983,12 @@ void Scene::stereo_projection(int view) // correction of near clipping plane to avoid extreme drifting // of left and right view +#if 0 if(iod*zn/fo<2.0) { zn=2.0*fo/iod; zf=std::max(zn+Real(0.2),zf); } +#endif Real sd = -ff*0.5*iod*zn/fo; left+=sd; @@ -1895,6 +2006,9 @@ void Scene::stereo_projection(int view) void Scene::render_stereo() { + glPushAttrib(GL_ALL_ATTRIB_BITS); + glPushClientAttrib(GL_ALL_ATTRIB_BITS); + int old_stereo_eye=stereo_eye_; stereo_eye_=-1; stereo_projection(-1); @@ -1912,6 +2026,7 @@ void Scene::render_stereo() stereo_eye_=1; stereo_projection(1); render_scene(); + glEnable(GL_TEXTURE_2D); #if OST_SHADER_SUPPORT_ENABLED if(OST_GL_VERSION_2_0) { @@ -1928,7 +2043,6 @@ void Scene::render_stereo() Shader::Instance().Activate(""); #endif - glPushAttrib(GL_ALL_ATTRIB_BITS); glDisable(GL_DEPTH_TEST); glDisable(GL_LIGHTING); glDisable(GL_COLOR_MATERIAL); @@ -1949,7 +2063,7 @@ void Scene::render_stereo() glLoadIdentity(); if(stereo_mode_==2) { - // draw interlace lines in stencil buffer + // draw interlaced lines in stencil buffer glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLineWidth(1.0); glEnable(GL_STENCIL_TEST); @@ -2014,10 +2128,14 @@ void Scene::render_stereo() glEnd(); // restore settings + glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, 0, 0, 0); + glBindTexture(GL_TEXTURE_2D, 0); + glDisable(GL_TEXTURE_2D); glMatrixMode(GL_PROJECTION); glPopMatrix(); glMatrixMode(GL_MODELVIEW); glPopMatrix(); + glPopClientAttrib(); glPopAttrib(); #if OST_SHADER_SUPPORT_ENABLED Shader::Instance().PopProgram(); diff --git a/modules/gfx/src/scene.hh b/modules/gfx/src/scene.hh index 932f7e5a7a0cf8f11a14b2c60f41f759184d8149..a5868d0606581bff66c84b32b5d53f071bc44751 100644 --- a/modules/gfx/src/scene.hh +++ b/modules/gfx/src/scene.hh @@ -42,6 +42,7 @@ #include "scene_observer.hh" #include "gfx_prim.hh" #include "povray_fw.hh" +#include "exporter_fw.hh" namespace ost { namespace gfx { @@ -95,27 +96,25 @@ class DLLEXPORT_OST_GFX Scene { /// \brief turn fog on or off void SetFog(bool f); - /// \brief check fog status bool GetFog() const; - /// \brief set the fog color void SetFogColor(const Color& c); - /// \brief get the fog color Color GetFogColor() const; /// \brief turn shadow mapping on and off void SetShadow(bool f); - /// \brief get shadow mapping status bool GetShadow() const; - /// \brief shadow quality from 0 (low) to 3 (high), default=1 void SetShadowQuality(int q); - + /// \brief get shadow quality + int GetShadowQuality() const; /// \brief multiplier for shadow strength void SetShadowWeight(float w); + /// \brief get shadow strength + float GetShadowWeight() const; /// experimental feature void SetDepthDarkening(bool f); @@ -129,9 +128,15 @@ class DLLEXPORT_OST_GFX Scene { /// experimental feature void SetAmbientOcclusionWeight(float f); /// experimental feature + float GetAmbientOcclusionWeight() const; + /// experimental feature void SetAmbientOcclusionMode(uint m); /// experimental feature + uint GetAmbientOcclusionMode() const; + /// experimental feature void SetAmbientOcclusionQuality(uint q); + /// experimental feature + uint GetAmbientOcclusionQuality() const; /// \brief select shading mode /// one of fallback, basic, default, hf, toon1, toon2 @@ -256,6 +261,10 @@ class DLLEXPORT_OST_GFX Scene { /// \brief export scene into povray files named fname.pov and fname.inc void ExportPov(const std::string& fname, const std::string& wdir="."); + + /// \rbrief export scene via exporter + void Export(Exporter* ex) const; + //@} /// \brief entry point for gui events (internal use) void OnInput(const InputEvent& e); @@ -409,6 +418,17 @@ class DLLEXPORT_OST_GFX Scene { /// \brief stops offline rendering in interactive mode void StopOffscreenMode(); + /// \brief show center of rotation of true + void SetShowCenter(bool f); + + bool GetShowCenter() const {return cor_flag_;} + + /// \brief if true fix center of rotation upon input induced shift + void SetFixCenter(bool f) {fix_cor_flag_=f;} + + /// \brief return flag + bool GetFixCenter() const {return fix_cor_flag_;} + /// experimental feature void SetBlur(uint n); /// experimental feature @@ -472,7 +492,8 @@ private: Color light_diff_; Color light_spec_; - bool axis_flag_; + bool cor_flag_; + bool fix_cor_flag_; bool fog_flag_; Color fog_color_; bool auto_autoslab_; diff --git a/modules/gfx/src/vertex_array.cc b/modules/gfx/src/vertex_array.cc index c1c53d57fa29110368a7b1a5a2da28fb2c7c5612..b9c45e5a7ce54f274b2b1e0b029f100fd81772ec 100644 --- a/modules/gfx/src/vertex_array.cc +++ b/modules/gfx/src/vertex_array.cc @@ -30,6 +30,7 @@ #include "scene.hh" #include "vertex_array_helper.hh" #include "povray.hh" +#include "exporter.hh" #if OST_SHADER_SUPPORT_ENABLED #include "shader.hh" @@ -108,7 +109,7 @@ unsigned int IndexedVertexArray::GetFormat() void IndexedVertexArray::Cleanup() { if(initialized_) { - glDeleteTextures(1,&tex_id_); + //glDeleteTextures(1,&tex_id_); glDeleteLists(outline_mat_dlist_,1); #if OST_SHADER_SUPPORT_ENABLED glDeleteBuffers(7,buffer_id_); @@ -431,6 +432,12 @@ void IndexedVertexArray::RenderGL() glPushAttrib(GL_ALL_ATTRIB_BITS); glPushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT); + + if(use_tex_) { + glEnable(GL_TEXTURE_2D); + } else { + glDisable(GL_TEXTURE_2D); + } if(outline_mode_>0) { LOG_TRACE("outline rendering"); @@ -654,6 +661,14 @@ void IndexedVertexArray::RenderPov(PovState& pov, const std::string& name) pov.inc() << "}\n"; } +void IndexedVertexArray::Export(Exporter* ex) const +{ + ex->WriteVertexData(entry_list_[0].v,entry_list_[0].n, entry_list_[0].c, entry_list_[0].t, sizeof(Entry), entry_list_.size()); + ex->WriteLineData(&line_index_list_[0],line_index_list_.size()/2); + ex->WriteTriData(&tri_index_list_[0],tri_index_list_.size()/3); + ex->WriteQuadData(&quad_index_list_[0],quad_index_list_.size()/4); +} + void IndexedVertexArray::Clear() { dirty_=true; @@ -685,7 +700,7 @@ void IndexedVertexArray::Reset() outline_exp_factor_=0.1; outline_exp_color_=Color(0,0,0); draw_normals_=false; - use_tex_=true; + use_tex_=false; } void IndexedVertexArray::FlagRefresh() diff --git a/modules/gfx/src/vertex_array.hh b/modules/gfx/src/vertex_array.hh index 3d24320e7900985df54c352135b35e173e488d5c..ee63c939aae475959cfa12963b730f7326392df6 100644 --- a/modules/gfx/src/vertex_array.hh +++ b/modules/gfx/src/vertex_array.hh @@ -39,6 +39,7 @@ #include "material.hh" #include "gfx_prim.hh" #include "povray_fw.hh" +#include "exporter_fw.hh" namespace ost { namespace gfx { @@ -162,6 +163,8 @@ class DLLEXPORT_OST_GFX IndexedVertexArray { // POVray export void RenderPov(PovState& pov, const std::string& name); + void Export(Exporter* ex) const; + // only removes the drawing elements void Clear(); // removes all elements and resets internal state to default diff --git a/modules/gfx/tests/test_gfx.py b/modules/gfx/tests/test_gfx.py index b6911eee12fc2a5401a11d1284dc14d1eb7e3f17..ffca3b507ebbc6dfc8fe3d50c1701af75d0f0574 100644 --- a/modules/gfx/tests/test_gfx.py +++ b/modules/gfx/tests/test_gfx.py @@ -1,3 +1,22 @@ +#------------------------------------------------------------------------------ +# This file is part of the OpenStructure project <www.openstructure.org> +# +# Copyright (C) 2008-2011 by the OpenStructure authors +# +# This library is free software; you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the Free +# Software Foundation; either version 3.0 of the License, or (at your option) +# any later version. +# This library is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +# details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this library; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +#------------------------------------------------------------------------------ + import unittest if __name__== '__main__': import sys @@ -9,15 +28,44 @@ import ost.mol as mol import ost.gfx as gfx import ost.geom as geom +if ost.WITH_NUMPY: + has_numpy=True + try: + import numpy + except ImportError, e: + has_numpy=False +else: + has_numpy=False + def col_delta(c1,c2): return geom.Distance(geom.Vec3(c1[0],c1[1],c1[2]),geom.Vec3(c2[0],c2[1],c2[2])) +class MyGfxObj(gfx.GfxObj): + def __init__(self,name): + gfx.GfxObj.__init__(self,name) + self.rendered=False + + def CustomRenderGL(self,render_pass): + self.rendered=True + class TestGfx(unittest.TestCase): def runTest(self): self.test_gradient() self.test_color() self.test_primlist() self.test_entity_reset() + self.test_custom_gfx_obj() + self.test_gfxobj_conv() + + def test_gfxobj_conv(self): + e=mol.CreateEntity() + gfx.Scene().Add(gfx.Entity("foo2",e)) + gfx.Scene()["foo2"].SetColor(gfx.YELLOW) + + def test_custom_gfx_obj(self): + myobj=MyGfxObj("foo") + gfx.Scene().Add(myobj) + #self.assertTrue(myobj.rendered) def test_entity_reset(self): eh=mol.CreateEntity() @@ -32,7 +80,8 @@ class TestGfx(unittest.TestCase): def test_gradient(self): gs=[gfx.Gradient(), - gfx.Gradient({0.0: [1,0,0], 1.0: gfx.Color(0,1,0)})] + gfx.Gradient({0.0: [1,0,0], 1.0: gfx.Color(0,1,0)}), + gfx.Gradient([[1,0,0], gfx.Color(0,1,0)])] gs[0].SetColorAt(0.0,gfx.Color(1.0,0.0,0.0)) gs[0].SetColorAt(1.0,gfx.Color(0.0,1.0,0.0)) for g in gs: @@ -71,7 +120,18 @@ class TestGfx(unittest.TestCase): pl.AddCyl(geom.Vec3(0,0,0),geom.Vec3(1,2,3),radius1=0.5,radius2=0.1,color1=gfx.BLUE,color2=gfx.GREEN) pl.AddText("foo",[0,2,3]) pl.AddText("bar",[-2,0,0],color=gfx.WHITE,point_size=8) + if has_numpy: + pl.AddMesh(numpy.zeros((5,3),dtype=numpy.float32), + numpy.zeros((5,3),dtype=numpy.float32), + numpy.zeros((5,4),dtype=numpy.float32), + numpy.zeros((2,3),dtype=numpy.uint32)) + pl.AddMesh(numpy.zeros((7,3),dtype=numpy.float32), + None, + None, + numpy.zeros((4,3),dtype=numpy.uint32)) + if __name__== '__main__': - unittest.main() + from ost import testutils + testutils.RunTests() diff --git a/modules/gfx/tests/test_gost_export.py b/modules/gfx/tests/test_gost_export.py new file mode 100644 index 0000000000000000000000000000000000000000..efb56861b18f52fae0b92d25e62477b06901fdfe --- /dev/null +++ b/modules/gfx/tests/test_gost_export.py @@ -0,0 +1,22 @@ +import desost_util as util + +e=io.LoadPDB("../../../examples/demos/data/sdh.pdb") + +s=util.CreateSurf(e.Select("chain=A"),density=4) + +scene.Add(gfx.Entity("trace",gfx.TUBE,e.Select("chain=A"))) +scene["trace"].tube_options.arc_detail=8 +scene["trace"].tube_options.spline_detail=8 +scene["trace"].tube_options.tube_radius=1.0 +grad=gfx.Gradient() +grad.SetColorAt(0.0,gfx.RED) +grad.SetColorAt(0.5,gfx.GREEN) +grad.SetColorAt(1.0,gfx.BLUE) +scene["trace"].ColorBy("rnum",grad) + +scene.Add(gfx.Surface("surf",s)) +scene["surf"].ColorBy("rnum",grad) + +if not gui_mode: + ge = gfx.GostExporter("test.gost") + scene.Export(ge) diff --git a/modules/gfx/tests/test_gost_import.py b/modules/gfx/tests/test_gost_import.py new file mode 100644 index 0000000000000000000000000000000000000000..deebd2d31d805c7c0cc190d5ad273262dc7728bf --- /dev/null +++ b/modules/gfx/tests/test_gost_import.py @@ -0,0 +1,15 @@ +import struct + +with open("test.gost","rb") as gf: + + header = gf.read(6) + if str(header[0:4]) != "GOST": + raise RuntimeError("file format mismatch") + raw = gf.read(16) + + while raw: + (type, subtype,size) = struct.unpack("iiL",raw) + print "found type=%d, subtype=%d and blocksize=%u"%(type,subtype,size) + if size>0: + data = gf.read(size) + raw = gf.read(16) diff --git a/modules/gui/pymod/export_data_viewer.cc b/modules/gui/pymod/export_data_viewer.cc index 993f272a8bbf28417568c1118e1b847acb040665..6efdef65e1a980d4a77b4b79111a0e77bd38babf 100644 --- a/modules/gui/pymod/export_data_viewer.cc +++ b/modules/gui/pymod/export_data_viewer.cc @@ -67,12 +67,12 @@ void export_data_viewer() .def("SetData",&DataViewer::SetData) .def("SetName",&DataViewer::SetName) .def("GetOverlayManager",&DataViewer::GetOverlayManager) - .def("GetNormalizer",&DataViewer::GetNormalizer, - return_value_policy<return_by_value>()) + .def("GetNormalizer",&DataViewer::GetNormalizer,return_value_policy<return_by_value>()) .def("Renormalize",&DataViewer::Renormalize) .def("AddOverlay",&DataViewer::AddOverlay,o_AddOverlay()) .def("ClearOverlays",&DataViewer::ClearOverlays) .def("GetSelection",&DataViewer::GetSelection) + .def("SetSelection",&DataViewer::SetSelection) .def("UpdateView",&DataViewer::UpdateView) .def("Recenter",&DataViewer::Recenter) .def("AddDockWidget",add_dock1) @@ -80,6 +80,24 @@ void export_data_viewer() .def("SetSlab", &DataViewer::SetSlab) .def("GetSlab", &DataViewer::GetSlab) .add_property("slab", &DataViewer::GetSlab, &DataViewer::SetSlab) + .def("SetZoomScale", &DataViewer::SetZoomScale) + .def("GetZoomScale", &DataViewer::GetZoomScale) + .add_property("zoomscale", &DataViewer::GetZoomScale, &DataViewer::SetZoomScale) + .def("SetViewerMin", &DataViewer::SetViewerMin) + .def("GetViewerMin", &DataViewer::GetViewerMin) + .add_property("viewer_min", &DataViewer::GetViewerMin, &DataViewer::SetViewerMin) + .def("SetViewerMax", &DataViewer::SetViewerMax) + .def("GetViewerMax", &DataViewer::GetViewerMax) + .add_property("viewer_max", &DataViewer::GetViewerMax, &DataViewer::SetViewerMax) + .def("SetGamma", &DataViewer::SetGamma) + .def("GetGamma", &DataViewer::GetGamma) + .add_property("gamma", &DataViewer::GetGamma, &DataViewer::SetGamma) + .def("SetInvert", &DataViewer::SetInvert) + .def("GetInvert", &DataViewer::GetInvert) + .add_property("invert", &DataViewer::GetInvert, &DataViewer::SetInvert) + .def("SetOffset", &DataViewer::SetOffset) + .def("GetOffset", &DataViewer::GetOffset) + .add_property("offset", &DataViewer::GetOffset, &DataViewer::SetOffset) .def("AddDockWidget",add_dock3) .def("AddDockWidget",add_dock4) .def("RemoveDockWidget",&DataViewer::RemoveDockWidget) diff --git a/modules/gui/pymod/export_tool.cc b/modules/gui/pymod/export_tool.cc index fbcf9375b7ba02a8c23599cd3650a7571f39672a..c5165570e5cf113da1392e422488dbf9acb5feb7 100644 --- a/modules/gui/pymod/export_tool.cc +++ b/modules/gui/pymod/export_tool.cc @@ -32,7 +32,6 @@ using namespace boost::python; using namespace ost::gui; using namespace ost; -namespace { struct WrappedTool : public Tool { @@ -81,7 +80,6 @@ struct WrappedTool : public Tool }; -namespace { void tm_add_tool(ToolManager& tm, QPtr<WrappedTool> tool) { @@ -127,13 +125,10 @@ object get_delta_wrapper(MouseEvent& me) return qpoint_to_bp_object(delta); } -} - ToolOption* (ToolOptions::*get_option_a)(const String&, const String&) const=&ToolOptions::GetOption; ToolOption* (ToolOptions::*get_option_b)(const String&) const=&ToolOptions::GetOption; -} void export_Tool() { diff --git a/modules/gui/pymod/scene/loaders.xml b/modules/gui/pymod/scene/loaders.xml index 90021f812619a5d9cfd78745ff439b0fc9db0819..6c0378641a0dd8c22bd0872058f1d523f72bdd1f 100644 --- a/modules/gui/pymod/scene/loaders.xml +++ b/modules/gui/pymod/scene/loaders.xml @@ -1,8 +1,11 @@ <!DOCTYPE EMDataInfo> <EMDataInfo> <GenericLoaders> + <GenericLoader ExtName="cif" Name="pdb.org (mmCIF)" + Url="http://www.pdb.org/pdb/files/${ID}.cif.gz" Default="1" + FileType="cif.gz"/> <GenericLoader ExtName="pdbredo" Name="pdbredo" Url="http://www.cmbi.ru.nl/pdb_redo/ak/${ID}/${ID}_besttls.pdb" /> - <GenericLoader ExtName="" Name="pdb.org" Url="http://www.pdb.org/pdb/files/${ID}.pdb" Default="1" /> + <GenericLoader ExtName="" Name="pdb.org" FileType="pdb.gz" Url="http://www.pdb.org/pdb/files/${ID}.pdb.gz"/> <GenericLoader ExtName="emdb" Name="emdb" Url="ftp://emdb.rutgers.edu/structures/EMD-${ID}/map/emd_${ID}.map.gz" FileType="map.gz" Img="1"/> </GenericLoaders> </EMDataInfo> diff --git a/modules/gui/pymod/traj.py b/modules/gui/pymod/traj.py index 6df252b35e7db3501fd374b74cbb765d5049b28b..1fcb1c77959528cdda00f05140f89902d4c86863 100644 --- a/modules/gui/pymod/traj.py +++ b/modules/gui/pymod/traj.py @@ -21,12 +21,13 @@ from PyQt4.QtGui import * from ost import * class TrajWidget(QWidget): - def __init__(self, traj=None, render_mode=gfx.SIMPLE, parent=None): + def __init__(self, traj=None, render_mode=gfx.SIMPLE, sel='', parent=None): QWidget.__init__(self, parent, Qt.Tool) self.render_mode=render_mode vb=QVBoxLayout() hb=QHBoxLayout() hb2=QHBoxLayout() + self.selection=sel self.callback=None self._slider=QSlider(self) self._slider.setOrientation(Qt.Horizontal) @@ -116,7 +117,8 @@ class TrajWidget(QWidget): self._traj=traj if self._traj: ev=traj.GetEntity() - self.gfx_entity=gfx.Entity("mol",self.render_mode, ev) + self.gfx_entity=gfx.Entity("mol",self.render_mode, + ev.Select(self.selection)) gfx.Scene().Add(self.gfx_entity) gfx.Scene().CenterOn(self.gfx_entity) # enable the blur effect diff --git a/modules/gui/src/CMakeLists.txt b/modules/gui/src/CMakeLists.txt index c8dc99f72669ed86d28e8cdd768b59ff18b3ad63..50c89edb8b7ee2ee3f3ff059e2fc2128ce72ba11 100644 --- a/modules/gui/src/CMakeLists.txt +++ b/modules/gui/src/CMakeLists.txt @@ -441,7 +441,8 @@ endif() set(QT_USE_QTOPENGL 1) set(QT_USE_QTNETWORK 1) include(${QT_USE_FILE}) -qt4_wrap_cpp(OST_GUI_MOCS "${HEADERS_TO_BE_MOCCED}") +qt4_wrap_cpp(OST_GUI_MOCS "${HEADERS_TO_BE_MOCCED}" + OPTIONS -DBOOST_TT_HAS_OPERATOR_HPP_INCLUDED) module(NAME gui SOURCES ${OST_GUI_MOCS} ${OST_GUI_SOURCES} HEADERS ${OST_GUI_TOOLS_HEADERS} IN_DIR tools ${OST_GUI_SEQUENCE_VIEWER_HEADERS} IN_DIR sequence_viewer @@ -463,7 +464,8 @@ endif() include_directories(${PYTHON_INCLUDE_PATH}) qt4_add_resources(OST_QT_RESOURCE dngr.qrc) -qt4_wrap_cpp(OST_GOSTY_MOC "gosty.hh") +qt4_wrap_cpp(OST_GOSTY_MOC "gosty.hh" + OPTIONS -DBOOST_TT_HAS_OPERATOR_HPP_INCLUDED) # if someone has ANY idea why windows already has the boost program options # symbols defined, please talk to Marco and Juergen. You will be rewarded with # dogfood for a lifetime! diff --git a/modules/gui/src/data_viewer/data_viewer.cc b/modules/gui/src/data_viewer/data_viewer.cc index 14e15380a5c3dbc2e271b8dec3d99cdefb59bea1..2bc7d368f8ce6b178a01d9580de9d7d383edddd2 100644 --- a/modules/gui/src/data_viewer/data_viewer.cc +++ b/modules/gui/src/data_viewer/data_viewer.cc @@ -118,6 +118,12 @@ Extent DataViewer::GetSelection() const return panel_->GetSelection(); } +void DataViewer::SetSelection(const Extent& selection) +{ + assert(panel_); + panel_->SetSelection(selection); +} + void DataViewer::SetName(const String& name) { setWindowTitle(QString::fromStdString(name)); @@ -128,6 +134,66 @@ int DataViewer::GetSlab() const return panel_->GetSlab(); } +void DataViewer::SetZoomScale(Real zoomscale) +{ + panel_->SetZoomScale(zoomscale); +} + +Real DataViewer::GetZoomScale() const +{ + return panel_->GetZoomScale(); +} + +void DataViewer::SetViewerMin(Real min) +{ + panel_->SetViewerMin(min); +} + +Real DataViewer::GetViewerMin() const +{ + return panel_->GetViewerMin(); +} + +void DataViewer::SetViewerMax(Real max) +{ + panel_->SetViewerMax(max); +} + +Real DataViewer::GetViewerMax() const +{ + return panel_->GetViewerMax(); +} + +void DataViewer::SetGamma(Real gamma) +{ + panel_->SetGamma(gamma); +} + +Real DataViewer::GetGamma() const +{ + return panel_->GetGamma(); +} + +void DataViewer::SetInvert(bool invert) +{ + panel_->SetInvert(invert); +} + +bool DataViewer::GetInvert() const +{ + return panel_->GetInvert(); +} + +void DataViewer::SetOffset(const geom::Vec2& offset) +{ + panel_->SetOffset(offset); +} + +geom::Vec2 DataViewer::GetOffset() const +{ + return panel_->GetOffset(); +} + int DataViewer::AddOverlay(const OverlayPtr& ov, bool make_active) { int retval= ov_manager_->AddOverlay(ov,make_active); diff --git a/modules/gui/src/data_viewer/data_viewer.hh b/modules/gui/src/data_viewer/data_viewer.hh index 3fd08f9775ea06762342272e6ce41d5f40737856..e9e417f6b0c6a0076ab728ae8dd60b0dacabf71d 100644 --- a/modules/gui/src/data_viewer/data_viewer.hh +++ b/modules/gui/src/data_viewer/data_viewer.hh @@ -80,6 +80,9 @@ public: //! return currently active selection Extent GetSelection() const; + //! set currently active selection + void SetSelection(const Extent& selection); + //! set the name, displayed as the window title void SetName(const String& name); @@ -101,9 +104,41 @@ public: //! event filter for DataViewerPanel virtual bool eventFilter(QObject * object, QEvent *event); - void SetSlab(int slab); + //! set z slab + void SetSlab(int slab); + //! get z slab int GetSlab() const; + //! set zoom scale (range: 1e-8 to 1e8) + void SetZoomScale(Real zoomscale); + //! get zoom scale (range: 1e-8 to 1e8) + Real GetZoomScale() const; + + //! set minimum level of the viewer (e.g. the value that will be displayed as black) + void SetViewerMin(Real min); + //! get minimum level of the viewer (e.g. the value that will be displayed as black) + Real GetViewerMin() const; + + //! set maximum level of the viewer (e.g. the value that will be displayed as white) + void SetViewerMax(Real max); + //! get maximum level of the viewer (e.g. the value that will be displayed as white) + Real GetViewerMax() const; + + //! set viewer gamma + void SetGamma(Real gamma); + //! get viewer gamma + Real GetGamma() const; + + //! set invert flag + void SetInvert(bool invert); + //! get invert flag + bool GetInvert() const; + + //! set image offset + void SetOffset(const geom::Vec2& offset); + //! get image offset + geom::Vec2 GetOffset() const; + signals: void released(); diff --git a/modules/gui/src/data_viewer/data_viewer_panel_base.cc b/modules/gui/src/data_viewer/data_viewer_panel_base.cc index ec113e525419d81359650d68106d9a868ec9d7e6..eb53154eef140a11ab9d215ab5a5137ce0127821 100644 --- a/modules/gui/src/data_viewer/data_viewer_panel_base.cc +++ b/modules/gui/src/data_viewer/data_viewer_panel_base.cc @@ -46,7 +46,7 @@ namespace ost { namespace img { namespace gui { DataViewerPanelBase::DataViewerPanelBase(const Data& data,QWidget* parent): QWidget(parent), DataObserver(data), - popupmenu_(new QMenu), + popupmenu_(new QMenu(this)), data_min_(0.0), data_max_(0.0), data_min_pos_(), @@ -643,6 +643,18 @@ Extent DataViewerPanelBase::GetSelection() const return selection_; } +void DataViewerPanelBase::SetSelection(const Extent& selection) +{ + selection_=selection; + update_rubberband_from_selection_(); + if(selection==Extent()){ + rubberband_->hide(); + }else{ + rubberband_->show(); + } + UpdateView(false); +} + Real DataViewerPanelBase::GetZoomScale() const { return zoom_scale_; @@ -782,7 +794,7 @@ void DataViewerPanelBase::extract_ri() void DataViewerPanelBase::zoom(int d) { - // maximal zoom = 2^8, therefore zoom_level_ goes from 8 to 8 and delta from -16 to 16 + // maximal zoom = 2^8, therefore zoom_level_ goes from -8 to 8 and delta from -16 to 16 int old_zoom_level=zoom_level_; int dl=std::max(d,-16); dl=std::min(dl,16); @@ -927,6 +939,53 @@ void DataViewerPanelBase::SetInvert(bool invert) UpdateView(true); } +Real DataViewerPanelBase::GetGamma() const +{ + return normalizer_->GetGamma(); +} + +void DataViewerPanelBase::SetGamma(Real gamma) +{ + UpdateNormalizer(normalizer_->GetMinimum(), + normalizer_->GetMaximum(), + gamma,normalizer_->GetInvert()); + UpdateView(true); +} + +Real DataViewerPanelBase::GetViewerMin() const +{ + return normalizer_->GetMinimum(); +} + +void DataViewerPanelBase::SetViewerMin(Real min) +{ + UpdateNormalizer(min,normalizer_->GetMaximum(),normalizer_->GetGamma(),normalizer_->GetInvert()); + UpdateView(true); +} + +Real DataViewerPanelBase::GetViewerMax() const +{ + return normalizer_->GetMaximum(); +} + +void DataViewerPanelBase::SetViewerMax(Real max) +{ + UpdateNormalizer(normalizer_->GetMinimum(),max,normalizer_->GetGamma(),normalizer_->GetInvert()); + UpdateView(true); +} + +geom::Vec2 DataViewerPanelBase::GetOffset() const +{ + return geom::Vec2(offset_x_,offset_y_); +} + +void DataViewerPanelBase::SetOffset(const geom::Vec2& offset) +{ + offset_x_=offset[0]; + offset_y_=offset[1]; + UpdateView(true); +} + void DataViewerPanelBase::SetAntialiasing(bool f) { antialiasing_=f; diff --git a/modules/gui/src/data_viewer/data_viewer_panel_base.hh b/modules/gui/src/data_viewer/data_viewer_panel_base.hh index 60999a9003355073ef1810d7067c0a7f635a0847..4c4b59bb5df8bb4df9853d6f10dd42d577e78ed0 100644 --- a/modules/gui/src/data_viewer/data_viewer_panel_base.hh +++ b/modules/gui/src/data_viewer/data_viewer_panel_base.hh @@ -101,6 +101,9 @@ public: */ Extent GetSelection() const; + //! set currently active selection + void SetSelection(const Extent& extent); + //! convert window coordinates to image point Point WinToPoint(int mx, int my) const; Point WinToPoint(const QPoint& p) const; @@ -174,6 +177,12 @@ public: Real GetDataMax() const; bool GetInvert() const; void SetInvert(bool invert); + Real GetGamma() const; + void SetGamma(Real gamma); + void SetViewerMin(Real min); + Real GetViewerMin() const; + void SetViewerMax(Real max); + Real GetViewerMax() const; void UpdateNormalizer(Real min, Real max, Real gamma, bool invert); int GetSlab(); void SetSlab(int slab); @@ -181,6 +190,10 @@ public: int GetSelectionMode(); void SetAntialiasing(bool f); bool GetAntialiasing() const; + geom::Vec2 GetOffset() const; + void SetOffset(const geom::Vec2& offset); + + signals: void clicked(const geom::Vec3& mousepos); diff --git a/modules/gui/src/data_viewer/info_panel.cc b/modules/gui/src/data_viewer/info_panel.cc index 34f1790aa10636f60aa6fda2a8897de3dc044175..f90d45b17feb18b469fb205e4ad36f684f395932 100644 --- a/modules/gui/src/data_viewer/info_panel.cc +++ b/modules/gui/src/data_viewer/info_panel.cc @@ -46,18 +46,18 @@ InfoPanelLabel::InfoPanelLabel(const QString& t, QWidget* parent): InfoPanel::InfoPanel(QWidget* parent): QWidget(parent), - image_extent_(new InfoPanelLabel), - image_size_(new InfoPanelLabel), - image_sampling_(new InfoPanelLabel), - image_type_(new InfoPanelLabel), - mouse_xy_(new InfoPanelLabel), - mouse_val_(new InfoPanelLabel), - click_xy_(new InfoPanelLabel), - click_val_(new InfoPanelLabel), - selection_xy_(new InfoPanelLabel), - size_xy_(new InfoPanelLabel), - distance_(new InfoPanelLabel), - popupmenu_(new QMenu), + image_extent_(new InfoPanelLabel("",this)), + image_size_(new InfoPanelLabel("",this)), + image_sampling_(new InfoPanelLabel("",this)), + image_type_(new InfoPanelLabel("",this)), + mouse_xy_(new InfoPanelLabel("",this)), + mouse_val_(new InfoPanelLabel("",this)), + click_xy_(new InfoPanelLabel("",this)), + click_val_(new InfoPanelLabel("",this)), + selection_xy_(new InfoPanelLabel("",this)), + size_xy_(new InfoPanelLabel("",this)), + distance_(new InfoPanelLabel("",this)), + popupmenu_(new QMenu(this)), amp_pha_(false), click_(geom::Vec2()) { diff --git a/modules/gui/src/data_viewer/mask_overlay.cc b/modules/gui/src/data_viewer/mask_overlay.cc index 6b52851831d44995a70eb3f6beffe518bada2447..c0c0e6560344c59f75cb95031a1a372086aba0ad 100644 --- a/modules/gui/src/data_viewer/mask_overlay.cc +++ b/modules/gui/src/data_viewer/mask_overlay.cc @@ -57,43 +57,46 @@ MaskOverlay::MaskOverlay(const MaskPtr& m): void MaskOverlay::OnDraw(QPainter& pnt, DataViewerPanel* dvp, bool is_active) { + QPainter::RenderHints render_hints=pnt.renderHints(); + pnt.setRenderHints(render_hints | QPainter::Antialiasing); for (int i=0;i<static_cast<int>(polygons_.size());++i){ if(is_active){ if(i==active_){ - pnt.setPen(QPen(QColor(255,255,0),2)); + pnt.setPen(QPen(QColor(255,255,0),1)); pnt.setBrush(QColor(255,255,0,30)); }else{ - pnt.setPen(QPen(QColor(255,0,0),2)); + pnt.setPen(QPen(QColor(255,0,0),1)); pnt.setBrush(QColor(255,0,0,30)); } }else{ - pnt.setPen(QPen(QColor(100,100,100),2)); + pnt.setPen(QPen(QColor(100,100,100),1)); pnt.setBrush(QColor(100,100,100,30)); } geom::Polygon2 pol=polygons_[i]; QPolygon qpol; for(int j=0;j<static_cast<int>(pol.GetNodeCount());++j){ qpol << dvp->FracPointToWinCenter(pol.GetNode(j)+shift_); - pnt.drawEllipse(qpol.back(),3,3); + pnt.drawEllipse(qpol.back(),4,4); } pnt.drawPolygon(qpol); } if(add_mode_) { if(is_active){ - pnt.setPen(QPen(QColor(255,0,255),3)); + pnt.setPen(QPen(QColor(255,0,255),1)); pnt.setBrush(QColor(255,0,255,30)); }else{ - pnt.setPen(QPen(QColor(100,100,100),2)); + pnt.setPen(QPen(QColor(100,100,100),1)); pnt.setBrush(QColor(100,100,100,30)); } QPolygon qpol; for(int j=0;j<static_cast<int>(new_poly_.GetNodeCount());++j){ qpol << dvp->FracPointToWinCenter(new_poly_.GetNode(j)+shift_); - pnt.drawEllipse(qpol.back(),3,3); + pnt.drawEllipse(qpol.back(),4,4); } pnt.drawPolygon(qpol); } + pnt.setRenderHints(render_hints); } bool MaskOverlay::OnMouseEvent(QMouseEvent* e, DataViewerPanel* dvp, @@ -118,7 +121,7 @@ bool MaskOverlay::OnMouseEvent(QMouseEvent* e, DataViewerPanel* dvp, if(active_>=0){ geom::Polygon2 pol=polygons_[active_]; for(unsigned int j=0;j<pol.GetNodeCount();++j){ - if(Length(mousepos-(pol.GetNode(j)+shift_))<3){ + if(Length(mousepos-(pol.GetNode(j)+shift_))<4){ active_node_=j; return true; } @@ -128,7 +131,7 @@ bool MaskOverlay::OnMouseEvent(QMouseEvent* e, DataViewerPanel* dvp, if(i!=active_){ geom::Polygon2 pol=polygons_[i]; for(unsigned int j=0;j<pol.GetNodeCount();++j){ - if(Length(mousepos-pol.GetNode(j))<3){ + if(Length(mousepos-(pol.GetNode(j)+shift_))<4){ active_=i; active_node_=j; return true; @@ -142,7 +145,7 @@ bool MaskOverlay::OnMouseEvent(QMouseEvent* e, DataViewerPanel* dvp, } } if(e->buttons() & Qt::LeftButton && active_>=0 && active_node_>=0 && ! (e->modifiers() & Qt::ShiftModifier)){ - polygons_[active_].SetNode(active_node_,mousepos); + polygons_[active_].SetNode(active_node_,mousepos-shift_); } return false; } diff --git a/modules/gui/src/data_viewer/overlay_manager_gui.cc b/modules/gui/src/data_viewer/overlay_manager_gui.cc index 74d24415c5bc1431389b8437becad5e4db400782..ba9d884cbd88b0f603c670a93dcfb995eb168177 100644 --- a/modules/gui/src/data_viewer/overlay_manager_gui.cc +++ b/modules/gui/src/data_viewer/overlay_manager_gui.cc @@ -135,6 +135,7 @@ void OverlayManagerGUI::OnAddOverlay(OverlayManager* m, int id) OverlayPtr ov = m->RetrieveOverlay(id); connect(ov.get(),SIGNAL(InfoTextChanged(const QString&)),this,SLOT(SetInfoText(const QString&))); OverlayEntry oe; + oe.row=0.0; oe.a=new OverlayCustomActCheckBox(id,m); connect(oe.a,SIGNAL(toggled(bool)),oe.a,SLOT(OnToggle(bool))); active_group_->addButton(oe.a); diff --git a/modules/gui/src/gosty.cc b/modules/gui/src/gosty.cc index 3ea2bdda6e64bb18677c0cb86ac08fb303bddf95..49750b9dca33c65e927d52dad461d5973b96fc80 100644 --- a/modules/gui/src/gosty.cc +++ b/modules/gui/src/gosty.cc @@ -205,7 +205,6 @@ int main(int argc, char** argv) QCoreApplication::setOrganizationName("OpenStructure"); QCoreApplication::setOrganizationDomain("openstructure.org"); QCoreApplication::setApplicationName(QString(argv[2])); - app.setLibraryPaths(QStringList()); if (int rv=setup_resources(app)<0) { return rv; } diff --git a/modules/gui/src/loader_manager.cc b/modules/gui/src/loader_manager.cc index 3febfd7ad3ade3945477ad06ab834648433017e2..bfe2853dc926669bdf33ddbee80bb360925c46f0 100644 --- a/modules/gui/src/loader_manager.cc +++ b/modules/gui/src/loader_manager.cc @@ -30,12 +30,13 @@ namespace ost { namespace gui { -LoaderManager::LoaderManager() +LoaderManager::LoaderManager(): + site_loaders_(), + site_actions_(new QActionGroup(GostyApp::Instance()->GetPerspective()->GetMenuBar())), + default_site_() + { - QMenuBar* menu_bar = GostyApp::Instance()->GetPerspective()->GetMenuBar(); - site_actions_=new QActionGroup(menu_bar); site_actions_->setExclusive(true); - site_menu_=new QMenu(); } void LoaderManager::AddRemoteSiteLoader(const QString& ident, RemoteSiteLoader* site_loader) @@ -48,7 +49,6 @@ void LoaderManager::AddRemoteSiteLoader(const QString& ident, RemoteSiteLoader* if(site_actions_->checkedAction()==NULL){ action->setChecked(true); } - site_menu_->addAction(action); } void LoaderManager::RemoveRemoteSiteLoader(const QString& ident) @@ -65,7 +65,6 @@ void LoaderManager::RemoveRemoteSiteLoader(const QString& ident) } if(action){ site_actions_->removeAction(action); - site_menu_->removeAction(action); } } @@ -95,10 +94,6 @@ std::vector<String> LoaderManager::GetSiteLoaderIdents() return sites; } -QMenu* LoaderManager::GetSiteMenu(){ - return site_menu_; -} - RemoteSiteLoader* LoaderManager::GetDefaultRemoteSiteLoader() { return GetRemoteSiteLoader(GetDefaultRemoteSiteIdent()); diff --git a/modules/gui/src/loader_manager.hh b/modules/gui/src/loader_manager.hh index fb6dfe8e8aef97705f382ac3776150159a08bed7..f969b289c45282d13e5f8541f31f0f96e66157e2 100644 --- a/modules/gui/src/loader_manager.hh +++ b/modules/gui/src/loader_manager.hh @@ -31,11 +31,6 @@ namespace ost { namespace gui { class DLLEXPORT_OST_GUI LoaderManager { - QMap<QString,RemoteSiteLoader*> site_loaders_; - QActionGroup* site_actions_; - QMenu* site_menu_; - QString default_site_; - public: LoaderManager(); virtual ~LoaderManager(); @@ -48,6 +43,13 @@ public: QString GetDefaultRemoteSiteIdent(); void SetDefaultRemoteSiteIdent(const QString& ident); QMenu* GetSiteMenu(); + +private: + QMap<QString,RemoteSiteLoader*> site_loaders_; + QActionGroup* site_actions_; + QString default_site_; + + }; typedef boost::shared_ptr<LoaderManager> LoaderManagerPtr; diff --git a/modules/gui/src/main.cc b/modules/gui/src/main.cc index 61d6b05d8227dd1d1f36be1578c514607fa62a24..f3b1c6f6e76f005ab2701a976980bd5af5cfb3a9 100644 --- a/modules/gui/src/main.cc +++ b/modules/gui/src/main.cc @@ -93,7 +93,9 @@ void GostyMainWindow::OnQuit() //SetFullScreen(false); GostyApp::Instance()->OnQuit(); deleteLater(); - QApplication::exit(0); + // exit has to be called on the instance not the class, + // otherwise the aboutToQuit singal doesn't get emitted + QApplication::instance()->exit(0); } void GostyMainWindow::closeEvent(QCloseEvent * event) diff --git a/modules/gui/src/messages/log_reader.cc b/modules/gui/src/messages/log_reader.cc index 3562df102ffb13a9a72bae29183d56732830849f..33ad612ba2e73ce8245c481c5e2701e17aaec82c 100644 --- a/modules/gui/src/messages/log_reader.cc +++ b/modules/gui/src/messages/log_reader.cc @@ -72,8 +72,6 @@ QMessageBox::Icon LogReader::GetIconForSeverity(int severity){ } LogReader::~LogReader() { - ost::Logger& logger = ost::Logger::Instance(); - logger.PopSink(); } } diff --git a/modules/gui/src/messages/message_widget.cc b/modules/gui/src/messages/message_widget.cc index 983a4ec169ee450f4b88ef2a0821c1fa90420582..038840ae1482d064608385c2e62225c8b7f19b88 100644 --- a/modules/gui/src/messages/message_widget.cc +++ b/modules/gui/src/messages/message_widget.cc @@ -61,6 +61,7 @@ MessageWidget::MessageWidget(QWidget* parent) : view_->setDragEnabled(true); view_->setContextMenuPolicy(Qt::CustomContextMenu); view_->setFrameShape(QFrame::NoFrame); + view_->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel); layout->addWidget(view_); connect(view_, SIGNAL(customContextMenuRequested(const QPoint&)), this, diff --git a/modules/gui/src/panels/panel_bar.cc b/modules/gui/src/panels/panel_bar.cc index 706c0294176bcec6e5b4a287964d77bc69bda47e..81312afb1016eff513857e790ec64bcadce9962f 100644 --- a/modules/gui/src/panels/panel_bar.cc +++ b/modules/gui/src/panels/panel_bar.cc @@ -35,17 +35,17 @@ namespace ost { namespace gui { PanelBar::PanelBar(QWidget* parent) : - Widget(NULL, parent) + Widget(NULL, parent), + layout_(new QStackedLayout(this)), + view_modes_( new QActionGroup(this)), + view_mode_menu_(new QMenu("View Mode",this)), + current_view_mode_(NULL), + widget_states_(), + drop_box_(new DropBox), // DropBox having no parent is done on purpose (otherwise it will not hide properly) + show_action_(new QAction(this)) { - widget_states_ = QList<WidgetState> (); - - view_modes_ = new QActionGroup(this); - view_mode_menu_ = new QMenu("View Mode"); connect(view_mode_menu_,SIGNAL(triggered(QAction*)),this,SLOT(ChangeViewMode(QAction*))); - current_view_mode_ = NULL; - - layout_ = new QStackedLayout(this); layout_->setMargin(0); layout_->setSpacing(0); this->setLayout(layout_); @@ -53,16 +53,18 @@ PanelBar::PanelBar(QWidget* parent) : this->setVisible(false); - show_action_ = new QAction(this); show_action_->setText("Show"); show_action_->setCheckable(true); show_action_->setChecked(false); show_action_->setEnabled(false); connect(show_action_, SIGNAL(triggered(bool)), this, - SLOT(ShowActionTrigger())); + SLOT(ShowActionTrigger())); this->addAction(show_action_); +} - drop_box_ = new DropBox(); +PanelBar::~PanelBar() +{ + delete drop_box_; // manually destroy drop_box_ widget, as it has no parent. } void PanelBar::AddWidget(Widget* widget, bool is_hidden) diff --git a/modules/gui/src/panels/panel_bar.hh b/modules/gui/src/panels/panel_bar.hh index 7c81cbd0be81cd5c4ca11d6e801f1d2ad4787036..463641357c99248957c51e7ed8394c870eef8bf1 100644 --- a/modules/gui/src/panels/panel_bar.hh +++ b/modules/gui/src/panels/panel_bar.hh @@ -54,6 +54,7 @@ class DLLEXPORT_OST_GUI PanelBar : public Widget { Q_OBJECT public: PanelBar(QWidget* parent); + virtual ~PanelBar(); virtual bool Save(const QString& prefix); virtual bool Restore(const QString& prefix); diff --git a/modules/gui/src/panels/panel_manager.cc b/modules/gui/src/panels/panel_manager.cc index 0bf0b7f0b848a47b6b15f124c451c135113decd3..1c30ad993cd90d7ab7265f071e9f6469489cc12b 100644 --- a/modules/gui/src/panels/panel_manager.cc +++ b/modules/gui/src/panels/panel_manager.cc @@ -50,7 +50,7 @@ PanelManager::PanelManager(QWidget* widget): right_panel_splitter_(new ThinSplitter(Qt::Horizontal, this)), left_panel_splitter_(new ThinSplitter(Qt::Horizontal, this)), bottom_panel_splitter_(new ThinSplitter(Qt::Vertical, this)), - pool_(new WidgetPool()) + pool_(new WidgetPool(this)) { PanelBar* bottom_bar = new BottomBar(this); diff --git a/modules/gui/src/python_shell/python_interpreter_worker.cc b/modules/gui/src/python_shell/python_interpreter_worker.cc index b89859142642c21d4fc6f624b9727aa27d35dc81..47dbcfc9e27282c6ec3b3f0e06203fb87b87b0b8 100644 --- a/modules/gui/src/python_shell/python_interpreter_worker.cc +++ b/modules/gui/src/python_shell/python_interpreter_worker.cc @@ -51,6 +51,12 @@ PythonInterpreterWorker::PythonInterpreterWorker(): main_namespace_["sys"].attr("stdout") = output_redirector_; } +PythonInterpreterWorker::~PythonInterpreterWorker() +{ + // we have to manually run the exit functions because we cannot use Py_Finalize due to some problems in boost python + run_command_(std::pair<unsigned int, QString>(0,"import atexit\natexit._run_exitfuncs()\n")); +} + void PythonInterpreterWorker::Wake() { if (awake_) return; diff --git a/modules/gui/src/python_shell/python_interpreter_worker.hh b/modules/gui/src/python_shell/python_interpreter_worker.hh index 7d38dd544b040c86a19106751bf4813fe165dd1f..ed80f6fe78b308f1269a5a723bffe46883fbe35b 100644 --- a/modules/gui/src/python_shell/python_interpreter_worker.hh +++ b/modules/gui/src/python_shell/python_interpreter_worker.hh @@ -3,8 +3,11 @@ #include <csignal> #include <utility> -#include <boost/python.hpp> -#include <boost/shared_ptr.hpp> +// workaround for QTBUG-22829: https://bugreports.qt-project.org/browse/QTBUG-22829 +#ifndef Q_MOC_RUN + #include <boost/python.hpp> + #include <boost/shared_ptr.hpp> +#endif #include "output_redirector.hh" #include <QObject> #include <QQueue> @@ -17,6 +20,7 @@ class PythonInterpreterWorker: public QObject Q_OBJECT public: PythonInterpreterWorker(); + ~PythonInterpreterWorker(); unsigned int AddCommand(const QString& command); signals: diff --git a/modules/img/alg/pymod/CMakeLists.txt b/modules/img/alg/pymod/CMakeLists.txt index c257040e5f976609bd7c0c13469690c2260b758e..be68daec5e5a2446bd3a6548ae34b59cc4884332 100644 --- a/modules/img/alg/pymod/CMakeLists.txt +++ b/modules/img/alg/pymod/CMakeLists.txt @@ -6,5 +6,7 @@ export_transcendentals.cc export_polar.cc ) -pymod(NAME img_alg OUTPUT_DIR ost/img/alg CPP ${OST_IMG_ALG_PYMOD_SOURCES} - PY __init__.py) +if (NOT ENABLE_STATIC) + pymod(NAME img_alg OUTPUT_DIR ost/img/alg CPP ${OST_IMG_ALG_PYMOD_SOURCES} + PY __init__.py) +endif() diff --git a/modules/img/alg/src/CMakeLists.txt b/modules/img/alg/src/CMakeLists.txt index 11fba15d4e3ffc675692c8ad0d73bb3c1738a5b7..a49b80125f11de0531412e7fd2929577669aa647 100644 --- a/modules/img/alg/src/CMakeLists.txt +++ b/modules/img/alg/src/CMakeLists.txt @@ -75,6 +75,7 @@ power_spectrum.hh randomize.hh smooth_mask_image.hh stat.hh +stat_accumulator.hh stat_min_max.hh threshold.hh transcendentals.hh @@ -93,7 +94,9 @@ line_average.hh rscrosscorr.hh ) +if(ENABLE_INFO) include(${QT_USE_FILE}) +endif() module(NAME img_alg SOURCES "${OST_IMG_ALG_SOURCES}" HEADERS "${OST_IMG_ALG_HEADERS}" HEADER_OUTPUT_DIR ost/img/alg diff --git a/modules/img/alg/src/fft.cc b/modules/img/alg/src/fft.cc index 84ac57b19bed1eda916653ca4a44b355c908892f..49fc3f6260ffdb986a3cb6f91a7da890516b2405 100644 --- a/modules/img/alg/src/fft.cc +++ b/modules/img/alg/src/fft.cc @@ -25,8 +25,12 @@ #include <boost/shared_ptr.hpp> #include <fftw3.h> +#if OST_INFO_ENABLED #include <QThread> - +#define IDEAL_NUMBER_OF_THREADS() QThread::idealThreadCount() +#else +#define IDEAL_NUMBER_OF_THREADS() 1 +#endif #include <ost/message.hh> #include <ost/img/value_util.hh> #include <ost/img/image_state/image_state_def.hh> @@ -130,7 +134,7 @@ reinterpret_cast<OST_FFTW_fftw_complex*>(out_state->Data().GetData()); for(size_t i=0;i<block_count;i++) { std::copy(&in_ptr[i*src_size],&in_ptr[(i+1)*src_size],&fftw_in[i*2*dst_size]); } - OST_FFTW_fftw_plan_with_nthreads(std::max<int>(1,QThread::idealThreadCount())); + OST_FFTW_fftw_plan_with_nthreads(std::max<int>(1,IDEAL_NUMBER_OF_THREADS())); OST_FFTW_fftw_plan plan = OST_FFTW_fftw_plan_dft_r2c(rank,n, fftw_in,fftw_out, FFTW_ESTIMATE); @@ -213,7 +217,7 @@ ImageStateBasePtr FFTFnc::VisitState<Complex,HalfFrequencyDomain>(const ComplexH Real* fftw_out = reinterpret_cast<Real*>(out_ptr); assert(sizeof(OST_FFTW_fftw_complex)==sizeof(Complex)); - OST_FFTW_fftw_plan_with_nthreads(std::max<int>(1,QThread::idealThreadCount())); + OST_FFTW_fftw_plan_with_nthreads(std::max<int>(1,IDEAL_NUMBER_OF_THREADS())); OST_FFTW_fftw_complex* fftw_in = reinterpret_cast<OST_FFTW_fftw_complex*>(out_ptr); @@ -259,7 +263,7 @@ ImageStateBasePtr FFTFnc::VisitState<Complex,SpatialDomain>(const ComplexSpatial reinterpret_cast<OST_FFTW_fftw_complex*>(out_state->Data().GetData()); // in place transform - OST_FFTW_fftw_plan_with_nthreads(std::max<int>(1,QThread::idealThreadCount())); + OST_FFTW_fftw_plan_with_nthreads(std::max<int>(1,IDEAL_NUMBER_OF_THREADS())); OST_FFTW_fftw_plan plan = OST_FFTW_fftw_plan_dft(rank,n, fftw_out, fftw_out, dir, @@ -297,7 +301,7 @@ ImageStateBasePtr FFTFnc::VisitState<Complex,FrequencyDomain>(const ComplexFrequ reinterpret_cast<OST_FFTW_fftw_complex*>(out_state->Data().GetData()); // in place transform - OST_FFTW_fftw_plan_with_nthreads(std::max<int>(1,QThread::idealThreadCount())); + OST_FFTW_fftw_plan_with_nthreads(std::max<int>(1,IDEAL_NUMBER_OF_THREADS())); OST_FFTW_fftw_plan plan = OST_FFTW_fftw_plan_dft(rank,n, fftw_out, fftw_out, dir, diff --git a/modules/img/alg/src/stat.cc b/modules/img/alg/src/stat.cc index 2a9427abbaea05fdc290d0642ed6918ea6b455dd..01053ab7e28bbccdfaf0a7c4839633246d675995 100644 --- a/modules/img/alg/src/stat.cc +++ b/modules/img/alg/src/stat.cc @@ -30,6 +30,7 @@ #include <ost/img/value_util.hh> #include "stat.hh" +#include "stat_accumulator.hh" namespace ost { namespace img { namespace alg { @@ -58,14 +59,12 @@ void StatBase::VisitState(const ImageStateImpl<T,D>& isi) return; } - Real sum2=0.0; Vec3 sumcenter(0.0,0.0,0.0); - Real current_n=1.0; - Real m2=0.0,m3=0.0,m4=0.0; ValIndex minindex(std::numeric_limits<Real>::max(),Point(0,0,0)); ValIndex maxindex(-std::numeric_limits<Real>::max(),Point(0,0,0)); min_ = std::numeric_limits<Real>::max(); max_ = -std::numeric_limits<Real>::max(); + StatAccumulator<> acc; int wi=isi.GetSize()[0]; int he=isi.GetSize()[1]; @@ -74,23 +73,11 @@ void StatBase::VisitState(const ImageStateImpl<T,D>& isi) for(int j=0;j<he;++j) { for(int k=0;k<de;++k) { Real val=Val2Val<T,Real>(isi.Value(Index(i,j,k))); - Real delta = val - mean_; - Real delta_n = delta / current_n; - Real delta_n2 = delta_n * delta_n; - Real term = delta * delta_n * (current_n-1); - - mean_ += delta_n; - m4 += term * delta_n2 * (current_n*current_n - 3*current_n + 3) + 6 * delta_n2 * m2 - 4 * delta_n * m3; - m3 += term * delta_n * (current_n - 2) - 3 * delta_n * m2; - m2 += term; - ValIndex vi(val,Point(i,j,k)); minindex=std::min<ValIndex>(vi,minindex); maxindex=std::max<ValIndex>(vi,maxindex); sumcenter+=Vec3(i,j,k)*val; - sum_+=val; - sum2+=val*val; - current_n+=1; + acc(val); } } } @@ -98,16 +85,13 @@ void StatBase::VisitState(const ImageStateImpl<T,D>& isi) max_=maxindex.first; minpos_=minindex.second+isi.GetExtent().GetStart(); maxpos_=maxindex.second+isi.GetExtent().GetStart(); - var_=m2/n; - std_dev_=sqrt(var_); - rms_=sqrt(sum2/n); - if(m2<1e20){ - skewness_=0.0; - kurtosis_= 0.0; - }else{ - skewness_=m3/sqrt(m2*m2*m2); - kurtosis_= (n*m4) / (m2*m2) - 3.0; - } + var_=acc.GetVariance(); + std_dev_=acc.GetStandardDeviation(); + rms_=acc.GetRootMeanSquare(); + skewness_=acc.GetSkewness(); + kurtosis_= acc.GetKurtosis(); + sum_=acc.GetSum(); + mean_=acc.GetMean(); if(sum_!=0.0){ center_of_mass_=sumcenter/sum_+isi.GetExtent().GetStart().ToVec3(); }else{ @@ -135,49 +119,32 @@ void StatBase::VisitFunction(const Function& fnc) return; } - Real sum2=0.0; Vec3 sumcenter(0.0,0.0,0.0); - Real current_n=1.0; - Real m2=0.0,m3=0.0,m4=0.0; ValIndex minindex(std::numeric_limits<Real>::max(),Point(0,0,0)); ValIndex maxindex(-std::numeric_limits<Real>::max(),Point(0,0,0)); min_ = std::numeric_limits<Real>::max(); max_ = -std::numeric_limits<Real>::max(); + StatAccumulator<> acc; for(ExtentIterator it(fnc.GetExtent());!it.AtEnd(); ++it) { Real val=fnc.GetReal(it); - Real delta = val - mean_; - Real delta_n = delta / current_n; - Real delta_n2 = delta_n * delta_n; - Real term = delta * delta_n * (current_n-1); - - mean_ += delta_n; - m4 += term * delta_n2 * (current_n*current_n - 3*current_n + 3) + 6 * delta_n2 * m2 - 4 * delta_n * m3; - m3 += term * delta_n * (current_n - 2) - 3 * delta_n * m2; - m2 += term; - ValIndex vi(val,it); minindex=std::min<ValIndex>(vi,minindex); maxindex=std::max<ValIndex>(vi,maxindex); sumcenter+=Point(it).ToVec3()*val; - sum_+=val; - sum2+=val*val; - current_n+=1; + acc(val); } min_=minindex.first; max_=maxindex.first; minpos_=minindex.second; - maxpos_=maxindex.second; - var_=m2/n; - std_dev_=sqrt(var_); - rms_=sqrt(sum2/n); - if(m2<1e20){ - skewness_=0.0; - kurtosis_= 0.0; - }else{ - skewness_=m3/sqrt(m2*m2*m2); - kurtosis_= (n*m4) / (m2*m2) - 3.0; - } + maxpos_=maxindex.second; + var_=acc.GetVariance(); + std_dev_=acc.GetStandardDeviation(); + rms_=acc.GetRootMeanSquare(); + skewness_=acc.GetSkewness(); + kurtosis_= acc.GetKurtosis(); + sum_=acc.GetSum(); + mean_=acc.GetMean(); if(sum_!=0.0){ center_of_mass_=sumcenter/sum_; }else{ diff --git a/modules/img/alg/src/stat_accumulator.hh b/modules/img/alg/src/stat_accumulator.hh new file mode 100644 index 0000000000000000000000000000000000000000..3483890b0ced8c3f5e71382f3273fcdcafc68ef0 --- /dev/null +++ b/modules/img/alg/src/stat_accumulator.hh @@ -0,0 +1,202 @@ +//------------------------------------------------------------------------------ +// This file is part of the OpenStructure project <www.openstructure.org> +// +// Copyright (C) 2008-2011 by the OpenStructure authors +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License as published by the Free +// Software Foundation; either version 3.0 of the License, or (at your option) +// any later version. +// This library is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this library; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +//------------------------------------------------------------------------------ + +#ifndef OST_STAT_ACCUMULATOR_HH +#define OST_STAT_ACCUMULATOR_HH + +#include <ost/base.hh> +#include <ost/img/alg/module_config.hh> + +namespace ost { namespace img { namespace alg { + +template<unsigned int MAX_MOMENT=4> +class DLLEXPORT_IMG_ALG StatAccumulator +{ +public: + StatAccumulator(): + mean_(0.0), + sum_(0.0), + sum2_(0.0), + m2_(0.0), + m3_(0.0), + m4_(0.0), + n_(1) + {} + + void operator()(Real val) + { + Real delta,delta_n,delta_n2,term; + if(MAX_MOMENT>0){ + delta = val - mean_; + delta_n = delta / n_; + } + if(MAX_MOMENT>3){ + delta_n2 = delta_n * delta_n; + } + if(MAX_MOMENT>1){ + term = delta * delta_n * (n_-1); + } + if(MAX_MOMENT>3){ + m4_ += term * delta_n2 * (n_*n_ - 3*n_ + 3) + 6 * delta_n2 * m2_ - 4 * delta_n * m3_; + } + if(MAX_MOMENT>2){ + m3_ += term * delta_n * (n_ - 2) - 3 * delta_n * m2_; + } + if(MAX_MOMENT>1){ + m2_ += term; + } + if(MAX_MOMENT>0){ + mean_ += delta_n; + } + n_+=1; + sum_+=val; + sum2_+=val*val; + } + + StatAccumulator operator+(const StatAccumulator& acc2) const + { + StatAccumulator acc(acc2); + acc+=*this; + return acc; + } + + StatAccumulator& operator+=(const StatAccumulator& acc) + { + if(acc.n_==1){ + return *this; + } + if(n_==1){ + mean_=acc.mean_; + sum_=acc.sum_; + sum2_=acc.sum2_; + m2_=acc.m2_; + m3_=acc.m3_; + m4_=acc.m4_; + n_=acc.n_; + return *this; + } + Real delta,delta_n,delta_n2,na,nanb; + Real nb=acc.n_-1; + if(MAX_MOMENT>0){ + na=n_-1; + delta = acc.mean_ - mean_; + delta_n = delta / (na+nb); + } + if(MAX_MOMENT>1){ + nanb=na*nb; + } + if(MAX_MOMENT>2){ + delta_n2 = delta_n * delta_n; + } + if(MAX_MOMENT>3){ + m4_+=acc.m4_+delta*delta_n*delta_n2*nanb*(na*na-nanb+nb*nb)+6.0*delta_n2*(na*na*acc.m2_+nb*nb*m2_)+4.0*delta_n*(na*acc.m3_-nb*m3_); + } + if(MAX_MOMENT>2){ + m3_+=acc.m3_+delta*delta_n2*nanb*(na-nb)+3.0*delta_n*(na*acc.m2_-nb*m2_); + } + if(MAX_MOMENT>1){ + m2_ += acc.m2_+delta*delta_n*nanb; + } + if(MAX_MOMENT>0){ + mean_ += nb*delta_n; + } + sum_+=acc.sum_; + sum2_+=acc.sum2_; + n_+=nb; + return *this; + } + + Real GetNumSamples() const + { + return n_-1.0; + } + + Real GetMean() const + { + if(MAX_MOMENT<1){ + throw Error("Mean was not calculated."); + } + return mean_; + } + + Real GetSum() const + { + return sum_; + } + + Real GetVariance() const + { + if(MAX_MOMENT<2){ + throw Error("Variance was not calculated."); + } + if(n_==1.0){ + return 0.0; + } + return m2_/(n_-1); + } + + Real GetStandardDeviation() const + { + return sqrt(GetVariance()); + } + + Real GetRootMeanSquare() const + { + if(n_==1.0){ + return 0.0; + } + return sqrt(sum2_/(n_-1)); + } + + Real GetSkewness() const + { + if(MAX_MOMENT<3){ + throw Error("Skewness was not calculated."); + } + if(m2_<1e-20){ + return 0.0; + }else{ + return m3_/sqrt(m2_*m2_*m2_); + } + } + + Real GetKurtosis() const + { + if(MAX_MOMENT<4){ + throw Error("Kurtosis was not calculated."); + } + if(m2_<1e-20){ + return 0.0; + }else{ + return ((n_-1)*m4_) / (m2_*m2_); + } + } + +private: + Real mean_; + Real sum_; + Real sum2_; + Real m2_; + Real m3_; + Real m4_; + Real n_; +}; + +}}} //ns +#endif // OST_STAT_ACCUMULATOR_HH diff --git a/modules/img/alg/tests/CMakeLists.txt b/modules/img/alg/tests/CMakeLists.txt index cdbd8b459c114e0765bb53280f144043be34a8cc..cea46dcb979d4f6a73e515b81bf26858876f2468 100644 --- a/modules/img/alg/tests/CMakeLists.txt +++ b/modules/img/alg/tests/CMakeLists.txt @@ -14,6 +14,7 @@ test_power_spectrum.cc test_shift.cc test_stat.cc test_transform.cc +test_normalizer.cc tests.cc ) diff --git a/modules/img/alg/tests/test_normalizer.cc b/modules/img/alg/tests/test_normalizer.cc new file mode 100644 index 0000000000000000000000000000000000000000..e072626dbc562e70703ae226606c4c9e0d1f6c9d --- /dev/null +++ b/modules/img/alg/tests/test_normalizer.cc @@ -0,0 +1,76 @@ +//------------------------------------------------------------------------------ +// This file is part of the OpenStructure project <www.openstructure.org> +// +// Copyright (C) 2008-2011 by the OpenStructure authors +// Copyright (C) 2003-2010 by the IPLT authors +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License as published by the Free +// Software Foundation; either version 3.0 of the License, or (at your option) +// any later version. +// This library is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this library; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +//------------------------------------------------------------------------------ + +/* + Author: Andreas Schenk +*/ + +#include <iostream> + +#include "tests.hh" + +#include <ost/img/image.hh> +#include <ost/img/alg/normalizer_factory.hh> +#include <ost/img/alg/stat.hh> + + + +namespace { + +using namespace ost::img; +using namespace ost::img::alg; + +void test() +{ + boost::test_tools::close_at_tolerance<Real> close_test(::boost::test_tools::percent_tolerance(0.001)); + ost::img::ImageHandle testimage=ost::img::CreateImage(ost::img::Extent(ost::img::Point(0,0),ost::img::Point(3,3))); + int counter=0; + for (ost::img::ExtentIterator i(testimage.GetExtent()); !i.AtEnd(); ++i, ++counter) { + testimage.SetReal(i, counter); + } + ost::img::alg::Normalizer norm=ost::img::alg::CreateLinearRangeNormalizer(testimage,0.0,65535.0); + ost::img::ImageHandle scaled_image=testimage.Apply(norm); + scaled_image+=0.01; //if all values are > 0.0 we can use close_at_tolerance + bool failed=false; + ost::img::ExtentIterator eit(testimage.GetExtent()); + for(;!eit.AtEnd();++eit) { + if( ! close_test(scaled_image.GetReal(eit),testimage.GetReal(eit)/15.0*65535.0+0.01)){ + failed=true; + break; + } + } + if(failed){ + BOOST_ERROR("Normalizer failed at point " + << ost::img::Point(eit)<< ". Should be " + << testimage.GetReal(eit)/15.0*65535.0+0.01 << ", but " + << scaled_image.GetReal(eit) << " found."); + } +} + +} // ns + +test_suite* CreateNormalizerTest() +{ + test_suite* ts=BOOST_TEST_SUITE("img alg Normalizer Test"); + + ts->add(BOOST_TEST_CASE(&test)); + + return ts; +} diff --git a/modules/img/alg/tests/test_stat.cc b/modules/img/alg/tests/test_stat.cc index 3f5e6d2ed6a3a1114f59458361021b7f9a0ccdad..b736c6bd93d30aebbcc2eb05616e70c4d0d19f7e 100644 --- a/modules/img/alg/tests/test_stat.cc +++ b/modules/img/alg/tests/test_stat.cc @@ -29,6 +29,7 @@ #include <ost/img/image.hh> #include <ost/img/alg/stat.hh> +#include <ost/img/alg/stat_accumulator.hh> namespace test_stat { @@ -51,7 +52,40 @@ void test() { im.Apply(stat); BOOST_CHECK_CLOSE(stat.GetMean(),Real(5.0),Real(0.0001)); BOOST_CHECK_CLOSE(stat.GetStandardDeviation(),Real(2.58198889747),Real(0.0001)); - + BOOST_CHECK_CLOSE(stat.GetSkewness()+Real(0.5),Real(0.5),Real(0.0001)); + BOOST_CHECK_CLOSE(stat.GetKurtosis(),Real(1.77),Real(0.0001)); + + // check for rounding errors + im+=10000.0; + im.Apply(stat); + BOOST_CHECK_CLOSE(stat.GetMean(),Real(10005.0),Real(0.0001)); + BOOST_CHECK_CLOSE(stat.GetStandardDeviation(),Real(2.58198889747),Real(0.01)); + BOOST_CHECK_CLOSE(stat.GetSkewness()+Real(0.5),Real(0.5),Real(0.01)); + BOOST_CHECK_CLOSE(stat.GetKurtosis(),Real(1.77),Real(0.01)); + + + StatAccumulator<> acc; + for(int u=0;u<3;++u) { + for(int v=0;v<3;++v) { + acc(val[u][v]); + } + } + BOOST_CHECK_CLOSE(acc.GetMean(),Real(5.0),Real(0.0001)); + BOOST_CHECK_CLOSE(acc.GetStandardDeviation(),Real(2.58198889747),Real(0.0001)); + BOOST_CHECK_CLOSE(acc.GetSkewness()+Real(0.5),Real(0.5),Real(0.0001)); + BOOST_CHECK_CLOSE(acc.GetKurtosis(),Real(1.77),Real(0.0001)); + + StatAccumulator<> acc1,acc2,acc3; + for(int u=0;u<3;++u) { + acc1(val[u][0]); + acc2(val[u][1]); + acc3(val[u][2]); + } + StatAccumulator<> acc_c=acc1+acc2+acc3; + BOOST_CHECK_CLOSE(acc_c.GetMean(),Real(5.0),Real(0.0001)); + BOOST_CHECK_CLOSE(acc_c.GetStandardDeviation(),Real(2.58198889747),Real(0.0001)); + BOOST_CHECK_CLOSE(acc_c.GetSkewness()+Real(0.5),Real(0.5),Real(0.0001)); + BOOST_CHECK_CLOSE(acc_c.GetKurtosis(),Real(1.77),Real(0.0001)); } } // namespace diff --git a/modules/img/alg/tests/tests.cc b/modules/img/alg/tests/tests.cc index 0a4ae6cecd7020190c0e6415ae0938ba0061a481..d3db88c2f29c5c3bbb19517e4d0800f9488f4ea3 100644 --- a/modules/img/alg/tests/tests.cc +++ b/modules/img/alg/tests/tests.cc @@ -41,6 +41,7 @@ extern test_suite* CreateClearTest(); extern test_suite* CreateFFTTest(); extern test_suite* CreateNegateTest(); extern test_suite* CreateConjugateTest(); +extern test_suite* CreateNormalizerTest(); bool init_ost_img_alg_unit_tests() { try { @@ -54,6 +55,7 @@ bool init_ost_img_alg_unit_tests() { framework::master_test_suite().add(CreateClearTest()); framework::master_test_suite().add(CreateNegateTest()); framework::master_test_suite().add(CreateFFTTest()); + framework::master_test_suite().add(CreateNormalizerTest()); } catch(std::exception& e) { return false; } diff --git a/modules/img/base/pymod/CMakeLists.txt b/modules/img/base/pymod/CMakeLists.txt index aecb5eeb9386d66c5495af54ec897e3189dd4763..de787d14064aa27fb4f0117e9f9bf3bdac06c596 100644 --- a/modules/img/base/pymod/CMakeLists.txt +++ b/modules/img/base/pymod/CMakeLists.txt @@ -16,5 +16,7 @@ export_map.cc wrap_img.cc ) -pymod(NAME img OUTPUT_DIR ost/img - CPP ${OST_IMG_PYMOD_SOURCES} PY __init__.py) +if (NOT ENABLE_STATIC) + pymod(NAME img OUTPUT_DIR ost/img + CPP ${OST_IMG_PYMOD_SOURCES} PY __init__.py) +endif() diff --git a/modules/img/base/pymod/export_mask.cc b/modules/img/base/pymod/export_mask.cc index 3a5faacf883ec2845ba48f06f4021d8bb23d14ba..40f42e9b0f00e1ca5ac20021e8e544e72bc9fd7f 100644 --- a/modules/img/base/pymod/export_mask.cc +++ b/modules/img/base/pymod/export_mask.cc @@ -26,7 +26,10 @@ using namespace boost::python; #include <ost/img/mask.hh> +#include <ost/config.hh> +#if(OST_INFO_ENABLED) #include <ost/img/mask_info_convert.hh> +#endif namespace ost { namespace img { @@ -101,7 +104,10 @@ void export_Mask() def("Mask",mask2); def("Mask",mask3); def("Mask",mask4); + +#if(OST_INFO_ENABLED) def("InfoToMask",InfoToMask); def("MaskToInfo",MaskToInfo); - +#endif + } diff --git a/modules/img/base/src/CMakeLists.txt b/modules/img/base/src/CMakeLists.txt index d218ac2ad4f265d7dfd8098313b93b46d71f8a60..ff5191865fc22a3364106ba0980174417946742b 100644 --- a/modules/img/base/src/CMakeLists.txt +++ b/modules/img/base/src/CMakeLists.txt @@ -29,7 +29,6 @@ extent_mask.cc spherical_mask.cc mask_op.cc circle_mask.cc -mask_info_convert.cc image_list.cc physical_units.cc progress.cc @@ -86,13 +85,17 @@ spherical_mask.hh mask_op.hh mask.hh circle_mask.hh -mask_info_convert.hh image_list.hh physical_units.hh progress.hh map.hh ) +if (ENABLE_INFO) + list(APPEND OST_IMG_SOURCES mask_info_convert.cc) + list(APPEND OST_IMG_HEADERS mask_info_convert.hh) + set(INFO_DEPS ost_info) +endif() foreach(fname ${OST_IMG_IMAGE_STATE_SOURCES}) set(OST_IMG_SOURCES ${OST_IMG_SOURCES} image_state/${fname}) @@ -106,4 +109,4 @@ module(NAME img SOURCES "${OST_IMG_SOURCES}" HEADERS ${OST_IMG_RASTER_IMAGE_HEADERS} IN_DIR raster_image ${OST_IMG_IMAGE_STATE_HEADERS} IN_DIR image_state ${OST_IMG_HEADERS} - DEPENDS_ON ost_geom ost_base ost_info) + DEPENDS_ON ost_geom ost_base ${INFO_DEPS}) diff --git a/modules/img/base/tests/test_image.cc b/modules/img/base/tests/test_image.cc index e04eba193893e5fb730065a25e2a29d159e143ef..160b7e044da1711751b03c677e498a6519460b4d 100644 --- a/modules/img/base/tests/test_image.cc +++ b/modules/img/base/tests/test_image.cc @@ -97,17 +97,17 @@ void test_Cctor_Assignement() ih1.ApplyIP(alg::Randomize()); ImageHandle ih2(ih1); - BOOST_REQUIRE(ih1==ih2); + BOOST_CHECK(ih1==ih2); for(ExtentIterator it(ih1.GetExtent());!it.AtEnd(); ++it) { - BOOST_REQUIRE(ih1.GetReal(it)==ih2.GetReal(it)); + BOOST_CHECK(ih1.GetReal(it)==ih2.GetReal(it)); } ImageHandle ih3=CreateImage(Size(10)); ih3.ApplyIP(alg::Randomize()); ih3=ih1; - BOOST_REQUIRE(ih1==ih3); + BOOST_CHECK(ih1==ih3); for(ExtentIterator it(ih1.GetExtent());!it.AtEnd(); ++it) { - BOOST_REQUIRE(ih1.GetReal(it)==ih3.GetReal(it)); + BOOST_CHECK(ih1.GetReal(it)==ih3.GetReal(it)); } } @@ -176,14 +176,14 @@ void test_Observer() { ImageHandle ih = CreateImage(); - BOOST_REQUIRE(ih.obs_); + BOOST_CHECK(ih.obs_); BOOST_CHECK(ih.obs_.get()->GetListSize()==0); to1 = new MyObserver(ih); - BOOST_REQUIRE(ih.obs_.get()->GetListSize()==1); + BOOST_CHECK(ih.obs_.get()->GetListSize()==1); to2 = new MyObserver(ih); - BOOST_REQUIRE(ih.obs_.get()->GetListSize()==2); + BOOST_CHECK(ih.obs_.get()->GetListSize()==2); BOOST_CHECK(to1->update_count==0); BOOST_CHECK(to1->release_count==0); @@ -197,7 +197,7 @@ void test_Observer() delete to2; - BOOST_REQUIRE(ih.obs_.get()->GetListSize()==1); + BOOST_CHECK(ih.obs_.get()->GetListSize()==1); ImageHandle ih2 = ih; @@ -241,7 +241,7 @@ void test_Interpolation() +( dx )*(one-dy)*( dz )*ih3d.GetReal(Point(1,0,1)) +(one-dx)*( dy )*( dz )*ih3d.GetReal(Point(0,1,1)) +( dx )*( dy )*( dz )*ih3d.GetReal(Point(1,1,1)); - BOOST_REQUIRE(check_close(val3,ih3d.GetIntpolReal(Vec3(dx,dy,dz)),1.0e-8)); + BOOST_CHECK(check_close(val3,ih3d.GetIntpolReal(Vec3(dx,dy,dz)),1.0e-8)); ImageHandle ih2d=CreateImage(Extent(Point(0,0),Point(1,1))); @@ -254,7 +254,7 @@ void test_Interpolation() +(one-dx)*( dy )*ih2d.GetReal(Point(0,1)) +( dx )*( dy )*ih2d.GetReal(Point(1,1)); - BOOST_REQUIRE(check_close(val2,ih2d.GetIntpolReal(Vec2(dx,dy)),1.0e-10)); + BOOST_CHECK(check_close(val2,ih2d.GetIntpolReal(Vec2(dx,dy)),1.0e-10)); ImageHandle ih1d=CreateImage(Extent(Point(0),Point(1))); ih3d.SetReal(Point(0,0,0), Real(0.000)); @@ -262,7 +262,7 @@ void test_Interpolation() Real val1= (one-dx)*ih1d.GetReal(Point(0,0)) +( dx )*ih1d.GetReal(Point(1,0)); - BOOST_REQUIRE(check_close(val1,ih1d.GetIntpolReal(dx),1.0e-15)); + BOOST_CHECK(check_close(val1,ih1d.GetIntpolReal(dx),1.0e-15)); } @@ -273,50 +273,56 @@ void test_ScalarOps() ih2+=1.0; for(ExtentIterator it(ih2.GetExtent()); !it.AtEnd(); ++it) { - BOOST_REQUIRE(ih2.GetReal(it) == ih1.GetReal(it) + 1.0); + BOOST_CHECK(ih2.GetReal(it) == ih1.GetReal(it) + 1.0); } ih2 = ih1.Copy(); ih2-=2.5; for(ExtentIterator it(ih2.GetExtent()); !it.AtEnd(); ++it) { - BOOST_REQUIRE(ih2.GetReal(it) == ih1.GetReal(it) - 2.5); + BOOST_CHECK(ih2.GetReal(it) == ih1.GetReal(it) - 2.5); } ih2 = ih1.Copy(); ih2*=0.9; for(ExtentIterator it(ih2.GetExtent()); !it.AtEnd(); ++it) { - BOOST_REQUIRE(std::abs(ih2.GetReal(it) - ih1.GetReal(it) * 0.9)<1e-10); + BOOST_CHECK(std::abs(ih2.GetReal(it) - ih1.GetReal(it) * 0.9)<1e-10); } ih2 = ih1.Copy(); ih2/=2.1; for(ExtentIterator it(ih2.GetExtent()); !it.AtEnd(); ++it) { - BOOST_REQUIRE(std::abs(ih2.GetReal(it) - ih1.GetReal(it) / 2.1)<1e-10); + BOOST_CHECK(std::abs(ih2.GetReal(it) - ih1.GetReal(it) / 2.1)<1e-10); } } void test_ImageOps() { - alg::Randomize rnd; Extent ex1(Point(-3,-2),Point(2,2)); ImageHandle h1=CreateImage(ex1); - h1.ApplyIP(rnd); + Real count=1.0; + for(ExtentIterator it(ex1); !it.AtEnd(); ++it) { + h1.SetReal(it,count); + count+=1.0; + } Extent ex2(Point(-1,-2),Point(3,4)); ImageHandle h2=CreateImage(ex2, COMPLEX); - h2.ApplyIP(rnd); + for(ExtentIterator it(ex2); !it.AtEnd(); ++it) { + h2.SetReal(it,count); + count+=1.0; + } // addition ImageHandle h3=h1+h2; for(ExtentIterator it(Extent(Point(-4,-3),Point(4,5))); !it.AtEnd(); ++it) { if(ex1.Contains(it) && ex2.Contains(it)) { - BOOST_REQUIRE(check_close(std::fabs(h3.GetReal(it)-(h1.GetReal(it)+h2.GetReal(it))),Real(0.0),1e-6)); + BOOST_CHECK_SMALL(h3.GetReal(it)-(h1.GetReal(it)+h2.GetReal(it)),Real(1e-6)); } else if (ex1.Contains(it)) { - BOOST_REQUIRE(h3.GetReal(it)==h1.GetReal(it)); + BOOST_CHECK(h3.GetReal(it)==h1.GetReal(it)); } else { - BOOST_REQUIRE(h3.GetReal(it)==0.0); + BOOST_CHECK(h3.GetReal(it)==0.0); } } @@ -324,28 +330,36 @@ void test_ImageOps() h3=h1-h2; for(ExtentIterator it(Extent(Point(-2,-1),Point(1,2))); !it.AtEnd(); ++it) { if(ex1.Contains(it) && ex2.Contains(it)) { - BOOST_REQUIRE(check_close(std::fabs(h3.GetReal(it)-(h1.GetReal(it)-h2.GetReal(it))),Real(0.0),1e-6)); + BOOST_CHECK_SMALL(h3.GetReal(it)-(h1.GetReal(it)-h2.GetReal(it)),Real(1e-6)); } else if (ex1.Contains(it)) { - BOOST_REQUIRE(h3.GetReal(it)==h1.GetReal(it)); + BOOST_CHECK(h3.GetReal(it)==h1.GetReal(it)); } else { - BOOST_REQUIRE(h3.GetReal(it)==0.0); + BOOST_CHECK(h3.GetReal(it)==0.0); } } // half frequency tests h1=CreateImage(Size(4,5),COMPLEX,HALF_FREQUENCY); h2=CreateImage(Size(4,5),COMPLEX,HALF_FREQUENCY); - h1.ApplyIP(rnd); - h2.ApplyIP(rnd); + for(ExtentIterator it(h1.GetExtent()); !it.AtEnd(); ++it) { + Complex c(count,count+2); + h1.SetComplex(it,c); + count+=1.0; + } + for(ExtentIterator it(h2.GetExtent()); !it.AtEnd(); ++it) { + Complex c(count,count+2); + h2.SetComplex(it,c); + count+=1.0; + } h3=h1+h2; for(ExtentIterator it(h1.GetExtent());!it.AtEnd();++it) { - BOOST_REQUIRE(std::abs(h1.GetComplex(it)+h2.GetComplex(it)-h3.GetComplex(it))<1e-10); + BOOST_CHECK_SMALL(std::abs(h1.GetComplex(it)+h2.GetComplex(it)-h3.GetComplex(it)),Real(1e-10)); } h3=h1-h2; for(ExtentIterator it(Extent(Point(-1,0),Point(2,2)));!it.AtEnd();++it) { - BOOST_REQUIRE(std::abs(h1.GetComplex(it)-h2.GetComplex(it)-h3.GetComplex(it))<1e-10); + BOOST_CHECK_SMALL(std::abs(h1.GetComplex(it)-h2.GetComplex(it)-h3.GetComplex(it)),Real(1e-10)); } } @@ -408,7 +422,7 @@ void test_DataAlgorithms() TestOPAlg op_alg; ImageHandle ih1=CreateImage(Size(1)); - BOOST_REQUIRE(ih1.GetReal(Point(0))==0.0); + BOOST_CHECK(ih1.GetReal(Point(0))==0.0); // in-place alg applied in-place ih1.ApplyIP(ip_alg); @@ -442,28 +456,36 @@ void test_Mult() { ImageHandle im1=CreateImage(Extent(Point(-2,-1,-3),Point(1,2,1)),REAL); ImageHandle im2=CreateImage(Extent(Point(-1,-2,-1),Point(2,1,3)),COMPLEX); - im1.ApplyIP(alg::Randomize()); - im2.ApplyIP(alg::Randomize()); + Real count=0; + for(ExtentIterator it(im1.GetExtent()); !it.AtEnd(); ++it) { + im1.SetReal(it,count); + count+=1.0; + } + for(ExtentIterator it(im2.GetExtent()); !it.AtEnd(); ++it) { + Complex c(count,count+2); + im2.SetComplex(it,c); + count+=1.0; + } ImageHandle im12=im1*im2; - BOOST_REQUIRE(im12.GetExtent()==im1.GetExtent()); + BOOST_CHECK(im12.GetExtent()==im1.GetExtent()); for(ExtentIterator it(im12.GetExtent());!it.AtEnd();++it) { - if(im2.GetExtent().Contains(it)) { - BOOST_REQUIRE(check_close(im12.GetReal(it),im1.GetReal(it)*im2.GetReal(it),1e-10)); + if(im1.GetExtent().Contains(it) && im2.GetExtent().Contains(it)) { + BOOST_CHECK_CLOSE(im12.GetReal(it),im1.GetReal(it)*im2.GetReal(it),Real(1e-10)); } else { - //BOOST_REQUIRE(im12.GetReal(it)==0.0); + //BOOST_CHECK(im21.GetReal(it)==0.0); } } ImageHandle im21=im2*im1; - BOOST_REQUIRE(im21.GetExtent()==im2.GetExtent()); + BOOST_CHECK(im21.GetExtent()==im2.GetExtent()); for(ExtentIterator it(im21.GetExtent());!it.AtEnd();++it) { if(im1.GetExtent().Contains(it) && im2.GetExtent().Contains(it)) { - BOOST_REQUIRE(std::abs(im21.GetComplex(it)-im2.GetComplex(it)*im1.GetComplex(it))<1e-10); + BOOST_CHECK_SMALL(std::abs(im21.GetComplex(it)-im2.GetComplex(it)*im1.GetComplex(it)),Real(1e-10)); } else { - //BOOST_REQUIRE(im21.GetReal(it)==0.0); + //BOOST_CHECK(im21.GetReal(it)==0.0); } } } @@ -476,46 +498,48 @@ void test_AddSub() im2.ApplyIP(alg::Randomize()); ImageHandle im12=im1+im2; - BOOST_REQUIRE(im12.GetExtent()==im1.GetExtent()); + BOOST_CHECK(im12.GetExtent()==im1.GetExtent()); for(ExtentIterator it(im12.GetExtent());!it.AtEnd();++it) { if(im2.GetExtent().Contains(it)) { - BOOST_REQUIRE(check_close(im12.GetReal(it),im1.GetReal(it)+im2.GetReal(it),1e-10)); + BOOST_CHECK_CLOSE(im12.GetReal(it),im1.GetReal(it)+im2.GetReal(it),Real(1e-10)); } else { - BOOST_REQUIRE(im12.GetReal(it)==im1.GetReal(it)); + BOOST_CHECK(im12.GetReal(it)==im1.GetReal(it)); } } im12=im1-im2; - BOOST_REQUIRE(im12.GetExtent()==im1.GetExtent()); + BOOST_CHECK(im12.GetExtent()==im1.GetExtent()); for(ExtentIterator it(im12.GetExtent());!it.AtEnd();++it) { if(im2.GetExtent().Contains(it)) { - BOOST_REQUIRE(check_close(im12.GetReal(it),im1.GetReal(it)-im2.GetReal(it),1e-10)); + BOOST_CHECK_CLOSE(im12.GetReal(it),im1.GetReal(it)-im2.GetReal(it),Real(1e-10)); } else { - BOOST_REQUIRE(im12.GetReal(it)==im1.GetReal(it)); + BOOST_CHECK(im12.GetReal(it)==im1.GetReal(it)); } } ImageHandle im21=im2+im1; - BOOST_REQUIRE(im21.GetExtent()==im2.GetExtent()); + BOOST_CHECK(im21.GetExtent()==im2.GetExtent()); for(ExtentIterator it(im21.GetExtent());!it.AtEnd();++it) { if(im2.GetExtent().Contains(it)) { - BOOST_REQUIRE(im21.GetComplex(it)==im1.GetComplex(it)+im2.GetComplex(it)); + BOOST_CHECK_CLOSE(real(im21.GetComplex(it)),real(im1.GetComplex(it)+im2.GetComplex(it)),Real(1e-10)); + BOOST_CHECK_CLOSE(imag(im21.GetComplex(it)),imag(im1.GetComplex(it)+im2.GetComplex(it)),Real(1e-10)); } else { - BOOST_REQUIRE(im21.GetReal(it)==im2.GetReal(it)); + BOOST_CHECK_CLOSE(im21.GetReal(it),im2.GetReal(it),Real(1e-10)); } } im21=im2-im1; - BOOST_REQUIRE(im21.GetExtent()==im2.GetExtent()); + BOOST_CHECK(im21.GetExtent()==im2.GetExtent()); for(ExtentIterator it(im21.GetExtent());!it.AtEnd();++it) { if(im2.GetExtent().Contains(it)) { - BOOST_REQUIRE(im21.GetComplex(it)==im2.GetComplex(it)-im1.GetComplex(it)); + BOOST_CHECK_CLOSE(real(im21.GetComplex(it)),real(im2.GetComplex(it)-im1.GetComplex(it)),Real(1e-10)); + BOOST_CHECK_CLOSE(imag(im21.GetComplex(it)),imag(im2.GetComplex(it)-im1.GetComplex(it)),Real(1e-10)); } else { - BOOST_REQUIRE(im21.GetReal(it)==im2.GetReal(it)); + BOOST_CHECK_CLOSE(im21.GetReal(it),im2.GetReal(it),Real(1e-10)); } } } @@ -532,8 +556,8 @@ void test_Copy() ImageHandle i3=i1.Copy(false); BOOST_CHECK(i3.GetSpatialOrigin()==Point(7,3,-2)); for(ExtentIterator it(i1.GetExtent());!it.AtEnd();++it) { - BOOST_REQUIRE(i1.GetReal(it)==i2.GetReal(it)); - BOOST_REQUIRE(i3.GetReal(it)==0.0); + BOOST_CHECK(i1.GetReal(it)==i2.GetReal(it)); + BOOST_CHECK(i3.GetReal(it)==0.0); } // complex half frequency i1=CreateImage(Size(6,7),COMPLEX,HALF_FREQUENCY); @@ -554,7 +578,7 @@ void test_Extract() BOOST_CHECK(i2.GetDomain()==SPATIAL); BOOST_CHECK(i2.GetExtent()==Extent(Point(2,3),Point(7,8))); for(ExtentIterator it(i2.GetExtent());!it.AtEnd();++it) { - BOOST_REQUIRE(i2.GetReal(it)==i1.GetReal(it)); + BOOST_CHECK(i2.GetReal(it)==i1.GetReal(it)); } i1=CreateImage(Size(13,20),COMPLEX,FREQUENCY); @@ -565,7 +589,7 @@ void test_Extract() BOOST_CHECK(i2.GetDomain()==SPATIAL); BOOST_CHECK(i2.GetExtent()==Extent(Point(2,3),Point(7,8))); for(ExtentIterator it(i2.GetExtent());!it.AtEnd();++it) { - BOOST_REQUIRE(i2.GetComplex(it)==i1.GetComplex(it)); + BOOST_CHECK(i2.GetComplex(it)==i1.GetComplex(it)); } i1=CreateImage(Size(13,30),COMPLEX,HALF_FREQUENCY); @@ -576,7 +600,7 @@ void test_Extract() BOOST_CHECK(i2.GetDomain()==SPATIAL); BOOST_CHECK(i2.GetExtent()==Extent(Point(-2,-3),Point(7,8))); for(ExtentIterator it(i2.GetExtent());!it.AtEnd();++it) { - BOOST_REQUIRE(i2.GetComplex(it)==i1.GetComplex(it)); + BOOST_CHECK(i2.GetComplex(it)==i1.GetComplex(it)); } } @@ -592,9 +616,9 @@ void test_Paste() for(ExtentIterator it(i3.GetExtent());!it.AtEnd();++it) { if(i2.GetExtent().Contains(it)) { - BOOST_REQUIRE(i3.GetReal(it)==i2.GetReal(it)); + BOOST_CHECK(i3.GetReal(it)==i2.GetReal(it)); } else { - BOOST_REQUIRE(i3.GetReal(it)==i1.GetReal(it)); + BOOST_CHECK(i3.GetReal(it)==i1.GetReal(it)); } } } diff --git a/modules/index.rst b/modules/index.rst index afc2142cfb81f0b06d9c83755207b29523132d7a..89bb6d3614d7c91c7fb9050a1fc9f9ab73deecc3 100644 --- a/modules/index.rst +++ b/modules/index.rst @@ -93,6 +93,9 @@ Varia **Datasets:** :doc:`tabular data <table>` +**File Formats:** :doc:`supported file formats <io/formats>` + + Extending OpenStructure -------------------------------------------------------------------------------- @@ -102,4 +105,4 @@ Extending OpenStructure - \ No newline at end of file + diff --git a/modules/info/CMakeLists.txt b/modules/info/CMakeLists.txt index 9214aaa382e2e266e1d41dc1aeab37a69d4001ca..23eb6ec6733d11d5a081328ae04865a0240f66b2 100644 --- a/modules/info/CMakeLists.txt +++ b/modules/info/CMakeLists.txt @@ -1,2 +1,4 @@ -add_subdirectory(src) -add_subdirectory(pymod) +if (ENABLE_INFO) + add_subdirectory(src) + add_subdirectory(pymod) +endif() \ No newline at end of file diff --git a/modules/info/pymod/wrap_info.cc b/modules/info/pymod/wrap_info.cc index 223dbe1a9cfd8bd79ada7978aa6cf6a94e1b6225..4af9741d63430f0964b415d83410641ab9d54762 100644 --- a/modules/info/pymod/wrap_info.cc +++ b/modules/info/pymod/wrap_info.cc @@ -34,8 +34,6 @@ using namespace boost::python; using namespace ost; using namespace ost::info; -namespace { - InfoHandle (*CreateInfoPtr1)()=CreateInfo; InfoHandle (*CreateInfoPtr2)(const String&)=CreateInfo; @@ -94,7 +92,7 @@ void info_handle_apply2b(InfoHandle* h, InfoConstVisitor& v, bool b) h->Apply(v,b); } -void info_handle_remove1(InfoHandle* h, InfoPath& path ) +void info_handle_remove1(InfoHandle* h, const String& path ) { h->Remove(path); } @@ -103,7 +101,7 @@ void info_handle_remove2(InfoHandle* h, InfoGroup& group ) { h->Remove(group); } -void info_handle_remove3(InfoHandle* h, InfoPath& path, bool use_defaults ) +void info_handle_remove3(InfoHandle* h, const String& path, bool use_defaults ) { h->Remove(path,use_defaults); } @@ -154,7 +152,6 @@ InfoItem (InfoGroup::*create_item_b)(const String&, int)=&InfoGroup::CreateItem; InfoItem (InfoGroup::*create_item_c)(const String&, bool)=&InfoGroup::CreateItem; InfoItem (InfoGroup::*create_item_d)(const String&, Real)=&InfoGroup::CreateItem; -} BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(getgroup_overloads, GetGroup, 1, 2) BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(retrievegroup_overloads, RetrieveGroup, 1, 2) diff --git a/modules/io/doc/formats.rst b/modules/io/doc/formats.rst index 3912141d21a5a59de7aeb94306e7e014890c1069..fc6fee4cb8e12e0b2ed01731d0a213be18270b76 100644 --- a/modules/io/doc/formats.rst +++ b/modules/io/doc/formats.rst @@ -71,3 +71,116 @@ Promod *Format Name* promod + + +Image File Formats +-------------------------------------------------------------------------------- + +DAT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +*Recognized File Extensions* + dat, img + +*Format Name* + Simple binary format for square images + +DF3 +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +*Recognized File Extensions* + df3 + +*Format Name* + PovRay Density file format + +DM3 +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +*Recognized File Extensions* + dm3 + +*Format Name* + Format used by Gatan Inc.'s Digital Micrograph software + +DX +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +*Recognized File Extensions* + dx + +*Format Name* + Format used by the OpenDX software package + +IPL +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +*Recognized File Extensions* + ipl + +*Format Name* + Ditabis Micron Image Plate Scanner Format + +JPK +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +*Recognized File Extensions* + jpk + +*Format Name* + Format used by JPK Instruments AG's software (Customized Tiff format) + +MRC +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +*Recognized File Extensions* + map, ccp4, mrc + +*Format Name* + Format used by the MRC software package + +NanoScope +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +*Recognized File Extensions* + mod + +*Format Name* + Format used by software from Veeco + +PNG +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +*Recognized File Extensions* + png + +*Format Name* + Portable Network Graphic image format + +Situs +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +*Recognized File Extensions* + situs, sit + +*Format Name* + Format used by the Situs software package + +SPI +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +*Recognized File Extensions* + spi + +*Format Name* + Format used by the Spider software package + +TIFF +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +*Recognized File Extensions* + tif, tiff + +*Format Name* + Tagged Image File Format + diff --git a/modules/io/doc/io.rst b/modules/io/doc/io.rst index 4746f452cf6e72287c54e2e05012fd775d7be3d3..41759d1987ef149bd53ed942fc21814b22ba43c0 100644 --- a/modules/io/doc/io.rst +++ b/modules/io/doc/io.rst @@ -5,6 +5,7 @@ :hidden: formats + mmcif profile .. module:: ost.io diff --git a/modules/io/doc/mmcif.rst b/modules/io/doc/mmcif.rst new file mode 100644 index 0000000000000000000000000000000000000000..7e1c330a4dc4f0efd72e8eb424ef43539c4d4352 --- /dev/null +++ b/modules/io/doc/mmcif.rst @@ -0,0 +1,776 @@ +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:`MMCifInfoBioUnit`, :class:`MMCifInfoStructDetails`). + + +Loading mmCIF Files +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. autofunction:: ost.io.LoadMMCIF + + +Categories Available +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The following categories of a mmCIF file are considered by the reader: + +* ``atom_site``: Used to build the :class:`entity <ost.mol.EntityHandle>` +* ``entity``: Involved in setting ChainTypes +* ``entity_poly``: Involved in setting ChainTypes +* ``citation``: Goes into :class:`MMCifInfoCitation` +* ``citation_author``: Goes into :class:`MMCifInfoCitation` +* ``exptl``: Goes into :class:`MMCifInfo` as :attr:`method <MMCifInfo.method>`. +* ``refine``: Goes into :class:`MMCifInfo` as + :attr:`resolution <MMCifInfo.resolution>`. +* ``pdbx_struct_assembly``: Used for :class:`MMCifInfoBioUnit`. +* ``pdbx_struct_assembly_gen``: Used for :class:`MMCifInfoBioUnit`. +* ``pdbx_struct_oper_list``: Used for :class:`MMCifInfoBioUnit`. +* ``struct``: Details about a structure, stored in + :class:`MMCifInfoStructDetails`. +* ``struct_conf``: Stores secondary structure information (practically helices) + in the :class:`entity <ost.mol.EntityHandle>` +* ``struct_sheet_range``: Stores secondary structure information for sheets in + the :class:`entity <ost.mol.EntityHandle>` +* ``pdbx_database_PDB_obs_spr``: Verbose information on obsoleted/ superseded + entries, stored in :class:`MMCifInfoObsolete`. +* ``struct_ref`` stored in :class:`MMCifInfoStructRef` +* ``struct_ref_seq`` stored in :class:`MMCifInfoStructRefSeq` +* ``struct_ref_seq_dif`` stored in :class:`MMCifInfoStructRefDif` + +Info Classes +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Information from mmCIF files which goes beyond structural data, is kept in a +special container, the :class:`MMCifInfo` class. Here is a detailed description +of the annotation available. + +.. class:: MMCifInfo + + This is the container for all bits of non-molecular data pulled from a mmCIF + file. + + .. attribute:: citations + + Stores a list of citations (:class:`MMCifInfoCitation`). + + Also available as :meth:`GetCitations`. + + .. attribute:: biounits + + Stores a list of biounits (:class:`MMCifInfoBioUnit`). + + Also available as :meth:`GetBioUnits`. + + .. attribute:: method + + Stores the experimental method used to create the structure. + + Also available as :meth:`GetMethod`. May also be modified by + :meth:`SetMethod`. + + .. attribute:: resolution + + Stores the resolution of the crystal structure. + + Also available as :meth:`GetResolution`. May also be modified by + :meth:`SetResolution`. + + .. attribute:: operations + + Stores the operations needed to transform a crystal structure into a + bio unit. + + Also available as :meth:`GetOperations`. May also be modified by + :meth:`AddOperation`. + + .. attribute:: struct_details + + Stores details about the structure in a :class:`MMCifInfoStructDetails` + object. + + Also available as :meth:`GetStructDetails`. May also be modified by + :meth:`SetStructDetails`. + + .. attribute:: struct_refs + + Lists all links to external databases in the mmCIF file. + .. method:: AddCitation(citation) + + Add a citation to the citation list of an info object. + + :param citation: Citation to be added. + :type citation: :class:`MMCifInfoCitation` + + .. method:: AddAuthorsToCitation(id, authors) + + Adds a list of authors to a specific citation. + + :param id: identifier of the citation + :type id: :class:`str` + :param authors: List of authors. + :type authors: :class:`~ost.StringList` + + .. method:: GetCitations() + + See :attr:`citations` + + .. method:: AddBioUnit(biounit) + + Add a bio unit to the bio unit list of an info object. + + :param biounit: Bio unit to be added. + :type biounit: :class:`MMCifInfoBioUnit` + + .. method:: GetBioUnits() + + See :attr:`biounits` + + .. method:: SetMethod(method) + + See :attr:`method` + + .. method:: GetMethod() + + See :attr:`method` + + .. method:: SetResolution(resolution) + + See :attr:`resolution` + + .. method:: GetResolution() + + See :attr:`resolution` + + .. method:: AddOperation(operation) + + See :attr:`operations` + + .. method:: GetOperations() + + See :attr:`operations` + + .. method:: SetStructDetails(details) + + See :attr:`struct_details` + + .. method:: GetStructDetails() + +.. class:: MMCifInfoCitation + + This stores citation information from an input file. + + .. attribute:: id + + Stores an internal identifier for a citation. If not provided, resembles an + empty string. + + Also available as :meth:`GetID`. May also be modified by :meth:`SetID`. + + .. attribute:: cas + + Stores a Chemical Abstract Service identifier, if available. If not + provided, resembles an empty string. + + Also available as :meth:`GetCAS`. May also be modified by :meth:`SetCas`. + + .. attribute:: isbn + + Stores the ISBN code, presumably for cited books. If not + provided, resembles an empty string. + + Also available as :meth:`GetISBN`. May also be modified by :meth:`SetISBN`. + + .. attribute:: published_in + + Stores the book or journal title of a publication. Should take the full + title, no abbreviations. If not provided, resembles an empty string. + + Also available as :meth:`GetPublishedIn`. May also be modified by + :meth:`SetPublishedIn`. + + .. attribute:: volume + + Supposed to store volume information for journals. Since the volume number + is not always a simple integer, it is stored as a string. If not provided, + resembles an empty string. + + Also available as :meth:`GetVolume`. May also be modified by + :meth:`SetVolume`. + + .. attribute:: page_first + + Stores the first page of a publication. Since the page numbers are not + always a simple integers, they are stored as strings. If not provided, + resembles empty strings. + + Also available as :meth:`GetPageFirst`. May also be modified by + :meth:`SetPageFirst`. + + .. attribute:: page_last + + Stores the last page of a publication. Since the page numbers are not + always a simple integers, they are stored as strings. If not provided, + resembles empty strings. + + Also available as :meth:`GetPageLast`. May also be modified by + :meth:`SetPageLast`. + + .. attribute:: doi + + Stores the Document Object Identifier as used by doi.org for a cited + document. If not provided, resembles a empty strings. + + Also available as :meth:`GetDOI`. May also be modified by :meth:`SetDOI`. + + .. attribute:: pubmed + + Stores the PubMed accession number. If not provided, is set to 0. + + Also available as :meth:`GetPubMed`. May also be modified by + :meth:`SetPubmed`. + + .. attribute:: year + + Stores the publication year. If not provided, is set to 0. + + Also available as :meth:`GetYear`. May also be modified by :meth:`SetYear`. + + .. attribute:: title + + Stores a title. If not provided, is set to an empty string. + + Also available as :meth:`GetTitle`. May also be modified by + :meth:`SetTitle`. + + .. attribute:: authors + + Stores a :class:`~ost.StringList` of authors. + + Also available as :meth:`GetAuthorList`. May also be modified by + :meth:`SetAuthorList`. + + .. method:: GetCAS() + + See :attr:`cas` + + .. method:: SetCAS(cas) + + See :attr:`cas` + + .. method:: GetISBN() + + See :attr:`isbn` + + .. method:: SetISBN(isbn) + + See :attr:`isbn` + + .. method:: GetPublishedIn() + + See :attr:`published_in` + + .. method:: SetPublishedIn(title) + + See :attr:`published_in` + + .. method:: GetVolume() + + See :attr:`volume` + + .. method:: SetVolume(volume) + + See :attr:`volume` + + .. method:: GetPageFirst() + + See :attr:`page_first` + + .. method:: SetPageFirst(first) + + See :attr:`page_first` + + .. method:: GetPageLast() + + See :attr:`page_last` + + .. method:: SetPageLast(last) + + See :attr:`page_last` + + .. method:: GetDOI() + + See :attr:`doi` + + .. method:: SetDOI(doi) + + See :attr:`doi` + + .. method:: GetPubMed() + + See :attr:`pubmed` + + .. method:: SetPubMed(no) + + See :attr:`pubmed` + + .. method:: GetYear() + + See :attr:`year` + + .. method:: SetYear(year) + + See :attr:`year` + + .. method:: GetTitle() + + See :attr:`title` + + .. method:: SetTitle(title) + + See :attr:`title` + + .. method:: GetAuthorList() + + See :attr:`authors` + + .. method:: SetAuthorList(list) + + See :attr:`authors` + + +.. class:: MMCifInfoTransOperation + + This stores operations needed to transform an + :class:`entity <ost.mol.EntityHandle>` into a bio unit. + + .. attribute:: id + + A unique identifier. If not provided, resembles an empty string. + + Also available as :meth:`GetID`. May also be modified by + :meth:`SetID`. + + .. attribute:: type + + Describes the operation. If not provided, resembles an empty string. + + Also available as :meth:`GetType`. May also be modified by + :meth:`SetType`. + + .. attribute:: translation + + The translational vector. Also available as :meth:`GetVector`. May also be + + modified by :meth:`SetVector`. + + .. attribute:: rotation + + The rotational matrix. Also available as :meth:`GetMatrix`. May also be + + modified by :meth:`SetMatrix`. + + .. method:: GetID() + + See :attr:`id` + + .. method:: SetID(id) + + See :attr:`id` + + .. method:: GetType() + + See :attr:`type` + + .. method:: SetType(type) + + See :attr:`type` + + .. method:: GetVector() + + See :attr:`translation` + + .. method:: SetVector(x, y, z) + + See :attr:`translation` + + .. method:: GetMatrix() + + See :attr:`rotation` + + .. method:: SetMatrix(i00,i01, i02, i10,i11, i12, i20,i21, i22) + + See :attr:`rotation` + +.. class:: MMCifInfoBioUnit + + This stores information how a structure is to be assembled to form the + bio unit. + + .. attribute:: details + + Special aspects of the biological assembly. If not provided, resembles an + empty string. + + Also available as :meth:`GetDetails`. May also be modified by + :meth:`SetDetails`. + + .. attribute:: chains + + Chains involved in this bio unit. If not provided, resembles an empty list. + + Also available as :meth:`GetChainList`. May also be modified by + :meth:`AddChain`. + + .. attribute:: operations + + Translations and rotations needed to create the bio unit. Filled with + objects of class :class:`MMCifInfoTransOperation`. + + Also available as :meth:`GetOperations`. May be modified by + :meth:`AddOperations` + + .. method:: GetDetails() + + See :attr:`details` + + .. method:: SetDetails(details) + + See :attr:`details` + + .. method:: GetChainList() + + See :attr:`chains` + + .. method:: AddChain(chain name) + + See :attr:`chains` + + .. method:: GetOperations() + + See :attr:`operations` + + .. method:: AddOperations(list of operations) + + See :attr:`operations` + +.. function:: PDBize(asu, seqres=None, min_polymer_size=10) + + Returns the biological assembly (bio unit) for an entity. The new entity + created is well suited to be saved as a PDB file. Therefore the function + tries to meet the requirements of single-character chain names. The + following measures are taken. + + - All ligands are put into one chain (_) + - Water is put into one chain (-) + - Each polymer gets its own chain, named A-Z 0-9 a-z. + - The description of non-polymer chains will be put into a generic string + property called description on the residue level. + - ligands which resemble a polymer but have less than min_polymer_size + residues are assigned the same numeric residue number. The residues are + distinguished by insertion code. + + Since this function is at the moment mainly used to create biounits from + mmCIF files to be saved as PDBs, the function assumes that the + :ref:`ChainType` properties are set correctly. :func:`ost.conop.ConnectAll` + is used to derive connectivity. + + :param asu: Asymmetric unit to work on. Should be created from a mmCIF + file. + :type asu: :class:`~ost.mol.EntityHandle>` + :param seqres: If set to a valid sequence list, the length of the seqres + records will be used to determine if a certain chain has the minimally + required length. + :type seqres: :class:'~ost.seq.SequenceList' + :param min_polymer_size: The minimal number of residues a polymer needs to + get its own chain. Everything below that number will be sorted into the + ligand chain. + :type min_polymer_size: int + +.. class:: MMCifInfoStructDetails + + Holds details about the structure. + + .. attribute:: entry_id + + Identifier for a curtain data block. If not provided, resembles an empty + string. + + Also available as :meth:`GetEntryID`. May also be modified by + :meth:`SetEntryID`. + + .. attribute:: title + + Set a title for the structure. + + Also available as :meth:`GetTitle`. May also be modified by + :meth:`SetTitle`. + + .. attribute:: casp_flag + + Tells whether this structure was target in some competition. + + Also available as :meth:`GetCASPFlag`. May also be modified by + :meth:`SetCASPFlag`. + + .. attribute:: descriptor + + Descriptor for an NDB structure or the unstructured content of a PDB COMPND + record. + + Also available as :meth:`GetDescriptor`. May also be modified by + :meth:`SetDescriptor`. + + .. attribute:: mass + + Molecular mass of a molecule. + + Also available as :meth:`GetMass`. May also be modified by + :meth:`SetMass`. + + .. attribute:: mass_method + + Method used to determine the molecular weight. + + Also available as :meth:`GetMassMethod`. May also be modified by + :meth:`SetMassMethod`. + + .. attribute:: model_details + + Details about how the structure was determined. + + Also available as :meth:`GetModelDetails`. May also be modified by + :meth:`SetModelDetails`. + + .. attribute:: model_type_details + + Details about how the type of the structure. + + Also available as :meth:`GetModelTypeDetails`. May also be modified by + :meth:`SetModelTypeDetails`. + + .. method:: GetEntryID() + + See :attr:`entry_id` + + .. method:: SetEntryID(id) + + See :attr:`entry_id` + + .. method:: GetTitle() + + See :attr:`title` + + .. method:: SetTitle(title) + + See :attr:`title` + + .. method:: GetCASPFlag() + + See :attr:`casp_flag` + + .. method:: SetCASPFlag(flag) + + See :attr:`casp_flag` + + .. method:: GetDescriptor() + + See :attr:`descriptor` + + .. method:: SetDescriptor(descriptor) + + See :attr:`descriptor` + + .. method:: GetMass() + + See :attr:`mass` + + .. method:: SetMass(mass) + + See :attr:`mass` + + .. method:: GetMassMethod() + + See :attr:`mass_method` + + .. method:: SetMassMethod(method) + + See :attr:`mass_method` + + .. method:: GetModelDetails() + + See :attr:`model_details` + + .. method:: SetModelDetails(details) + + See :attr:`model_details` + + .. method:: GetModelTypeDetails() + + See :attr:`model_type_details` + + .. method:: SetModelTypeDetails(details) + + See :attr:`model_type_details` + +.. class:: MMCifInfoObsolete + + Holds details on obsolete/ superseded structures. + + .. attribute:: date + + When was the entry replaced? + + Also available as :meth:`GetDate`. May also be modified by + :meth:`SetDate`. + + .. attribute:: id + + Type of change. Either *Obsolete* or *Supersede*. Returns a string starting + upper case. Has to be set via ``OBSLTE`` or ``SPRSDE``. + + Also available as :meth:`GetID`. May also be modified by + :meth:`SetID`. + + .. attribute:: pdb_id + + ID of the replacing entry. + + Also available as :meth:`GetPDBID`. May also be modified by + :meth:`SetPDBID`. + + .. attribute:: replace_pdb_id + + ID of the replaced entry. + + Also available as :meth:`GetReplacedPDBID`. May also be modified by + :meth:`SetReplacedPDBID`. + + .. method:: GetDate() + + See :attr:`date` + + .. method:: SetDate(date) + + See :attr:`date` + + .. method:: GetID() + + See :attr:`id` + + .. method:: SetID(id) + + See :attr:`id` + + .. method:: GetPDBID() + + See :attr:`pdb_id` + + .. method:: SetPDBID(flag) + + See :attr:`pdb_id` + + .. method:: GetReplacedPDBID() + + See :attr:`replace_pdb_id` + + .. method:: SetReplacedPDBID(descriptor) + + See :attr:`replace_pdb_id` + +.. 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. + + .. attribute:: db_name + + + Name of the external database, for example UNP for uniprot. + + :type: :class:`str` + + + .. attribute:: db_id + + Name of the reference sequence in the database pointed to by :attr:`db_name`. + + :type: :class:`str` + + .. attribute:: db_access + + Alternative accession code for the sequence in the database pointed to by + :attr:`db_name`. + + :type: :class:`str` + + .. method:: GetAlignedSeq(name) + + Returns the aligned sequence for the given name, None if the sequence does + not exist. + + .. attribute:: aligned_seqs + + List of aligned sequences (all entries of the struct_ref_seq category + mapping to this struct_ref). + +.. class:: MMCifInfoStructRefSeq + + An aligned range of residues between a sequence in a reference database and the + deposited sequence. + + .. attribute:: align_id + + Uniquely identifies every struct_ref_seq item in the mmCIF file. + :type: :class:`str` + + .. attribute:: seq_begin + seq_end + The starting point (1-based) and end point of the aligned range in the + deposited sequence, respectively. + + :type: :class:`int` + + .. attribute:: db_begin + db_end + The starting point (1-based) and end point of the aligned range in the + database sequence, respectively. + + :type: :class:`int` + + .. attribute:: difs + + List of differences between the deposited sequence and the sequence in the + database. + + .. attribute:: chain_name + + Chain name of the polymer in the mmCIF file. + +.. class:: MMCifInfoStructRefSeqDif + + A particular difference between the deposited sequence and the sequence in + the database. + + .. attribute:: rnum + + The residue number (1-based) of the residue in the deposited sequence + + :type: :class:`int` + + .. attribute:: details + + A textual description of the difference, e.g. point mutation, + expressiontag, purification artifact. + + :type: :class:`str` +.. LocalWords: cas isbn pubmed asu seqres conop ConnectAll casp COMPND OBSLTE +.. LocalWords: SPRSDE pdb func diff --git a/modules/io/pymod/CMakeLists.txt b/modules/io/pymod/CMakeLists.txt index 902089f7f0d3e28b219993f01c79852ac37135c2..007569fff38887504ed15d21231b2b5d4464b346 100644 --- a/modules/io/pymod/CMakeLists.txt +++ b/modules/io/pymod/CMakeLists.txt @@ -1,6 +1,7 @@ set(OST_IO_PYMOD_SOURCES wrap_io.cc export_pdb_io.cc + export_mmcif_io.cc ) if (ENABLE_IMG) @@ -13,10 +14,11 @@ set(OST_IO_PYMOD_MODULES repository.py ) - -pymod(NAME io CPP ${OST_IO_PYMOD_SOURCES} PY ${OST_IO_PYMOD_MODULES}) -if (STATIC_LIBRARIES) - message("adding zlib libraries") - target_link_libraries(_io ${ZLIB_LIBRARIES}) +if (NOT ENABLE_STATIC) + pymod(NAME io CPP ${OST_IO_PYMOD_SOURCES} PY ${OST_IO_PYMOD_MODULES}) + if (STATIC_LIBRARIES) + message("adding zlib libraries") + target_link_libraries(_ost_io ${ZLIB_LIBRARIES}) + endif() endif() diff --git a/modules/io/pymod/__init__.py b/modules/io/pymod/__init__.py index 74047dec07c568e5514e3dfcde4a7df9ec9c02a9..95ea418b344a21910a925f463151d34af4a8eb22 100644 --- a/modules/io/pymod/__init__.py +++ b/modules/io/pymod/__init__.py @@ -19,7 +19,7 @@ import os, tempfile, ftplib, httplib from _ost_io import * -from ost import mol, conop +from ost import mol, geom, conop profiles=None @@ -86,9 +86,9 @@ def LoadPDB(filename, restrict_chains="", no_hetatms=None, fault_tolerant=None, load_multi=False, quack_mode=None, join_spread_atom_records=None, calpha_only=None, profile='DEFAULT', remote=False, dialect=None, - strict_hydrogens=None, seqres=False): + strict_hydrogens=None, seqres=False, bond_feasibility_check=None): """ - Load PDB file from disk and returns one or more entities. Several options + Load PDB file from disk and return one or more entities. Several options allow to customize the exact behaviour of the PDB import. For more information on these options, see :doc:`profile`. @@ -147,6 +147,7 @@ def LoadPDB(filename, restrict_chains="", no_hetatms=None, prof.quack_mode=_override(prof.quack_mode, quack_mode) prof.strict_hydrogens=_override(prof.strict_hydrogens, strict_hydrogens) prof.fault_tolerant=_override(prof.fault_tolerant, fault_tolerant) + prof.bond_feasibility_check=_override(prof.bond_feasibility_check, bond_feasibility_check) prof.join_spread_atom_records=_override(prof.join_spread_atom_records, join_spread_atom_records) @@ -164,6 +165,7 @@ def LoadPDB(filename, restrict_chains="", no_hetatms=None, elif prof.dialect=='CHARMM': builder.dialect=conop.CHARMM_DIALECT builder.strict_hydrogens=prof.strict_hydrogens + builder.bond_feasibility_check=prof.bond_feasibility_check reader=PDBReader(filename, prof) reader.read_seqres=seqres try: @@ -175,7 +177,7 @@ def LoadPDB(filename, restrict_chains="", no_hetatms=None, conop_inst.ConnectAll(builder, ent, 0) ent_list.append(ent) if len(ent_list)==0: - raise IOError("File doesn't contain any entities") + raise IOError("File '%s' doesn't contain any entities" % filename) return ent_list else: ent=mol.CreateEntity() @@ -183,7 +185,7 @@ def LoadPDB(filename, restrict_chains="", no_hetatms=None, reader.Import(ent, restrict_chains) conop_inst.ConnectAll(builder, ent, 0) else: - raise IOError("File doesn't contain any entities") + raise IOError("File '%s' doesn't contain any entities" % filename) if seqres: return ent, reader.seqres return ent @@ -192,10 +194,12 @@ def LoadPDB(filename, restrict_chains="", no_hetatms=None, def SavePDB(models, filename, dialect=None, pqr=False, profile='DEFAULT'): """ - Save entity or list of entities to disk. If a list of entities is supplied the - PDB file will be saved as a multi PDB file. Each of the entities is wrapped - into a MODEL/ENDMDL pair. - + Save entity or list of entities to disk. If a list of entities is supplied + the PDB file will be saved as a multi PDB file. Each of the entities is + wrapped into a MODEL/ENDMDL pair. + + If the atom number exceeds 99999, '*****' is used. + :param models: The entity or list of entities (handles or views) to be saved :param filename: The filename :type filename: string @@ -264,6 +268,190 @@ def LoadCHARMMTraj(crd, dcd_file=None, profile='CHARMM', raise ValueError("No DCD filename given") return LoadCHARMMTraj_(crd, dcd_file, stride, lazy_load) +def LoadMMCIF(filename, restrict_chains="", fault_tolerant=None, calpha_only=None, profile='DEFAULT', remote=False, strict_hydrogens=None, seqres=False, info=False): + """ + Load MMCIF file from disk and return one or more entities. Several options + allow to customize the exact behaviour of the MMCIF import. For more + information on these options, see :doc:`profile`. + + Residues are flagged as ligand if they are mentioned in a HET record. + + :param restrict_chains: If not an empty string, only chains listed in the + string will be imported. + + :param fault_tolerant: Enable/disable fault-tolerant import. If set, overrides + the value of :attr:`IOProfile.fault_tolerant`. + + :param remote: If set to true, the method tries to load the pdb from the + remote pdb repository www.pdb.org. The filename is then interpreted as the + pdb id. + + :rtype: :class:`~ost.mol.EntityHandle`. + + :param strict_hydrogens: If set, overrides the value of + :attr:`IOProfile.strict_hydrogens`. + + :param seqres: Whether to read SEQRES records. If set to true, the loaded + entity and seqres entry will be returned as second item. + + :param info: Whether to return an info container with the other output. + Returns a :class:`MMCifInfo` object as last item. + + :raises: :exc:`~ost.io.IOException` if the import fails due to an erroneous + or inexistent file + """ + def _override(val1, val2): + if val2!=None: + return val2 + else: + return val1 + if isinstance(profile, str): + prof = profiles[profile].Copy() + else: + prof = profile.Copy() + + prof.calpha_only=_override(prof.calpha_only, calpha_only) + prof.strict_hydrogens=_override(prof.strict_hydrogens, strict_hydrogens) + prof.fault_tolerant=_override(prof.fault_tolerant, fault_tolerant) + + if remote: + output_dir = tempfile.gettempdir() + if __GetModelFromPDB(filename, output_dir): + filename = os.path.join(output_dir, 'pdb%s.ent.gz' % filename) + else: + raise IOError('Can not load PDB %s from www.pdb.org'%filename) + + conop_inst = conop.Conopology.Instance() + builder = conop_inst.GetBuilder("DEFAULT") + + builder.strict_hydrogens = prof.strict_hydrogens + + try: + ent = mol.CreateEntity() + reader = MMCifReader(filename, ent, prof) + reader.read_seqres = seqres + #if reader.HasNext(): + reader.Parse() + conop_inst.ConnectAll(builder, ent, 0) + #else: + # raise IOError("File doesn't contain any entities") + if seqres and info: + return ent, reader.seqres, reader.info + if seqres: + return ent, reader.seqres + if info: + return ent, reader.info + return ent + except: + raise + +# this function uses a dirty trick: should be a member of MMCifInfoBioUnit +# which is totally C++, but we want the method in Python... so we define it +# here (__init__) and add it as a member to the class. With this, the first +# arguement is the usual 'self'. +# documentation for this function was moved to mmcif.rst, +# MMCifInfoBioUnit.PDBize, since this function is not included in SPHINX. +def _PDBize(biounit, asu, seqres=None, min_polymer_size=10): + def _CopyAtoms(src_res, dst_res, edi, trans=geom.Mat4()): + for atom in src_res.atoms: + tmp_pos = geom.Vec4(atom.pos) + new_atom=edi.InsertAtom(dst_res, atom.name, geom.Vec3(trans*tmp_pos), + element=atom.element, + occupancy=atom.occupancy, + b_factor=atom.b_factor, + is_hetatm=atom.is_hetatom) + + chain_names='ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz' + # create list of operations + # for cartesian products, operations are stored in a list, multiplied with + # the next list of operations and re-stored... until all lists of operations + # are multiplied in an all-against-all manner. + operations = biounit.GetOperations() + trans_matrices = list() + if len(operations) > 0: + for op in operations[0]: + rot = geom.Mat4() + rot.PasteRotation(op.rotation) + trans = geom.Mat4() + trans.PasteTranslation(op.translation) + tr = geom.Mat4() + tr = trans * rot + trans_matrices.append(tr) + for op_n in range(1, len(operations)): + tmp_ops = list() + for o in operations[op_n]: + rot = geom.Mat4() + rot.PasteRotation(o.rotation) + trans = geom.Mat4() + trans.PasteTranslation(o.translation) + tr = geom.Mat4() + tr = trans * rot + for t_o in trans_matrices: + tp = t_o * tr + tmp_ops.append(tp) + trans_matrices = tmp_ops + # select chains into a view as basis for each transformation + assu = asu.Select('cname=' + ','.join(biounit.GetChainList())) + # use each transformation on the view, store as entity and transform, PDBize + # the result while adding everything to one large entity + pdb_bu = mol.CreateEntity() + edi = pdb_bu.EditXCS(mol.BUFFERED_EDIT) + cur_chain_name = 0 + water_chain = mol.ChainHandle() + ligand_chain = mol.ChainHandle() + for tr in trans_matrices: + # do a PDBize, add each new entity to the end product + for chain in assu.chains: + residue_count = len(chain.residues) + if seqres: + seqres_chain = seqres.FindSequence(chain.name) + if seqres_chain.IsValid(): + residue_count = len(seqres_chain) + if chain.is_polymer and residue_count >= min_polymer_size: + if len(chain_names) == cur_chain_name: + raise RuntimeError('Running out of chain names') + new_chain = edi.InsertChain(chain_names[cur_chain_name]) + cur_chain_name += 1 + edi.SetChainDescription(new_chain, chain.description) + edi.SetChainType(new_chain, chain.type) + new_chain.SetStringProp('original_name', chain.name) + for res in chain.residues: + new_res = edi.AppendResidue(new_chain, res.name, res.number) + _CopyAtoms(res, new_res, edi, tr) + elif chain.type == mol.CHAINTYPE_WATER: + if not water_chain.IsValid(): + # water gets '-' as name + water_chain = edi.InsertChain('-') + edi.SetChainDescription(water_chain, chain.description) + edi.SetChainType(water_chain, chain.type) + for res in chain.residues: + new_res = edi.AppendResidue(water_chain, res.name) + new_res.SetStringProp('type', mol.StringFromChainType(chain.type)) + new_res.SetStringProp('description', chain.description) + _CopyAtoms(res, new_res, edi, tr) + else: + if not ligand_chain.IsValid(): + # all ligands, put in one chain, are named '_' + ligand_chain = edi.InsertChain('_') + last_rnum = 0 + else: + last_rnum = ligand_chain.residues[-1].number.num + residues=chain.residues + ins_code='\0' + if len(residues)>1: + ins_code='A' + for res in chain.residues: + new_res = edi.AppendResidue(ligand_chain, res.name, + mol.ResNum(last_rnum+1, ins_code)) + new_res.SetStringProp('description', chain.description) + new_res.SetStringProp('type', mol.StringFromChainType(chain.type)) + ins_code = chr(ord(ins_code)+1) + _CopyAtoms(res, new_res, edi, tr) + conop.ConnectAll(pdb_bu) + return pdb_bu + +MMCifInfoBioUnit.PDBize = _PDBize + ## \example fft_li.py # # This scripts loads one or more images and shows their Fourier Transforms on diff --git a/modules/io/pymod/export_map_io.cc b/modules/io/pymod/export_map_io.cc index beb7601bc63916a64e52e74035c853ebbb778662..afe494d1997b4d1720fe49592b35c36e51976980 100644 --- a/modules/io/pymod/export_map_io.cc +++ b/modules/io/pymod/export_map_io.cc @@ -27,6 +27,7 @@ #include <ost/io/img/map_io_dat_handler.hh> #include <ost/io/img/map_io_jpk_handler.hh> #include <ost/io/img/map_io_nanoscope_handler.hh> +#include <ost/io/img/map_io_ipl_handler.hh> #include <ost/io/img/image_format.hh> #include <ost/io/img/load_map.hh> @@ -79,18 +80,17 @@ void export_map_io() .export_values() ; - enum_<Subformat>("Format") + enum_<Subformat>("Subformat") .value("MRC_NEW_FORMAT", MRC_NEW_FORMAT) .value("MRC_OLD_FORMAT", MRC_OLD_FORMAT) .value("MRC_AUTO_FORMAT", MRC_AUTO_FORMAT) .export_values() ; + class_<ImageFormatBase>("ImageFormatBase",no_init) .def("GetMaximum", &ImageFormatBase::GetMaximum) - .def("SetMaximum", &ImageFormatBase::GetMaximum) .def("GetMinimum", &ImageFormatBase::GetMinimum) - .def("SetMinimum", &ImageFormatBase::GetMinimum) ; class_<DX, bases<ImageFormatBase> >("DX", init<bool>(arg("normalize_on_save") = false)) @@ -154,6 +154,13 @@ void export_map_io() .def("GetBitDepth", &DAT::GetBitDepth) ; + class_<IPL, bases<ImageFormatBase> >("IPL", init<bool,Format>((arg("normalize_on_save") = true,arg("format")=OST_DEFAULT_FORMAT))) + .def("SetNormalizeOnSave", &IPL::SetNormalizeOnSave) + .def("GetNormalizeOnSave", &IPL::GetNormalizeOnSave) + .def("SetBitDepth", &IPL::SetBitDepth) + .def("GetBitDepth", &IPL::GetBitDepth) + ; + class_<JPK, bases<TIF> >("JPK", init<boost::logic::tribool,Format,bool,bool,int> ((arg("normalize_on_save") = boost::logic::tribool(boost::logic::indeterminate),arg("format")=OST_DEFAULT_FORMAT,arg("signed")=false,arg("phasecolor")=false,arg("subimage") = -1))) ; diff --git a/modules/io/pymod/export_mmcif_io.cc b/modules/io/pymod/export_mmcif_io.cc new file mode 100644 index 0000000000000000000000000000000000000000..70e6b46590148293e396cd5dc28b9766fdda3ce5 --- /dev/null +++ b/modules/io/pymod/export_mmcif_io.cc @@ -0,0 +1,296 @@ +//------------------------------------------------------------------------------ +// This file is part of the OpenStructure project <www.openstructure.org> +// +// Copyright (C) 2008-2011 by the OpenStructure authors +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License as published by the Free +// Software Foundation; either version 3.0 of the License, or (at your option) +// any later version. +// This library is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this library; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +//------------------------------------------------------------------------------ +#include <boost/python.hpp> +#include <boost/shared_ptr.hpp> +#include <boost/python/suite/indexing/vector_indexing_suite.hpp> +using namespace boost::python; + +#include <ost/io/mol/io_profile.hh> +#include <ost/io/mol/mmcif_reader.hh> +#include <ost/io/mol/mmcif_info.hh> +using namespace ost; +using namespace ost::io; +using namespace ost::mol; + +void export_mmcif_io() +{ + class_<MMCifReader, boost::noncopyable>("MMCifReader", init<const String&, EntityHandle&, const IOProfile&>()) + .def("Parse", &MMCifReader::Parse) + .def("SetRestrictChains", &MMCifReader::SetRestrictChains) + .def("SetReadCanonicalSeqRes", &MMCifReader::SetReadCanonicalSeqRes) + .def("GetSeqRes", &MMCifReader::GetSeqRes) + .def("GetInfo", make_function(&MMCifReader::GetInfo, + return_value_policy<copy_const_reference>())) + .add_property("restrict_chains", + make_function(&MMCifReader::GetRestrictChains, + return_value_policy<copy_const_reference>()), + &MMCifReader::SetRestrictChains) + .add_property("seqres", &MMCifReader::GetSeqRes) + .add_property("read_seqres", &MMCifReader::GetReadSeqRes, + &MMCifReader::SetReadSeqRes) + .add_property("info", make_function(&MMCifReader::GetInfo, + return_value_policy<copy_const_reference>())) + ; + + class_<MMCifInfoCitation>("MMCifInfoCitation", init<>()) + .def("SetID", &MMCifInfoCitation::SetID) + .def("GetID", &MMCifInfoCitation::GetID) + .def("SetCAS", &MMCifInfoCitation::SetCAS) + .def("GetCAS", &MMCifInfoCitation::GetCAS) + .def("SetISBN", &MMCifInfoCitation::SetISBN) + .def("GetISBN", &MMCifInfoCitation::GetISBN) + .def("SetPublishedIn", &MMCifInfoCitation::SetPublishedIn) + .def("GetPublishedIn", &MMCifInfoCitation::GetPublishedIn) + .def("SetVolume", &MMCifInfoCitation::SetVolume) + .def("GetVolume", &MMCifInfoCitation::GetVolume) + .def("SetPageFirst", &MMCifInfoCitation::SetPageFirst) + .def("GetPageFirst", &MMCifInfoCitation::GetPageFirst) + .def("SetPageLast", &MMCifInfoCitation::SetPageLast) + .def("GetPageLast", &MMCifInfoCitation::GetPageLast) + .def("SetDOI", &MMCifInfoCitation::SetDOI) + .def("GetDOI", &MMCifInfoCitation::GetDOI) + .def("SetPubMed", &MMCifInfoCitation::SetPubMed) + .def("GetPubMed", &MMCifInfoCitation::GetPubMed) + .def("SetYear", &MMCifInfoCitation::SetYear) + .def("GetYear", &MMCifInfoCitation::GetYear) + .def("SetTitle", &MMCifInfoCitation::SetTitle) + .def("GetTitle", &MMCifInfoCitation::GetTitle) + .def("SetAuthorList", &MMCifInfoCitation::SetAuthorList) + .def("GetAuthorList", make_function(&MMCifInfoCitation::GetAuthorList, + return_value_policy<copy_const_reference>())) + .add_property("id", &MMCifInfoCitation::GetID, &MMCifInfoCitation::SetID) + .add_property("cas", &MMCifInfoCitation::GetCAS, &MMCifInfoCitation::SetCAS) + .add_property("isbn", &MMCifInfoCitation::GetISBN, + &MMCifInfoCitation::SetISBN) + .add_property("published_in", &MMCifInfoCitation::GetPublishedIn, + &MMCifInfoCitation::SetPublishedIn) + .add_property("volume", &MMCifInfoCitation::GetVolume, + &MMCifInfoCitation::SetVolume) + .add_property("page_first", &MMCifInfoCitation::GetPageFirst, + &MMCifInfoCitation::SetPageFirst) + .add_property("page_last", &MMCifInfoCitation::GetPageLast, + &MMCifInfoCitation::SetPageLast) + .add_property("doi", &MMCifInfoCitation::GetDOI, &MMCifInfoCitation::SetDOI) + .add_property("pubmed", &MMCifInfoCitation::GetPubMed, + &MMCifInfoCitation::SetPubMed) + .add_property("year", &MMCifInfoCitation::GetYear, + &MMCifInfoCitation::SetYear) + .add_property("title", &MMCifInfoCitation::GetTitle, + &MMCifInfoCitation::SetTitle) + .add_property("authors", make_function(&MMCifInfoCitation::GetAuthorList, + return_value_policy<copy_const_reference>()), + &MMCifInfoCitation::SetAuthorList) + ; + + typedef std::vector<MMCifInfoCitation> MMCifInfoCitationList; + class_<std::vector<MMCifInfoCitation> >("MMCifInfoCitationList", init<>()) + .def(vector_indexing_suite<std::vector<MMCifInfoCitation> >()) + ; + + + class_<MMCifInfoTransOp, MMCifInfoTransOpPtr>("MMCifInfoTransOp", init<>()) + .def("SetID", &MMCifInfoTransOp::SetID) + .def("GetID", &MMCifInfoTransOp::GetID) + .def("SetType", &MMCifInfoTransOp::SetType) + .def("GetType", &MMCifInfoTransOp::GetType) + .def("SetVector", &MMCifInfoTransOp::SetVector) + .def("GetVector", &MMCifInfoTransOp::GetVector) + .def("SetMatrix", &MMCifInfoTransOp::SetMatrix) + .def("GetMatrix", &MMCifInfoTransOp::GetMatrix) + .add_property("id", &MMCifInfoTransOp::GetID, + &MMCifInfoTransOp::SetID) + .add_property("type", &MMCifInfoTransOp::GetType, + &MMCifInfoTransOp::SetType) + .add_property("translation", &MMCifInfoTransOp::GetVector, + &MMCifInfoTransOp::SetVector) + .add_property("rotation", &MMCifInfoTransOp::GetMatrix, + &MMCifInfoTransOp::SetMatrix) + ; + + typedef std::vector<MMCifInfoTransOp> MMCifInfoTransOpList; + class_<std::vector<MMCifInfoTransOp> >("MMCifInfoTransOpList", init<>()) + .def(vector_indexing_suite<std::vector<MMCifInfoTransOp> >()) + ; + + typedef std::vector<MMCifInfoTransOpPtr> MMCifInfoTransOpPtrList; + class_<std::vector<MMCifInfoTransOpPtr> >("MMCifInfoTransOpPtrList", init<>()) + .def(vector_indexing_suite<std::vector<MMCifInfoTransOpPtr>, true >()) + ; + + typedef std::vector<MMCifInfoTransOpPtrList > MMCifInfoTransOpPtrListList; + class_<std::vector<MMCifInfoTransOpPtrList > >("MMCifInfoTransOpPtrListList", + init<>()) + .def(vector_indexing_suite<std::vector<MMCifInfoTransOpPtrList >, true >()) + ; + class_<MMCifInfoStructRef, MMCifInfoStructRefPtr>("MMCifInfoStructRef", no_init) + .add_property("id", make_function(&MMCifInfoStructRef::GetID, + return_value_policy<copy_const_reference>())) + .add_property("db_name", make_function(&MMCifInfoStructRef::GetDBName, + return_value_policy<copy_const_reference>())) + .add_property("db_id", make_function(&MMCifInfoStructRef::GetDBID, + return_value_policy<copy_const_reference>())) + .add_property("entity_id", make_function(&MMCifInfoStructRef::GetEntityID, + return_value_policy<copy_const_reference>())) + .add_property("db_access", make_function(&MMCifInfoStructRef::GetDBAccess, + return_value_policy<copy_const_reference>())) + .def("GetAlignedSeq", &MMCifInfoStructRef::GetAlignedSeq, arg("align_id")) + .def("GetAlignedSeqs", &MMCifInfoStructRef::GetAlignedSeqs) + .add_property("aligned_seqs", &MMCifInfoStructRef::GetAlignedSeqs) + ; + class_<MMCifInfoStructRefSeq, MMCifInfoStructRefSeqPtr>("MMCifInfoStructRefSeq", no_init) + .add_property("align_id", make_function(&MMCifInfoStructRefSeq::GetID, + return_value_policy<copy_const_reference>())) + .add_property("chain_name", make_function(&MMCifInfoStructRefSeq::GetChainName, + return_value_policy<copy_const_reference>())) + .add_property("seq_begin", &MMCifInfoStructRefSeq::GetSeqBegin) + .add_property("seq_end", &MMCifInfoStructRefSeq::GetSeqEnd) + .add_property("db_begin", &MMCifInfoStructRefSeq::GetDBBegin) + .add_property("db_end", &MMCifInfoStructRefSeq::GetDBEnd) + .add_property("difs", make_function(&MMCifInfoStructRefSeq::GetDifs, + return_value_policy<copy_const_reference>())) + ; + class_<MMCifInfoStructRefSeqDif, + MMCifInfoStructRefSeqDifPtr>("MMCifInfoStructRefSeqDif", no_init) + .add_property("details", make_function(&MMCifInfoStructRefSeqDif::GetDetails, + return_value_policy<copy_const_reference>())) + .add_property("seq_rnum", &MMCifInfoStructRefSeqDif::GetSeqRNum) + .add_property("db_rnum", &MMCifInfoStructRefSeqDif::GetDBRNum) + ; + class_<MMCifInfoBioUnit>("MMCifInfoBioUnit", init<>()) + .def("SetDetails", &MMCifInfoBioUnit::SetDetails) + .def("GetDetails", &MMCifInfoBioUnit::GetDetails) + .def("AddChain", &MMCifInfoBioUnit::AddChain) + .def("GetChainList", make_function(&MMCifInfoBioUnit::GetChainList, + return_value_policy<copy_const_reference>())) + .def("AddOperations", &MMCifInfoBioUnit::AddOperations) + .def("GetOperations", make_function(&MMCifInfoBioUnit::GetOperations, + return_value_policy<copy_const_reference>())) + .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>())) + ; + + class_<MMCifInfoStructRefs>("MMCifInfoStructRefs", init<>()) + .def(vector_indexing_suite<MMCifInfoStructRefs, true>()) + ; + class_<MMCifInfoStructRefSeqs>("MMCifInfoStructRefSeqs", init<>()) + .def(vector_indexing_suite<MMCifInfoStructRefSeqs, true>()) + ; + class_<MMCifInfoStructRefSeqDifs>("MMCifInfoStructRefSeqDifs", init<>()) + .def(vector_indexing_suite<MMCifInfoStructRefSeqDifs, true>()) + ; + typedef std::vector<MMCifInfoBioUnit> MMCifInfoBioUnitList; + class_<std::vector<MMCifInfoBioUnit> >("MMCifInfoBioUnitList", init<>()) + .def(vector_indexing_suite<std::vector<MMCifInfoBioUnit> >()) + ; + + class_<MMCifInfoStructDetails>("MMCifInfoStructDetails", init<>()) + .def("SetEntryID", &MMCifInfoStructDetails::SetEntryID) + .def("GetEntryID", &MMCifInfoStructDetails::GetEntryID) + .def("SetTitle", &MMCifInfoStructDetails::SetTitle) + .def("GetTitle", &MMCifInfoStructDetails::GetTitle) + .def("SetCASPFlag", &MMCifInfoStructDetails::SetCASPFlag) + .def("GetCASPFlag", &MMCifInfoStructDetails::GetCASPFlag) + .def("SetDescriptor", &MMCifInfoStructDetails::SetDescriptor) + .def("GetDescriptor", &MMCifInfoStructDetails::GetDescriptor) + .def("SetMass", &MMCifInfoStructDetails::SetMass) + .def("GetMass", &MMCifInfoStructDetails::GetMass) + .def("SetMassMethod", &MMCifInfoStructDetails::SetMassMethod) + .def("GetMassMethod", &MMCifInfoStructDetails::GetMassMethod) + .def("SetModelDetails", &MMCifInfoStructDetails::SetModelDetails) + .def("GetModelDetails", &MMCifInfoStructDetails::GetModelDetails) + .def("SetModelTypeDetails", &MMCifInfoStructDetails::SetModelTypeDetails) + .def("GetModelTypeDetails", &MMCifInfoStructDetails::GetModelTypeDetails) + .add_property("entry_id", &MMCifInfoStructDetails::GetEntryID, + &MMCifInfoStructDetails::SetEntryID) + .add_property("title", &MMCifInfoStructDetails::GetTitle, + &MMCifInfoStructDetails::SetTitle) + .add_property("casp_flag", &MMCifInfoStructDetails::GetCASPFlag, + &MMCifInfoStructDetails::SetCASPFlag) + .add_property("descriptor", &MMCifInfoStructDetails::GetDescriptor, + &MMCifInfoStructDetails::SetDescriptor) + .add_property("mass", &MMCifInfoStructDetails::GetMass, + &MMCifInfoStructDetails::SetMass) + .add_property("mass_method", &MMCifInfoStructDetails::GetMassMethod, + &MMCifInfoStructDetails::SetMassMethod) + .add_property("model_details", &MMCifInfoStructDetails::GetModelDetails, + &MMCifInfoStructDetails::SetModelDetails) + .add_property("model_type_details", + &MMCifInfoStructDetails::GetModelTypeDetails, + &MMCifInfoStructDetails::SetModelTypeDetails) + ; + + class_<MMCifInfoObsolete>("MMCifInfoObsolete", init<>()) + .def("SetDate", &MMCifInfoObsolete::SetDate) + .def("GetDate", &MMCifInfoObsolete::GetDate) + .def("SetID", &MMCifInfoObsolete::SetID) + .def("GetID", &MMCifInfoObsolete::GetID) + .def("SetPDBID", &MMCifInfoObsolete::SetPDBID) + .def("GetPDBID", &MMCifInfoObsolete::GetPDBID) + .def("SetReplacedPDBID", &MMCifInfoObsolete::SetReplacedPDBID) + .def("GetReplacedPDBID", &MMCifInfoObsolete::GetReplacedPDBID) + .add_property("date", &MMCifInfoObsolete::GetDate, + &MMCifInfoObsolete::SetDate) + .add_property("id", &MMCifInfoObsolete::GetID, + &MMCifInfoObsolete::SetID) + .add_property("pdb_id", &MMCifInfoObsolete::GetPDBID, + &MMCifInfoObsolete::SetPDBID) + .add_property("replace_pdb_id", &MMCifInfoObsolete::GetReplacedPDBID, + &MMCifInfoObsolete::SetReplacedPDBID) + ; + + class_<MMCifInfo>("MMCifInfo", init<>()) + .def("AddCitation", &MMCifInfo::AddCitation) + .def("GetCitations", make_function(&MMCifInfo::GetCitations, + return_value_policy<copy_const_reference>())) + .def("AddBioUnit", &MMCifInfo::AddBioUnit) + .def("GetBioUnits", make_function(&MMCifInfo::GetBioUnits, + return_value_policy<copy_const_reference>())) + .def("SetMethod", &MMCifInfo::SetMethod) + .def("GetMethod", &MMCifInfo::GetMethod) + .def("SetResolution", &MMCifInfo::SetResolution) + .def("GetResolution", &MMCifInfo::GetResolution) + .def("AddAuthorsToCitation", &MMCifInfo::AddAuthorsToCitation) + .def("AddOperation", &MMCifInfo::AddOperation) + .def("GetOperations", make_function(&MMCifInfo::GetOperations, + return_value_policy<copy_const_reference>())) + .def("SetStructDetails", &MMCifInfo::SetStructDetails) + .def("GetStructDetails", &MMCifInfo::GetStructDetails) + .def("SetObsoleteInfo", &MMCifInfo::SetObsoleteInfo) + .def("GetObsoleteInfo", &MMCifInfo::GetObsoleteInfo) + .add_property("citations", make_function(&MMCifInfo::GetCitations, + return_value_policy<copy_const_reference>())) + .add_property("biounits", make_function(&MMCifInfo::GetBioUnits, + return_value_policy<copy_const_reference>())) + .add_property("method", &MMCifInfo::GetMethod, &MMCifInfo::SetMethod) + .add_property("resolution", &MMCifInfo::GetResolution, + &MMCifInfo::SetResolution) + .add_property("operations", make_function(&MMCifInfo::GetOperations, + return_value_policy<copy_const_reference>())) + .add_property("struct_details", &MMCifInfo::GetStructDetails, + &MMCifInfo::SetStructDetails) + .add_property("struct_refs", make_function(&MMCifInfo::GetStructRefs, + return_value_policy<copy_const_reference>())) + .add_property("obsolete", &MMCifInfo::GetObsoleteInfo, + &MMCifInfo::SetObsoleteInfo) + ; +} diff --git a/modules/io/pymod/export_pdb_io.cc b/modules/io/pymod/export_pdb_io.cc index e431239e2e7d591d508f05d01464be380f468b49..c5abad5d434ddbdf1285c854cf4a427a8d0f34b9 100644 --- a/modules/io/pymod/export_pdb_io.cc +++ b/modules/io/pymod/export_pdb_io.cc @@ -36,13 +36,14 @@ void (PDBWriter::*write_b)(const mol::EntityView&)=&PDBWriter::Write; void export_pdb_io() { class_<IOProfile>("IOProfile", - init<String,bool,bool,bool,bool,bool,bool>((arg("dialect")="PDB", - arg("strict_hydrogens")=false, - arg("quack_mode")=false, - arg("fault_tolerant")=false, - arg("join_spread_atom_records")=false, - arg("no_hetatms")=false, - arg("calpha_only")=false))) + init<String,bool,bool,bool,bool,bool,bool,bool>((arg("dialect")="PDB", + arg("strict_hydrogens")=false, + arg("quack_mode")=false, + arg("fault_tolerant")=false, + arg("join_spread_atom_records")=false, + arg("no_hetatms")=false, + arg("calpha_only")=false, + arg("bond_feasibility_check")=true))) .def_readwrite("dialect", &IOProfile::dialect) .def_readwrite("fault_tolerant", &IOProfile::fault_tolerant) .def_readwrite("quack_mode", &IOProfile::quack_mode) @@ -50,6 +51,7 @@ void export_pdb_io() .def_readwrite("no_hetatms", &IOProfile::no_hetatms) .def_readwrite("calpha_only", &IOProfile::calpha_only) .def_readwrite("join_spread_atom_records", &IOProfile::join_spread_atom_records) + .def_readwrite("bond_feasibility_check", &IOProfile::bond_feasibility_check) .def("Copy", &IOProfile::Copy) .def(self_ns::str(self)) ; diff --git a/modules/io/pymod/wrap_io.cc b/modules/io/pymod/wrap_io.cc index af5087cd2272c823232aabba9fadd50a0bb6278c..bc10f6f6a32fc6c9e6c3031e5abd94031f367d2e 100644 --- a/modules/io/pymod/wrap_io.cc +++ b/modules/io/pymod/wrap_io.cc @@ -72,6 +72,7 @@ BOOST_PYTHON_FUNCTION_OVERLOADS(save_charmm_trj_ov, } void export_pdb_io(); +void export_mmcif_io(); #if OST_IMG_ENABLED void export_map_io(); #endif @@ -112,12 +113,14 @@ BOOST_PYTHON_MODULE(_ost_io) def("LoadCRD", &LoadCRD); def("LoadCHARMMTraj_", &LoadCHARMMTraj, (arg("ent"), arg("trj_filename"), arg("stride")=1, arg("lazy_load")=false)); - def("SaveCHARMMTraj",SaveCHARMMTraj,save_charmm_trj_ov()); - def("LoadMAE", &LoadMAE); export_pdb_io(); + export_mmcif_io(); #if OST_IMG_ENABLED export_map_io(); #endif + def("SaveCHARMMTraj", &SaveCHARMMTraj, + (arg("traj"), arg("pdb_filename"), arg("dcd_filename"), arg("stride")=1, + arg("profile")=IOProfile())); } diff --git a/modules/io/src/CMakeLists.txt b/modules/io/src/CMakeLists.txt index 08b65a7a2f2f8509834db7dfcb97a0fdd35d0646..c2a465686698258543707f91b5097e7d5f98ff11 100644 --- a/modules/io/src/CMakeLists.txt +++ b/modules/io/src/CMakeLists.txt @@ -13,6 +13,7 @@ io_utils.hh io_exception.hh convert.hh converting_streams.hh + formatted_line.hh ) diff --git a/modules/io/src/img/CMakeLists.txt b/modules/io/src/img/CMakeLists.txt index 8fa9a30ffd45564867fef83e5b17ef7bee0250b0..d17f46e8ec5e043b1a74c67ee900e5e01271ccd7 100644 --- a/modules/io/src/img/CMakeLists.txt +++ b/modules/io/src/img/CMakeLists.txt @@ -7,6 +7,7 @@ map_io_mrc_handler.cc map_io_dm3_handler.cc map_io_tiff_handler.cc map_io_dat_handler.cc +map_io_ipl_handler.cc map_io_jpk_handler.cc map_io_nanoscope_handler.cc map_io_png_handler.cc @@ -28,6 +29,7 @@ map_io_situs_handler.hh map_io_handler.hh map_io_mrc_handler.hh map_io_dat_handler.hh +map_io_ipl_handler.hh map_io_jpk_handler.hh map_io_nanoscope_handler.hh map_io_png_handler.hh diff --git a/modules/io/src/img/map_io_dx_handler.cc b/modules/io/src/img/map_io_dx_handler.cc index 70303c97a08da2e8565cc3241ad5e7d9e27d8af8..4509d327d51187961802658a214d69c8b8bdf245 100644 --- a/modules/io/src/img/map_io_dx_handler.cc +++ b/modules/io/src/img/map_io_dx_handler.cc @@ -24,6 +24,9 @@ #include <sstream> #include <ost/log.hh> +#include <ost/string_ref.hh> +#include <boost/iostreams/filter/gzip.hpp> +#include <boost/iostreams/filtering_stream.hpp> #include <boost/filesystem/fstream.hpp> #include <boost/filesystem/convenience.hpp> #include <boost/lexical_cast.hpp> @@ -43,6 +46,23 @@ namespace ost { namespace io { using boost::format; +namespace { + +bool IEquals(const StringRef& a, const StringRef& b) +{ + if (a.size()!=b.size()) { + return false; + } + for (size_t i=0; i<a.size(); ++i) { + if (toupper(a[i])!=b[i]) { + return false; + } + } + return true; +} + +} + String DX::FORMAT_STRING="defined_dx"; DX::DX (bool normalize_on_save): @@ -68,8 +88,12 @@ void MapIODxHandler::Import(img::MapHandle& mh, const bf::path& loc,const ImageF { throw IOException("could not open "+loc.string()); } - - this->Import(mh,infile,form); + boost::iostreams::filtering_stream<boost::iostreams::input> in; + if (boost::iequals(".gz", boost::filesystem::extension(loc))) { + in.push(boost::iostreams::gzip_decompressor()); + } + in.push(infile); + this->Import(mh,in,form); infile.close(); } @@ -91,6 +115,9 @@ void MapIODxHandler::Import(img::MapHandle& mh, std::istream& infile, const Imag img::MapHandle mh2; std::vector<String> tokens; while (std::getline(infile,line)) { + if (line.empty()) { + continue; + } // read gridpoints line if (boost::iequals(line.substr(0,35), "object 1 class gridpositions counts")) { boost::split(tokens, line, boost::is_any_of(" "), boost::token_compress_on); @@ -183,14 +210,14 @@ void MapIODxHandler::Import(img::MapHandle& mh, std::istream& infile, const Imag Real value=0; for(int i=0; i<num_gridpoints; i+=3) { std::getline(infile,line); - boost::split(tokens, line, boost::is_any_of(" "), boost::token_compress_on); - for (size_t j=0; j<tokens.size()-1; j++) { // three values per line - try { - value=boost::lexical_cast<Real>(boost::trim_copy(tokens[j])); - } catch(boost::bad_lexical_cast&) { - format fmer = format("Bad value line: Can't convert grid point value '%s' to Real constant.") % line; - throw IOException(fmer.str()); - } + StringRef curr_line(line.c_str(), line.size()); + std::vector<StringRef> fields=curr_line.split(' '); + for (size_t j=0; j<fields.size(); j++) { + std::pair<bool, float> result=fields[j].trim().to_float(); + if (!result.first) { + throw IOException((format("Bad value line: Can't convert grid point value '%s' to Real constant.") % line).str()); + } + value=result.second; mh2.SetReal(img::Point(((i+j)/(v_size*w_size))%u_size,((i+j)/w_size)%v_size, (i+j)%w_size), value); } } @@ -266,10 +293,10 @@ bool MapIODxHandler::MatchType(const ImageFormatBase& formatstruct) } bool MapIODxHandler::MatchSuffix(const String& loc) { - if(detail::FilenameEndsWith(loc,".dx") ) { - return true; - } - return false; + if(detail::FilenameEndsWith(loc,".dx") || detail::FilenameEndsWith(loc,".dx.gz")) { + return true; + } + return false; } }} // ns diff --git a/modules/io/src/img/map_io_ipl_handler.cc b/modules/io/src/img/map_io_ipl_handler.cc new file mode 100644 index 0000000000000000000000000000000000000000..dd1fb2981a1f8c95f407331086508253a425f450 --- /dev/null +++ b/modules/io/src/img/map_io_ipl_handler.cc @@ -0,0 +1,416 @@ +//------------------------------------------------------------------------------ +// This file is part of the OpenStructure project <www.openstructure.org> +// +// Copyright (C) 2008-2011 by the OpenStructure authors +// Copyright (C) 2003-2010 by the IPLT authors +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License as published by the Free +// Software FounIPLion; either version 3.0 of the License, or (at your option) +// any later version. +// This library is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this library; if not, write to the Free Software FounIPLion, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110String::npos301 USA +//------------------------------------------------------------------------------ +#include <cassert> +#include <ctime> +#include <iomanip> +#include <cstring> + +#include <boost/shared_array.hpp> +#include <boost/filesystem/operations.hpp> +#include <boost/filesystem/fstream.hpp> +#include <ost/stdint.hh> +#include <ost/units.hh> +#include <ost/log.hh> +#include <ost/img/image.hh> +#include <ost/img/alg/normalizer_factory.hh> +#include <ost/img/progress.hh> +#include <ost/io/io_exception.hh> +#include <ost/io/convert.hh> +#include <ost/io/converting_streams.hh> +#include <ost/img/alg/discrete_shrink.hh> + +#include "map_io_ipl_handler.hh" + +namespace ost { namespace io { + +String IPL::FORMAT_STRING = "defined_ipl"; + +IPL::IPL(bool normalize_on_save, Format bit_depth): + ImageFormatBase(FORMAT_STRING), + normalize_on_save_(normalize_on_save), + bit_depth_(OST_DEFAULT_FORMAT) +{ + this->SetBitDepth(bit_depth); +} + +Format IPL::GetBitDepth() const +{ + return bit_depth_; +} + +void IPL::SetBitDepth (Format bitdepth) +{ + if( ! (bitdepth==OST_BIT16_FORMAT || bitdepth==OST_BIT32_FORMAT || bitdepth==OST_DEFAULT_FORMAT)) + { + throw IOException("Unsupported bit depth for IPL file format."); + } + + bit_depth_ = bitdepth; +} + +bool IPL::GetNormalizeOnSave() const +{ + return normalize_on_save_; +} + +void IPL::SetNormalizeOnSave(bool normalize_on_save) +{ + normalize_on_save_ = normalize_on_save; +} + +Real IPL::GetMaximum() const +{ + switch(bit_depth_){ + case OST_BIT32_FORMAT: + return 4294967295.0; + default: + return 65535.0; + } +} + +Real IPL::GetMinimum() const +{ + return 0.0; +} + +bool MapIOIPLHandler::MatchContent(unsigned char* header) +{ + String magic_token("DITABIS micron Data File"); + if(magic_token.compare(0,magic_token.size(),reinterpret_cast<char*>(header),magic_token.size())==0) + { + return true; + } + return false; +} + +namespace detail{ + +class IPLHeader{ +public: + IPLHeader(): + date(), + header_length(2048), + size_x(), + size_y(), + bit_depth(), + resolution_x(), + resolution_y(), + magnification(1), + thumb_nail_zoom(10), + channel("PMT LOWSENS"), + params("dummy.set"), + format("2 2 2 2 Standard.fmt"), + laser(30), + gain(20000), + offset_correction(true), + offset(0), + comment() + {} + IPLHeader(const img::ConstImageHandle& im,Format bit_depth): + date(), + header_length(2048), + size_x(im.GetSize()[0]), + size_y(im.GetSize()[1]), + bit_depth(bit_depth==OST_BIT32_FORMAT ? 4: 2), + resolution_x(im.GetSpatialSampling()[0]), + resolution_y(im.GetSpatialSampling()[1]), + magnification(1), + thumb_nail_zoom(10), + channel("PMT LOWSENS"), + params("dummy.set"), + format("2 2 2 2 Standard.fmt"), + laser(30), + gain(20000), + offset_correction(true), + offset(0), + comment() + {} + String date; + int header_length; + int size_x; + int size_y; + int bit_depth; + Real resolution_x; + Real resolution_y; + int magnification; + int thumb_nail_zoom; + String channel; + String params; + String format; + int laser; + int gain; + bool offset_correction; + int offset; + String comment; +}; + +std::ostream& operator<< (std::ostream& out, const IPLHeader& h ) +{ + uint start_pos = out.tellp(); + out << "DITABIS micron Data File\r\n"; + time_t rawtime=time(NULL); + char * timestr = asctime(localtime(&rawtime)); + timestr[strlen(timestr)-1] = '\0'; + out << "CREATED = "<< timestr <<" \r\n"; + out << "HEADER = "<< h.header_length <<" \r\n"; + // x and y get swapped here (follows the behaviour of the original conversion software) + out << "YPIXEL = "<< h.size_x <<" \r\n"; + out << "XPIXEL = "<< h.size_y <<" \r\n"; + out << "BYTE PER PIXEL = "<< h.bit_depth <<" \r\n"; + // x and y get swapped here (follows the behaviour of the original conversion software) + out << "XRESOLUTION = "<< std::setprecision(0)<< h.resolution_y/Units::nm <<" (" << std::setprecision(2)<< h.resolution_y/Units::nm<<") \r\n"; + out << "YRESOLUTION = "<< std::setprecision(0)<< h.resolution_x/Units::nm <<" (" << std::setprecision(2)<< h.resolution_x/Units::nm<<") \r\n"; + out << "MAGNIFICATION = "<< h.magnification <<" \r\n"; + out << "THUMB-NAIL-ZOOM = "<< h.thumb_nail_zoom <<" \r\n"; + out << "CHANNEL = "<< h.channel <<" \r\n"; + out << "PARAMS = "<< h.params <<" \r\n"; + out << "FORMAT = "<< h.format <<" \r\n"; + out << "LASER = "<< h.laser <<" \r\n"; + out << "GAIN = "<< h.gain <<" \r\n"; + if(h.offset_correction){ + out << "OFFSET CORRECTION = YES \r\n"; + }else{ + out << "OFFSET CORRECTION = NO \r\n"; + } + out << "OFFSET = "<< h.offset <<" \r\n"; + out << "COMMENT = Created by OpenStructure \r\n"; + out << " \r\n"; + uint fillsize=h.header_length-out.tellp()+start_pos; + char empty[fillsize]; + std::fill_n(empty,fillsize,0); + out.write(empty,fillsize); + return out; +} + +std::istream& operator>> (std::istream& in, IPLHeader& h) +{ + String line; + uint start_pos = in.tellg(); + do{ + std::getline(in,line); + if(line.find("DITABIS micron Data File")!=String::npos){ + //ignore + }else if(line.find("CREATED")!=String::npos){ + h.date=line.substr(line.find("=")+2); + }else if(line.find("HEADER")!=String::npos){ + std::istringstream ( line.substr(line.find("=")+2) ) >> h.header_length; + // x and y get swapped here (follows the behaviour of the original conversion software) + }else if(line.find("XPIXEL")!=String::npos){ + std::istringstream ( line.substr(line.find("=")+2) ) >> h.size_y; + }else if(line.find("YPIXEL")!=String::npos){ + std::istringstream ( line.substr(line.find("=")+2) ) >> h.size_x; + }else if(line.find("BYTE PER PIXEL")!=String::npos){ + std::istringstream ( line.substr(line.find("=")+2) ) >> h.bit_depth; + // x and y get swapped here (follows the behaviour of the original conversion software) + }else if(line.find("XRESOLUTION")!=String::npos){ + std::istringstream ( line.substr(line.find("(")+1) ) >> h.resolution_y; + h.resolution_y*=Units::nm; + }else if(line.find("YRESOLUTION")!=String::npos){ + std::istringstream ( line.substr(line.find("(")+1) ) >> h.resolution_x; + h.resolution_x*=Units::nm; + }else if(line.find("MAGNIFICATION")!=String::npos){ + std::istringstream ( line.substr(line.find("=")+2) ) >> h.magnification; + }else if(line.find("THUMB-NAIL-ZOOM")!=String::npos){ + std::istringstream ( line.substr(line.find("=")+2) ) >> h.thumb_nail_zoom; + }else if(line.find("CHANNEL")!=String::npos){ + h.channel=line.substr(line.find("=")+2); + }else if(line.find("PARAMS")!=String::npos){ + h.params=line.substr(line.find("=")+2); + }else if(line.find("FORMAT")!=String::npos){ + h.format=line.substr(line.find("=")+2); + }else if(line.find("LASER")!=String::npos){ + std::istringstream ( line.substr(line.find("=")+2) ) >> h.laser; + }else if(line.find("GAIN")!=String::npos){ + std::istringstream ( line.substr(line.find("=")+2) ) >> h.gain; + }else if(line.find("OFFSET CORRECTION")!=String::npos){ + if(line.substr(line.find("=")+2).find("YES")!=String::npos){ + h.offset_correction=true; + }else{ + h.offset_correction=false; + } + }else if(line.find("OFFSET")!=String::npos){ + std::istringstream ( line.substr(line.find("=")+2) ) >> h.offset; + }else if(line.find("COMMENT")!=String::npos){ + h.comment=line.substr(line.find("=")+2); + }else if(line.find(" ")!=String::npos){ + //ignore + }else{ + LOG_ERROR("IPL import: unknown header line: " << line); + } + }while(in.peek()!=0); + uint fillsize=h.header_length-in.tellg()+start_pos; + char empty[h.header_length]; + std::fill_n(empty,fillsize,0); + in.read(empty,fillsize); + return in; +} + +}//ns + +bool MapIOIPLHandler::MatchType(const ImageFormatBase& type) +{ + if(type.GetFormatString()==IPL::FORMAT_STRING) { + return true; + } + return false; +} + +bool MapIOIPLHandler::MatchSuffix(const String& loc) +{ + if(detail::FilenameEndsWith(loc,".IPL") || detail::FilenameEndsWith(loc,".ipl") ) { + return true; + } + return false; +} + +void MapIOIPLHandler::Import(img::MapHandle& sh, const boost::filesystem::path& loc,const ImageFormatBase& formatstruct ) +{ + boost::filesystem::ifstream infile(loc, std::ios::binary); + if(!infile) { + throw IOException("could not open "+loc.string()); + } + this->Import(sh,infile,formatstruct); + infile.close(); +} + +template <typename DATATYPE> +void real_filler(img::image_state::RealSpatialImageState& isi, std::istream& file) +{ + BinaryIStream<OST_LITTLE_ENDIAN> file_bin(file); + img::Size size = isi.GetSize(); + char this_dummy; //create dummy variable to give to img::Progress as this + img::Progress::Instance().Register(&this_dummy,size[1],100); + for(unsigned int row=0;row<size[1];row++) { + for(unsigned int column=0;column<size[0];column++) { + DATATYPE value; + file_bin >> value; + isi.Value(img::Point(column,row))=static_cast<Real>(value); + } + img::Progress::Instance().AdvanceProgress(&this_dummy); + } + img::Progress::Instance().DeRegister(&this_dummy); +} + +template <typename DATATYPE> +void real_dumper( const img::ConstImageHandle& sh, std::ostream& file, const IPL& formatIPL, int shrinksize) +{ + img::image_state::RealSpatialImageState *isi=dynamic_cast<img::image_state::RealSpatialImageState*>(sh.ImageStatePtr().get()); + if(! isi){ + throw(IOException("IPL export: dynamic cast failed in real dumper.")); + } + BinaryOStream<OST_LITTLE_ENDIAN> file_bin(file); + img::alg::Normalizer norm = img::alg::CreateNoOpNormalizer(); + if (formatIPL.GetNormalizeOnSave() == true) { + norm = img::alg::CreateLinearRangeNormalizer(sh,formatIPL.GetMinimum(),formatIPL.GetMaximum()); + } + img::Size size = isi->GetSize(); + img::ImageHandle thumbnail=sh.Apply(img::alg::DiscreteShrink(img::Size(shrinksize,shrinksize,1))); + img::image_state::RealSpatialImageState *thumb_isi=dynamic_cast<img::image_state::RealSpatialImageState*>(thumbnail.ImageStatePtr().get()); + if(! thumb_isi){ + throw(IOException("IPL export: dynamic cast failed in real dumper.")); + } + + char this_dummy; //create dummy variable to give to img::Progress as this + img::Progress::Instance().Register(&this_dummy,size[1]+1,100); + for(unsigned int row=0;row<size[1];row++) { + for(unsigned int column=0;column<size[0];column++) + { + file_bin << static_cast<DATATYPE>(norm.Convert(isi->Value(ost::img::Point(column,row,0)))); + } + img::Progress::Instance().AdvanceProgress(&this_dummy); + } + img::Progress::Instance().AdvanceProgress(&this_dummy); + img::Size thumb_size = thumb_isi->GetSize(); + for(unsigned int row=0;row<thumb_size[1];row++) { + for(unsigned int column=0;column<thumb_size[0];column++) + { + file_bin << static_cast<DATATYPE>(norm.Convert(thumb_isi->Value(ost::img::Point(column,row,0)))); + } + img::Progress::Instance().AdvanceProgress(&this_dummy); + } + img::Progress::Instance().DeRegister(&this_dummy); +} + + +void MapIOIPLHandler::Import(img::MapHandle& sh, std::istream& file, const ImageFormatBase& formatstruct) +{ + + IPL form; + IPL& formatIPL = form; + if (formatstruct.GetFormatString()==IPL::FORMAT_STRING) { + formatIPL = formatstruct.As<IPL>(); + } else { + assert (formatstruct.GetFormatString()==UndefinedImageFormat::FORMAT_STRING); + } + + detail::IPLHeader header; + file >> header; + + sh.Reset(img::Extent(img::Point(0,0),img::Size(header.size_x,header.size_y)), img::REAL, img::SPATIAL); + sh.SetSpatialSampling(geom::Vec3(header.resolution_x,header.resolution_y,1.0)); + img::image_state::RealSpatialImageState * isi; + if(! (isi=dynamic_cast<img::image_state::RealSpatialImageState*>(sh.ImageStatePtr().get()))) { + throw IOException("internal error in IPL io: expected RealSpatialImageState"); + } + + if(header.bit_depth==4){ + real_filler<uint32_t>(*isi,file); + }else{ + real_filler<uint16_t>(*isi,file); + } +} + +void MapIOIPLHandler::Export(const img::MapHandle& mh2, + const boost::filesystem::path& loc,const ImageFormatBase& formatstruct) const +{ + boost::filesystem::ofstream outfile(loc, std::ios::binary); + if(!outfile) + { + throw IOException("could not open "+loc.string()); + } + this->Export(mh2,outfile,formatstruct); + outfile.close(); +} + +void MapIOIPLHandler::Export(const img::MapHandle& sh, std::ostream& file,const ImageFormatBase& formatstruct) const +{ + + IPL form; + IPL& formatIPL = form; + if (formatstruct.GetFormatString()==IPL::FORMAT_STRING) { + formatIPL = formatstruct.As<IPL>(); + } else { + assert (formatstruct.GetFormatString()==UndefinedImageFormat::FORMAT_STRING); + } + if (sh.GetSize()[2]!=1 || sh.GetDomain()!=img::SPATIAL || sh.GetType()!=img::REAL) { + throw IOException("IPL IO: IPL format only supports spatial 2D images."); + } + detail::IPLHeader header(sh,formatIPL.GetBitDepth()); + file << header; + if(header.bit_depth==4){ + real_dumper<uint32_t>(sh,file,formatIPL,header.thumb_nail_zoom); + }else{ + real_dumper<uint16_t>(sh,file,formatIPL,header.thumb_nail_zoom); + } +} + +}} // namespaces + + diff --git a/modules/io/src/img/map_io_ipl_handler.hh b/modules/io/src/img/map_io_ipl_handler.hh new file mode 100644 index 0000000000000000000000000000000000000000..3e76ac9895c0689defe002d0399359e03f3e09aa --- /dev/null +++ b/modules/io/src/img/map_io_ipl_handler.hh @@ -0,0 +1,78 @@ +//------------------------------------------------------------------------------ +// This file is part of the OpenStructure project <www.openstructure.org> +// +// Copyright (C) 2008-2011 by the OpenStructure authors +// Copyright (C) 2003-2010 by the IPLT authors +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License as published by the Free +// Software Foundation; either version 3.0 of the License, or (at your option) +// any later version. +// This library is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this library; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +//------------------------------------------------------------------------------ +#ifndef OST_IO_MAP_IO_IPL_HANDLER_HH +#define OST_IO_MAP_IO_IPL_HANDLER_HH + + +/* +Andreas Schenk +*/ + +#include "map_io_handler.hh" + +namespace ost { namespace io { + +class DLLEXPORT_OST_IO IPL: public ImageFormatBase +{ + + public: + + IPL(bool normalize_on_save = true, Format bit_depth = OST_DEFAULT_FORMAT); + + Format GetBitDepth() const; + void SetBitDepth ( Format bitdepth); + + + bool GetNormalizeOnSave() const; + void SetNormalizeOnSave(bool normalize_on_save=true); + Real GetMaximum() const; + Real GetMinimum() const; + static String FORMAT_STRING; + + private: + bool normalize_on_save_; + Format bit_depth_; + +}; + +class DLLEXPORT_OST_IO MapIOIPLHandler: public MapIOHandler +{ + public: + /// \brief Map IO handler to read/write Ipl map files + /// + /// This map IO handler reads and writes Ipl formatted map files. + virtual void Import(img::MapHandle& sh, const boost::filesystem::path& loc,const ImageFormatBase& formatstruct ); + virtual void Import(img::MapHandle& sh, std::istream& loc, const ImageFormatBase& formatstruct); + virtual void Export(const img::MapHandle& sh, const boost::filesystem::path& loc, const ImageFormatBase& formatstruct) const; + virtual void Export(const img::MapHandle& sh, std::ostream& loc,const ImageFormatBase& formatstruct) const; + static bool MatchContent(unsigned char* header); + static bool MatchType(const ImageFormatBase& type); + static bool MatchSuffix(const String& loc); + static bool ProvidesImport() { return true; } + static bool ProvidesExport() { return true; } + static String GetFormatName() { return String("IPL"); } + static String GetFormatDescription() {return String("Ditabis Micron Image Plate Scanner Format");} +}; + +typedef MapIOHandlerFactory<MapIOIPLHandler> MapIOIPLHandlerFactory; + +}} // ns + +#endif diff --git a/modules/io/src/img/map_io_mrc_handler.cc b/modules/io/src/img/map_io_mrc_handler.cc index abdf2807b7a35f05ee25d53f09e099ed408da04e..bdde9d1e1701bb7180874db98d9bf9f7f8dc47a1 100644 --- a/modules/io/src/img/map_io_mrc_handler.cc +++ b/modules/io/src/img/map_io_mrc_handler.cc @@ -628,16 +628,17 @@ void complex_filler(img::image_state::ComplexHalfFrequencyImageState& isi, p[mapc]=-sc; // complex conjugate fhandle >> real >> imag; - isi.Value(p)=Complex(Real(real),-Real(imag)); + isi.Value(p)=Complex(Real(real),Real(imag)); LOG_DEBUG(" " << p << " " << isi.Value(p)); } + fhandle >> real >> imag; if(sr==header.nr) { // why set point (py,header.ny/2,pz)? // isi.Value(Point(py,header.ny/2,pz))=scale*Complex(Real(real),Real(imag)); // LOG_DEBUG("+" << Point(py,header.ny/2,pz) << " <- " << Point(sx,cy,sz) << " " << " " << isi.Value(Point(py,header.ny/2,pz))); p[mapc]=p[header.mapr]; p[mapr]=header.nr/2; - isi.Value(p)=Complex(Real(real),Real(imag)); + isi.Value(p)=Complex(Real(real),-Real(imag)); LOG_DEBUG("+" << p << " " << isi.Value(p)); } Progress::Instance().AdvanceProgress(&this_dummy); @@ -649,11 +650,12 @@ void complex_filler(img::image_state::ComplexHalfFrequencyImageState& isi, for(;sc<header.nc-1;++sc) { p[mapc]=sc; fhandle >> real >> imag; - isi.Value(p)=Complex(Real(real),Real(imag)); + isi.Value(p)=Complex(Real(real),-Real(imag)); LOG_DEBUG(" " << p << " " << isi.Value(p)); } + fhandle >> real >> imag; p[mapc]=sc; - isi.Value(p)=Complex(Real(real),-Real(imag)); + isi.Value(p)=Complex(Real(real),Real(imag)); LOG_DEBUG(" " << p << " " << isi.Value(p)); Progress::Instance().AdvanceProgress(&this_dummy); } @@ -740,7 +742,7 @@ void complex_dumper(BinaryOStream<CONVERSIONTYPE>& f, pnt[mapr]=header.nr/2-sr; for(int sc=0;sc<header.nc-1;++sc) { pnt[mapc]=-sc; - Complex val = conj(norm.Convert(isc->Value(pnt))); + Complex val = norm.Convert(isc->Value(pnt)); f << static_cast<B>(val.real()) << static_cast<B>(val.imag()); LOG_DEBUG(" " << pnt << " " << val); } @@ -754,12 +756,12 @@ void complex_dumper(BinaryOStream<CONVERSIONTYPE>& f, for(;sc<header.nc-1;++sc) { pnt[mapc]=sc; Complex val =norm.Convert(isc->Value(pnt)); - f << static_cast<B>(val.real()) << static_cast<B>(val.imag()); + f << static_cast<B>(val.real()) << static_cast<B>(-val.imag()); LOG_DEBUG(" " << pnt << " " << val); } pnt[mapc]=sc; Complex val = norm.Convert(conj(isc->Value(pnt))); - f << static_cast<B>(val.real()) << static_cast<B>(val.imag()); + f << static_cast<B>(val.real()) << static_cast<B>(-val.imag()); LOG_DEBUG(" " << pnt << " " << val); Progress::Instance().AdvanceProgress(&this_dummy); } @@ -780,7 +782,7 @@ void import_helper(img::MapHandle& image, std::istream& in,const MRC& formatmrc) } if(header.mode==3 || header.mode==4) { // always assume half-complex mode - image.Reset(img::Size((header.nx-1)*2,header.ny,header.nz),img::COMPLEX,img::HALF_FREQUENCY); + image.Reset(img::Size(header.nx,header.ny,header.nz),img::COMPLEX,img::HALF_FREQUENCY); if(img::image_state::ComplexHalfFrequencyImageState *cs=dynamic_cast<img::image_state::ComplexHalfFrequencyImageState*>(image.ImageStatePtr().get())) { if (header.mode==3) { detail::complex_filler<ushort,CONVERSIONTYPE>(*cs,f,header); diff --git a/modules/io/src/img/map_io_spi_handler.cc b/modules/io/src/img/map_io_spi_handler.cc index d22897f4ee3976555418d3fdd8c0f49f49a14aa7..6f5e1798b4674ed037884719036eeeda30323f6e 100644 --- a/modules/io/src/img/map_io_spi_handler.cc +++ b/modules/io/src/img/map_io_spi_handler.cc @@ -198,9 +198,6 @@ void prep_header(spider_header& header, const img::Size& size, const geom::Vec3& header.fNcol = ncol; header.fLenbyt = ncol*4.0; // record length in bytesS header.fLabrec = ceil(1024.0 / header.fLenbyt); // nr label records in file header - if (fmod(1024,header.fLenbyt) != 0.0) { - header.fLabrec += 1.0; - } header.fLabbyt = header.fLabrec * header.fLenbyt; header.fIangle = 0.0; // flag indicating that tilt angles have been filled header.fScale = spatial_sampling; // scale @@ -389,6 +386,10 @@ void real_filler(std::istream& in, const spider_header& header, img::ImageHandle template <typename B > void real_dumper(std::ostream& f, const spider_header& header, const img::ImageHandle& mh,const img::alg::Normalizer& norm, bool swap_flag) { + int padding = header.fLabbyt-f.tellp(); + char* buffer=new char[padding]; + f.write(buffer,padding); + delete[] buffer; int slice_size=static_cast<int>(header.fNcol) * static_cast<int>(header.fNrow); boost::scoped_array<B> rawp(new B[slice_size]); diff --git a/modules/io/src/img/map_io_tiff_handler.cc b/modules/io/src/img/map_io_tiff_handler.cc index 2ca26e838f363f9de88e4b435a895003aafb8a93..0f418bc896c6f0563a5a3a0d38d1e5aecfe6495e 100644 --- a/modules/io/src/img/map_io_tiff_handler.cc +++ b/modules/io/src/img/map_io_tiff_handler.cc @@ -299,19 +299,19 @@ void MapIOTiffHandler::do_export(const img::MapHandle& image,TIFF* tfile,TIF& fo img::image_state::ComplexSpatialImageState *isc = NULL; img::image_state::WordSpatialImageState *isw = NULL; - boost::function<void (TIFF *,img::image_state::RealSpatialImageState*,uint32_t,uint32_t,uint32_t,uint32_t,const img::NormalizerPtr& )> fsr; - boost::function<void (TIFF *,img::image_state::ComplexSpatialImageState*,uint32_t,uint32_t,uint32_t,uint32_t,const img::NormalizerPtr&)> fsc; - boost::function<void (TIFF *,img::image_state::WordSpatialImageState*,uint32_t,uint32_t,uint32_t,uint32_t,const img::NormalizerPtr&)> fsw; + boost::function<void (TIFF *,img::image_state::RealSpatialImageState*,UINTNN_T,UINTNN_T,UINTNN_T,UINTNN_T,const img::NormalizerPtr& )> fsr; + boost::function<void (TIFF *,img::image_state::ComplexSpatialImageState*,UINTNN_T,UINTNN_T,UINTNN_T,UINTNN_T,const img::NormalizerPtr&)> fsc; + boost::function<void (TIFF *,img::image_state::WordSpatialImageState*,UINTNN_T,UINTNN_T,UINTNN_T,UINTNN_T,const img::NormalizerPtr&)> fsw; - uint32_t width=image.GetSize().GetWidth(); - uint32_t height=image.GetSize().GetHeight(); + UINTNN_T width=image.GetSize().GetWidth(); + UINTNN_T height=image.GetSize().GetHeight(); uint16 spp=1; uint16 fmt =0; uint16 bpp =0 ; img::Point ori=image.GetSpatialOrigin(); geom::Vec3 sampling=image.GetPixelSampling(); float xreso=sampling[0]/Units::cm,yreso=sampling[1]/Units::cm; - float xpos=xreso*ori[0],ypos=yreso*ori[1]; + float xpos=std::max<Real>(0.0,xreso*ori[0]),ypos=std::max<Real>(0.0,yreso*ori[1]); //tiff file format only allows positivie origins, negative origins are lost here TIFFSetField(tfile,TIFFTAG_IMAGEWIDTH,width); TIFFSetField(tfile,TIFFTAG_IMAGELENGTH,height); TIFFSetField(tfile,TIFFTAG_SAMPLESPERPIXEL,spp); @@ -342,7 +342,7 @@ void MapIOTiffHandler::do_export(const img::MapHandle& image,TIFF* tfile,TIF& fo case OST_BIT32_FORMAT: fmt=SAMPLEFORMAT_INT; bpp=32; - fsr=detail::do_tiff_write<Real,int32_t,img::image_state::RealSpatialImageState>; + fsr=detail::do_tiff_write<Real,INTNN_T,img::image_state::RealSpatialImageState>; break; case OST_FLOAT_FORMAT: fmt=SAMPLEFORMAT_IEEEFP; @@ -375,7 +375,7 @@ void MapIOTiffHandler::do_export(const img::MapHandle& image,TIFF* tfile,TIF& fo case OST_BIT32_FORMAT: fmt=SAMPLEFORMAT_UINT; bpp=32; - fsr=detail::do_tiff_write<Real,uint32_t,img::image_state::RealSpatialImageState>; + fsr=detail::do_tiff_write<Real,UINTNN_T,img::image_state::RealSpatialImageState>; break; case OST_FLOAT_FORMAT: fmt=SAMPLEFORMAT_IEEEFP; @@ -410,7 +410,7 @@ void MapIOTiffHandler::do_export(const img::MapHandle& image,TIFF* tfile,TIF& fo case OST_BIT32_FORMAT: fmt=SAMPLEFORMAT_COMPLEXINT; bpp=64; - fsc=detail::do_tiff_write<Complex,std::complex<int32_t>,img::image_state::ComplexSpatialImageState>; + fsc=detail::do_tiff_write<Complex,std::complex<INTNN_T>,img::image_state::ComplexSpatialImageState>; break; case OST_FLOAT_FORMAT: fmt=SAMPLEFORMAT_COMPLEXIEEEFP; @@ -436,7 +436,7 @@ void MapIOTiffHandler::do_export(const img::MapHandle& image,TIFF* tfile,TIF& fo } TIFFSetField(tfile,TIFFTAG_BITSPERSAMPLE,bpp); - uint32_t rowsperstrip=std::max<int>(1,8192/(width*bpp/8)); //ca. 8 kb per strip (adobe tiff specs recomendation) + UINTNN_T rowsperstrip=std::max<int>(1,8192/(width*bpp/8)); //ca. 8 kb per strip (adobe tiff specs recomendation) TIFFSetField(tfile,TIFFTAG_ROWSPERSTRIP,rowsperstrip); TIFFSetField(tfile,TIFFTAG_SAMPLEFORMAT,fmt); unsigned int stripcount=static_cast<int>(ceil( height/static_cast<Real>(rowsperstrip))); @@ -549,9 +549,9 @@ TIFF* MapIOTiffHandler::open_subimage_stream(std::istream& location,const TIF& f void MapIOTiffHandler::load_image_data(TIFF* tfile, img::ImageHandle& image, const TIF& formattif) { - uint32_t width,height,rps; + UINTNN_T width,height,rps; uint16 bpp,spp,plc,ori,reso=RESUNIT_NONE,fmt=SAMPLEFORMAT_UINT; - uint32_t* sbc; + UINTNN_T* sbc; float xpos=0.0,ypos=0.0; float xreso=1.0,yreso=1.0; @@ -652,7 +652,7 @@ void MapIOTiffHandler::load_image_data(TIFF* tfile, img::ImageHandle& image, co detail::do_tiff_read<uint16,short,img::image_state::WordSpatialImageState>(buf,rowcount,width,is,current_row,spp); } else if(bpp==32) { uint rowcount = cread/(width*4*spp); - detail::do_tiff_read<uint32_t,short,img::image_state::WordSpatialImageState>(buf,rowcount,width,is,current_row,spp); + detail::do_tiff_read<UINTNN_T,short,img::image_state::WordSpatialImageState>(buf,rowcount,width,is,current_row,spp); } img::Progress::Instance().AdvanceProgress(this); } @@ -726,9 +726,9 @@ void MapIOTiffHandler::load_image_data(TIFF* tfile, img::ImageHandle& image, co } else if(bpp==32) { uint rowcount = cread/(width*4*spp); if(fmt==SAMPLEFORMAT_INT){ - detail::do_tiff_read<int32_t,Real,img::image_state::RealSpatialImageState>(buf,rowcount,width,isr,current_row,spp); + detail::do_tiff_read<INTNN_T,Real,img::image_state::RealSpatialImageState>(buf,rowcount,width,isr,current_row,spp); }else if(fmt==SAMPLEFORMAT_UINT){ - detail::do_tiff_read<uint32_t,Real,img::image_state::RealSpatialImageState>(buf,rowcount,width,isr,current_row,spp); + detail::do_tiff_read<UINTNN_T,Real,img::image_state::RealSpatialImageState>(buf,rowcount,width,isr,current_row,spp); }else if(fmt==SAMPLEFORMAT_IEEEFP){ detail::do_tiff_read<float,Real,img::image_state::RealSpatialImageState>(buf,rowcount,width,isr,current_row,spp); }else if(fmt==SAMPLEFORMAT_COMPLEXINT){ @@ -743,7 +743,7 @@ void MapIOTiffHandler::load_image_data(TIFF* tfile, img::ImageHandle& image, co if(fmt==SAMPLEFORMAT_IEEEFP){ detail::do_tiff_read<Real,Real,img::image_state::RealSpatialImageState>(buf,rowcount,width,isr,current_row,spp); }else if(fmt==SAMPLEFORMAT_COMPLEXINT){ - detail::do_tiff_read<detail::complexint32_t,Complex,img::image_state::ComplexSpatialImageState>(buf,rowcount,width,isc,current_row,spp); + detail::do_tiff_read<detail::COMPLEXINTNN_T,Complex,img::image_state::ComplexSpatialImageState>(buf,rowcount,width,isc,current_row,spp); }else if(fmt==SAMPLEFORMAT_COMPLEXIEEEFP){ detail::do_tiff_read<std::complex<float>,Complex,img::image_state::ComplexSpatialImageState>(buf,rowcount,width,isc,current_row,spp); }else{ diff --git a/modules/io/src/img/tiff_util.cc b/modules/io/src/img/tiff_util.cc index fd1cf3f25d5a5c3af71a5cd9467cca35041b6832..105ebf73becf4ea763190c52d1fdec59402eca7f 100644 --- a/modules/io/src/img/tiff_util.cc +++ b/modules/io/src/img/tiff_util.cc @@ -41,7 +41,7 @@ void tiff_warning_handler(const char *mod, const char* fmt, va_list ap) LOG_INFO(mod << ": " << message); } -int32_t CustomTIFFReadProcIStream(void* thandle, void* tdata, int32_t tsize) +INTNN_T CustomTIFFReadProcIStream(void* thandle, void* tdata, INTNN_T tsize) { std::istream* file= reinterpret_cast<std::istream*>(thandle); char* data= reinterpret_cast<char*>(tdata); @@ -49,29 +49,29 @@ int32_t CustomTIFFReadProcIStream(void* thandle, void* tdata, int32_t tsize) return file->gcount(); } -int32_t CustomTIFFReadProcOStream(void* thandle, void* tdata, int32_t tsize) +INTNN_T CustomTIFFReadProcOStream(void* thandle, void* tdata, INTNN_T tsize) { assert(false); return -1; } -int32_t CustomTIFFWriteProcIStream(void* thandle, void* tdata, int32_t tsize) +INTNN_T CustomTIFFWriteProcIStream(void* thandle, void* tdata, INTNN_T tsize) { assert(false); return -1; } -int32_t CustomTIFFWriteProcOStream(void* thandle, void* tdata, int32_t tsize) +INTNN_T CustomTIFFWriteProcOStream(void* thandle, void* tdata, INTNN_T tsize) { std::ostream* file= reinterpret_cast<std::ostream*>(thandle); char* data= reinterpret_cast<char*>(tdata); - int32_t before = file->tellp(); + INTNN_T before = file->tellp(); file->write(data,tsize); - int32_t after = file->tellp(); + INTNN_T after = file->tellp(); return after-before; } -uint32_t CustomTIFFSeekProcIStream(void* thandle, uint32_t toff, int dir) +UINTNN_T CustomTIFFSeekProcIStream(void* thandle, UINTNN_T toff, int dir) { std::istream* stream= reinterpret_cast<std::istream*>(thandle); @@ -89,7 +89,7 @@ uint32_t CustomTIFFSeekProcIStream(void* thandle, uint32_t toff, int dir) return stream->rdstate(); } -uint32_t CustomTIFFSeekProcOStream(void* thandle, uint32_t toff, int dir) +UINTNN_T CustomTIFFSeekProcOStream(void* thandle, UINTNN_T toff, int dir) { std::ostream* stream= reinterpret_cast<std::ostream*>(thandle); @@ -111,33 +111,33 @@ int CustomTIFFCloseProc(void* thandle) return 0; } -uint32_t CustomTIFFSizeProcIStream(void* thandle) +UINTNN_T CustomTIFFSizeProcIStream(void* thandle) { std::istream* stream= reinterpret_cast<std::istream*>(thandle); - uint32_t curr_pos = stream->tellg(); + UINTNN_T curr_pos = stream->tellg(); stream->seekg(0,std::ios::end); - uint32_t size = stream->tellg(); + UINTNN_T size = stream->tellg(); stream->seekg(curr_pos,std::ios::beg); return size; } -uint32_t CustomTIFFSizeProcOStream(void* thandle) +UINTNN_T CustomTIFFSizeProcOStream(void* thandle) { std::ostream* stream= reinterpret_cast<std::ostream*>(thandle); - uint32_t curr_pos = stream->tellp(); + UINTNN_T curr_pos = stream->tellp(); stream->seekp(0,std::ios::end); - uint32_t size = stream->tellp(); + UINTNN_T size = stream->tellp(); stream->seekp(curr_pos,std::ios::beg); return size; } -int CustomTIFFMapFileProc(void* thandle, void** tdata, uint32* toff) +int CustomTIFFMapFileProc(void* thandle, void** tdata, UINTNN* toff) { assert(false); return(0); } -void CustomTIFFUnmapFileProc(void* thandle, void* tdata, uint32 toff) +void CustomTIFFUnmapFileProc(void* thandle, void* tdata, UINTNN toff) { assert(false); } diff --git a/modules/io/src/img/tiff_util.hh b/modules/io/src/img/tiff_util.hh index 66393291b1d80f64feedb4082239d0b492f01160..b2aca3386a39f3587ba4fb31eb892147932940b7 100644 --- a/modules/io/src/img/tiff_util.hh +++ b/modules/io/src/img/tiff_util.hh @@ -27,6 +27,17 @@ #include <ost/img/alg/normalizer_factory.hh> #include <ost/io/img/image_format.hh> +#if defined(TIFFLIB_VERSION) && TIFFLIB_VERSION >= 20111221 +# define INTNN_T int64_t +# define UINTNN uint64 +# define UINTNN_T uint64_t +# define COMPLEXINTNN_T complexint64_t +#else +# define INTNN_T int32_t +# define UINTNN uint32 +# define UINTNN_T uint32_t +# define COMPLEXINTNN_T complexint32_t +#endif namespace ost { namespace io { namespace detail { /// \internal @@ -49,7 +60,7 @@ struct tiff_warning_handler_wrapper { }; /// \internal -class complexint32_t:public std::complex<int32_t>{ +class COMPLEXINTNN_T:public std::complex<INTNN_T>{ public: operator std::complex<Real>() @@ -79,33 +90,33 @@ public: }; /// \internal -int32_t CustomTIFFReadProcIStream(void* thandle, void* tdata, int32_t tsize); +INTNN_T CustomTIFFReadProcIStream(void* thandle, void* tdata, INTNN_T tsize); /// \internal -int32_t CustomTIFFReadProcIStream(void* thandle, void* tdata, int32_t tsize); +INTNN_T CustomTIFFReadProcIStream(void* thandle, void* tdata, INTNN_T tsize); /// \internal -int32_t CustomTIFFReadProcOStream(void* thandle, void* tdata, int32_t tsize); +INTNN_T CustomTIFFReadProcOStream(void* thandle, void* tdata, INTNN_T tsize); /// \internal -int32_t CustomTIFFWriteProcIStream(void* thandle, void* tdata, int32_t tsize); +INTNN_T CustomTIFFWriteProcIStream(void* thandle, void* tdata, INTNN_T tsize); /// \internal -int32_t CustomTIFFWriteProcOStream(void* thandle, void* tdata, int32_t tsize); +INTNN_T CustomTIFFWriteProcOStream(void* thandle, void* tdata, INTNN_T tsize); /// \internal -uint32_t CustomTIFFSeekProcIStream(void* thandle, uint32_t toff, int dir); +UINTNN_T CustomTIFFSeekProcIStream(void* thandle, UINTNN_T toff, int dir); /// \internal -uint32_t CustomTIFFSeekProcOStream(void* thandle, uint32_t toff, int dir); +UINTNN_T CustomTIFFSeekProcOStream(void* thandle, UINTNN_T toff, int dir); /// \internal int CustomTIFFCloseProc(void* thandle); /// \internal -uint32_t CustomTIFFSizeProcIStream(void* thandle); +UINTNN_T CustomTIFFSizeProcIStream(void* thandle); /// \internal -uint32_t CustomTIFFSizeProcOStream(void* thandle); +UINTNN_T CustomTIFFSizeProcOStream(void* thandle); /// \internal -int CustomTIFFMapFileProc(void* thandle, void** tdata, uint32* toff); +int CustomTIFFMapFileProc(void* thandle, void** tdata, UINTNN* toff); /// \internal -void CustomTIFFUnmapFileProc(void* thandle, void* tdata, uint32 toff); +void CustomTIFFUnmapFileProc(void* thandle, void* tdata, UINTNN toff); /// \internal template<typename IN_TYPE,typename OUT_TYPE, class IST> -void do_tiff_read(tdata_t buf,uint16 rps, uint32_t width, IST* is,int& current_row, int spp) +void do_tiff_read(tdata_t buf,uint16 rps, UINTNN_T width, IST* is,int& current_row, int spp) { IN_TYPE* dp = static_cast<IN_TYPE*>(buf); for(uint r=0;r<rps;r++) { @@ -118,7 +129,7 @@ void do_tiff_read(tdata_t buf,uint16 rps, uint32_t width, IST* is,int& current_r /// \internal template<typename IN_TYPE,typename OUT_TYPE, class IST> -void do_tiff_write(TIFF *tif, IST* is,uint32_t rowsperstrip,uint32_t width,uint32_t height, uint32_t strip,const img::NormalizerPtr& nptr) +void do_tiff_write(TIFF *tif, IST* is,UINTNN_T rowsperstrip,UINTNN_T width,UINTNN_T height, UINTNN_T strip,const img::NormalizerPtr& nptr) { uint datalength=rowsperstrip*width; if((strip+1)*rowsperstrip>height){ diff --git a/modules/io/src/io_manager.cc b/modules/io/src/io_manager.cc index 12e714fd63a0170d32c676bf60bde007571ff6f6..6edc7fe430dd928159152bed7ebea0bde53aeb44 100644 --- a/modules/io/src/io_manager.cc +++ b/modules/io/src/io_manager.cc @@ -21,6 +21,7 @@ #include <ost/io/mol/entity_io_crd_handler.hh> #include <ost/io/mol/entity_io_sdf_handler.hh> #include <ost/io/mol/entity_io_mae_handler.hh> +#include <ost/io/mol/entity_io_mmcif_handler.hh> #include <ost/io/seq/fasta_io_handler.hh> #include <ost/io/seq/pir_io_handler.hh> #include <ost/io/seq/promod_io_handler.hh> @@ -38,11 +39,13 @@ # include <ost/io/img/map_io_jpk_handler.hh> # include <ost/io/img/map_io_nanoscope_handler.hh> # include <ost/io/img/map_io_df3_handler.hh> +# include <ost/io/img/map_io_ipl_handler.hh> #endif namespace ost { namespace io { IOManager::IOManager() { + RegisterFactory(EntityIOHandlerFactoryBaseP(new EntityIOMMCIFHandlerFactory)); RegisterFactory(EntityIOHandlerFactoryBaseP(new EntityIOPDBHandlerFactory)); RegisterFactory(EntityIOHandlerFactoryBaseP(new EntityIOCRDHandlerFactory)); RegisterFactory(EntityIOHandlerFactoryBaseP(new EntityIOSDFHandlerFactory)); @@ -63,7 +66,8 @@ IOManager::IOManager() RegisterFactory(MapIOHandlerFactoryBasePtr(new MapIOJpkHandlerFactory)); RegisterFactory(MapIOHandlerFactoryBasePtr(new MapIODatHandlerFactory)); RegisterFactory(MapIOHandlerFactoryBasePtr(new MapIONanoscopeHandlerFactory)); - RegisterFactory(MapIOHandlerFactoryBasePtr(new MapIODF3HandlerFactory)); + RegisterFactory(MapIOHandlerFactoryBasePtr(new MapIODF3HandlerFactory)); + RegisterFactory(MapIOHandlerFactoryBasePtr(new MapIOIPLHandlerFactory)); #endif } diff --git a/modules/io/src/mol/CMakeLists.txt b/modules/io/src/mol/CMakeLists.txt index 1201eb58fcff984f0bf0b5887a29f011ed6fd7ac..cb80b67a9600ed5ec3f98e19a5669dcb4b1f1a1b 100644 --- a/modules/io/src/mol/CMakeLists.txt +++ b/modules/io/src/mol/CMakeLists.txt @@ -5,6 +5,7 @@ pdb_reader.cc entity_io_pdb_handler.cc pdb_writer.cc entity_io_sdf_handler.cc +entity_io_mmcif_handler.cc sdf_reader.cc sdf_writer.cc save_entity.cc @@ -15,16 +16,21 @@ chemdict_parser.cc io_profile.cc dcd_io.cc star_parser.cc +mmcif_reader.cc +mmcif_info.cc PARENT_SCOPE ) set(OST_IO_MOL_HEADERS chemdict_parser.hh star_parser.hh +mmcif_reader.hh +mmcif_info.hh io_profile.hh dcd_io.hh entity_io_crd_handler.hh entity_io_mae_handler.hh +entity_io_mmcif_handler.hh entity_io_handler.hh pdb_reader.hh entity_io_pdb_handler.hh diff --git a/modules/io/src/mol/chemdict_parser.cc b/modules/io/src/mol/chemdict_parser.cc index 5934b8341cf3220addbca4eaccd313984c7ecb39..a44dc733803bf7b805d52b839c8d756b3941f929 100644 --- a/modules/io/src/mol/chemdict_parser.cc +++ b/modules/io/src/mol/chemdict_parser.cc @@ -93,7 +93,18 @@ void ChemdictParser::OnDataItem(const StarDataItem& item) << compound_->GetID() << std::endl; } } - + } else if (item.GetName()==StringRef("pdbx_type", 9)) { + String type=item.GetValue().str(); + for (String::iterator i=type.begin(), e=type.end(); i!=e; ++i) { + *i=toupper(*i); + } + std::map<String, mol::ChemType>::iterator i=xtm_.find(type); + if (i!=xtm_.end()) { + compound_->SetChemType(i->second); + } else { + std::cout << "unknown pdbx_type '" << type << "' for compound " + << compound_->GetID() << std::endl; + } } else if (item.GetName()==StringRef("formula", 7)) { compound_->SetFormula(item.GetValue().str()); if (compound_->GetFormula()=="H2 O") { @@ -136,6 +147,7 @@ void ChemdictParser::OnEndData() } std::map<String, mol::ChemClass> ChemdictParser::tm_=std::map<String, mol::ChemClass>(); +std::map<String, mol::ChemType> ChemdictParser::xtm_=std::map<String, mol::ChemType>(); void ChemdictParser::InitTypeMap() { @@ -168,4 +180,20 @@ void ChemdictParser::InitTypeMap() tm_["WATER"]=mol::ChemClass(mol::ChemClass::WATER); } +void ChemdictParser::InitPDBXTypeMap() +{ + if (!xtm_.empty()) + return; + xtm_["HETAI"]=mol::ChemType(mol::ChemType::IONS); + xtm_["HETAIN"]=mol::ChemType(mol::ChemType::NONCANONICALMOLS); + xtm_["ATOMS"]=mol::ChemType(mol::ChemType::SACCHARIDES); + xtm_["ATOMN"]=mol::ChemType(mol::ChemType::NUCLEOTIDES); + xtm_["ATOMP"]=mol::ChemType(mol::ChemType::AMINOACIDS); + xtm_["HETAC"]=mol::ChemType(mol::ChemType::COENZYMES); + xtm_["HETIC"]=mol::ChemType(mol::ChemType::WATERCOORDIONS); + xtm_["HETAD"]=mol::ChemType(mol::ChemType::DRUGS); + xtm_["HETAS"]=mol::ChemType(mol::ChemType::WATERS); + xtm_["?"]=mol::ChemType(mol::ChemType::UNKNOWN); +} + }} diff --git a/modules/io/src/mol/chemdict_parser.hh b/modules/io/src/mol/chemdict_parser.hh index 4df2f4e2ddc0e7425c7c10704d88d39acb1198c9..51142744c37de1e419f39395db04edc926801982 100644 --- a/modules/io/src/mol/chemdict_parser.hh +++ b/modules/io/src/mol/chemdict_parser.hh @@ -25,6 +25,7 @@ #include <ost/mol/chem_class.hh> +#include <ost/mol/chem_type.hh> #include <ost/io/mol/star_parser.hh> #include <ost/conop/compound_lib.hh> @@ -43,6 +44,7 @@ public: last_(0), loop_type_(DONT_KNOW), dialect_(dialect) { this->InitTypeMap(); + this->InitPDBXTypeMap(); } virtual bool OnBeginData(const StringRef& data_name); @@ -62,6 +64,7 @@ public: } private: void InitTypeMap(); + void InitPDBXTypeMap(); conop::CompoundLibPtr lib_; conop::CompoundPtr compound_; typedef enum { @@ -80,6 +83,7 @@ private: int indices_[10]; bool insert_; static std::map<String, mol::ChemClass> tm_; + static std::map<String, mol::ChemType> xtm_; std::map<String, int> atom_map_; LoopType loop_type_; conop::AtomSpec atom_; @@ -90,4 +94,4 @@ private: }} -#endif \ No newline at end of file +#endif diff --git a/modules/io/src/mol/dcd_io.cc b/modules/io/src/mol/dcd_io.cc index e5f48a93d4486e2de8c358ebb310dfb589f3d9e6..15a290279063e9c2dd7dc9948f55c0d0d70437e6 100644 --- a/modules/io/src/mol/dcd_io.cc +++ b/modules/io/src/mol/dcd_io.cc @@ -141,17 +141,41 @@ size_t calc_frame_size(bool skip_flag, bool gap_flag, size_t num_atoms) return frame_size; } + bool read_frame(std::istream& istream, const DCDHeader& header, size_t frame_size, bool skip_flag, bool gap_flag, bool swap_flag, std::vector<float>& xlist, - std::vector<geom::Vec3>& frame) + std::vector<geom::Vec3>& frame, + uint frame_num,geom::Vec3& cell_size,geom::Vec3& cell_angles) { char dummy[4]; - if(skip_flag) istream.seekg(14*4,std::ios_base::cur); + //if(skip_flag) istream.seekg(14*4,std::ios_base::cur); + if(skip_flag){ + istream.read(dummy,sizeof(dummy)); + double x,y,z,a,b,c; + istream.read(reinterpret_cast<char*>(&x),sizeof(double)); + istream.read(reinterpret_cast<char*>(&a),sizeof(double)); + istream.read(reinterpret_cast<char*>(&y),sizeof(double)); + istream.read(reinterpret_cast<char*>(&b),sizeof(double)); + istream.read(reinterpret_cast<char*>(&c),sizeof(double)); + istream.read(reinterpret_cast<char*>(&z),sizeof(double)); + istream.read(dummy,sizeof(dummy)); + cell_size[0]=x; + cell_size[1]=y; + cell_size[2]=z; + cell_angles[0]=acos(a); + cell_angles[1]=acos(b); + cell_angles[2]=acos(c); + if(a!=0.0||b!=0.0||c!=0.0){ + LOG_ERROR("LoadCHARMMTraj: periodic cell not parallelepipedic, cell angles might be wrong, handle carefully") + } + } + // read each frame if(!istream) { /* premature EOF */ - LOG_ERROR("LoadCHARMMTraj: premature end of file, frames read"); + LOG_ERROR("LoadCHARMMTraj: premature end of file while trying to read frame " + << frame_num << "Nothing left to be read"); return false; } // x coord @@ -162,7 +186,12 @@ bool read_frame(std::istream& istream, const DCDHeader& header, for(uint j=0;j<frame.size();++j) { frame[j].x=xlist[j]; } - + if(!istream) { + /* premature EOF */ + LOG_ERROR("LoadCHARMMTraj: premature end of file while trying to read frame " + << frame_num << ". No y coordinates"); + return false; + } // y coord if(gap_flag) istream.read(dummy,sizeof(dummy)); istream.read(reinterpret_cast<char*>(&xlist[0]),sizeof(float)*xlist.size()); @@ -171,7 +200,12 @@ bool read_frame(std::istream& istream, const DCDHeader& header, for(uint j=0;j<frame.size();++j) { frame[j].y=xlist[j]; } - + if(!istream) { + /* premature EOF */ + LOG_ERROR("LoadCHARMMTraj: premature end of file while trying to read frame " + << frame_num << ". No z coordinates"); + return false; + } // z coord if(gap_flag) istream.read(dummy,sizeof(dummy)); istream.read(reinterpret_cast<char*>(&xlist[0]),sizeof(float)*xlist.size()); @@ -180,10 +214,26 @@ bool read_frame(std::istream& istream, const DCDHeader& header, for(uint j=0;j<frame.size();++j) { frame[j].z=xlist[j]; } + if(!istream) { + /* premature EOF */ + LOG_ERROR("LoadCHARMMTraj: premature end of file while trying to read frame " + << frame_num); + return false; + } return true; } - +bool read_frame(std::istream& istream, const DCDHeader& header, + size_t frame_size, bool skip_flag, bool gap_flag, + bool swap_flag, std::vector<float>& xlist, + std::vector<geom::Vec3>& frame,uint frame_num) +{ + geom::Vec3 cell_size=geom::Vec3(),cell_angles=geom::Vec3(); + return read_frame(istream,header, frame_size,skip_flag, gap_flag, + swap_flag, xlist,frame,frame_num, cell_size, cell_angles); +} + + mol::CoordGroupHandle load_dcd(const mol::AtomHandleList& alist, // this atom list is already sorted! const String& trj_fn, unsigned int stride) @@ -199,10 +249,6 @@ mol::CoordGroupHandle load_dcd(const mol::AtomHandleList& alist, // this atom li DCDHeader header; bool swap_flag=false, skip_flag=false, gap_flag=false; read_dcd_header(istream, header, swap_flag, skip_flag, gap_flag); - LOG_DEBUG("LoadCHARMMTraj: " << header.num << " trajectories with " - << header.atom_count << " atoms (" << header.f_atom_count - << " fixed) each"); - if(alist.size() != static_cast<size_t>(header.t_atom_count)) { LOG_ERROR("LoadCHARMMTraj: atom count missmatch: " << alist.size() << " in coordinate file, " << header.t_atom_count @@ -213,26 +259,31 @@ mol::CoordGroupHandle load_dcd(const mol::AtomHandleList& alist, // this atom li mol::CoordGroupHandle cg=CreateCoordGroup(alist); std::vector<geom::Vec3> clist(header.t_atom_count); std::vector<float> xlist(header.t_atom_count); + geom::Vec3 cell_size, cell_angles; size_t frame_size=calc_frame_size(skip_flag, gap_flag, xlist.size()); int i=0; for(;i<header.num;i+=stride) { + std::cout << i << " " << header.num << std::endl; if (!read_frame(istream, header, frame_size, skip_flag, gap_flag, - swap_flag, xlist, clist)) { + swap_flag, xlist, clist, i,cell_size,cell_angles)) { break; } - cg.AddFrame(clist); + if(skip_flag) { + cg.AddFrame(clist,cell_size,cell_angles); + } + else cg.AddFrame(clist); // skip frames (defined by stride) if(stride>1) istream.seekg(frame_size*(stride-1),std::ios_base::cur); } - istream.get(); if(!istream.eof()) { LOG_VERBOSE("LoadCHARMMTraj: unexpected trailing file data, bytes read: " << istream.tellg()); } - LOG_VERBOSE("Loaded " << cg.GetFrameCount() << " frames with " << cg.GetAtomCount() << " atoms each"); + LOG_VERBOSE("Loaded " << cg.GetFrameCount() << " frames with " + << cg.GetAtomCount() << " atoms each"); return cg; } @@ -263,6 +314,7 @@ public: } virtual void AddFrame(const std::vector<geom::Vec3>& coords) {} + virtual void AddFrame(const std::vector<geom::Vec3>& coords,const geom::Vec3& box_size,const geom::Vec3& box_angles) {} virtual void InsertFrame(int pos, const std::vector<geom::Vec3>& coords) {} private: @@ -296,7 +348,7 @@ void DCDCoordSource::FetchFrame(uint frame) stream_.seekg(pos,std::ios_base::beg); std::vector<float> xlist(header_.t_atom_count); if (!read_frame(stream_, header_, frame_size, skip_flag_, gap_flag_, - swap_flag_, xlist, *frame_.get())) { + swap_flag_, xlist, *frame_.get(), frame)) { } } diff --git a/modules/io/src/mol/entity_io_mae_handler.cc b/modules/io/src/mol/entity_io_mae_handler.cc index a60b913f378db4b65a6043dfdf7959ef155d236a..6a5306b055c44f7d6c6ccc82f5defa8c1acd1d35 100644 --- a/modules/io/src/mol/entity_io_mae_handler.cc +++ b/modules/io/src/mol/entity_io_mae_handler.cc @@ -143,7 +143,13 @@ void MAEReader::Import(mol::EntityHandle& ent) else if(line2=="r_m_z_coord") i_atom_zpos=pid; else if(line2=="s_m_pdb_residue_name") i_res_name=pid; else if(line2=="i_m_residue_number") i_res_num=pid; - else if(line2=="s_m_pdb_segment_name") i_chain_name=pid; + else if(line2=="s_m_chain_name") i_chain_name=pid; + else if(line2=="s_m_pdb_segment_name") { + // only use this one if s_m_chain_name is not present + if(i_chain_name<0) { + i_chain_name=pid; + } + } } } } diff --git a/modules/io/src/mol/entity_io_mmcif_handler.cc b/modules/io/src/mol/entity_io_mmcif_handler.cc new file mode 100644 index 0000000000000000000000000000000000000000..23e9ff3c52a1fd2652b1bbf7c1b7995eac487a11 --- /dev/null +++ b/modules/io/src/mol/entity_io_mmcif_handler.cc @@ -0,0 +1,98 @@ +//------------------------------------------------------------------------------ +// This file is part of the OpenStructure project <www.openstructure.org> +// +// Copyright (C) 2008-2011 by the OpenStructure authors +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License as published by the Free +// Software Foundation; either version 3.0 of the License, or (at your option) +// any later version. +// This library is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this library; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +//------------------------------------------------------------------------------ +/* + Author: Marco Biasini, Ansgar Philippsen + */ +#include <iostream> +#include <sstream> +#include <iomanip> + +#include <boost/algorithm/string.hpp> +#include <boost/filesystem/convenience.hpp> +#include <boost/format.hpp> +#include <boost/lexical_cast.hpp> + +#include <ost/log.hh> +#include <ost/io/io_exception.hh> +#include "entity_io_mmcif_handler.hh" +#include <ost/profile.hh> +#include <ost/io/mol/mmcif_reader.hh> +namespace ost { namespace io { + +using boost::format; + + +bool EntityIOMMCIFHandler::RequiresBuilder() const +{ + return true; +} + + +void EntityIOMMCIFHandler::Export(const mol::EntityView& ent, + const boost::filesystem::path& loc) const +{ +} + +void EntityIOMMCIFHandler::Import(mol::EntityHandle& ent, + std::istream& stream) +{ + MMCifReader reader(stream,ent, + IOProfileRegistry::Instance().GetDefault()); + reader.Parse(); +} + +void EntityIOMMCIFHandler::Export(const mol::EntityView& ent, + std::ostream& stream) const +{ +} + +void EntityIOMMCIFHandler::Import(mol::EntityHandle& ent, + const boost::filesystem::path& loc) +{ + std::string filename=loc.string(); + MMCifReader reader(filename, ent, + IOProfileRegistry::Instance().GetDefault()); + reader.Parse(); +} + +bool EntityIOMMCIFHandler::ProvidesImport(const boost::filesystem::path& loc, + const String& type) +{ + if (type=="auto") { + String match_suf_string=loc.string(); + std::transform(match_suf_string.begin(),match_suf_string.end(), + match_suf_string.begin(),tolower); + if(detail::FilenameEndsWith(match_suf_string,".cif") || + detail::FilenameEndsWith(match_suf_string,".cif.gz")){ + return true; + } + } + return type=="cif"; +} + +bool EntityIOMMCIFHandler::ProvidesExport(const boost::filesystem::path& loc, + const String& type) +{ + return false; +} + + +}} // ns + + diff --git a/modules/io/src/mol/entity_io_mmcif_handler.hh b/modules/io/src/mol/entity_io_mmcif_handler.hh new file mode 100644 index 0000000000000000000000000000000000000000..2fa262156d4867f665a8fc3f4d5ea8e71877f16f --- /dev/null +++ b/modules/io/src/mol/entity_io_mmcif_handler.hh @@ -0,0 +1,59 @@ +//------------------------------------------------------------------------------ +// This file is part of the OpenStructure project <www.openstructure.org> +// +// Copyright (C) 2008-2011 by the OpenStructure authors +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License as published by the Free +// Software Foundation; either version 3.0 of the License, or (at your option) +// any later version. +// This library is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this library; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +//------------------------------------------------------------------------------ +#ifndef OST_IO_ENTITY_IO_PLUGIN_MMCIF_HH +#define OST_IO_ENTITY_IO_PLUGIN_MMCIF_HH + +#include <vector> + +#include <ost/io/mol/entity_io_handler.hh> + +namespace ost { namespace io { + + +class DLLEXPORT_OST_IO EntityIOMMCIFHandler: public EntityIOHandler { +public: + virtual void Import(mol::EntityHandle& ent, + const boost::filesystem::path& loc); + + virtual void Export(const mol::EntityView& ent, + const boost::filesystem::path& loc) const; + + virtual void Import(mol::EntityHandle& ent, std::istream& stream); + + virtual void Export(const mol::EntityView& ent, std::ostream& stream) const; + + static bool ProvidesImport(const boost::filesystem::path& loc, + const String& format="auto"); + static bool ProvidesExport(const boost::filesystem::path& loc, + const String& format="auto"); + virtual bool RequiresBuilder() const; + + static String GetFormatName() { return String("mmCIF"); } + static String GetFormatDescription() { + return String("macromolecular Crystallographic Information File "); + } +}; + + +typedef EntityIOHandlerFactory<EntityIOMMCIFHandler> EntityIOMMCIFHandlerFactory; + + +}} // ns + +#endif diff --git a/modules/io/src/mol/io_profile.hh b/modules/io/src/mol/io_profile.hh index 91fe27b7793350e10d29d922cf0ca501a1697da5..b4802583a838156ef5aac62048c158b50bff65d3 100644 --- a/modules/io/src/mol/io_profile.hh +++ b/modules/io/src/mol/io_profile.hh @@ -27,13 +27,13 @@ namespace ost { namespace io { struct DLLEXPORT IOProfile { public: - IOProfile(String d, bool sh, bool qm, bool ft, bool js, bool nh, bool co): + IOProfile(String d, bool sh, bool qm, bool ft, bool js, bool nh, bool co, bool bf): dialect(d), strict_hydrogens(sh), quack_mode(qm), fault_tolerant(ft), - join_spread_atom_records(js), no_hetatms(nh), calpha_only(co) + join_spread_atom_records(js), no_hetatms(nh), calpha_only(co), bond_feasibility_check(bf) { } IOProfile(): dialect("PDB"), strict_hydrogens(true), quack_mode(false), fault_tolerant(false), join_spread_atom_records(false), no_hetatms(false), - calpha_only(false) + calpha_only(false), bond_feasibility_check(true) { } virtual ~IOProfile() { } @@ -44,11 +44,12 @@ public: bool join_spread_atom_records; bool no_hetatms; bool calpha_only; + bool bond_feasibility_check; IOProfile Copy() { return IOProfile(dialect, strict_hydrogens, quack_mode, fault_tolerant, - join_spread_atom_records, no_hetatms, calpha_only); + join_spread_atom_records, no_hetatms, calpha_only, bond_feasibility_check); } virtual void PostImport(mol::EntityHandle ent) { } }; @@ -61,7 +62,8 @@ inline std::ostream& operator<<(std::ostream& stream, const IOProfile& p) << (p.join_spread_atom_records ? "True" : "False") << ", no_hetatms=" << (p.no_hetatms ? "True" : "False") << ", calpha_only=" << (p.calpha_only ? "True" : "False") << ", fault_tolerant=" - << (p.fault_tolerant ? "True" : "False") << ")"; + << (p.fault_tolerant ? "True" : "False") << ", bond_feasibility_check=" + << (p.bond_feasibility_check ? "True" : "False") << ")"; return stream; } diff --git a/modules/io/src/mol/mmcif_info.cc b/modules/io/src/mol/mmcif_info.cc new file mode 100644 index 0000000000000000000000000000000000000000..c8565a2e809ff1f84b182b9f73e4cacd1866c509 --- /dev/null +++ b/modules/io/src/mol/mmcif_info.cc @@ -0,0 +1,76 @@ +//------------------------------------------------------------------------------ +// This file is part of the OpenStructure project <www.openstructure.org> +// +// Copyright (C) 2008-2011 by the OpenStructure authors +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License as published by the Free +// Software Foundation; either version 3.0 of the License, or (at your option) +// any later version. +// This library is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this library; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +//------------------------------------------------------------------------------ + +#include <ost/io/io_exception.hh> +#include <ost/io/mol/mmcif_info.hh> + +namespace ost { namespace io { + +void MMCifInfo::AddAuthorsToCitation(StringRef id, std::vector<String> list) +{ + // find citation + std::vector<MMCifInfoCitation>::iterator cit_it; + for (cit_it = citations_.begin(); cit_it != citations_.end(); ++cit_it) { + if (id == StringRef(cit_it->GetID().c_str(), cit_it->GetID().length())) { + cit_it->SetAuthorList(list); + return; + } + } + + throw IOException("No citation for identifier '" + id.str() + "' found."); +} + + + +MMCifInfoStructRefSeqPtr +MMCifInfoStructRef::AddAlignedSeq(const String& aid, const String& chain_name, + int seq_begin, int seq_end, int db_begin, + int db_end) +{ + std::map<String, MMCifInfoStructRefSeqPtr>::const_iterator i=seqs_.find(aid); + if (i!=seqs_.end()) { + throw IOException("duplicate align_id for struct_ref '"+id_+"'"); + } + MMCifInfoStructRefSeqPtr p(new MMCifInfoStructRefSeq(aid, chain_name, + seq_begin, seq_end, + db_begin, db_end)); + seqs_[aid]=p; + return p; +} + + +MMCifInfoStructRefSeqPtr +MMCifInfoStructRef::GetAlignedSeq(const String& aid) const +{ + + std::map<String, MMCifInfoStructRefSeqPtr>::const_iterator i=seqs_.find(aid); + return i==seqs_.end() ? MMCifInfoStructRefSeqPtr() : i->second; +} + +MMCifInfoStructRefSeqDifPtr +MMCifInfoStructRefSeq::AddDif(int seq_rnum, int db_rnum, const String& details) +{ + MMCifInfoStructRefSeqDifPtr d(new MMCifInfoStructRefSeqDif(seq_rnum, db_rnum, + details)); + difs_.push_back(d); + return d; +} + + +}} //ns diff --git a/modules/io/src/mol/mmcif_info.hh b/modules/io/src/mol/mmcif_info.hh new file mode 100644 index 0000000000000000000000000000000000000000..38e49f58bec9420e353088d8a7858908be887456 --- /dev/null +++ b/modules/io/src/mol/mmcif_info.hh @@ -0,0 +1,843 @@ +//------------------------------------------------------------------------------ +// This file is part of the OpenStructure project <www.openstructure.org> +// +// Copyright (C) 2008-2011 by the OpenStructure authors +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License as published by the Free +// Software Foundation; either version 3.0 of the License, or (at your option) +// any later version. +// This library is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this library; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +//------------------------------------------------------------------------------ +#ifndef OST_MMCIF_INFO_HH +#define OST_MMCIF_INFO_HH + +#include <vector> +#include <map> +#include <boost/shared_ptr.hpp> +#include <ost/geom/geom.hh> +#include <ost/string_ref.hh> +#include <ost/io/module_config.hh> + +namespace ost { namespace io { + +class DLLEXPORT_OST_IO MMCifInfoStructDetails { +public: + /// \brief Create a details object. + MMCifInfoStructDetails(): entry_id_(""), title_(""), casp_flag_('\0'), + descriptor_(""), mass_(0.0), mass_method_(""), model_details_(""), + model_type_details_("") {}; + + /// \brief Set id. + /// + /// \param id id + void SetEntryID(String id) { entry_id_ = id; } + /// \brief Get id. + /// + /// \return id + String GetEntryID() const { return entry_id_; } + + /// \brief Set CASP flag. + /// + /// \param flag flag + void SetCASPFlag(char flag) { casp_flag_ = flag; } + /// \brief Get CASP flag. + /// + /// \return flag + char GetCASPFlag() const { return casp_flag_; } + + /// \brief Set descriptor. + /// + /// \param desc descriptor for an NDB structure or PDB COMPND record + void SetDescriptor(String desc) { descriptor_ = desc; } + /// \brief Get CASP flag. + /// + /// \return flag + String GetDescriptor() const { return descriptor_; } + + /// \brief Set mass. + /// + /// \param mass molecular mass + void SetMass(Real mass) { mass_ = mass; } + /// \brief Get molecular weight. + /// + /// \return mass + Real GetMass() const { return mass_; } + + /// \brief Set the method how the molecular weight was detected. + /// + /// \param method detection method + void SetMassMethod(String method) { mass_method_ = method; } + /// \brief Get the method how the molecular weight was determined. + /// + /// \return method + String GetMassMethod() const { return mass_method_; } + + /// \brief Set the description about the production of this structure. + /// + /// \param desc explaination + void SetModelDetails(String desc) { model_details_ = desc; } + /// \brief Get the details how the structure was determined. + /// + /// \return details + String GetModelDetails() const { return model_details_; } + + /// \brief Set a description for the type of the structure model. + /// + /// \param desc explaination + void SetModelTypeDetails(String desc) { model_type_details_ = desc; } + /// \brief Get the description for the type of the structure model. + /// + /// \return details + String GetModelTypeDetails() const { return model_type_details_; } + + /// \brief Set a title for the data block. + /// + /// \param title title + void SetTitle(String title) { title_ = title; } + /// \brief Get the title of the structure model. + /// + /// \return title + String GetTitle() const { return title_; } + + bool operator==(const MMCifInfoStructDetails& sd) const { + if (this->entry_id_ != sd.entry_id_) { + return false; + } + if (this->casp_flag_ != sd.casp_flag_) { + return false; + } + if (this->descriptor_ != sd.descriptor_) { + return false; + } + if (this->mass_ != sd.mass_) { + return false; + } + if (this->mass_method_ != sd.mass_method_) { + return false; + } + if (this->model_details_ != sd.model_details_) { + return false; + } + if (this->model_type_details_ != sd.model_type_details_) { + return false; + } + if (this->title_ != sd.title_) { + return false; + } + + return true; + } + + bool operator!=(const MMCifInfoStructDetails& sd) const { + return !this->operator == (sd); + } + +private: + String entry_id_; + String title_; + char casp_flag_; + String descriptor_; + Real mass_; + String mass_method_; + String model_details_; + String model_type_details_; +}; + +class DLLEXPORT_OST_IO MMCifInfoTransOp { +public: + /// \brief Create an operation + MMCifInfoTransOp(): id_(""), type_("") + { + translation_ = geom::Vec3(); + }; + + /// \brief Set id + /// + /// \param id id + void SetID(String id) { id_ = id; } + /// \brief Get id + /// + /// \return id + String GetID() const { return id_; } + + /// \brief Set type + /// + /// \param type + void SetType(String type) { type_ = type; } + /// \brief Get type + /// + /// \return type + String GetType() const { return type_; } + + /// \brief Set the translational vector + /// + /// \param + void SetVector(Real x, Real y, Real z) + { + translation_.SetX(x); + translation_.SetY(y); + translation_.SetZ(z); + } + /// \brief Get the translational vector + /// + /// \return vector + geom::Vec3 GetVector() const { return translation_; } + + /// \brief Set the rotational matrix + /// + /// \param + void SetMatrix(Real i00, Real i01, Real i02, + Real i10, Real i11, Real i12, + Real i20, Real i21, Real i22) + { + rotation_ = geom::Mat3(i00,i01,i02, i10,i11,i12, i20,i21,i22); + } + /// \brief Get the rotational matrix + /// + /// \return matrix + geom::Mat3 GetMatrix() const { return rotation_; } + + bool operator==(const MMCifInfoTransOp& op) const { + if (this->id_ != op.id_) { + return false; + } + if (this->type_ != op.type_) { + return false; + } + if (this->translation_ != op.translation_) { + return false; + } + if (this->rotation_ != op.rotation_) { + return false; + } + + return true; + } + + bool operator!=(const MMCifInfoTransOp& op) const { + return !this->operator==(op); + } + +private: + String id_; ///< identifier + String type_; ///< type of operation + geom::Vec3 translation_; ///< translational vector + geom::Mat3 rotation_; ///< rotational matrix +}; +typedef boost::shared_ptr<MMCifInfoTransOp> MMCifInfoTransOpPtr; + + +class DLLEXPORT_OST_IO MMCifInfoBioUnit { +public: + /// \brief Create a biounit. + MMCifInfoBioUnit(): details_("") {}; + + /// \brief Set details + /// + /// \param details details + void SetDetails(String details) { details_ = details; } + /// \brief Get details + /// + /// \return details + String GetDetails() const { return details_; } + + /// \brief Add a chain name + /// + /// \param chain chain name + void AddChain(String chain) { chains_.push_back(chain); } + /// \brief Get vector of chain names + /// + /// \return chains + const std::vector<String>& GetChainList() const { return chains_; } + + /// \brief Add a set of operations + /// + /// \param operations vector of operations to be added + void AddOperations(std::vector<MMCifInfoTransOpPtr> operations) + { + operations_.push_back(operations); + } + /// \brief Get the list of operations + /// + /// \return vector of vectors of iterators. + const std::vector<std::vector<MMCifInfoTransOpPtr> >& GetOperations() + { + return operations_; + } + + bool operator==(const MMCifInfoBioUnit& bu) const { + if (this->details_ != bu.details_) { + return false; + } + if (this->chains_ != bu.chains_) { + return false; + } + if (this->operations_.size() == bu.operations_.size()) { + std::vector<std::vector<MMCifInfoTransOpPtr> >::const_iterator th_ops_it; + std::vector<std::vector<MMCifInfoTransOpPtr> >::const_iterator bu_ops_it; + std::vector<MMCifInfoTransOpPtr>::const_iterator th_op_it; + std::vector<MMCifInfoTransOpPtr>::const_iterator bu_op_it; + + for (th_ops_it = this->operations_.begin(), + bu_ops_it = bu.operations_.begin(); + th_ops_it != this->operations_.end(); + ++th_ops_it, ++bu_ops_it) { + if (th_ops_it->size() == bu_ops_it->size()) { + for (th_op_it = th_ops_it->begin(), bu_op_it = bu_ops_it->begin(); + th_op_it != th_ops_it->end(); + ++th_op_it, ++bu_op_it) { + if (*th_op_it != *bu_op_it) { + return false; + } + } + } else { + return false; + } + } + } else { + return false; + } + + return true; + } + + bool operator!=(const MMCifInfoBioUnit& bu) const { + return !this->operator==(bu); + } + +private: + String details_; ///< pdbx_struct_assembly.details + std::vector<String> chains_; ///< chains involved in this assembly + std::vector<std::vector<MMCifInfoTransOpPtr> > operations_; +}; + +class DLLEXPORT_OST_IO MMCifInfoCitation { +public: + /// \brief Create a citation. + MMCifInfoCitation(): id_(""), where_(UNKNOWN), cas_(""), published_in_(""), + volume_(""), page_first_(""), page_last_(""), doi_(""), pubmed_(0), + year_(0), title_("") {}; + + /// \brief Set ID + /// + /// \param id ID + void SetID(String id) { id_ = id; } + /// \brief Get ID + /// + /// \return ID + String GetID() const { return id_; } + + /// \brief Set a CAS identifier + /// + /// \param id CAS identifier + void SetCAS(String id) { cas_ = id; } + /// \brief Get a CAS identifier + /// + /// \return CAS identifier + String GetCAS() const { return cas_; } + + /// \brief Set an ISBN code + /// + /// \param code ISBN code + void SetISBN(String code) { isbn_ = code; } + + /// \brief Get an ISBN code + /// + /// \return ISBN code + String GetISBN() const { return isbn_; } + + /// \brief Set a book title or journal name + /// + /// \param title where published + void SetPublishedIn(String title) { published_in_ = title; } + + /// \brief Get a book title or journal name + /// + /// \return title + String GetPublishedIn() const { return published_in_; } + + /// \brief Set a journal volume + /// + /// \param volume + void SetVolume(String volume) { volume_ = volume; } + + /// \brief Get a journal volume + /// + /// \return volume + String GetVolume() const { return volume_; } + + /// \brief Set the start page for a publication + /// + /// \param start + void SetPageFirst(String first) { page_first_ = first; } + + /// \brief Get the start page of a publication + /// + /// \return first page + String GetPageFirst() const { return page_first_; } + + /// \brief Set the end page for a publication + /// + /// \param end + void SetPageLast(String last) { page_last_ = last; } + + /// \brief Get the last page of a publication + /// + /// \return last page + String GetPageLast() const { return page_last_; } + + /// \brief Set the DOI of a document + /// + /// \param doi + void SetDOI(String doi) { doi_ = doi; } + + + /// \brief Get the DOI of a document + /// + /// \return DOI + String GetDOI() const { return doi_; } + + /// \brief Set the PubMed accession number + /// + /// \param no + void SetPubMed(int no) { pubmed_ = no; } + + /// \brief Get the PubMed accession number + /// + /// \return PubMed accession + int GetPubMed() const { return pubmed_; } + + /// \brief Set the year of a publication + /// + /// \param year + void SetYear(int year) { year_ = year; } + + + /// \brief Get the year of a publication + /// + /// \return year + int GetYear() const { return year_; } + + + /// \brief Set the title of a publication + /// + /// \param title + void SetTitle(String title) { title_ = title; } + + /// \brief Get the title of a publication + /// + /// \return title + String GetTitle() const { return title_; } + + /// \brief Set the list of authors + /// + /// \param list + void SetAuthorList(std::vector<String> list) { authors_ = list; } + + /// \brief Get the list of authors + /// + /// \return list + const std::vector<String>& GetAuthorList() const { return authors_; } + + bool operator==(const MMCifInfoCitation& cit) const { + if (this->year_ != cit.year_) { + return false; + } + if (this->pubmed_ != cit.pubmed_) { + return false; + } + if (this->where_ != cit.where_) { + return false; + } + if (StringRef(this->id_.c_str(), this->id_.length()) != + StringRef(cit.id_.c_str(), cit.id_.length())) { + return false; + } + if (StringRef(this->cas_.c_str(), this->cas_.length()) != + StringRef(cit.cas_.c_str(), cit.cas_.length())) { + return false; + } + if (StringRef(this->isbn_.c_str(), this->isbn_.length()) != + StringRef(cit.isbn_.c_str(), cit.isbn_.length())) { + return false; + } + if (StringRef(this->published_in_.c_str(), this->published_in_.length()) != + StringRef(cit.published_in_.c_str(), cit.published_in_.length())) { + return false; + } + if (StringRef(this->volume_.c_str(), this->volume_.length()) != + StringRef(cit.volume_.c_str(), cit.volume_.length())) { + return false; + } + if (StringRef(this->page_first_.c_str(), this->page_first_.length()) != + StringRef(cit.page_first_.c_str(), cit.page_first_.length())) { + return false; + } + if (StringRef(this->page_last_.c_str(), this->page_last_.length()) != + StringRef(cit.page_last_.c_str(), cit.page_last_.length())) { + return false; + } + if (StringRef(this->doi_.c_str(), this->doi_.length()) != + StringRef(cit.doi_.c_str(), cit.doi_.length())) { + return false; + } + if (StringRef(this->title_.c_str(), this->title_.length()) != + StringRef(cit.title_.c_str(), cit.title_.length())) { + return false; + } + if (this->authors_ != cit.authors_) { + return false; + } + + return true; + } + + bool operator!=(const MMCifInfoCitation& cit) const { + return !this->operator==(cit); + } + +private: + /// \enum types of citations + typedef enum { + JOURNAL, + BOOK, + UNKNOWN + } MMCifInfoCType; + + String id_; ///< internal identifier + MMCifInfoCType where_; ///< journal or book? + String cas_; ///< CAS identifier + String isbn_; ///< ISBN no. of medium + String published_in_; ///< book title or full journal name + String volume_; ///< journal volume + String page_first_; ///< first page + String page_last_; ///< last page + String doi_; ///< DOI identifier + int pubmed_; ///< accession no. + int year_; ///< year of publication + String title_; ///< title of the publication + std::vector<String> authors_; ///< author information +}; + +/// \brief container class for information on obsolete entries +/// +class DLLEXPORT_OST_IO MMCifInfoObsolete { +public: + /// \brief Create an object of information baout an obsolete entry. + MMCifInfoObsolete(): date_(""), id_(UNKNOWN), pdb_id_(""), + replaced_pdb_id_("") {}; + + /// \brief Set date of replacement. + /// + /// \param date + void SetDate(String date) { date_ = date; } + + /// \brief Get the date string. + /// + /// \return date as string. + String GetDate() { return date_; } + + /// \brief Set type of entry. + /// + /// \param type + void SetID(StringRef type) + { + if (type == StringRef("OBSLTE", 6)) { + id_ = OBSLTE; + } + else if (type == StringRef("SPRSDE", 6)) { + id_ = SPRSDE; + } + } + + /// \brief Get type of entry. + /// + /// \return type as string, starting with an upper case letter. + String GetID() + { + if (id_ == OBSLTE) { + return "Obsolete"; + } + if (id_ == SPRSDE) { + return "Supersede"; + } + return "Unknown"; + } + + /// \brief Set id of replacement. + /// + /// \param id + void SetPDBID(String id) { pdb_id_ = id; } + + /// \brief Get id of replacement. + /// + /// \return id + String GetPDBID() { return pdb_id_; } + + /// \brief Set id of replaced entry. + /// + /// \param id + void SetReplacedPDBID(String id) { replaced_pdb_id_ = id; } + + /// \brief Get id of replaced entry. + /// + /// \return id + String GetReplacedPDBID() { return replaced_pdb_id_; } + +private: + /// \enum types of obsolete entries + typedef enum { + OBSLTE, + SPRSDE, + UNKNOWN + } MMCifObsoleteType; + + String date_; ///< date of replacement + MMCifObsoleteType id_; ///< type of entry + String pdb_id_; ///< replacing entry + String replaced_pdb_id_; ///< replaced entry +}; + +class MMCifInfoStructRef; +class MMCifInfoStructRefSeq; +class MMCifInfoStructRefSeqDif; + + +typedef boost::shared_ptr<MMCifInfoStructRef> MMCifInfoStructRefPtr; +typedef boost::shared_ptr<MMCifInfoStructRefSeq> MMCifInfoStructRefSeqPtr; +typedef boost::shared_ptr<MMCifInfoStructRefSeqDif> MMCifInfoStructRefSeqDifPtr; + +typedef std::vector<MMCifInfoStructRefPtr> MMCifInfoStructRefs; +typedef std::vector<MMCifInfoStructRefSeqPtr> MMCifInfoStructRefSeqs; +typedef std::vector<MMCifInfoStructRefSeqDifPtr> MMCifInfoStructRefSeqDifs; +class DLLEXPORT_OST_IO MMCifInfoStructRef { +public: + MMCifInfoStructRef(const String& id, const String& ent_id, + const String& db_name, + const String& db_ident, const String& db_access): + id_(id), ent_id_(ent_id), db_name_(db_name), db_ident_(db_ident), + db_access_(db_access) + { } + const String& GetID() const { return id_; } + const String& GetDBName() const { return db_name_; } + const String& GetDBID() const { return db_ident_; } + const String& GetEntityID() const { return ent_id_; } + const String& GetDBAccess() const { return db_access_; } + MMCifInfoStructRefSeqPtr AddAlignedSeq(const String& align_id, + const String& chain_name, int seq_begin, + int seq_end, int db_begin, int db_end); + MMCifInfoStructRefSeqPtr GetAlignedSeq(const String& align_id) const; + MMCifInfoStructRefSeqs GetAlignedSeqs() const + { + MMCifInfoStructRefSeqs seqs; + seqs.reserve(seqs_.size()); + for (std::map<String, MMCifInfoStructRefSeqPtr>::const_iterator + i=seqs_.begin(), e=seqs_.end(); i!=e; ++i) { + seqs.push_back(i->second); + } + return seqs; + } +private: + String id_; + String ent_id_; + String db_name_; + String db_ident_; + String db_access_; + std::map<String, MMCifInfoStructRefSeqPtr> seqs_; +}; + +class DLLEXPORT_OST_IO MMCifInfoStructRefSeq { +public: + MMCifInfoStructRefSeq(const String& align_id, const String& chain_name, + int seq_begin, int seq_end, + int db_begin, int db_end): + id_(align_id), chain_name_(chain_name), + seq_begin_(seq_begin), seq_end_(seq_end), db_begin_(db_begin), db_end_(db_end) + { } + + const String& GetID() const { return id_; } + const String& GetChainName() const { return chain_name_; } + int GetSeqBegin() const { return seq_begin_; } + int GetSeqEnd() const { return seq_end_; } + int GetDBBegin() const { return db_begin_; } + int GetDBEnd() const { return db_end_; } + MMCifInfoStructRefSeqDifPtr AddDif(int seq_num, int db_num, + const String& details); + const std::vector<MMCifInfoStructRefSeqDifPtr>& GetDifs() const { return difs_; } +private: + String id_; + String chain_name_; + int seq_begin_; + int seq_end_; + int db_begin_; + int db_end_; + std::vector<MMCifInfoStructRefSeqDifPtr> difs_; +}; + +class DLLEXPORT_OST_IO MMCifInfoStructRefSeqDif { +public: + MMCifInfoStructRefSeqDif(int seq_rnum, int db_rnum, const String& details): + seq_rnum_(seq_rnum), db_rnum_(db_rnum), details_(details) {} + int GetSeqRNum() const { return seq_rnum_;} + int GetDBRNum() const { return db_rnum_; } + const String& GetDetails() const { return details_; } +private: + int seq_rnum_; + int db_rnum_; + String details_; +}; + +/// \brief container class for additional information from MMCif files +/// +/// \section mmcif annotation information +/// +/// MMCif files contain loads of additional information beside coordinates. +/// This class is set up to capture some of it. In detail, we have: +/// +/// \li citations +/// \li biounits +/// \li transformation information from asym. unit to biounit +/// \li structure information +/// \li resolution +/// \li method +class DLLEXPORT_OST_IO MMCifInfo { +public: + /// \brief Create an info object. + MMCifInfo(): exptl_method_(""), resolution_(0.0f) {}; + + /// \brief Add an item to the list of citations + /// + /// \param citation to be added + void AddCitation(MMCifInfoCitation citation) // unit test + { + citations_.push_back(citation); + } + + /// \brief Add a list of authors to a specific citation. + /// + /// \param id identifier of the citation to be modified. + /// \param list list of authors to be added. + void AddAuthorsToCitation(StringRef id, std::vector<String> list); //unit test + + /// \brief Get the list of citations stored in an info object. + /// + /// \return vector of MMCifInfoCitation objects + const std::vector<MMCifInfoCitation>& GetCitations() const + { + return citations_; + } + + /// \brief Set an experimental method. + /// + /// \param method Method description + void SetMethod(String method) { exptl_method_ = method; } + + /// \brief Get an experimental method. + /// + /// \return Method description + const StringRef GetMethod() const + { + return StringRef(exptl_method_.c_str(), exptl_method_.length()); + } + + /// \brief Set resolution. + /// + /// \param res experiment resolution + void SetResolution(Real res) { resolution_ = res; } + + /// \brief Get resolution. + /// + /// \return experiment resolution + Real GetResolution() const { return resolution_; } + + /// \brief Add a biounit + /// + /// \param bu biounit to be added + void AddBioUnit(MMCifInfoBioUnit bu) // unit test + { + biounits_.push_back(bu); + } + + /// \brief Get the list of biounits stored in an info object. + /// + /// \return vector of MMCifInfoBioUnit objects + const std::vector<MMCifInfoBioUnit>& GetBioUnits() const + { + return biounits_; + } + + /// \brief Add a operation + /// + /// \param op operation to be added + void AddOperation(MMCifInfoTransOpPtr op) // unit test + { + transops_.push_back(op); + } + + /// \brief Get the list of operations stored in an info object. + /// + /// \return vector of MMCifInfoTransOp objects + const std::vector<MMCifInfoTransOpPtr>& GetOperations() const + { + return transops_; + } + + /// \brief Add a set of structure details + /// + /// \param details info block to be added + void SetStructDetails(MMCifInfoStructDetails details) + { + struct_details_ = details; + } + + /// \brief Get the list of details about structures. + /// + /// \return vector of MMCifInfoStructDetails objects + const MMCifInfoStructDetails GetStructDetails() const + { + return struct_details_; + } + + /// \brief Add a block of information on obsolete entries + /// + /// \param obsolete + void SetObsoleteInfo(MMCifInfoObsolete obsolete) + { + obsolete_ = obsolete; + } + + /// \brief Get information on an obsolete entries + /// + /// \return MMCifInfoObsolete object + MMCifInfoObsolete GetObsoleteInfo() const + { + return obsolete_; + } + const MMCifInfoStructRefs& GetStructRefs() const { return struct_refs_; } + void SetStructRefs(const MMCifInfoStructRefs& sr) { struct_refs_=sr; } +//protected: + +private: + // members + String exptl_method_; + Real resolution_; + MMCifInfoStructDetails struct_details_; ///< mmCIF struct category + MMCifInfoObsolete obsolete_; ///< obsolete/ superseded entry + std::vector<MMCifInfoCitation> citations_; ///< list of citations + std::vector<MMCifInfoBioUnit> biounits_; ///< list of biounits + std::vector<MMCifInfoTransOpPtr> transops_; + MMCifInfoStructRefs struct_refs_; +}; + + +}} // ns + +#endif diff --git a/modules/io/src/mol/mmcif_reader.cc b/modules/io/src/mol/mmcif_reader.cc new file mode 100644 index 0000000000000000000000000000000000000000..409902ab4391a66860aeed24d9b9aa3d6a9720a9 --- /dev/null +++ b/modules/io/src/mol/mmcif_reader.cc @@ -0,0 +1,1638 @@ +//------------------------------------------------------------------------------ +// This file is part of the OpenStructure project <www.openstructure.org> +// +// Copyright (C) 2008-2011 by the OpenStructure authors +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License as published by the Free +// Software Foundation; either version 3.0 of the License, or (at your option) +// any later version. +// This library is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this library; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +//------------------------------------------------------------------------------ + +#include <ctype.h> + +#include <ost/profile.hh> +#include <ost/log.hh> +#include <ost/dyn_cast.hh> +#include <ost/mol/xcs_editor.hh> +#include <ost/conop/conop.hh> + +#include <ost/conop/rule_based_builder.hh> +#include <ost/io/mol/mmcif_reader.hh> + +namespace ost { namespace io { + + +bool is_undef(StringRef value) +{ + return value.size()==1 && (value[0]=='?' || value[0]=='.'); +} + +MMCifReader::MMCifReader(std::istream& stream, mol::EntityHandle& ent_handle, + const IOProfile& profile): + StarParser(stream, true), profile_(profile), ent_handle_(ent_handle) +{ + this->Init(); +} + +MMCifReader::MMCifReader(const String& filename, mol::EntityHandle& ent_handle, + const IOProfile& profile): + StarParser(filename, true), profile_(profile), ent_handle_(ent_handle) +{ + this->Init(); +} + +void MMCifReader::Init() +{ + warned_name_mismatch_ = false; + category_ = DONT_KNOW; + memset(category_counts_, 0, DONT_KNOW * sizeof(int)); + chain_count_ = 0; + atom_count_ = 0; + residue_count_ = 0; + auth_chain_id_ = false; + seqres_can_ = false; + has_model_ = false; + restrict_chains_ = ""; + subst_res_id_ = ""; + curr_chain_ = mol::ChainHandle(); + curr_residue_ = mol::ResidueHandle(); + seqres_ = seq::CreateSequenceList(); + read_seqres_ = false; + warned_rule_based_ = false; + info_ = MMCifInfo(); +} + +void MMCifReader::ClearState() +{ + curr_chain_ = mol::ChainHandle(); + curr_residue_ = mol::ResidueHandle(); + chain_count_ = 0; + residue_count_ = 0; + atom_count_ = 0; + category_ = DONT_KNOW; + warned_name_mismatch_ = false; + seqres_ = seq::CreateSequenceList(); + info_ = MMCifInfo(); + entity_desc_map_.clear(); + authors_map_.clear(); + bu_origin_map_.clear(); + bu_assemblies_.clear(); + helix_list_.clear(); + strand_list_.clear(); +} + +void MMCifReader::SetRestrictChains(const String& restrict_chains) +{ + restrict_chains_ = restrict_chains; +} + +bool MMCifReader::IsValidPDBIdent(const StringRef& pdbid) +{ + if (pdbid.length() == PDBID_LEN && isdigit(pdbid[0])) { + return true; + } + return false; +} + +bool MMCifReader::OnBeginData(const StringRef& data_name) +{ + LOG_DEBUG("MCIFFReader: " << profile_); + Profile profile_import("MMCifReader::OnBeginData"); + + // check for PDB id + if (!this->IsValidPDBIdent(data_name)) { + throw IOException(this->FormatDiagnostic(STAR_DIAG_ERROR, + "No valid PDB id found for data block, read instead \'" + + data_name.str() + "\'", + this->GetCurrentLinenum())); + } + + this->ClearState(); + + return true; +} + +bool MMCifReader::OnBeginLoop(const StarLoopDesc& header) +{ + bool cat_available = false; + category_ = DONT_KNOW; + // set whole array to -1 + memset(indices_, -1, MAX_ITEMS_IN_ROW * sizeof(int)); + // walk through possible categories + if (header.GetCategory() == "atom_site") { + category_ = ATOM_SITE; + // mandatory items + this->TryStoreIdx(AUTH_ASYM_ID, "auth_asym_id", header); + this->TryStoreIdx(AS_ID, "id", header); + this->TryStoreIdx(LABEL_ALT_ID, "label_alt_id", header); + this->TryStoreIdx(LABEL_ASYM_ID, "label_asym_id", header); + this->TryStoreIdx(LABEL_ATOM_ID, "label_atom_id", header); + this->TryStoreIdx(LABEL_COMP_ID, "label_comp_id", header); + this->TryStoreIdx(LABEL_ENTITY_ID, "label_entity_id", header); + this->TryStoreIdx(LABEL_SEQ_ID, "label_seq_id", header); + this->TryStoreIdx(TYPE_SYMBOL, "type_symbol", header); + // assumed mandatory + this->TryStoreIdx(CARTN_X, "Cartn_x", header); + this->TryStoreIdx(CARTN_Y, "Cartn_y", header); + this->TryStoreIdx(CARTN_Z, "Cartn_z", header); + // optional + indices_[OCCUPANCY] = header.GetIndex("occupancy"); + indices_[B_ISO_OR_EQUIV] = header.GetIndex("B_iso_or_equiv"); + indices_[GROUP_PDB] = header.GetIndex("group_PDB"); + indices_[AUTH_SEQ_ID] = header.GetIndex("auth_seq_id"); + indices_[PDBX_PDB_INS_CODE] = header.GetIndex("pdbx_PDB_ins_code"); + indices_[PDBX_PDB_MODEL_NUM] = header.GetIndex("pdbx_PDB_model_num"); + + // post processing + if (category_counts_[category_] > 0) { + if ((has_model_ && (indices_[PDBX_PDB_MODEL_NUM] == -1))|| + (!has_model_ && (indices_[PDBX_PDB_MODEL_NUM] != -1))) { + throw IOException(this->FormatDiagnostic(STAR_DIAG_ERROR, + "Not all atom_site entries carry a model number.", + this->GetCurrentLinenum())); + } + } + cat_available = true; + } else if (header.GetCategory() == "entity") { + category_ = ENTITY; + // mandatory items + this->TryStoreIdx(E_ID, "id", header); + // optional + indices_[E_TYPE] = header.GetIndex("type"); + indices_[PDBX_DESCRIPTION] = header.GetIndex("pdbx_description"); + cat_available = true; + } else if (header.GetCategory() == "entity_poly") { + category_ = ENTITY_POLY; + // mandatory + this->TryStoreIdx(ENTITY_ID, "entity_id", header); + // optional + indices_[EP_TYPE] = header.GetIndex("type"); + indices_[PDBX_SEQ_ONE_LETTER_CODE] = + header.GetIndex("pdbx_seq_one_letter_code"); + indices_[PDBX_SEQ_ONE_LETTER_CODE_CAN] = + header.GetIndex("pdbx_seq_one_letter_code_can"); + cat_available = true; + } else if (header.GetCategory() == "citation") { + category_ = CITATION; + // mandatory items + this->TryStoreIdx(CITATION_ID, "id", header); + // optional + indices_[ABSTRACT_ID_CAS] = header.GetIndex("abstract_id_CAS"); + indices_[BOOK_ID_ISBN] = header.GetIndex("book_id_ISBN"); + indices_[BOOK_TITLE] = header.GetIndex("book_title"); + indices_[JOURNAL_ABBREV] = header.GetIndex("journal_abbrev"); + indices_[YEAR] = header.GetIndex("year"); + indices_[TITLE] = header.GetIndex("title"); + indices_[JOURNAL_VOLUME] = header.GetIndex("journal_volume"); + indices_[PAGE_FIRST] = header.GetIndex("page_first"); + indices_[PAGE_LAST] = header.GetIndex("page_last"); + indices_[PDBX_DATABASE_ID_DOI] = header.GetIndex("pdbx_database_id_DOI"); + indices_[PDBX_DATABASE_ID_PUBMED] = + header.GetIndex("pdbx_database_id_PubMed"); + cat_available = true; + } else if (header.GetCategory()=="citation_author") { + category_ = CITATION_AUTHOR; + // mandatory items + this->TryStoreIdx(AUTHOR_CITATION_ID, "citation_id", header); + this->TryStoreIdx(AUTHOR_NAME, "name", header); + this->TryStoreIdx(ORDINAL, "ordinal", header); + cat_available = true; + } else if (header.GetCategory() == "exptl") { + category_ = EXPTL; + // mandatory items + this->TryStoreIdx(CITATION_ID, "entry_id", header); + this->TryStoreIdx(METHOD, "method", header); + cat_available = true; + } else if (header.GetCategory() == "refine") { + category_ = REFINE; + // mandatory items + this->TryStoreIdx(REFINE_ENTRY_ID, "entry_id", header); + this->TryStoreIdx(LS_D_RES_HIGH, "ls_d_res_high", header); + this->TryStoreIdx(LS_D_RES_LOW, "ls_d_res_low", header); + cat_available = true; + } else if (header.GetCategory() == "pdbx_struct_assembly") { + category_ = PDBX_STRUCT_ASSEMBLY; + // mandatory items + this->TryStoreIdx(PSA_ID, "id", header); + // optional + indices_[PSA_DETAILS] = header.GetIndex("details"); + //indices_[METHOD_DETAILS] = header.GetIndex("method_details"); + cat_available = true; + } else if (header.GetCategory() == "pdbx_struct_assembly_gen") { + category_ = PDBX_STRUCT_ASSEMBLY_GEN; + // mandatory items + this->TryStoreIdx(ASSEMBLY_ID, "assembly_id", header); + this->TryStoreIdx(ASYM_ID_LIST, "asym_id_list", header); + this->TryStoreIdx(OPER_EXPRESSION, "oper_expression", header); + cat_available = true; + } else if (header.GetCategory() == "pdbx_struct_oper_list") { + category_ = PDBX_STRUCT_OPER_LIST; + // mandatory items + this->TryStoreIdx(PSOL_ID, "id", header); + this->TryStoreIdx(PSOL_TYPE, "type", header); + // optional items + indices_[VECTOR_1] = header.GetIndex("vector[1]"); + indices_[VECTOR_2] = header.GetIndex("vector[2]"); + indices_[VECTOR_3] = header.GetIndex("vector[3]"); + indices_[MATRIX_1_1] = header.GetIndex("matrix[1][1]"); + indices_[MATRIX_1_2] = header.GetIndex("matrix[1][2]"); + indices_[MATRIX_1_3] = header.GetIndex("matrix[1][3]"); + indices_[MATRIX_2_1] = header.GetIndex("matrix[2][1]"); + indices_[MATRIX_2_2] = header.GetIndex("matrix[2][2]"); + indices_[MATRIX_2_3] = header.GetIndex("matrix[2][3]"); + indices_[MATRIX_3_1] = header.GetIndex("matrix[3][1]"); + indices_[MATRIX_3_2] = header.GetIndex("matrix[3][2]"); + indices_[MATRIX_3_3] = header.GetIndex("matrix[3][3]"); + cat_available = true; + } else if (header.GetCategory() == "struct") { + category_ = STRUCT; + // mandatory items + this->TryStoreIdx(STRUCT_ENTRY_ID, "entry_id", header); + // optional items + indices_[PDBX_CASP_FLAG] = header.GetIndex("pdbx_CASP_flag"); + indices_[PDBX_DESCRIPTOR] = header.GetIndex("pdbx_descriptor"); + indices_[PDBX_FORMULA_WEIGHT] = header.GetIndex("pdbx_formula_weight"); + indices_[PDBX_FORMULA_WEIGHT_METHOD] + = header.GetIndex("pdbx_formula_weight_method"); + indices_[PDBX_MODEL_DETAILS] = header.GetIndex("pdbx_model_details"); + indices_[PDBX_MODEL_TYPE_DETAILS] + = header.GetIndex("pdbx_model_type_details"); + indices_[STRUCT_TITLE] = header.GetIndex("title"); + cat_available = true; + } else if (header.GetCategory() == "struct_conf") { + category_ = STRUCT_CONF; + // mandatory items + this->TryStoreIdx(SC_BEG_LABEL_ASYM_ID, "beg_label_asym_id", header); + this->TryStoreIdx(SC_BEG_LABEL_COMP_ID, "beg_label_comp_id", header); + this->TryStoreIdx(SC_BEG_LABEL_SEQ_ID, "beg_label_seq_id", header); + this->TryStoreIdx(SC_CONF_TYPE_ID, "conf_type_id", header); + this->TryStoreIdx(SC_END_LABEL_ASYM_ID, "end_label_asym_id", header); + this->TryStoreIdx(SC_END_LABEL_COMP_ID, "end_label_comp_id", header); + this->TryStoreIdx(SC_END_LABEL_SEQ_ID, "end_label_seq_id", header); + this->TryStoreIdx(SC_ID, "id", header); + // optional items + indices_[SC_BEG_AUTH_ASYM_ID] = header.GetIndex("beg_auth_asym_id"); + indices_[SC_END_AUTH_ASYM_ID] = header.GetIndex("end_auth_asym_id"); + cat_available = true; + } else if (header.GetCategory() == "struct_sheet_range") { + category_ = STRUCT_SHEET_RANGE; + // mandatory items + this->TryStoreIdx(SSR_BEG_LABEL_ASYM_ID, "beg_label_asym_id", header); + this->TryStoreIdx(SSR_BEG_LABEL_COMP_ID, "beg_label_comp_id", header); + this->TryStoreIdx(SSR_BEG_LABEL_SEQ_ID, "beg_label_seq_id", header); + this->TryStoreIdx(SSR_END_LABEL_ASYM_ID, "end_label_asym_id", header); + this->TryStoreIdx(SSR_END_LABEL_COMP_ID, "end_label_comp_id", header); + this->TryStoreIdx(SSR_END_LABEL_SEQ_ID, "end_label_seq_id", header); + this->TryStoreIdx(SSR_SHEET_ID, "sheet_id", header); + this->TryStoreIdx(SSR_ID, "id", header); + // optional items + indices_[SSR_BEG_AUTH_ASYM_ID] = header.GetIndex("beg_auth_asym_id"); + indices_[SSR_END_AUTH_ASYM_ID] = header.GetIndex("end_auth_asym_id"); + cat_available = true; + } else if (header.GetCategory() == "pdbx_database_PDB_obs_spr") { + category_ = PDBX_DATABASE_PDB_OBS_SPR; + // mandatory items + this->TryStoreIdx(DATE, "date", header); + this->TryStoreIdx(PDPOS_ID, "id", header); + this->TryStoreIdx(PDB_ID, "pdb_id", header); + this->TryStoreIdx(REPLACE_PDB_ID, "replace_pdb_id", header); + cat_available = true; + } else if (header.GetCategory() == "struct_ref") { + category_ = STRUCT_REF; + this->TryStoreIdx(SR_ENTITY_ID, "entity_id", header); + this->TryStoreIdx(SR_ID, "id", header); + this->TryStoreIdx(SR_DB_NAME, "db_name", header); + this->TryStoreIdx(SR_DB_CODE, "db_code", header); + indices_[SR_DB_ACCESS]=header.GetIndex("pdbx_db_accession"); + cat_available = true; + } else if (header.GetCategory() == "struct_ref_seq") { + category_ = STRUCT_REF_SEQ; + this->TryStoreIdx(SRS_ALIGN_ID, "align_id", header); + this->TryStoreIdx(SRS_STRUCT_REF_ID, "ref_id", header); + this->TryStoreIdx(SRS_ENT_ALIGN_BEG, "seq_align_beg", header); + this->TryStoreIdx(SRS_ENT_ALIGN_END, "seq_align_end", header); + this->TryStoreIdx(SRS_DB_ALIGN_BEG, "db_align_beg", header); + this->TryStoreIdx(SRS_DB_ALIGN_END, "db_align_end", header); + indices_[SRS_PDBX_STRAND_ID]=header.GetIndex("pdbx_strand_id"); + cat_available = true; + } else if (header.GetCategory()=="struct_ref_seq_dif") { + category_ = STRUCT_REF_SEQ_DIF; + this->TryStoreIdx(SRSD_ALIGN_ID, "align_id", header); + this->TryStoreIdx(SRSD_SEQ_RNUM, "seq_num", header); + this->TryStoreIdx(SRSD_DB_RNUM, "pdbx_seq_db_seq_num", header); + indices_[SRSD_DETAILS]=header.GetIndex("details"); + cat_available = true; + } + category_counts_[category_]++; + return cat_available; +} + +mol::ResNum to_res_num(int num, char ins_code) +{ + return mol::ResNum(num, ins_code==' ' ? '\0' : ins_code); +} + +bool MMCifReader::ParseAtomIdent(const std::vector<StringRef>& columns, + String& auth_chain_name, + String& cif_chain_name, + StringRef& res_name, + mol::ResNum& resnum, + bool& valid_res_num, + StringRef& atom_name, + char& alt_loc) +{ + // ATOM name + atom_name = columns[indices_[LABEL_ATOM_ID]]; + if (profile_.calpha_only) { + if (atom_name != StringRef("CA", 2)) { + return false; + } + } + // CHAIN ID + auth_chain_name = columns[indices_[AUTH_ASYM_ID]].str(); + cif_chain_name = columns[indices_[LABEL_ASYM_ID]].str(); + + if (restrict_chains_.size() > 0 && + restrict_chains_.find(cif_chain_name) == String::npos) { + return false; + } + + std::pair<bool, int> a_num = this->TryGetInt(columns[indices_[AS_ID]], + "atom_site.id", + profile_.fault_tolerant); // unit test + + alt_loc = columns[indices_[LABEL_ALT_ID]][0]; + res_name = columns[indices_[LABEL_COMP_ID]]; + std::pair<bool, int> res_num; + if (columns[indices_[LABEL_SEQ_ID]][0] != '.') { + res_num =this->TryGetInt(columns[indices_[LABEL_SEQ_ID]], + "atom_site.label_seq_id", + profile_.fault_tolerant); // unit test + if (!res_num.first) { // unit test + if (profile_.fault_tolerant) { + return false; + } + } + valid_res_num = true; + } else { + valid_res_num = false; + return true; + } + + resnum = to_res_num(res_num.second, ' '); + + return true; +} + +void MMCifReader::ParseAndAddAtom(const std::vector<StringRef>& columns) +{ + mol::XCSEditor editor=ent_handle_.EditXCS(mol::BUFFERED_EDIT); // potbl + char alt_loc=0; + String auth_chain_name; + String cif_chain_name; + StringRef res_name, atom_name; + mol::ResNum res_num(0); + bool valid_res_num = false; + if (indices_[PDBX_PDB_MODEL_NUM] != -1) { + if (has_model_) { + if (curr_model_ != TryGetInt(columns[indices_[PDBX_PDB_MODEL_NUM]], + "atom_site.pdbx_PDB_model_num")) { + return; + } + } else { + has_model_ = true; + curr_model_ = TryGetInt(columns[indices_[PDBX_PDB_MODEL_NUM]], + "atom_site.pdbx_PDB_model_num"); + } + } + + if (!this->ParseAtomIdent(columns, + auth_chain_name, + cif_chain_name, + res_name, + res_num, + valid_res_num, + atom_name, + alt_loc)) {// unit test + return; + } + Real occ = 1.00f, temp = 0; + geom::Vec3 apos; + + for (int i = CARTN_X; i <= CARTN_Z; ++i) { + std::pair<bool, float> result = this->TryGetFloat(columns[indices_[i]], + "atom_site.cartn_[xyz]", + profile_.fault_tolerant); + if (!result.first) { // unit test + if (profile_.fault_tolerant) { // unit test + return; + } + } + apos[i - CARTN_X] = result.second; + } + + if (indices_[OCCUPANCY] != -1) { // unit test + occ = this->TryGetReal(columns[indices_[OCCUPANCY]], "atom_site.occupancy"); + } + if (indices_[B_ISO_OR_EQUIV] != -1) { // unit test + temp = this->TryGetReal(columns[indices_[B_ISO_OR_EQUIV]], + "atom_site.B_iso_or_equiv"); + } + + // determine element + String s_ele(columns[indices_[TYPE_SYMBOL]].str()); + + String aname(atom_name.str()); + // some postprocessing + LOG_TRACE( "s_chain: [" << cif_chain_name << "]" ); + + // determine chain and residue update + bool update_chain = false; + bool update_residue = false; + if(!curr_chain_) { // unit test + update_chain=true; + update_residue=true; + } else if(curr_chain_.GetName() != cif_chain_name) { // unit test + update_chain=true; + update_residue=true; + } + + if(!curr_residue_) { // unit test + update_residue=true; + } else if (!valid_res_num) { + if (indices_[AUTH_SEQ_ID] != -1 && + indices_[PDBX_PDB_INS_CODE] != -1) { + if (subst_res_id_ != + cif_chain_name + + columns[indices_[AUTH_SEQ_ID]].str() + + columns[indices_[PDBX_PDB_INS_CODE]].str()) { + update_residue=true; + + subst_res_id_ = cif_chain_name + + columns[indices_[AUTH_SEQ_ID]].str() + + columns[indices_[PDBX_PDB_INS_CODE]].str(); + } + } else { + throw IOException(this->FormatDiagnostic(STAR_DIAG_ERROR, + "Missing residue number information", + this->GetCurrentLinenum())); + } + } else if(curr_residue_.GetNumber() != res_num) { // unit test + update_residue=true; + } + + if(update_chain) { // unit test + curr_chain_ = ent_handle_.FindChain(cif_chain_name); + if(!curr_chain_.IsValid()) { // unit test + LOG_DEBUG("new chain " << cif_chain_name); + curr_chain_=editor.InsertChain(cif_chain_name); + curr_chain_.SetStringProp("pdb_auth_chain_name", auth_chain_name); + ++chain_count_; + // store entity id + chain_id_pairs_.push_back(std::pair<mol::ChainHandle,String>(curr_chain_, + columns[indices_[LABEL_ENTITY_ID]].str())); + } + assert(curr_chain_.IsValid()); + } else if (chain_id_pairs_.back().second != // unit test + columns[indices_[LABEL_ENTITY_ID]].str()) { + // check that label_entity_id stays the same + throw IOException(this->FormatDiagnostic(STAR_DIAG_ERROR, + "Change of 'atom_site.label_entity_id' item for chain " + + curr_chain_.GetName() + "! Expected: " + chain_id_pairs_.back().second + + ", found: " + columns[indices_[LABEL_ENTITY_ID]].str() + ".", + this->GetCurrentLinenum())); + } + + if(update_residue) { // unit test + curr_residue_=mol::ResidueHandle(); + if (valid_res_num && profile_.join_spread_atom_records) { // unit test + curr_residue_=curr_chain_.FindResidue(res_num); + } + if (!curr_residue_.IsValid()) { // unit test + LOG_DEBUG("new residue " << res_name << " " << res_num); + if (valid_res_num) { + curr_residue_ = editor.AppendResidue(curr_chain_, + res_name.str(), + res_num); + } else { + curr_residue_ = editor.AppendResidue(curr_chain_, res_name.str()); + } + warned_name_mismatch_=false; + ++residue_count_; + } + assert(curr_residue_.IsValid()); + } + + // finally add atom + LOG_DEBUG("adding atom " << aname << " (" << s_ele << ") @" << apos); + mol::AtomHandle ah; + if (curr_residue_.GetName()!=res_name.str()) { // unit test + if (!profile_.fault_tolerant && alt_loc=='.') { // unit test + std::stringstream ss; + ss << "Residue with number " << res_num << " has more than one name."; + throw IOException(this->FormatDiagnostic(STAR_DIAG_ERROR, + ss.str(), + this->GetCurrentLinenum())); + } + if (!warned_name_mismatch_) { // unit test + if (alt_loc=='.') { // unit test + LOG_WARNING("Residue with number " << res_num << " has more than one " + "name. Ignoring atoms for everything but the first"); + } else { + LOG_WARNING("Residue with number " << res_num + << " contains a microheterogeneity. Everything but atoms " + "for the residue '" << curr_residue_.GetName() + << "' will be ignored"); + } + } + warned_name_mismatch_=true; + return; + } + if (alt_loc!='.') { // unit test + // Check if there is already a atom with the same name. + mol::AtomHandle me=curr_residue_.FindAtom(aname); + if (me.IsValid()) { // unit test + try { + editor.AddAltAtomPos(String(1, alt_loc), me, apos); + } catch (Error) { + LOG_INFO("Ignoring atom alt location since there is already an atom " + "with name " << aname << ", but without an alt loc"); + return; + } + return; + } else { + ah = editor.InsertAltAtom(curr_residue_, aname, + String(1, alt_loc), apos, s_ele); + ++atom_count_; + } + } else { + mol::AtomHandle atom=curr_residue_.FindAtom(aname); + if (atom.IsValid() && !profile_.quack_mode) { // unit test + if (profile_.fault_tolerant) { // unit test + LOG_WARNING("duplicate atom '" << aname << "' in residue " + << curr_residue_); + return; + } + throw IOException(this->FormatDiagnostic(STAR_DIAG_ERROR, + "Duplicate atom '"+aname+ + "' in residue "+ + curr_residue_.GetQualifiedName(), + this->GetCurrentLinenum())); + } + ah = editor.InsertAtom(curr_residue_, aname, apos, s_ele); + ++atom_count_; + } + ah.SetBFactor(temp); + + ah.SetOccupancy(occ); + + // record type + ah.SetHetAtom(indices_[GROUP_PDB] == -1 ? false : + columns[indices_[GROUP_PDB]][0]=='H'); + +} + +void MMCifReader::ParseEntity(const std::vector<StringRef>& columns) +{ + bool store = false; // is it worth storing this record? + MMCifEntityDesc desc; + + // type + if (indices_[E_TYPE] != -1) { + desc.type = mol::ChainTypeFromString(columns[indices_[E_TYPE]]); + store = true; + } + + // description + if (indices_[PDBX_DESCRIPTION] != -1) { + desc.details = columns[indices_[PDBX_DESCRIPTION]].str(); + } else { + desc.details = ""; + } + + if (store) { + desc.seqres = ""; + entity_desc_map_.insert( + MMCifEntityDescMap::value_type(columns[indices_[E_ID]].str(), + desc) + ); + } +} + +void MMCifReader::ParseEntityPoly(const std::vector<StringRef>& columns) +{ + // we assume that the entity cat. ALWAYS comes before the entity_poly cat. + // search entity + MMCifEntityDescMap::iterator edm_it = + entity_desc_map_.find(columns[indices_[ENTITY_ID]].str()); + + if (edm_it == entity_desc_map_.end()) { + throw IOException(this->FormatDiagnostic(STAR_DIAG_ERROR, + "'entity_poly' category defined before 'entity' for id '" + + columns[indices_[ENTITY_ID]].str() + + "' or missing.", + this->GetCurrentLinenum())); + } + + // store type + if (indices_[EP_TYPE] != -1) { + edm_it->second.type = mol::ChainTypeFromString(columns[indices_[EP_TYPE]]); + } + + // store seqres + if (edm_it->second.seqres.length() > 0) { + throw IOException(this->FormatDiagnostic(STAR_DIAG_ERROR, + "entity_poly.pdbx_seq_one_letter_code[_can] clash: sequence for entry '" + + columns[indices_[ENTITY_ID]].str() + + "' is already set to '" + + edm_it->second.seqres + "'.", + this->GetCurrentLinenum())); + } + if (read_seqres_) { + StringRef seqres; + if (seqres_can_) { + if (indices_[PDBX_SEQ_ONE_LETTER_CODE_CAN] != -1) { + seqres=columns[indices_[PDBX_SEQ_ONE_LETTER_CODE_CAN]]; + edm_it->second.seqres = seqres.str_no_whitespace(); + } else { + throw IOException(this->FormatDiagnostic(STAR_DIAG_ERROR, + "'entity_poly.pdbx_seq_one_letter_code_can' not available.'", + this->GetCurrentLinenum())); + } + } else if (indices_[PDBX_SEQ_ONE_LETTER_CODE] != -1) { + seqres=columns[indices_[PDBX_SEQ_ONE_LETTER_CODE]]; + conop::BuilderP builder=conop::Conopology::Instance().GetBuilder("DEFAULT"); + conop::RuleBasedBuilderPtr rbb=dyn_cast<conop::RuleBasedBuilder>(builder); + if (!rbb) { + if (!warned_rule_based_) { + LOG_WARNING("SEQRES import requires the rule-based builder. Ignoring " + "SEQRES records"); + } + warned_rule_based_=true; + return; + } + conop::CompoundLibPtr comp_lib=rbb->GetCompoundLib(); + edm_it->second.seqres = this->ConvertSEQRES(seqres.str_no_whitespace(), + comp_lib); + } else { + throw IOException(this->FormatDiagnostic(STAR_DIAG_ERROR, + "'entity_poly.pdbx_seq_one_letter_code' not available.'", + this->GetCurrentLinenum())); + } + } +} + +String MMCifReader::ConvertSEQRES(const String& seqres, + conop::CompoundLibPtr comp_lib) +{ + String can_seqres; + for (String::const_iterator i=seqres.begin(), e=seqres.end(); i!=e; ++i) { + if (*i=='(') { + bool found_end_paren=false; + String tlc; + tlc.reserve(3); + while ((++i)!=seqres.end()) { + if (*i==')') { + found_end_paren=true; + break; + } + tlc.push_back(*i); + } + if (!found_end_paren) { + throw IOException(this->FormatDiagnostic(STAR_DIAG_ERROR, + "'entity_poly.pdbx_seq_one_letter_code' contains " + "unmatched '('", this->GetCurrentLinenum())); + } + conop::CompoundPtr compound=comp_lib->FindCompound(tlc, + conop::Compound::PDB); + if (!compound) { + if (tlc!="UNK") { + + LOG_WARNING("unknown residue '" << tlc << "' in SEQRES record. " + "Setting one-letter-code to 'X'"); + } + can_seqres.push_back('X'); + continue; + } + if (compound->GetOneLetterCode()=='?') { + can_seqres.push_back('X'); + } else { + can_seqres.push_back(compound->GetOneLetterCode()); + } + + } else { + can_seqres.push_back(*i); + } + } + return can_seqres; +} + +void MMCifReader::ParseCitation(const std::vector<StringRef>& columns) +{ + // create citation object + MMCifInfoCitation cit = MMCifInfoCitation(); + // just add info + cit.SetID(columns[indices_[CITATION_ID]].str()); + if (indices_[ABSTRACT_ID_CAS] != -1) { + cit.SetCAS(columns[indices_[ABSTRACT_ID_CAS]].str()); + } + if (indices_[BOOK_ID_ISBN] != -1) { + cit.SetISBN(columns[indices_[BOOK_ID_ISBN]].str()); + } + if (indices_[BOOK_TITLE] != -1) { + if (columns[indices_[BOOK_TITLE]] != StringRef(".", 1)) { + cit.SetPublishedIn(columns[indices_[BOOK_TITLE]].str()); + } + } + if (indices_[JOURNAL_ABBREV] != -1) { + if (columns[indices_[JOURNAL_ABBREV]] != StringRef(".", 1)) { + if (cit.GetPublishedIn().length() > 0) { + throw IOException(this->FormatDiagnostic(STAR_DIAG_WARNING, + "citation.book_title already occupies the 'published_in' field of this citation, cannot add " + + columns[indices_[JOURNAL_ABBREV]].str() + + ".", + this->GetCurrentLinenum())); + } else { + cit.SetPublishedIn(columns[indices_[JOURNAL_ABBREV]].str()); + } + } + } + if (indices_[JOURNAL_VOLUME] != -1) { + cit.SetVolume(columns[indices_[JOURNAL_VOLUME]].str()); + } + if (indices_[PAGE_FIRST] != -1) { + cit.SetPageFirst(columns[indices_[PAGE_FIRST]].str()); + } + if (indices_[PAGE_LAST] != -1) { + cit.SetPageLast(columns[indices_[PAGE_LAST]].str()); + } + if (indices_[PDBX_DATABASE_ID_DOI] != -1) { + cit.SetDOI(columns[indices_[PDBX_DATABASE_ID_DOI]].str()); + } + if (indices_[PDBX_DATABASE_ID_PUBMED] != -1) { + if (columns[indices_[PDBX_DATABASE_ID_PUBMED]][0]!='?') { + cit.SetPubMed(this->TryGetInt(columns[indices_[PDBX_DATABASE_ID_PUBMED]], + "citation.pdbx_database_id_PubMed")); + } + } + if (indices_[YEAR] != -1) { + if (columns[indices_[YEAR]][0]!='?') { + cit.SetYear(this->TryGetInt(columns[indices_[YEAR]], "citation.year")); + } + } + if (indices_[TITLE] != -1) { + cit.SetTitle(columns[indices_[TITLE]].str()); + } + + // store citation (wo author, yet) + info_.AddCitation(cit); +} + +void MMCifReader::ParseCitationAuthor(const std::vector<StringRef>& columns) +{ + // get/ pack values + MMCifCitationAuthorMap::iterator atm_it; + std::vector<String> at_vec; + std::vector<int> pos_vec; + atm_it = authors_map_.find(columns[indices_[AUTHOR_CITATION_ID]].str()); + if (atm_it != authors_map_.end()) { + at_vec = atm_it->second.second; + pos_vec = atm_it->second.first; + } + at_vec.push_back(columns[indices_[AUTHOR_NAME]].str()); + pos_vec.push_back(this->TryGetInt(columns[indices_[ORDINAL]], + "citation_author.ordinal")); + + // sort new author into right position + std::vector<int>::iterator pos_it; + std::vector<String>::iterator atv_it; + int ti; + String ts; + pos_it = pos_vec.end(); + atv_it = at_vec.end(); + --pos_it; + --atv_it; + for (; pos_it != pos_vec.begin(); --pos_it, --atv_it) { + if (*pos_it < *(pos_it-1)) { + ti = *pos_it; + *pos_it = *(pos_it-1); + *(pos_it-1) = ti; + ts = *atv_it; + *atv_it = *(atv_it-1); + *(atv_it-1) = ts; + } + else { + break; + } + } + + // store new values in map + if (atm_it != authors_map_.end()) { + atm_it->second.second = at_vec; + atm_it->second.first = pos_vec; + } else { + authors_map_.insert(MMCifCitationAuthorMap::value_type( + columns[indices_[AUTHOR_CITATION_ID]].str(), + std::pair<std::vector<int>, std::vector<String> >(pos_vec, at_vec) + )); + } +} + +void MMCifReader::ParseExptl(const std::vector<StringRef>& columns) +{ + info_.SetMethod(columns[indices_[METHOD]].str()); +} + +void MMCifReader::ParseRefine(const std::vector<StringRef>& columns) +{ + StringRef col=columns[indices_[LS_D_RES_HIGH]]; + if (col.size()!=1 || (col[0]!='?' && col[0]!='.')) { + info_.SetResolution(this->TryGetReal(columns[indices_[LS_D_RES_HIGH]], + "refine.ls_d_res_high")); + } +} + +void MMCifReader::ParsePdbxStructAssembly(const std::vector<StringRef>& columns) +{ + if (indices_[PSA_DETAILS] != -1) { + bu_origin_map_.insert(std::pair<String, + String>(columns[indices_[PSA_ID]].str(), + columns[indices_[PSA_DETAILS]].str())); + } else { + bu_origin_map_.insert(std::pair<String, + String>(columns[indices_[PSA_ID]].str(), + "?")); + } +} + +void MMCifReader::StoreExpression(const char* l, const char* s, + bool& is_range, int lborder, + std::vector<String>& single_block) +{ + std::stringstream ss; + int rborder; + + if (l != s) { + if (is_range) { + is_range = false; + rborder = this->TryGetInt(StringRef(l, s-l), + "pdbx_struct_assembly_gen.oper_expression"); + for (lborder += 1; lborder < rborder; lborder++) { + ss << lborder; + single_block.push_back(ss.str()); + ss.str(""); + } + } + single_block.push_back(String(l, s-l)); + } +} + +void MMCifReader::StoreRange(const char*& l, const char* s, bool& is_range, + int& lborder, std::vector<String>& single_block) +{ + if (is_range) { + throw IOException(this->FormatDiagnostic(STAR_DIAG_WARNING, + "pdbx_struct_assembly_gen.oper_expression is missing a right border for a range expression.", + this->GetCurrentLinenum())); + } + is_range = true; + if (l != s) { + lborder = this->TryGetInt(StringRef(l, s-l), + "pdbx_struct_assembly_gen.oper_expression"); + single_block.push_back(String(l, s-l)); + } + l = s+1; +} + +std::vector<std::vector<String> > MMCifReader::UnPackOperExperession(StringRef expression) +{ + std::vector<std::vector<String> > unpacked; + std::vector<String> single_block; + int lborder; + bool is_range = false; + std::stringstream ss; + const char* s = expression.begin(); + const char* e = expression.end(); + const char* l = expression.begin(); + + if (*s == '(') { + ++s; + ++l; + // multiple blocks + while (s != e) { + if (*s == ',') { + StoreExpression(l, s, is_range, lborder, single_block); + l = s+1; + } else if (*s == '-') { + StoreRange(l, s, is_range, lborder, single_block); + } else if (*s == '(') { + ++l; + } else if (*s == ')') { + StoreExpression(l, s, is_range, lborder, single_block); + l = s+1; + if (single_block.size() > 0) { + unpacked.push_back(single_block); + } + single_block.clear(); + } + ++s; + } + } else { + // single block + while (s != e) { + if (*s == ',') { + StoreExpression(l, s, is_range, lborder, single_block); + l = s+1; + } else if (*s == '-') { + StoreRange(l, s, is_range, lborder, single_block); + } + ++s; + } + StoreExpression(l, s, is_range, lborder, single_block); + + if (is_range) { + throw IOException(this->FormatDiagnostic(STAR_DIAG_WARNING, + "pdbx_struct_assembly_gen.oper_expression is missing a right border for a range expression.", + this->GetCurrentLinenum())); + } + unpacked.push_back(single_block); + } + + return unpacked; +} + +void MMCifReader::ParsePdbxStructAssemblyGen(const std::vector<StringRef>& columns) +{ + MMCifBioUAssembly assembly; + assembly.biounit = MMCifInfoBioUnit(); + + assembly.biounit.SetDetails(columns[indices_[ASSEMBLY_ID]].str()); + + std::vector<StringRef> tmp_chains=columns[indices_[ASYM_ID_LIST]].split(','); + std::vector<StringRef>::const_iterator tc_it; + for (tc_it = tmp_chains.begin(); tc_it != tmp_chains.end(); ++tc_it) { + assembly.biounit.AddChain(tc_it->str()); + } + + assembly.operations = + this->UnPackOperExperession(columns[indices_[OPER_EXPRESSION]]); + + bu_assemblies_.push_back(assembly); +} + +void MMCifReader::ParsePdbxStructOperList(const std::vector<StringRef>& columns) +{ + MMCifInfoTransOpPtr op(new MMCifInfoTransOp); + + op->SetID(columns[indices_[PSOL_ID]].str()); + op->SetType(columns[indices_[PSOL_TYPE]].str()); + + if ((indices_[VECTOR_1] != -1)&& + (indices_[VECTOR_2] != -1)&& + (indices_[VECTOR_3] != -1)) { + op->SetVector(this->TryGetReal(columns[indices_[VECTOR_1]], + "pdbx_struct_oper_list.vector[1]"), + this->TryGetReal(columns[indices_[VECTOR_2]], + "pdbx_struct_oper_list.vector[2]"), + this->TryGetReal(columns[indices_[VECTOR_3]], + "pdbx_struct_oper_list.vector[3]")); + } + + if ((indices_[MATRIX_1_1] != -1)&& + (indices_[MATRIX_1_2] != -1)&& + (indices_[MATRIX_1_3] != -1)&& + (indices_[MATRIX_2_1] != -1)&& + (indices_[MATRIX_2_2] != -1)&& + (indices_[MATRIX_2_3] != -1)&& + (indices_[MATRIX_3_1] != -1)&& + (indices_[MATRIX_3_2] != -1)&& + (indices_[MATRIX_3_3] != -1)) { + op->SetMatrix(this->TryGetReal(columns[indices_[MATRIX_1_1]], + "pdbx_struct_oper_list.matrix[1][1]"), + this->TryGetReal(columns[indices_[MATRIX_1_2]], + "pdbx_struct_oper_list.matrix[1][2]"), + this->TryGetReal(columns[indices_[MATRIX_1_3]], + "pdbx_struct_oper_list.matrix[1][3]"), + this->TryGetReal(columns[indices_[MATRIX_2_1]], + "pdbx_struct_oper_list.matrix[2][1]"), + this->TryGetReal(columns[indices_[MATRIX_2_2]], + "pdbx_struct_oper_list.matrix[2][2]"), + this->TryGetReal(columns[indices_[MATRIX_2_3]], + "pdbx_struct_oper_list.matrix[2][3]"), + this->TryGetReal(columns[indices_[MATRIX_3_1]], + "pdbx_struct_oper_list.matrix[3][1]"), + this->TryGetReal(columns[indices_[MATRIX_3_2]], + "pdbx_struct_oper_list.matrix[3][2]"), + this->TryGetReal(columns[indices_[MATRIX_3_3]], + "pdbx_struct_oper_list.matrix[3][3]")); + } + + info_.AddOperation(op); +} + +void MMCifReader::ParseStruct(const std::vector<StringRef>& columns) +{ + MMCifInfoStructDetails details = MMCifInfoStructDetails(); + + details.SetEntryID(columns[indices_[STRUCT_ENTRY_ID]].str()); + + if (indices_[STRUCT_TITLE] != -1) { + details.SetTitle(columns[indices_[STRUCT_TITLE]].str()); + } + + if ((indices_[PDBX_CASP_FLAG] != -1) && + (columns[indices_[PDBX_CASP_FLAG]][0] != '?')) { + details.SetCASPFlag(columns[indices_[PDBX_CASP_FLAG]][0]); + } + + if (indices_[PDBX_DESCRIPTOR] != -1) { + details.SetDescriptor(columns[indices_[PDBX_DESCRIPTOR]].str()); + } + + if (indices_[PDBX_FORMULA_WEIGHT] != -1) { + details.SetMass(this->TryGetReal(columns[indices_[PDBX_FORMULA_WEIGHT]], + "struct.pdbx_formula_weight")); + } + + if (indices_[PDBX_FORMULA_WEIGHT_METHOD] != -1) { + details.SetMassMethod(columns[indices_[PDBX_FORMULA_WEIGHT_METHOD]].str()); + } + + if ((indices_[PDBX_MODEL_DETAILS] != -1) && + (columns[indices_[PDBX_MODEL_DETAILS]][0] != '?')) { + details.SetModelDetails(columns[indices_[PDBX_MODEL_DETAILS]].str()); + } + + if ((indices_[PDBX_MODEL_TYPE_DETAILS] != -1) && + (columns[indices_[PDBX_MODEL_TYPE_DETAILS]][0] != '?')) { + details.SetModelTypeDetails( + columns[indices_[PDBX_MODEL_TYPE_DETAILS]].str()); + } + + info_.SetStructDetails(details); +} + +MMCifReader::MMCifSecStructElement MMCifReader::DetermineSecStructType( + const StringRef& type) const +{ + if (type == StringRef("HELX_P", 6)) { + return MMCIF_HELIX; + } else if (type == StringRef("HELX_OT_P", 9)) { + return MMCIF_HELIX; + } + else if (type == StringRef("HELX_RH_P", 9)) { + return MMCIF_HELIX; + } + else if (type == StringRef("HELX_RH_OT_P", 12)) { + return MMCIF_HELIX; + } + else if (type == StringRef("HELX_RH_AL_P", 12)) { + return MMCIF_HELIX; + } + else if (type == StringRef("HELX_RH_GA_P", 12)) { + return MMCIF_HELIX; + } + else if (type == StringRef("HELX_RH_OM_P", 12)) { + return MMCIF_HELIX; + } + else if (type == StringRef("HELX_RH_PI_P", 12)) { + return MMCIF_HELIX; + } + else if (type == StringRef("HELX_RH_27_P", 12)) { + return MMCIF_HELIX; + } + else if (type == StringRef("HELX_RH_3T_P", 12)) { + return MMCIF_HELIX; + } + else if (type == StringRef("HELX_RH_PP_P", 12)) { + return MMCIF_HELIX; + } + else if (type == StringRef("HELX_LH_P", 9)) { + return MMCIF_HELIX; + } + else if (type == StringRef("HELX_LH_OT_P", 12)) { + return MMCIF_HELIX; + } + else if (type == StringRef("HELX_LH_AL_P", 12)) { + return MMCIF_HELIX; + } + else if (type == StringRef("HELX_LH_GA_P", 12)) { + return MMCIF_HELIX; + } + else if (type == StringRef("HELX_LH_OM_P", 12)) { + return MMCIF_HELIX; + } + else if (type == StringRef("HELX_LH_PI_P", 12)) { + return MMCIF_HELIX; + } + else if (type == StringRef("HELX_LH_27_P", 12)) { + return MMCIF_HELIX; + } + else if (type == StringRef("HELX_LH_3T_P", 12)) { + return MMCIF_HELIX; + } + else if (type == StringRef("HELX_LH_PP_P", 12)) { + return MMCIF_HELIX; + } + else if (type == StringRef("HELX_N", 6)) { + return MMCIF_HELIX; + } + else if (type == StringRef("HELX_OT_N", 9)) { + return MMCIF_HELIX; + } + else if (type == StringRef("HELX_RH_N", 9)) { + return MMCIF_HELIX; + } + else if (type == StringRef("HELX_RH_OT_N", 12)) { + return MMCIF_HELIX; + } + else if (type == StringRef("HELX_RH_A_N", 11)) { + return MMCIF_HELIX; + } + else if (type == StringRef("HELX_RH_B_N", 11)) { + return MMCIF_HELIX; + } + else if (type == StringRef("HELX_RH_Z_N", 11)) { + return MMCIF_HELIX; + } + else if (type == StringRef("HELX_LH_N", 9)) { + return MMCIF_HELIX; + } + else if (type == StringRef("HELX_LH_OT_N", 12)) { + return MMCIF_HELIX; + } + else if (type == StringRef("HELX_LH_A_N", 11)) { + return MMCIF_HELIX; + } + else if (type == StringRef("HELX_LH_B_N", 11)) { + return MMCIF_HELIX; + } + else if (type == StringRef("HELX_LH_Z_N", 11)) { + return MMCIF_HELIX; + } + else if (type == StringRef("TURN_P", 6)) { + return MMCIF_TURN; + } + else if (type == StringRef("TURN_OT_P", 9)) { + return MMCIF_TURN; + } + else if (type == StringRef("TURN_TY1_P", 10)) { + return MMCIF_TURN; + } + else if (type == StringRef("TURN_TY1P_P", 11)) { + return MMCIF_TURN; + } + else if (type == StringRef("TURN_TY2_P", 10)) { + return MMCIF_TURN; + } + else if (type == StringRef("TURN_TY2P_P", 11)) { + return MMCIF_TURN; + } + else if (type == StringRef("TURN_TY3_P", 10)) { + return MMCIF_TURN; + } + else if (type == StringRef("TURN_TY3P_P", 11)) { + return MMCIF_TURN; + } + else if (type == StringRef("STRN", 4)) { + return MMCIF_STRAND; + } + + throw IOException(this->FormatDiagnostic(STAR_DIAG_ERROR, + "Unknown secondary structure class found: "+ + type.str(), + this->GetCurrentLinenum())); +} + +void MMCifReader::ParseStructConf(const std::vector<StringRef>& columns) +{ + StringRef chain_name; + int s_res_num; + int e_res_num; + + // fetch chain name, first + if(auth_chain_id_) { + if (indices_[SC_BEG_AUTH_ASYM_ID] != -1) { + chain_name = columns[indices_[SC_BEG_AUTH_ASYM_ID]]; + } else { + throw IOException(this->FormatDiagnostic(STAR_DIAG_ERROR, +"Chain name by author requested but 'struct_conf.beg_auth_asym_id' is not set.", + this->GetCurrentLinenum())); + } + } else { + chain_name = columns[indices_[SC_BEG_LABEL_ASYM_ID]]; + } + + if (restrict_chains_.size() == 0 || + restrict_chains_.find(chain_name.str()) != String::npos) { + // fetch start and end + s_res_num = this->TryGetInt(columns[indices_[SC_BEG_LABEL_SEQ_ID]], + "struct_conf.beg_label_seq_id"); + e_res_num = this->TryGetInt(columns[indices_[SC_END_LABEL_SEQ_ID]], + "struct_conf.end_label_seq_id"); + MMCifHSEntry hse = {to_res_num(s_res_num, ' '), + to_res_num(e_res_num, ' '), + chain_name.str()}; + + MMCifSecStructElement type = + DetermineSecStructType(columns[indices_[SC_CONF_TYPE_ID]]); + if (type == MMCIF_HELIX) { + helix_list_.push_back(hse); + } else if (type == MMCIF_STRAND) { + strand_list_.push_back(hse); + } + } +} + +void MMCifReader::ParseStructSheetRange(const std::vector<StringRef>& columns) +{ + StringRef chain_name; + int s_res_num; + int e_res_num; + + if(auth_chain_id_) { + if (indices_[SSR_BEG_AUTH_ASYM_ID] != -1) { + chain_name = columns[indices_[SSR_BEG_AUTH_ASYM_ID]]; + } else { + throw IOException(this->FormatDiagnostic(STAR_DIAG_ERROR, +"Chain name by author requested but 'struct_sheet_range.beg_auth_asym_id' is not set.", + this->GetCurrentLinenum())); + } + } else { + chain_name = columns[indices_[SSR_BEG_LABEL_ASYM_ID]]; + } + + // restrict_chains feature not unit tested, since its about to be changed in + // the future + if (restrict_chains_.size() == 0 || + restrict_chains_.find(chain_name.str()) != String::npos) { + + s_res_num = this->TryGetInt(columns[indices_[SSR_BEG_LABEL_SEQ_ID]], + "struct_sheet_range.beg_label_seq_id"); + e_res_num = this->TryGetInt(columns[indices_[SSR_END_LABEL_SEQ_ID]], + "struct_sheet_range.end_label_seq_id"); + + MMCifHSEntry hse = {to_res_num(s_res_num, ' '), + to_res_num(e_res_num, ' '), + chain_name.str()}; + strand_list_.push_back(hse); + } +} + +void MMCifReader::ParsePdbxDatabasePdbObsSpr(const std::vector<StringRef>& + columns) +{ + MMCifInfoObsolete obs_data = MMCifInfoObsolete(); + + obs_data.SetDate(columns[indices_[DATE]].str()); + obs_data.SetID(columns[indices_[PDPOS_ID]]); + obs_data.SetPDBID(columns[indices_[PDB_ID]].str()); + obs_data.SetReplacedPDBID(columns[indices_[REPLACE_PDB_ID]].str()); + + info_.SetObsoleteInfo(obs_data); +} + +void MMCifReader::OnDataRow(const StarLoopDesc& header, + const std::vector<StringRef>& columns) +{ + switch(category_) { + case ATOM_SITE: + LOG_TRACE("processing atom_site entry"); + this->ParseAndAddAtom(columns); + break; + case ENTITY: + LOG_TRACE("processing entity entry"); + this->ParseEntity(columns); + break; + case ENTITY_POLY: + LOG_TRACE("processing entity_poly entry"); + this->ParseEntityPoly(columns); + break; + case CITATION: + LOG_TRACE("processing citation entry"); + this->ParseCitation(columns); + break; + case CITATION_AUTHOR: + LOG_TRACE("processing citation_author entry") + this->ParseCitationAuthor(columns); + break; + case EXPTL: + LOG_TRACE("processing exptl entry") + this->ParseExptl(columns); + break; + case REFINE: + LOG_TRACE("processing refine entry") + this->ParseRefine(columns); + break; + case PDBX_STRUCT_ASSEMBLY: + LOG_TRACE("processing pdbx_struct_assembly entry") + this->ParsePdbxStructAssembly(columns); + break; + case PDBX_STRUCT_ASSEMBLY_GEN: + LOG_TRACE("processing pdbx_struct_assembly_gen entry") + this->ParsePdbxStructAssemblyGen(columns); + break; + case PDBX_STRUCT_OPER_LIST: + LOG_TRACE("processing pdbx_struct_oper_list entry") + this->ParsePdbxStructOperList(columns); + break; + case STRUCT: + LOG_TRACE("processing struct entry") + this->ParseStruct(columns); + break; + case STRUCT_CONF: + LOG_TRACE("processing struct_conf entry") + this->ParseStructConf(columns); + break; + case STRUCT_SHEET_RANGE: + LOG_TRACE("processing struct_sheet_range entry") + this->ParseStructSheetRange(columns); + break; + case PDBX_DATABASE_PDB_OBS_SPR: + LOG_TRACE("processing pdbx_database_PDB_obs_spr entry") + this->ParsePdbxDatabasePdbObsSpr(columns); + break; + case STRUCT_REF: + LOG_TRACE("processing struct_ref entry"); + this->ParseStructRef(columns); + break; + case STRUCT_REF_SEQ: + LOG_TRACE("processing struct_ref entry"); + this->ParseStructRefSeq(columns); + break; + case STRUCT_REF_SEQ_DIF: + LOG_TRACE("processing struct_ref entry"); + this->ParseStructRefSeqDif(columns); + break; + default: + throw IOException(this->FormatDiagnostic(STAR_DIAG_ERROR, + "Uncatched category '"+ header.GetCategory() +"' found.", + this->GetCurrentLinenum())); + return; + } +} + +void MMCifReader::AssignSecStructure(mol::EntityHandle ent) +{ + for (MMCifHSVector::const_iterator i=helix_list_.begin(), e=helix_list_.end(); + i!=e; ++i) { + mol::ChainHandle chain = ent.FindChain(i->chain_name); + if (!chain.IsValid()) { + LOG_INFO("ignoring helix record for unknown chain " + i->chain_name); + continue; + } + mol::SecStructure alpha(mol::SecStructure::ALPHA_HELIX); + // some PDB files contain helix/strand entries that are adjacent to each + // other. To avoid visual artifacts, we effectively shorten the first of + // the two secondary structure segments to insert one residue of coil + // conformation. + mol::ResNum start = i->start, end = i->end; + if (helix_list_.end() != i+1 && // unit test + (*(i+1)).start.GetNum() <= end.GetNum()+1 && + (*(i+1)).end.GetNum() > end.GetNum()) { + end = mol::ResNum((*(i+1)).start.GetNum()-2); + } + chain.AssignSecondaryStructure(alpha, start, end); + } + + for (MMCifHSVector::const_iterator i=strand_list_.begin(), + e=strand_list_.end(); + i!=e; ++i) { + mol::ChainHandle chain=ent.FindChain(i->chain_name); + if (!chain.IsValid()) { + LOG_INFO("ignoring strand record for unknown chain " + i->chain_name); + continue; + } + mol::SecStructure extended(mol::SecStructure::EXTENDED); + mol::ResNum start = i->start, end = i->end; + // see comment for helix assignment + if (strand_list_.end() != i+1 && // unit test + (*(i+1)).start.GetNum() <= end.GetNum()+1 && + (*(i+1)).end.GetNum() > end.GetNum()) { + end=mol::ResNum((*(i+1)).start.GetNum()-2); + } + chain.AssignSecondaryStructure(extended, start, end); + } +} + + +void MMCifReader::ParseStructRef(const std::vector<StringRef>& columns) +{ + String ent_id=columns[indices_[SR_ENTITY_ID]].str(); + String db_name=columns[indices_[SR_DB_NAME]].str(); + String db_code=columns[indices_[SR_DB_CODE]].str(); + String id=columns[indices_[SR_ID]].str(); + String db_access; + if (indices_[SR_DB_ACCESS]!=-1) { + db_access=columns[indices_[SR_DB_ACCESS]].str(); + } + MMCifInfoStructRefPtr sr(new MMCifInfoStructRef(id, ent_id, db_name, + db_code, db_access)); + struct_refs_.push_back(sr); +} + +void MMCifReader::ParseStructRefSeq(const std::vector<StringRef>& columns) +{ + String aln_id=columns[indices_[SRS_ALIGN_ID]].str(); + String sr_id=columns[indices_[SRS_STRUCT_REF_ID]].str(); + String chain_name; + if (indices_[SRS_PDBX_STRAND_ID]!=-1) { + chain_name=columns[indices_[SRS_PDBX_STRAND_ID]].str(); + } + std::pair<bool,int> dbbeg=this->TryGetInt(columns[indices_[SRS_DB_ALIGN_BEG]], + "_struct_ref_seq.db_align_beg", + profile_.fault_tolerant); + std::pair<bool,int> dbend=this->TryGetInt(columns[indices_[SRS_DB_ALIGN_END]], + "_struct_ref_seq.db_align_end", + profile_.fault_tolerant); + std::pair<bool,int> entbeg=this->TryGetInt(columns[indices_[SRS_ENT_ALIGN_BEG]], + "_struct_ref_seq.seq_align_beg", + profile_.fault_tolerant); + std::pair<bool,int> entend=this->TryGetInt(columns[indices_[SRS_ENT_ALIGN_END]], + "_struct_ref_seq.seq_align_END", + profile_.fault_tolerant); + if (!(dbbeg.first && dbend.first && entbeg.first && entend.first)) { + return; + } + bool found=false; + for (MMCifInfoStructRefs::iterator i=struct_refs_.begin(), + e=struct_refs_.end(); i!=e; ++i) { + if ((*i)->GetID()==sr_id) { + (*i)->AddAlignedSeq(aln_id, chain_name, entbeg.second, entend.second, + dbbeg.second, dbend.second); + found=true; + break; + } + } + if (!found) { + if (profile_.fault_tolerant) { + LOG_ERROR("struct_ref_seq.ref_id points to inexistent struct_ref '" + << sr_id << "'"); + return; + } + std::stringstream ss; + ss << "struct_ref_seq.ref_id points to inexistent struct_ref '"; + ss << sr_id << "'"; + throw IOException(ss.str()); + } +} + +void MMCifReader::ParseStructRefSeqDif(const std::vector<StringRef>& columns) +{ + String aln_id=columns[indices_[SRSD_ALIGN_ID]].str(); + std::pair<bool,int> db_rnum(true, -1); + if (!is_undef(columns[indices_[SRSD_DB_RNUM]])) { + db_rnum=this->TryGetInt(columns[indices_[SRSD_DB_RNUM]], + "_struct_ref_seq_dif.pdbx_seq_db_seq_num", + profile_.fault_tolerant); + + } + std::pair<bool,int> seq_rnum(true, -1); + if (!is_undef(columns[indices_[SRSD_SEQ_RNUM]])) { + seq_rnum=this->TryGetInt(columns[indices_[SRSD_SEQ_RNUM]], + "_struct_ref_seq_dif.seq_num", + profile_.fault_tolerant); + + } + if (!seq_rnum.first || !db_rnum.first) { + return; + } + String details; + if (indices_[SRSD_DETAILS]!=-1) { + details=columns[indices_[SRSD_DETAILS]].str(); + } + bool found=false; + for (MMCifInfoStructRefs::iterator i=struct_refs_.begin(), + e=struct_refs_.end(); i!=e; ++i) { + if (MMCifInfoStructRefSeqPtr s=(*i)->GetAlignedSeq(aln_id)) { + s->AddDif(seq_rnum.second, db_rnum.second, details); + found=true; + break; + } + } + if (!found) { + if (profile_.fault_tolerant) { + LOG_ERROR("struct_ref_seq_dif.align_id points to inexistent " + "struct_ref_seq '" << aln_id << "'"); + return; + } + std::stringstream ss; + ss << "struct_ref_seq.ref_id points to inexistent struct_ref '"; + ss << aln_id << "'"; + throw IOException(ss.str()); + } +} + +void MMCifReader::OnEndData() +{ + mol::XCSEditor editor=ent_handle_.EditXCS(mol::BUFFERED_EDIT); + + // process chain types + std::vector<std::pair<mol::ChainHandle, String> >::const_iterator css; + MMCifEntityDescMap::const_iterator edm_it; + for (css = chain_id_pairs_.begin(); css != chain_id_pairs_.end(); ++css) { + edm_it = entity_desc_map_.find(css->second); + + if (edm_it != entity_desc_map_.end()) { + editor.SetChainType(css->first, edm_it->second.type); + editor.SetChainDescription(css->first, edm_it->second.details); + if (edm_it->second.seqres.length() > 0) { + seqres_.AddSequence(seq::CreateSequence(css->first.GetName(), + edm_it->second.seqres)); + } else if (edm_it->second.type!=mol::CHAINTYPE_WATER) { + // mark everything that doesn't have SEQRES as ligand and isn't of type + // water as ligand + mol::ChainHandle chain=css->first; + mol::ResidueHandleList residues=chain.GetResidueList(); + for (mol::ResidueHandleList::iterator + i=residues.begin(), e=residues.end(); i!=e; ++i) { + (*i).SetIsLigand(true); + } + } + } else { + LOG_WARNING("No entity description found for atom_site.label_entity_id '" + << css->second << "'"); + } + } + + // process citations (couple with authors + // iterate citations + MMCifCitationAuthorMap::const_iterator atm_it; + for (atm_it = authors_map_.begin(); atm_it != authors_map_.end(); ++atm_it) { + info_.AddAuthorsToCitation(StringRef(atm_it->first.c_str(), + atm_it->first.length()), + atm_it->second.second); + } + + bool found; + MMCifBioUAssemblyVector::iterator bua_it; + std::vector<std::vector<String> >::const_iterator aol_it; + std::vector<String>::const_iterator aob_it; + std::vector<MMCifInfoTransOpPtr> operation_list; + std::map<String, String>::const_iterator buom_it; + std::vector<MMCifInfoTransOpPtr> operations = info_.GetOperations(); + info_.SetStructRefs(struct_refs_); + std::vector<MMCifInfoTransOpPtr>::const_iterator buop_it; + for (bua_it = bu_assemblies_.begin(); + bua_it != bu_assemblies_.end(); + ++bua_it) { + // pair with pdbx_struct_assembly entry + buom_it = bu_origin_map_.find(bua_it->biounit.GetDetails()); + if (buom_it == bu_origin_map_.end()) { + throw IOException(this->FormatDiagnostic(STAR_DIAG_ERROR, + "No pdbx_struct_assembly.id '"+ + bua_it->biounit.GetDetails() + + "' found as requested by pdbx_struct_assembly_gen.")); + } + bua_it->biounit.SetDetails(buom_it->second); + + // pair with pdbx_struct_oper_list + for (aol_it = bua_it->operations.begin(); + aol_it != bua_it->operations.end(); + ++aol_it) { + operation_list.clear(); + for (aob_it = aol_it->begin(); aob_it != aol_it->end(); aob_it++) { + found = false; + for (buop_it = operations.begin(); + buop_it != operations.end(); + ++buop_it) { + if ((*buop_it)->GetID() == *aob_it) { + operation_list.push_back(*buop_it); + found = true; + break; + } + } + if (!found) { + throw IOException(this->FormatDiagnostic(STAR_DIAG_ERROR, + "No pdbx_struct_oper_list.id '"+ + *aob_it + + "' found as requested by pdbx_struct_assembly_gen.")); + } + } + bua_it->biounit.AddOperations(operation_list); + } + info_.AddBioUnit(bua_it->biounit); + } + bu_assemblies_.clear(); + + // create secondary structure from struct_conf info + this->AssignSecStructure(ent_handle_); + + LOG_INFO("imported " + << chain_count_ << " chains, " + << residue_count_ << " residues, " + << atom_count_ << " atoms;" + << helix_list_.size() << " helices and " + << strand_list_.size() << " strands"); +} + +}} diff --git a/modules/io/src/mol/mmcif_reader.hh b/modules/io/src/mol/mmcif_reader.hh new file mode 100644 index 0000000000000000000000000000000000000000..e9ff3b893f0e8ade4cce29838b79fb8ab89cf871 --- /dev/null +++ b/modules/io/src/mol/mmcif_reader.hh @@ -0,0 +1,598 @@ +//------------------------------------------------------------------------------ +// This file is part of the OpenStructure project <www.openstructure.org> +// +// Copyright (C) 2008-2011 by the OpenStructure authors +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License as published by the Free +// Software Foundation; either version 3.0 of the License, or (at your option) +// any later version. +// This library is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this library; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +//------------------------------------------------------------------------------ +#ifndef OST_MMCIF_READER_HH +#define OST_MMCIF_READER_HH + +#include <map> + +#include <ost/geom/geom.hh> +#include <ost/seq/sequence_list.hh> +#include <ost/mol/residue_handle.hh> +#include <ost/mol/chain_type.hh> +#include <ost/conop/compound_lib.hh> +#include <ost/io/mol/io_profile.hh> +#include <ost/io/io_exception.hh> +#include <ost/io/mol/star_parser.hh> +#include <ost/io/mol/mmcif_info.hh> + +namespace ost { namespace io { + +/// \brief reader for the mmcif file format +/// +/// \section mmcif_format mmcif format description/ coverage +/// +/// mmcif is an instance of the \link StarParser STAR format\endlink to store +/// entries of the PDB. The following data categories should be covered by this +/// reader: +/// +/// \li atom_site +/// \li entity +/// \li entity_poly +/// \li citation +/// \li citation_author +/// \li exptl +/// \li refine +/// \li pdbx_struct_assembly +/// \li pdbx_struct_assembly_gen +/// \li pdbx_struct_oper_list +/// \li struct +/// \li struct_conf +/// \li struct_sheet_range +/// \li pdbx_database_PDB_obs_spr +class DLLEXPORT_OST_IO MMCifReader : public StarParser { +public: + /// \brief create a MMCifReader + /// + /// \param stream input stream + MMCifReader(std::istream& stream, mol::EntityHandle& ent_handle, + const IOProfile& profile); + + /// \brief create a MMCifReader + /// + /// \param filename input file + MMCifReader(const String& filename, mol::EntityHandle& ent_handle, + const IOProfile& profile); + + /// \brief Initialise the reader. + /// + /// \param loc Location of the file + void Init(); + + /// \brief Set up a fresh instance + void ClearState(); + + /// \brief Set names of restricted chains for the reader. + /// + /// \param restrict_chains chain name + void SetRestrictChains(const String& restrict_chains); + + /// \brief Toggle reading of canonical sequence residues + /// (entity_poly.pdbx_seq_one_letter_code_can instead of + /// entity_poly.pdbx_seq_one_letter_code). This flag is exclusive. + /// + /// \param flag True for reading canonical sequences. + void SetReadCanonicalSeqRes(bool flag) + { + seqres_can_ = flag; + } + + const String& GetRestrictChains() const + { + return restrict_chains_; + } + + /// \brief Enable or disable reading of auth_chain_id instead aof label_chain + /// id (default) + /// + /// \param id enable (true) or disable (false) reading of auth_chain_id. + void SetAuthChainID(bool id) + { + auth_chain_id_ = id; + } + + /// \brief check mmcif input to be read. Substitutional function for + /// \link StarParser StarParser\endlink. + /// + /// \param data_name value of the data_ tag + /// + /// \return true, if the blockcode (PDB id) is valid, false otherwise + virtual bool OnBeginData(const StringRef& data_name); + + /// \brief check if a current loop is to be parsed + /// + /// \param header categories of the upcoming loop block + /// + /// \return bool + virtual bool OnBeginLoop(const StarLoopDesc& header); // tested + + /// \brief read a row of data + /// + /// \param header categories and items + /// \param columns data + virtual void OnDataRow(const StarLoopDesc& header, + const std::vector<StringRef>& columns); + + /// \brief Finalise parsing. + virtual void OnEndData(); + + /// \brief Return sequences + /// + /// \return List of sequences + seq::SequenceList GetSeqRes() const { + return seqres_; + } + + /// \brief Toggle reading of SEQRES + /// + /// \param flag True enables, False disables reading SEQRES + void SetReadSeqRes(bool flag) + { + read_seqres_ = flag; + } + + /// \brief Check if reading of SEQRES is enabled + /// + /// \return True if reading of SEQRES is enabled + bool GetReadSeqRes() const + { + return read_seqres_; + } + + /// \brief Get additional information of the mmCIF file. + /// + /// \return MMCitfInfo object + const MMCifInfo& GetInfo() { return info_; } + +protected: + /// \brief Store an item index from loop header in preparation for reading a + /// row. Throws an exception if the item does not exist. + /// + /// \param mapping position the item index is stored at + /// \param item exact item name to fetch + /// \param header loop header to pull index from + void TryStoreIdx(const int mapping, + const String& item, + const StarLoopDesc& header) + { + indices_[mapping] = header.GetIndex(item); + + if (indices_[mapping] == -1) { + throw IOException(this->FormatDiagnostic(STAR_DIAG_ERROR, + "No item '" + item + + "' found in '" + + header.GetCategory()+ + "' header", + this->GetCurrentLinenum())); + } + } // tested + + /// \brief Check a PDB id to be of length 4 and start with a digit + /// + /// \param pdbid putative PDB id + /// + /// \return true for a valid id, false otherwise + bool IsValidPDBIdent(const StringRef& pdbid); + + /// \brief fetch values identifying atoms + /// + /// \param[in] columns data row + /// \param[out] chain_name takes atom_site.label_asym_id or, if + /// auth_chain_id_ is set, atom_site.auth_asym_id as a chain name + /// \param[out] res_name fetches atom_site.label_comp_id + /// \param[out] resnum gets atom_site.label_seq_id if available, consecutive + /// numbers, otherwise + /// \param[out] valid_res_num shows if we have a valid residue number or if + /// we have to invent our own + /// \param[out] atom_name corresponds to label_atom_id + /// \param[out] alt_loc gets first letter of atom_site.label_alt_id + bool ParseAtomIdent(const std::vector<StringRef>& columns, + String& auth_chain_name, + String& cif_chain_name, + StringRef& res_name, + mol::ResNum& resnum, + bool& valid_res_num, + StringRef& atom_name, + char& alt_loc); + + /// \brief Fetch atom information and store it. + /// + /// \param columns data row + void ParseAndAddAtom(const std::vector<StringRef>& columns); + + /// \brief Fetch mmCIF entity information + /// + /// \param columns data row + void ParseEntity(const std::vector<StringRef>& columns); + + /// \brief Fetch mmCIF entity_poly information + /// + /// \param columns data row + void ParseEntityPoly(const std::vector<StringRef>& columns); + + /// \brief Fetch mmCIF citation information + /// + /// \param columns data row + void ParseCitation(const std::vector<StringRef>& columns); + + const MMCifInfoStructRefs& GetStructRefs() const { return struct_refs_; } + /// \brief convert the seqres data item to canonical form. + /// + /// The seqres sequence lists non-standard residues in paranthesis. For + /// proper handling of our sequence classes, these need to be converted to + /// one-letter-codes. Ideally, we would use the canonical SEQRES. This is + /// not possible, however, since the PDB assigns multiple one letter codes + /// to some of the residues. To be consistent, we have to do the conversion on + /// our own. + String ConvertSEQRES(const String& seqres, conop::CompoundLibPtr compound_lib); + /// \brief Fetch mmCIF citation_author information + /// + /// \param columns data row + void ParseCitationAuthor(const std::vector<StringRef>& columns); + + /// \ brief parse a row in the struct_ref category + void ParseStructRef(const std::vector<StringRef>& columns); + + /// \brief parse row in the struct_ref_seq category + void ParseStructRefSeq(const std::vector<StringRef>& columns); + + /// \brief parse row in the struct_ref_seq_dif category + void ParseStructRefSeqDif(const std::vector<StringRef>& columns); + /// \brief Fetch mmCIF exptl information + /// + /// \param columns data row + void ParseExptl(const std::vector<StringRef>& columns); + + /// \brief Fetch mmCIF refine information + /// + /// \param columns data row + void ParseRefine(const std::vector<StringRef>& columns); + + /// \brief Fetch mmCIF pdbx_struct_assembly information + /// + /// \param columns data row + void ParsePdbxStructAssembly(const std::vector<StringRef>& columns); + + /// \brief Fetch mmCIF pdbx_struct_assembly_gen information + /// + /// \param columns data row + void ParsePdbxStructAssemblyGen(const std::vector<StringRef>& columns); + + std::vector<std::vector<String> > UnPackOperExperession(StringRef expression); + + void StoreExpression(const char* l, const char* s, + bool& is_range, int lborder, + std::vector<String>& single_block); + + void StoreRange(const char*& l, const char* s, bool& is_range, int& lborder, + std::vector<String>& single_block); + + /// \brief Fetch mmCIF pdbx_struct_oper_list information + /// + /// \param columns data row + void ParsePdbxStructOperList(const std::vector<StringRef>& columns); + + /// \brief Fetch mmCIF struct information + /// + /// \param columns data row + void ParseStruct(const std::vector<StringRef>& columns); + + /// \brief Fetch mmCIF struct_conf (secondary structure) information + /// + /// \param columns data row + void ParseStructConf(const std::vector<StringRef>& columns); + + /// \brief Fetch mmCIF struct_sheet_range (beta sheets) information + /// + /// \param columns data row + void ParseStructSheetRange(const std::vector<StringRef>& columns); + + /// \brief Fetch mmCIF pdbx_database_PDB_obs_spr information + /// + /// \param columns data row + void ParsePdbxDatabasePdbObsSpr(const std::vector<StringRef>& columns); + + /// \struct types of secondary structure + typedef enum { + MMCIF_HELIX, + MMCIF_STRAND, + MMCIF_TURN + } MMCifSecStructElement; + + /// \brief Check whether an element was classified sheet or helix + /// + /// \param type Type to be classified + MMCifSecStructElement DetermineSecStructType(const StringRef& type) const; + + /// \brief Transform data from struct_conf entry into secondary structure + /// + /// \param ent Entity to assign secondary structure to + void AssignSecStructure(mol::EntityHandle ent); + +private: + /// \enum magic numbers of this class + typedef enum { + PDBID_LEN=4, ///< length of a PDB id + MAX_ITEMS_IN_ROW=18, ///< count for possible items in a loop row + } MMCifMagicNos; + + /// \enum items of the atom_site category + typedef enum { + AUTH_ASYM_ID, ///< chain name by author as in PDB + AS_ID, ///< atom serial id + LABEL_ALT_ID, ///< AltLoc + LABEL_ASYM_ID, ///< chain name by PDB + LABEL_ATOM_ID, + LABEL_COMP_ID, + LABEL_ENTITY_ID, ///< link to category entity + LABEL_SEQ_ID, ///< residue no. + AUTH_SEQ_ID, ///< residue no. by author + TYPE_SYMBOL, ///< chemical element + CARTN_X, ///< Coordinates ||IMPORTANT: This 3 entries have to stay + CARTN_Y, ///< Coordinates ||together for the reader to work! + CARTN_Z, ///< Coordinates || + OCCUPANCY, + B_ISO_OR_EQUIV, + PDBX_PDB_INS_CODE, + GROUP_PDB, ///< record name + PDBX_PDB_MODEL_NUM ///< model no. (especially NMR structures) + } AtomSiteItems; + + /// \enum items of the entity category + typedef enum { + E_ID, ///< unique identifier + E_TYPE, ///< polymer, non-polymer or water + PDBX_DESCRIPTION ///< special aspects of the entity + } EntityItems; + + /// \enum items of the entity_poly category + typedef enum { + ENTITY_ID, ///< pointer to entity.id + EP_TYPE, ///< type of polymer + PDBX_SEQ_ONE_LETTER_CODE, ///< sequence, 1-letter code + PDBX_SEQ_ONE_LETTER_CODE_CAN ///< canonical sequence, 1-letter code + } EntityPolyItems; + + /// \enum items of the citation category + typedef enum { + CITATION_ID, ///< unique identifier + ABSTRACT_ID_CAS, ///< CAS identifier + BOOK_ID_ISBN, ///< ISBN code assigned, if book cited + BOOK_TITLE, ///< title of book storing the citation + JOURNAL_ABBREV, ///< abbreviated journal title for articles + JOURNAL_VOLUME, ///< volume of cited journal + PAGE_FIRST, ///< first page of citation + PAGE_LAST, ///< last page of citation + PDBX_DATABASE_ID_DOI, ///< Document Object Identifier of doi.org + PDBX_DATABASE_ID_PUBMED, ///< Ascession number of PubMed + YEAR, ///< year of the citation + TITLE ///< title of the citation + } CitationItems; + + /// \enum items of the citation_author category + typedef enum { + AUTHOR_CITATION_ID, ///< link to CITATION_ID + AUTHOR_NAME, ///< name of an author + ORDINAL ///< position in author list + } CitationAuthorItems; + + /// \enum items of the exptl category + typedef enum { + EXPTL_ENTRY_ID, ///< identifier + METHOD ///< method of the experiment + } ExptlItems; + + /// \enum items of the refine category + typedef enum { + REFINE_ENTRY_ID, ///< id + LS_D_RES_HIGH, ///< crystal resolution + LS_D_RES_LOW + } RefineItems; + + /// \enum items of the pdbx_struct_assembly category + typedef enum { + PSA_DETAILS, ///< special aspects of the assembly + PSA_ID, ///< unique identifier + METHOD_DETAILS ///< details about assembly computation + } PdbxStructAssemblyItems; + + // \enum items of the struct_ref category + typedef enum { + SR_ENTITY_ID, + SR_ID, + SR_DB_CODE, + SR_DB_NAME, + SR_DB_ACCESS + } StructRefItems; + + /// \enum items of the struct_ref_seq category + typedef enum { + SRS_ALIGN_ID, + SRS_STRUCT_REF_ID, + SRS_PDBX_STRAND_ID, + SRS_DB_ALIGN_BEG, + SRS_DB_ALIGN_END, + SRS_ENT_ALIGN_BEG, + SRS_ENT_ALIGN_END + } StructRefSeqItems; + + /// \enum items of the struct_ref_seq_dif category + typedef enum { + SRSD_ALIGN_ID, + SRSD_SEQ_RNUM, + SRSD_DB_RNUM, + SRSD_DETAILS + } StructRefSeqDifItems; + /// \enum items of the pdbx_struct_assembly_gen category + typedef enum { + ASSEMBLY_ID, ///< link to pdbx_struct_assembly.id + ASYM_ID_LIST, ///< list of chains + OPER_EXPRESSION ///< list of pdbx_struct_oper_list.ids + } PdbxStructAssemblyGenItems; + + /// \enum items of the pdbx_struct_oper_list category + typedef enum { + PSOL_ID, ///< unique identifier + PSOL_TYPE, ///< type of operation + VECTOR_1, ///< vector component + VECTOR_2, ///< vector component + VECTOR_3, ///< vector component + MATRIX_1_1, ///< matrix component + MATRIX_1_2, ///< matrix component + MATRIX_1_3, ///< matrix component + MATRIX_2_1, ///< matrix component + MATRIX_2_2, ///< matrix component + MATRIX_2_3, ///< matrix component + MATRIX_3_1, ///< matrix component + MATRIX_3_2, ///< matrix component + MATRIX_3_3 ///< matrix component + } PdbxStructOperListItems; + + /// \enum items of the struct category + typedef enum { + STRUCT_ENTRY_ID, ///< name of the structure + PDBX_CASP_FLAG, ///< CASP/ CASD-NMR/ other contest target + PDBX_DESCRIPTOR, ///< descriptor for NDB structure/ PDB COMPND record + PDBX_FORMULA_WEIGHT, ///< mass in daltons + PDBX_FORMULA_WEIGHT_METHOD, ///< how mass was determined + PDBX_MODEL_DETAILS, ///< methodology + PDBX_MODEL_TYPE_DETAILS, ///< type of structure model + STRUCT_TITLE ///< title for the data block + } StructItems; + + /// \enum items of the struct_conf category + typedef enum { + SC_BEG_AUTH_ASYM_ID, ///< Starting residue (atom_site.auth_asym_id) + SC_BEG_LABEL_ASYM_ID, ///< Starting residue (atom_site.label_asym_id) + SC_BEG_LABEL_COMP_ID, ///< Starting residue (atom_site.label_comp_id) + SC_BEG_LABEL_SEQ_ID, ///< Starting residue (atom_site.label_seq_id) + SC_CONF_TYPE_ID, ///< Pointer to struct_conf_type.id + SC_END_AUTH_ASYM_ID, ///< Ending residue, points to atom_site.auth_asym_id + SC_END_LABEL_ASYM_ID, ///< Ending residue, points to atom_site.label_asym_id + SC_END_LABEL_COMP_ID, ///< Ending residue, points to atom_site.label_comp_id + SC_END_LABEL_SEQ_ID, ///< Ending residue, points to atom_site.label_seq_id + SC_ID, ///< Unique identifier + } StructConfItems; + + /// \enum items of the struct_sheet_range category + typedef enum { + SSR_BEG_LABEL_ASYM_ID, ///< start, chain name (atom_site.label_asym_id) + SSR_BEG_LABEL_COMP_ID, ///< start, atom_site.label_comp_id + SSR_BEG_LABEL_SEQ_ID, ///< start, residue number (atom_site.label_seq_id) + SSR_END_LABEL_ASYM_ID, ///< end, chain name (atom_site.label_asym_id) + SSR_END_LABEL_COMP_ID, ///< end, atom_site.label_comp_id + SSR_END_LABEL_SEQ_ID, ///< end, residue number (atom_site.label_seq_id) + SSR_SHEET_ID, ///< unique identifier + SSR_ID, ///< link to struct_sheet.id + SSR_BEG_AUTH_ASYM_ID, ///< alternative start, (atom_site.auth_asym_id) + SSR_END_AUTH_ASYM_ID, ///< alternative end, (atom_site.auth_asym_id) + } StructSheetRangeItems; + + /// \enum items of the pdbx_database_PDB_obs_spr category + typedef enum { + DATE, ///< date of replacement + PDPOS_ID, ///< type of obsolete of this entry + PDB_ID, ///< NEW PDB ID + REPLACE_PDB_ID, ///< OLD PDB ID + } PdbxDatabasePDBObsSpr; + + /// \enum categories of the mmcif format + typedef enum { + ATOM_SITE, + ENTITY, + ENTITY_POLY, + CITATION, + CITATION_AUTHOR, + EXPTL, + REFINE, + PDBX_STRUCT_ASSEMBLY, + PDBX_STRUCT_ASSEMBLY_GEN, + PDBX_STRUCT_OPER_LIST, + STRUCT, + STRUCT_CONF, + STRUCT_SHEET_RANGE, + PDBX_DATABASE_PDB_OBS_SPR, + STRUCT_REF, + STRUCT_REF_SEQ, + STRUCT_REF_SEQ_DIF, + DONT_KNOW + } MMCifCategory; + + /// \struct keeping track of entity information + typedef struct { + mol::ChainType type; ///< characterise entity + String details; ///< description of this entity + String seqres; ///< chain of monomers + } MMCifEntityDesc; + typedef std::map<String, MMCifEntityDesc> MMCifEntityDescMap; + + /// \struct assembly information + typedef struct { + MMCifInfoBioUnit biounit; + std::vector<std::vector<String> > operations; ///< list of links to + /// MMCifBioUOperation + } MMCifBioUAssembly; + typedef std::vector<MMCifBioUAssembly> MMCifBioUAssemblyVector; + + typedef std::map<String, std::pair<std::vector<int>, std::vector<String> > > + MMCifCitationAuthorMap; + + /// \struct store struct_conf info (secondary structure) + typedef struct { + mol::ResNum start; + mol::ResNum end; + String chain_name; + } MMCifHSEntry; + typedef std::vector<MMCifHSEntry> MMCifHSVector; + + // members + MMCifCategory category_; + int category_counts_[DONT_KNOW+1]; ///< overall no. of atom_site loops + int indices_[MAX_ITEMS_IN_ROW]; ///< map items to values in loops + const IOProfile& profile_; + mol::EntityHandle& ent_handle_; + String restrict_chains_; + bool auth_chain_id_; ///< use chain IDs given by authors rather than pdb + bool seqres_can_; ///< read canonical 1-letter residues? + mol::ChainHandle curr_chain_; + mol::ResidueHandle curr_residue_; + int chain_count_; + int residue_count_; + int atom_count_; + bool warned_name_mismatch_; + bool warned_rule_based_; + String subst_res_id_; ///< work around for missing label_seq_id's + bool has_model_; ///< keep track of models through different atom_sites + int curr_model_; ///< if we have pdbx_PDB_model_num, store no. + std::vector<std::pair<mol::ChainHandle, String> > chain_id_pairs_; + ///< chain and label_entity_id + MMCifEntityDescMap entity_desc_map_; ///< stores entity items + seq::SequenceList seqres_; + bool read_seqres_; + MMCifInfo info_; ///< info container + MMCifCitationAuthorMap authors_map_; + MMCifBioUAssemblyVector bu_assemblies_; + std::map<String, String> bu_origin_map_; ///< pdbx_struct_assembly.details + MMCifHSVector helix_list_; ///< for storing struct_conf sec.struct. data + MMCifHSVector strand_list_; ///< for storing struct_conf sec.struct. data + MMCifInfoStructRefs struct_refs_; +}; + +}} + +#endif diff --git a/modules/io/src/mol/pdb_reader.cc b/modules/io/src/mol/pdb_reader.cc index 65078588a0fe28bdbf2a2cafa982a4be7452a5f8..287c605f6b3003c02aeed0eafecaeb5e363c5b4e 100644 --- a/modules/io/src/mol/pdb_reader.cc +++ b/modules/io/src/mol/pdb_reader.cc @@ -102,6 +102,9 @@ void PDBReader::Init(const boost::filesystem::path& loc) hard_end_=false; skip_next_=false; data_continues_=false; + old_key_=""; + mol_id_=std::make_pair(false, 0); + } void PDBReader::ThrowFaultTolerant(const String& msg) { @@ -114,7 +117,7 @@ void PDBReader::ThrowFaultTolerant(const String& msg) { void PDBReader::ParseCompndEntry (const StringRef& line, int line_num) { - if (line.size()<20) { + if (line.size()<12) { if (profile_.fault_tolerant) { LOG_WARNING("invalid COMPND record on line " << line_num << ": record is too short"); @@ -147,11 +150,22 @@ void PDBReader::ParseCompndEntry (const StringRef& line, int line_num) } if((entry.find(':')!=entry.end())){ std::vector<StringRef> fields=entry.split(':'); - key=fields[0].trim(); - old_key_=key.str(); - data=fields[1].trim(); + key=fields[0].trim(); + old_key_=key.str(); + if (fields.size()>1) { + data=fields[1].trim(); + } + if(data.size()<1){ + if (!(key.str()=="MOL_ID")&&!(key.str()=="CHAIN")){ + LOG_WARNING("skipping unsupported COMPND record on line " << line_num<< ": record value"<< key.str()<<" too small"); + if (data_continues_) { + skip_next_=true; + } else { + return; + } + } ThrowFaultTolerant(str(format("invalid COMPND record on line %d, record after ':' too small")%line_num)); } data_continues_=true; @@ -179,7 +193,7 @@ void PDBReader::ParseCompndEntry (const StringRef& line, int line_num) } //currently only these are parsed if (!(key.str()=="MOL_ID")&&!(key.str()=="CHAIN")){ - LOG_TRACE("reading COMPND record on line " << line_num<< "is not supported"); + LOG_INFO("reading COMPND record on line " << line_num<< "is not supported"); if (data_continues_) { skip_next_=true; } else { @@ -470,7 +484,9 @@ void PDBReader::AssignMolIds(mol::EntityHandle ent) { if (chain) { chain.SetIntProp("mol_id", compnd_iterator->mol_id); }else{ - std::stringstream ss("could not map COMPND record MOL_ID onto chain"); + LOG_WARNING("failed to assign MOL_ID to chain: "<<*chain_iterator <<std::endl); + std::stringstream ss; + ss << "could not map COMPND record MOL_ID onto chain"; ss <<*chain_iterator; ThrowFaultTolerant(ss.str()); } @@ -481,9 +497,13 @@ void PDBReader::AssignMolIds(mol::EntityHandle ent) { mol::ChainHandleList ch_list=ent.GetChainList(); for (mol::ChainHandleList::const_iterator chain=ch_list.begin(); chain!=ch_list.end(); ++chain) { + //~ skip HETATM only chains!! if(chain->IsValid()){ if (!chain->HasProp("mol_id")) { - ThrowFaultTolerant("found chain without MOL_ID"); + std::stringstream ss; + ss << "found chain without MOL_ID: "; + ss << chain->GetName(); + LOG_WARNING(ss.str()); } } } @@ -583,14 +603,6 @@ bool PDBReader::ParseAtomIdent(const StringRef& line, int line_num, } } - std::pair<bool, int> a_num=line.substr(6, 5).ltrim().to_int(); - if (!a_num.first) { - if (!(profile_.fault_tolerant)) { - throw IOException(str(format("invalid atom number on line %d") %line_num)); - } - LOG_WARNING("invalid atom number on line " << line_num); - } - alt_loc=line[16]; res_name=line.substr(17, charmm_style_ ? 4 : 3).trim(); std::pair<bool, int> res_num=line.substr(22, 4).ltrim().to_int();; @@ -694,10 +706,10 @@ void PDBReader::ParseAndAddAtom(const StringRef& line, int line_num, occ=std::make_pair(true, Real(1.0)); temp=std::make_pair(true, Real(0.0)); if (line.length()>=60) { - charge=line.substr(54,6).ltrim().to_float(); + charge=line.substr(55,7).ltrim().to_float(); } - if (line.length()>=66) { - radius=line.substr(60, 6).ltrim().to_float(); + if (line.length()>=68) { + radius=line.substr(63,6).ltrim().to_float(); } } else { if (line.length()>=60) { @@ -772,7 +784,7 @@ void PDBReader::ParseAndAddAtom(const StringRef& line, int line_num, assert(curr_residue_.IsValid()); } // finally add atom - LOG_DEBUG("adding atom " << aname << " (" << s_ele << ") @" << apos); + LOG_DEBUG("adding atom " << aname << " (" << s_ele << " '" << alt_loc << "'" << ") @" << apos); mol::AtomHandle ah; if (curr_residue_.GetName()!=res_name.str()) { if (!profile_.fault_tolerant && alt_loc==' ') { @@ -781,26 +793,30 @@ void PDBReader::ParseAndAddAtom(const StringRef& line, int line_num, << "residue with number " << res_num << " has more than one name."; throw IOException(ss.str()); } - if (!warned_name_mismatch_) { - if (alt_loc==' ') { - LOG_WARNING("Residue with number " << res_num << " has more than one name." - "Ignoring atoms for everything but the first"); - } else { - LOG_WARNING("Residue with number " << res_num - << " contains a microheterogeneity. Everything but atoms for " - << "the residue '" << curr_residue_.GetName() - << "' will be ignored"); + if(!profile_.quack_mode) { + if (!warned_name_mismatch_) { + if (alt_loc==' ') { + LOG_WARNING("Residue with number " << res_num << " has more than one name. " + "Ignoring atoms for everything but the first"); + } else { + LOG_WARNING("Residue with number " << res_num + << " contains a microheterogeneity. Everything but atoms for " + << "the residue '" << curr_residue_.GetName() + << "' will be ignored"); + } } + warned_name_mismatch_=true; + return; } - warned_name_mismatch_=true; - return; } - if (alt_loc!=' ') { + Real b=temp.first ? temp.second : 0.0; + Real o=occ.first ? occ.second : 1.0; + if (!profile_.quack_mode && alt_loc!=' ') { // Check if there is already a atom with the same name. mol::AtomHandle me=curr_residue_.FindAtom(aname); if (me.IsValid()) { try { - editor.AddAltAtomPos(String(1, alt_loc), me, apos); + editor.AddAltAtomPos(String(1, alt_loc), me, apos, o, b); } catch (Error) { LOG_INFO("Ignoring atom alt location since there is already an atom " "with name " << aname << ", but without an alt loc"); @@ -809,7 +825,7 @@ void PDBReader::ParseAndAddAtom(const StringRef& line, int line_num, return; } else { ah=editor.InsertAltAtom(curr_residue_, aname, - String(1, alt_loc), apos, s_ele); + String(1, alt_loc), apos, s_ele, o, b); ++atom_count_; } } else { @@ -831,12 +847,8 @@ void PDBReader::ParseAndAddAtom(const StringRef& line, int line_num, ah.SetRadius(radius.second); } } - if (temp.first) { - ah.SetBFactor(temp.second); - } - if (occ.first) { - ah.SetOccupancy(occ.second); - } + ah.SetBFactor(b); + ah.SetOccupancy(o); if (charge.first) { ah.SetCharge(charge.second); } diff --git a/modules/io/src/mol/pdb_writer.cc b/modules/io/src/mol/pdb_writer.cc index 2b4379ae33c60476b043bb5df40cd927e3a6acbe..fdae17a5110b741790e5c4c4c791b78cb67edbe6 100644 --- a/modules/io/src/mol/pdb_writer.cc +++ b/modules/io/src/mol/pdb_writer.cc @@ -20,9 +20,14 @@ Author: Marco Biasini */ #include <locale> -#include <boost/format.hpp> + #include <string.h> +#include <boost/format.hpp> +#include <boost/iostreams/filter/gzip.hpp> +#include <boost/filesystem/convenience.hpp> +#include <boost/algorithm/string.hpp> + #include <ost/io/io_exception.hh> #include <ost/mol/atom_handle.hh> #include <ost/mol/residue_handle.hh> @@ -73,7 +78,12 @@ void write_atom(std::ostream& ostr, FormattedLine& line, geom::Vec3 p=atom.GetPos(); line( 0, 6)=record_name; - line( 6, 5)=fmt::LPaddedInt(atomnum); + // Avoid writing out atomnumbers larger than 5 digits + if (atomnum > 99999) { + line( 6, 5)=fmt::LPadded("*****"); + } else { + line( 6, 5)=fmt::LPaddedInt(atomnum); + } String atom_name=atom.GetName(); if (atom_name.size()>4) { throw IOException("Atom name '"+atom.GetQualifiedName()+ @@ -125,8 +135,8 @@ void write_atom(std::ostream& ostr, FormattedLine& line, line(46, 8)=fmt::LPaddedFloat(p[2], 3); if (is_pqr) { - line(54, 6)=fmt::LPaddedFloat(atom.GetCharge(), 2); - line(60, 6)=fmt::LPaddedFloat(atom.GetRadius(), 2); + line(55, 7)=fmt::LPaddedFloat(atom.GetCharge(), 4); + line(63, 6)=fmt::LPaddedFloat(atom.GetRadius(), 4); } else { line(54, 6)=fmt::LPaddedFloat(atom.GetOccupancy(), 2); Real bfac=atom.GetBFactor(); @@ -162,8 +172,8 @@ void write_atom(std::ostream& ostr, FormattedLine& line, line(54, 6)=fmt::LPaddedFloat(atom.GetCharge(), 2); line(60, 6)=fmt::LPaddedFloat(atom.GetRadius(), 2); } else { - line(54, 6)=fmt::LPaddedFloat(atom.GetOccupancy(), 2); - Real bfac=atom.GetBFactor(); + line(54, 6)=fmt::LPaddedFloat(atom.GetAltOcc(*i), 2); + Real bfac=atom.GetAltBFactor(*i); if (bfac>999.99) { line(60, 6)=fmt::LPaddedFloat(999.99, 2); } else { @@ -332,7 +342,7 @@ PDBWriter::PDBWriter(std::ostream& stream, const IOProfile& profile): multi_model_(false), charmm_style_(profile.dialect=="CHARMM"), is_pqr_(false), profile_(profile) { - + out_.push(outstream_); } PDBWriter::PDBWriter(const boost::filesystem::path& filename, @@ -346,19 +356,34 @@ PDBWriter::PDBWriter(const boost::filesystem::path& filename, charmm_style_(profile.dialect=="CHARMM"), is_pqr_(false), profile_(profile), filename_("") { + if (boost::iequals(".pqr", boost::filesystem::extension(filename))) { + is_pqr_=true; + } + if (boost::iequals(".gz", boost::filesystem::extension(filename))) { + out_.push(boost::iostreams::gzip_compressor()); + } + out_.push(outstream_); } PDBWriter::PDBWriter(const String& filename, const IOProfile& profile): outfile_(filename.c_str()), outstream_(outfile_), mol_count_(0), line_(80), multi_model_(false), charmm_style_(profile.dialect=="CHARMM"), is_pqr_(false), profile_(profile), filename_(filename) -{} +{ + if (boost::iequals(".pqr", boost::filesystem::extension(filename))) { + is_pqr_=true; + } + if (boost::iequals(".gz", boost::filesystem::extension(filename))) { + out_.push(boost::iostreams::gzip_compressor()); + } + out_.push(outstream_); +} void PDBWriter::WriteModelLeader() { ++mol_count_; if (multi_model_) { - outstream_ << "MODEL " << mol_count_ << std::endl; + out_ << "MODEL " << mol_count_ << std::endl; } else if (mol_count_>1) { throw IOException("Trying to write several models into one file with "); } @@ -367,14 +392,14 @@ void PDBWriter::WriteModelLeader() void PDBWriter::WriteModelTrailer() { if (multi_model_) { - outstream_ << "ENDMDL" << std::endl; + out_ << "ENDMDL" << std::endl; } } template <typename H> void PDBWriter::WriteModel(H ent) { - if (!outstream_) { + if (!out_) { if (!filename_.empty()) { std::stringstream ss; ss << "Can't write PDB to file '" << filename_ << "'"; @@ -384,10 +409,10 @@ void PDBWriter::WriteModel(H ent) } ForcePOSIX posix; this->WriteModelLeader(); - PDBWriterImpl writer(outstream_,line_, atom_indices_, charmm_style_); + PDBWriterImpl writer(out_, line_, atom_indices_, charmm_style_); writer.SetIsPQR(is_pqr_); ent.Apply(writer); - PDBConectWriterImpl con_writer(outstream_,atom_indices_); + PDBConectWriterImpl con_writer(out_, atom_indices_); ent.Apply(con_writer); this->WriteModelTrailer(); } @@ -410,7 +435,7 @@ void PDBWriter::Write(const mol::AtomHandleList& atoms) mol::ChainHandle last_chain; for (mol::AtomHandleList::const_iterator i=atoms.begin(), e=atoms.end(); i!=e; ++i, ++counter) { - write_atom(outstream_, line_, *i, counter, is_pqr_, charmm_style_); + write_atom(out_, line_, *i, counter, is_pqr_, charmm_style_); } this->WriteModelTrailer(); } @@ -418,7 +443,7 @@ void PDBWriter::Write(const mol::AtomHandleList& atoms) PDBWriter::~PDBWriter() { - outstream_ << "END "; + out_ << "END "; } }} diff --git a/modules/io/src/mol/pdb_writer.hh b/modules/io/src/mol/pdb_writer.hh index b0e70a89f5e3478fdf572798b93a517f4988e173..d12b3219f5cd509cebefea9f1444cdd028ae7b60 100644 --- a/modules/io/src/mol/pdb_writer.hh +++ b/modules/io/src/mol/pdb_writer.hh @@ -43,7 +43,9 @@ class EntityHandle; namespace io { + class DLLEXPORT_OST_IO PDBWriter { + typedef boost::iostreams::filtering_stream<boost::iostreams::output> OutStream; public: PDBWriter(const String& filename, const IOProfile& profile); @@ -76,6 +78,7 @@ private: bool is_pqr_; IOProfile profile_; String filename_; + OutStream out_; }; }} diff --git a/modules/io/src/mol/star_parser.cc b/modules/io/src/mol/star_parser.cc index cee3a1c38f1fffbd51536fb7cca44b4322edcc45..0de35fec5072aff97c421fa8a9de409b8cb2011b 100644 --- a/modules/io/src/mol/star_parser.cc +++ b/modules/io/src/mol/star_parser.cc @@ -20,33 +20,44 @@ /* Author: Marco Biasini */ +#include <boost/iostreams/filter/gzip.hpp> + #include <cassert> #include <sstream> +#include <ost/log.hh> #include <ost/io/io_exception.hh> #include <ost/io/mol/star_parser.hh> namespace ost { namespace io { StarParser::StarParser(std::istream& stream, bool items_as_row): - stream_(stream), filename_("<stream>"), line_num_(0), + filename_("<stream>"), line_num_(0), has_current_line_(false), current_line_(), items_row_header_(), file_open_(true), items_row_columns_(), items_row_values_() { items_as_row_ = items_as_row; - - if (!fstream_) { + + if (!stream) { file_open_ = false; } + + stream_.push(stream); } StarParser::StarParser(const String& filename, bool items_as_row): - fstream_(filename.c_str()), stream_(fstream_), filename_(filename), + fstream_(filename.c_str()), filename_(filename), line_num_(0), has_current_line_(false), current_line_(), items_row_header_(), file_open_(true), items_row_columns_(), items_row_values_() { - items_as_row_ = items_as_row; + items_as_row_=items_as_row; + if (filename.length() >= 3 && + filename.substr(filename.length() - 3) == ".gz") { + stream_.push(boost::iostreams::gzip_decompressor()); + } + + stream_.push(fstream_); if (!fstream_) { file_open_ = false; @@ -75,6 +86,18 @@ String StarParser::FormatDiagnostic(StarDiagType type, const String& message, return ss.str(); } +Real StarParser::TryGetReal(const StringRef& data, const String& name) const +{ + std::pair<bool, Real> value = data.to_float(); + if (!value.first) { + throw IOException(this->FormatDiagnostic(STAR_DIAG_ERROR, + "Expecting real number for " + + name + ", found '" + data.str() + + "' instead.", line_num_)); + } + return value.second; +} + float StarParser::TryGetFloat(const StringRef& data, const String& name) const { std::pair<bool, float> value = data.to_float(); @@ -87,6 +110,28 @@ float StarParser::TryGetFloat(const StringRef& data, const String& name) const return value.second; } +std::pair<bool, float> StarParser::TryGetFloat(const StringRef& data, + const String& name, + bool may_fail) const +{ + std::pair<bool, float> value = data.to_float(); + if (!value.first) { + if (!may_fail) { + throw IOException(this->FormatDiagnostic(STAR_DIAG_ERROR, + "Expecting floating point value for " + + name + ", found '" + data.str() + + "' instead.", line_num_)); + } + else { + LOG_WARNING(this->FormatDiagnostic(STAR_DIAG_WARNING, + "Expecting floating point value for " + + name + ", found '" + data.str() + + "' instead.", line_num_)); + } + } + return value; +} + int StarParser::TryGetInt(const StringRef& data, const String& name) const { std::pair<bool, int> value = data.to_int(); @@ -99,6 +144,27 @@ int StarParser::TryGetInt(const StringRef& data, const String& name) const return value.second; } +std::pair<bool, int> StarParser::TryGetInt(const StringRef& data, + const String& name, + bool may_fail) const +{ + std::pair<bool, int> value = data.to_int(); + if (!value.first) { + if (!may_fail) { + throw IOException(this->FormatDiagnostic(STAR_DIAG_ERROR, + "Expecting integer value for " + + name + ", found '" + data.str() + + "' instead.", line_num_)); + } else { + LOG_WARNING(this->FormatDiagnostic(STAR_DIAG_WARNING, + "Expecting integer value for " + + name + ", found '" + data.str() + + "' instead.", line_num_)); + } + } + return value; +} + bool StarParser::TryGetBool(const StringRef& data, const String& name) const { if (data.length() == 1) { @@ -343,7 +409,7 @@ void StarParser::ParseDataItem() StarParser::SplitLine(line, nv); if (nv.size()==1) { // remember identifier. - String identifier=line.str(); + String identifier=line.trim().str(); String value; while (this->NextLine(line)) { diff --git a/modules/io/src/mol/star_parser.hh b/modules/io/src/mol/star_parser.hh index b0ef784b76c5633487e7c113398d8c6e8751bf03..c5febf7fb3c2672c2381cdac72c178e9e93beb9a 100644 --- a/modules/io/src/mol/star_parser.hh +++ b/modules/io/src/mol/star_parser.hh @@ -23,6 +23,8 @@ /* Author: Marco Biasini */ +#include <boost/iostreams/filtering_stream.hpp> + #include <iostream> #include <fstream> #include <vector> @@ -148,6 +150,14 @@ public: /// OnBeginData() returned true. virtual void OnEndData() { } + /// \brief try to convert a value to Real, on failure raise an exception. + /// + /// \param data value to be converted + /// \param name to be included in the message + /// + /// \return converted value + Real TryGetReal(const StringRef& data, const String& name) const; + /// \brief try to convert a value to float, on failure raise an exception. /// /// \param data value to be converted @@ -156,6 +166,17 @@ public: /// \return converted value float TryGetFloat(const StringRef& data, const String& name) const; + /// \brief try to convert a value to float, on failure raise an exception. + /// + /// \param data value to be converted + /// \param name to be included in the message + /// \param may_fail decides if an exception is raised (false) or not (true) + /// + /// \return converted value + std::pair<bool, float> TryGetFloat(const StringRef& data, + const String& name, + bool may_fail) const; + /// \brief try to convert a value to integer, on failure raise an exception. /// /// \param data value to be converted @@ -164,6 +185,17 @@ public: /// \return converted value int TryGetInt(const StringRef& data, const String& name) const; + /// \brief try to convert a value to integer, exception can be turned off. + /// + /// \param data value to be converted + /// \param name to be included in the message + /// \param may_fail decides if an exception is raised (false) or not (true) + /// + /// \return pair with value and indicator if conversion worked + std::pair<bool, int> TryGetInt(const StringRef& data, + const String& name, + bool may_fail) const; + /// \brief try to convert a value to bool, on failure raise an exception. /// /// \param data value to be converted @@ -238,7 +270,7 @@ private: void DiagnoseUnknown(); bool ParseMultilineValue(String& value, bool skip=false); std::ifstream fstream_; - std::istream& stream_; + boost::iostreams::filtering_stream<boost::iostreams::input> stream_; String filename_; int line_num_; bool has_current_line_; diff --git a/modules/io/tests/CMakeLists.txt b/modules/io/tests/CMakeLists.txt index f10be7bc4857bbe2d04bb896849f9d677707cfa0..98f075bd9785c1c051f642e3be91dd2e125cc62f 100644 --- a/modules/io/tests/CMakeLists.txt +++ b/modules/io/tests/CMakeLists.txt @@ -1,5 +1,6 @@ set(OST_IO_UNIT_TESTS test_io_pdb.py + test_io_mmcif.py test_clustal.cc test_io_pdb.cc test_io_crd.cc @@ -8,6 +9,8 @@ set(OST_IO_UNIT_TESTS test_iomanager.cc tests.cc test_star_parser.cc + test_mmcif_reader.cc + test_mmcif_info.cc ) if (ENABLE_IMG) list(APPEND OST_IO_UNIT_TESTS test_io_img.cc) @@ -16,6 +19,9 @@ ost_unittest(MODULE io SOURCES "${OST_IO_UNIT_TESTS}" LINK ost_mol ost_seq) -add_executable(test_mae_standalone test_mae_standalone.cc) -target_link_libraries(test_mae_standalone ost_mol) -target_link_libraries(test_mae_standalone ost_io) +if(NOT ENABLE_STATIC) + add_executable(test_mae_standalone test_mae_standalone.cc) + target_link_libraries(test_mae_standalone ost_mol) + target_link_libraries(test_mae_standalone ost_io) + target_link_libraries(test_mae_standalone ${Boost_REGEX_LIBRARY}) +endif() diff --git a/modules/io/tests/test_io_img.cc b/modules/io/tests/test_io_img.cc index d8165dd76203ba7fcb1fc8e00fcce5a7df290a62..890a7a9c29a22beb57b4c7c0aa0ffb04273f8777 100644 --- a/modules/io/tests/test_io_img.cc +++ b/modules/io/tests/test_io_img.cc @@ -34,6 +34,7 @@ #include <ost/io/img/map_io_dat_handler.hh> #include <ost/io/img/map_io_jpk_handler.hh> #include <ost/io/img/map_io_nanoscope_handler.hh> +#include <ost/io/img/map_io_ipl_handler.hh> #include <ost/img/alg/normalizer_factory.hh> using namespace ost; @@ -46,17 +47,16 @@ BOOST_AUTO_TEST_CASE(test_io_img) { //float tests boost::test_tools::close_at_tolerance<Real> close_test(::boost::test_tools::percent_tolerance(0.001)); - ost::img::ImageHandle testimage=ost::img::CreateImage(ost::img::Extent(ost::img::Point(0,0),ost::img::Point(3,3))); + ost::img::ImageHandle testimage=ost::img::CreateImage(ost::img::Extent(ost::img::Point(0,0),ost::img::Point(4,3))); int counter=0; for (img::ExtentIterator i(testimage.GetExtent()); !i.AtEnd(); ++i, ++counter) { testimage.SetReal(i, counter); } - testimage+=0.01; //if all values are > 0.0 we can use close_at_tolerance + testimage+=5.01; //if all values are > 0.0 we can use close_at_tolerance const String fname("temp_img.tmp"); std::map<String,ImageFormatBase*> float_formats; float_formats["DX"]=new DX; float_formats["Situs"]=new Situs; - float_formats["DAT (float)"]=new DAT(false,OST_FLOAT_FORMAT); float_formats["CCP4 (float)"]=new MRC; float_formats["MRC (float)"]=new MRC(false,MRC_OLD_FORMAT); float_formats["SPIDER"]= new Spider; @@ -82,7 +82,7 @@ BOOST_AUTO_TEST_CASE(test_io_img) } //int 16 formats std::map<String,ImageFormatBase*> int_formats; - int_formats["DAT (16 bit)"]=new DAT(true,OST_BIT16_FORMAT); + int_formats["IPL (16 bit)"]=new IPL(true,OST_BIT16_FORMAT); int_formats["TIF (16 bit)"]=new TIF; int_formats["JPK (16 bit)"]=new JPK; // int_formats["DF3"]=new DF3(true); @@ -108,9 +108,33 @@ BOOST_AUTO_TEST_CASE(test_io_img) delete it->second; } + //int 32 formats + std::map<String,ImageFormatBase*> int32_formats; + int32_formats["IPL (32 bit)"]=new IPL(true,OST_BIT32_FORMAT); + for(std::map<String,ImageFormatBase*>::iterator it=int32_formats.begin();it!=int32_formats.end();++it){ + ost::io::SaveImage(testimage,fname,*(it->second)); + ost::img::ImageHandle loadedimage=ost::io::LoadImage(fname,*(it->second)); + ost::img::alg::Normalizer norm=ost::img::alg::CreateLinearRangeNormalizer(testimage,0.0,4294967295.0); + ost::img::ImageHandle scaled_image=testimage.Apply(norm); + bool failed=false; + ost::img::ExtentIterator eit(scaled_image.GetExtent()); + for(;!eit.AtEnd();++eit) { + if( static_cast<uint>(scaled_image.GetReal(eit))!=static_cast<uint>(loadedimage.GetReal(eit))){ + failed=true; + break; + } + } + if(failed){ + BOOST_ERROR("Image IO failed for plugin " << it->first << " at point " + << ost::img::Point(eit)<< ". Should be " + << static_cast<uint>(scaled_image.GetReal(eit)) << ", but " + << static_cast<uint>(loadedimage.GetReal(eit)) << " found."); + } + delete it->second; + } + //byte formats std::map<String,ImageFormatBase*> byte_formats; - byte_formats["DAT (byte)"]=new DAT(true,OST_BIT8_FORMAT); byte_formats["PNG"]=new PNG; byte_formats["JPK (byte)"]= new JPK(true,OST_BIT8_FORMAT); byte_formats["TIF (byte)"]= new TIF(true,OST_BIT8_FORMAT); @@ -134,4 +158,70 @@ BOOST_AUTO_TEST_CASE(test_io_img) } } +BOOST_AUTO_TEST_CASE(test_io_img_dat) +{ + // test for the dat file format using a square image (non square images not supported by dat) + //float test + boost::test_tools::close_at_tolerance<Real> close_test(::boost::test_tools::percent_tolerance(0.001)); + ost::img::ImageHandle testimage=ost::img::CreateImage(ost::img::Extent(ost::img::Point(0,0),ost::img::Point(3,3))); + int counter=0; + for (img::ExtentIterator i(testimage.GetExtent()); !i.AtEnd(); ++i, ++counter) { + testimage.SetReal(i, counter); + } + testimage+=5.01; //if all values are > 0.0 we can use close_at_tolerance + const String fname("temp_img.tmp"); + ost::io::SaveImage(testimage,fname,DAT(false,OST_FLOAT_FORMAT)); + ost::img::ImageHandle loadedimage=ost::io::LoadImage(fname,DAT(false,OST_FLOAT_FORMAT)); + bool failed=false; + ost::img::ExtentIterator eit(testimage.GetExtent()); + for(;!eit.AtEnd();++eit) { + if( ! close_test(testimage.GetReal(eit),loadedimage.GetReal(eit))){ + failed=true; + break; + } + } + if(failed){ + BOOST_ERROR("Image IO failed for plugin DAT (float) at point " << ost::img::Point(eit)<< ". The values are: " << testimage.GetReal(eit)<< ","<< loadedimage.GetReal(eit) ); + } + //int 16 format + ost::io::SaveImage(testimage,fname,DAT(true,OST_BIT16_FORMAT)); + loadedimage=ost::io::LoadImage(fname,DAT(true,OST_BIT16_FORMAT)); + ost::img::alg::Normalizer norm=ost::img::alg::CreateLinearRangeNormalizer(testimage,0.0,65535.0); + ost::img::ImageHandle scaled_image=testimage.Apply(norm); + failed=false; + eit=ost::img::ExtentIterator(testimage.GetExtent()); + for(;!eit.AtEnd();++eit) { + if( static_cast<int>(scaled_image.GetReal(eit))!=static_cast<int>(loadedimage.GetReal(eit))){ + failed=true; + break; + } + } + if(failed){ + BOOST_ERROR("Image IO failed for plugin DAT (int16) at point " + << ost::img::Point(eit)<< ". Should be " + << static_cast<int>(scaled_image.GetReal(eit)) << ", but " + << static_cast<int>(loadedimage.GetReal(eit)) << " found."); + } + + //byte format + ost::io::SaveImage(testimage,fname,DAT(true,OST_BIT8_FORMAT)); + loadedimage=ost::io::LoadImage(fname,DAT(true,OST_BIT8_FORMAT)); + norm=ost::img::alg::CreateLinearRangeNormalizer(testimage,0.0,255.0); + scaled_image=testimage.Apply(norm); + failed=false; + eit=ost::img::ExtentIterator(testimage.GetExtent()); + for(;!eit.AtEnd();++eit) { + if( static_cast<int>(scaled_image.GetReal(eit))!=static_cast<int>(loadedimage.GetReal(eit))){ + failed=true; + break; + } + } + if(failed){ + BOOST_ERROR("Image IO failed for plugin DAT (int8) at point " + << ost::img::Point(eit)<< ". Should be " + << static_cast<int>(scaled_image.GetReal(eit)) << ", but " + << static_cast<int>(loadedimage.GetReal(eit)) << " found."); + } +} + BOOST_AUTO_TEST_SUITE_END() diff --git a/modules/io/tests/test_io_mmcif.py b/modules/io/tests/test_io_mmcif.py new file mode 100644 index 0000000000000000000000000000000000000000..94eb063301b5e56f697c7d67f43452c023b38f56 --- /dev/null +++ b/modules/io/tests/test_io_mmcif.py @@ -0,0 +1,223 @@ +import unittest +from ost import * + +class TestMMCifInfo(unittest.TestCase): + def setUp(self): + pass + + def test_mmcifinfo_citation(self): + c = io.MMCifInfoCitation() + # test ID setting/ getting + c.SetID('ID') + self.assertEquals(c.GetID(), 'ID') + # test CAS setting/ getting + c.SetCAS('FOO') + self.assertEquals(c.GetCAS(), 'FOO') + # test ISBN setting/ getting + c.SetISBN('0-0-0-0-0-0') + self.assertEquals(c.GetISBN(), '0-0-0-0-0-0') + # test published_in setting/ getting + c.SetPublishedIn('Best Book Ever') + self.assertEquals(c.GetPublishedIn(), 'Best Book Ever') + # test volume setting/ getting + c.SetVolume('3') + self.assertEquals(c.GetVolume(), '3') + # test page setting/ getting + c.SetPageFirst('1') + self.assertEquals(c.GetPageFirst(), '1') + c.SetPageLast('10') + self.assertEquals(c.GetPageLast(), '10') + # test doi setting/ getting + c.SetDOI('HERE') + self.assertEquals(c.GetDOI(), 'HERE') + # test PubMed setting/ getting + c.SetPubMed(815) + self.assertEquals(c.GetPubMed(), 815) + # test year setting/ getting + c.SetYear(815) + self.assertEquals(c.GetYear(), 815) + # test title setting/ getting + c.SetTitle('Foo') + self.assertEquals(c.GetTitle(), 'Foo') + # test auhtors setting/ getting + s = ost.StringList() + s.append('Foo') + c.SetAuthorList(s) + s2 = c.GetAuthorList() + self.assertEquals(s2[0], 'Foo') + + i = io.MMCifInfo() + i.SetMethod('Deep-Fry') + i.SetResolution(2.0) + i.AddCitation(c) + s.append('Bar') + i.AddAuthorsToCitation('ID', s) + + cl = i.GetCitations() + self.assertEquals(len(cl), 1) + al = cl[0].GetAuthorList() + self.assertEquals(len(al), 2) + self.assertEquals(al[0], 'Foo') + self.assertEquals(al[1], 'Bar') + + self.assertEquals(i.GetMethod(), 'Deep-Fry') + self.assertEquals(i.GetResolution(), 2.0) + + + def test_mmcifinfo_biounit(self): + b = io.MMCifInfoBioUnit() + b.SetDetails('Details') + self.assertEquals(b.GetDetails(), 'Details') + b.AddChain('A') + cl = b.GetChainList() + self.assertEquals(cl[0], 'A') + + i = io.MMCifInfo() + i.AddBioUnit(b) + + bl = i.GetBioUnits() + self.assertEquals(len(bl), 1) + + + def test_mmcifinfo_transoperation(self): + o = io.MMCifInfoTransOp() + o.SetID("1") + self.assertEquals(o.GetID(), '1') + o.SetType("identity operation") + self.assertEquals(o.GetType(), 'identity operation') + o.SetVector(1.0, 2.0, 3.0) + self.assertEquals(o.GetVector().x, 1.0) + self.assertEquals(o.GetVector().y, 2.0) + self.assertEquals(o.GetVector().z, 3.0) + o.SetMatrix(1, 2, 3, 4, 5, 6, 7, 8, 9) + self.assertEquals(geom.Equal(o.GetMatrix(), + geom.Mat3(1, 2, 3, 4, 5, 6, 7, 8, 9)), True) + + i = io.MMCifInfo() + i.AddOperation(o) + ol = i.GetOperations() + self.assertEquals(ol[0].GetID(), '1') + + b = io.MMCifInfoBioUnit() + b.AddOperations(ol) + oll = b.GetOperations() + self.assertEquals(oll[0][0].GetID(), '1') + + def test_mmcifinfo_biounit_pdbize(self): + ent, seqres, info = io.LoadMMCIF("testfiles/mmcif/3T6C.cif.gz", + seqres=True, + info=True) + pdb_ent = info.GetBioUnits()[0].PDBize(ent) + pdb_seqres_ent = info.GetBioUnits()[0].PDBize(ent, seqres) + + # chains + self.assertEquals(str(pdb_ent.GetChainList()[0]), 'A') + self.assertEquals(str(pdb_ent.GetChainList()[1]), 'B') + self.assertEquals(str(pdb_ent.GetChainList()[2]), '_') + self.assertEquals(str(pdb_ent.GetChainList()[3]), '-') + self.assertEquals(str(pdb_ent.GetChainList()[4]), 'C') + self.assertEquals(str(pdb_ent.GetChainList()[5]), 'D') + self.assertEquals(str(pdb_ent.GetChainList()[6]), 'E') + self.assertEquals(str(pdb_ent.GetChainList()[7]), 'F') + self.assertEquals(str(pdb_ent.GetChainList()[8]), 'G') + self.assertEquals(str(pdb_ent.GetChainList()[9]), 'H') + # size of chains + self.assertEquals(len(pdb_ent.GetChainList()[0].GetResidueList()), 415) + self.assertEquals(len(pdb_ent.GetChainList()[1].GetResidueList()), 414) + self.assertEquals(len(pdb_ent.GetChainList()[2].GetResidueList()), 64) + self.assertEquals(len(pdb_ent.GetChainList()[3].GetResidueList()), 3816) + self.assertEquals(len(pdb_ent.GetChainList()[4].GetResidueList()), 415) + self.assertEquals(len(pdb_ent.GetChainList()[5].GetResidueList()), 414) + self.assertEquals(len(pdb_ent.GetChainList()[6].GetResidueList()), 415) + self.assertEquals(len(pdb_ent.GetChainList()[7].GetResidueList()), 414) + self.assertEquals(len(pdb_ent.GetChainList()[8].GetResidueList()), 415) + self.assertEquals(len(pdb_ent.GetChainList()[9].GetResidueList()), 414) + + self.assertEquals(str(pdb_seqres_ent.GetChainList()[0]), 'A') + self.assertEquals(str(pdb_seqres_ent.GetChainList()[1]), 'B') + self.assertEquals(str(pdb_seqres_ent.GetChainList()[2]), '_') + self.assertEquals(str(pdb_seqres_ent.GetChainList()[3]), '-') + self.assertEquals(str(pdb_seqres_ent.GetChainList()[4]), 'C') + self.assertEquals(str(pdb_seqres_ent.GetChainList()[5]), 'D') + self.assertEquals(str(pdb_seqres_ent.GetChainList()[6]), 'E') + self.assertEquals(str(pdb_seqres_ent.GetChainList()[7]), 'F') + self.assertEquals(str(pdb_seqres_ent.GetChainList()[8]), 'G') + self.assertEquals(str(pdb_seqres_ent.GetChainList()[9]), 'H') + + self.assertEquals(len(pdb_seqres_ent.GetChainList()[0].GetResidueList()), + 415) + self.assertEquals(len(pdb_seqres_ent.GetChainList()[1].GetResidueList()), + 414) + self.assertEquals(len(pdb_seqres_ent.GetChainList()[2].GetResidueList()), + 64) + self.assertEquals(len(pdb_seqres_ent.GetChainList()[3].GetResidueList()), + 3816) + self.assertEquals(len(pdb_seqres_ent.GetChainList()[4].GetResidueList()), + 415) + self.assertEquals(len(pdb_seqres_ent.GetChainList()[5].GetResidueList()), + 414) + self.assertEquals(len(pdb_seqres_ent.GetChainList()[6].GetResidueList()), + 415) + self.assertEquals(len(pdb_seqres_ent.GetChainList()[7].GetResidueList()), + 414) + self.assertEquals(len(pdb_seqres_ent.GetChainList()[8].GetResidueList()), + 415) + self.assertEquals(len(pdb_seqres_ent.GetChainList()[9].GetResidueList()), + 414) + + def test_mmcifinfo_structdetails(self): + d = io.MMCifInfoStructDetails() + + d.SetEntryID('1BAR') + d.SetTitle('A Title') + d.SetCASPFlag('N') + d.SetDescriptor('FooBar') + d.SetMass(1.0) + d.SetMassMethod('Good Guess') + d.SetModelDetails('Created with SwissModel') + d.SetModelTypeDetails('Average') + self.assertEquals(d.GetEntryID(), '1BAR') + self.assertEquals(d.GetTitle(), 'A Title') + self.assertEquals(d.GetCASPFlag(), 'N') + self.assertEquals(d.GetDescriptor(), 'FooBar') + self.assertEquals(d.GetMass(), 1.0) + self.assertEquals(d.GetMassMethod(), 'Good Guess') + self.assertEquals(d.GetModelDetails(), 'Created with SwissModel') + self.assertEquals(d.GetModelTypeDetails(), 'Average') + + i = io.MMCifInfo() + i.SetStructDetails(d) + self.assertEquals(i.GetStructDetails().GetEntryID(), '1BAR') + self.assertEquals(i.GetStructDetails().GetTitle(), 'A Title') + self.assertEquals(i.GetStructDetails().GetCASPFlag(), 'N') + self.assertEquals(i.GetStructDetails().GetDescriptor(), 'FooBar') + self.assertEquals(i.GetStructDetails().GetMass(), 1.0) + self.assertEquals(i.GetStructDetails().GetMassMethod(), 'Good Guess') + self.assertEquals(i.GetStructDetails().GetModelDetails(), + 'Created with SwissModel') + self.assertEquals(i.GetStructDetails().GetModelTypeDetails(), 'Average') + + def test_mmcifinfo_obsolete(self): + obs = io.MMCifInfoObsolete() + obs.SetDate('2011-08-31') + obs.SetID('SPRSDE') + obs.SetPDBID('1FOO') + obs.SetReplacedPDBID('2BAR') + self.assertEquals(obs.GetDate(), '2011-08-31') + self.assertEquals(obs.GetID(), 'Supersede') + self.assertEquals(obs.GetPDBID(), '1FOO') + self.assertEquals(obs.GetReplacedPDBID(), '2BAR') + + i = io.MMCifInfo() + obs.id = 'OBSLTE' + i.SetObsoleteInfo(obs) + self.assertEquals(i.GetObsoleteInfo().GetDate(), '2011-08-31') + self.assertEquals(i.GetObsoleteInfo().GetID(), 'Obsolete') + self.assertEquals(i.GetObsoleteInfo().GetPDBID(), '1FOO') + self.assertEquals(i.GetObsoleteInfo().GetReplacedPDBID(), '2BAR') + +if __name__== '__main__': + from ost import testutils + testutils.RunTests() + + diff --git a/modules/io/tests/test_io_pdb.cc b/modules/io/tests/test_io_pdb.cc index 6a055b83fe0624cf9cb783162bc1028039b055ed..47f858f8eb26f61b3e7e775c201fbbfd2d73f160 100644 --- a/modules/io/tests/test_io_pdb.cc +++ b/modules/io/tests/test_io_pdb.cc @@ -27,6 +27,8 @@ #include <ost/io/mol/entity_io_pdb_handler.hh> #include <ost/io/pdb_reader.hh> #include <ost/io/pdb_writer.hh> +#include <ost/log.hh> + #include <ost/io/io_exception.hh> #define BOOST_TEST_DYN_LINK #include <boost/test/unit_test.hpp> @@ -37,7 +39,6 @@ using namespace ost::io; BOOST_AUTO_TEST_SUITE( io ) - BOOST_AUTO_TEST_CASE(test_pdb_import_handler) { String fname("testfiles/test_in.pdb"); @@ -135,11 +136,53 @@ BOOST_AUTO_TEST_CASE(test_parse_compnd_record4) //COMPND CHAIN record misses B chain BOOST_AUTO_TEST_CASE(test_parse_compnd_record5) { + Logger::Instance().PushVerbosityLevel(0); + String fname("testfiles/pdb/1AKE_noBchain.pdb"); PDBReader reader(fname, IOProfile()); mol::EntityHandle ent=mol::CreateEntity(); + BOOST_CHECK_NO_THROW(reader.Import(ent)); + + mol::ChainHandle ch = ent.FindChain("A"); + BOOST_CHECK(ch.HasProp("mol_id")==true); + BOOST_CHECK(ch.GetIntProp("mol_id")==1); + + ch = ent.FindChain("B"); + BOOST_CHECK(ch.HasProp("mol_id")==false); +} + +//chain I in MOL_ID record but no chain I +BOOST_AUTO_TEST_CASE(test_parse_compnd_record6) +{ + Logger::Instance().PushVerbosityLevel(0); + String fname("testfiles/pdb/1oax.pdb"); + PDBReader reader(fname, IOProfile()); + mol::EntityHandle ent=mol::CreateEntity(); + BOOST_CHECK_THROW(reader.Import(ent), IOException); + +} + +// has an empy MOLECULE record (unsupported ATM anyway, but crashed ost) +BOOST_AUTO_TEST_CASE(test_parse_compnd_record7) +{ + Logger::Instance().PushVerbosityLevel(0); + String fname("testfiles/pdb/2p6a.pdb"); + PDBReader reader(fname, IOProfile()); + mol::EntityHandle ent=mol::CreateEntity(); + + reader.Import(ent); + mol::ChainHandle ch = ent.FindChain("A"); + BOOST_CHECK(ch.HasProp("mol_id")==true); + BOOST_CHECK(ch.GetIntProp("mol_id")==1); + ch = ent.FindChain("D"); + BOOST_CHECK(ch.HasProp("mol_id")==true); + BOOST_CHECK(ch.GetIntProp("mol_id")==2); + + ch = ent.FindChain("E"); + BOOST_CHECK(ch.HasProp("mol_id")==true); + BOOST_CHECK(ch.GetIntProp("mol_id")==3); } @@ -386,6 +429,25 @@ BOOST_AUTO_TEST_CASE(deuterium_import) BOOST_CHECK(ent.FindResidue("A", 297).IsPeptideLinking()); } +BOOST_AUTO_TEST_CASE(bzdng_318) +{ + String fname("testfiles/pdb/bzdng-318.pdb"); + PDBReader reader(fname, IOProfile()); + mol::EntityHandle ent=mol::CreateEntity(); + reader.Import(ent); + // we use conopology to mark amino acids as peptide-linking. + conop::Conopology& conop_inst=conop::Conopology::Instance(); + conop_inst.ConnectAll(conop_inst.GetBuilder(), ent); + { + PDBWriter writer(std::string("testfiles/pdb/bzdng-318-out.pdb"), + IOProfile()); + writer.Write(ent); + } + + BOOST_CHECK(compare_files("testfiles/pdb/bzdng-318.pdb", + "testfiles/pdb/bzdng-318-out.pdb")); +} + BOOST_AUTO_TEST_CASE(faulty_lines) { String fname("testfiles/pdb/faulty.pdb"); @@ -419,6 +481,64 @@ BOOST_AUTO_TEST_CASE(write_atom) " 1.00128.00 C "); } +BOOST_AUTO_TEST_CASE(write_atom_100000) +{ + char c_names[] = "ABCDEFGHIJ"; + std::stringstream out; + PDBWriter writer(out, IOProfile()); + + mol::EntityHandle ent=mol::CreateEntity(); + mol::XCSEditor edi=ent.EditXCS(); + mol::ChainHandle ch; + mol::ResidueHandle r; + mol::AtomHandle a; + + for (unsigned long i = 0; i < 10; ++i) { + ch=edi.InsertChain(String(1, c_names[i])); + for (unsigned long j = 1; j < 1000; ++j) { + r=edi.AppendResidue(ch, "ARG"); + a=edi.InsertAtom(r,"N", geom::Vec3(26.861, 50.841, 38.803), "N"); + a.SetOccupancy(1.0); + a.SetBFactor(128.0); + a=edi.InsertAtom(r,"CA", geom::Vec3(27.437, 49.969, 37.786), "C"); + a.SetOccupancy(1.0); + a.SetBFactor(128.0); + a=edi.InsertAtom(r,"C", geom::Vec3(26.336, 48.959, 37.429), "C"); + a.SetOccupancy(1.0); + a.SetBFactor(128.0); + a=edi.InsertAtom(r,"O", geom::Vec3(25.745, 48.313, 38.312), "O"); + a.SetOccupancy(1.0); + a.SetBFactor(128.0); + a=edi.InsertAtom(r,"CB", geom::Vec3(28.653, 49.266, 38.349), "C"); + a.SetOccupancy(1.0); + a.SetBFactor(128.0); + a=edi.InsertAtom(r,"CG", geom::Vec3(29.870, 50.188, 38.416), "C"); + a.SetOccupancy(1.0); + a.SetBFactor(128.0); + a=edi.InsertAtom(r,"CD", geom::Vec3(31.033, 49.532, 39.173), "C"); + a.SetOccupancy(1.0); + a.SetBFactor(128.0); + a=edi.InsertAtom(r,"NE", geom::Vec3(32.318, 50.244, 39.125), "N"); + a.SetOccupancy(1.0); + a.SetBFactor(128.0); + a=edi.InsertAtom(r,"CZ", geom::Vec3(33.462, 49.750, 39.679), "C"); + a.SetOccupancy(1.0); + a.SetBFactor(128.0); + a=edi.InsertAtom(r,"NH1", geom::Vec3(33.522, 48.572, 40.308), "N"); + a.SetOccupancy(1.0); + a.SetBFactor(128.0); + a=edi.InsertAtom(r,"NH2", geom::Vec3(34.610, 50.427, 39.597), "N"); + a.SetOccupancy(1.0); + a.SetBFactor(128.0); + } + } + + writer.Write(ent); + String s=out.str(); + BOOST_CHECK_EQUAL(s.substr(8099844, 5), "99999"); + BOOST_CHECK_EQUAL(s.substr(8099925, 5), "*****"); +} + BOOST_AUTO_TEST_CASE(write_hetatom) { std::stringstream out; @@ -798,7 +918,7 @@ BOOST_AUTO_TEST_CASE(charmm_rname) { PDBWriter writer(String("testfiles/pdb/charmm_rname-out.pdb"), IOProfile("CHARMM", true, false, false, - false, false, false)); + false, false, false, true)); mol::EntityHandle ent=mol::CreateEntity(); mol::XCSEditor edi=ent.EditXCS(); @@ -818,7 +938,7 @@ BOOST_AUTO_TEST_CASE(charmm_longcname) { PDBWriter writer(String("testfiles/pdb/charmm_longcname-out.pdb"), IOProfile("CHARMM", true, false, false, - false, false, false)); + false, false, false, true)); mol::EntityHandle ent=mol::CreateEntity(); mol::XCSEditor edi=ent.EditXCS(); @@ -838,7 +958,7 @@ BOOST_AUTO_TEST_CASE(write_charmm_ter) { PDBWriter writer(String("testfiles/pdb/charmm_ter-out.pdb"), IOProfile("CHARMM", true, false, false, - false, false, false)); + false, false, false, true)); mol::EntityHandle ent=mol::CreateEntity(); mol::XCSEditor edi=ent.EditXCS(); @@ -855,4 +975,88 @@ BOOST_AUTO_TEST_CASE(write_charmm_ter) "testfiles/pdb/charmm_ter-out.pdb")); } +BOOST_AUTO_TEST_CASE(test_pqr_import_handler) +{ + String fname("testfiles/test_in.pqr"); + + mol::EntityHandle eh=mol::CreateEntity(); + EntityIOPDBHandler pdbh; + + BOOST_CHECK(EntityIOPDBHandler::ProvidesImport(fname)); + BOOST_CHECK(EntityIOPDBHandler::ProvidesImport("test_in.PQR")); + + BOOST_CHECK(EntityIOPDBHandler::ProvidesExport(fname)); + BOOST_CHECK(EntityIOPDBHandler::ProvidesExport("test_in.PQR")); + + pdbh.Import(eh,"testfiles/pdb/simple.pqr"); +} + + +BOOST_AUTO_TEST_CASE(test_pqr_read_atom) +{ + String fname("testfiles/pdb/simple.pqr"); + PDBReader reader(fname, IOProfile()); + mol::EntityHandle ent=mol::CreateEntity(); + reader.Import(ent); + BOOST_REQUIRE_EQUAL(ent.GetChainCount(), 1); + BOOST_REQUIRE_EQUAL(ent.GetResidueCount(), 5); + BOOST_REQUIRE_EQUAL(ent.GetAtomCount(), 91); + mol::AtomHandle a1=ent.FindAtom(" ", mol::ResNum(1), "N"); + BOOST_REQUIRE(a1.IsValid()); + BOOST_CHECK_EQUAL(a1.GetName(), "N"); + BOOST_CHECK_EQUAL(a1.GetResidue().GetName(), "MET"); + BOOST_CHECK_EQUAL(a1.GetResidue().GetChain().GetName(), " "); + + + BOOST_CHECK_EQUAL(a1.GetPos(), geom::Vec3(21.6, 35.3, 56.7)); + BOOST_CHECK_EQUAL(a1.GetElement(), ""); + BOOST_CHECK_EQUAL(a1.IsHetAtom(), false); + BOOST_CHECK_CLOSE(a1.GetCharge(), Real(-0.3755), Real(1e-4)); + BOOST_CHECK_CLOSE(a1.GetRadius(), Real(2.0005), Real(1e-4)); + + mol::AtomHandle a2=ent.FindAtom(" ", mol::ResNum(2), "CZ"); + BOOST_REQUIRE(a2.IsValid()); + BOOST_CHECK_EQUAL(a2.GetName(), "CZ"); + BOOST_CHECK_EQUAL(a2.GetResidue().GetName(), "ARG"); + BOOST_CHECK_EQUAL(a2.GetResidue().GetChain().GetName(), " "); + + BOOST_CHECK_EQUAL(a2.GetPos(), geom::Vec3(23.9, 28.7, 56.5)); + BOOST_CHECK_EQUAL(a2.GetElement(), ""); + BOOST_CHECK_EQUAL(a2.IsHetAtom(), false); + BOOST_CHECK_CLOSE(a2.GetCharge(), Real(0.2507), Real(1e-4)); + BOOST_CHECK_CLOSE(a2.GetRadius(), Real(1.7503), Real(1e-4)); +} + +BOOST_AUTO_TEST_CASE(test_pqr_write_atom) +{ + std::stringstream out; + PDBWriter writer(out, IOProfile()); + writer.SetIsPQR(true); + + mol::EntityHandle ent=mol::CreateEntity(); + mol::XCSEditor edi=ent.EditXCS(); + mol::ChainHandle ch=edi.InsertChain("A"); + mol::ResidueHandle r=edi.AppendResidue(ch, "GLY"); + + mol::AtomHandle a=edi.InsertAtom(r, "CA", geom::Vec3(32.0, -128.0, -2.5), "C"); + a.SetOccupancy(1.0); + a.SetBFactor(128.0); + a.SetCharge(-0.6543); + a.SetRadius(1.2345); + mol::AtomHandle a2=edi.InsertAtom(r, "CA", geom::Vec3(32.0, -128.0, -2.5), "C"); + a2.SetOccupancy(1.0); + a2.SetBFactor(128.0); + a2.SetCharge(0.1234); + a2.SetRadius(2.5432); + writer.Write(ent); + String s=out.str(); + BOOST_CHECK_EQUAL(s.substr(0, 54), + "ATOM 1 CA GLY A 1 32.000-128.000 -2.500"); + BOOST_CHECK_EQUAL(s.substr(54, 26), + " -0.6543 1.2345 C "); + + PDBWriter fwriter(String("testfiles/pdb/pqr_atom-out.pqr"), IOProfile()); + BOOST_CHECK_EQUAL(fwriter.IsPQR(), true); +} + BOOST_AUTO_TEST_SUITE_END() diff --git a/modules/io/tests/test_io_pdb.py b/modules/io/tests/test_io_pdb.py index c8bb3902dbd45b1fb08aea68b81982662d3178a1..348fde1d929669405e612cb92d3a274ceb5636f1 100644 --- a/modules/io/tests/test_io_pdb.py +++ b/modules/io/tests/test_io_pdb.py @@ -11,7 +11,23 @@ class TestPDB(unittest.TestCase): ch = e.FindChain("A"); self.assertEquals(ch.GetIntProp("mol_id"), 1) +class TestPDB(unittest.TestCase): + def setUp(self): + pass + + def test_compnd_parser(self): + profiles=io.IOProfiles() + profiles['NO_FEAS_CHECK']=io.IOProfile(bond_feasibility_check=False) + + e=io.LoadPDB('testfiles/pdb/simple_defective.pdb', restrict_chains="A",profile='NO_FEAS_CHECK') + + res=e.FindResidue('A',3) + + self.assertTrue(mol.BondExists(res.FindAtom("CA"),res.FindAtom("CB"))) + if __name__== '__main__': - unittest.main() + from ost import testutils + testutils.RunTests() + diff --git a/modules/io/tests/test_mmcif_info.cc b/modules/io/tests/test_mmcif_info.cc new file mode 100644 index 0000000000000000000000000000000000000000..23a28205ea74f2e15eb9cd793e16113d137da425 --- /dev/null +++ b/modules/io/tests/test_mmcif_info.cc @@ -0,0 +1,201 @@ +//------------------------------------------------------------------------------ +// This file is part of the OpenStructure project <www.openstructure.org> +// +// Copyright (C) 2008-2011 by the OpenStructure authors +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License as published by the Free +// Software Foundation; either version 3.0 of the License, or (at your option) +// any later version. +// This library is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this library; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +//------------------------------------------------------------------------------ + +#include <ost/io/io_exception.hh> +#include <ost/io/mol/mmcif_info.hh> + +#define BOOST_AUTO_TEST_DYN_LINK +#include <boost/test/unit_test.hpp> + + +using namespace ost; +using namespace ost::io; + +BOOST_AUTO_TEST_SUITE( io ); + +BOOST_AUTO_TEST_CASE(mmcif_info_obsolete) +{ + BOOST_MESSAGE(" Running mmcif_info_obsolete tests..."); + + MMCifInfoObsolete obs = MMCifInfoObsolete(); + + obs.SetDate("2011-08-31"); + obs.SetID(StringRef("OBSLTE", 6)); + obs.SetPDBID("1FOO"); + obs.SetReplacedPDBID("1BAR"); + + BOOST_CHECK(obs.GetDate() == "2011-08-31"); + BOOST_CHECK(obs.GetID() == "Obsolete"); + BOOST_CHECK(obs.GetPDBID() == "1FOO"); + BOOST_CHECK(obs.GetReplacedPDBID() == "1BAR"); + + obs.SetID(StringRef("SPRSDE", 6)); + BOOST_CHECK(obs.GetID() == "Supersede"); + + BOOST_MESSAGE(" done."); +} + +BOOST_AUTO_TEST_CASE(mmcif_info_citation) +{ + BOOST_MESSAGE(" Running mmcif_info_citation tests..."); + + MMCifInfoCitation cit = MMCifInfoCitation(); + std::vector<String> author_list; + + author_list.push_back("Kabel, H."); + + cit.SetID("ID"); + cit.SetCAS("FOO"); + cit.SetISBN("0-0-0-0-0"); + cit.SetPublishedIn("Journal of Uncanny Science"); + cit.SetVolume("3"); + cit.SetPageFirst("1"); + cit.SetPageLast("10"); + cit.SetDOI("HERE"); + cit.SetPubMed(815); + cit.SetYear(815); + cit.SetTitle("Foo"); + cit.SetAuthorList(author_list); + author_list.clear(); + + BOOST_CHECK(cit.GetID() == "ID"); + BOOST_CHECK(cit.GetCAS() == "FOO"); + BOOST_CHECK(cit.GetISBN() == "0-0-0-0-0"); + BOOST_CHECK(cit.GetPublishedIn() == "Journal of Uncanny Science"); + BOOST_CHECK(cit.GetVolume() == "3"); + BOOST_CHECK(cit.GetPageFirst() == "1"); + BOOST_CHECK(cit.GetPageLast() == "10"); + BOOST_CHECK(cit.GetDOI() == "HERE"); + BOOST_CHECK(cit.GetPubMed() == 815); + BOOST_CHECK(cit.GetYear() == 815); + BOOST_CHECK(cit.GetTitle() == "Foo"); + author_list = cit.GetAuthorList(); + BOOST_CHECK(author_list.back() == "Kabel, H."); + + BOOST_MESSAGE(" done."); + BOOST_MESSAGE(" trying to add everything to an info object"); + MMCifInfo info = MMCifInfo(); + info.AddCitation(cit); + std::vector<MMCifInfoCitation> citations = info.GetCitations(); + BOOST_CHECK(citations.size() == 1); + BOOST_CHECK(citations.back() == cit); + BOOST_CHECK_THROW(info.AddAuthorsToCitation(StringRef("Foo", 3), + author_list), + IOException); + BOOST_MESSAGE(" done."); +} + +BOOST_AUTO_TEST_CASE(mmcif_info_biounit) +{ + BOOST_MESSAGE(" Running mmcif_info_biounit tests..."); + + MMCifInfoBioUnit bu = MMCifInfoBioUnit(); + + bu.SetDetails("author_defined_assembly"); + bu.AddChain("A"); + + BOOST_CHECK(bu.GetDetails() == "author_defined_assembly"); + BOOST_CHECK(bu.GetChainList().back() == "A"); + + MMCifInfo info = MMCifInfo(); + info.AddBioUnit(bu); + std::vector<MMCifInfoBioUnit> biounits = info.GetBioUnits(); + BOOST_CHECK(biounits.size() == 1); + BOOST_CHECK(biounits.back() == bu); + + BOOST_MESSAGE(" done."); +} + +BOOST_AUTO_TEST_CASE(mmcif_info_transoperation) +{ + BOOST_MESSAGE(" Running mmcif_info_transoperation tests..."); + + MMCifInfoTransOpPtr op(new MMCifInfoTransOp); + + op->SetID("1"); + op->SetType("identity operation"); + op->SetVector(1, 2, 3); + op->SetMatrix(1, 2, 3, 4, 5, 6, 7 ,8, 9); + + BOOST_CHECK(op->GetID() == "1"); + BOOST_CHECK(op->GetVector() == geom::Vec3(1, 2, 3)); + BOOST_CHECK(op->GetMatrix() == geom::Mat3(1, 2, 3, 4, 5, 6, 7, 8, 9)); + BOOST_CHECK(op->GetType() == "identity operation"); + + MMCifInfo info = MMCifInfo(); + info.AddOperation(op); + BOOST_CHECK(info.GetOperations().back() == op); + + std::vector<MMCifInfoTransOpPtr> ops; + ops.push_back(*(info.GetOperations().begin())); + MMCifInfoBioUnit bu = MMCifInfoBioUnit(); + bu.AddOperations(ops); + BOOST_CHECK((*(bu.GetOperations().begin()->begin())) == op); + + BOOST_MESSAGE(" done."); +} + +BOOST_AUTO_TEST_CASE(mmcif_info_structdetails) +{ + BOOST_MESSAGE(" Running mmcif_info_structdetails tests..."); + + MMCifInfoStructDetails sd = MMCifInfoStructDetails(); + + sd.SetEntryID("1BAR"); + sd.SetTitle("More than a structure"); + sd.SetCASPFlag('Y'); + sd.SetDescriptor("ADENYLATE KINASE"); + sd.SetMass(1.0); + sd.SetMassMethod("Good Guess"); + sd.SetModelDetails("Even more guessing"); + sd.SetModelTypeDetails("MINIMIZED AVERAGE"); + + BOOST_CHECK(sd.GetEntryID() == "1BAR"); + BOOST_CHECK(sd.GetTitle() == "More than a structure"); + BOOST_CHECK(sd.GetCASPFlag() == 'Y'); + BOOST_CHECK(sd.GetDescriptor() == "ADENYLATE KINASE"); + BOOST_CHECK_CLOSE(sd.GetMass(), 1.0f, 0.001f); + BOOST_CHECK(sd.GetMassMethod() == "Good Guess"); + BOOST_CHECK(sd.GetModelDetails() == "Even more guessing"); + BOOST_CHECK(sd.GetModelTypeDetails() == "MINIMIZED AVERAGE"); + + MMCifInfo info = MMCifInfo(); + info.SetStructDetails(sd); + BOOST_CHECK(info.GetStructDetails() == sd); + + BOOST_MESSAGE(" done."); +} + +BOOST_AUTO_TEST_CASE(mmcif_info) +{ + BOOST_MESSAGE(" Running mmcif_info tests..."); + + MMCifInfo info = MMCifInfo(); + + info.SetMethod("Cooking."); + info.SetResolution(1.9f); + + BOOST_CHECK(info.GetMethod() == StringRef("Cooking.", 8)); + BOOST_CHECK_CLOSE(info.GetResolution(), 1.9f, 0.001f); + + BOOST_MESSAGE(" done."); +} + + +BOOST_AUTO_TEST_SUITE_END(); diff --git a/modules/io/tests/test_mmcif_reader.cc b/modules/io/tests/test_mmcif_reader.cc new file mode 100644 index 0000000000000000000000000000000000000000..fff6bbb2e6d6d2596f69f6a223aeeb957f84a50d --- /dev/null +++ b/modules/io/tests/test_mmcif_reader.cc @@ -0,0 +1,1270 @@ +//------------------------------------------------------------------------------ +// This file is part of the OpenStructure project <www.openstructure.org> +// +// Copyright (C) 2008-2011 by the OpenStructure authors +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License as published by the Free +// Software Foundation; either version 3.0 of the License, or (at your option) +// any later version. +// This library is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this library; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +//------------------------------------------------------------------------------ + +#include <fstream> +#include <ost/platform.hh> +#include <ost/io/io_exception.hh> +#include <ost/io/mol/mmcif_reader.hh> +#include <ost/conop/conop.hh> +#include <ost/conop/rule_based_builder.hh> + +#define BOOST_AUTO_TEST_DYN_LINK +#include <boost/test/unit_test.hpp> + + +using namespace ost; +using namespace ost::io; + +class TestMMCifReaderProtected : MMCifReader { +public: + TestMMCifReaderProtected(std::istream& stream, mol::EntityHandle& ent_handle): + MMCifReader(stream, ent_handle, IOProfile()) + { } + + TestMMCifReaderProtected(std::istream& stream, mol::EntityHandle& ent_handle, + const IOProfile& profile): + MMCifReader(stream, ent_handle, profile) + { } + + TestMMCifReaderProtected(const String& filename, + mol::EntityHandle& ent_handle): + MMCifReader(filename, ent_handle, IOProfile()) + { } + + using MMCifReader::OnBeginLoop; + using MMCifReader::OnEndData; + using MMCifReader::IsValidPDBIdent; + using MMCifReader::ParseAtomIdent; + using MMCifReader::ParseAndAddAtom; + using MMCifReader::ParseEntity; + using MMCifReader::ParseEntityPoly; + using MMCifReader::ParseCitation; + using MMCifReader::ParseRefine; + using MMCifReader::ParsePdbxStructAssemblyGen; + using MMCifReader::ParsePdbxStructAssembly; + using MMCifReader::ParsePdbxStructOperList; + using MMCifReader::ParseStruct; + using MMCifReader::ParseStructConf; + using MMCifReader::ParseStructSheetRange; + using MMCifReader::TryStoreIdx; + using MMCifReader::SetRestrictChains; + using MMCifReader::SetReadSeqRes; + using MMCifReader::SetReadCanonicalSeqRes; + using MMCifReader::ClearState; + using MMCifReader::ConvertSEQRES; + using MMCifReader::GetInfo; + using MMCifReader::DetermineSecStructType; + using MMCifReader::MMCifSecStructElement; + using MMCifReader::MMCIF_HELIX; + using MMCifReader::MMCIF_TURN; + using MMCifReader::MMCIF_STRAND; + using MMCifReader::SetAuthChainID; +}; + +void SetAtomSiteHeader(StarLoopDesc* mmcif_h) +{ + mmcif_h->Clear(); + mmcif_h->SetCategory(StringRef("atom_site", 9)); + mmcif_h->Add(StringRef("auth_asym_id", 12)); + mmcif_h->Add(StringRef("id", 2)); + mmcif_h->Add(StringRef("label_alt_id", 12)); + mmcif_h->Add(StringRef("label_asym_id", 13)); + mmcif_h->Add(StringRef("label_atom_id", 13)); + mmcif_h->Add(StringRef("label_comp_id", 13)); + mmcif_h->Add(StringRef("label_entity_id", 15)); + mmcif_h->Add(StringRef("label_seq_id", 12)); + mmcif_h->Add(StringRef("type_symbol", 11)); + mmcif_h->Add(StringRef("Cartn_x", 7)); + mmcif_h->Add(StringRef("Cartn_y", 7)); + mmcif_h->Add(StringRef("Cartn_z", 7)); +} + +BOOST_AUTO_TEST_SUITE( io ); + +BOOST_AUTO_TEST_CASE(mmcif_isvalidpdbident) +{ + mol::EntityHandle eh=mol::CreateEntity(); + + // on changing the tests for a PDB id in mmcif files, extend this unit test + BOOST_MESSAGE(" Running mmcif_isvalidpdbident tests..."); + std::ifstream s("testfiles/mmcif/atom_site.mmcif"); + TestMMCifReaderProtected tmmcif_p(s, eh); + StringRef id = StringRef("1FOO", 4); + BOOST_MESSAGE(" Testing valid id ('"+ id.str() +"')..."); + BOOST_CHECK(tmmcif_p.IsValidPDBIdent(id)); + BOOST_MESSAGE(" done."); + id = StringRef("this is to long for a PDB id", 28); + BOOST_MESSAGE(" Testing oversized PDB id ('"+ id.str() +"')..."); + BOOST_CHECK(!tmmcif_p.IsValidPDBIdent(id)); + BOOST_MESSAGE(" done."); + id = StringRef("nFOO", 4); + BOOST_MESSAGE(" Testing PDB id with missing number ('"+ id.str() +"')..."); + BOOST_CHECK(!tmmcif_p.IsValidPDBIdent(id)); + BOOST_MESSAGE(" done."); +} + +BOOST_AUTO_TEST_CASE(mmcif_trystoreidx) +{ + mol::EntityHandle eh = mol::CreateEntity(); + + BOOST_MESSAGE(" Running mmcif_trystoreidx tests..."); + std::ifstream s("testfiles/mmcif/atom_site.mmcif"); + TestMMCifReaderProtected tmmcif_p(s, eh, IOProfile()); + StarLoopDesc mmcif_h; + mmcif_h.SetCategory(StringRef("Foo", 3)); + // negative + BOOST_CHECK_THROW(tmmcif_p.TryStoreIdx(0, "bar", mmcif_h), IOException); + // positive + mmcif_h.Add(StringRef("bar", 3)); + BOOST_CHECK_NO_THROW(tmmcif_p.TryStoreIdx(0, "bar", mmcif_h)); +} + +BOOST_AUTO_TEST_CASE(mmcif_convert_seqres) +{ + SetPrefixPath(getenv("OST_ROOT")); + String lib_path=GetSharedDataPath()+"/compounds.chemlib"; + conop::CompoundLibPtr compound_lib=conop::CompoundLib::Load(lib_path); + if (!compound_lib) { + std::cout << "WARNING: skipping SEQRES import unit test. " + << "Rule-based builder is required" << std::endl; + return; + } + conop::RuleBasedBuilderPtr rbb(new conop::RuleBasedBuilder(compound_lib)); + conop::Conopology::Instance().RegisterBuilder(rbb, "RBB"); + conop::Conopology::Instance().SetDefaultBuilder("RBB"); + mol::EntityHandle eh=mol::CreateEntity(); + + TestMMCifReaderProtected tmmcif_p("testfiles/mmcif/atom_site.mmcif", eh); + std::vector<StringRef> columns; + StarLoopDesc tmmcif_h; + BOOST_CHECK_EQUAL(tmmcif_p.ConvertSEQRES("A(MSE)Y", compound_lib), "AMY"); + BOOST_CHECK_THROW(tmmcif_p.ConvertSEQRES("A(MSEY", compound_lib), + IOException); + conop::Conopology::Instance().SetDefaultBuilder("HEURISTIC"); +} + +BOOST_AUTO_TEST_CASE(mmcif_onbeginloop) +{ + mol::EntityHandle eh=mol::CreateEntity(); + + // add more tests on new mandatory items + BOOST_MESSAGE(" Running mmcif_onbeginloop tests..."); + std::ifstream s("testfiles/mmcif/atom_site.mmcif"); + MMCifReader mmcif_p(s, eh, IOProfile()); + StarLoopDesc mmcif_h; + BOOST_MESSAGE(" testing atom_site items..."); + mmcif_h.SetCategory(StringRef("atom_site", 9)); + BOOST_MESSAGE(" auth_asym_id"); + BOOST_CHECK_THROW(mmcif_p.OnBeginLoop(mmcif_h), IOException); + mmcif_h.Add(StringRef("auth_asym_id", 12)); + BOOST_MESSAGE(" id"); + BOOST_CHECK_THROW(mmcif_p.OnBeginLoop(mmcif_h), IOException); + mmcif_h.Add(StringRef("id", 2)); + BOOST_MESSAGE(" label_alt_id"); + BOOST_CHECK_THROW(mmcif_p.OnBeginLoop(mmcif_h), IOException); + mmcif_h.Add(StringRef("label_alt_id", 12)); + BOOST_MESSAGE(" label_asym_id"); + BOOST_CHECK_THROW(mmcif_p.OnBeginLoop(mmcif_h), IOException); + mmcif_h.Add(StringRef("label_asym_id", 13)); + BOOST_MESSAGE(" label_atom_id"); + BOOST_CHECK_THROW(mmcif_p.OnBeginLoop(mmcif_h), IOException); + mmcif_h.Add(StringRef("label_atom_id", 13)); + BOOST_MESSAGE(" label_comp_id"); + BOOST_CHECK_THROW(mmcif_p.OnBeginLoop(mmcif_h), IOException); + mmcif_h.Add(StringRef("label_comp_id", 13)); + BOOST_MESSAGE(" label_entity_id"); + BOOST_CHECK_THROW(mmcif_p.OnBeginLoop(mmcif_h), IOException); + mmcif_h.Add(StringRef("label_entity_id", 15)); + BOOST_MESSAGE(" label_seq_id"); + BOOST_CHECK_THROW(mmcif_p.OnBeginLoop(mmcif_h), IOException); + mmcif_h.Add(StringRef("label_seq_id", 12)); + BOOST_MESSAGE(" type_symbol"); + BOOST_CHECK_THROW(mmcif_p.OnBeginLoop(mmcif_h), IOException); + mmcif_h.Add(StringRef("type_symbol", 11)); + BOOST_MESSAGE(" Cartn_x"); + BOOST_CHECK_THROW(mmcif_p.OnBeginLoop(mmcif_h), IOException); + mmcif_h.Add(StringRef("Cartn_x", 7)); + BOOST_MESSAGE(" Cartn_y"); + BOOST_CHECK_THROW(mmcif_p.OnBeginLoop(mmcif_h), IOException); + mmcif_h.Add(StringRef("Cartn_y", 7)); + BOOST_MESSAGE(" Cartn_z"); + BOOST_CHECK_THROW(mmcif_p.OnBeginLoop(mmcif_h), IOException); + mmcif_h.Add(StringRef("Cartn_z", 7)); + BOOST_CHECK_NO_THROW(mmcif_p.OnBeginLoop(mmcif_h)); + BOOST_MESSAGE(" done."); + mmcif_h.Clear(); + BOOST_MESSAGE(" testing entity items..."); + mmcif_h.SetCategory(StringRef("entity", 6)); + BOOST_MESSAGE(" id"); + BOOST_CHECK_THROW(mmcif_p.OnBeginLoop(mmcif_h), IOException); + mmcif_h.Add(StringRef("id", 2)); + BOOST_CHECK_NO_THROW(mmcif_p.OnBeginLoop(mmcif_h)); + BOOST_MESSAGE(" done."); + BOOST_MESSAGE(" done."); +} + +BOOST_AUTO_TEST_CASE(mmcif_parse_models) +{ + BOOST_MESSAGE(" Running mmcif_parse_models tests..."); + IOProfile profile; + + // positive w models + BOOST_MESSAGE(" true positive test for models..."); + { + mol::EntityHandle eh = mol::CreateEntity(); + MMCifReader mmcif_p("testfiles/mmcif/model_truepos.mmcif", eh, profile); + BOOST_CHECK_NO_THROW(mmcif_p.Parse()); + BOOST_REQUIRE_EQUAL(eh.GetChainCount(), 2); + BOOST_REQUIRE_EQUAL(eh.GetResidueCount(), 2); + BOOST_REQUIRE_EQUAL(eh.GetAtomCount(), 26); + } + BOOST_MESSAGE(" done."); + + // positive wo models atom_site.mmcif + BOOST_MESSAGE(" test absent atom_site.pdbx_PDB_model_num entry..."); + { + mol::EntityHandle eh = mol::CreateEntity(); + MMCifReader mmcif_p("testfiles/mmcif/atom_site.mmcif", eh, profile); + BOOST_CHECK_NO_THROW(mmcif_p.Parse()); + } + BOOST_MESSAGE(" done."); + // negative, more than 1 atom_site category + BOOST_MESSAGE(" testing more than one atom_site block..."); + { + mol::EntityHandle eh = mol::CreateEntity(); + MMCifReader mmcif_p("testfiles/mmcif/model_multi_atom_site.mmcif", eh, + profile); + BOOST_CHECK_THROW(mmcif_p.Parse(), IOException); + } + { + mol::EntityHandle eh = mol::CreateEntity(); + MMCifReader mmcif_p("testfiles/mmcif/model_multi_atom_site_inverted.mmcif", + eh, profile); + BOOST_CHECK_THROW(mmcif_p.Parse(), IOException); + } + BOOST_MESSAGE(" done."); + + BOOST_MESSAGE(" testing single model with model no. entry..."); + { + // build dummy header + mol::EntityHandle eh = mol::CreateEntity(); + StarLoopDesc tmmcif_h; + TestMMCifReaderProtected tmmcif_p("testfiles/mmcif/atom_site.mmcif", eh); + SetAtomSiteHeader(&tmmcif_h); + tmmcif_p.OnBeginLoop(tmmcif_h); + tmmcif_h.Add(StringRef("pdbx_PDB_model_num", 18)); + BOOST_CHECK_THROW(tmmcif_p.OnBeginLoop(tmmcif_h), IOException); + } + BOOST_MESSAGE(" done."); + + BOOST_MESSAGE(" done."); +} + +BOOST_AUTO_TEST_CASE(mmcif_changing_label_entity_id) +{ + BOOST_MESSAGE(" Running mmcif_changing_label_entity_id tests..."); + IOProfile profile; + + // positive + BOOST_MESSAGE(" true positive test..."); + { + mol::EntityHandle eh = mol::CreateEntity(); + MMCifReader mmcif_p("testfiles/mmcif/atom_site.mmcif", eh, profile); + BOOST_CHECK_NO_THROW(mmcif_p.Parse()); + } + BOOST_MESSAGE(" done."); + + // negative + BOOST_MESSAGE(" true negative test..."); + { + mol::EntityHandle eh = mol::CreateEntity(); + MMCifReader mmcif_p("testfiles/mmcif/changing_label_entity_id.mmcif", eh, + profile); + BOOST_CHECK_THROW(mmcif_p.Parse(), IOException); + } + BOOST_MESSAGE(" done."); + + BOOST_MESSAGE(" done."); +} + +BOOST_AUTO_TEST_CASE(mmcif_unknown_entity_type) +{ + BOOST_MESSAGE(" Running mmcif_unknown_entity_type tests..."); + + mol::EntityHandle eh = mol::CreateEntity(); + std::vector<StringRef> columns; + TestMMCifReaderProtected tmmcif_p("testfiles/mmcif/atom_site.mmcif", eh); + StarLoopDesc tmmcif_h; + + // build dummy header + tmmcif_h.SetCategory(StringRef("entity", 6)); + tmmcif_h.Add(StringRef("id", 2)); + tmmcif_h.Add(StringRef("type", 4)); + tmmcif_p.OnBeginLoop(tmmcif_h); + + // positive + BOOST_MESSAGE(" known type..."); + // build datarow + columns.push_back(StringRef("1", 1)); + columns.push_back(StringRef("polymer", 7)); + BOOST_CHECK_NO_THROW(tmmcif_p.ParseEntity(columns)); + columns.pop_back(); + columns.push_back(StringRef("non-polymer", 11)); + BOOST_CHECK_NO_THROW(tmmcif_p.ParseEntity(columns)); + columns.pop_back(); + columns.push_back(StringRef("water", 5)); + BOOST_CHECK_NO_THROW(tmmcif_p.ParseEntity(columns)); + BOOST_MESSAGE(" done."); + + // negative + BOOST_MESSAGE(" unknown type..."); + columns.pop_back(); + columns.push_back(StringRef("foo", 3)); + BOOST_CHECK_THROW(tmmcif_p.ParseEntity(columns), std::runtime_error); + BOOST_MESSAGE(" done."); + + BOOST_MESSAGE(" done."); +} + +BOOST_AUTO_TEST_CASE(mmcif_entity_tests) +{ + BOOST_MESSAGE(" Running mmcif_entity_tests..."); + mol::ChainHandle ch; + IOProfile profile; + + // positive + BOOST_MESSAGE(" fetching chain type..."); + { + mol::EntityHandle eh = mol::CreateEntity(); + MMCifReader mmcif_p("testfiles/mmcif/atom_site.mmcif", eh, profile); + mmcif_p.Parse(); + ch = eh.FindChain("A"); + BOOST_CHECK(ch.IsValid()); + BOOST_CHECK(ch.GetType() == mol::CHAINTYPE_POLY_PEPTIDE_L); + ch = eh.FindChain("C"); + BOOST_CHECK(ch.IsValid()); + BOOST_CHECK(ch.GetType() == mol::CHAINTYPE_POLY_PEPTIDE_L); + ch = eh.FindChain("O"); + BOOST_CHECK(ch.IsValid()); + BOOST_CHECK(ch.GetType() == mol::CHAINTYPE_WATER); + } + BOOST_MESSAGE(" done."); + // negative: no entity description + BOOST_MESSAGE(" check missing entity description..."); + { + mol::EntityHandle eh = mol::CreateEntity(); + MMCifReader mmcif_p("testfiles/mmcif/model_truepos.mmcif", + eh, + profile); + mmcif_p.Parse(); + ch = eh.FindChain("A"); + BOOST_CHECK(ch.IsValid()); + BOOST_CHECK(ch.GetType() == mol::CHAINTYPE_UNKNOWN); + ch = eh.FindChain("B"); + BOOST_CHECK(ch.IsValid()); + BOOST_CHECK(ch.GetType() == mol::CHAINTYPE_UNKNOWN); + } + BOOST_MESSAGE(" done."); + BOOST_MESSAGE(" fetch details..."); + { + mol::EntityHandle eh = mol::CreateEntity(); + MMCifReader mmcif_p("testfiles/mmcif/atom_site.mmcif", eh, profile); + mmcif_p.Parse(); + ch = eh.FindChain("A"); + BOOST_CHECK(ch.IsValid()); + BOOST_CHECK(ch.GetDescription() == "Very important information."); + } + BOOST_MESSAGE(" done."); + + BOOST_MESSAGE(" done."); +} + +BOOST_AUTO_TEST_CASE(mmcif_entity_poly_tests) +{ + conop::Conopology::Instance().SetDefaultBuilder("RBB"); + BOOST_MESSAGE(" Running mmcif_entity_poly_tests..."); + mol::ChainHandle ch; + IOProfile profile; + StarLoopDesc tmmcif_h; + + mol::EntityHandle eh = mol::CreateEntity(); + MMCifReader mmcif_p("testfiles/mmcif/atom_site.mmcif", eh, profile); + + mmcif_p.SetReadSeqRes(true); + mmcif_p.Parse(); + + seq::SequenceList seqres = mmcif_p.GetSeqRes(); + seq::SequenceHandle curr = seqres.FindSequence("A"); + BOOST_CHECK(curr.GetString() == "VTI"); + + BOOST_MESSAGE(" testing missing corresponding entity entry..."); + { + mol::EntityHandle eh = mol::CreateEntity(); + std::vector<StringRef> columns; + TestMMCifReaderProtected tmmcif_p("testfiles/mmcif/atom_site.mmcif", eh); + + tmmcif_h.SetCategory(StringRef("entity_poly", 11)); + tmmcif_h.Add(StringRef("entity_id", 9)); + tmmcif_p.OnBeginLoop(tmmcif_h); + + columns.push_back(StringRef("1", 1)); + BOOST_CHECK_THROW(tmmcif_p.ParseEntityPoly(columns), IOException); + } + BOOST_MESSAGE(" done."); + BOOST_MESSAGE(" testing type recognition..."); + { + TestMMCifReaderProtected tmmcif_p("testfiles/mmcif/atom_site.mmcif", eh); + std::vector<StringRef> columns; + + // create corresponding entity entry + tmmcif_h.Clear(); + tmmcif_h.SetCategory(StringRef("entity", 6)); + tmmcif_h.Add(StringRef("id", 2)); + tmmcif_h.Add(StringRef("type", 4)); + tmmcif_p.OnBeginLoop(tmmcif_h); + columns.push_back(StringRef("1", 1)); + columns.push_back(StringRef("polymer", 7)); + tmmcif_p.ParseEntity(columns); + columns.pop_back(); + columns.pop_back(); + + // build dummy entity_poly header + tmmcif_h.Clear(); + tmmcif_h.SetCategory(StringRef("entity_poly", 11)); + tmmcif_h.Add(StringRef("entity_id", 9)); + tmmcif_h.Add(StringRef("type", 4)); + tmmcif_p.OnBeginLoop(tmmcif_h); + + columns.push_back(StringRef("1", 1)); + columns.push_back(StringRef("polypeptide(D)", 14)); + BOOST_CHECK_NO_THROW(tmmcif_p.ParseEntityPoly(columns)); + columns.pop_back(); + columns.push_back(StringRef("polypeptide(L)", 14)); + BOOST_CHECK_NO_THROW(tmmcif_p.ParseEntityPoly(columns)); + columns.pop_back(); + columns.push_back(StringRef("polydeoxyribonucleotide", 23)); + BOOST_CHECK_NO_THROW(tmmcif_p.ParseEntityPoly(columns)); + columns.pop_back(); + columns.push_back(StringRef("polyribonucleotide", 18)); + BOOST_CHECK_NO_THROW(tmmcif_p.ParseEntityPoly(columns)); + columns.pop_back(); + columns.push_back(StringRef("polysaccharide(D)", 17)); + BOOST_CHECK_NO_THROW(tmmcif_p.ParseEntityPoly(columns)); + columns.pop_back(); + columns.push_back(StringRef("polysaccharide(L)", 17)); + BOOST_CHECK_NO_THROW(tmmcif_p.ParseEntityPoly(columns)); + columns.pop_back(); +columns.push_back(StringRef("polydeoxyribonucleotide/polyribonucleotide hybrid", + 49)); + BOOST_CHECK_NO_THROW(tmmcif_p.ParseEntityPoly(columns)); + columns.pop_back(); + columns.push_back(StringRef("other", 5)); + BOOST_CHECK_NO_THROW(tmmcif_p.ParseEntityPoly(columns)); + columns.pop_back(); + columns.pop_back(); + columns.push_back(StringRef("badbadprion", 11)); + BOOST_CHECK_THROW(tmmcif_p.ParseEntityPoly(columns), IOException); + columns.pop_back(); + } + BOOST_MESSAGE(" done."); + BOOST_MESSAGE(" testing pdbx_seq_one_letter_code reading..."); + { + TestMMCifReaderProtected tmmcif_p("testfiles/mmcif/atom_site.mmcif", eh); + std::vector<StringRef> columns; + + tmmcif_h.Clear(); + tmmcif_h.SetCategory(StringRef("entity", 6)); + tmmcif_h.Add(StringRef("id", 2)); + tmmcif_h.Add(StringRef("type", 4)); + tmmcif_p.OnBeginLoop(tmmcif_h); + columns.push_back(StringRef("1", 1)); + columns.push_back(StringRef("polymer", 7)); + tmmcif_p.ParseEntity(columns); + columns.pop_back(); + columns.pop_back(); + + tmmcif_h.Clear(); + tmmcif_h.SetCategory(StringRef("entity_poly", 11)); + tmmcif_h.Add(StringRef("entity_id", 9)); + tmmcif_h.Add(StringRef("type", 4)); + tmmcif_h.Add(StringRef("pdbx_seq_one_letter_code", 24)); + tmmcif_p.OnBeginLoop(tmmcif_h); + + columns.push_back(StringRef("1", 1)); + columns.push_back(StringRef("other", 5)); + columns.push_back(StringRef("ABRND", 5)); + tmmcif_p.SetReadSeqRes(true); + tmmcif_p.SetReadCanonicalSeqRes(true); + BOOST_CHECK_THROW(tmmcif_p.ParseEntityPoly(columns), IOException); + tmmcif_p.SetReadCanonicalSeqRes(false); + BOOST_CHECK_NO_THROW(tmmcif_p.ParseEntityPoly(columns)); + BOOST_CHECK_THROW(tmmcif_p.ParseEntityPoly(columns), IOException); + } + BOOST_MESSAGE(" done."); + BOOST_MESSAGE(" testing pdbx_seq_one_letter_code_can reading..."); + { + TestMMCifReaderProtected tmmcif_p("testfiles/mmcif/atom_site.mmcif", eh); + std::vector<StringRef> columns; + + tmmcif_h.Clear(); + tmmcif_h.SetCategory(StringRef("entity", 6)); + tmmcif_h.Add(StringRef("id", 2)); + tmmcif_h.Add(StringRef("type", 4)); + tmmcif_p.OnBeginLoop(tmmcif_h); + columns.push_back(StringRef("1", 1)); + columns.push_back(StringRef("polymer", 7)); + tmmcif_p.ParseEntity(columns); + columns.pop_back(); + columns.pop_back(); + + tmmcif_h.Clear(); + tmmcif_h.SetCategory(StringRef("entity_poly", 11)); + tmmcif_h.Add(StringRef("entity_id", 9)); + tmmcif_h.Add(StringRef("type", 4)); + tmmcif_h.Add(StringRef("pdbx_seq_one_letter_code_can", 28)); + tmmcif_p.OnBeginLoop(tmmcif_h); + tmmcif_p.SetReadCanonicalSeqRes(false); + columns.push_back(StringRef("1", 1)); + columns.push_back(StringRef("other", 5)); + columns.push_back(StringRef("ABRND", 5)); + tmmcif_p.SetReadSeqRes(true); + BOOST_CHECK_THROW(tmmcif_p.ParseEntityPoly(columns), IOException); + tmmcif_p.SetReadCanonicalSeqRes(true); + BOOST_CHECK_NO_THROW(tmmcif_p.ParseEntityPoly(columns)); + BOOST_CHECK_THROW(tmmcif_p.ParseEntityPoly(columns), IOException); + } + BOOST_MESSAGE(" done."); + + BOOST_MESSAGE(" done."); + conop::Conopology::Instance().SetDefaultBuilder("HEURISTIC"); +} + +BOOST_AUTO_TEST_CASE(mmcif_citation_tests) +{ + BOOST_MESSAGE(" Running mmcif_citation_tests..."); + //build dummy citation + mol::EntityHandle eh; + TestMMCifReaderProtected tmmcif_p("testfiles/mmcif/atom_site.mmcif", eh); + StarLoopDesc tmmcif_h; + std::vector<StringRef> columns; + + tmmcif_h.SetCategory(StringRef("citation", 8)); + tmmcif_h.Add(StringRef("id", 2)); + tmmcif_h.Add(StringRef("book_title", 10)); + tmmcif_h.Add(StringRef("journal_abbrev", 14)); + tmmcif_p.OnBeginLoop(tmmcif_h); + + columns.push_back(StringRef("Foo", 3)); + columns.push_back(StringRef("The Guide", 9)); + columns.push_back(StringRef(".", 1)); + + BOOST_CHECK_NO_THROW(tmmcif_p.ParseCitation(columns)); + + columns.pop_back(); + columns.pop_back(); + columns.push_back(StringRef(".", 1)); + columns.push_back(StringRef("Hitch", 5)); + + BOOST_CHECK_NO_THROW(tmmcif_p.ParseCitation(columns)); + + columns.pop_back(); + columns.pop_back(); + columns.push_back(StringRef("The Guide", 9)); + columns.push_back(StringRef("Hitch", 5)); + + BOOST_CHECK_THROW(tmmcif_p.ParseCitation(columns), IOException); + + BOOST_MESSAGE(" done."); +} + +BOOST_AUTO_TEST_CASE(mmcif_citation_author_tests) +{ + BOOST_MESSAGE(" Running mmcif_citation_author_tests..."); + + mol::EntityHandle eh = mol::CreateEntity(); + std::ifstream s("testfiles/mmcif/atom_site.mmcif"); + IOProfile profile; + MMCifReader mmcif_p(s, eh, profile); + BOOST_CHECK_NO_THROW(mmcif_p.Parse()); + + std::vector<String> authors = + mmcif_p.GetInfo().GetCitations().back().GetAuthorList(); + + BOOST_CHECK(authors.size() == 3); + BOOST_CHECK(authors[0] == "Whiskers, P.D."); + BOOST_CHECK(authors[1] == "McCheese, B.M."); + BOOST_CHECK(authors[2] == "Van Hummel, J.F."); + + BOOST_MESSAGE(" done."); +} + +BOOST_AUTO_TEST_CASE(mmcif_struct_ref) +{ + mol::EntityHandle eh = mol::CreateEntity(); + std::ifstream s("testfiles/mmcif/struct_ref.cif"); + IOProfile profile; + MMCifReader mmcif_p(s, eh, profile); + mmcif_p.Parse(); + MMCifInfoStructRefs refs=mmcif_p.GetInfo().GetStructRefs(); + BOOST_CHECK_EQUAL(refs.size(), 1); + MMCifInfoStructRefPtr sr1=refs[0]; + BOOST_CHECK_EQUAL(sr1->GetDBName(), "UNP"); + BOOST_CHECK_EQUAL(sr1->GetDBID(), "BLA2_BACCE"); + BOOST_CHECK_EQUAL(sr1->GetDBAccess(), "P04190"); + BOOST_CHECK_EQUAL(sr1->GetID(), "1"); + MMCifInfoStructRefSeqs seqs=sr1->GetAlignedSeqs(); + BOOST_CHECK_EQUAL(seqs.size(), 2); + BOOST_CHECK_EQUAL(seqs[0]->GetID(), "1"); + BOOST_CHECK_EQUAL(seqs[0]->GetChainName(), "A"); + BOOST_CHECK_EQUAL(seqs[0]->GetSeqBegin(), 1); + BOOST_CHECK_EQUAL(seqs[0]->GetSeqEnd(), 19); + BOOST_CHECK_EQUAL(seqs[0]->GetDBBegin(), 31); + BOOST_CHECK_EQUAL(seqs[0]->GetDBEnd(), 49); + BOOST_CHECK_EQUAL(seqs[1]->GetID(), "13"); + BOOST_CHECK_EQUAL(seqs[1]->GetChainName(), "B"); + BOOST_CHECK_EQUAL(seqs[1]->GetSeqBegin(), 1); + BOOST_CHECK_EQUAL(seqs[1]->GetSeqEnd(), 19); + BOOST_CHECK_EQUAL(seqs[1]->GetDBBegin(), 31); + BOOST_CHECK_EQUAL(seqs[1]->GetDBEnd(), 49); + MMCifInfoStructRefSeqDifs diffs=seqs[0]->GetDifs(); + BOOST_CHECK_EQUAL(diffs.size(), 1); + BOOST_CHECK_EQUAL(diffs[0]->GetSeqRNum(), 91); + BOOST_CHECK_EQUAL(diffs[0]->GetDetails(), "ENGINEERED MUTATION"); +} + +BOOST_AUTO_TEST_CASE(mmcif_refine_tests) +{ + BOOST_MESSAGE(" Running mmcif_refine_tests..."); + BOOST_MESSAGE(" positive test..."); + { + mol::EntityHandle eh = mol::CreateEntity(); + std::ifstream s("testfiles/mmcif/atom_site.mmcif"); + IOProfile profile; + MMCifReader mmcif_p(s, eh, profile); + BOOST_CHECK_NO_THROW(mmcif_p.Parse()); + BOOST_CHECK_CLOSE(mmcif_p.GetInfo().GetResolution(), 2.0f, 0.001f); + } + BOOST_MESSAGE(" done."); + BOOST_MESSAGE(" capturing fishy data lines..."); + { + mol::EntityHandle eh; + TestMMCifReaderProtected tmmcif_p("testfiles/mmcif/atom_site.mmcif", eh); + StarLoopDesc tmmcif_h; + std::vector<StringRef> columns; + + tmmcif_h.SetCategory(StringRef("refine", 6)); + tmmcif_h.Add(StringRef("entry_id", 8)); + tmmcif_h.Add(StringRef("ls_d_res_high", 13)); + tmmcif_h.Add(StringRef("ls_d_res_low", 12)); + tmmcif_p.OnBeginLoop(tmmcif_h); + + columns.push_back(StringRef("1Foo", 4)); + columns.push_back(StringRef("Foo", 3)); + columns.push_back(StringRef("1", 1)); + + BOOST_CHECK_THROW(tmmcif_p.ParseRefine(columns), IOException); + } + BOOST_MESSAGE(" done."); + BOOST_MESSAGE(" done."); +} + +BOOST_AUTO_TEST_CASE(mmcif_biounit_tests) +{ + BOOST_MESSAGE(" Running mmcif_biounit_tests..."); + //build dummy biounit + mol::EntityHandle eh = mol::CreateEntity(); + TestMMCifReaderProtected tmmcif_p("testfiles/mmcif/atom_site.mmcif", eh); + StarLoopDesc tmmcif_h; + std::vector<StringRef> columns; + + tmmcif_h.SetCategory(StringRef("pdbx_struct_assembly_gen", 24)); + tmmcif_h.Add(StringRef("assembly_id", 11)); + tmmcif_h.Add(StringRef("asym_id_list", 12)); + tmmcif_h.Add(StringRef("oper_expression", 15)); + tmmcif_p.OnBeginLoop(tmmcif_h); + + columns.push_back(StringRef("1", 1)); + columns.push_back(StringRef("A", 1)); + columns.push_back(StringRef("1", 1)); + + BOOST_CHECK_NO_THROW(tmmcif_p.ParsePdbxStructAssemblyGen(columns)); + BOOST_CHECK_THROW(tmmcif_p.OnEndData(), IOException); + + tmmcif_h.Clear(); + tmmcif_h.SetCategory(StringRef("pdbx_struct_assembly", 20)); + tmmcif_h.Add(StringRef("id", 2)); + columns.pop_back(); + columns.pop_back(); + columns.pop_back(); + columns.push_back(StringRef("1", 1)); + tmmcif_p.OnBeginLoop(tmmcif_h); + tmmcif_p.ParsePdbxStructAssembly(columns); + + tmmcif_h.Clear(); + tmmcif_h.SetCategory(StringRef("pdbx_struct_assembly_gen", 24)); + tmmcif_h.Add(StringRef("assembly_id", 11)); + tmmcif_h.Add(StringRef("asym_id_list", 12)); + tmmcif_h.Add(StringRef("oper_expression", 15)); + tmmcif_p.OnBeginLoop(tmmcif_h); + + columns.pop_back(); + columns.push_back(StringRef("1", 1)); + columns.push_back(StringRef("A", 1)); + columns.push_back(StringRef("1", 1)); + + BOOST_CHECK_NO_THROW(tmmcif_p.ParsePdbxStructAssemblyGen(columns)); + BOOST_CHECK_THROW(tmmcif_p.OnEndData(), IOException); + + tmmcif_h.Clear(); + tmmcif_h.SetCategory(StringRef("pdbx_struct_assembly_gen", 24)); + tmmcif_h.Add(StringRef("assembly_id", 11)); + tmmcif_h.Add(StringRef("asym_id_list", 12)); + tmmcif_h.Add(StringRef("oper_expression", 15)); + tmmcif_p.OnBeginLoop(tmmcif_h); + + columns.pop_back(); + columns.push_back(StringRef("1-Z", 3)); + BOOST_CHECK_THROW(tmmcif_p.ParsePdbxStructAssemblyGen(columns), IOException); + + columns.pop_back(); + columns.push_back(StringRef("--", 3)); + BOOST_CHECK_THROW(tmmcif_p.ParsePdbxStructAssemblyGen(columns), IOException); + + columns.pop_back(); + columns.push_back(StringRef("A-3", 3)); + BOOST_CHECK_THROW(tmmcif_p.ParsePdbxStructAssemblyGen(columns), IOException); + + tmmcif_h.Clear(); + tmmcif_h.SetCategory(StringRef("pdbx_struct_oper_list", 21)); + tmmcif_h.Add(StringRef("id", 2)); + tmmcif_h.Add(StringRef("type", 4)); + tmmcif_h.Add(StringRef("vector[1]", 9)); + tmmcif_h.Add(StringRef("vector[2]", 9)); + tmmcif_h.Add(StringRef("vector[3]", 9)); + tmmcif_h.Add(StringRef("matrix[1][1]", 12)); + tmmcif_h.Add(StringRef("matrix[1][2]", 12)); + tmmcif_h.Add(StringRef("matrix[1][3]", 12)); + tmmcif_h.Add(StringRef("matrix[2][1]", 12)); + tmmcif_h.Add(StringRef("matrix[2][2]", 12)); + tmmcif_h.Add(StringRef("matrix[2][3]", 12)); + tmmcif_h.Add(StringRef("matrix[3][1]", 12)); + tmmcif_h.Add(StringRef("matrix[3][2]", 12)); + tmmcif_h.Add(StringRef("matrix[3][3]", 12)); + + tmmcif_p.OnBeginLoop(tmmcif_h); + + columns.pop_back(); + columns.pop_back(); + columns.pop_back(); + columns.push_back(StringRef("1", 1)); + columns.push_back(StringRef("Nan", 3)); + columns.push_back(StringRef("1", 1)); + columns.push_back(StringRef("A", 1)); + columns.push_back(StringRef("3", 1)); + BOOST_CHECK_THROW(tmmcif_p.ParsePdbxStructOperList(columns), IOException); + + columns.pop_back(); + columns.pop_back(); + columns.pop_back(); + columns.pop_back(); + columns.pop_back(); + columns.push_back(StringRef("1", 1)); + columns.push_back(StringRef("Nan", 3)); + columns.push_back(StringRef("1", 1)); + columns.push_back(StringRef("2", 1)); + columns.push_back(StringRef("3", 1)); + columns.push_back(StringRef("1", 1)); + columns.push_back(StringRef("2", 1)); + columns.push_back(StringRef("3", 1)); + columns.push_back(StringRef("1", 1)); + columns.push_back(StringRef("2", 1)); + columns.push_back(StringRef("3", 1)); + columns.push_back(StringRef("1", 1)); + columns.push_back(StringRef("A", 1)); + columns.push_back(StringRef("3", 1)); + BOOST_CHECK_THROW(tmmcif_p.ParsePdbxStructOperList(columns), IOException); + + BOOST_MESSAGE(" done."); +} + +BOOST_AUTO_TEST_CASE(mmcif_struct_tests) +{ + BOOST_MESSAGE(" Running mmcif_struct_tests..."); + + mol::EntityHandle eh = mol::CreateEntity(); + TestMMCifReaderProtected tmmcif_p("testfiles/mmcif/atom_site.mmcif", eh); + StarLoopDesc tmmcif_h; + std::vector<StringRef> columns; + + tmmcif_h.SetCategory(StringRef("struct", 6)); + tmmcif_h.Add(StringRef("entry_id", 8)); + tmmcif_h.Add(StringRef("pdbx_CASP_flag", 14)); + tmmcif_h.Add(StringRef("pdbx_model_details", 18)); + tmmcif_h.Add(StringRef("pdbx_model_type_details", 23)); + tmmcif_h.Add(StringRef("pdbx_formula_weight", 19)); + tmmcif_p.OnBeginLoop(tmmcif_h); + + columns.push_back(StringRef("1BAR", 4)); + columns.push_back(StringRef("?", 1)); + columns.push_back(StringRef("?", 1)); + columns.push_back(StringRef("?", 1)); + columns.push_back(StringRef("1.0", 3)); + BOOST_CHECK_NO_THROW(tmmcif_p.ParseStruct(columns)); + + MMCifInfoStructDetails sd = MMCifInfoStructDetails(); + sd = tmmcif_p.GetInfo().GetStructDetails(); + + BOOST_CHECK(sd.GetCASPFlag() == '\0'); + BOOST_CHECK(sd.GetModelDetails() == ""); + BOOST_CHECK(sd.GetModelTypeDetails() == ""); + + columns.pop_back(); + columns.push_back(StringRef("A", 1)); + BOOST_CHECK_THROW(tmmcif_p.ParseStruct(columns), IOException); + + BOOST_MESSAGE(" done."); +} + +BOOST_AUTO_TEST_CASE(mmcif_struct_conf_tests) +{ + BOOST_MESSAGE(" Running mmcif_struct_conf_tests..."); + mol::EntityHandle eh = mol::CreateEntity(); + TestMMCifReaderProtected tmmcif_p("testfiles/mmcif/atom_site.mmcif", eh); + + BOOST_MESSAGE(" testing type validation"); + StringRef type = StringRef("HELX_P", 6); + BOOST_CHECK(tmmcif_p.DetermineSecStructType(type) == + TestMMCifReaderProtected::MMCIF_HELIX); + type = StringRef("HELX_OT_P", 9); + BOOST_CHECK(tmmcif_p.DetermineSecStructType(type) == + TestMMCifReaderProtected::MMCIF_HELIX); + type = StringRef("HELX_RH_P", 9); + BOOST_CHECK(tmmcif_p.DetermineSecStructType(type) == + TestMMCifReaderProtected::MMCIF_HELIX); + type = StringRef("HELX_RH_OT_P", 12); + BOOST_CHECK(tmmcif_p.DetermineSecStructType(type) == + TestMMCifReaderProtected::MMCIF_HELIX); + type = StringRef("HELX_RH_AL_P", 12); + BOOST_CHECK(tmmcif_p.DetermineSecStructType(type) == + TestMMCifReaderProtected::MMCIF_HELIX); + type = StringRef("HELX_RH_GA_P", 12); + BOOST_CHECK(tmmcif_p.DetermineSecStructType(type) == + TestMMCifReaderProtected::MMCIF_HELIX); + type = StringRef("HELX_RH_OM_P", 12); + BOOST_CHECK(tmmcif_p.DetermineSecStructType(type) == + TestMMCifReaderProtected::MMCIF_HELIX); + type = StringRef("HELX_RH_PI_P", 12); + BOOST_CHECK(tmmcif_p.DetermineSecStructType(type) == + TestMMCifReaderProtected::MMCIF_HELIX); + type = StringRef("HELX_RH_27_P", 12); + BOOST_CHECK(tmmcif_p.DetermineSecStructType(type) == + TestMMCifReaderProtected::MMCIF_HELIX); + type = StringRef("HELX_RH_3T_P", 12); + BOOST_CHECK(tmmcif_p.DetermineSecStructType(type) == + TestMMCifReaderProtected::MMCIF_HELIX); + type = StringRef("HELX_RH_PP_P", 12); + BOOST_CHECK(tmmcif_p.DetermineSecStructType(type) == + TestMMCifReaderProtected::MMCIF_HELIX); + type = StringRef("HELX_LH_P", 9); + BOOST_CHECK(tmmcif_p.DetermineSecStructType(type) == + TestMMCifReaderProtected::MMCIF_HELIX); + type = StringRef("HELX_LH_OT_P", 12); + BOOST_CHECK(tmmcif_p.DetermineSecStructType(type) == + TestMMCifReaderProtected::MMCIF_HELIX); + type = StringRef("HELX_LH_AL_P", 12); + BOOST_CHECK(tmmcif_p.DetermineSecStructType(type) == + TestMMCifReaderProtected::MMCIF_HELIX); + type = StringRef("HELX_LH_GA_P", 12); + BOOST_CHECK(tmmcif_p.DetermineSecStructType(type) == + TestMMCifReaderProtected::MMCIF_HELIX); + type = StringRef("HELX_LH_OM_P", 12); + BOOST_CHECK(tmmcif_p.DetermineSecStructType(type) == + TestMMCifReaderProtected::MMCIF_HELIX); + type = StringRef("HELX_LH_PI_P", 12); + BOOST_CHECK(tmmcif_p.DetermineSecStructType(type) == + TestMMCifReaderProtected::MMCIF_HELIX); + type = StringRef("HELX_LH_27_P", 12); + BOOST_CHECK(tmmcif_p.DetermineSecStructType(type) == + TestMMCifReaderProtected::MMCIF_HELIX); + type = StringRef("HELX_LH_3T_P", 12); + BOOST_CHECK(tmmcif_p.DetermineSecStructType(type) == + TestMMCifReaderProtected::MMCIF_HELIX); + type = StringRef("HELX_LH_PP_P", 12); + BOOST_CHECK(tmmcif_p.DetermineSecStructType(type) == + TestMMCifReaderProtected::MMCIF_HELIX); + type = StringRef("HELX_N", 6); + BOOST_CHECK(tmmcif_p.DetermineSecStructType(type) == + TestMMCifReaderProtected::MMCIF_HELIX); + type = StringRef("HELX_OT_N", 9); + BOOST_CHECK(tmmcif_p.DetermineSecStructType(type) == + TestMMCifReaderProtected::MMCIF_HELIX); + type = StringRef("HELX_RH_N", 9); + BOOST_CHECK(tmmcif_p.DetermineSecStructType(type) == + TestMMCifReaderProtected::MMCIF_HELIX); + type = StringRef("HELX_RH_OT_N", 12); + BOOST_CHECK(tmmcif_p.DetermineSecStructType(type) == + TestMMCifReaderProtected::MMCIF_HELIX); + type = StringRef("HELX_RH_A_N", 11); + BOOST_CHECK(tmmcif_p.DetermineSecStructType(type) == + TestMMCifReaderProtected::MMCIF_HELIX); + type = StringRef("HELX_RH_B_N", 11); + BOOST_CHECK(tmmcif_p.DetermineSecStructType(type) == + TestMMCifReaderProtected::MMCIF_HELIX); + type = StringRef("HELX_RH_Z_N", 11); + BOOST_CHECK(tmmcif_p.DetermineSecStructType(type) == + TestMMCifReaderProtected::MMCIF_HELIX); + type = StringRef("HELX_LH_N", 9); + BOOST_CHECK(tmmcif_p.DetermineSecStructType(type) == + TestMMCifReaderProtected::MMCIF_HELIX); + type = StringRef("HELX_LH_OT_N", 12); + BOOST_CHECK(tmmcif_p.DetermineSecStructType(type) == + TestMMCifReaderProtected::MMCIF_HELIX); + type = StringRef("HELX_LH_A_N", 11); + BOOST_CHECK(tmmcif_p.DetermineSecStructType(type) == + TestMMCifReaderProtected::MMCIF_HELIX); + type = StringRef("HELX_LH_B_N", 11); + BOOST_CHECK(tmmcif_p.DetermineSecStructType(type) == + TestMMCifReaderProtected::MMCIF_HELIX); + type = StringRef("HELX_LH_Z_N", 11); + BOOST_CHECK(tmmcif_p.DetermineSecStructType(type) == + TestMMCifReaderProtected::MMCIF_HELIX); + type = StringRef("TURN_P", 6); + BOOST_CHECK(tmmcif_p.DetermineSecStructType(type) == + TestMMCifReaderProtected::MMCIF_TURN); + type = StringRef("TURN_OT_P", 9); + BOOST_CHECK(tmmcif_p.DetermineSecStructType(type) == + TestMMCifReaderProtected::MMCIF_TURN); + type = StringRef("TURN_TY1_P", 10); + BOOST_CHECK(tmmcif_p.DetermineSecStructType(type) == + TestMMCifReaderProtected::MMCIF_TURN); + type = StringRef("TURN_TY1P_P", 11); + BOOST_CHECK(tmmcif_p.DetermineSecStructType(type) == + TestMMCifReaderProtected::MMCIF_TURN); + type = StringRef("TURN_TY2_P", 10); + BOOST_CHECK(tmmcif_p.DetermineSecStructType(type) == + TestMMCifReaderProtected::MMCIF_TURN); + type = StringRef("TURN_TY2P_P", 11); + BOOST_CHECK(tmmcif_p.DetermineSecStructType(type) == + TestMMCifReaderProtected::MMCIF_TURN); + type = StringRef("TURN_TY3_P", 10); + BOOST_CHECK(tmmcif_p.DetermineSecStructType(type) == + TestMMCifReaderProtected::MMCIF_TURN); + type = StringRef("TURN_TY3P_P", 11); + BOOST_CHECK(tmmcif_p.DetermineSecStructType(type) == + TestMMCifReaderProtected::MMCIF_TURN); + type = StringRef("STRN", 4); + BOOST_CHECK(tmmcif_p.DetermineSecStructType(type) == + TestMMCifReaderProtected::MMCIF_STRAND); + type = StringRef("Foo", 3); + BOOST_CHECK_THROW(tmmcif_p.DetermineSecStructType(type), IOException); + + BOOST_MESSAGE(" done."); + + BOOST_MESSAGE(" testing auth_chain_id switch..."); + StarLoopDesc tmmcif_h; + { + std::vector<StringRef> columns; + tmmcif_h.SetCategory(StringRef("struct_conf", 11)); + tmmcif_h.Add(StringRef("beg_label_asym_id", 17)); + tmmcif_h.Add(StringRef("beg_label_comp_id", 17)); + tmmcif_h.Add(StringRef("beg_label_seq_id", 16)); + tmmcif_h.Add(StringRef("conf_type_id", 12)); + tmmcif_h.Add(StringRef("end_label_asym_id", 17)); + tmmcif_h.Add(StringRef("end_label_comp_id", 17)); + tmmcif_h.Add(StringRef("end_label_seq_id", 16)); + tmmcif_h.Add(StringRef("id", 2)); + tmmcif_h.Add(StringRef("beg_auth_asym_id", 16)); + tmmcif_p.OnBeginLoop(tmmcif_h); + columns.push_back(StringRef("A", 1)); + columns.push_back(StringRef("ARG", 3)); + columns.push_back(StringRef("1", 1)); + columns.push_back(StringRef("HELX_RH_AL_P", 12)); + columns.push_back(StringRef("A", 1)); + columns.push_back(StringRef("ARG", 3)); + columns.push_back(StringRef("2", 1)); + columns.push_back(StringRef("DHLX1", 5)); + columns.push_back(StringRef("A", 1)); + tmmcif_p.SetAuthChainID(true); + BOOST_CHECK_NO_THROW(tmmcif_p.ParseStructConf(columns)); + tmmcif_p.SetAuthChainID(false); + BOOST_CHECK_NO_THROW(tmmcif_p.ParseStructConf(columns)); + tmmcif_h.Clear(); + tmmcif_h.SetCategory(StringRef("struct_conf", 11)); + tmmcif_h.Add(StringRef("beg_label_asym_id", 17)); + tmmcif_h.Add(StringRef("beg_label_comp_id", 17)); + tmmcif_h.Add(StringRef("beg_label_seq_id", 16)); + tmmcif_h.Add(StringRef("conf_type_id", 12)); + tmmcif_h.Add(StringRef("end_label_asym_id", 17)); + tmmcif_h.Add(StringRef("end_label_comp_id", 17)); + tmmcif_h.Add(StringRef("end_label_seq_id", 16)); + tmmcif_h.Add(StringRef("id", 2)); + tmmcif_p.OnBeginLoop(tmmcif_h); + columns.pop_back(); + tmmcif_p.SetAuthChainID(true); + BOOST_CHECK_THROW(tmmcif_p.ParseStructConf(columns), IOException); + } + tmmcif_p.SetAuthChainID(false); + BOOST_MESSAGE(" done."); + + BOOST_MESSAGE(" done."); +} + +BOOST_AUTO_TEST_CASE(mmcif_struct_sheet_range_tests) +{ + BOOST_MESSAGE(" Running mmcif_struct_sheet_range_tests..."); + mol::EntityHandle eh = mol::CreateEntity(); + TestMMCifReaderProtected tmmcif_p("testfiles/mmcif/atom_site.mmcif", eh); + + BOOST_MESSAGE(" testing auth_chain_id switch..."); + StarLoopDesc tmmcif_h; + std::vector<StringRef> columns; + tmmcif_h.SetCategory(StringRef("struct_sheet_range", 18)); + tmmcif_h.Add(StringRef("sheet_id", 8)); + tmmcif_h.Add(StringRef("beg_label_asym_id", 17)); + tmmcif_h.Add(StringRef("beg_label_comp_id", 17)); + tmmcif_h.Add(StringRef("beg_label_seq_id", 16)); + tmmcif_h.Add(StringRef("end_label_asym_id", 17)); + tmmcif_h.Add(StringRef("end_label_comp_id", 17)); + tmmcif_h.Add(StringRef("end_label_seq_id", 16)); + tmmcif_h.Add(StringRef("id", 2)); + tmmcif_h.Add(StringRef("beg_auth_asym_id", 16)); + tmmcif_p.OnBeginLoop(tmmcif_h); + columns.push_back(StringRef("Sheet1", 6)); + columns.push_back(StringRef("A", 1)); + columns.push_back(StringRef("ARG", 3)); + columns.push_back(StringRef("1", 1)); + columns.push_back(StringRef("A", 1)); + columns.push_back(StringRef("ARG", 3)); + columns.push_back(StringRef("2", 1)); + columns.push_back(StringRef("DSTRAND", 7)); + columns.push_back(StringRef("A", 1)); + tmmcif_p.SetAuthChainID(true); + BOOST_CHECK_NO_THROW(tmmcif_p.ParseStructSheetRange(columns)); + tmmcif_p.SetAuthChainID(false); + BOOST_CHECK_NO_THROW(tmmcif_p.ParseStructSheetRange(columns)); + tmmcif_h.Clear(); + tmmcif_h.SetCategory(StringRef("struct_sheet_range", 11)); + tmmcif_h.Add(StringRef("sheet_id", 8)); + tmmcif_h.Add(StringRef("beg_label_asym_id", 17)); + tmmcif_h.Add(StringRef("beg_label_comp_id", 17)); + tmmcif_h.Add(StringRef("beg_label_seq_id", 16)); + tmmcif_h.Add(StringRef("end_label_asym_id", 17)); + tmmcif_h.Add(StringRef("end_label_comp_id", 17)); + tmmcif_h.Add(StringRef("end_label_seq_id", 16)); + tmmcif_h.Add(StringRef("id", 2)); + tmmcif_p.OnBeginLoop(tmmcif_h); + columns.pop_back(); + tmmcif_p.SetAuthChainID(true); + BOOST_CHECK_THROW(tmmcif_p.ParseStructSheetRange(columns), IOException); + tmmcif_p.SetAuthChainID(false); + BOOST_MESSAGE(" done."); + + + + BOOST_MESSAGE(" done."); +} + +BOOST_AUTO_TEST_CASE(mmcif_parseatomident) +{ + BOOST_MESSAGE(" Running mmcif_parseatomident tests..."); + + mol::EntityHandle eh = mol::CreateEntity(); + + std::ifstream s("testfiles/mmcif/atom_site.mmcif"); + IOProfile profile; + StarLoopDesc tmmcif_h; + TestMMCifReaderProtected tmmcif_p(s, eh, profile); + std::vector<StringRef> columns; + String cif_chain_name; + String auth_chain_name; + StringRef res_name; + mol::ResNum resnum(0); + bool valid_res_num = false; + char alt_loc; + StringRef atom_name; + + BOOST_MESSAGE(" testing valid line"); + BOOST_MESSAGE(" done."); + // negative + //cols.push_back(StringRef("ATOM", 4)); + //BOOST_CHECK_THROW(tmmcif_p.ParseAtomIdent(cols, + // chain_name, + // res_name, + // resnum, + // atom_name, + // alt_loc), IOException); + // positive + //StarLoopDesc tmmcif_h; + //tmmcif_h.SetCategory(StringRef("atom_site", 9)); + // build header + //mmcif_h.Add(StringRef("AUTH_ASYM_ID", 12)); + /* + this->TryStoreIdx(AUTH_ASYM_ID, "auth_asym_id", header); + this->TryStoreIdx(ID, "id", header); + this->TryStoreIdx(LABEL_ALT_ID, "label_alt_id", header); + this->TryStoreIdx(LABEL_ASYM_ID, "label_asym_id", header); + this->TryStoreIdx(LABEL_ATOM_ID, "label_atom_id", header); + this->TryStoreIdx(LABEL_COMP_ID, "label_comp_id", header); + this->TryStoreIdx(LABEL_ENTITY_ID, "label_entity_id", header); + this->TryStoreIdx(LABEL_SEQ_ID, "label_seq_id", header); + this->TryStoreIdx(TYPE_SYMBOL, "type_symbol", header); + this->TryStoreIdx(CARTN_X, "Cartn_x", header); + this->TryStoreIdx(CARTN_Y, "Cartn_y", header); + this->TryStoreIdx(CARTN_Z, "Cartn_z", header); +*/ + + BOOST_MESSAGE(" testing profile to read calpha only"); + { + profile.calpha_only = true; + // set up dummy header to pre-set indices + SetAtomSiteHeader(&tmmcif_h); + tmmcif_p.OnBeginLoop(tmmcif_h); + // create CA dummy line + columns.push_back(StringRef("A", 1)); + columns.push_back(StringRef("2", 1)); + columns.push_back(StringRef(".", 1)); + columns.push_back(StringRef("A", 1)); + columns.push_back(StringRef("CA", 2)); + columns.push_back(StringRef("VAL", 3)); + columns.push_back(StringRef("1", 1)); // label_entity_id + columns.push_back(StringRef("11", 2)); // label_seq_id + columns.push_back(StringRef("C", 1)); // type_symbol + columns.push_back(StringRef("25.369", 6)); // Cartn_x + columns.push_back(StringRef("30.691", 6)); // Cartn_y + columns.push_back(StringRef("11.795", 6)); // Cartn_z + BOOST_CHECK_EQUAL(tmmcif_p.ParseAtomIdent(columns, auth_chain_name, + cif_chain_name, res_name, + resnum, valid_res_num, atom_name, + alt_loc), true); + columns.pop_back(); + columns.pop_back(); + columns.pop_back(); + columns.pop_back(); + columns.pop_back(); + columns.pop_back(); + columns.pop_back(); + columns.pop_back(); + columns.push_back(StringRef("CB", 2)); + columns.push_back(StringRef("VAL", 3)); + columns.push_back(StringRef("1", 1)); // label_entity_id + columns.push_back(StringRef("11", 2)); // label_seq_id + columns.push_back(StringRef("C", 1)); // type_symbol + columns.push_back(StringRef("25.369", 6)); // Cartn_x + columns.push_back(StringRef("30.691", 6)); // Cartn_y + columns.push_back(StringRef("11.795", 6)); // Cartn_z + BOOST_CHECK_EQUAL(tmmcif_p.ParseAtomIdent(columns, auth_chain_name, + cif_chain_name, res_name, + resnum, valid_res_num, atom_name, + alt_loc), false); + } + BOOST_MESSAGE(" done."); + + BOOST_MESSAGE(" done."); +} + +/* +BOOST_AUTO_TEST_CASE(mmcif_parseandaddatom) +{ + mol::EntityHandle eh = mol::CreateEntity(); + + BOOST_MESSAGE(" Running mmcif_parseandaddatom tests..."); + std::ifstream s("testfiles/mmcif/atom_site.mmcif"); + TestMMCifReaderProtected tmmcif_p(s, eh, IOProfile()); + std::vector<StringRef> cols; + + //BOOST_MESSAGE(" testing short atom_site entry"); + //cols.push_back(StringRef("ATOM", 4)); + //BOOST_CHECK_THROW(tmmcif_p.ParseAndAddAtom(cols), IOException); + //BOOST_MESSAGE(" done."); +} +*/ + +BOOST_AUTO_TEST_CASE(mmcif_testreader) +{ + BOOST_MESSAGE(" Running mmcif_testreader tests..."); + mol::EntityHandle eh = mol::CreateEntity(); + std::ifstream s("testfiles/mmcif/atom_site.mmcif"); + IOProfile profile; + MMCifReader mmcif_p(s, eh, profile); + + mmcif_p.SetRestrictChains("A O C"); + + BOOST_MESSAGE(" testing Parse()..."); + BOOST_CHECK_NO_THROW(mmcif_p.Parse()); + + BOOST_REQUIRE_EQUAL(eh.GetChainCount(), 3); + BOOST_REQUIRE_EQUAL(eh.GetResidueCount(), 14); + BOOST_REQUIRE_EQUAL(eh.GetAtomCount(), 35); + + mol::ChainHandle ch = eh.FindChain("A"); + BOOST_CHECK(ch.IsValid()); + BOOST_MESSAGE(" done."); + + BOOST_MESSAGE(" testing numbering water..."); + ch = eh.FindChain("O"); + BOOST_CHECK(ch.IsValid()); + mol::ResidueHandleList rl = ch.GetResidueList(); + mol::ResidueHandleList::const_iterator rs; + int i = 1; + for (rs = rl.begin(); rs != rl.end(); ++rs, ++i) { + BOOST_CHECK_EQUAL(rs->GetNumber().GetNum(), i); + } + BOOST_MESSAGE(" done."); + + BOOST_MESSAGE(" testing secondary structure..."); + // pick chains, iterate residues, check for correct sec.struct. + ch = eh.FindChain("A"); + rl = ch.GetResidueList(); + BOOST_CHECK_EQUAL(rl[0].GetSecStructure().IsHelical(), true); + BOOST_CHECK_EQUAL(rl[1].GetSecStructure().IsHelical(), true); + BOOST_CHECK_EQUAL(rl[2].GetSecStructure().IsExtended(), true); + ch = eh.FindChain("C"); + rl = ch.GetResidueList(); + BOOST_CHECK_EQUAL(rl[0].GetSecStructure().IsExtended(), true); + BOOST_MESSAGE(" done."); + + BOOST_MESSAGE(" reading data fields which should not fail..."); + 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().GetChainList().back() == + "F"); + MMCifInfoBioUnit bu = mmcif_p.GetInfo().GetBioUnits().back(); + BOOST_CHECK(bu.GetOperations().back().back()->GetType() == + "identity operation"); + MMCifInfoStructDetails sd = mmcif_p.GetInfo().GetStructDetails(); + BOOST_CHECK(sd.GetEntryID() == "1BAR"); + BOOST_CHECK(sd.GetTitle() == "A Title"); + BOOST_CHECK(sd.GetCASPFlag() == 'Y'); + BOOST_CHECK(sd.GetDescriptor() == "ADENYLATE KINASE"); + BOOST_CHECK_CLOSE(sd.GetMass(), 1.0f, 0.001f); + BOOST_CHECK(sd.GetMassMethod() == "Good Guess"); + BOOST_CHECK(sd.GetModelDetails() == "Even better guessing"); + BOOST_CHECK(sd.GetModelTypeDetails() == "Guess"); + MMCifInfoObsolete obs = mmcif_p.GetInfo().GetObsoleteInfo(); + BOOST_CHECK(obs.GetDate() == "2011-08-31"); + BOOST_CHECK(obs.GetID() == "Obsolete"); + BOOST_CHECK(obs.GetPDBID() == "1FOO"); + BOOST_CHECK(obs.GetReplacedPDBID() == "2BAR"); + BOOST_MESSAGE(" done."); + + BOOST_MESSAGE(" done."); +} + +BOOST_AUTO_TEST_SUITE_END(); diff --git a/modules/io/tests/testfiles/mmcif/3T6C.cif.gz b/modules/io/tests/testfiles/mmcif/3T6C.cif.gz new file mode 100644 index 0000000000000000000000000000000000000000..afda31f696dd24fcbecee1d652b7431b93d5dca4 Binary files /dev/null and b/modules/io/tests/testfiles/mmcif/3T6C.cif.gz differ diff --git a/modules/io/tests/testfiles/mmcif/atom_site.mmcif b/modules/io/tests/testfiles/mmcif/atom_site.mmcif new file mode 100644 index 0000000000000000000000000000000000000000..ce890cf9d3be305019cbc431726433df8a06beee --- /dev/null +++ b/modules/io/tests/testfiles/mmcif/atom_site.mmcif @@ -0,0 +1,195 @@ +data_1BAR + +# this file is also used in the mmcif_parse_models tests for a true negative +# test, hence it is not allowed to carry atom_site.pdbx_PDB_model_num entries + +# this file is also used in the mmcif_mmcif_chaintype_setting test for a true +# positive test, hence the entity category is not to be changed + +_pdbx_database_PDB_obs_spr.id OBSLTE +_pdbx_database_PDB_obs_spr.date 2011-08-31 +_pdbx_database_PDB_obs_spr.pdb_id 1FOO +_pdbx_database_PDB_obs_spr.replace_pdb_id 2BAR + +loop_ +_entity.id +_entity.type +_entity.pdbx_description +1 polymer +; Very important information. +; +5 water . + +_entity_poly.entity_id 1 +_entity_poly.type 'polypeptide(L)' +_entity_poly.nstd_linkage no +_entity_poly.nstd_monomer no +_entity_poly.pdbx_seq_one_letter_code 'VTI' + +loop_ +_citation.id +_citation.abstract_id_CAS +_citation.title +_citation.journal_volume +_citation.journal_full +_citation.page_first +_citation.page_last +_citation.pdbx_database_id_DOI +_citation.pdbx_database_id_PubMed +_citation.year +primary 58-08-2 'Very important, but we won't tell' 1 'Some Journal' 0 10 0815 0815 2011 + +# the authors are not ordered on purpose for unit tests +loop_ +_citation_author.citation_id +_citation_author.ordinal +_citation_author.name + primary 1 'Whiskers, P.D.' + primary 3 'Van Hummel, J.F.' + primary 2 'McCheese, B.M.' + +_exptl.entry_id experiment1 +_exptl.method 'Deep-fry' + +_refine.entry_id '1BAR' +_refine.ls_d_res_high 2.0 +_refine.ls_d_res_low 1.5 + +# biounit begin +loop_ +_pdbx_struct_assembly.id +_pdbx_struct_assembly.details +_pdbx_struct_assembly.method_details +_pdbx_struct_assembly.oligomeric_details +_pdbx_struct_assembly.oligomeric_count +1 author_defined_assembly ? monomeric 1 +2 author_defined_assembly ? monomeric 1 + +loop_ +_pdbx_struct_assembly_gen.assembly_id +_pdbx_struct_assembly_gen.oper_expression +_pdbx_struct_assembly_gen.asym_id_list +1 1 A,C,E +2 1 B,D,F + +_pdbx_struct_oper_list.id 1 +_pdbx_struct_oper_list.type 'identity operation' +_pdbx_struct_oper_list.name 1_555 +_pdbx_struct_oper_list.symmetry_operation x,y,z +_pdbx_struct_oper_list.matrix[1][1] 1.0000000000 +_pdbx_struct_oper_list.matrix[1][2] 0.0000000000 +_pdbx_struct_oper_list.matrix[1][3] 0.0000000000 +_pdbx_struct_oper_list.vector[1] 1.1000000000 +_pdbx_struct_oper_list.matrix[2][1] 0.0000000000 +_pdbx_struct_oper_list.matrix[2][2] 1.0000000000 +_pdbx_struct_oper_list.matrix[2][3] 0.0000000000 +_pdbx_struct_oper_list.vector[2] 0.5000000000 +_pdbx_struct_oper_list.matrix[3][1] 0.0000000000 +_pdbx_struct_oper_list.matrix[3][2] 0.0000000000 +_pdbx_struct_oper_list.matrix[3][3] 1.0000000000 +_pdbx_struct_oper_list.vector[3] 23.3000000000 +# biounit end + +_struct.entry_id 1BAR +_struct.title 'A Title' +_struct.pdbx_CASP_flag Y +_struct.pdbx_descriptor 'ADENYLATE KINASE' +_struct.pdbx_formula_weight 1.0 +_struct.pdbx_formula_weight_method 'Good Guess' +_struct.pdbx_model_details 'Even better guessing' +_struct.pdbx_model_type_details 'Guess' + +# do not change anything, here +loop_ +_struct_conf.id +_struct_conf.conf_type_id +_struct_conf.beg_label_comp_id +_struct_conf.beg_label_asym_id +_struct_conf.beg_label_seq_id +_struct_conf.end_label_comp_id +_struct_conf.end_label_asym_id +_struct_conf.end_label_seq_id +_struct_conf.details +HELX1 HELX_RH_AL_P VAL A 11 THR A 12 . +STRN1 STRN ILE A 13 ILE A 13 . +HELX1 HELX_RH_AL_P ILE Z 1 ILE Z 1 . + +loop_ +_struct_sheet_range.sheet_id +_struct_sheet_range.id +_struct_sheet_range.beg_label_comp_id +_struct_sheet_range.beg_label_asym_id +_struct_sheet_range.beg_label_seq_id +_struct_sheet_range.end_label_comp_id +_struct_sheet_range.end_label_asym_id +_struct_sheet_range.end_label_seq_id +sheet_1 strand_a APS C 1 APS C 1 + +loop_ +_atom_site.group_PDB +_atom_site.type_symbol +_atom_site.label_atom_id +_atom_site.label_comp_id +_atom_site.label_asym_id +_atom_site.label_seq_id +_atom_site.label_alt_id +_atom_site.label_entity_id +_atom_site.Cartn_x +_atom_site.Cartn_y +_atom_site.Cartn_z +_atom_site.occupancy +_atom_site.B_iso_or_equiv +_atom_site.footnote_id +_atom_site.auth_seq_id +_atom_site.id +_atom_site.pdbx_PDB_ins_code +_atom_site.auth_asym_id +ATOM N N VAL A 11 . 1 25.369 30.691 11.795 1.00 17.93 . 11 1 ? A +ATOM C CA VAL A 11 . 1 25.970 31.965 12.332 1.00 17.75 . 11 2 ? A +ATOM C C VAL A 11 . 1 25.569 32.010 13.808 1.00 17.83 . 11 3 ? A +ATOM O O VAL A 11 . 1 24.735 31.190 14.167 1.00 17.53 . 11 4 ? A +ATOM C CB VAL A 11 . 1 25.379 33.146 11.540 1.00 17.66 . 11 5 ? A +ATOM C CG1 VAL A 11 . 1 25.584 33.034 10.030 1.00 18.86 . 11 6 ? A +ATOM C CG2 VAL A 11 . 1 23.933 33.309 11.872 1.00 17.12 . 11 7 ? A +ATOM N N THR A 12 . 1 26.095 32.930 14.590 1.00 18.97 4 12 8 ? A +ATOM C CA THR A 12 . 1 25.734 32.995 16.032 1.00 19.80 4 12 9 ? A +ATOM C C THR A 12 . 1 24.695 34.106 16.113 1.00 20.92 4 12 10 ? A +ATOM O O THR A 12 . 1 24.869 35.118 15.421 1.00 21.84 4 12 11 ? A +ATOM C CB THR A 12 . 1 26.911 33.346 17.018 1.00 20.51 4 12 12 ? A +ATOM O OG1 THR A 12 3 1 27.946 33.921 16.183 0.50 20.29 4 12 13 ? A +ATOM O OG1 THR A 12 4 1 27.769 32.142 17.103 0.50 20.59 4 12 14 ? A +ATOM C CG2 THR A 12 3 1 27.418 32.181 17.878 0.50 20.47 4 12 15 ? A +ATOM C CG2 THR A 12 4 1 26.489 33.778 18.426 0.50 20.00 4 12 16 ? A +ATOM N N ILE A 13 . 1 23.664 33.855 16.884 1.00 22.08 . 13 17 ? A +ATOM C CA ILE A 13 . 1 22.623 34.850 17.093 1.00 23.44 . 13 18 ? A +ATOM C C ILE A 13 . 1 22.657 35.113 18.610 1.00 25.77 . 13 19 ? A +ATOM O O ILE A 13 . 1 23.123 34.250 19.406 1.00 26.28 . 13 20 ? A +ATOM C CB ILE A 13 . 1 21.236 34.463 16.492 1.00 22.67 . 13 21 ? A +ATOM C CG1 ILE A 13 . 1 20.478 33.469 17.371 1.00 22.14 . 13 22 ? A +ATOM C CG2 ILE A 13 . 1 21.357 33.986 15.016 1.00 21.75 . 13 23 ? A +# - - - - data truncated for brevity - - - - +HETATM C C1 APS C 1 1 1 4.171 29.012 7.116 0.58 17.27 1 300 101 ? A +HETATM C C2 APS C 1 1 1 4.949 27.758 6.793 0.58 16.95 1 300 102 ? A +HETATM O O3 APS C 1 1 1 4.800 26.678 7.393 0.58 16.85 1 300 103 ? A +HETATM N N4 APS C 1 1 1 5.930 27.841 5.869 0.58 16.43 1 300 104 ? A +# - - - - data truncated for brevity - - - - +# chain to be ignored by 'restrict_chains' feature +ATOM N N ILE Z 1 . 1 23.664 33.855 16.884 1.00 22.08 . 1 17 ? Z +ATOM C CA ILE Z 1 . 1 22.623 34.850 17.093 1.00 23.44 . 1 18 ? Z +ATOM C C ILE Z 1 . 1 22.657 35.113 18.610 1.00 25.77 . 1 19 ? Z +ATOM O O ILE Z 1 . 1 23.123 34.250 19.406 1.00 26.28 . 1 20 ? Z +ATOM C CB ILE Z 1 . 1 21.236 34.463 16.492 1.00 22.67 . 1 21 ? Z +ATOM C CG1 ILE Z 1 . 1 20.478 33.469 17.371 1.00 22.14 . 1 22 ? Z +ATOM C CG2 ILE Z 1 . 1 21.357 33.986 15.016 1.00 21.75 . 1 23 ? Z +# +# H2O +HETATM O O HOH O . . 5 -5.322 10.972 9.720 0.95 7.25 . 2001 2731 ? B +HETATM O O HOH O . . 5 4.148 4.008 12.383 0.64 14.61 . 2002 2732 ? B +HETATM O O HOH O . . 5 -2.238 5.875 8.525 0.92 15.43 . 2003 2733 ? B +HETATM O O HOH O . . 5 0.114 4.343 8.960 0.45 20.65 . 2004 2734 ? B +HETATM O O HOH O . . 5 1.045 9.537 8.846 0.98 4.03 . 2005 2735 ? B +HETATM O O HOH O . . 5 -0.532 11.899 9.196 1.00 4.09 . 2006 2736 ? B +HETATM O O HOH O . . 5 0.936 18.270 7.581 0.97 5.52 . 2007 2737 ? B +HETATM O O HOH O . . 5 -6.561 13.498 9.629 1.00 8.03 . 2008 2738 ? B +HETATM O O HOH O . . 5 -11.465 18.494 11.144 0.81 14.02 . 2009 2739 ? B +HETATM O O HOH O . . 5 12.795 11.508 13.991 0.90 35.55 . 2010 2740 ? B diff --git a/modules/io/tests/testfiles/mmcif/changing_label_entity_id.mmcif b/modules/io/tests/testfiles/mmcif/changing_label_entity_id.mmcif new file mode 100644 index 0000000000000000000000000000000000000000..c19da79d7f7e6c5bbdb1f4f8f473d92ebce2d69d --- /dev/null +++ b/modules/io/tests/testfiles/mmcif/changing_label_entity_id.mmcif @@ -0,0 +1,26 @@ +data_1BAR + +# this file is also used in the mmcif_parse_models tests for a true negative +# test, hence it is not allowed to carry atom_site.pdbx_PDB_model_num entries + +loop_ +_atom_site.group_PDB +_atom_site.type_symbol +_atom_site.label_atom_id +_atom_site.label_comp_id +_atom_site.label_asym_id +_atom_site.label_seq_id +_atom_site.label_alt_id +_atom_site.label_entity_id +_atom_site.Cartn_x +_atom_site.Cartn_y +_atom_site.Cartn_z +_atom_site.occupancy +_atom_site.B_iso_or_equiv +_atom_site.footnote_id +_atom_site.auth_seq_id +_atom_site.id +_atom_site.pdbx_PDB_ins_code +_atom_site.auth_asym_id +ATOM N N VAL A 11 . 1 25.369 30.691 11.795 1.00 17.93 . 11 1 ? A +ATOM C CA VAL A 11 . 2 25.970 31.965 12.332 1.00 17.75 . 11 2 ? A diff --git a/modules/io/tests/testfiles/mmcif/model_multi_atom_site.mmcif b/modules/io/tests/testfiles/mmcif/model_multi_atom_site.mmcif new file mode 100644 index 0000000000000000000000000000000000000000..760e7556496ab0d41268fe46f8aaab2d6418b3b0 --- /dev/null +++ b/modules/io/tests/testfiles/mmcif/model_multi_atom_site.mmcif @@ -0,0 +1,120 @@ +data_1MBA +# derived from 2JSP + +loop_ +_atom_site.group_PDB +_atom_site.id +_atom_site.type_symbol +_atom_site.label_atom_id +_atom_site.label_alt_id +_atom_site.label_comp_id +_atom_site.label_asym_id +_atom_site.label_entity_id +_atom_site.label_seq_id +_atom_site.pdbx_PDB_ins_code +_atom_site.Cartn_x +_atom_site.Cartn_y +_atom_site.Cartn_z +_atom_site.auth_seq_id +_atom_site.auth_comp_id +_atom_site.auth_asym_id +_atom_site.auth_atom_id +_atom_site.pdbx_PDB_model_num +ATOM 1 N N . ALA A 1 1 ? 13.847 16.632 5.806 1 ALA A N 1 +ATOM 2 C CA . ALA A 1 1 ? 14.050 15.239 5.351 1 ALA A CA 1 +ATOM 3 C C . ALA A 1 1 ? 15.057 15.051 4.185 1 ALA A C 1 +ATOM 4 O O . ALA A 1 1 ? 16.242 14.860 4.448 1 ALA A O 1 +ATOM 5 C CB . ALA A 1 1 ? 12.682 14.599 5.070 1 ALA A CB 1 +ATOM 6 H H1 . ALA A 1 1 ? 14.344 17.346 5.293 1 ALA A H1 1 +ATOM 7 H HA . ALA A 1 1 ? 14.425 14.660 6.196 1 ALA A HA 1 +ATOM 8 H HB1 . ALA A 1 1 ? 12.168 15.166 4.295 1 ALA A HB1 1 +ATOM 9 H HB2 . ALA A 1 1 ? 12.824 13.571 4.734 1 ALA A HB2 1 +ATOM 10 H HB3 . ALA A 1 1 ? 12.085 14.603 5.981 1 ALA A HB3 1 +ATOM 11 N N . VAL B 1 2 ? 14.602 15.209 2.935 2 VAL A N 1 +ATOM 12 C CA . VAL B 1 2 ? 15.402 15.012 1.699 2 VAL A CA 1 +ATOM 13 C C . VAL B 1 2 ? 14.579 15.343 0.431 2 VAL A C 1 +ATOM 14 O O . VAL B 1 2 ? 14.518 16.503 0.039 2 VAL A O 1 +ATOM 15 C CB . VAL B 1 2 ? 16.165 13.656 1.685 2 VAL A CB 1 +ATOM 16 C CG1 . VAL B 1 2 ? 15.292 12.399 1.812 2 VAL A CG1 1 +ATOM 17 C CG2 . VAL B 1 2 ? 17.136 13.551 0.504 2 VAL A CG2 1 +ATOM 18 H H . VAL B 1 2 ? 13.617 15.489 2.821 2 VAL A H 1 +ATOM 19 H HA . VAL B 1 2 ? 16.285 15.650 1.689 2 VAL A HA 1 +ATOM 20 H HB . VAL B 1 2 ? 16.859 13.653 2.526 2 VAL A HB 1 +ATOM 21 H HG11 . VAL B 1 2 ? 15.925 11.512 1.791 2 VAL A HG11 1 +ATOM 22 H HG12 . VAL B 1 2 ? 14.743 12.431 2.754 2 VAL A HG12 1 +ATOM 23 H HG13 . VAL B 1 2 ? 14.586 12.361 0.982 2 VAL A HG13 1 +ATOM 24 H HG21 . VAL B 1 2 ? 17.872 14.353 0.565 2 VAL A HG21 1 +ATOM 25 H HG22 . VAL B 1 2 ? 17.645 12.588 0.536 2 VAL A HG22 1 +ATOM 26 H HG23 . VAL B 1 2 ? 16.583 13.637 -0.431 2 VAL A HG23 1 +# +ATOM 1 N N . ALA A 1 1 ? 13.847 16.632 5.806 1 ALA A N 2 +ATOM 2 C CA . ALA A 1 1 ? 14.050 15.239 5.351 1 ALA A CA 2 +ATOM 3 C C . ALA A 1 1 ? 15.057 15.051 4.185 1 ALA A C 2 +ATOM 4 O O . ALA A 1 1 ? 16.242 14.860 4.448 1 ALA A O 2 +ATOM 5 C CB . ALA A 1 1 ? 12.682 14.599 5.070 1 ALA A CB 2 +ATOM 6 H H1 . ALA A 1 1 ? 14.344 17.346 5.293 1 ALA A H1 2 +ATOM 7 H HA . ALA A 1 1 ? 14.425 14.660 6.196 1 ALA A HA 2 +ATOM 8 H HB1 . ALA A 1 1 ? 12.168 15.166 4.295 1 ALA A HB1 2 +ATOM 9 H HB2 . ALA A 1 1 ? 12.824 13.571 4.734 1 ALA A HB2 2 +ATOM 10 H HB3 . ALA A 1 1 ? 12.085 14.603 5.981 1 ALA A HB3 2 +ATOM 11 N N . VAL B 1 2 ? 14.602 15.209 2.935 2 VAL A N 2 +ATOM 12 C CA . VAL B 1 2 ? 15.402 15.012 1.699 2 VAL A CA 2 +ATOM 13 C C . VAL B 1 2 ? 14.579 15.343 0.431 2 VAL A C 2 +ATOM 14 O O . VAL B 1 2 ? 14.518 16.503 0.039 2 VAL A O 2 +ATOM 15 C CB . VAL B 1 2 ? 16.165 13.656 1.685 2 VAL A CB 2 +ATOM 16 C CG1 . VAL B 1 2 ? 15.292 12.399 1.812 2 VAL A CG1 2 +ATOM 17 C CG2 . VAL B 1 2 ? 17.136 13.551 0.504 2 VAL A CG2 2 +ATOM 18 H H . VAL B 1 2 ? 13.617 15.489 2.821 2 VAL A H 2 +ATOM 19 H HA . VAL B 1 2 ? 16.285 15.650 1.689 2 VAL A HA 2 +ATOM 20 H HB . VAL B 1 2 ? 16.859 13.653 2.526 2 VAL A HB 2 +ATOM 21 H HG11 . VAL B 1 2 ? 15.925 11.512 1.791 2 VAL A HG11 2 +ATOM 22 H HG12 . VAL B 1 2 ? 14.743 12.431 2.754 2 VAL A HG12 2 +ATOM 23 H HG13 . VAL B 1 2 ? 14.586 12.361 0.982 2 VAL A HG13 2 +ATOM 24 H HG21 . VAL B 1 2 ? 17.872 14.353 0.565 2 VAL A HG21 2 +ATOM 25 H HG22 . VAL B 1 2 ? 17.645 12.588 0.536 2 VAL A HG22 2 +ATOM 26 H HG23 . VAL B 1 2 ? 16.583 13.637 -0.431 2 VAL A HG23 2 +# additional atom_site block +loop_ +_atom_site.group_PDB +_atom_site.id +_atom_site.type_symbol +_atom_site.label_atom_id +_atom_site.label_alt_id +_atom_site.label_comp_id +_atom_site.label_asym_id +_atom_site.label_entity_id +_atom_site.label_seq_id +_atom_site.pdbx_PDB_ins_code +_atom_site.Cartn_x +_atom_site.Cartn_y +_atom_site.Cartn_z +_atom_site.auth_seq_id +_atom_site.auth_comp_id +_atom_site.auth_asym_id +_atom_site.auth_atom_id +ATOM 1 N N . ALA A 1 1 ? 13.847 16.632 5.806 1 ALA A N +ATOM 2 C CA . ALA A 1 1 ? 14.050 15.239 5.351 1 ALA A CA +ATOM 3 C C . ALA A 1 1 ? 15.057 15.051 4.185 1 ALA A C +ATOM 4 O O . ALA A 1 1 ? 16.242 14.860 4.448 1 ALA A O +ATOM 5 C CB . ALA A 1 1 ? 12.682 14.599 5.070 1 ALA A CB +ATOM 6 H H1 . ALA A 1 1 ? 14.344 17.346 5.293 1 ALA A H1 +ATOM 7 H HA . ALA A 1 1 ? 14.425 14.660 6.196 1 ALA A HA +ATOM 8 H HB1 . ALA A 1 1 ? 12.168 15.166 4.295 1 ALA A HB1 +ATOM 9 H HB2 . ALA A 1 1 ? 12.824 13.571 4.734 1 ALA A HB2 +ATOM 10 H HB3 . ALA A 1 1 ? 12.085 14.603 5.981 1 ALA A HB3 +ATOM 11 N N . VAL B 1 2 ? 14.602 15.209 2.935 2 VAL A N +ATOM 12 C CA . VAL B 1 2 ? 15.402 15.012 1.699 2 VAL A CA +ATOM 13 C C . VAL B 1 2 ? 14.579 15.343 0.431 2 VAL A C +ATOM 14 O O . VAL B 1 2 ? 14.518 16.503 0.039 2 VAL A O +ATOM 15 C CB . VAL B 1 2 ? 16.165 13.656 1.685 2 VAL A CB +ATOM 16 C CG1 . VAL B 1 2 ? 15.292 12.399 1.812 2 VAL A CG1 +ATOM 17 C CG2 . VAL B 1 2 ? 17.136 13.551 0.504 2 VAL A CG2 +ATOM 18 H H . VAL B 1 2 ? 13.617 15.489 2.821 2 VAL A H +ATOM 19 H HA . VAL B 1 2 ? 16.285 15.650 1.689 2 VAL A HA +ATOM 20 H HB . VAL B 1 2 ? 16.859 13.653 2.526 2 VAL A HB +ATOM 21 H HG11 . VAL B 1 2 ? 15.925 11.512 1.791 2 VAL A HG11 +ATOM 22 H HG12 . VAL B 1 2 ? 14.743 12.431 2.754 2 VAL A HG12 +ATOM 23 H HG13 . VAL B 1 2 ? 14.586 12.361 0.982 2 VAL A HG13 +ATOM 24 H HG21 . VAL B 1 2 ? 17.872 14.353 0.565 2 VAL A HG21 +ATOM 25 H HG22 . VAL B 1 2 ? 17.645 12.588 0.536 2 VAL A HG22 +ATOM 26 H HG23 . VAL B 1 2 ? 16.583 13.637 -0.431 2 VAL A HG23 diff --git a/modules/io/tests/testfiles/mmcif/model_multi_atom_site_inverted.mmcif b/modules/io/tests/testfiles/mmcif/model_multi_atom_site_inverted.mmcif new file mode 100644 index 0000000000000000000000000000000000000000..58d22a61f34a1fe561bd2881d7db5211e7a148f3 --- /dev/null +++ b/modules/io/tests/testfiles/mmcif/model_multi_atom_site_inverted.mmcif @@ -0,0 +1,124 @@ +data_1MBA +# derived from 2JSP + +loop_ +_atom_site.group_PDB +_atom_site.id +_atom_site.type_symbol +_atom_site.label_atom_id +_atom_site.label_alt_id +_atom_site.label_comp_id +_atom_site.label_asym_id +_atom_site.label_entity_id +_atom_site.label_seq_id +_atom_site.pdbx_PDB_ins_code +_atom_site.Cartn_x +_atom_site.Cartn_y +_atom_site.Cartn_z +_atom_site.auth_seq_id +_atom_site.auth_comp_id +_atom_site.auth_asym_id +_atom_site.auth_atom_id +ATOM 1 N N . ALA A 1 1 ? 13.847 16.632 5.806 1 ALA A N +ATOM 2 C CA . ALA A 1 1 ? 14.050 15.239 5.351 1 ALA A CA +ATOM 3 C C . ALA A 1 1 ? 15.057 15.051 4.185 1 ALA A C +ATOM 4 O O . ALA A 1 1 ? 16.242 14.860 4.448 1 ALA A O +ATOM 5 C CB . ALA A 1 1 ? 12.682 14.599 5.070 1 ALA A CB +ATOM 6 H H1 . ALA A 1 1 ? 14.344 17.346 5.293 1 ALA A H1 +ATOM 7 H HA . ALA A 1 1 ? 14.425 14.660 6.196 1 ALA A HA +ATOM 8 H HB1 . ALA A 1 1 ? 12.168 15.166 4.295 1 ALA A HB1 +ATOM 9 H HB2 . ALA A 1 1 ? 12.824 13.571 4.734 1 ALA A HB2 +ATOM 10 H HB3 . ALA A 1 1 ? 12.085 14.603 5.981 1 ALA A HB3 +ATOM 11 N N . VAL B 1 2 ? 14.602 15.209 2.935 2 VAL A N +ATOM 12 C CA . VAL B 1 2 ? 15.402 15.012 1.699 2 VAL A CA +ATOM 13 C C . VAL B 1 2 ? 14.579 15.343 0.431 2 VAL A C +ATOM 14 O O . VAL B 1 2 ? 14.518 16.503 0.039 2 VAL A O +ATOM 15 C CB . VAL B 1 2 ? 16.165 13.656 1.685 2 VAL A CB +ATOM 16 C CG1 . VAL B 1 2 ? 15.292 12.399 1.812 2 VAL A CG1 +ATOM 17 C CG2 . VAL B 1 2 ? 17.136 13.551 0.504 2 VAL A CG2 +ATOM 18 H H . VAL B 1 2 ? 13.617 15.489 2.821 2 VAL A H +ATOM 19 H HA . VAL B 1 2 ? 16.285 15.650 1.689 2 VAL A HA +ATOM 20 H HB . VAL B 1 2 ? 16.859 13.653 2.526 2 VAL A HB +ATOM 21 H HG11 . VAL B 1 2 ? 15.925 11.512 1.791 2 VAL A HG11 +ATOM 22 H HG12 . VAL B 1 2 ? 14.743 12.431 2.754 2 VAL A HG12 +ATOM 23 H HG13 . VAL B 1 2 ? 14.586 12.361 0.982 2 VAL A HG13 +ATOM 24 H HG21 . VAL B 1 2 ? 17.872 14.353 0.565 2 VAL A HG21 +ATOM 25 H HG22 . VAL B 1 2 ? 17.645 12.588 0.536 2 VAL A HG22 +ATOM 26 H HG23 . VAL B 1 2 ? 16.583 13.637 -0.431 2 VAL A HG23 + +# additional atom_site block + +loop_ +_atom_site.group_PDB +_atom_site.id +_atom_site.type_symbol +_atom_site.label_atom_id +_atom_site.label_alt_id +_atom_site.label_comp_id +_atom_site.label_asym_id +_atom_site.label_entity_id +_atom_site.label_seq_id +_atom_site.pdbx_PDB_ins_code +_atom_site.Cartn_x +_atom_site.Cartn_y +_atom_site.Cartn_z +_atom_site.auth_seq_id +_atom_site.auth_comp_id +_atom_site.auth_asym_id +_atom_site.auth_atom_id +_atom_site.pdbx_PDB_model_num +ATOM 1 N N . ALA A 1 1 ? 13.847 16.632 5.806 1 ALA A N 1 +ATOM 2 C CA . ALA A 1 1 ? 14.050 15.239 5.351 1 ALA A CA 1 +ATOM 3 C C . ALA A 1 1 ? 15.057 15.051 4.185 1 ALA A C 1 +ATOM 4 O O . ALA A 1 1 ? 16.242 14.860 4.448 1 ALA A O 1 +ATOM 5 C CB . ALA A 1 1 ? 12.682 14.599 5.070 1 ALA A CB 1 +ATOM 6 H H1 . ALA A 1 1 ? 14.344 17.346 5.293 1 ALA A H1 1 +ATOM 7 H HA . ALA A 1 1 ? 14.425 14.660 6.196 1 ALA A HA 1 +ATOM 8 H HB1 . ALA A 1 1 ? 12.168 15.166 4.295 1 ALA A HB1 1 +ATOM 9 H HB2 . ALA A 1 1 ? 12.824 13.571 4.734 1 ALA A HB2 1 +ATOM 10 H HB3 . ALA A 1 1 ? 12.085 14.603 5.981 1 ALA A HB3 1 +ATOM 11 N N . VAL B 1 2 ? 14.602 15.209 2.935 2 VAL A N 1 +ATOM 12 C CA . VAL B 1 2 ? 15.402 15.012 1.699 2 VAL A CA 1 +ATOM 13 C C . VAL B 1 2 ? 14.579 15.343 0.431 2 VAL A C 1 +ATOM 14 O O . VAL B 1 2 ? 14.518 16.503 0.039 2 VAL A O 1 +ATOM 15 C CB . VAL B 1 2 ? 16.165 13.656 1.685 2 VAL A CB 1 +ATOM 16 C CG1 . VAL B 1 2 ? 15.292 12.399 1.812 2 VAL A CG1 1 +ATOM 17 C CG2 . VAL B 1 2 ? 17.136 13.551 0.504 2 VAL A CG2 1 +ATOM 18 H H . VAL B 1 2 ? 13.617 15.489 2.821 2 VAL A H 1 +ATOM 19 H HA . VAL B 1 2 ? 16.285 15.650 1.689 2 VAL A HA 1 +ATOM 20 H HB . VAL B 1 2 ? 16.859 13.653 2.526 2 VAL A HB 1 +ATOM 21 H HG11 . VAL B 1 2 ? 15.925 11.512 1.791 2 VAL A HG11 1 +ATOM 22 H HG12 . VAL B 1 2 ? 14.743 12.431 2.754 2 VAL A HG12 1 +ATOM 23 H HG13 . VAL B 1 2 ? 14.586 12.361 0.982 2 VAL A HG13 1 +ATOM 24 H HG21 . VAL B 1 2 ? 17.872 14.353 0.565 2 VAL A HG21 1 +ATOM 25 H HG22 . VAL B 1 2 ? 17.645 12.588 0.536 2 VAL A HG22 1 +ATOM 26 H HG23 . VAL B 1 2 ? 16.583 13.637 -0.431 2 VAL A HG23 1 +# +ATOM 1 N N . ALA A 1 1 ? 13.847 16.632 5.806 1 ALA A N 2 +ATOM 2 C CA . ALA A 1 1 ? 14.050 15.239 5.351 1 ALA A CA 2 +ATOM 3 C C . ALA A 1 1 ? 15.057 15.051 4.185 1 ALA A C 2 +ATOM 4 O O . ALA A 1 1 ? 16.242 14.860 4.448 1 ALA A O 2 +ATOM 5 C CB . ALA A 1 1 ? 12.682 14.599 5.070 1 ALA A CB 2 +ATOM 6 H H1 . ALA A 1 1 ? 14.344 17.346 5.293 1 ALA A H1 2 +ATOM 7 H HA . ALA A 1 1 ? 14.425 14.660 6.196 1 ALA A HA 2 +ATOM 8 H HB1 . ALA A 1 1 ? 12.168 15.166 4.295 1 ALA A HB1 2 +ATOM 9 H HB2 . ALA A 1 1 ? 12.824 13.571 4.734 1 ALA A HB2 2 +ATOM 10 H HB3 . ALA A 1 1 ? 12.085 14.603 5.981 1 ALA A HB3 2 +ATOM 11 N N . VAL B 1 2 ? 14.602 15.209 2.935 2 VAL A N 2 +ATOM 12 C CA . VAL B 1 2 ? 15.402 15.012 1.699 2 VAL A CA 2 +ATOM 13 C C . VAL B 1 2 ? 14.579 15.343 0.431 2 VAL A C 2 +ATOM 14 O O . VAL B 1 2 ? 14.518 16.503 0.039 2 VAL A O 2 +ATOM 15 C CB . VAL B 1 2 ? 16.165 13.656 1.685 2 VAL A CB 2 +ATOM 16 C CG1 . VAL B 1 2 ? 15.292 12.399 1.812 2 VAL A CG1 2 +ATOM 17 C CG2 . VAL B 1 2 ? 17.136 13.551 0.504 2 VAL A CG2 2 +ATOM 18 H H . VAL B 1 2 ? 13.617 15.489 2.821 2 VAL A H 2 +ATOM 19 H HA . VAL B 1 2 ? 16.285 15.650 1.689 2 VAL A HA 2 +ATOM 20 H HB . VAL B 1 2 ? 16.859 13.653 2.526 2 VAL A HB 2 +ATOM 21 H HG11 . VAL B 1 2 ? 15.925 11.512 1.791 2 VAL A HG11 2 +ATOM 22 H HG12 . VAL B 1 2 ? 14.743 12.431 2.754 2 VAL A HG12 2 +ATOM 23 H HG13 . VAL B 1 2 ? 14.586 12.361 0.982 2 VAL A HG13 2 +ATOM 24 H HG21 . VAL B 1 2 ? 17.872 14.353 0.565 2 VAL A HG21 2 +ATOM 25 H HG22 . VAL B 1 2 ? 17.645 12.588 0.536 2 VAL A HG22 2 +ATOM 26 H HG23 . VAL B 1 2 ? 16.583 13.637 -0.431 2 VAL A HG23 2 + + diff --git a/modules/io/tests/testfiles/mmcif/model_truepos.mmcif b/modules/io/tests/testfiles/mmcif/model_truepos.mmcif new file mode 100644 index 0000000000000000000000000000000000000000..9f1e39f16319bb4e9290c31d9896f209ecb15796 --- /dev/null +++ b/modules/io/tests/testfiles/mmcif/model_truepos.mmcif @@ -0,0 +1,78 @@ +data_1TPM +# derived from 2JSP + +# this file is also used in the mmcif_mmcif_chaintype_setting test for a true +# negative test, hence no entity category may be added + +loop_ +_atom_site.group_PDB +_atom_site.id +_atom_site.type_symbol +_atom_site.label_atom_id +_atom_site.label_alt_id +_atom_site.label_comp_id +_atom_site.label_asym_id +_atom_site.label_entity_id +_atom_site.label_seq_id +_atom_site.pdbx_PDB_ins_code +_atom_site.Cartn_x +_atom_site.Cartn_y +_atom_site.Cartn_z +_atom_site.auth_seq_id +_atom_site.auth_comp_id +_atom_site.auth_asym_id +_atom_site.auth_atom_id +_atom_site.pdbx_PDB_model_num +ATOM 1 N N . ALA A 1 1 ? 13.847 16.632 5.806 1 ALA A N 1 +ATOM 2 C CA . ALA A 1 1 ? 14.050 15.239 5.351 1 ALA A CA 1 +ATOM 3 C C . ALA A 1 1 ? 15.057 15.051 4.185 1 ALA A C 1 +ATOM 4 O O . ALA A 1 1 ? 16.242 14.860 4.448 1 ALA A O 1 +ATOM 5 C CB . ALA A 1 1 ? 12.682 14.599 5.070 1 ALA A CB 1 +ATOM 6 H H1 . ALA A 1 1 ? 14.344 17.346 5.293 1 ALA A H1 1 +ATOM 7 H HA . ALA A 1 1 ? 14.425 14.660 6.196 1 ALA A HA 1 +ATOM 8 H HB1 . ALA A 1 1 ? 12.168 15.166 4.295 1 ALA A HB1 1 +ATOM 9 H HB2 . ALA A 1 1 ? 12.824 13.571 4.734 1 ALA A HB2 1 +ATOM 10 H HB3 . ALA A 1 1 ? 12.085 14.603 5.981 1 ALA A HB3 1 +ATOM 11 N N . VAL B 1 2 ? 14.602 15.209 2.935 2 VAL A N 1 +ATOM 12 C CA . VAL B 1 2 ? 15.402 15.012 1.699 2 VAL A CA 1 +ATOM 13 C C . VAL B 1 2 ? 14.579 15.343 0.431 2 VAL A C 1 +ATOM 14 O O . VAL B 1 2 ? 14.518 16.503 0.039 2 VAL A O 1 +ATOM 15 C CB . VAL B 1 2 ? 16.165 13.656 1.685 2 VAL A CB 1 +ATOM 16 C CG1 . VAL B 1 2 ? 15.292 12.399 1.812 2 VAL A CG1 1 +ATOM 17 C CG2 . VAL B 1 2 ? 17.136 13.551 0.504 2 VAL A CG2 1 +ATOM 18 H H . VAL B 1 2 ? 13.617 15.489 2.821 2 VAL A H 1 +ATOM 19 H HA . VAL B 1 2 ? 16.285 15.650 1.689 2 VAL A HA 1 +ATOM 20 H HB . VAL B 1 2 ? 16.859 13.653 2.526 2 VAL A HB 1 +ATOM 21 H HG11 . VAL B 1 2 ? 15.925 11.512 1.791 2 VAL A HG11 1 +ATOM 22 H HG12 . VAL B 1 2 ? 14.743 12.431 2.754 2 VAL A HG12 1 +ATOM 23 H HG13 . VAL B 1 2 ? 14.586 12.361 0.982 2 VAL A HG13 1 +ATOM 24 H HG21 . VAL B 1 2 ? 17.872 14.353 0.565 2 VAL A HG21 1 +ATOM 25 H HG22 . VAL B 1 2 ? 17.645 12.588 0.536 2 VAL A HG22 1 +ATOM 26 H HG23 . VAL B 1 2 ? 16.583 13.637 -0.431 2 VAL A HG23 1 +# +ATOM 1 N N . ALA A 1 1 ? 13.847 16.632 5.806 1 ALA A N 2 +ATOM 2 C CA . ALA A 1 1 ? 14.050 15.239 5.351 1 ALA A CA 2 +ATOM 3 C C . ALA A 1 1 ? 15.057 15.051 4.185 1 ALA A C 2 +ATOM 4 O O . ALA A 1 1 ? 16.242 14.860 4.448 1 ALA A O 2 +ATOM 5 C CB . ALA A 1 1 ? 12.682 14.599 5.070 1 ALA A CB 2 +ATOM 6 H H1 . ALA A 1 1 ? 14.344 17.346 5.293 1 ALA A H1 2 +ATOM 7 H HA . ALA A 1 1 ? 14.425 14.660 6.196 1 ALA A HA 2 +ATOM 8 H HB1 . ALA A 1 1 ? 12.168 15.166 4.295 1 ALA A HB1 2 +ATOM 9 H HB2 . ALA A 1 1 ? 12.824 13.571 4.734 1 ALA A HB2 2 +ATOM 10 H HB3 . ALA A 1 1 ? 12.085 14.603 5.981 1 ALA A HB3 2 +ATOM 11 N N . VAL B 1 2 ? 14.602 15.209 2.935 2 VAL A N 2 +ATOM 12 C CA . VAL B 1 2 ? 15.402 15.012 1.699 2 VAL A CA 2 +ATOM 13 C C . VAL B 1 2 ? 14.579 15.343 0.431 2 VAL A C 2 +ATOM 14 O O . VAL B 1 2 ? 14.518 16.503 0.039 2 VAL A O 2 +ATOM 15 C CB . VAL B 1 2 ? 16.165 13.656 1.685 2 VAL A CB 2 +ATOM 16 C CG1 . VAL B 1 2 ? 15.292 12.399 1.812 2 VAL A CG1 2 +ATOM 17 C CG2 . VAL B 1 2 ? 17.136 13.551 0.504 2 VAL A CG2 2 +ATOM 18 H H . VAL B 1 2 ? 13.617 15.489 2.821 2 VAL A H 2 +ATOM 19 H HA . VAL B 1 2 ? 16.285 15.650 1.689 2 VAL A HA 2 +ATOM 20 H HB . VAL B 1 2 ? 16.859 13.653 2.526 2 VAL A HB 2 +ATOM 21 H HG11 . VAL B 1 2 ? 15.925 11.512 1.791 2 VAL A HG11 2 +ATOM 22 H HG12 . VAL B 1 2 ? 14.743 12.431 2.754 2 VAL A HG12 2 +ATOM 23 H HG13 . VAL B 1 2 ? 14.586 12.361 0.982 2 VAL A HG13 2 +ATOM 24 H HG21 . VAL B 1 2 ? 17.872 14.353 0.565 2 VAL A HG21 2 +ATOM 25 H HG22 . VAL B 1 2 ? 17.645 12.588 0.536 2 VAL A HG22 2 +ATOM 26 H HG23 . VAL B 1 2 ? 16.583 13.637 -0.431 2 VAL A HG23 2 diff --git a/modules/io/tests/testfiles/mmcif/struct_ref.cif b/modules/io/tests/testfiles/mmcif/struct_ref.cif new file mode 100644 index 0000000000000000000000000000000000000000..1d87ec60bb9b4cbca7c25ce02255be58a3f31896 --- /dev/null +++ b/modules/io/tests/testfiles/mmcif/struct_ref.cif @@ -0,0 +1,47 @@ +data_2bfl +# taken from 2bfl.cif +_struct_ref.id 1 +_struct_ref.db_name UNP +_struct_ref.db_code BLA2_BACCE +_struct_ref.entity_id 1 +_struct_ref.pdbx_seq_one_letter_code ? +_struct_ref.pdbx_align_begin ? +_struct_ref.biol_id . +_struct_ref.pdbx_db_accession P04190 +# +loop_ +_struct_ref_seq.align_id +_struct_ref_seq.ref_id +_struct_ref_seq.pdbx_PDB_id_code +_struct_ref_seq.pdbx_strand_id +_struct_ref_seq.seq_align_beg +_struct_ref_seq.pdbx_seq_align_beg_ins_code +_struct_ref_seq.seq_align_end +_struct_ref_seq.pdbx_seq_align_end_ins_code +_struct_ref_seq.pdbx_db_accession +_struct_ref_seq.db_align_beg +_struct_ref_seq.pdbx_db_align_beg_ins_code +_struct_ref_seq.db_align_end +_struct_ref_seq.pdbx_db_align_end_ins_code +_struct_ref_seq.pdbx_auth_seq_align_beg +_struct_ref_seq.pdbx_auth_seq_align_end +1 1 2BFL A 1 ? 19 ? P04190 31 ? 49 ? 27 45 +13 1 2BFL B 1 ? 19 ? P04190 31 ? 49 ? 27 45 +# +loop_ +_struct_ref_seq_dif.align_id +_struct_ref_seq_dif.pdbx_pdb_id_code +_struct_ref_seq_dif.mon_id +_struct_ref_seq_dif.pdbx_pdb_strand_id +_struct_ref_seq_dif.seq_num +_struct_ref_seq_dif.pdbx_pdb_ins_code +_struct_ref_seq_dif.pdbx_seq_db_name +_struct_ref_seq_dif.pdbx_seq_db_accession_code +_struct_ref_seq_dif.db_mon_id +_struct_ref_seq_dif.pdbx_seq_db_seq_num +_struct_ref_seq_dif.details +_struct_ref_seq_dif.pdbx_auth_seq_num +_struct_ref_seq_dif.pdbx_ordinal +1 2BFL CYS A 91 ? UNP P04190 ARG 121 'ENGINEERED MUTATION' 121 1 +13 2BFL CYS B 91 ? UNP P04190 ARG 121 'ENGINEERED MUTATION' 121 2 + diff --git a/modules/io/tests/testfiles/pdb/1oax.pdb b/modules/io/tests/testfiles/pdb/1oax.pdb new file mode 100644 index 0000000000000000000000000000000000000000..8a61950e8a0970d2b719b35c65465907ff0b6f3d --- /dev/null +++ b/modules/io/tests/testfiles/pdb/1oax.pdb @@ -0,0 +1,24 @@ + +COMPND MOL_ID: 1; +COMPND 2 MOLECULE: IMMUNOGLOBULIN E; +COMPND 3 CHAIN: H, I, J, K; +COMPND 4 FRAGMENT: FV REGION, RESIDUES 1-122; +COMPND 5 ENGINEERED: YES; +COMPND 6 MOL_ID: 2; +COMPND 7 MOLECULE: IMMUNOGLOBULIN E; +COMPND 8 CHAIN: L, M, N, O; +COMPND 9 FRAGMENT: FV REGION, RESIDUES 1-110; +COMPND 10 ENGINEERED: YES + +ATOM 961 CB ALA H 122 24.405 78.113 110.762 1.00 46.85 C +TER 962 ALA H 122 +ATOM 1923 CB ALA J 122 -18.810 34.607 14.909 1.00 46.23 C +TER 1924 ALA J 122 +ATOM 2722 CD2 LEU L 109 61.832 51.079 106.030 1.00 43.23 C +TER 2723 LEU L 109 +ATOM 3521 CD2 LEU M 109 2.184 -0.589 68.108 1.00 43.23 C +TER 3522 LEU M 109 +ATOM 4320 CD2 LEU N 109 7.889 -2.865 19.656 1.00 43.22 C +TER 4321 LEU N 109 +ATOM 5113 CD2 LEU O 109 59.692 56.678 57.399 1.00 43.23 C +TER 5114 LEU O 109 diff --git a/modules/io/tests/testfiles/pdb/2p6a.pdb b/modules/io/tests/testfiles/pdb/2p6a.pdb new file mode 100644 index 0000000000000000000000000000000000000000..19935ba86c1e7b632bd02a2c50ac89a726f0e9cb --- /dev/null +++ b/modules/io/tests/testfiles/pdb/2p6a.pdb @@ -0,0 +1,25 @@ +COMPND MOL_ID: 1; +COMPND 2 MOLECULE: INHIBIN BETA A CHAIN; +COMPND 3 CHAIN: A, B; +COMPND 4 SYNONYM: ACTIVIN BETA-A CHAIN, ERYTHROID DIFFERENTIATION +COMPND 5 PROTEIN, EDF; +COMPND 6 ENGINEERED: YES; +COMPND 7 MOL_ID: 2; +COMPND 8 MOLECULE: FOLLISTATIN; +COMPND 9 CHAIN: D, C; +COMPND 10 SYNONYM: FS, ACTIVIN-BINDING PROTEIN; +COMPND 11 ENGINEERED: YES; +COMPND 12 MOL_ID: 3; +COMPND 13 MOLECULE:; +COMPND 14 CHAIN: E; +COMPND 15 ENGINEERED: YES +ATOM 882 OXT SER A 116 15.399 37.353 44.611 1.00 73.37 O +TER 883 SER A 116 +ATOM 3870 OXT SER B 116 13.780 40.357 30.274 1.00 27.95 O +TER 3871 SER B 116 +ATOM 2987 OE2 GLU D 299 33.348 36.499 4.332 1.00 81.88 O +TER 2988 GLU D 299 +ATOM 5905 CB ILE C 290 46.026 -9.354 55.435 1.00233.79 C +TER 5906 ILE C 290 +ATOM 5956 CB ALA E 10 30.651 13.129 53.296 1.00191.07 C +TER 5957 ALA E 10 diff --git a/modules/io/tests/testfiles/pdb/bzdng-318.pdb b/modules/io/tests/testfiles/pdb/bzdng-318.pdb new file mode 100644 index 0000000000000000000000000000000000000000..8008e84b1abbeeeed341e7e91745c5327923b633 --- /dev/null +++ b/modules/io/tests/testfiles/pdb/bzdng-318.pdb @@ -0,0 +1,4 @@ +ATOM 1 CA ALYS A 9 31.209 -9.896 12.154 0.62 22.96 C +ATOM 1 CA BLYS A 9 31.213 -9.902 12.145 0.38 24.64 C +TER 2 LYS A 9 +END \ No newline at end of file diff --git a/modules/io/tests/testfiles/pdb/simple.pqr b/modules/io/tests/testfiles/pdb/simple.pqr new file mode 100644 index 0000000000000000000000000000000000000000..57b48919b6f94b1ace9a91597b0c301b0b6adf23 --- /dev/null +++ b/modules/io/tests/testfiles/pdb/simple.pqr @@ -0,0 +1,100 @@ +REMARK 1 PQR file generated by PDB2PQR (Version 1.4.0) +REMARK 1 +REMARK 1 Forcefield Used: parse +REMARK 1 +REMARK 5 Gap in backbone detected between LEU A 3 and MET A 255! +REMARK 5 Gap in backbone detected between MET B 1 and SER B 256! +REMARK 5 +REMARK 6 Total charge on this protein: 1.0000 e +REMARK 6 +ATOM 1 N MET 1 21.600 35.300 56.700 -0.3755 2.0005 +ATOM 2 CA MET 1 20.601 35.494 57.793 0.3300 2.0000 +ATOM 3 C MET 1 19.654 34.300 57.789 0.5500 1.7000 +ATOM 4 O MET 1 18.447 34.456 57.595 -0.5500 1.4000 +ATOM 5 CB MET 1 19.789 36.783 57.639 0.0000 2.0000 +ATOM 6 CG MET 1 20.629 38.055 57.606 0.2650 2.0000 +ATOM 7 SD MET 1 21.638 38.325 59.084 -0.5300 1.8500 +ATOM 8 CE MET 1 23.233 37.697 58.529 0.2650 2.0000 +ATOM 9 HE1 MET 1 23.125 37.266 57.634 0.0000 0.0000 +ATOM 10 HE2 MET 1 23.881 38.455 58.461 0.0000 0.0000 +ATOM 11 HE3 MET 1 23.571 37.025 59.187 0.0000 0.0000 +ATOM 12 H2 MET 1 22.177 34.580 56.869 0.3300 0.0000 +ATOM 13 H3 MET 1 21.135 35.294 55.831 0.3300 0.0000 +ATOM 14 HG2 MET 1 21.223 38.027 56.761 0.0000 0.0000 +ATOM 15 HG3 MET 1 19.996 38.856 57.448 0.0000 0.0000 +ATOM 16 H MET 1 22.175 36.206 56.703 0.3300 0.0000 +ATOM 17 HA MET 1 21.099 35.502 58.665 0.0000 0.0000 +ATOM 18 HB3 MET 1 19.138 36.853 58.408 0.0000 0.0000 +ATOM 19 HB2 MET 1 19.255 36.733 56.783 0.0000 0.0000 +ATOM 20 N ARG 2 20.202 33.112 58.011 -0.4000 1.5000 +ATOM 21 CA ARG 2 19.396 31.903 58.033 -0.0000 2.0000 +ATOM 22 C ARG 2 18.608 31.739 59.328 0.5500 1.7000 +ATOM 23 O ARG 2 17.651 30.965 59.381 -0.5500 1.4000 +ATOM 24 CB ARG 2 20.284 30.681 57.801 0.0000 2.0000 +ATOM 25 CG ARG 2 20.665 30.488 56.342 0.0000 2.0000 +ATOM 26 CD ARG 2 21.557 29.281 56.154 0.3500 2.0000 +ATOM 27 NE ARG 2 22.931 29.557 56.551 -0.3500 1.5000 +ATOM 28 CZ ARG 2 23.900 28.700 56.500 0.2507 1.7503 +ATOM 29 NH1 ARG 2 23.640 27.417 56.130 -0.7000 1.5000 +ATOM 30 NH2 ARG 2 25.132 28.980 56.893 -0.7000 1.5000 +ATOM 31 HG3 ARG 2 21.156 31.294 56.019 0.0000 0.0000 +ATOM 32 HA ARG 2 18.738 31.934 57.260 0.0000 0.0000 +ATOM 33 HE ARG 2 23.157 30.486 56.860 0.4500 1.0000 +ATOM 34 HG2 ARG 2 19.838 30.356 55.799 0.0000 0.0000 +ATOM 35 HH22 ARG 2 25.859 28.300 56.895 0.4000 1.0000 +ATOM 36 HH21 ARG 2 25.336 29.925 57.170 0.4000 1.0000 +ATOM 37 H ARG 2 21.227 33.124 58.163 0.4000 1.0000 +ATOM 38 HD3 ARG 2 21.537 29.027 55.190 0.0000 0.0000 +ATOM 39 HD2 ARG 2 21.197 28.537 56.711 0.0000 0.0000 +ATOM 40 HH12 ARG 2 24.383 26.727 56.133 0.4000 1.0000 +ATOM 41 HH11 ARG 2 22.728 27.161 55.829 0.4000 1.0000 +ATOM 42 HB3 ARG 2 19.790 29.875 58.100 0.0000 0.0000 +ATOM 43 HB2 ARG 2 21.118 30.797 58.325 0.0000 0.0000 +ATOM 44 N LEU 3 19.003 32.473 60.366 -0.4000 1.5000 +ATOM 45 CA LEU 3 18.330 32.402 61.664 -0.0000 2.0000 +ATOM 46 C LEU 3 17.884 33.787 62.117 0.5500 1.7000 +ATOM 47 O LEU 3 17.853 34.091 63.308 -0.5500 1.4000 +ATOM 48 CB LEU 3 19.269 31.793 62.710 0.0000 2.0000 +ATOM 49 CG LEU 3 19.695 30.340 62.501 0.0000 2.0000 +ATOM 50 CD1 LEU 3 20.585 29.897 63.648 0.0000 2.0000 +ATOM 51 CD2 LEU 3 18.461 29.459 62.420 0.0000 2.0000 +ATOM 52 HD22 LEU 3 17.888 29.751 61.653 0.0000 0.0000 +ATOM 53 HD23 LEU 3 18.736 28.507 62.283 0.0000 0.0000 +ATOM 54 HD21 LEU 3 17.938 29.533 63.270 0.0000 0.0000 +ATOM 55 H LEU 3 19.817 33.091 60.179 0.4000 1.0000 +ATOM 56 HD13 LEU 3 20.084 29.973 64.512 0.0000 0.0000 +ATOM 57 HD12 LEU 3 20.863 28.945 63.510 0.0000 0.0000 +ATOM 58 HD11 LEU 3 21.400 30.478 63.686 0.0000 0.0000 +ATOM 59 HA LEU 3 17.516 31.820 61.570 0.0000 0.0000 +ATOM 60 HG LEU 3 20.197 30.269 61.643 0.0000 0.0000 +ATOM 61 HB3 LEU 3 18.811 31.845 63.597 0.0000 0.0000 +ATOM 62 HB2 LEU 3 20.102 32.347 62.730 0.0000 0.0000 +ATOM 63 N MET 255 29.709 5.069 60.642 -0.4000 1.5000 +ATOM 64 CA MET 255 28.701 5.164 59.592 -0.0000 2.0000 +ATOM 65 C MET 255 27.302 4.748 60.005 0.5500 1.7000 +ATOM 66 O MET 255 27.057 3.586 60.326 -0.5500 1.4000 +ATOM 67 CB MET 255 29.146 4.331 58.399 0.0000 2.0000 +ATOM 68 CG MET 255 30.558 4.642 57.948 0.2650 2.0000 +ATOM 69 SD MET 255 31.116 3.394 56.790 -0.5300 1.8500 +ATOM 70 CE MET 255 31.526 2.062 57.912 0.2650 2.0000 +ATOM 71 HG2 MET 255 30.571 5.563 57.524 0.0000 0.0000 +ATOM 72 HE1 MET 255 32.437 1.708 57.695 0.0000 0.0000 +ATOM 73 HE2 MET 255 31.518 2.401 58.854 0.0000 0.0000 +ATOM 74 HE3 MET 255 30.854 1.325 57.820 0.0000 0.0000 +ATOM 75 HB2 MET 255 29.096 3.355 58.642 0.0000 0.0000 +ATOM 76 HG3 MET 255 31.163 4.679 58.762 0.0000 0.0000 +ATOM 77 H MET 255 26.414 14.773 61.903 0.4000 1.0000 +ATOM 78 HA MET 255 28.661 6.140 59.286 0.0000 0.0000 +ATOM 79 HB3 MET 255 28.520 4.500 57.628 0.0000 0.0000 +ATOM 80 N SER 256 26.376 5.699 59.965 -0.4000 1.5000 +ATOM 81 CA SER 256 24.998 5.430 60.347 -0.0000 2.0000 +ATOM 82 C SER 256 24.040 5.839 59.231 0.1000 1.7000 +ATOM 83 O SER 256 24.543 6.294 58.186 -0.5500 1.4000 +ATOM 84 CB SER 256 24.664 6.188 61.642 0.0000 2.0000 +ATOM 85 OG SER 256 25.569 5.836 62.681 -0.4900 1.4000 +ATOM 86 OXT SER 256 22.811 5.701 59.408 -0.5500 1.4000 +ATOM 87 H SER 256 26.714 6.626 59.646 0.4000 1.0000 +ATOM 88 HA SER 256 24.898 4.440 60.490 0.0000 0.0000 +ATOM 89 HB3 SER 256 23.741 5.949 61.922 0.0000 0.0000 +ATOM 90 HB2 SER 256 24.734 7.163 61.468 0.0000 0.0000 +ATOM 91 HG SER 256 26.464 6.235 62.490 0.4900 1.0000 diff --git a/modules/io/tests/testfiles/pdb/simple_defective.pdb b/modules/io/tests/testfiles/pdb/simple_defective.pdb new file mode 100644 index 0000000000000000000000000000000000000000..725b68dbad3e82a101122f3f301f8a254e9a4aab --- /dev/null +++ b/modules/io/tests/testfiles/pdb/simple_defective.pdb @@ -0,0 +1,67 @@ +HELIX 1 1 ARG A 15 GLU A 28 1 14 +HELIX 2 2 ASN A 38 GLY A 50 1 13 +SHEET 1 A 7 ALA A 53 ALA A 57 0 +SHEET 2 A 7 ALA A 30 ASP A 36 1 N ILE A 34 O CYS A 54 +CRYST1 67.465 67.465 191.044 90.00 90.00 120.00 P 31 2 1 12 +ATOM 1 N MET A 1 21.609 35.384 56.705 1.00 41.48 N +ATOM 2 CA MET A 1 20.601 35.494 57.793 1.00 41.58 C +ATOM 3 C MET A 1 19.654 34.300 57.789 1.00 39.51 C +ATOM 4 O MET A 1 18.447 34.456 57.595 1.00 38.98 O +ATOM 5 CB MET A 1 19.789 36.783 57.639 1.00 45.90 C +ATOM 6 CG MET A 1 20.629 38.055 57.606 1.00 51.18 C +ATOM 7 SD MET A 1 21.638 38.325 59.084 1.00 55.83 S +ATOM 8 CE MET A 1 23.233 37.697 58.529 1.00 54.59 C +ATOM 9 N ARG A 2 20.202 33.112 58.011 1.00 36.39 N +ATOM 10 CA ARG A 2 19.396 31.903 58.033 1.00 34.35 C +ATOM 11 C ARG A 2 18.608 31.739 59.328 1.00 34.20 C +ATOM 12 O ARG A 2 17.651 30.965 59.381 1.00 32.64 O +ATOM 13 CB ARG A 2 20.284 30.681 57.801 1.00 33.48 C +ATOM 14 CG ARG A 2 20.665 30.488 56.342 1.00 31.69 C +ATOM 15 CD ARG A 2 21.557 29.281 56.154 1.00 29.91 C +ATOM 16 NE ARG A 2 22.931 29.557 56.551 1.00 28.95 N +ATOM 17 CZ ARG A 2 23.901 28.653 56.528 1.00 30.21 C +ATOM 18 NH1 ARG A 2 23.640 27.417 56.130 1.00 32.54 N +ATOM 19 NH2 ARG A 2 25.132 28.980 56.893 1.00 29.14 N +ATOM 20 N LEU A 3 19.003 32.473 60.366 1.00 35.07 N +ATOM 21 CA LEU A 3 18.330 32.402 61.664 1.00 34.70 C +ATOM 22 C LEU A 3 17.884 33.787 62.117 1.00 35.41 C +ATOM 23 O LEU A 3 17.853 34.091 63.308 1.00 35.91 O +ATOM 24 CB LEU A 3 19.269 31.793 102.710 1.00 31.47 C +ATOM 25 CG LEU A 3 19.695 30.340 62.501 1.00 29.10 C +ATOM 26 CD1 LEU A 3 20.585 29.897 63.648 1.00 26.97 C +ATOM 27 CD2 LEU A 3 18.461 29.459 62.420 1.00 27.95 C +ATOM 1881 N MET A 255 29.709 5.069 60.642 1.00 26.34 N +ATOM 1882 CA MET A 255 28.701 5.164 59.592 1.00 27.93 C +ATOM 1883 C MET A 255 27.302 4.748 60.005 1.00 27.64 C +ATOM 1884 O MET A 255 27.057 3.586 60.326 1.00 29.54 O +ATOM 1885 CB MET A 255 29.146 4.331 58.399 1.00 28.54 C +ATOM 1886 CG MET A 255 30.558 4.642 57.948 1.00 30.99 C +ATOM 1887 SD MET A 255 31.116 3.394 56.790 1.00 34.74 S +ATOM 1888 CE MET A 255 31.526 2.062 57.912 1.00 35.45 C +ATOM 1889 N SER A 256 26.376 5.699 59.965 1.00 26.90 N +ATOM 1890 CA SER A 256 24.998 5.430 60.347 1.00 28.27 C +ATOM 1891 C SER A 256 24.040 5.839 59.231 1.00 28.44 C +ATOM 1892 O SER A 256 24.543 6.294 58.186 1.00 28.92 O +ATOM 1893 CB SER A 256 24.664 6.188 61.642 1.00 28.64 C +ATOM 1894 OG SER A 256 25.569 5.836 62.681 1.00 28.28 O +ATOM 1895 OXT SER A 256 22.811 5.701 59.408 1.00 27.92 O +TER 1896 SER A 256 +ATOM 1897 N MET B 1 22.333 -31.975 81.215 1.00 44.89 N +ATOM 1898 CA MET B 1 23.104 -30.998 82.028 1.00 43.40 C +ATOM 1899 C MET B 1 24.121 -30.191 81.211 1.00 40.48 C +ATOM 1900 O MET B 1 25.266 -30.614 81.040 1.00 38.97 O +ATOM 1901 CB MET B 1 23.828 -31.727 83.164 1.00 48.82 C +ATOM 1902 CG MET B 1 23.086 -31.723 84.500 1.00 55.57 C +ATOM 1903 SD MET B 1 21.607 -32.746 84.539 1.00 63.93 S +ATOM 1904 CE MET B 1 21.996 -33.836 85.950 1.00 64.69 C +ATOM 3785 N SER B 256 17.566 -6.734 64.432 1.00 23.90 N +ATOM 3786 CA SER B 256 18.942 -6.278 64.584 1.00 23.46 C +ATOM 3787 C SER B 256 19.884 -7.335 64.032 1.00 23.50 C +ATOM 3788 O SER B 256 19.390 -8.439 63.723 1.00 25.09 O +ATOM 3789 CB SER B 256 19.253 -6.025 66.064 1.00 22.10 C +ATOM 3790 OG SER B 256 18.279 -5.173 66.635 1.00 18.70 O +ATOM 3791 OXT SER B 256 21.095 -7.051 63.923 1.00 22.97 O +TER 3792 SER B 256 +HETATM 3793 O HOH 1 14.659 7.548 75.525 1.00 6.25 O +HETATM 3794 O HOH 2 29.166 1.788 77.529 1.00 15.43 O +END diff --git a/modules/mol/alg/pymod/CMakeLists.txt b/modules/mol/alg/pymod/CMakeLists.txt index 0ffb3f65183cb217c5fcfe6b1093a884ea42bca9..000e754817bce15b4e118a6ad65de253d9af8763 100644 --- a/modules/mol/alg/pymod/CMakeLists.txt +++ b/modules/mol/alg/pymod/CMakeLists.txt @@ -3,12 +3,16 @@ set(OST_MOL_ALG_PYMOD_SOURCES export_svd_superpose.cc export_clash.cc export_trajectory_analysis.cc + export_structure_analysis.cc ) set(OST_MOL_ALG_PYMOD_MODULES "__init__.py" views.py superpose.py + trajectory_analysis.py + structure_analysis.py + helix_kinks.py ) if (ENABLE_IMG) @@ -19,7 +23,7 @@ if (ENABLE_IMG) ) endif() - -pymod(NAME mol_alg OUTPUT_DIR ost/mol/alg CPP ${OST_MOL_ALG_PYMOD_SOURCES} - PY ${OST_MOL_ALG_PYMOD_MODULES}) - +if (NOT ENABLE_STATIC) + pymod(NAME mol_alg OUTPUT_DIR ost/mol/alg CPP ${OST_MOL_ALG_PYMOD_SOURCES} + PY ${OST_MOL_ALG_PYMOD_MODULES}) +endif() diff --git a/modules/mol/alg/pymod/__init__.py b/modules/mol/alg/pymod/__init__.py index 98fe346c5a07b1e28571832929b535ab0588adb3..3d7901d005e4328a1c730c1fd2e5a493360cce16 100644 --- a/modules/mol/alg/pymod/__init__.py +++ b/modules/mol/alg/pymod/__init__.py @@ -1,3 +1,5 @@ from _ost_mol_alg import * from ost.mol.alg.superpose import * - +import ost.mol.alg.trajectory_analysis +import ost.mol.alg.structure_analysis +import ost.mol.alg.helix_kinks diff --git a/modules/mol/alg/pymod/export_structure_analysis.cc b/modules/mol/alg/pymod/export_structure_analysis.cc new file mode 100644 index 0000000000000000000000000000000000000000..85fbc230d34a1a568b1565672278b61a85a1b5b6 --- /dev/null +++ b/modules/mol/alg/pymod/export_structure_analysis.cc @@ -0,0 +1,35 @@ +//------------------------------------------------------------------------------ +// This file is part of the OpenStructure project <www.openstructure.org> +// +// Copyright (C) 2008-2011 by the OpenStructure authors +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License as published by the Free +// Software Foundation; either version 3.0 of the License, or (at your option) +// any later version. +// This library is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this library; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +//------------------------------------------------------------------------------ +#include <boost/python.hpp> +using namespace boost::python; + +#include <ost/mol/alg/structure_analysis.hh> + +using namespace ost; +using namespace ost::mol::alg; + +void export_StructureAnalysis() +{ + def("GetPosListFromView",&GetPosListFromView, (arg("view"))); +#if OST_IMG_ENABLED + def("CalculateAverageAgreementWithDensityMap",&CalculateAverageAgreementWithDensityMap,(arg("pos_list"),arg("density_map"))); + def("CalculateAgreementWithDensityMap",&CalculateAgreementWithDensityMap,(arg("pos_list"),arg("density_map"))); +#endif + def("WrapEntityInPeriodicCell",&WrapEntityInPeriodicCell,(arg("Entity"),arg("cell_center"),arg("nasis_vec"))); +} diff --git a/modules/mol/alg/pymod/export_trajectory_analysis.cc b/modules/mol/alg/pymod/export_trajectory_analysis.cc index 31377016a874dc6dcc42cc702d11a3a4058f0934..4db2668e91832d72952b12b637ad7141a7117ff3 100644 --- a/modules/mol/alg/pymod/export_trajectory_analysis.cc +++ b/modules/mol/alg/pymod/export_trajectory_analysis.cc @@ -43,7 +43,13 @@ void export_TrajectoryAnalysis() def("AnalyzeDihedralAngle",&AnalyzeDihedralAngle, (arg("traj"), arg("atom"), arg("atom"), arg("atom"), arg("atom"), arg("stride")=1)); def("AnalyzeDistanceBetwCenterOfMass",&AnalyzeDistanceBetwCenterOfMass, (arg("traj"), arg("selection"), arg("selection"), arg("stride")=1)); def("AnalyzeRMSD",&AnalyzeRMSD, (arg("traj"), arg("reference_view"), arg("selection"), arg("stride")=1)); + def("AnalyzeRMSF",&AnalyzeRMSF, (arg("traj"), arg("selection"), arg("first")=0, arg("last")=-1, arg("stride")=1)); def("AnalyzeMinDistance", &AnalyzeMinDistance, (arg("traj"), arg("view1"), arg("view2"), arg("stride")=1)); def("AnalyzeMinDistanceBetwCenterOfMassAndView", &AnalyzeMinDistanceBetwCenterOfMassAndView, (arg("traj"), arg("view_cm"), arg("view_atoms"), arg("stride")=1)); def("AnalyzeAromaticRingInteraction", &AnalyzeAromaticRingInteraction, (arg("traj"), arg("view_ring1"), arg("view_ring2"), arg("stride")=1)); + def("AnalyzeAlphaHelixAxis", &AnalyzeAlphaHelixAxis, (arg("traj"), arg("protein_segment"), arg("directions"), arg("centers"), arg("stride")=1)); + def("AnalyzeBestFitLine", &AnalyzeBestFitLine, (arg("traj"), arg("protein_segment"), arg("directions"), arg("centers"), arg("stride")=1)); + def("AnalyzeBestFitPlane", &AnalyzeBestFitPlane, (arg("traj"), arg("protein_segment"), arg("normals"), arg("origins"), arg("stride")=1)); + def("AnalyzeHelicity", &AnalyzeHelicity, (arg("traj"), arg("protein_segment"), arg("stride")=1)); + def("CreateMeanStructure", &CreateMeanStructure, (arg("traj"), arg("selection"), arg("from")=0, arg("to")=-1, arg("stride")=1 )); } diff --git a/modules/mol/alg/pymod/helix_kinks.py b/modules/mol/alg/pymod/helix_kinks.py new file mode 100644 index 0000000000000000000000000000000000000000..d57196bc5dc92d55e7b6f1abe6a7479b333b4fd2 --- /dev/null +++ b/modules/mol/alg/pymod/helix_kinks.py @@ -0,0 +1,150 @@ +""" +Functions to calculate helix kinks: bend, face shift and wobbla angles + +Author: Niklaus Johner +""" + +import os +import ost + +def __FindProline(sele,proline): + if not sele.IsValid(): + print 'selection is not valid' + raise RuntimeError + if proline==False: + proline=sele.Select('rname=PRO') + if not proline.GetResidueCount()==1: + print proline.GetResidueCount(),'prolines in the selection. One proline is needed' + raise RuntimeError + proline=proline.residues[0] + proline_ca=proline.FindAtom('CA') + if not proline_ca.IsValid(): + print 'proline has no CA atom' + raise RuntimeError + return (proline,proline_ca) + proline.GetNumber().num + +def __SelectPreAndPostProline(sele,proline_num): + pre_proline=sele.Select('rnum<'+str(proline_num)) + post_proline=sele.Select('rnum>'+str(proline_num)) + print 'pre-proline residues' + for res in pre_proline.residues: + print res + print 'post-proline residues' + for res in post_proline.residues: + print res + if pre_proline.GetResidueCount()<4 or post_proline.GetResidueCount()<4: + print 'pre and post proline helices should be at least 4 residues long, 7 for better stability' + raise RuntimeError + return (pre_proline,post_proline) + +def __FindCa3AndCa4(sele,proline_ca,proline_num): + ca_3=sele.FindAtom(proline_ca.GetHandle().GetChain().GetName(),proline_num-3,'CA') + ca_4=sele.FindAtom(proline_ca.GetHandle().GetChain().GetName(),proline_num-4,'CA') + if not (ca_3.IsValid() and ca_4.IsValid()): + print 'CA not found in (i-4) or (i-3) residue' + raise RuntimeError + return (ca_3,ca_4) + + +def __CalculateBendAngle(pre_proline_axis,post_proline_axis): + return ost.geom.Angle(pre_proline_axis,post_proline_axis) + +def __CalculateWobbleAngle(pre_proline_axis,post_proline_axis,post_proline_centers,proline_pos): + p1=proline_pos-post_proline_centers + n1=p1-ost.geom.Dot(p1,post_proline_axis)*post_proline_axis + p2=-pre_proline_axis + n2=p2-ost.geom.Dot(p2,post_proline_axis)*post_proline_axis + sign=ost.geom.Dot(ost.geom.Cross(pre_proline_axis,n2),n2-n1) + sign=sign/abs(sign) + return sign*ost.geom.Angle(n1,n2) + +def __CalculateFaceShift(pre_proline_axis,post_proline_axis,pre_proline_centers,post_proline_centers,proline_pos,ca3_pos,ca4_pos,bend_angle): + p1=proline_pos-post_proline_centers + n1=p1-ost.geom.Dot(p1,post_proline_axis)*post_proline_axis + p2=(ca3_pos+ca4_pos)/2.0-pre_proline_centers + n2=p2-ost.geom.Dot(p2,pre_proline_axis)*pre_proline_axis + #Here we want to apply a rotation to n1, to align the post-proline axis on the pre-proline axis + R=ost.geom.AxisRotation(ost.geom.Cross(post_proline_axis,pre_proline_axis),bend_angle) + n1=R*n1 + #We also need to determine the sign of the angle + sign=ost.geom.Dot(ost.geom.Cross(pre_proline_axis,n2),n2-n1) + sign=sign/abs(sign) + return sign*ost.geom.Angle(n1,n2) + + +def AnalyzeHelixKink(t,sele,proline=False): + """ + This function calculates the bend,wobble and face-shift angles + in an alpha-helix over a trajectory. The determination is more stable if + there are at least 4 residues on each side (8 is even better) of the prolin around which + the helix is kinked. The selection should contain all residues in the correct + order and with no gaps and no missing C-alphas. + Input: + t : The trajectory to be analyzed (CoordGroup) + sele : A selection containing the alpha helix to be analyzed (EntityView) + proline=False : An EntityView containing only the proline (or another residue) around which the + helix is kinked. If False, the proline will be serached for automatically + Output: + (bend_angle,face_shift,wobble_angle) : a tuple of FloatLists + """ + n_frames=t.GetFrameCount() + (proline,proline_ca)=__FindProline(sele,proline) + proline_num=proline.GetNumber().num + (pre_proline,post_proline)=__SelectPreAndPostProline(sele,proline_num) + (ca_3,ca_4)=__FindCa3AndCa4(sele,proline_ca,proline_num) + #Here we extract the necessary information from the trajectory + pre_proline_axis=ost.geom.Vec3List() + post_proline_axis=ost.geom.Vec3List() + pre_proline_centers=ost.geom.Vec3List() + post_proline_centers=ost.geom.Vec3List() + ost.mol.alg.AnalyzeAlphaHelixAxis(t,pre_proline,pre_proline_axis,pre_proline_centers) + ost.mol.alg.AnalyzeAlphaHelixAxis(t,post_proline,post_proline_axis,post_proline_centers) + proline_pos=ost.mol.alg.AnalyzeAtomPos(t,proline_ca.GetHandle()) + ca3_pos=ost.mol.alg.AnalyzeAtomPos(t,ca_3.GetHandle()) + ca4_pos=ost.mol.alg.AnalyzeAtomPos(t,ca_4.GetHandle()) + #Now we calculate the bend angle + bend_angle=[] + face_shift=[] + wobble_angle=[] + for i in range(n_frames): + bend_angle.append(__CalculateBendAngle(pre_proline_axis[i],post_proline_axis[i])) + face_shift.append(__CalculateFaceShift(pre_proline_axis[i],post_proline_axis[i],pre_proline_centers[i],post_proline_centers[i],proline_pos[i],ca3_pos[i],ca4_pos[i],bend_angle[i])) + wobble_angle.append(__CalculateWobbleAngle(pre_proline_axis[i],post_proline_axis[i],post_proline_centers[i],proline_pos[i])) + return (bend_angle,face_shift,wobble_angle) + + +def CalculateHelixKink(sele,proline=False): + """ + This function calculates the bend,wobble and face-shift angles + in an alpha-helix of an EntityView. The determination is more stable if + there are at least 4 residues on each side (8 is even better) of the prolin around which + the helix is kinked. The selection should contain all residues in the correct + order and with no gaps and no missing C-alphas. + Input: + sele : A selection containing the alpha helix to be analyzed (EntityView) + proline=False : An EntityView containing only the proline (or another residue) around which the + helix is kinked. If False, the proline will be serached for automatically + Output: + (bend_angle,face_shift,wobble_angle) : a tuple of Floats + """ + (proline,proline_ca)=__FindProline(sele,proline) + proline_num=proline.GetNumber().num + (pre_proline,post_proline)=__SelectPreAndPostProline(sele,proline_num) + (ca_3,ca_4)=__FindCa3AndCa4(sele,proline_ca,proline_num) + #Here we extract the necessary information from the structure + pre_proline_axis=ost.mol.alg.structure_analysis.CalculateHelixAxis(pre_proline) + post_proline_axis=ost.mol.alg.structure_analysis.CalculateHelixAxis(post_proline) + prepa=pre_proline_axis.GetDirection() + prepc=pre_proline_axis.GetOrigin() + postpa=post_proline_axis.GetDirection() + postpc=post_proline_axis.GetOrigin() + #calculate the angles + bend=__CalculateBendAngle(prepa,postpa) + wobble=__CalculateWobbleAngle(prepa,postpa,postpc,proline_ca.pos) + shift=__CalculateFaceShift(prepa,postpa,prepc,postpc,proline_ca.pos,ca_3.pos,ca_4.pos,bend) + return (bend,shift,wobble) + + + + \ No newline at end of file diff --git a/modules/mol/alg/pymod/structure_analysis.py b/modules/mol/alg/pymod/structure_analysis.py new file mode 100644 index 0000000000000000000000000000000000000000..7cbd0dd4b32bb7e6f4093ed23bbbb52a700fc320 --- /dev/null +++ b/modules/mol/alg/pymod/structure_analysis.py @@ -0,0 +1,131 @@ +""" +Some functions for analyzing trajectories + +Author: Niklaus Johner +""" + +import os +import ost + +def GetFrameFromEntity(eh): + """ + This function returns a CoordFrame from an EntityHandle + Input: + eh : EntityHandle + """ + return ost.mol.CreateCoordFrame(eh.GetAtomPosList()) + +def GetDistanceBetwCenterOfMass(sele1,sele2): + """ + This function calculates the distance between the centers of mass + of sele1 and sele2, two selections from the same Entity. + Input: + sele1 : EntityView + sele2 : EntityView + """ + if not sele1.IsValid() and sele2.IsValid(): + print 'invalid view' + return + eh=sele1.GetHandle() + if not eh==sele2.GetHandle(): + print 'The two views must be from the same entity' + return + f=GetFrameFromEntity(eh) + return f.GetDistanceBetwCenterOfMass(sele1,sele2) + +def GetMinDistanceBetweenViews(sele1,sele2): + """ + This function calculates the minimal distance between + sele1 and sele2, two selections from the same Entity. + Input: + sele1 : EntityView + sele2 : EntityView + """ + if not sele1.IsValid() and sele2.IsValid(): + print 'invalid view' + return + eh=sele1.GetHandle() + if not eh==sele2.GetHandle(): + print 'The two views must be from the same entity' + return + f=GetFrameFromEntity(eh) + return f.GetMinDistance(sele1,sele2) + +def GetMinDistBetwCenterOfMassAndView(sele1,sele2): + """ + This function calculates the minimal distance between sele2 and + the center of mass of sele1, two selections from the same Entity. + Input: + sele1 : EntityView from which the center of mass is taken + sele2 : EntityView + """ + if not sele1.IsValid() and sele2.IsValid(): + print 'invalid view' + return + eh=sele1.GetHandle() + if not eh==sele2.GetHandle(): + print 'The two views must be from the same entity' + return + f=GetFrameFromEntity(eh) + return f.GetMinDistBetwCenterOfMassAndView(sele1,sele2) + + +def GetAlphaHelixContent(sele1): + """ + This function calculates the content of alpha helix in a view. + All residues in the view have to ordered and adjacent (no gaps allowed) + Input: + sele1 : EntityView + """ + if not sele1.IsValid(): + print 'invalid view' + return + eh=sele1.GetHandle() + f=GetFrameFromEntity(eh) + return f.GetAlphaHelixContent(sele1) + + +def CalculateBestFitLine(sele1): + """ + This function calculates the best fit line to the atoms in sele1. + Input: + sele1 : EntityView + It returns a geom::Line3 + """ + if not sele1.IsValid(): + print 'invalid view' + return + eh=sele1.GetHandle() + f=GetFrameFromEntity(eh) + return f.GetODRLine(sele1) + +def CalculateBestFitPlane(sele1): + """ + This function calculates the best fit plane to the atoms in sele1. + Input: + sele1 : EntityView + It returns a geom::Plane + """ + if not sele1.IsValid(): + print 'invalid view' + return + eh=sele1.GetHandle() + f=GetFrameFromEntity(eh) + return f.GetODRPlane(sele1) + +def CalculateHelixAxis(sele1): + """ + This function calculates the best fit cylinder to the CA atoms in sele1, + and returns its axis as a Line3. residues should be ordered correctly + in the EntityView. + Input: + sele1 : EntityView + It returns a geom::Line3 + """ + if not sele1.IsValid(): + print 'invalid view' + return + eh=sele1.GetHandle() + f=GetFrameFromEntity(eh) + return f.FitCylinder(sele1) + diff --git a/modules/mol/alg/pymod/superpose.py b/modules/mol/alg/pymod/superpose.py index 96ad881b0e045f8ded7af3ff745ef00a712a0ff4..76d4afe98d53178bba1cf357e2e4f827ccef7f01 100644 --- a/modules/mol/alg/pymod/superpose.py +++ b/modules/mol/alg/pymod/superpose.py @@ -112,10 +112,11 @@ def MatchResidueByNum(ent_a, ent_b, atoms='all'): while True: r_a=residues_a.next() r_b=residues_b.next() - while r_a.number<r_b.number: - r_a=residues_a.next() - while r_b.number<r_a.number: - r_b=residues_b.next() + while r_a.number!=r_b.number: + while r_a.number<r_b.number: + r_a=residues_a.next() + while r_b.number<r_a.number: + r_b=residues_b.next() assert r_a.number==r_b.number result_a,result_b=_fetch_atoms(r_a, r_b, result_a, result_b, atmset) except StopIteration: diff --git a/modules/mol/alg/pymod/trajectory_analysis.py b/modules/mol/alg/pymod/trajectory_analysis.py new file mode 100644 index 0000000000000000000000000000000000000000..b445b02351775b92ba66cf80655f63610999569f --- /dev/null +++ b/modules/mol/alg/pymod/trajectory_analysis.py @@ -0,0 +1,199 @@ +""" +Some functions for analyzing trajectories + +Author: Niklaus Johner +""" + +import ost.mol.alg +import ost.geom +from ost import LogError +import os + +def smooth(vec,n): +#Function to smooth a vector or a list of floats +#for each element it takes the average over itself and the +#n elements on each side, so over (2n+1) elements + try: + vec2=vec.copy() + except: + vec2=vec[:] + for i in range(n): + v=0.0 + count=1.0 + v+=vec[i] + for j in range(n): + count+=1 + v+=vec[i+j+1] + for j in range(i): + count+=1 + v+=vec[i-(j+1)] + vec2[i]=v/float(count) + for i in range(1,n+1): + v=0.0 + count=1.0 + v+=vec[-i] + for j in range(n): + count+=1 + v+=vec[-(i+j+1)] + for j in range(i-1): + count+=1 + v+=vec[-i+j+1] + vec2[-i]=v/float(count) + for i in range(n,len(vec2)-n): + v=vec[i] + for j in range(n): + v+=vec[i+j+1] + v+=vec[i-j-1] + vec2[i]=v/float(2.*n+1.) + return vec2 + + +""" +From here on the module needs numpy +""" + +def RMSD_Matrix_From_Traj(t,sele,first=0,last=-1): + """ + This function calculates a matrix M such that M[i,j] is the + RMSD of the EntityView sele between frames i and j of the trajectory t + aligned on sele. + Its inputs are: + t : the trajectory (CoordGroupHandle) + sele : the EntityView used for alignment and RMSD calculation + first=0 : the first frame of t to be used + last=-1 : the last frame of t to be used + Returns a numpy NxN matrix, where n is the number of frames. + """ + try: + import numpy as npy + if last==-1:last=t.GetFrameCount() + n_frames=last-first + rmsd_matrix=npy.identity(n_frames) + for i in range(n_frames): + t=ost.mol.alg.SuperposeFrames(t,sele,begin=first,end=last,ref=i) + eh=t.GetEntity() + t.CopyFrame(i) + rmsd_matrix[i,:]=ost.mol.alg.AnalyzeRMSD(t,sele,sele) + if i==0: + last=last-first + first=0 + return rmsd_matrix + except ImportError: + LogError("Function needs numpy, but I could not import it.") + raise + + +def PairwiseDistancesFromTraj(t,sele,first=0,last=-1,seq_sep=1): + """ + This function calculates the distances between any pair of atoms in the + EntityView sele with sequence separation larger than seq_sep from a trajectory t. + It return a matrix containing one line for each atom pair and N columns, where + N is the length of the trajectory. + Its inputs are: + t : the trajectory (CoordGroupHandle) + sele : the EntityView used to determine the atom pairs + first=0 : the first frame of t to be used + last=-1 : the last frame of t to be used + seq_sep=1 : The minimal sequence separation between + Returns a numpy NpairsxNframes matrix. + """ + try: + import numpy as npy + if last==-1:last=t.GetFrameCount() + n_frames=last-first + n_var=0 + for i,a1 in enumerate(sele.atoms): + for j,a2 in enumerate(sele.atoms): + if not j-i<seq_sep:n_var+=1 + #n_var=sele.GetAtomCount() + #n_var=(n_var-1)*(n_var)/2. + dist_matrix=npy.zeros(n_frames*n_var) + dist_matrix=dist_matrix.reshape(n_var,n_frames) + k=0 + for i,a1 in enumerate(sele.atoms): + for j,a2 in enumerate(sele.atoms): + if j-i<seq_sep:continue + dist_matrix[k]=ost.mol.alg.AnalyzeDistanceBetwAtoms(t,a1.GetHandle(),a2.GetHandle())[first:last] + k+=1 + return dist_matrix + except ImportError: + LogError("Function needs numpy, but I could not import it.") + raise + +def DistanceMatrixFromPairwiseDistances(distances,p=2): + """ + This function calculates an distance matrix M(NxN) from + the pairwise distances matrix D(MxN), where N is the number + of frames in the trajectory and M the number of atom pairs. + M[i,j] is the distance between frame i and frame j + calculated as a p-norm of the differences in distances + from the two frames (distance-RMSD for p=2). + Inputs: + distances : a pairwise distance matrix as obtained from PairwiseDistancesFromTraj() + Returns a numpy NxN matrix, where N is the number of frames. + """ + try: + import numpy as npy + n1=distances.shape[0] + n2=distances.shape[1] + dist_mat=npy.identity(n2) + for i in range(n2): + for j in range(n2): + if j<=i:continue + d=(((abs(distances[:,i]-distances[:,j])**p).sum())/float(n1))**(1./p) + dist_mat[i,j]=d + dist_mat[j,i]=d + return dist_mat + except ImportError: + LogError("Function needs numpy, but I could not import it.") + raise + +def DistRMSDFromTraj(t,sele,ref_sele,radius=7.0,average=False,seq_sep=4,first=0,last=-1): + """ + This function calculates the distance RMSD from a trajectory. + The distances selected for the calculation are all the distances + between pair of atoms that from residues that are at least seq_sep apart + in the sequence and that are smaller than radius in ref_sel. + The number and order of atoms in ref_sele and sele should be the same. + Its inputs are: + t : the trajectory (CoordGroupHandle) + sele : the EntityView used to determine the distances from t + radius=7 : the upper limit of distances in ref_sele considered for the calculation + seq_sep=4 : The minimal sequence separation between atom pairs considered for the calculation + average=false : use the average distance in the trajectory as reference instead of the distance obtained from ref_sele + first=0 : the first frame of t to be used + last=-1 : the last frame of t to be used + Returns a numpy vecor dist_rmsd(Nframes). + """ + if not sele.GetAtomCount()==ref_sele.GetAtomCount(): + print 'Not same number of atoms in the two views' + return + try: + import numpy as npy + if last==-1:last=t.GetFrameCount() + n_frames=last-first + dist_rmsd=npy.zeros(n_frames) + pair_count=0.0 + for i,a1 in enumerate(ref_sele.atoms): + for j,a2 in enumerate(ref_sele.atoms): + if j<=i:continue + r1=a1.GetResidue() + c1=r1.GetChain() + r2=a2.GetResidue() + c2=r2.GetChain() + if c1==c2 and abs(r2.GetNumber().num-r1.GetNumber().num)<seq_sep:continue + d=ost.geom.Distance(a1.pos,a2.pos) + if d<radius: + a3=sele.atoms[i] + a4=sele.atoms[j] + d_traj=ost.mol.alg.AnalyzeDistanceBetwAtoms(t,a3.GetHandle(),a4.GetHandle())[first:last] + if average:d=npy.mean(d_traj) + for k,el in enumerate(d_traj): + dist_rmsd[k]+=(el-d)**2.0 + pair_count+=1.0 + return (dist_rmsd/float(pair_count))**0.5 + except ImportError: + LogError("Function needs numpy, but I could not import it.") + raise + + \ No newline at end of file diff --git a/modules/mol/alg/pymod/wrap_mol_alg.cc b/modules/mol/alg/pymod/wrap_mol_alg.cc index 4f974d940ee2f090eb4d0a5c3d90f46a06616747..c7c3e1c3b3b62e46de87b21ff5a118da5808cbcb 100644 --- a/modules/mol/alg/pymod/wrap_mol_alg.cc +++ b/modules/mol/alg/pymod/wrap_mol_alg.cc @@ -18,6 +18,7 @@ //------------------------------------------------------------------------------ #include <boost/python.hpp> +#include <boost/python/suite/indexing/vector_indexing_suite.hpp> #include <ost/config.hh> #include <ost/mol/alg/local_dist_test.hh> #include <ost/mol/alg/superpose_frames.hh> @@ -27,6 +28,7 @@ using namespace ost; void export_svdSuperPose(); void export_TrajectoryAnalysis(); +void export_StructureAnalysis(); void export_Clash(); #if OST_IMG_ENABLED void export_entity_to_density(); @@ -34,12 +36,39 @@ void export_entity_to_density(); namespace { -Real (*ldt_a)(const mol::EntityView&, const mol::EntityView& ref, Real, Real, const String&)=&mol::alg::LocalDistTest; +Real (*ldt_a)(const mol::EntityView&, const mol::alg::GlobalDistanceList& glob_dist_list, Real, const String&)=&mol::alg::LocalDistTest; Real (*ldt_b)(const seq::AlignmentHandle&,Real, Real, int, int)=&mol::alg::LocalDistTest; -mol::EntityView (*fc_a)(const mol::EntityView&, Real,bool)=&mol::alg::FilterClashes; -mol::EntityView (*fc_b)(const mol::EntityHandle&, Real, bool)=&mol::alg::FilterClashes; +mol::EntityView (*fc_a)(const mol::EntityView&, const mol::alg::ClashingDistances&,bool)=&mol::alg::FilterClashes; +mol::EntityView (*fc_b)(const mol::EntityHandle&, const mol::alg::ClashingDistances&, bool)=&mol::alg::FilterClashes; +mol::EntityView (*csc_a)(const mol::EntityView&, const mol::alg::StereoChemicalParams&, const mol::alg::StereoChemicalParams&, Real, Real, bool)=&mol::alg::CheckStereoChemistry; +mol::EntityView (*csc_b)(const mol::EntityHandle&, const mol::alg::StereoChemicalParams&, const mol::alg::StereoChemicalParams&, Real, Real, bool)=&mol::alg::CheckStereoChemistry; mol::CoordGroupHandle (*superpose_frames1)(mol::CoordGroupHandle&, mol::EntityView&, int, int, int)=&mol::alg::SuperposeFrames; mol::CoordGroupHandle (*superpose_frames2)(mol::CoordGroupHandle&, mol::EntityView&, mol::EntityView&, int, int)=&mol::alg::SuperposeFrames; + +ost::mol::alg::StereoChemicalParams fill_stereochemical_params_wrapper (const String& header, const list& stereo_chemical_props_file) +{ + int stereo_chemical_props_file_length = boost::python::extract<int>(stereo_chemical_props_file.attr("__len__")()); + std::vector<String> stereo_chemical_props_file_vector; + + for (int i=0; i<stereo_chemical_props_file_length; i++) { + String extracted_string = boost::python::extract<String>(stereo_chemical_props_file[i]); + stereo_chemical_props_file_vector.push_back(extracted_string); + } + return ost::mol::alg::FillStereoChemicalParams(header,stereo_chemical_props_file_vector); +} + +ost::mol::alg::ClashingDistances fill_clashing_distances_wrapper (const list& stereo_chemical_props_file, Real min_default_distance, Real min_distance_tolerance) +{ + int stereo_chemical_props_file_length = boost::python::extract<int>(stereo_chemical_props_file.attr("__len__")()); + std::vector<String> stereo_chemical_props_file_vector(stereo_chemical_props_file_length); + + for (int i=0; i<stereo_chemical_props_file_length; i++) { + stereo_chemical_props_file_vector[i] = boost::python::extract<char const*>(stereo_chemical_props_file[i]); + } + + return ost::mol::alg::FillClashingDistances(stereo_chemical_props_file_vector,min_default_distance,min_distance_tolerance); +} + } @@ -48,18 +77,71 @@ BOOST_PYTHON_MODULE(_ost_mol_alg) { export_svdSuperPose(); export_TrajectoryAnalysis(); + export_StructureAnalysis(); #if OST_IMG_ENABLED export_entity_to_density(); #endif def("LocalDistTest", ldt_a, (arg("local_ldt_property_string")="")); def("LocalDistTest", ldt_b, (arg("ref_index")=0, arg("mdl_index")=1)); - def("FilterClashes", fc_a, (arg("ent"), arg("tolerance")=0.1, arg("always_remove_bb")=false)); - def("FilterClashes", fc_b, (arg("ent"), arg("tolerance")=0.1, arg("always_remove_bb")=false)); + def("FilterClashes", fc_a, (arg("ent"), arg("clashing_distances"), arg("always_remove_bb")=false)); + def("FilterClashes", fc_b, (arg("ent"), arg("clashing_distances"), arg("always_remove_bb")=false)); + def("CheckStereoChemistry", csc_a, (arg("ent"), arg("bonds"), arg("angles"), arg("bond_tolerance"), arg("angle_tolerance"), arg("always_remove_bb")=false)); + def("CheckStereoChemistry", csc_b, (arg("ent"), arg("bonds"), arg("angles"), arg("bond_tolerance"), arg("angle_tolerance"), arg("always_remove_bb")=false)); + def("LDTHA",&mol::alg::LDTHA); + def("CreateDistanceList",&mol::alg::CreateDistanceList); + def("SuperposeFrames", superpose_frames1, (arg("source"), arg("sel")=ost::mol::EntityView(), arg("begin")=0, arg("end")=-1, arg("ref")=-1)); def("SuperposeFrames", superpose_frames2, - (arg("source"), arg("sel")=ost::mol::EntityView(), arg("ref_view")=ost::mol::EntityView(),arg("begin")=0, - arg("end")=-1)); + (arg("source"), arg("sel"), arg("ref_view"),arg("begin")=0, arg("end")=-1)); + + + class_<mol::alg::ClashingDistances> ("ClashingDistances" ,init<Real,Real>()) + .def("SetClashingDistance",&mol::alg::ClashingDistances::SetClashingDistance) + .def("GetClashingDistance",&mol::alg::ClashingDistances::GetClashingDistance) + .def("GetMaxAdjustedDistance",&mol::alg::ClashingDistances::GetMaxAdjustedDistance) + .def("IsEmpty",&mol::alg::ClashingDistances::IsEmpty) + + .def("PrintAllDistances",&mol::alg::ClashingDistances::PrintAllDistances) + ; + + class_<mol::alg::StereoChemicalParams> ("StereoChemicalParams" ,init<>()) + .def("SetParam",&mol::alg::StereoChemicalParams::SetParam) + .def("GetParam",&mol::alg::StereoChemicalParams::GetParam) + .def("ContainsParam",&mol::alg::StereoChemicalParams::ContainsParam) + .def("IsEmpty",&mol::alg::StereoChemicalParams::IsEmpty) + + .def("PrintAllParameters",&mol::alg::StereoChemicalParams::PrintAllParameters) + + ; + + class_<mol::alg::UniqueAtomIdentifier> ("UniqueAtomIdentifier" ,init <const String&, const mol::ResNum&, const String&, const String&>()) + .def("GetChainName",&mol::alg::UniqueAtomIdentifier::GetChainName) + .def("GetResNum",&mol::alg::UniqueAtomIdentifier::GetResNum) + .def("GetResidueName",&mol::alg::UniqueAtomIdentifier::GetResidueName) + .def("GetAtomName",&mol::alg::UniqueAtomIdentifier::GetAtomName) + ; + + + class_<mol::alg::ReferenceDistance> ("ReferenceDistance", init <const mol::alg::UniqueAtomIdentifier&,const mol::alg::UniqueAtomIdentifier&, Real, Real>()) + .def("GetFirstAtom",&mol::alg::ReferenceDistance::GetFirstAtom) + .def("GetSecondAtom",&mol::alg::ReferenceDistance::GetSecondAtom) + .def("GetMinDistance",&mol::alg::ReferenceDistance::GetMinDistance) + .def("GetMaxDistance",&mol::alg::ReferenceDistance::GetMaxDistance) + ; + + class_<std::vector<mol::alg::ReferenceDistance> >("ResidueDistanceList") + .def(vector_indexing_suite<std::vector<mol::alg::ReferenceDistance > >()) + ; + + class_<std::vector<mol::alg::ResidueDistanceList> >("GlobalDistanceList") + .def(vector_indexing_suite<std::vector<mol::alg::ResidueDistanceList > >()) + ; + + def("FillClashingDistances",&fill_clashing_distances_wrapper); + def("FillStereoChemicalParams",&fill_stereochemical_params_wrapper); + def("IsStandardResidue",&mol::alg::IsStandardResidue); + } diff --git a/modules/mol/alg/src/CMakeLists.txt b/modules/mol/alg/src/CMakeLists.txt index 47c9af142248f8a4ee18cc65bbf24fd59d7f8f92..050d4822712f8789bfac97938e18c327334f7d92 100644 --- a/modules/mol/alg/src/CMakeLists.txt +++ b/modules/mol/alg/src/CMakeLists.txt @@ -8,6 +8,7 @@ set(OST_MOL_ALG_HEADERS construct_cbeta.hh clash_score.hh trajectory_analysis.hh + structure_analysis.hh ) set(OST_MOL_ALG_SOURCES @@ -19,6 +20,7 @@ set(OST_MOL_ALG_SOURCES filter_clashes.cc construct_cbeta.cc trajectory_analysis.cc + structure_analysis.cc ) set(MOL_ALG_DEPS ost_mol ost_seq) @@ -38,7 +40,7 @@ if (ENABLE_IMG) endif() executable(NAME ldt SOURCES ldt.cc - DEPENDS_ON ost_io ost_mol_alg STATIC) + DEPENDS_ON ost_mol ost_mol_alg ost_io STATIC) module(NAME mol_alg SOURCES ${OST_MOL_ALG_SOURCES} HEADERS ${OST_MOL_ALG_HEADERS} @@ -51,3 +53,7 @@ copy_if_different("." "${STAGE_DIR}/share/openstructure" "ost_mol_alg") install(FILES "atom_scattering_properties.txt" DESTINATION "share/openstructure/") +copy_if_different("." "${STAGE_DIR}/share/openstructure" + "stereo_chemical_props.txt" "STEREO_CHEMICAL_PROPS" + "ost_mol_alg") +install(FILES "stereo_chemical_props.txt" DESTINATION "share/openstructure/") diff --git a/modules/mol/alg/src/filter_clashes.cc b/modules/mol/alg/src/filter_clashes.cc index 0fbca1696e5bc3ef1196f6d2a4863a1b0d72dcef..1b163d17616c676e0933b7ebc7bad4c6e56dea91 100644 --- a/modules/mol/alg/src/filter_clashes.cc +++ b/modules/mol/alg/src/filter_clashes.cc @@ -18,78 +18,479 @@ //------------------------------------------------------------------------------ #include <ost/log.hh> #include <ost/mol/mol.hh> +#include <sstream> +#include <math.h> #include "filter_clashes.hh" +#include <ost/units.hh> + -namespace ost { namespace mol { namespace alg { namespace { -Real GetThreshold(const String& ele1, const String& ele2) { - if (ele1.length()!=1 || ele2.length()!=1) { - return 1.5; +String bond_string(const ost::mol::AtomView& atom1, const ost::mol::AtomHandle& atom2) { + String atom1_str = atom1.GetName(); + String atom2_str = atom2.GetName(); + String string1,string2; + if (atom1_str < atom2_str) { + string1 = atom1_str; + string2 = atom2_str; + } else { + string1 = atom2_str; + string2 = atom1_str; } - switch (ele1[0]) { - case 'C' : - switch (ele2[0]) { - case 'C' : return 2.10; - case 'N' : return 2.10; - case 'S' : return 2.45; - case 'O' : return 2.25; - default: return 1.5; - } - case 'N': - switch (ele2[0]) { - case 'C' : return 2.10; - case 'N' : return 2.05; - case 'S' : return 2.55; - case 'O' : return 2.10; - default: return 1.5; + std::stringstream stkey; + stkey << string1 << "-" << string2; + return stkey.str(); +} + +String angle_string(const ost::mol::AtomHandle& atom1, const ost::mol::AtomView& atom, const ost::mol::AtomHandle& atom2 ) { + String atom1_str = atom1.GetName(); + String atom2_str = atom2.GetName(); + String string1,string2; + if (atom1_str < atom2_str) { + string1 = atom1_str; + string2 = atom2_str; + } else { + string1 = atom2_str; + string2 = atom1_str; + } + std::stringstream stkey; + stkey << string1 << "-" << atom.GetName() << "-" << string2; + return stkey.str(); +} + + +} + + +namespace ost { namespace mol { namespace alg { + +void ClashingDistances::SetClashingDistance(const String& ele1,const String& ele2, Real min_distance, Real tolerance) +{ + std::stringstream stkey; + stkey << ele1 << "--" << ele2; + String key=stkey.str(); + min_distance_[key]=std::make_pair<Real,Real>(min_distance,tolerance); +} + +std::pair<Real,Real> ClashingDistances::GetClashingDistance(const String& ele1,const String& ele2) const +{ + std::stringstream stkey; + if (ele1<ele2) { + stkey << ele1 << "--" << ele2; + } else { + stkey << ele2 << "--" << ele1; + } + String key=stkey.str(); + std::map <String,std::pair<float,float> >::const_iterator find_ci= min_distance_.find(key); + if (find_ci == min_distance_.end()) { + return std::make_pair<Real,Real> (default_min_distance_,default_min_distance_tolerance_); + } + return find_ci->second; +} + +void ClashingDistances::PrintAllDistances() const +{ + for (std::map <String,std::pair<float,float> >::const_iterator index = min_distance_.begin();index != min_distance_.end();++index) { + std::cout << index->first << "\t" << index->second.first << "\t" << index->second.second << std::endl; + } +} + +Real ClashingDistances::GetMaxAdjustedDistance() const +{ + Real max_adjusted_distance=0; + for (std::map <String,std::pair<float,float> >::const_iterator index = min_distance_.begin();index != min_distance_.end();++index) { + Real distance = index->second.first; + Real tolerance = index->second.second; + if ((distance-tolerance) > max_adjusted_distance) { + max_adjusted_distance=distance-tolerance; + } + } + return max_adjusted_distance; +} + +bool ClashingDistances::IsEmpty() const +{ + if (min_distance_.size()==0) { + return true; + } + return false; +} + +void StereoChemicalParams::SetParam(const String& param, const String& residue, Real value, Real st_dev) +{ + std::pair<String,String> key = std::make_pair<String,String>(param,residue); + params_[key]=std::make_pair<Real,Real>(value,st_dev); +} + +std::pair<Real,Real> StereoChemicalParams::GetParam(const String& param,const String& residue) const +{ + std::pair<String,String> key = std::make_pair<String,String>(param,residue); + std::map<std::pair<String,String>,std::pair<float,float> >::const_iterator find_ci = params_.find(key); + if (find_ci == params_.end()) { + std::stringstream serr; + serr << "Entry " << param << " for residue " << residue << " not found in the parameter table"; + throw Error(serr.str()); + } + return find_ci->second; +} + +bool StereoChemicalParams::ContainsParam(const String& param,const String& residue) const +{ + std::pair<String,String> key = std::make_pair<String,String>(param,residue); + std::map<std::pair<String,String>,std::pair<float,float> >::const_iterator find_ci = params_.find(key); + if (find_ci == params_.end()) { + return false; + } + return true; +} + +void StereoChemicalParams::PrintAllParameters() const +{ + for (std::map <std::pair<String,String>,std::pair<float,float> >::const_iterator index = params_.begin();index != params_.end();++index) { + std::cout << index->first.first << "\t" << index->first.second << "\t" << index->second.first << "\t" << index->second.second << std::endl; + } +}; + +bool StereoChemicalParams::IsEmpty() const +{ + if (params_.size()==0) { + return true; + } + return false; +} + +StereoChemicalParams FillStereoChemicalParams(const String& header, std::vector<String>& stereo_chemical_props_file) +{ + StereoChemicalParams table; + bool found=false; + std::vector<String>::const_iterator line_iter=stereo_chemical_props_file.begin(); + while (line_iter!=stereo_chemical_props_file.end()) { + if ((*line_iter).length()!=0 && (*line_iter).length()!=1) { + StringRef line_string_ref(line_iter->data(),(*line_iter).length()); + std::vector<StringRef> line_str_vec = line_string_ref.split(); + if (line_str_vec[0].str()==header) { + found=true; + line_iter++; + while ((*line_iter)[0]!='-') { + if ((*line_iter)[0]!='#') { + StringRef second_line_string_ref(line_iter->data(),(*line_iter).length()); + std::vector<StringRef> second_line_str_vec = second_line_string_ref.split(); + if (second_line_str_vec.size()!=4) { + std::cout << "The number of elements in one of the lines is wrong" << std::endl; + return StereoChemicalParams(); + } + StringRef item = second_line_str_vec[0]; + String res = second_line_str_vec[1].str(); + std::pair<bool,float> parse_value = second_line_str_vec[2].to_float(); + std::pair<bool,float> parse_stddev = second_line_str_vec[3].to_float(); + Real value,stddev; + if (parse_value.first==true) { + value=static_cast<Real>(parse_value.second); + } else { + std::cout << "One of the values in the third column is not a number" << std::endl; + return StereoChemicalParams(); + }; + if (parse_stddev.first==true) { + stddev=static_cast<Real>(parse_stddev.second); + } else { + std::cout << "One of the values in the fourth column is not a number" << std::endl; + return StereoChemicalParams(); + }; + std::vector<StringRef> split_item = item.split('-'); + String rearranged_item; + if (split_item.size() == 2) { + String atom1 = split_item[0].str(); + String atom2 = split_item[1].str(); + if (atom2 < atom1) { + std::stringstream srearr; + srearr << atom2 << "-" << atom1; + rearranged_item=srearr.str(); + } else { + rearranged_item = item.str(); + } + } else if (split_item.size() == 3) { + String atom1 = split_item[0].str(); + String atom = split_item[1].str(); + String atom2 = split_item[2].str(); + if (atom2 < atom1) { + std::stringstream srearr; + srearr << atom2 << "-" << atom << "-" << atom1; + rearranged_item=srearr.str(); + } else { + rearranged_item = item.str(); + } + } else { + std::cout << "One of the strings describing the parameter has the wrong format" << std::endl; + return StereoChemicalParams(); + } + table.SetParam(rearranged_item,res,value,stddev); + line_iter++; + } + } + } + } + line_iter++; + } + if (found==false) { + std::cout << "Could not find the relevant section in the stereo-chemical parameter file" << std::endl; + return StereoChemicalParams(); + }; + return table; +}; + +ClashingDistances FillClashingDistances(std::vector<String>& stereo_chemical_props_file, Real min_default_distance, Real min_distance_tolerance) +{ + ClashingDistances table(min_default_distance,min_distance_tolerance); + bool found=false; + std::vector<String>::const_iterator line_iter=stereo_chemical_props_file.begin(); + while (line_iter!=stereo_chemical_props_file.end()) { + if ((*line_iter).length()!=0 && (*line_iter).length()!=1) { + StringRef line_string_ref(line_iter->data(),(*line_iter).length()); + std::vector<StringRef> line_str_vec = line_string_ref.split(); + if (line_str_vec[0].str()=="Non-bonded") { + found=true; + line_iter++; + while ((*line_iter)[0]!='-') { + if ((*line_iter)[0]!='#') { + StringRef second_line_string_ref(line_iter->data(),(*line_iter).length()); + std::vector<StringRef> second_line_str_vec = second_line_string_ref.split(); + if (second_line_str_vec.size()!=3) { + std::cout << "The number of elements in one of the lines is wrong" << std::endl; + return ClashingDistances(min_default_distance,min_distance_tolerance); + } + String item = second_line_str_vec[0].str(); + + std::pair<bool,float> parse_value = second_line_str_vec[1].to_float(); + std::pair<bool,float> parse_stddev = second_line_str_vec[2].to_float(); + Real value,stddev; + if (parse_value.first==true) { + value=static_cast<Real>(parse_value.second); + } else { + std::cout << "One of the distance values is not a number" << std::endl; + return ClashingDistances(min_default_distance,min_distance_tolerance); + }; + if (parse_stddev.first==true) { + stddev=static_cast<Real>(parse_stddev.second); + } else { + std::cout << "One of the tolerance values is not a number" << std::endl; + return ClashingDistances(min_default_distance,min_distance_tolerance); + } + StringRef itemsr(item.data(),item.length()); + std::vector<StringRef> eles = itemsr.split('-'); + if (itemsr.size() != 3) { + std::cout << "One of the strings describing the interacting atoms has the wrong format" << std::endl; + return ClashingDistances(min_default_distance,min_distance_tolerance); + } + String ele1=eles[0].str(); + String ele2=eles[1].str(); + if (ele2 < ele1) { + table.SetClashingDistance(ele2,ele1,value,stddev); + } else { + table.SetClashingDistance(ele1,ele2,value,stddev); + } + line_iter++; + } + } + } + } + line_iter++; + } + if (found==false) { + std::cout << "Could not find the relevant section in the stereo-chemical parameter file" << std::endl; + return ClashingDistances(min_default_distance,min_distance_tolerance); + } + return table; +} + + +EntityView CheckStereoChemistry(const EntityView& ent, const StereoChemicalParams& bond_table, const StereoChemicalParams& angle_table, Real bond_tolerance, Real angle_tolerance, bool always_remove_bb) +{ + Real running_sum_zscore_bonds=0.0; + Real running_sum_zscore_angles=0.0; + int bond_count = 0; + int bad_bond_count = 0; + int angle_count = 1; + int bad_angle_count = 0; + LOG_INFO("Checking stereo-chemistry") + EntityView filtered=ent.CreateEmptyView(); + ResidueViewList residues=ent.GetResidueList(); + for (ResidueViewList::iterator i=residues.begin(), e=residues.end(); i!=e; ++i) { + bool remove_sc=false, remove_bb=false; + ResidueView res=*i; + if (res.GetOneLetterCode()=='?') { + filtered.AddResidue(res, ViewAddFlag::INCLUDE_ATOMS); + continue; + } + String residue_str = res.GetName(); + const AtomViewList& atoms=res.GetAtomList(); + for (AtomViewList::const_iterator j=atoms.begin(), e2=atoms.end(); j!=e2; ++j) { + AtomView atom=*j; + String ele1=atom.GetElement(); + if (ele1=="H" || ele1=="D") { + continue; } - case 'O': - switch (ele2[0]) { - case 'C' : return 2.25; - case 'N' : return 2.10; - case 'S' : return 2.45; - case 'O' : return 2.05; - default: return 1.5; + BondHandleList bonds = atom.GetBondList(); + + for (BondHandeList::const_iterator bi = bonds.begin();bi!=bonds.end();++bi) { + BondHandle bond = *bi; + AtomHandle other_atom = bond.GetOther(atom.GetHandle()); + if (other_atom.GetResidue()!=res.GetHandle()) { + continue; + } + String ele2 = other_atom.GetElement(); + if (ele2=="H" || ele2=="D") { + continue; + } + if (other_atom.GetHashCode() > atom.GetHandle().GetHashCode()) { + Real blength = bond.GetLength(); + String bond_str = bond_string(atom,other_atom); + std::pair<Real,Real> length_stddev = bond_table.GetParam(bond_str,residue_str); + Real ref_length = length_stddev.first; + Real ref_stddev = length_stddev.second; + Real min_length = ref_length - bond_tolerance*ref_stddev; + Real max_length = ref_length + bond_tolerance*ref_stddev; + Real zscore = (blength - ref_length)/ref_stddev; + if (blength < min_length || blength > max_length) { + LOG_INFO("BOND:" << " " << res.GetChain() << " " << res.GetName() << " " << res.GetNumber() << " " << bond_str << " " << min_length << " " << max_length << " " << blength << " " << zscore << " " << "FAIL") + bad_bond_count++; + remove_sc=true; + if (always_remove_bb==true) { + remove_bb=true; + } + String name=atom.GetName(); + if (name=="CA" || name=="N" || name=="O" || name=="C") { + remove_bb=true; + } + } else { + LOG_VERBOSE("BOND:" << " " << res.GetChain() << " " << res.GetName() << " " << res.GetNumber() << " " << bond_str << " " << min_length << " " << max_length << " " << blength << " " << zscore << " " << "PASS") + } + bond_count++; + running_sum_zscore_bonds+=zscore; + } } - case 'S': - switch (ele2[0]) { - case 'C' : return 2.45; - case 'N' : return 2.55; - case 'S' : return 1.80; - case 'O' : return 2.45; - default: return 1.5; + + for (BondHandeList::const_iterator bond_iter1=bonds.begin(); bond_iter1!=bonds.end(); ++bond_iter1) { + BondHandle bond1=*bond_iter1; + AtomHandle atom1= bond1.GetOther(atom.GetHandle()); + String ele_atom1=atom1.GetElement(); + if (ele_atom1=="H" || ele_atom1=="D") { + continue; + } + if (atom1.GetResidue()!=res.GetHandle()) { + continue; + } + for (BondHandeList::const_iterator bond_iter2=bonds.begin(); bond_iter2!=bonds.end(); ++bond_iter2) { + BondHandle bond2=*bond_iter2; + AtomHandle atom2 = bond2.GetOther(atom.GetHandle()); + String ele_atom2=atom2.GetElement(); + if (ele_atom2=="H" || ele_atom2=="D") { + continue; + } + if (atom2.GetResidue()!=res.GetHandle()) { + continue; + } + if (atom1.GetHashCode() > atom2.GetHashCode()) { + Real awidth; + if (atom1.GetName()<atom2.GetName()) { + awidth = ent.GetAngle(atom1,atom.GetHandle(),atom2); + } else { + awidth = ent.GetAngle(atom2,atom.GetHandle(),atom1); + } + awidth/=(ost::Units::deg); + String angle_str = angle_string(atom1,atom,atom2); + std::pair<Real,Real> width_stddev = angle_table.GetParam(angle_str,residue_str); + Real ref_width = width_stddev.first; + Real ref_stddev = width_stddev.second; + Real min_width = ref_width - angle_tolerance*ref_stddev; + Real max_width = ref_width + angle_tolerance*ref_stddev; + Real zscore = (awidth - ref_width)/ref_stddev; + if (awidth < min_width || awidth > max_width) { + LOG_INFO("ANGLE:" << " " << res.GetChain() << " " << res.GetName() << " " << res.GetNumber() << " " << angle_str << " " << min_width << " " << max_width << " " << awidth << " " << zscore << " " << "FAIL") + bad_angle_count++; + remove_sc=true; + if (always_remove_bb==true) { + remove_bb=true; + } + String name=atom.GetName(); + if (name=="CA" || name=="N" || name=="O" || name=="C") { + remove_bb=true; + } + } else { + LOG_VERBOSE("ANGLE:" << " " << res.GetChain() << " " << res.GetName() << " " << res.GetNumber() << " " << angle_str << " " << min_width << " " << max_width << " " << awidth << " " << zscore << " " << "PASS") + } + angle_count++; + running_sum_zscore_angles+=zscore; + } + } + } + } + + if (remove_bb) { + LOG_INFO("ACTION: removing whole residue " << res); + continue; + } + if (remove_sc) { + LOG_INFO("ACTION: removing sidechain of residue " << res); + for (AtomViewList::const_iterator + j=atoms.begin(), e2=atoms.end(); j!=e2; ++j) { + AtomView atom=*j; + String name=atom.GetName(); + if (name=="CA" || name=="N" || name=="O" || name=="C") { + filtered.AddAtom(atom); + } } - default: - return 1.5; + continue; + } + filtered.AddResidue(res, ViewAddFlag::INCLUDE_ATOMS); } + Real avg_zscore_bonds = running_sum_zscore_bonds/static_cast<float>(bond_count); + Real avg_zscore_angles = running_sum_zscore_angles/static_cast<float>(angle_count); + LOG_SCRIPT("Average Z-Score for bond lengths: " << avg_zscore_bonds); + LOG_SCRIPT("Bonds outside of tolerance range: " << bad_bond_count << " out of " << bond_count); + LOG_SCRIPT("Average Z-Score angle widths: " << avg_zscore_angles); + LOG_SCRIPT("Angles outside of tolerance range: " << bad_angle_count << " out of " << angle_count); + return filtered; } +EntityView CheckStereoChemistry(const EntityHandle& ent, const StereoChemicalParams& bond_table, const StereoChemicalParams& angle_table, Real bond_tolerance, Real angle_tolerance, bool always_remove_bb) +{ + return CheckStereoChemistry(ent.CreateFullView(), bond_table, angle_table, bond_tolerance, angle_tolerance, always_remove_bb); } -EntityView FilterClashes(const EntityView& ent, Real tolerance, - bool always_remove_bb) + +EntityView FilterClashes(const EntityView& ent, const ClashingDistances& min_distances, bool always_remove_bb) { + int distance_count = 0; + int bad_distance_count = 0; + LOG_INFO("Filtering non-bonded clashes") EntityView filtered=ent.CreateEmptyView(); ResidueViewList residues=ent.GetResidueList(); for (ResidueViewList::iterator i=residues.begin(), e=residues.end(); i!=e; ++i) { bool remove_sc=false, remove_bb=false; ResidueView res=*i; + if (res.GetOneLetterCode()=='?') { + filtered.AddResidue(res, ViewAddFlag::INCLUDE_ATOMS); + continue; + } const AtomViewList& atoms=res.GetAtomList(); for (AtomViewList::const_iterator j=atoms.begin(), e2=atoms.end(); j!=e2; ++j) { AtomView atom=*j; + String ele1=atom.GetElement(); if (ele1=="H" || ele1=="D") { continue; } - AtomViewList within=ent.FindWithin(atom.GetPos(), 2.5-tolerance); + AtomViewList within=ent.FindWithin(atom.GetPos(),min_distances.GetMaxAdjustedDistance()); for (AtomViewList::iterator k=within.begin(), e3=within.end(); k!=e3; ++k) { AtomView atom2=*k; + + + if (atom2==atom) { continue; } @@ -97,33 +498,47 @@ EntityView FilterClashes(const EntityView& ent, Real tolerance, if (ele2=="H" || ele2=="D") { continue; } + + // In theory, this should also trigger for disulfide bonds, but // since we don't detect disulfides correctly, we can't count on that - // and we instead allow S-S distances down to 1.8. + // and we instead allow S-S distances down to 1.8. if (atom.GetHandle().FindBondToAtom(atom2.GetHandle()).IsValid()) { continue; } + + + Real d=geom::Length2(atom.GetPos()-atom2.GetPos()); - Real threshold=GetThreshold(ele1, ele2)-tolerance; + std::pair <Real,Real> distance_tolerance=min_distances.GetClashingDistance(ele1, ele2); + Real distance=distance_tolerance.first; + Real tolerance=distance_tolerance.second; + Real threshold=distance-tolerance; + if (d<threshold*threshold) { + LOG_INFO(atom.GetResidue().GetChain() << " " << atom.GetResidue().GetName() << " " << atom.GetResidue().GetNumber() << " " << atom.GetName() << " " << atom2.GetResidue().GetChain() << " " << atom2.GetResidue().GetName() << " " << atom2.GetResidue().GetNumber() << " " << atom2.GetName() << " " << threshold << " " << sqrt(d) << " " << sqrt(d)-threshold << " " << "FAIL") + bad_distance_count++; remove_sc=true; if (always_remove_bb==true) { remove_bb=true; - continue; } String name=atom.GetName(); if (name=="CA" || name=="N" || name=="O" || name=="C") { remove_bb=true; } + } else { + LOG_VERBOSE("CLASH:" << " " << atom.GetResidue().GetChain() << " " << atom.GetResidue().GetName() << " " << atom.GetResidue().GetNumber() << " " << atom.GetName() << " " << atom2.GetResidue().GetChain() << " " << atom2.GetResidue().GetNumber() << " " << atom2.GetResidue().GetName() << " " << atom2.GetName() << " " << threshold << " " << sqrt(d) << " " << sqrt(d)-threshold << " " << "PASS") } + distance_count++; } } + if (remove_bb) { - LOG_VERBOSE("removing whole residue " << res); + LOG_VERBOSE("ACTION: removing whole residue " << res); continue; } if (remove_sc) { - LOG_VERBOSE("removing sidechain of residue " << res); + LOG_VERBOSE("ACTION: removing sidechain of residue " << res); for (AtomViewList::const_iterator j=atoms.begin(), e2=atoms.end(); j!=e2; ++j) { AtomView atom=*j; @@ -136,16 +551,16 @@ EntityView FilterClashes(const EntityView& ent, Real tolerance, } filtered.AddResidue(res, ViewAddFlag::INCLUDE_ATOMS); } + LOG_SCRIPT(bad_distance_count << " out of " << distance_count << " non-bonded short-range distances checked shorter than tolerance distance"); return filtered; } -EntityView FilterClashes(const EntityHandle& ent, Real tolerance, - bool always_remove_bb) +EntityView FilterClashes(const EntityHandle& ent, + const ClashingDistances& min_distances, bool always_remove_bb) { - return FilterClashes(ent.CreateFullView(), tolerance, always_remove_bb); + return FilterClashes(ent.CreateFullView(), min_distances, always_remove_bb); } }}} - diff --git a/modules/mol/alg/src/filter_clashes.hh b/modules/mol/alg/src/filter_clashes.hh index 052e1ce5f65efd86396de967b9ad635afee3a715..5d64fc23060cdf879c434ccf52c950444b2087d0 100644 --- a/modules/mol/alg/src/filter_clashes.hh +++ b/modules/mol/alg/src/filter_clashes.hh @@ -24,14 +24,70 @@ namespace ost { namespace mol { namespace alg { +class ClashingDistances +{ +public: + ClashingDistances(Real default_dist, Real tolerance): default_min_distance_(default_dist), default_min_distance_tolerance_(tolerance), valid_flag_(true) {} + void SetClashingDistance(const String& ele1,const String& ele2, Real min_distance, Real tolerance); + std::pair<Real,Real> GetClashingDistance(const String& ele1,const String& ele2) const; + Real GetMaxAdjustedDistance() const; + bool IsEmpty() const; + + //DEBUG + void PrintAllDistances() const; + +private: + + std::map <String,std::pair<float,float> > min_distance_; + Real default_min_distance_; + Real default_min_distance_tolerance_; + bool valid_flag_; + +}; + +class StereoChemicalParams +{ + +public: + void SetParam(const String& param, const String& residue, Real value, Real st_dev); + std::pair<Real,Real> GetParam(const String& element,const String& residue) const; + bool ContainsParam(const String& param,const String& residue) const; + bool IsEmpty() const; + + //DEBUG + void PrintAllParameters() const; + +private: + + std::map<std::pair<String,String>,std::pair<float,float> > params_; + +}; + +ClashingDistances DLLEXPORT_OST_MOL_ALG FillClashingDistances(std::vector<String>& stereo_chemical_props_file, Real min_default_distance, Real min_distance_tolerance); +StereoChemicalParams DLLEXPORT_OST_MOL_ALG FillStereoChemicalParams(const String& header, std::vector<String>& stereo_chemical_props_file); + EntityView DLLEXPORT_OST_MOL_ALG FilterClashes(const EntityView& ent, - Real tolerance=0.1, - bool always_remove_bb=false); + const ClashingDistances& min_distances, bool always_remove_bb=false); EntityView DLLEXPORT_OST_MOL_ALG FilterClashes(const EntityHandle& ent, - Real tolerance=0.1, - bool always_remove_bb=false); + const ClashingDistances& min_distances, bool always_remove_bb=false); + +EntityView DLLEXPORT_OST_MOL_ALG CheckStereoChemistry(const EntityView& ent, + const StereoChemicalParams& bond_table, + const StereoChemicalParams& angle_table, + Real bond_tolerance, + Real angle_tolerance, + bool always_remove_bb=false); + +EntityView DLLEXPORT_OST_MOL_ALG CheckStereoChemistry(const EntityHandle& ent, + const StereoChemicalParams& bond_table, + const StereoChemicalParams& angle_table, + Real bond_tolerance, + Real angle_tolerance, + bool always_remove_bb=false); + + }}} diff --git a/modules/mol/alg/src/ldt.cc b/modules/mol/alg/src/ldt.cc index ff566e489af453c26fdc29ffacbe5c11464730eb..48dfc9a6ca3e08762a8356be905867bd3c868678 100644 --- a/modules/mol/alg/src/ldt.cc +++ b/modules/mol/alg/src/ldt.cc @@ -13,22 +13,32 @@ // details. // // You should have received a copy of the GNU Lesser General Public License -// along with this library; if not, write to the Free Software Foundation, Inc., +// along with this library; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA //------------------------------------------------------------------------------ #if defined (_MSC_VER) #define BOOST_ALL_DYN_LINK 1 #endif #include <boost/program_options.hpp> +#include <boost/filesystem/fstream.hpp> +#include <boost/filesystem/convenience.hpp> #include <ost/mol/alg/local_dist_test.hh> #include <ost/mol/alg/filter_clashes.hh> #include <ost/io/mol/pdb_reader.hh> #include <ost/io/io_exception.hh> #include <ost/conop/conop.hh> +#include <ost/conop/amino_acids.hh> +#include <ost/mol/iterator.hh> +#include <ost/platform.hh> +#include <ost/log.hh> + +#include <ost/conop/rule_based_builder.hh> +#include <ost/dyn_cast.hh> using namespace ost; using namespace ost::io; using namespace ost::mol; +using namespace ost::mol::alg; namespace po=boost::program_options; EntityHandle load(const String& file, const IOProfile& profile) @@ -42,7 +52,7 @@ EntityHandle load(const String& file, const IOProfile& profile) conop_inst.ConnectAll(conop_inst.GetBuilder(), ent); return ent; } - std::cerr << "ERROR: '" << file << "' does not contain any ATOM records. " + std::cerr << "ERROR: '" << file << "' does not contain any ATOM records. " << "Are you sure this is a PDB file?" << std::endl; return EntityHandle(); } catch (io::IOException& e) { @@ -54,25 +64,70 @@ EntityHandle load(const String& file, const IOProfile& profile) void usage() { std::cerr << "usage: ldt [options] <mod1> [mod1 [mod2]] <ref>" << std::endl; - std::cerr << " -s selection performed on ref" << std::endl; - std::cerr << " -c use Calphas only" << std::endl; - std::cerr << " -f filter clashes (not implemented yet)" << std::endl; - std::cerr << " -t fault tolerant parsing" << std::endl; + std::cerr << " -s selection performed on ref" << std::endl; + std::cerr << " -c use Calphas only" << std::endl; + std::cerr << " -f perform structural checks and filter input data" << std::endl; + std::cerr << " -t fault tolerant parsing" << std::endl; + std::cerr << " -p <file> use specified parmeter file. Mandatory" << std::endl; + std::cerr << " -v <level> verbosity level (0=results only,1=problems reported, 2=full report)" << std::endl; + std::cerr << " -b <value> tolerance in stddevs for bonds" << std::endl; + std::cerr << " -a <value> tolerance in stddevs for angles" << std::endl; + std::cerr << " -m <value> clashing distance for unknwon atom types" << std::endl; + std::cerr << " -r <value> distance inclusion radius" << std::endl; + std::cerr << " -e print version" << std::endl; +} + +std::pair<int,int> compute_coverage (const EntityView& v,const GlobalDistanceList& glob_dist_list) +{ + int second=0; + int first=0; + if (v.GetResidueList().size()==0) { + return std::make_pair<int,int>(0,1); + } + ChainView vchain=v.GetChainList()[0]; + for (std::vector<ResidueDistanceList>::const_iterator i=glob_dist_list.begin();i!=glob_dist_list.end();++i) + { + ResNum rnum = (*i)[0].GetFirstAtom().GetResNum(); + String rname = (*i)[0].GetFirstAtom().GetResidueName(); + if (IsStandardResidue(rname)) { + second++; + if (vchain.FindResidue(rnum)) { + first++; + } + } + } + return std::make_pair<int,int>(first,second); } int main (int argc, char **argv) { + String version = "Beta - 2012-01-17"; + Real min_default_distance = 1.5; + Real min_distance_tolerance = 0.0; + Real bond_tolerance = 8.0; + Real angle_tolerance = 8.0; + Real radius=15.0; + IOProfile profile; + profile.bond_feasibility_check=false; // parse options String sel; - bool filter_clashes=false; + bool structural_checks=false; po::options_description desc("Options"); desc.add_options() ("calpha,c", "consider only calpha atoms") - ("sel,s", po::value<String>(&sel)->default_value(""), "selection for reference") + ("sel,s", po::value<String>(&sel)->default_value(""), "selection performed on reference structure") ("tolerant,t", "fault tolerant mode") - ("filter-clashes,f", "filter clashes") - ("files", po::value< std::vector<String> >(), "input file") + ("structural-checks,f", "perform stereo-chemical and clash checks") + ("version,e", "version") + ("parameter-file,p", po::value<String>(), "stereo-chemical parameter file") + ("verbosity,v", po::value<int>(), "verbosity level") + ("bond_tolerance,b", po::value<Real>(), "tolerance in stddev for bonds") + ("angle_tolerance,a", po::value<Real>(), "tolerance in stddev for angles") + ("default_clash,m", po::value<Real>(), "clashing distance for unknown atom types") + ("inclusion_radius,r", po::value<Real>(), "distance inclusion radius") + ("files", po::value< std::vector<String> >(), "input file(s)") + ("reference",po::value<String>(),"reference(s)") ; po::positional_options_description p; p.add("files", -1); @@ -81,48 +136,184 @@ int main (int argc, char **argv) options(desc).positional(p).run(), vm); po::notify(vm); + if (vm.count("version")) { + std::cout << "Version: " << version << std::endl; + exit(0); + } + std::vector<String> files; + if (vm.count("files")) { + files=vm["files"].as<std::vector<String> >(); + } else { + usage(); + exit(-1); + } if (vm.count("calpha")) { profile.calpha_only=true; } - if (vm.count("filter-clashes")) { - filter_clashes=true; + if (vm.count("structural-checks")) { + structural_checks=true; } if (vm.count("tolerant")) { profile.fault_tolerant=true; } - std::vector<String> files; - if (vm.count("files")) { - files=vm["files"].as<std::vector<String> >(); - } else { - usage(); + String parameter_filename; + if (vm.count("parameter-file")) { + parameter_filename=vm["parameter-file"].as<String>(); + } else if (structural_checks==true) { + std::cout << "Please specify a stereo-chemical parameter file" << std::endl; exit(-1); } + int verbosity_level=0; + int ost_verbosity_level=2; + if (vm.count("verbosity")) { + verbosity_level=vm["verbosity"].as<int>(); + if (verbosity_level==0) { + ost_verbosity_level=2; + } else if (verbosity_level==1) { + ost_verbosity_level=3; + } else if (verbosity_level==2) { + ost_verbosity_level=4; + } else { + std::cout << "Verbosity level " << verbosity_level << " is not available" << std::endl; + exit(-1); + } + } + + Logger::Instance().PushVerbosityLevel(ost_verbosity_level); + + if (vm.count("bond_tolerance")) { + bond_tolerance=vm["bond_tolerance"].as<Real>(); + } + if (vm.count("angle_tolerance")) { + angle_tolerance=vm["angle_tolerance"].as<Real>(); + } + if (vm.count("default_clash")) { + min_default_distance=vm["default_clash"].as<Real>(); + } + if (vm.count("inclusion_radius")) { + radius=vm["inclusion_radius"].as<Real>(); + } String ref_file=files.back(); EntityHandle ref=load(ref_file, profile); if (!ref) { - return -1; + exit(-1); } files.pop_back(); EntityView ref_view=ref.Select(sel); + GlobalDistanceList glob_dist_list = CreateDistanceList(ref_view,radius); + std::cout << "Verbosity level: " << verbosity_level << std::endl; + if (structural_checks) { + std::cout << "Stereo-chemical and steric clash checks: On " << std::endl; + } else { + std::cout << "Stereo-chemical and steric clash checks: Off " << std::endl; + } + std::cout << "Inclusion Radius: " << radius << std::endl; + if (structural_checks) { + std::cout << "Parameter filename: " << parameter_filename << std::endl; + std::cout << "Tolerance in stddevs for bonds: " << bond_tolerance << std::endl; + std::cout << "Tolerance in stddevs for angles: " << angle_tolerance << std::endl; + std::cout << "Clashing distance for unknown atom types: " << min_default_distance << std::endl; + LOG_INFO("Log entries format:"); + LOG_INFO("BOND INFO FORMAT: Chain Residue ResNum Bond Min Max Observed Z-score Status"); + LOG_INFO("ANGLE INFO FORMAT: Chain Residue ResNum Angle Min Max Observed Z-score Status"); + LOG_INFO("CLASH INFO FORMAT: Chain1 Residue1 ResNum1 Atom1 Chain2 Residue2 ResNum2 Atom2 Observed Difference Status"); + } + LOG_INFO("LDT INFO FORMAT: Chain1 Residue1 ResNum1 Atom1 Chain2 Residue2 ResNum2 Atom2 ModelDist TargetDist Difference Tolerance Status"); for (size_t i=0; i<files.size(); ++i) { EntityHandle model=load(files[i], profile); if (!model) { if (!profile.fault_tolerant) { - return -1; + exit(-1); } continue; } EntityView v=model.CreateFullView(); - if (filter_clashes) { - v=alg::FilterClashes(v); + + + // The code in this following block is only used to make CASP9 models load correctly and normally commented out + EntityView model2=model.Select("aname!=CEN,NV,OT1,OT,CAY,CY,OXT,1OCT,NT,OT2,2OCT,OVL1,OC1,O1,OC2,O2,OVU1"); + EntityView v1=model2.Select("not (rname==GLY and aname==CB)"); + boost::filesystem::path pathstring(files[i]); + + #if BOOST_FILESYSTEM_VERSION==3 + String filestring=pathstring.filename().string(); + #else + String filestring=pathstring.file_string(); + #endif + + if (filestring.substr(5,5)=="TS257" || filestring.substr(5,5)=="TS458" ) { + for (AtomHandleIter ait=v1.GetHandle().AtomsBegin();ait!=v1.GetHandle().AtomsEnd();++ait){ + AtomHandle aitv = *ait; + String atomname=aitv.GetName(); + String firstletter=atomname.substr(0,1); + aitv.SetElement(firstletter); + } + } + v=v1; + std::cout << "File: " << files[i] << std::endl; + std::pair<int,int> cov = compute_coverage(v,glob_dist_list); + std::cout << "Coverage: " << (float(cov.first)/float(cov.second)) << " (" << cov.first << " out of " << cov.second << " residues)" << std::endl; + + if (structural_checks) { + boost::filesystem::path loc(parameter_filename); + boost::filesystem::ifstream infile(loc); + if (!infile) { + std::cout << "Could not find " << parameter_filename << std::endl; + exit(-1); + } + std::vector<String> stereo_chemical_props; + String line; + while (std::getline(infile, line)) + { + std::stringstream line_stream(line); + stereo_chemical_props.push_back(line); + } + StereoChemicalParams bond_table = FillStereoChemicalParams("Bond",stereo_chemical_props); + if (bond_table.IsEmpty()) { + std::cout << "Error reading the Bond section of the stereo-chemical parameter file." << std::endl; + exit(-1); + } + StereoChemicalParams angle_table = FillStereoChemicalParams("Angle",stereo_chemical_props); + if (angle_table.IsEmpty()) { + std::cout << "Error reading the Angles section of the stereo-chemical parameter file." << std::endl; + exit(-1); + } + + ClashingDistances nonbonded_table = FillClashingDistances(stereo_chemical_props,min_default_distance,min_distance_tolerance); + + if (nonbonded_table.IsEmpty()) { + std::cout << "Error reading the Clashing section of the stereo-chemical parameter file." << std::endl; + exit(-1); + } + v=alg::CheckStereoChemistry(v,bond_table,angle_table,bond_tolerance,angle_tolerance); + 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); + 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; } - float cutoffs[]={0.5,1,2,4}; - float ldt=0.0; - for (int n=0; n<4; ++n) { - ldt+=alg::LocalDistTest(v, ref_view, cutoffs[n], 8.0); + if (cov.first==0) { + std::cout << "Global LDT score: 0.0" << std::endl; + return 0; } - ldt/=4.0; - std::cout << files[i] << " " << ldt << std::endl; + Real ldt=LDTHA(v, glob_dist_list); + + std::cout << "Global LDT score: " << ldt << std::endl; + std::cout << "Local LDT Score:" << std::endl; + std::cout << "Chain\tResName\tResNum\tScore" << std::endl; + String labels[]={"localldt0.5","localldt1","localldt2","ldtlocal4"}; + for (ResidueViewIter rit=v.ResiduesBegin();rit!=v.ResiduesEnd();++rit){ + ResidueView ritv = *rit; + Real ldt_local_sum = 0; + if (ritv.HasProp("localldt0.5")) { + for (int n=0; n<4; ++n) { + ldt_local_sum+=ritv.GetFloatProp(labels[n]); + } + ldt_local_sum/=4.0; + std::cout << ritv.GetChain() << "\t" << ritv.GetName() << "\t" << ritv.GetNumber() << '\t' << ldt_local_sum << std::endl; + } + } + std::cout << std::endl; } return 0; -} \ No newline at end of file +} diff --git a/modules/mol/alg/src/local_dist_test.cc b/modules/mol/alg/src/local_dist_test.cc index 5441f681b2349797eb6b0a38266d63285dbe7616..430dd31bebb4e5c5bea26461df9b253e8bc0d608 100644 --- a/modules/mol/alg/src/local_dist_test.cc +++ b/modules/mol/alg/src/local_dist_test.cc @@ -1,6 +1,7 @@ #include <ost/log.hh> #include <ost/mol/mol.hh> #include "local_dist_test.hh" +#include <boost/concept_check.hpp> namespace ost { namespace mol { namespace alg { @@ -37,7 +38,8 @@ bool swappable(const String& rname, const String& aname) if (rname=="ASP") { return (aname=="OD1" || aname=="OD2"); } - if (rname=="VAL") { + if (rname=="VAL") { + return (aname=="CG1" || aname=="CG2"); } if (rname=="TYR" || rname=="PHE") { @@ -49,73 +51,103 @@ bool swappable(const String& rname, const String& aname) return false; } -std::pair<Real, Real> calc_overlap1(ResidueView ref_res, - EntityView ref, +std::pair<bool,Real> within_tolerance(Real mdl_dist, const ReferenceDistance& ref_dist, Real tol) +{ + Real min = ref_dist.GetMaxDistance(); + Real max = ref_dist.GetMaxDistance(); + bool within_tol = false; + Real difference = 0; + if (mdl_dist>=min && mdl_dist <=max) { + within_tol=true; + } else if (mdl_dist < min && std::abs(min-mdl_dist) < tol) { + within_tol = true; + } else if (mdl_dist > max && std::abs(mdl_dist-max) < tol) { + within_tol = true; + } + if (within_tol == false) { + if (mdl_dist > max) { + difference = mdl_dist-(max+tol); + } else { + difference = mdl_dist-(min-tol); + } + } + return std::make_pair<bool,Real>(within_tol,difference); +} + + +std::pair<Real, Real> calc_overlap1(const ResidueDistanceList& res_distance_list, ChainView mdl_chain, - Real tol, Real max_dist, bool only_fixed, - bool swap,std::vector<std::pair<Real, Real> >& overlap_list ) + Real tol, bool only_fixed, + bool swap,std::vector<std::pair<Real, Real> >& overlap_list, bool log ) { std::pair<Real, Real> overlap(0.0, 0.0); - AtomViewList ref_atoms=ref_res.GetAtomList(); - ResidueView mdl_res=mdl_chain.FindResidue(ref_res.GetNumber()); - AtomViewList within; - if (max_dist<0){ - within=ref.GetAtomList(); - } - for (AtomViewList::iterator ai=ref_atoms.begin(), - ae=ref_atoms.end(); ai!=ae; ++ai) { - if (ai->GetElement()=="H") { continue; } - String name=swap ? swapped_name(ai->GetName()) : ai->GetName(); + ResidueView mdl_res=mdl_chain.FindResidue(res_distance_list[0].GetFirstAtom().GetResNum()); + for (ResidueDistanceList::const_iterator ai=res_distance_list.begin(), + ae=res_distance_list.end(); ai!=ae; ++ai) { + UniqueAtomIdentifier first_atom=ai->GetFirstAtom(); + UniqueAtomIdentifier second_atom=ai->GetSecondAtom(); + String name=swap ? swapped_name(first_atom.GetAtomName()) : first_atom.GetAtomName(); AtomView av1=mdl_res ? mdl_res.FindAtom(name) : AtomView(); - if (max_dist>=0){ - within=ref.FindWithin(ai->GetPos(), max_dist); - } - for (AtomViewList::iterator aj=within.begin(), - ae2=within.end(); aj!=ae2; ++aj) { - if (aj->GetElement()=="H") { continue; } - if (only_fixed) { - if (aj->GetResidue().GetNumber()==ref_res.GetNumber()) { + + if (only_fixed) { + if (swappable(second_atom.GetResidueName(), second_atom.GetAtomName())) { continue; - } - if (swappable(aj->GetResidue().GetName(), aj->GetName())) { - continue; - } - AtomView av2=mdl_chain.FindAtom(aj->GetResidue().GetNumber(), - aj->GetName()); - overlap.second+=1.0; - if (!(av1 && av2)) { - continue; - } - Real mdl_dist=geom::Length(av1.GetPos()-av2.GetPos()); - Real ref_dist=geom::Length(ai->GetPos()-aj->GetPos()); - if (std::abs(mdl_dist-ref_dist)<tol) { - overlap.first+=1; - } + } + AtomView av2=mdl_chain.FindAtom(second_atom.GetResNum(),second_atom.GetAtomName()); + overlap.second+=1.0; + if (!(av1 && av2)) { continue; } - if (aj->GetResidue().GetNumber()>ref_res.GetNumber()) { - AtomView av2=mdl_chain.FindAtom(aj->GetResidue().GetNumber(), - aj->GetName()); - overlap.second+=1.0; - overlap_list[ref_res.GetIndex()].second+=1.0; - overlap_list[aj->GetResidue().GetIndex()].second+=1.0; - if (!(av1 && av2)) { - continue; - } - Real mdl_dist=geom::Length(av1.GetPos()-av2.GetPos()); - Real ref_dist=geom::Length(ai->GetPos()-aj->GetPos()); - if (std::abs(mdl_dist-ref_dist)<tol) { - overlap.first+=1; - overlap_list[ref_res.GetIndex()].first+=1.0; - overlap_list[aj->GetResidue().GetIndex()].first+=1.0; - } + Real mdl_dist=geom::Length(av1.GetPos()-av2.GetPos()); + ReferenceDistance ref_dist=*ai; + if (within_tolerance(mdl_dist,ref_dist,tol).first) { + if (log) { + LOG_VERBOSE("LDT:" << " " << av1.GetResidue().GetChain() << " " << av1.GetResidue().GetName() << " " << av1.GetResidue().GetNumber() << " " << av1.GetName() + << " " << av2.GetResidue().GetChain() << " " << av2.GetResidue().GetName() << " " << av2.GetResidue().GetNumber() << " " << av2.GetName() << " " + << mdl_dist << " " << ref_dist.GetMinDistance() << " " << ref_dist.GetMaxDistance() << " " << tol << " " << "PASS") + } + overlap.first+=1; + } else { + if (log) { + LOG_VERBOSE("LDT:" << " " << av1.GetResidue().GetChain() << " " << av1.GetResidue().GetName() << " " << av1.GetResidue().GetNumber() << " " << av1.GetName() + << " " << av2.GetResidue().GetChain() << " " << av2.GetResidue().GetName() << " " << av2.GetResidue().GetNumber() << " " << av2.GetName() << " " + << mdl_dist << " " << ref_dist.GetMinDistance() << " " << mdl_dist-ref_dist.GetMinDistance() << " " << tol << " " << "FAIL") + } } - } - } + continue; + } + AtomView av2=mdl_chain.FindAtom(second_atom.GetResNum(), second_atom.GetAtomName()); + overlap.second+=1.0; + if (av1) { + overlap_list[av1.GetResidue().GetIndex()].second+=1.0; + } + if (av2) { + overlap_list[av2.GetResidue().GetIndex()].second+=1.0; + } + if (!(av1 && av2)) { + continue; + } + + Real mdl_dist=geom::Length(av1.GetPos()-av2.GetPos()); + ReferenceDistance ref_dist=*ai; + if (within_tolerance(mdl_dist,ref_dist,tol).first) { + LOG_INFO("LDT:" << " " << av1.GetResidue().GetChain() << " " << av1.GetResidue().GetName() << " " << av1.GetResidue().GetNumber() << " " << av1.GetName() + << " " << av2.GetResidue().GetChain() << " " << av2.GetResidue().GetName() << " " << av2.GetResidue().GetNumber() << " " << av2.GetName() << " " + << mdl_dist << " " << ref_dist.GetMinDistance() << " " << mdl_dist-ref_dist.GetMinDistance() << " " << tol << " " << "PASS") + overlap.first+=1; + overlap_list[av1.GetResidue().GetIndex()].first+=1.0; + overlap_list[av2.GetResidue().GetIndex()].first+=1.0; + } else { + LOG_VERBOSE("LDT:" << " " << av1.GetResidue().GetChain() << " " << av1.GetResidue().GetName() << " " << av1.GetResidue().GetNumber() << " " << av1.GetName() + << " " << av2.GetResidue().GetChain() << " " << av2.GetResidue().GetName() << " " << av2.GetResidue().GetNumber() << " " << av2.GetName() << " " + << mdl_dist << " " << ref_dist.GetMinDistance() << " " << mdl_dist-ref_dist.GetMinDistance() << " " << tol << " " << "FAIL") + } + } return overlap; } + std::pair<Real, Real> calc_overlap2(const seq::ConstSequenceHandle& ref_seq, const seq::ConstSequenceHandle& mdl_seq, int pos, Real tol, Real max_dist, @@ -143,7 +175,10 @@ std::pair<Real, Real> calc_overlap2(const seq::ConstSequenceHandle& ref_seq, } for (AtomViewList::iterator aj=within.begin(), ae2=within.end(); aj!=ae2; ++aj) { - if (aj->GetElement()=="H") { continue; } + if (aj->GetElement()=="H" || + aj->GetResidue().GetChain()!=ai->GetResidue().GetChain()) { + continue; + } if (only_fixed) { if (aj->GetResidue().GetNumber()==ref_res.GetNumber()) { continue; @@ -172,7 +207,8 @@ std::pair<Real, Real> calc_overlap2(const seq::ConstSequenceHandle& ref_seq, continue; } else { if (aj->GetResidue().GetNumber()>ref_res.GetNumber()) { - overlap.second+=1.0; + overlap.second+=1.0; + try { int aln_pos=ref_seq.GetPos(aj->GetResidue().GetIndex()); ResidueView r2=mdl_seq.GetResidue(aln_pos); @@ -198,81 +234,194 @@ std::pair<Real, Real> calc_overlap2(const seq::ConstSequenceHandle& ref_seq, } -Real LocalDistTest(const EntityView& mdl, const EntityView& ref, - Real cutoff, Real max_dist, const String& local_ldt_property_string) +bool IsStandardResidue(String rn) +{ + String upper_rn=rn; + std::transform(rn.begin(),rn.end(),rn.begin(),toupper); + if (upper_rn == "ALA" || + upper_rn == "ARG" || + upper_rn == "ASN" || + upper_rn == "ASP" || + upper_rn == "GLN" || + upper_rn == "GLU" || + upper_rn == "LYS" || + upper_rn == "SER" || + upper_rn == "CYS" || + upper_rn == "TYR" || + upper_rn == "TRP" || + upper_rn == "THR" || + upper_rn == "VAL" || + upper_rn == "ILE" || + upper_rn == "MET" || + upper_rn == "LEU" || + upper_rn == "GLY" || + upper_rn == "PRO" || + upper_rn == "HIS" || + upper_rn == "PHE") { + return true; + } + return false; +} + +bool UniqueAtomIdentifier::operator==(const UniqueAtomIdentifier& rhs) const +{ + if (chain_ == rhs.GetChainName() && + residue_ == rhs.GetResNum() && + residue_name_ == rhs.GetResidueName() && + atom_ == rhs.GetAtomName() ) { + return true; + } + return false; +} + +bool ReferenceDistance::IsValid() const +{ + if (mind_ == -1.0 and maxd_ == -1.0) { + return false; + } + return true; +} + +void ReferenceDistance::Print() const +{ + if (this->IsValid() == true) { + std::cout << first_atom_.GetChainName() << " " << first_atom_.GetResNum() << " " << first_atom_.GetResidueName() << " " << first_atom_.GetAtomName() << " " << + second_atom_.GetChainName() << " " << second_atom_.GetResNum() << " " << second_atom_.GetResidueName() << " " << second_atom_.GetAtomName() << " " << + mind_ << " " << maxd_ << std::endl; + } else { + std::cout << first_atom_.GetChainName() << " " << first_atom_.GetResNum() << " " << first_atom_.GetResidueName() << " Placeholder" << std::endl; + } +} + +bool ReferenceDistance::operator==(const ReferenceDistance& rhs) const +{ + if (first_atom_ == rhs.GetFirstAtom() && + second_atom_ == rhs.GetSecondAtom() && + mind_ == rhs.GetMinDistance() && + maxd_ == rhs.GetMaxDistance() ) { + return true; + } + return false; +} + + + + +GlobalDistanceList CreateDistanceList(const EntityView& ref,Real max_dist) +{ + GlobalDistanceList dist_list; + ResidueViewList ref_residues=ref.GetChainList()[0].GetResidueList(); + for (ResidueViewList::iterator i=ref_residues.begin(), e=ref_residues.end(); i!=e; ++i) { + ResidueView rview = (*i); + if (IsStandardResidue(rview.GetName())) { + ResidueDistanceList res_dist_list; + AtomViewList ref_atoms=(*i).GetAtomList(); + AtomViewList within; + if (max_dist<0){ + dist_list.push_back(res_dist_list); + within=ref.GetAtomList(); + } + for (AtomViewList::iterator ai=ref_atoms.begin(), ae=ref_atoms.end(); ai!=ae; ++ai) { + UniqueAtomIdentifier first_atom(ai->GetResidue().GetChain().GetName(),ai->GetResidue().GetNumber(),ai->GetResidue().GetName(),ai->GetName()); + if (ai->GetElement()=="H") { continue; } + if (max_dist>=0){ + within=ref.FindWithin(ai->GetPos(), max_dist); + } + for (AtomViewList::iterator aj=within.begin(), ae2=within.end(); aj!=ae2; ++aj) { + UniqueAtomIdentifier second_atom(aj->GetResidue().GetChain().GetName(),aj->GetResidue().GetNumber(),aj->GetResidue().GetName(),aj->GetName()); + if (aj->GetElement()=="H" || + aj->GetResidue().GetChain()!=ai->GetResidue().GetChain()) { + continue; + } + if (aj->GetResidue().GetNumber()>i->GetNumber()) { + Real dist=geom::Length(ai->GetPos()-aj->GetPos()); + ReferenceDistance ref_dist(first_atom,second_atom,dist,dist); + res_dist_list.push_back(ref_dist); + } + } + } + if (res_dist_list.size()==0) { + UniqueAtomIdentifier current_residue_fake_atom(rview.GetChain().GetName(),rview.GetNumber(),rview.GetName(),"CA"); + ReferenceDistance fake_ref_distance(current_residue_fake_atom,current_residue_fake_atom,-1.0,-1.0); + res_dist_list.push_back(fake_ref_distance); + } + dist_list.push_back(res_dist_list); + } + } + return dist_list; +} + + +Real LocalDistTest(const EntityView& mdl, const GlobalDistanceList& glob_dist_list, + Real cutoff, const String& local_ldt_property_string) { - if (!mdl.GetResidueCount()) { LOG_WARNING("model structures doesn't contain any residues"); return 0.0; } - - if (!ref.GetResidueCount()) { - LOG_WARNING("reference structures doesn't contain any residues"); + if (glob_dist_list.size()==0) { + LOG_WARNING("global reference list is empty"); return 0.0; } - ResidueViewList ref_residues=ref.GetResidueList(); - std::vector<std::pair<Real, Real> > overlap_list(ref_residues.size(), std::pair<Real, Real>(0.0, 0.0)); + std::vector<std::pair<Real, Real> > overlap_list(mdl.GetResidueCount(), std::pair<Real, Real>(0.0, 0.0)); ChainView mdl_chain=mdl.GetChainList()[0]; // Residues with symmetric side-chains require special treatment as there are // two possible ways to name the atoms. We calculate the overlap with the // fixed atoms and take the solution that gives bigger scores. - XCSEditor edi=ref.GetHandle().EditXCS(BUFFERED_EDIT); - for (ResidueViewList::iterator - i=ref_residues.begin(), e=ref_residues.end(); i!=e; ++i) { - const String rname=i->GetName(); - ResidueView mdl_res=mdl_chain.FindResidue(i->GetNumber()); - if (!mdl_res) { - continue; - } - if (!(rname=="GLU" || rname=="ASP" || rname=="VAL" || rname=="TYR" || - rname=="PHE" || rname=="LYS" || rname=="ARG")) { + XCSEditor edi=mdl.GetHandle().EditXCS(BUFFERED_EDIT); + for (GlobalDistanceList::const_iterator i=glob_dist_list.begin(), e=glob_dist_list.end(); i!=e; ++i) { + ResidueDistanceList rdl = *i; + if (!rdl[0].IsValid()) { continue; } - - std::pair<Real, Real> ov1=calc_overlap1(*i, ref, mdl_chain, - cutoff, max_dist, true, - false, overlap_list); - std::pair<Real, Real> ov2=calc_overlap1(*i, ref, mdl_chain, - cutoff, max_dist, true, - true, overlap_list); + + ResNum rnum = rdl[0].GetFirstAtom().GetResNum() ; + String rname=rdl[0].GetFirstAtom().GetResidueName(); + ResidueView mdl_res=mdl_chain.FindResidue(rnum); + if (!mdl_res) { + continue; + } + if (!(rname=="GLU" || rname=="ASP" || rname=="VAL" || rname=="TYR" || rname=="PHE" || rname=="LYS" || rname=="ARG")) { + continue; + } + std::pair<Real, Real> ov1=calc_overlap1(*i, mdl_chain, + cutoff, true, + false, overlap_list,false); + + std::pair<Real, Real> ov2=calc_overlap1(*i, mdl_chain, + cutoff, true, + true, overlap_list,false); if (ov1.first/ov1.second<ov2.first/ov2.second) { - AtomViewList atoms=mdl_res.GetAtomList(); - for (AtomViewList::iterator j=atoms.begin(), - e2=atoms.end(); j!=e2; ++j) { - if (swappable(rname, j->GetName())) { - edi.RenameAtom(j->GetHandle(), swapped_name(j->GetName())); - } - } + AtomViewList atoms=mdl_res.GetAtomList(); + for (AtomViewList::iterator j=atoms.begin(), e2=atoms.end(); j!=e2; ++j) { + if (swappable(rname, j->GetName())) { + edi.RenameAtom(j->GetHandle(), swapped_name(j->GetName())); + } + } } } + overlap_list.clear(); std::pair<Real, Real> total_ov(0.0, 0.0); - for (ResidueViewList::iterator - i=ref_residues.begin(), e=ref_residues.end(); i!=e; ++i) { - std::pair<Real, Real> ov1=calc_overlap1(*i, ref, mdl_chain, cutoff, - max_dist, false, false, overlap_list); - total_ov.first+=ov1.first; - total_ov.second+=ov1.second; - } - - // attach local per-residue LDT as property: - if(local_ldt_property_string!="") { - for (ResidueViewList::iterator - i=ref_residues.begin(), e=ref_residues.end(); i!=e; ++i) { - std::pair<Real, Real> ov1=calc_overlap1(*i, ref, mdl_chain, cutoff, - max_dist, false, false, overlap_list); - total_ov.first+=ov1.first; - total_ov.second+=ov1.second; - Real local_ldt=overlap_list[(*i).GetIndex()].first/(overlap_list[(*i).GetIndex()].second ? overlap_list[(*i).GetIndex()].second : 1); - if (mdl_chain.FindResidue((*i).GetNumber()).IsValid()) { - ResidueView mdl_res=mdl_chain.FindResidue((*i).GetNumber()); - mdl_res.SetFloatProp(local_ldt_property_string, local_ldt); - } + for (GlobalDistanceList::const_iterator i=glob_dist_list.begin(), e=glob_dist_list.end(); i!=e; ++i) { + ResidueDistanceList rdl = *i; + if (rdl[0].IsValid()) { + std::pair<Real, Real> ov1=calc_overlap1(*i, mdl_chain, cutoff, + false, false, overlap_list,true); + total_ov.first+=ov1.first; + total_ov.second+=ov1.second; } - mdl_chain.SetFloatProp(local_ldt_property_string, total_ov.first/(total_ov.second ? total_ov.second : 1)); + if(local_ldt_property_string!="") { + ResNum rn = rdl[0].GetFirstAtom().GetResNum(); + ResidueView mdlr=mdl_chain.FindResidue(rn); + if (mdlr.IsValid()) { + int mdl_res_index =mdlr.GetIndex(); + Real local_ldt=overlap_list[mdl_res_index].first/(overlap_list[mdl_res_index].second ? overlap_list[mdl_res_index].second : 1); + ResidueView res_to_wr = mdl_chain.FindResidue((*i)[0].GetFirstAtom().GetResNum()); + res_to_wr.SetFloatProp(local_ldt_property_string, local_ldt); + } + } } overlap_list.clear(); - return total_ov.first/(total_ov.second ? total_ov.second : 1); } @@ -327,4 +476,17 @@ Real LocalDistTest(const ost::seq::AlignmentHandle& aln, return 0.0; } +Real LDTHA(EntityView& v, const GlobalDistanceList& global_dist_list) +{ + + Real cutoffs[]={0.5,1,2,4}; + String labels[]={"localldt0.5","localldt1","localldt2","ldtlocal4"}; + Real ldt=0.0; + for (int n=0; n<4; ++n) { + ldt+=alg::LocalDistTest(v, global_dist_list, cutoffs[n], labels[n]); + } + ldt/=4.0; + return ldt; +} + }}} diff --git a/modules/mol/alg/src/local_dist_test.hh b/modules/mol/alg/src/local_dist_test.hh index 76ef238034ea095ec26eebff64e08e48b60b0e8e..74e0f4f29ca00b54340a683a036904d3eb66e596 100644 --- a/modules/mol/alg/src/local_dist_test.hh +++ b/modules/mol/alg/src/local_dist_test.hh @@ -25,15 +25,70 @@ namespace ost { namespace mol { namespace alg { + +class UniqueAtomIdentifier +{ + +public: + UniqueAtomIdentifier(const String& chain,const ResNum& residue,const String& residue_name, const String& atom): chain_(chain),residue_(residue),residue_name_(residue_name),atom_(atom) {} + + String GetChainName() const { return chain_; } + ResNum GetResNum() const { return residue_; } + String GetResidueName() const { return residue_name_; } + String GetAtomName() const { return atom_; } + bool operator==(const UniqueAtomIdentifier& rhs) const; + +private: + + String chain_; + ResNum residue_; + String residue_name_; + String atom_; +}; + +class ReferenceDistance +{ + +public: + + ReferenceDistance(const UniqueAtomIdentifier& first_atom, const UniqueAtomIdentifier& second_atom, Real mind, Real maxd): + first_atom_(first_atom),second_atom_(second_atom),mind_(mind),maxd_(maxd) {} + UniqueAtomIdentifier GetFirstAtom() const {return first_atom_;} + UniqueAtomIdentifier GetSecondAtom() const {return second_atom_;} + Real GetMinDistance() const {return mind_ ;} + Real GetMaxDistance() const {return maxd_ ;} + bool IsValid() const; + void Print() const; + bool operator==(const ReferenceDistance& rhs) const; + +private: + + UniqueAtomIdentifier first_atom_; + UniqueAtomIdentifier second_atom_; + Real mind_; + Real maxd_; +}; + +typedef std::vector<ReferenceDistance> ResidueDistanceList; +typedef std::vector<ResidueDistanceList> GlobalDistanceList; + Real DLLEXPORT_OST_MOL_ALG LocalDistTest(const EntityView& mdl, - const EntityView& ref, - Real cutoff, Real max_dist, + const GlobalDistanceList& dist_list, + Real cutoff, const String& local_ldt_property_string=""); Real DLLEXPORT_OST_MOL_ALG LocalDistTest(const ost::seq::AlignmentHandle& aln, - Real cutoff, Real max_dist, + Real cutoff, Real max_dist, int ref_index=0, int mdl_index=1); + +Real DLLEXPORT_OST_MOL_ALG LDTHA(EntityView& v, const GlobalDistanceList& global_dist_list); + +GlobalDistanceList CreateDistanceList(const EntityView& ref,Real max_dist); +bool IsStandardResidue(String rn); + + + }}} #endif diff --git a/modules/mol/alg/src/new_stereo_chemical_props.txt b/modules/mol/alg/src/new_stereo_chemical_props.txt new file mode 100644 index 0000000000000000000000000000000000000000..25262efd7689fc76f4d6ea1a7c75e342e840ea1d --- /dev/null +++ b/modules/mol/alg/src/new_stereo_chemical_props.txt @@ -0,0 +1,345 @@ +Bond Residue Mean StdDev +CA-CB ALA 1.520 0.021 +N-CA ALA 1.459 0.020 +CA-C ALA 1.525 0.026 +C-O ALA 1.229 0.019 +CA-CB ARG 1.535 0.022 +CB-CG ARG 1.521 0.027 +CG-CD ARG 1.515 0.025 +CD-NE ARG 1.460 0.017 +NE-CZ ARG 1.326 0.013 +CZ-NH1 ARG 1.326 0.013 +CZ-NH2 ARG 1.326 0.013 +N-CA ARG 1.459 0.020 +CA-C ARG 1.525 0.026 +C-O ARG 1.229 0.019 +CA-CB ASN 1.527 0.026 +CB-CG ASN 1.506 0.023 +CG-OD1 ASN 1.235 0.022 +CG-ND2 ASN 1.324 0.025 +N-CA ASN 1.459 0.020 +CA-C ASN 1.525 0.026 +C-O ASN 1.229 0.019 +CA-CB ASP 1.535 0.022 +CB-CG ASP 1.513 0.021 +CG-OD1 ASP 1.249 0.023 +CG-OD2 ASP 1.249 0.023 +N-CA ASP 1.459 0.020 +CA-C ASP 1.525 0.026 +C-O ASP 1.229 0.019 +CA-CB CYS 1.526 0.013 +CB-SG CYS 1.812 0.016 +N-CA CYS 1.459 0.020 +CA-C CYS 1.525 0.026 +C-O CYS 1.229 0.019 +CA-CB GLU 1.535 0.022 +CB-CG GLU 1.517 0.019 +CG-CD GLU 1.515 0.015 +CD-OE1 GLU 1.252 0.011 +CD-OE2 GLU 1.252 0.011 +N-CA GLU 1.459 0.020 +CA-C GLU 1.525 0.026 +C-O GLU 1.229 0.019 +CA-CB GLN 1.535 0.022 +CB-CG GLN 1.521 0.027 +CG-CD GLN 1.506 0.023 +CD-OE1 GLN 1.235 0.022 +CD-NE2 GLN 1.324 0.025 +N-CA GLN 1.459 0.020 +CA-C GLN 1.525 0.026 +C-O GLN 1.229 0.019 +N-CA GLY 1.456 0.015 +CA-C GLY 1.514 0.016 +C-O GLY 1.232 0.016 +CA-CB HIS 1.535 0.022 +CB-CG HIS 1.492 0.016 +CG-ND1 HIS 1.369 0.015 +CG-CD2 HIS 1.353 0.017 +ND1-CE1 HIS 1.343 0.025 +CD2-NE2 HIS 1.415 0.021 +CE1-NE2 HIS 1.322 0.023 +N-CA HIS 1.459 0.020 +CA-C HIS 1.525 0.026 +C-O HIS 1.229 0.019 +CA-CB ILE 1.544 0.023 +CB-CG1 ILE 1.536 0.028 +CB-CG2 ILE 1.524 0.031 +CG1-CD1 ILE 1.500 0.069 +N-CA ILE 1.459 0.020 +CA-C ILE 1.525 0.026 +C-O ILE 1.229 0.019 +CA-CB LEU 1.533 0.023 +CB-CG LEU 1.521 0.029 +CG-CD1 LEU 1.514 0.037 +CG-CD2 LEU 1.514 0.037 +N-CA LEU 1.459 0.020 +CA-C LEU 1.525 0.026 +C-O LEU 1.229 0.019 +CA-CB LYS 1.535 0.022 +CB-CG LYS 1.521 0.027 +CG-CD LYS 1.520 0.034 +CD-CE LYS 1.508 0.025 +CE-NZ LYS 1.486 0.025 +N-CA LYS 1.459 0.020 +CA-C LYS 1.525 0.026 +C-O LYS 1.229 0.019 +CA-CB MET 1.535 0.022 +CB-CG MET 1.509 0.032 +CG-SD MET 1.807 0.026 +SD-CE MET 1.774 0.056 +N-CA MET 1.459 0.020 +CA-C MET 1.525 0.026 +C-O MET 1.229 0.019 +CA-CB PHE 1.535 0.022 +CB-CG PHE 1.509 0.017 +CG-CD1 PHE 1.383 0.015 +CG-CD2 PHE 1.383 0.015 +CD1-CE1 PHE 1.388 0.020 +CD2-CE2 PHE 1.388 0.020 +CE1-CZ PHE 1.369 0.019 +CE2-CZ PHE 1.369 0.019 +N-CA PHE 1.459 0.020 +CA-C PHE 1.525 0.026 +C-O PHE 1.229 0.019 +CA-CB PRO 1.531 0.020 +CB-CG PRO 1.495 0.050 +CG-CD PRO 1.502 0.033 +CD-N PRO 1.474 0.014 +N-CA PRO 1.468 0.017 +CA-C PRO 1.524 0.020 +C-O PRO 1.228 0.020 +CA-CB SER 1.525 0.015 +CB-OG SER 1.418 0.013 +N-CA SER 1.459 0.020 +CA-C SER 1.525 0.026 +C-O SER 1.229 0.019 +CA-CB THR 1.529 0.026 +CB-OG1 THR 1.428 0.020 +CB-CG2 THR 1.519 0.033 +N-CA THR 1.459 0.020 +CA-C THR 1.525 0.026 +C-O THR 1.229 0.019 +CA-CB TRP 1.535 0.022 +CB-CG TRP 1.498 0.018 +CG-CD1 TRP 1.363 0.014 +CG-CD2 TRP 1.432 0.017 +CD1-NE1 TRP 1.375 0.017 +NE1-CE2 TRP 1.371 0.013 +CD2-CE2 TRP 1.409 0.012 +CD2-CE3 TRP 1.399 0.015 +CE2-CZ2 TRP 1.393 0.017 +CE3-CZ3 TRP 1.380 0.017 +CZ2-CH2 TRP 1.369 0.019 +CZ3-CH2 TRP 1.396 0.016 +N-CA TRP 1.459 0.020 +CA-C TRP 1.525 0.026 +C-O TRP 1.229 0.019 +CA-CB TYR 1.535 0.022 +CB-CG TYR 1.512 0.015 +CG-CD1 TYR 1.387 0.013 +CG-CD2 TYR 1.387 0.013 +CD1-CE1 TYR 1.389 0.015 +CD2-CE2 TYR 1.389 0.015 +CE1-CZ TYR 1.381 0.013 +CE2-CZ TYR 1.381 0.013 +CZ-OH TYR 1.374 0.017 +N-CA TYR 1.459 0.020 +CA-C TYR 1.525 0.026 +C-O TYR 1.229 0.019 +CA-CB VAL 1.543 0.021 +CB-CG1 VAL 1.524 0.021 +CB-CG2 VAL 1.524 0.021 +N-CA VAL 1.459 0.020 +CA-C VAL 1.525 0.026 +C-O VAL 1.229 0.019 +- + +Angle Residue Mean StdDev +N-CA-CB ALA 110.1 1.4 +CB-CA-C ALA 110.1 1.5 +N-CA-C ALA 111.0 2.7 +CA-C-O ALA 120.1 2.1 +N-CA-CB ARG 110.6 1.8 +CB-CA-C ARG 110.4 2.0 +CA-CB-CG ARG 113.4 2.2 +CB-CG-CD ARG 111.6 2.6 +CG-CD-NE ARG 111.8 2.1 +CD-NE-CZ ARG 123.6 1.4 +NE-CZ-NH1 ARG 120.3 0.5 +NE-CZ-NH2 ARG 120.3 0.5 +NH1-CZ-NH2 ARG 119.4 1.1 +N-CA-C ARG 111.0 2.7 +CA-C-O ARG 120.1 2.1 +N-CA-CB ASN 110.6 1.8 +CB-CA-C ASN 110.4 2.0 +CA-CB-CG ASN 113.4 2.2 +CB-CG-ND2 ASN 116.7 2.4 +CB-CG-OD1 ASN 121.6 2.0 +ND2-CG-OD1 ASN 121.9 2.3 +N-CA-C ASN 111.0 2.7 +CA-C-O ASN 120.1 2.1 +N-CA-CB ASP 110.6 1.8 +CB-CA-C ASP 110.4 2.0 +CA-CB-CG ASP 113.4 2.2 +CB-CG-OD1 ASP 118.3 0.9 +CB-CG-OD2 ASP 118.3 0.9 +OD1-CG-OD2 ASP 123.3 1.9 +N-CA-C ASP 111.0 2.7 +CA-C-O ASP 120.1 2.1 +N-CA-CB CYS 110.8 1.5 +CB-CA-C CYS 111.5 1.2 +CA-CB-SG CYS 114.2 1.1 +N-CA-C CYS 111.0 2.7 +CA-C-O CYS 120.1 2.1 +N-CA-CB GLU 110.6 1.8 +CB-CA-C GLU 110.4 2.0 +CA-CB-CG GLU 113.4 2.2 +CB-CG-CD GLU 114.2 2.7 +CG-CD-OE1 GLU 118.3 2.0 +CG-CD-OE2 GLU 118.3 2.0 +OE1-CD-OE2 GLU 123.3 1.2 +N-CA-C GLU 111.0 2.7 +CA-C-O GLU 120.1 2.1 +N-CA-CB GLN 110.6 1.8 +CB-CA-C GLN 110.4 2.0 +CA-CB-CG GLN 113.4 2.2 +CB-CG-CD GLN 111.6 2.6 +CG-CD-OE1 GLN 121.6 2.0 +CG-CD-NE2 GLN 116.7 2.4 +OE1-CD-NE2 GLN 121.9 2.3 +N-CA-C GLN 111.0 2.7 +CA-C-O GLN 120.1 2.1 +N-CA-C GLY 113.1 2.5 +CA-C-O GLY 120.6 1.8 +N-CA-CB HIS 110.6 1.8 +CB-CA-C HIS 110.4 2.0 +CA-CB-CG HIS 113.6 1.7 +CB-CG-ND1 HIS 123.2 2.5 +CB-CG-CD2 HIS 130.8 3.1 +CG-ND1-CE1 HIS 108.2 1.4 +ND1-CE1-NE2 HIS 109.9 2.2 +CE1-NE2-CD2 HIS 106.6 2.5 +NE2-CD2-CG HIS 109.2 1.9 +CD2-CG-ND1 HIS 106.0 1.4 +N-CA-C HIS 111.0 2.7 +CA-C-O HIS 120.1 2.1 +N-CA-CB ILE 110.8 2.3 +CB-CA-C ILE 111.6 2.0 +CA-CB-CG1 ILE 111.0 1.9 +CB-CG1-CD1 ILE 113.9 2.8 +CA-CB-CG2 ILE 110.9 2.0 +CG1-CB-CG2 ILE 111.4 2.2 +N-CA-C ILE 111.0 2.7 +CA-C-O ILE 120.1 2.1 +N-CA-CB LEU 110.4 2.0 +CB-CA-C LEU 110.2 1.9 +CA-CB-CG LEU 115.3 2.3 +CB-CG-CD1 LEU 111.0 1.7 +CB-CG-CD2 LEU 111.0 1.7 +CD1-CG-CD2 LEU 110.5 3.0 +N-CA-C LEU 111.0 2.7 +CA-C-O LEU 120.1 2.1 +N-CA-CB LYS 110.6 1.8 +CB-CA-C LYS 110.4 2.0 +CA-CB-CG LYS 113.4 2.2 +CB-CG-CD LYS 111.6 2.6 +CG-CD-CE LYS 111.9 3.0 +CD-CE-NZ LYS 111.7 2.3 +N-CA-C LYS 111.0 2.7 +CA-C-O LYS 120.1 2.1 +N-CA-CB MET 110.6 1.8 +CB-CA-C MET 110.4 2.0 +CA-CB-CG MET 113.3 1.7 +CB-CG-SD MET 112.4 3.0 +CG-SD-CE MET 100.2 1.6 +N-CA-C MET 111.0 2.7 +CA-C-O MET 120.1 2.1 +N-CA-CB PHE 110.6 1.8 +CB-CA-C PHE 110.4 2.0 +CA-CB-CG PHE 113.9 2.4 +CB-CG-CD1 PHE 120.8 0.7 +CB-CG-CD2 PHE 120.8 0.7 +CD1-CG-CD2 PHE 118.3 1.3 +CG-CD1-CE1 PHE 120.8 1.1 +CG-CD2-CE2 PHE 120.8 1.1 +CD1-CE1-CZ PHE 120.1 1.2 +CD2-CE2-CZ PHE 120.1 1.2 +CE1-CZ-CE2 PHE 120.0 1.8 +N-CA-C PHE 111.0 2.7 +CA-C-O PHE 120.1 2.1 +N-CA-CB PRO 103.3 1.2 +CB-CA-C PRO 111.7 2.1 +CA-CB-CG PRO 104.8 1.9 +CB-CG-CD PRO 106.5 3.9 +CG-CD-N PRO 103.2 1.5 +CA-N-CD PRO 111.7 1.4 +N-CA-C PRO 112.1 2.6 +CA-C-O PRO 120.2 2.4 +N-CA-CB SER 110.5 1.5 +CB-CA-C SER 110.1 1.9 +CA-CB-OG SER 111.2 2.7 +N-CA-C SER 111.0 2.7 +CA-C-O SER 120.1 2.1 +N-CA-CB THR 110.3 1.9 +CB-CA-C THR 111.6 2.7 +CA-CB-OG1 THR 109.0 2.1 +CA-CB-CG2 THR 112.4 1.4 +OG1-CB-CG2 THR 110.0 2.3 +N-CA-C THR 111.0 2.7 +CA-C-O THR 120.1 2.1 +N-CA-CB TRP 110.6 1.8 +CB-CA-C TRP 110.4 2.0 +CA-CB-CG TRP 113.7 1.9 +CB-CG-CD1 TRP 127.0 1.3 +CB-CG-CD2 TRP 126.6 1.3 +CD1-CG-CD2 TRP 106.3 0.8 +CG-CD1-NE1 TRP 110.1 1.0 +CD1-NE1-CE2 TRP 109.0 0.9 +NE1-CE2-CD2 TRP 107.3 1.0 +CE2-CD2-CG TRP 107.3 0.8 +CG-CD2-CE3 TRP 133.9 0.9 +NE1-CE2-CZ2 TRP 130.4 1.1 +CE3-CD2-CE2 TRP 118.7 1.2 +CD2-CE2-CZ2 TRP 122.3 1.2 +CE2-CZ2-CH2 TRP 117.4 1.0 +CZ2-CH2-CZ3 TRP 121.6 1.2 +CH2-CZ3-CE3 TRP 121.2 1.1 +CZ3-CE3-CD2 TRP 118.8 1.3 +N-CA-C TRP 111.0 2.7 +CA-C-O TRP 120.1 2.1 +N-CA-CB TYR 110.6 1.8 +CB-CA-C TYR 110.4 2.0 +CA-CB-CG TYR 113.4 1.9 +CB-CG-CD1 TYR 121.0 0.6 +CB-CG-CD2 TYR 121.0 0.6 +CD1-CG-CD2 TYR 117.9 1.1 +CG-CD1-CE1 TYR 121.3 0.8 +CG-CD2-CE2 TYR 121.3 0.8 +CD1-CE1-CZ TYR 119.8 0.9 +CD2-CE2-CZ TYR 119.8 0.9 +CE1-CZ-CE2 TYR 119.8 1.6 +CE1-CZ-OH TYR 120.1 2.7 +CE2-CZ-OH TYR 120.1 2.7 +N-CA-C TYR 111.0 2.7 +CA-C-O TYR 120.1 2.1 +N-CA-CB VAL 111.5 2.2 +CB-CA-C VAL 111.4 1.9 +CA-CB-CG1 VAL 110.9 1.5 +CA-CB-CG2 VAL 110.9 1.5 +CG1-CB-CG2 VAL 110.9 1.6 +N-CA-C VAL 111.0 2.7 +CA-C-O VAL 120.1 2.1 +- + +Non-bonded distance Minimum Dist Tolerance +C-C 3.4 1.5 +C-N 3.25 1.5 +C-S 3.5 1.5 +C-O 3.22 1.5 +N-N 3.1 1.5 +N-S 3.35 1.5 +N-O 3.07 1.5 +O-S 3.32 1.5 +O-O 3.04 1.5 +S-S 2.03 1.0 +- diff --git a/modules/mol/alg/src/stereo_chemical_props.txt b/modules/mol/alg/src/stereo_chemical_props.txt new file mode 100644 index 0000000000000000000000000000000000000000..f17af3cf31baf8789c648fb1d5f1eff1d882a46d --- /dev/null +++ b/modules/mol/alg/src/stereo_chemical_props.txt @@ -0,0 +1,367 @@ +# This file contains stereochemical parameters used to evaluate the quality of models. +# Bond distances and Angles come from Engh,Huber (1991). Non bonded distances come from + +Bond Residue Mean StdDev +N-CA ALA 1.458 0.019 +CA-C ALA 1.525 0.021 +C-O ALA 1.231 0.02 +CA-CB ALA 1.521 0.033 +N-CA CYS 1.458 0.019 +CA-C CYS 1.525 0.021 +C-O CYS 1.231 0.02 +CA-CB CYS 1.53 0.02 +CB-SG CYS 1.808 0.033 +N-CA ASP 1.458 0.019 +CA-C ASP 1.525 0.021 +C-O ASP 1.231 0.02 +CA-CB ASP 1.53 0.02 +CB-CG ASP 1.516 0.025 +CG-OD1 ASP 1.249 0.019 +CG-OD2 ASP 1.249 0.019 +N-CA GLU 1.458 0.019 +CA-C GLU 1.525 0.021 +C-O GLU 1.231 0.02 +CA-CB GLU 1.53 0.02 +CB-CG GLU 1.52 0.03 +CG-CD GLU 1.516 0.025 +CD-OE1 GLU 1.249 0.019 +CD-OE2 GLU 1.249 0.019 +N-CA PHE 1.458 0.019 +CA-C PHE 1.525 0.021 +C-O PHE 1.231 0.02 +CA-CB PHE 1.53 0.02 +CB-CG PHE 1.502 0.023 +CG-CD1 PHE 1.384 0.021 +CG-CD2 PHE 1.384 0.021 +CD1-CE1 PHE 1.382 0.03 +CD2-CE2 PHE 1.382 0.03 +CE1-CZ PHE 1.382 0.03 +CE2-CZ PHE 1.382 0.03 +N-CA GLY 1.451 0.016 +CA-C GLY 1.516 0.018 +C-O GLY 1.231 0.02 +N-CA HIS 1.458 0.019 +CA-C HIS 1.525 0.021 +C-O HIS 1.231 0.02 +CA-CB HIS 1.53 0.02 +CB-CG HIS 1.497 0.014 +CG-ND1 HIS 1.378 0.011 +CG-CD2 HIS 1.354 0.011 +ND1-CE1 HIS 1.321 0.01 +CD2-NE2 HIS 1.374 0.011 +CE1-NE2 HIS 1.321 0.01 +N-CA ILE 1.458 0.019 +CA-C ILE 1.525 0.021 +C-O ILE 1.231 0.02 +CA-CB ILE 1.54 0.027 +CB-CG1 ILE 1.53 0.02 +CB-CG2 ILE 1.521 0.033 +CG1-CD1 ILE 1.513 0.039 +N-CA LYS 1.458 0.019 +CA-C LYS 1.525 0.021 +C-O LYS 1.231 0.02 +CA-CB LYS 1.53 0.02 +CB-CG LYS 1.52 0.03 +CG-CD LYS 1.52 0.03 +CD-CE LYS 1.52 0.03 +CE-NZ LYS 1.489 0.03 +N-CA LEU 1.458 0.019 +CA-C LEU 1.525 0.021 +C-O LEU 1.231 0.02 +CA-CB LEU 1.53 0.02 +CB-CG LEU 1.53 0.02 +CG-CD1 LEU 1.521 0.033 +CG-CD2 LEU 1.521 0.033 +N-CA MET 1.458 0.019 +CA-C MET 1.525 0.021 +C-O MET 1.231 0.02 +CA-CB MET 1.53 0.02 +CB-CG MET 1.52 0.03 +CG-SD MET 1.803 0.034 +SD-CE MET 1.791 0.059 +N-CA ASN 1.458 0.019 +CA-C ASN 1.525 0.021 +C-O ASN 1.231 0.02 +CA-CB ASN 1.53 0.02 +CB-CG ASN 1.516 0.025 +CG-OD1 ASN 1.231 0.02 +CG-ND2 ASN 1.328 0.021 +N-CA PRO 1.466 0.015 +CA-C PRO 1.525 0.021 +C-O PRO 1.231 0.02 +CA-CB PRO 1.53 0.02 +CB-CG PRO 1.492 0.05 +CG-CD PRO 1.503 0.034 +CD-N PRO 1.473 0.014 +N-CA GLN 1.458 0.019 +CA-C GLN 1.525 0.021 +C-O GLN 1.231 0.02 +CA-CB GLN 1.53 0.02 +CB-CG GLN 1.52 0.03 +CG-CD GLN 1.516 0.025 +CD-OE1 GLN 1.231 0.02 +CD-NE2 GLN 1.328 0.021 +N-CA ARG 1.458 0.019 +CA-C ARG 1.525 0.021 +C-O ARG 1.231 0.02 +CA-CB ARG 1.53 0.02 +CB-CG ARG 1.52 0.03 +CG-CD ARG 1.52 0.03 +CD-NE ARG 1.46 0.018 +NE-CZ ARG 1.329 0.014 +CZ-NH1 ARG 1.326 0.018 +CZ-NH2 ARG 1.326 0.018 +N-CA SER 1.458 0.019 +CA-C SER 1.525 0.021 +C-O SER 1.231 0.02 +CA-CB SER 1.53 0.02 +CB-OG SER 1.417 0.02 +N-CA THR 1.458 0.019 +CA-C THR 1.525 0.021 +C-O THR 1.231 0.02 +CA-CB THR 1.54 0.027 +CB-OG1 THR 1.433 0.016 +CB-CG2 THR 1.521 0.033 +N-CA VAL 1.458 0.019 +CA-C VAL 1.525 0.021 +C-O VAL 1.231 0.02 +CA-CB VAL 1.54 0.027 +CB-CG1 VAL 1.521 0.033 +CB-CG2 VAL 1.521 0.033 +N-CA TRP 1.458 0.019 +CA-C TRP 1.525 0.021 +C-O TRP 1.231 0.02 +CA-CB TRP 1.53 0.02 +CB-CG TRP 1.498 0.031 +CG-CD1 TRP 1.365 0.025 +CG-CD2 TRP 1.433 0.018 +CD1-NE1 TRP 1.374 0.021 +NE1-CE2 TRP 1.37 0.011 +CD2-CE2 TRP 1.409 0.017 +CD2-CE3 TRP 1.398 0.016 +CE2-CZ2 TRP 1.394 0.021 +CE3-CZ3 TRP 1.382 0.03 +CZ2-CH2 TRP 1.368 0.019 +CZ3-CH2 TRP 1.4 0.025 +N-CA TYR 1.458 0.019 +CA-C TYR 1.525 0.021 +C-O TYR 1.231 0.02 +CA-CB TYR 1.53 0.02 +CB-CG TYR 1.512 0.022 +CG-CD1 TYR 1.389 0.021 +CG-CD2 TYR 1.389 0.021 +CD1-CE1 TYR 1.382 0.03 +CD2-CE2 TYR 1.382 0.03 +CE1-CZ TYR 1.378 0.024 +CE2-CZ TYR 1.378 0.024 +CZ-OH TYR 1.376 0.021 +- + +Angle Residue Mean StdDev +N-CA-C ALA 111.2 2.8 +CA-C-O ALA 120.8 1.7 +N-CA-CB ALA 110.4 1.5 +C-CA-CB ALA 110.5 1.5 +N-CA-C CYS 111.2 2.8 +CA-C-O CYS 120.8 1.7 +N-CA-CB CYS 110.5 1.7 +C-CA-CB CYS 110.1 1.9 +N-CA-C ASP 111.2 2.8 +CA-C-O ASP 120.8 1.7 +N-CA-CB ASP 110.5 1.7 +C-CA-CB ASP 110.1 1.9 +CA-CB-CG ASP 112.6 1.0 +CB-CG-OD2 ASP 118.4 2.3 +CB-CG-OD1 ASP 118.4 2.3 +OD2-CG-OD1 ASP 122.9 2.4 +N-CA-C GLU 111.2 2.8 +CA-C-O GLU 120.8 1.7 +N-CA-CB GLU 110.5 1.7 +C-CA-CB GLU 110.1 1.9 +CA-CB-CG GLU 114.1 2.0 +CB-CG-CD GLU 112.6 1.7 +CG-CD-OE2 GLU 118.4 2.3 +CG-CD-OE1 GLU 118.4 2.3 +OE2-CD-OE1 GLU 122.9 2.4 +N-CA-C PHE 111.2 2.8 +CA-C-O PHE 120.8 1.7 +N-CA-CB PHE 110.5 1.7 +C-CA-CB PHE 110.1 1.9 +CA-CB-CG PHE 113.8 1.0 +CB-CG-CD1 PHE 120.7 1.7 +CB-CG-CD2 PHE 120.7 1.7 +CG-CD1-CE1 PHE 120.7 1.7 +CG-CD2-CE2 PHE 120.7 1.7 +CD1-CE1-CZ PHE 120.0 1.8 +CD2-CE2-CZ PHE 120.0 1.8 +CE1-CZ-CE2 PHE 120.0 1.8 +CD1-CG-CD2 PHE 118.6 1.5 +N-CA-C GLY 112.5 2.9 +CA-C-O GLY 120.8 2.1 +N-CA-C HIS 111.2 2.8 +CA-C-O HIS 120.8 1.7 +N-CA-CB HIS 110.5 1.7 +C-CA-CB HIS 110.1 1.9 +CA-CB-CG HIS 113.8 1.0 +CB-CG-ND1 HIS 122.7 1.5 +CG-ND1-CE1 HIS 109.3 1.7 +ND1-CE1-NE2 HIS 108.4 1.0 +CE1-NE2-CD2 HIS 109.0 1.0 +NE2-CD2-CG HIS 107.2 1.0 +CD2-CG-ND1 HIS 106.1 1.0 +CB-CG-CD2 HIS 131.2 1.3 +N-CA-C ILE 111.2 2.8 +CA-C-O ILE 120.8 1.7 +N-CA-CB ILE 111.5 1.7 +C-CA-CB ILE 109.1 2.2 +CA-CB-CG2 ILE 110.5 1.7 +CA-CB-CG1 ILE 110.4 1.7 +CG2-CB-CG1 ILE 110.7 3.0 +CB-CG1-CD1 ILE 113.8 2.1 +N-CA-C LYS 111.2 2.8 +CA-C-O LYS 120.8 1.7 +N-CA-CB LYS 110.5 1.7 +C-CA-CB LYS 110.1 1.9 +CA-CB-CG LYS 114.1 2.0 +CB-CG-CD LYS 111.3 2.3 +CG-CD-CE LYS 111.3 2.3 +CD-CE-NZ LYS 111.9 3.2 +N-CA-C LEU 111.2 2.8 +CA-C-O LEU 120.8 1.7 +N-CA-CB LEU 110.5 1.7 +C-CA-CB LEU 110.1 1.9 +CA-CB-CG LEU 116.3 3.5 +CB-CG-CD1 LEU 110.7 3.0 +CB-CG-CD2 LEU 110.7 3.0 +CD1-CG-CD2 LEU 110.8 2.2 +N-CA-C MET 111.2 2.8 +CA-C-O MET 120.8 1.7 +N-CA-CB MET 110.5 1.7 +C-CA-CB MET 110.1 1.9 +CA-CB-CG MET 114.1 2.0 +CB-CG-SD MET 112.7 3.0 +CG-SD-CE MET 100.9 2.2 +N-CA-C ASN 111.2 2.8 +CA-C-O ASN 120.8 1.7 +N-CA-CB ASN 110.5 1.7 +C-CA-CB ASN 110.1 1.9 +CA-CB-CG ASN 112.6 1.0 +CB-CG-ND2 ASN 116.4 1.5 +CB-CG-OD1 ASN 120.8 2.0 +ND2-CG-OD1 ASN 122.6 1.0 +N-CA-C PRO 111.8 2.5 +CA-C-O PRO 120.8 1.7 +N-CA-CB PRO 103.0 1.1 +C-CA-CB PRO 110.1 1.9 +CA-CB-CG PRO 104.5 1.9 +CB-CG-CD PRO 106.1 3.2 +CG-CD-N PRO 103.2 1.5 +CD-N-CA PRO 112.0 1.4 +N-CA-C GLN 111.2 2.8 +CA-C-O GLN 120.8 1.7 +N-CA-CB GLN 110.5 1.7 +C-CA-CB GLN 110.1 1.9 +CA-CB-CG GLN 114.1 2.0 +CB-CG-CD GLN 112.6 1.7 +CG-CD-NE2 GLN 116.4 1.5 +CG-CD-OE1 GLN 120.8 2.0 +NE2-CD-OE1 GLN 122.6 1.0 +N-CA-C ARG 111.2 2.8 +CA-C-O ARG 120.8 1.7 +N-CA-CB ARG 110.5 1.7 +C-CA-CB ARG 110.1 1.9 +CA-CB-CG ARG 114.1 2.0 +CB-CG-CD ARG 111.3 2.3 +CG-CD-NE ARG 112.0 2.2 +CD-NE-CZ ARG 124.2 1.5 +NE-CZ-NH1 ARG 120.0 1.9 +NE-CZ-NH2 ARG 120.0 1.9 +NH1-CZ-NH2 ARG 119.7 1.8 +N-CA-C SER 111.2 2.8 +CA-C-O SER 120.8 1.7 +N-CA-CB SER 110.5 1.7 +C-CA-CB SER 110.1 1.9 +CA-CB-OG SER 111.1 2.0 +N-CA-C THR 111.2 2.8 +CA-C-O THR 120.8 1.7 +N-CA-CB THR 111.5 1.7 +C-CA-CB THR 109.1 2.2 +CA-CB-CG2 THR 110.5 1.7 +CA-CB-OG1 THR 109.6 1.5 +CG2-CB-OG1 THR 109.3 2.0 +N-CA-C VAL 111.2 2.8 +CA-C-O VAL 120.8 1.7 +N-CA-CB VAL 111.5 1.7 +C-CA-CB VAL 109.1 2.2 +CA-CB-CG1 VAL 110.5 1.7 +CA-CB-CG2 VAL 110.5 1.7 +CG1-CB-CG2 VAL 110.8 2.2 +N-CA-C TRP 111.2 2.8 +CA-C-O TRP 120.8 1.7 +N-CA-CB TRP 110.5 1.7 +C-CA-CB TRP 110.1 1.9 +CA-CB-CG TRP 113.6 1.9 +CB-CG-CD1 TRP 126.9 1.5 +CB-CG-CD2 TRP 126.8 1.4 +CD1-CG-CD2 TRP 106.3 1.6 +CG-CD1-NE1 TRP 110.2 1.3 +CD1-NE1-CE2 TRP 108.9 1.8 +NE1-CE2-CZ2 TRP 130.1 1.5 +NE1-CE2-CD2 TRP 107.4 1.3 +CZ2-CE2-CD2 TRP 122.4 1.0 +CE2-CZ2-CH2 TRP 117.5 1.3 +CZ2-CH2-CZ3 TRP 121.5 1.3 +CH2-CZ3-CE3 TRP 121.1 1.3 +CZ3-CE3-CD2 TRP 118.6 1.3 +CE3-CD2-CG TRP 133.9 1.0 +CE3-CD2-CE2 TRP 118.8 1.0 +CG-CD2-CE2 TRP 107.2 1.2 +N-CA-C TYR 111.2 2.8 +CA-C-O TYR 120.8 1.7 +N-CA-CB TYR 110.5 1.7 +C-CA-CB TYR 110.1 1.9 +CA-CB-CG TYR 113.9 1.8 +CB-CG-CD1 TYR 120.8 1.5 +CB-CG-CD2 TYR 120.8 1.5 +CG-CD1-CE1 TYR 121.2 1.5 +CG-CD2-CE2 TYR 121.2 1.5 +CD1-CE1-CZ TYR 119.6 1.8 +CD2-CE2-CZ TYR 119.6 1.8 +CE1-CZ-CE2 TYR 120.3 2.0 +CD1-CG-CD2 TYR 118.1 1.5 +CE1-CZ-OH TYR 119.9 3.0 +CE2-CZ-OH TYR 119.9 3.0 +- + +Non-bonded distance Minimum Dist Tolerance +C-C 2.10 0.5 +C-N 2.10 0.5 +C-S 2.45 0.5 +C-O 2.25 0.5 +N-N 2.05 0.5 +N-S 2.55 0.5 +N-O 2.10 0.5 +O-S 2.45 0.5 +O-O 2.05 0.5 +S-S 1.80 0.5 +- + + + + + + + + + + + + + + + + + + + + diff --git a/modules/mol/alg/src/structure_analysis.cc b/modules/mol/alg/src/structure_analysis.cc new file mode 100644 index 0000000000000000000000000000000000000000..50689dfca3a27c1a62ef999e5ce9a048baeeffda --- /dev/null +++ b/modules/mol/alg/src/structure_analysis.cc @@ -0,0 +1,84 @@ +//------------------------------------------------------------------------------ +// This file is part of the OpenStructure project <www.openstructure.org> +// +// Copyright (C) 2008-2011 by the OpenStructure authors +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License as published by the Free +// Software Foundation; either version 3.0 of the License, or (at your option) +// any later version. +// This library is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this library; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +//------------------------------------------------------------------------------ + +/* + * Author Niklaus Johner + */ + +#include <ost/base.hh> +#include <ost/mol/mol.hh> +#include "structure_analysis.hh" + +namespace ost { namespace mol { namespace alg { + +geom::Vec3List GetPosListFromView(const EntityView& view){ + CheckHandleValidity(view); + geom::Vec3List vl; + AtomViewList atoms=view.GetAtomList(); + vl.reserve(atoms.size()); + for (AtomViewList::const_iterator i=atoms.begin(), + e=atoms.end(); i!=e; ++i) { + vl.push_back(i->GetPos()); + } + return vl; +} +#if OST_IMG_ENABLED +std::vector<Real> CalculateAgreementWithDensityMap(const geom::Vec3List& vl, img::MapHandle& density_map){ + CheckHandleValidity(density_map); + std::vector<Real> v; + v.reserve(vl.size()); + for (geom::Vec3List::const_iterator v1=vl.begin(),e=vl.end(); v1!=e; ++v1) { + img::Point p(density_map.CoordToIndex(*v1)); + v.push_back(density_map.GetReal(p)); + } + return v; +} + +Real CalculateAverageAgreementWithDensityMap(const geom::Vec3List& vl, img::MapHandle& density_map){ + CheckHandleValidity(density_map); + std::vector<Real> v=CalculateAgreementWithDensityMap(vl, density_map); + Real sum=0.0; + for (std::vector<Real>::const_iterator i=v.begin(),e=v.end(); i!=e; ++i) { + sum=sum+*i; + } + return sum/float(vl.size()); +} + +#endif +void DLLEXPORT_OST_MOL_ALG WrapEntityInPeriodicCell(EntityHandle eh, const geom::Vec3 cell_center, const geom::Vec3 basis_vec){ + mol::XCSEditor edi=eh.EditXCS(mol::BUFFERED_EDIT); + geom::Vec3 cm,wrapped_cm,shift; + edi=eh.EditXCS(); + ResidueHandleList residues=eh.GetResidueList(); + unsigned int n_residues=eh.GetResidueCount(); + for (unsigned int i=0; i<n_residues; ++i) { + ResidueHandle r=residues[i]; + cm=r.GetCenterOfMass(); + wrapped_cm=geom::WrapVec3(cm,cell_center,basis_vec); + if (wrapped_cm==cm) continue; + AtomHandleList atoms=r.GetAtomList(); + unsigned int n_atoms=r.GetAtomCount(); + shift=wrapped_cm-cm; + for (unsigned int j=0; j<n_atoms; ++j) { + edi.SetAtomPos(atoms[j],atoms[j].GetPos()+shift); + } + } +} + +}}} //ns diff --git a/modules/mol/alg/src/structure_analysis.hh b/modules/mol/alg/src/structure_analysis.hh new file mode 100644 index 0000000000000000000000000000000000000000..45cb601f8b32ba80656d031a211f5672202f4aed --- /dev/null +++ b/modules/mol/alg/src/structure_analysis.hh @@ -0,0 +1,42 @@ +//------------------------------------------------------------------------------ +// This file is part of the OpenStructure project <www.openstructure.org> +// +// Copyright (C) 2008-2011 by the OpenStructure authors +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License as published by the Free +// Software Foundation; either version 3.0 of the License, or (at your option) +// any later version. +// This library is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this library; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +//------------------------------------------------------------------------------ + +/* + * Niklaus Johner + */ +#ifndef OST_STRUCTURE_ANALYSIS_HH +#define OST_STRUCTURE_ANALYSIS_HH + +#include <ost/mol/alg/module_config.hh> + +#include <ost/mol/entity_view.hh> +#include <ost/mol/entity_handle.hh> +#if OST_IMG_ENABLED +# include <ost/img/map.hh> +#endif + +namespace ost { namespace mol { namespace alg { + geom::Vec3List DLLEXPORT_OST_MOL_ALG GetPosListFromView(const EntityView& view); +#if OST_IMG_ENABLED + std::vector<Real> DLLEXPORT_OST_MOL_ALG CalculateAgreementWithDensityMap(const geom::Vec3List& vl, img::MapHandle& density_map); + Real DLLEXPORT_OST_MOL_ALG CalculateAverageAgreementWithDensityMap(const geom::Vec3List& vl, img::MapHandle& density_map); +#endif + void DLLEXPORT_OST_MOL_ALG WrapEntityInPeriodicCell(EntityHandle eh, const geom::Vec3 cell_center, const geom::Vec3 basis_vec); +}}}//ns +#endif diff --git a/modules/mol/alg/src/superpose_frames.cc b/modules/mol/alg/src/superpose_frames.cc index 465f776e77558f14f2027d981d9c0c339a5c1e1e..85514d6d73a51ea060af6214dd9a748ca336f684 100644 --- a/modules/mol/alg/src/superpose_frames.cc +++ b/modules/mol/alg/src/superpose_frames.cc @@ -26,6 +26,13 @@ namespace ost { namespace mol { namespace alg { +namespace { +bool less_index(const mol::AtomHandle& a1, const mol::AtomHandle& a2) +{ + return a1.GetIndex()<a2.GetIndex(); +} + +} typedef Eigen::Matrix<Real, 3, 3> EMat3; typedef Eigen::Matrix<Real, 1, 3> ECVec3; @@ -76,7 +83,7 @@ inline EMatX3 col_sub(const EMatX3& m, const ECVec3& s) } - void AddSuperposedFrame(CoordGroupHandle& superposed, EMatX3& ref_mat,EMatX3& ref_centered,ECVec3& ref_center,CoordFramePtr frame,std::vector<unsigned long>& indices) +void AddSuperposedFrame(CoordGroupHandle& superposed, EMatX3& ref_mat,EMatX3& ref_centered,ECVec3& ref_center,CoordFramePtr frame,std::vector<unsigned long>& indices) { // This function superposes and then adds a CoordFrame (frame) to a CoordGroup (superposed). // ref_mat, ref_centered and ref_center contain respectively the positions, centered positions and @@ -144,7 +151,9 @@ CoordGroupHandle SuperposeFrames(CoordGroupHandle& cg, EntityView& sel, indices.push_back(i->GetIndex()); } } - CoordGroupHandle superposed=CreateCoordGroup(cg.GetEntity().GetAtomList()); + mol::AtomHandleList alist(cg.GetEntity().GetAtomList()); + std::sort(alist.begin(), alist.end(),less_index); + CoordGroupHandle superposed=CreateCoordGroup(alist); EMatX3 ref_mat=EMatX3::Zero(indices.size(), 3); EMatX3 ref_centered=EMatX3::Zero(indices.size(), 3); ECVec3 ref_center; @@ -208,7 +217,9 @@ CoordGroupHandle SuperposeFrames(CoordGroupHandle& cg, EntityView& sel, if (int(indices.size())!=ref_view.GetAtomCount()){ throw std::runtime_error("atom counts of the two views are not equal"); } - CoordGroupHandle superposed=CreateCoordGroup(cg.GetEntity().GetAtomList()); + mol::AtomHandleList alist(cg.GetEntity().GetAtomList()); + std::sort(alist.begin(), alist.end(),less_index); + CoordGroupHandle superposed=CreateCoordGroup(alist); EMatX3 ref_mat=EMatX3::Zero(indices.size(), 3); EMatX3 ref_centered=EMatX3::Zero(indices.size(), 3); ECVec3 ref_center; diff --git a/modules/mol/alg/src/trajectory_analysis.cc b/modules/mol/alg/src/trajectory_analysis.cc index 2c1225e753ba76adacfa3ccfd8dc6a2ccce18a95..4a2671c01b981c8eed22fc8ebe9c9a86a66664e7 100644 --- a/modules/mol/alg/src/trajectory_analysis.cc +++ b/modules/mol/alg/src/trajectory_analysis.cc @@ -25,8 +25,8 @@ #include <ost/geom/vec3.hh> #include <ost/base.hh> #include <ost/geom/geom.hh> -#include <ost/mol/entity_view.hh> -#include <ost/mol/coord_group.hh> +#include <ost/mol/mol.hh> +#include <ost/mol/view_op.hh> #include "trajectory_analysis.hh" namespace ost { namespace mol { namespace alg { @@ -230,4 +230,173 @@ std::vector<Real> AnalyzeAromaticRingInteraction(const CoordGroupHandle& traj, c } return dist; } + + void AnalyzeAlphaHelixAxis(const CoordGroupHandle& traj, const EntityView& prot_seg, geom::Vec3List& directions, + geom::Vec3List& centers, unsigned int stride) + //This function calculates the best fitting cylinder to the C-alpha atoms of an EntityView and returns + //the geometric center as well as the axis of that cylinder. We take care to have the axis point towards + //the last residue of the selection, usually the direction of the alpha-helix + { + CheckHandleValidity(traj); + if (prot_seg.GetAtomCount()==0){ + throw std::runtime_error("EntityView is empty"); + } + std::vector<unsigned long> indices_ca; + geom::Line3 axis; + Real sign; + directions.reserve(ceil(traj.GetFrameCount()/float(stride))); + centers.reserve(ceil(traj.GetFrameCount()/float(stride))); + GetCaIndices(prot_seg, indices_ca); + unsigned int n_atoms=indices_ca.size(); + for (size_t i=0; i<traj.GetFrameCount(); i+=stride) { + CoordFramePtr frame=traj.GetFrame(i); + axis=frame->FitCylinder(indices_ca); + sign=geom::Dot(axis.GetDirection(),(*frame)[indices_ca[n_atoms-1]]-axis.GetOrigin()); + sign=sign/fabs(sign); + directions.push_back(sign*axis.GetDirection()); + centers.push_back(axis.GetOrigin()); + } + return; + } + + //std::vector<geom::Line3> AnalyzeBestFitLine(const CoordGroupHandle& traj, const EntityView& prot_seg, + // unsigned int stride) + void AnalyzeBestFitLine(const CoordGroupHandle& traj, const EntityView& prot_seg, geom::Vec3List& directions, + geom::Vec3List& centers, unsigned int stride) + { + CheckHandleValidity(traj); + if (prot_seg.GetAtomCount()==0){ + throw std::runtime_error("EntityView is empty"); + } + std::vector<unsigned long> indices_ca; + geom::Line3 axis; + directions.reserve(ceil(traj.GetFrameCount()/float(stride))); + centers.reserve(ceil(traj.GetFrameCount()/float(stride))); + GetIndices(prot_seg, indices_ca); + for (size_t i=0; i<traj.GetFrameCount(); i+=stride) { + CoordFramePtr frame=traj.GetFrame(i); + axis=frame->GetODRLine(indices_ca); + directions.push_back(axis.GetDirection()); + centers.push_back(axis.GetOrigin()); + } + return; + } + + void AnalyzeBestFitPlane(const CoordGroupHandle& traj, const EntityView& prot_seg, geom::Vec3List& normals, + geom::Vec3List& origins, unsigned int stride) + { + CheckHandleValidity(traj); + if (prot_seg.GetAtomCount()==0){ + throw std::runtime_error("EntityView is empty"); + } + std::vector<unsigned long> indices_ca; + geom::Plane best_plane; + normals.reserve(ceil(traj.GetFrameCount()/float(stride))); + origins.reserve(ceil(traj.GetFrameCount()/float(stride))); + GetIndices(prot_seg, indices_ca); + for (size_t i=0; i<traj.GetFrameCount(); i+=stride) { + CoordFramePtr frame=traj.GetFrame(i); + best_plane=frame->GetODRPlane(indices_ca); + normals.push_back(best_plane.GetNormal()); + origins.push_back(best_plane.GetOrigin()); + } + return; + } + + std::vector<Real> AnalyzeHelicity(const CoordGroupHandle& traj, const EntityView& prot_seg, + unsigned int stride) + { + CheckHandleValidity(traj); + if (prot_seg.GetAtomCount()==0){ + throw std::runtime_error("EntityView is empty"); + } + std::vector<unsigned long> indices_c,indices_o, indices_n, indices_ca; + std::vector<Real> helicity; + helicity.reserve(ceil(traj.GetFrameCount()/float(stride))); + GetCaCONIndices(prot_seg, indices_ca, indices_c, indices_o, indices_n); + for (size_t i=0; i<traj.GetFrameCount(); i+=stride) { + CoordFramePtr frame=traj.GetFrame(i); + helicity.push_back(frame->GetAlphaHelixContent(indices_ca,indices_c,indices_o,indices_n)); + } + return helicity; + } + + //This function constructs mean structures from a trajectory + EntityHandle CreateMeanStructure(const CoordGroupHandle& traj, const EntityView& selection, + int from, int to, unsigned int stride) + { + CheckHandleValidity(traj); + if (to==-1)to=traj.GetFrameCount(); + unsigned int n_atoms=selection.GetAtomCount(); + if (to<from) { + throw std::runtime_error("to smaller than from"); + } + unsigned int n_frames=ceil((to-from)/stride); + if (n_atoms==0){ + throw std::runtime_error("EntityView is empty"); + } + if (n_frames<=1) { + throw std::runtime_error("number of frames is too small"); + } + std::vector<unsigned long> indices; + std::vector<geom::Vec3> mean_positions; + EntityHandle eh; + eh=CreateEntityFromView(selection,1); + GetIndices(selection,indices); + mean_positions.assign(n_atoms,geom::Vec3(0.0,0.0,0.0)); + for (int i=from; i<to; i+=stride) { + CoordFramePtr frame=traj.GetFrame(i); + for (unsigned int j=0; j<n_atoms; ++j) { + mean_positions[j]+=(*frame)[indices[j]]; + } + } + mol::XCSEditor edi=eh.EditXCS(mol::BUFFERED_EDIT); + AtomHandleList atoms=eh.GetAtomList(); + for (unsigned int j=0; j<n_atoms; ++j) { + edi.SetAtomPos(atoms[j],mean_positions[j]/Real(n_frames)); + } + return eh; + } + + Real AnalyzeRMSF(const CoordGroupHandle& traj, const EntityView& selection, int from, int to, unsigned int stride) + // This function extracts the rmsf between two entity views and assigns it + // The views don't have to be from the same entity + // If you want to compare to frame i of the trajectory t, first use t.CopyFrame(i) for example: + // eh=io.LoadPDB(...),t=io.LoadCHARMMTraj(eh,...);Sele=eh.Select(...);t.CopyFrame(0);mol.alg.AnalyzeRMSD(t,Sele,Sele) + { + CheckHandleValidity(traj); + if (to==-1)to=traj.GetFrameCount(); + unsigned int n_atoms=selection.GetAtomCount(); + if (to<from) { + throw std::runtime_error("to smaller than from"); + } + unsigned int n_frames=ceil((to-from)/stride); + if (n_atoms==0){ + throw std::runtime_error("EntityView is empty"); + } + if (n_frames<=1) { + throw std::runtime_error("number of frames is too small"); + } + Real rmsf=0.0; + geom::Vec3 v; + std::vector<unsigned long> sele_indices; + std::vector<geom::Vec3> ref_pos(n_atoms,geom::Vec3(0.,0.,0.)); + GetIndices(selection, sele_indices); + for (unsigned int j=0; j<n_atoms; ++j) { + for (int i=from; i<to; i+=stride) { + CoordFramePtr frame=traj.GetFrame(i); + ref_pos[j]+=frame->GetAtomPos(sele_indices[j]); + } + ref_pos[j]/=n_frames; + } + for (int i=from; i<to; i+=stride) { + CoordFramePtr frame=traj.GetFrame(i); + for (unsigned int j=0; j<n_atoms; ++j) { + v=frame->GetAtomPos(sele_indices[j])-ref_pos[j]; + rmsf+=geom::Dot(v,v); + } + } + return pow(rmsf/float(n_atoms*n_frames),0.5); + } + }}} //ns diff --git a/modules/mol/alg/src/trajectory_analysis.hh b/modules/mol/alg/src/trajectory_analysis.hh index faa6c8ea06d657afe169ac688c8cd8e6b8148b11..f32e4a85a07538d438ca25fcfba63eb8b74b5b35 100644 --- a/modules/mol/alg/src/trajectory_analysis.hh +++ b/modules/mol/alg/src/trajectory_analysis.hh @@ -40,8 +40,14 @@ namespace ost { namespace mol { namespace alg { std::vector<Real> DLLEXPORT_OST_MOL_ALG AnalyzeDistanceBetwCenterOfMass(const CoordGroupHandle& traj, const EntityView& sele1, const EntityView& sele2,unsigned int stride=1); std::vector<Real> DLLEXPORT_OST_MOL_ALG AnalyzeDihedralAngle(const CoordGroupHandle& traj, const AtomHandle& a1, const AtomHandle& a2, const AtomHandle& a3, const AtomHandle& a4,unsigned int stride=1); std::vector<Real> DLLEXPORT_OST_MOL_ALG AnalyzeRMSD(const CoordGroupHandle& traj, const EntityView& reference_view, const EntityView& sele,unsigned int stride=1); + Real DLLEXPORT_OST_MOL_ALG AnalyzeRMSF(const CoordGroupHandle& traj, const EntityView& selection,int from=0, int to=-1, unsigned int stride=1); std::vector<Real> DLLEXPORT_OST_MOL_ALG AnalyzeMinDistance(const CoordGroupHandle& traj, const EntityView& view1, const EntityView& view2,unsigned int stride=1); std::vector<Real> DLLEXPORT_OST_MOL_ALG AnalyzeMinDistanceBetwCenterOfMassAndView(const CoordGroupHandle& traj, const EntityView& view_cm, const EntityView& view_atoms,unsigned int stride=1); std::vector<Real> DLLEXPORT_OST_MOL_ALG AnalyzeAromaticRingInteraction(const CoordGroupHandle& traj, const EntityView& view_ring1, const EntityView& view_ring2,unsigned int stride=1); + void DLLEXPORT_OST_MOL_ALG AnalyzeAlphaHelixAxis(const CoordGroupHandle& traj, const EntityView& prot_seg, geom::Vec3List& directions, geom::Vec3List& centers, unsigned int stride=1); + void DLLEXPORT_OST_MOL_ALG AnalyzeBestFitLine(const CoordGroupHandle& traj, const EntityView& prot_seg, geom::Vec3List& directions, geom::Vec3List& centers, unsigned int stride=1); + void DLLEXPORT_OST_MOL_ALG AnalyzeBestFitPlane(const CoordGroupHandle& traj, const EntityView& prot_seg, geom::Vec3List& normals, geom::Vec3List& origins, unsigned int stride=1); + EntityHandle DLLEXPORT_OST_MOL_ALG CreateMeanStructure(const CoordGroupHandle& traj, const EntityView& selection, int from=0, int to=-1, unsigned int stride=1); + std::vector<Real> DLLEXPORT_OST_MOL_ALG AnalyzeHelicity(const CoordGroupHandle& traj, const EntityView& prot_seg, unsigned int stride=1); }}}//ns #endif diff --git a/modules/mol/alg/tests/test_convenient_superpose.py b/modules/mol/alg/tests/test_convenient_superpose.py index 7e03558c06647705589200688fb313df909e5c5b..eb4331ca3e8e6b65b0201197e5755cb2e5fcab15 100644 --- a/modules/mol/alg/tests/test_convenient_superpose.py +++ b/modules/mol/alg/tests/test_convenient_superpose.py @@ -193,4 +193,5 @@ class TestConvenientSuperpose(unittest.TestCase): self.assertEqualAtomOrder(view1, view2) if __name__ == "__main__": - unittest.main() + from ost import testutils + testutils.RunTests() diff --git a/modules/mol/base/doc/editors.rst b/modules/mol/base/doc/editors.rst index 574f6b18ccef97cb4922871d3942c70674f42be0..ad4d7fb07f3d0f6a135f966a7ff82ef947e2712e 100644 --- a/modules/mol/base/doc/editors.rst +++ b/modules/mol/base/doc/editors.rst @@ -90,6 +90,17 @@ The basic functionality of editors is implemented in the EditorBase class. :param new_name: is the new name :type new_name: string + .. method:: SetChainType(chain, type) + + :param chain: Must be a valid chain + :param type: Must be a value of enum ChainType + (see :attr:`ChainHandle.type`) + + .. method:: SetChainDescription(chain, description) + + :param chain: Must be a valid chain + :param description: Description to be added + .. method:: InsertAtom(residue, atom_name, pos, element="", occupancy=1.0, b_factor=0.0, is_hetatm=False) diff --git a/modules/mol/base/doc/entity.rst b/modules/mol/base/doc/entity.rst index 1ee9e6bdae35cce7abfe51d84e0315a354bc25da..94b8a1b3b14bbb62f03c68a043cf270b1e827e9f 100644 --- a/modules/mol/base/doc/entity.rst +++ b/modules/mol/base/doc/entity.rst @@ -280,11 +280,19 @@ The Handle Classes want to save them as PDB files This property is read-only. To change the name, use an :class:`XCSEditor`. - + Also available as :meth:`GetName` :type: str + .. attribute:: type + + Describes the type of the chain. See :ref:`chaintype`. + + .. attribute:: description + + Details about the chain. Not categorised, just text. + .. attribute:: residues List of all residues of this chain. The residues are sorted from N- to @@ -389,11 +397,18 @@ The Handle Classes .. method:: GetAtomList() See :attr:`atoms` - + .. method:: GetName() See :attr:`name` + .. method:: GetType() + + See :attr:`type` + + .. method:: GetDescription() + + See :attr:`description` .. class:: ResidueHandle @@ -496,6 +511,12 @@ The Handle Classes The chemical class of a residue is used to broadly categorize residues based on their chemical properties. For example, peptides belong to the `L_PEPTIDE_LINKING` or `D_PEPTIDE_LINKING` classes. + + .. attribute:: chem_type + + The chemical type of a residue is a classification of all compounds + obtained from the PDB component dictionary. For example, ions belong to the + class `ChemType::IONS`, amino acids to `ChemType::AMINOACIDS`. .. attribute:: sec_structure @@ -544,6 +565,9 @@ The Handle Classes See :attr:`psi_torsion` + .. method:: GetChemType() + + See :attr:`chem_type` .. class:: AtomHandle @@ -1513,12 +1537,84 @@ Other Entity-Related Functions .. function:: CreateViewFromAtomList(atom_list) - Returns a view made up of the atoms in *atom_list*. All atoms are required to - be atoms of the same entity. Duplicate atoms are only added to the view once. - - :param atom_list: the atoms - :type atom_list: :class:`AtomHandleList` or :class:`AtomViewList` - :raises: :class:`IntegrityError` if atoms of different entities are - encountered + Returns a view made up of the atoms in *atom_list*. All atoms are required to + be atoms of the same entity. Duplicate atoms are only added to the view once. + + :param atom_list: the atoms + :type atom_list: :class:`AtomHandleList` or :class:`AtomViewList` + :raises: :class:`IntegrityError` if atoms of different entities are + encountered + + :returns: :class:`EntityView` + +.. function:: CreateEntityFromView(view, include_exlusive_atoms, handle=EntityHandle()) + + This function behaves exactly like :meth:`EntityHandle.Copy`, except that only + atoms, residues, chains and bonds that are present in the view will be + copied. - :returns: :class:`EntityView` \ No newline at end of file + :param view: is the view to be converted to a handle + :param include_exlusive_atoms: if true, atoms that are part of an exclusive + bond (only one bond partner is included in the view) will also be included + in the new entity handle. + :param handle: If invalid a new entity will be created. If valid, the atoms, + residues, chains, bonds and torsions will be added to handle. This is + useful to combine several entities into one. + + :returns :class:`EntityHandle` + +.. _chaintype: + +ChainType +-------------------------------------------------------------------------------- + +A ChainType fills the :attr:`ChainHandle.type` attribute. Different types are +described in the :ref:`ChainType enum <chaintype_enum>`. Functions for setting +a type belong to the :class:`EditorBase` class, getting is provided by the +:class:`ChainHandle` class, further convenience functions are described here. + +.. _chaintype_enum: + +The ChainType enum +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The ChainType enum enumerates all types defined by the PDB for the MMCif file +format. Following values are supported: + + ``CHAINTYPE_POLY``, ``CHAINTYPE_NON_POLY``, ``CHAINTYPE_WATER``, + ``CHAINTYPE_POLY_PEPTIDE_D``, ``CHAINTYPE_POLY_PEPTIDE_L``, + ``CHAINTYPE_POLY_DN``, ``CHAINTYPE_POLY_RN``, ``CHAINTYPE_POLY_SAC_D``, + ``CHAINTYPE_POLY_SAC_L``, ``CHAINTYPE_POLY_DN_RN``, + ``CHAINTYPE_UNKNOWN``, ``CHAINTYPE_N_CHAINTYPES`` + +Where ``CHAINTYPE_N_CHAINTYPES`` holds the number of different types available. + +Setter & Getter functions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +:func:`EditorBase.SetChainType`, :func:`ChainHandle.GetType` + + +ChainType functions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. function:: ChainTypeFromString(identifier) + + Create a ChainType item for a given string. + + :param identifier: String to request a type for. + :type identifier: :class:`str` + :raises: :class:`runtime_error` if **identifier** is unrecognised. + + :returns: :class:`ChainType` + +.. function:: StringFromChainType(type) + + Return the String identifier for a given **type**. + + :param type: To be translated + :type type: :class:`ChainType` + :raises: :class:`runtime_error` if **type** is unrecognised. + + :returns: :class:`str` + diff --git a/modules/mol/base/doc/mol.rst b/modules/mol/base/doc/mol.rst index 976c2c8aa1ced240e5c461fb7f46745c60d0b36a..a416911491999891f73e81cfa6de2c9ef085b944 100644 --- a/modules/mol/base/doc/mol.rst +++ b/modules/mol/base/doc/mol.rst @@ -13,4 +13,4 @@ The mol module implements data structures to work with molecular datasets. At it editors query surface - traj \ No newline at end of file + traj diff --git a/modules/mol/base/pymod/CMakeLists.txt b/modules/mol/base/pymod/CMakeLists.txt index 87369f260e9e199fbcd107304f729f616d0d45c6..3f514b2b8afba9e8f95473898b9649da2b3afcb7 100644 --- a/modules/mol/base/pymod/CMakeLists.txt +++ b/modules/mol/base/pymod/CMakeLists.txt @@ -22,4 +22,6 @@ wrap_mol.cc export_entity_property_mapper.cc ) -pymod(NAME mol CPP ${OST_BASE_PYMOD_SOURCES} PY __init__.py) +if (NOT ENABLE_STATIC) + pymod(NAME mol CPP ${OST_BASE_PYMOD_SOURCES} PY __init__.py) +endif() diff --git a/modules/mol/base/pymod/export_chain.cc b/modules/mol/base/pymod/export_chain.cc index 8a4cb355258454f90c0588cba0f17cb432da9b29..36ed2b471f3a3658a9622d3fa907dc019725326f 100644 --- a/modules/mol/base/pymod/export_chain.cc +++ b/modules/mol/base/pymod/export_chain.cc @@ -21,6 +21,7 @@ using namespace boost::python; #include <ost/mol/mol.hh> +#include <ost/mol/chain_type.hh> #include <ost/geom/export_helper/vector.hh> using namespace ost; using namespace ost::mol; @@ -38,7 +39,9 @@ namespace { typedef EntityView (ChainHandle::*QueryMethod)(const Query&, uint) const; typedef EntityView (ChainHandle::*StringMethod)(const String&, uint) const; QueryMethod select_query=&ChainHandle::Select; - StringMethod select_string=&ChainHandle::Select; + StringMethod select_string=&ChainHandle::Select; + ChainType (*ChainTypeFromStringPtr)(const String& identifier) = + &ChainTypeFromString; } void export_Chain() @@ -50,6 +53,18 @@ void export_Chain() .def(self_ns::str(self)) .add_property("valid", &ChainBase::IsValid) .def("IsValid", &ChainBase::IsValid) + .def("GetType", &ChainBase::GetType) + .def("GetDescription", &ChainBase::GetDescription) + .def("IsPolypeptide", &ChainBase::IsPolypeptide) + .def("IsPolynucleotide", &ChainBase::IsPolynucleotide) + .def("IsPolysaccharide", &ChainBase::IsPolysaccharide) + .def("IsPolymer", &ChainBase::IsPolymer) + .add_property("is_polypeptide", &ChainBase::IsPolypeptide) + .add_property("is_polynucleotide", &ChainBase::IsPolynucleotide) + .add_property("is_polysaccharide", &ChainBase::IsPolysaccharide) + .add_property("is_polymer", &ChainBase::IsPolymer) + .add_property("type", &ChainBase::GetType) + .add_property("description", &ChainBase::GetDescription) ; generic_prop_def<ChainBase>(chain_base); class_<ChainHandle, bases<ChainBase> >("ChainHandle", init<>()) @@ -78,7 +93,9 @@ void export_Chain() .def("GetAtomCount", &ChainHandle::GetAtomCount) .def("GetBondCount", &ChainHandle::GetBondCount) .add_property("residue_count", &ChainHandle::GetResidueCount) - .add_property("atom_count", &ChainHandle::GetAtomCount) + .add_property("atom_count", &ChainHandle::GetAtomCount) + .add_property("chain_type", &ChainHandle::GetType) + .add_property("description", &ChainHandle::GetDescription) .def("InSequence", &ChainHandle::InSequence) .def("Select", select_string, arg("flags")=0) .def("Select", select_query, arg("flags")=0) @@ -103,4 +120,25 @@ void export_Chain() .def(vector_indexing_suite<ChainHandleList>()) .def(geom::VectorAdditions<ChainHandleList>()) ; + + { + enum_<ChainType>("ChainType") + .value("CHAINTYPE_POLY", CHAINTYPE_POLY) + .value("CHAINTYPE_NON_POLY", CHAINTYPE_NON_POLY) + .value("CHAINTYPE_WATER", CHAINTYPE_WATER) + .value("CHAINTYPE_POLY_PEPTIDE_D", CHAINTYPE_POLY_PEPTIDE_D) + .value("CHAINTYPE_POLY_PEPTIDE_L", CHAINTYPE_POLY_PEPTIDE_L) + .value("CHAINTYPE_POLY_DN", CHAINTYPE_POLY_DN) + .value("CHAINTYPE_POLY_RN", CHAINTYPE_POLY_RN) + .value("CHAINTYPE_POLY_SAC_D", CHAINTYPE_POLY_SAC_D) + .value("CHAINTYPE_POLY_SAC_L", CHAINTYPE_POLY_SAC_L) + .value("CHAINTYPE_POLY_DN_RN", CHAINTYPE_POLY_DN_RN) + .value("CHAINTYPE_UNKNOWN", CHAINTYPE_UNKNOWN) + .value("CHAINTYPE_N_CHAINTYPES", CHAINTYPE_N_CHAINTYPES) + .export_values() + ; + } + + def("ChainTypeFromString", ChainTypeFromStringPtr); + def("StringFromChainType", &StringFromChainType); } diff --git a/modules/mol/base/pymod/export_coord_frame.cc b/modules/mol/base/pymod/export_coord_frame.cc index fdb41fce60b8032ecb6f527256b4b9c90d7cc5e1..1f417064dd8cb2df0ee01956b1f0d0352c6c281f 100644 --- a/modules/mol/base/pymod/export_coord_frame.cc +++ b/modules/mol/base/pymod/export_coord_frame.cc @@ -26,26 +26,42 @@ using namespace boost::python; using namespace ost; using namespace ost::mol; +geom::Vec3 (CoordFrame::*GetCellSize)() = &CoordFrame::GetCellSize; +geom::Vec3 (CoordFrame::*GetCellAngles)() = &CoordFrame::GetCellAngles; geom::Vec3 (CoordFrame::*get_atom_pos)(const AtomHandle& atom) = &CoordFrame::GetAtomPos; Real (CoordFrame::*get_dist_atom)(const AtomHandle& a1, const AtomHandle& a2) = &CoordFrame::GetDistanceBetwAtoms; Real (CoordFrame::*get_angle)(const AtomHandle& a1, const AtomHandle& a2, const AtomHandle& a3) = &CoordFrame::GetAngle; Real (CoordFrame::*get_dihedral)(const AtomHandle& a1, const AtomHandle& a2, const AtomHandle& a3, const AtomHandle& a4) = &CoordFrame::GetDihedralAngle; geom::Vec3 (CoordFrame::*get_cm)(const mol::EntityView& sele) = &CoordFrame::GetCenterOfMassPos; Real (CoordFrame::*get_dist_cm)(const mol::EntityView& sele1, const mol::EntityView& sele2) = &CoordFrame::GetDistanceBetwCenterOfMass; +Real (CoordFrame::*get_min_dist_cm_v)(const mol::EntityView& sele1, const mol::EntityView& sele2) = &CoordFrame::GetMinDistBetwCenterOfMassAndView; Real (CoordFrame::*get_rmsd)(const mol::EntityView& Reference_View, const mol::EntityView& sele_View) = &CoordFrame::GetRMSD; Real (CoordFrame::*get_min_dist)(const mol::EntityView& view1, const mol::EntityView& view2) = &CoordFrame::GetMinDistance; +Real (CoordFrame::*get_alpha)(const mol::EntityView& segment) = &CoordFrame::GetAlphaHelixContent; +geom::Line3 (CoordFrame::*get_odr_line)(const mol::EntityView& view1) = &CoordFrame::GetODRLine; +geom::Line3 (CoordFrame::*get_odr_line2)() = &geom::Vec3List::GetODRLine; +geom::Plane (CoordFrame::*get_odr_plane)(const mol::EntityView& view1) = &CoordFrame::GetODRPlane; +geom::Line3 (CoordFrame::*fit_cylinder)(const mol::EntityView& view1) = &CoordFrame::FitCylinder; void export_CoordFrame() { class_<CoordFrame>("CoordFrame",no_init) + .def("GetCellSize",GetCellSize) + .def("GetCellAngles",GetCellAngles) .def("GetAtomPos", get_atom_pos) .def("GetDistanceBetwAtoms", get_dist_atom) .def("GetAngle", get_angle) .def("GetDihedralAngle", get_dihedral) .def("GetCenterOfMassPos", get_cm) .def("GetDistanceBetwCenterOfMass", get_dist_cm) + .def("GetMinDistBetwCenterOfMassAndView", get_min_dist_cm_v) .def("GetRMSD",get_rmsd) .def("GetMinDistance",get_min_dist) + .def("GetODRPlane",get_odr_plane) + .def("GetODRLine",get_odr_line) + .def("GetODRLine",get_odr_line2) + .def("GetAlphaHelixContent",get_alpha) + .def("FitCylinder",fit_cylinder) ; def("CreateCoordFrame",CreateCoordFrame); } diff --git a/modules/mol/base/pymod/export_coord_group.cc b/modules/mol/base/pymod/export_coord_group.cc index 794db5363c6ae050262e51c29608977ef83d569a..6bdeb1d6958f797898aea3a2915a3063daf10dea 100644 --- a/modules/mol/base/pymod/export_coord_group.cc +++ b/modules/mol/base/pymod/export_coord_group.cc @@ -38,6 +38,8 @@ namespace { void (CoordGroupHandle::*capture1)()=&CoordGroupHandle::Capture; void (CoordGroupHandle::*capture2)(uint)=&CoordGroupHandle::Capture; + void (CoordGroupHandle::*add_frame1)(const geom::Vec3List&)=&CoordGroupHandle::AddFrame; + void (CoordGroupHandle::*add_frame2)(const geom::Vec3List&,const geom::Vec3&,const geom::Vec3&)=&CoordGroupHandle::AddFrame; } void export_CoordGroup() @@ -46,8 +48,12 @@ void export_CoordGroup() .def("IsValid",&CoordGroupHandle::IsValid) .def("GetEntity",&CoordGroupHandle::GetEntity) .def("GetAtomCount",&CoordGroupHandle::GetAtomCount) + .def("GetFrame",&CoordGroupHandle::GetFrame2) .def("AddFrames", &CoordGroupHandle::AddFrames) + .def("AddFrame", add_frame1) + .def("AddFrame", add_frame2) .def("GetFrameCount",&CoordGroupHandle::GetFrameCount) + .def("GetFramePositions",&CoordGroupHandle::GetFramePositions) .def("SetFramePositions",&CoordGroupHandle::SetFramePositions) .def("SetAtomPos",&CoordGroupHandle::SetAtomPos) .def("GetAtomPos",&CoordGroupHandle::GetAtomPos) @@ -61,7 +67,7 @@ void export_CoordGroup() .def("GetAtomList",&CoordGroupHandle::GetAtomList) .def("__getitem__",cg_getitem) .def("__setitem__",cg_setitem) - .def("Filter", &CoordGroupHandle::Filter) + .def("Filter", &CoordGroupHandle::Filter, (arg("selected"),arg("first")=0,arg("last")=-1)) ; def("CreateCoordGroup",CreateCoordGroup); diff --git a/modules/mol/base/pymod/export_editors.cc b/modules/mol/base/pymod/export_editors.cc index 34d3a7fe8960cba5019702873fca197995f22eb0..6cee09765c2ce84e7a07bbddf4d05abebdd84cf6 100644 --- a/modules/mol/base/pymod/export_editors.cc +++ b/modules/mol/base/pymod/export_editors.cc @@ -48,15 +48,15 @@ ResidueHandle (EditorBase::*append_a)(ChainHandle ch, ResidueHandle (EditorBase::*append_b)(ChainHandle ch, const ResidueKey&, const ResNum&)=&EditorBase::AppendResidue; -void (ICSEditor::*set_torsion_a)(TorsionHandle, Real)=&ICSEditor::SetTorsionAngle; +void (ICSEditor::*set_torsion_a)(TorsionHandle, Real, bool)=&ICSEditor::SetTorsionAngle; void (ICSEditor::*set_torsion_b)(const AtomHandle&, const AtomHandle&, const AtomHandle&, const AtomHandle&, - Real)=&ICSEditor::SetTorsionAngle; + Real, bool)=&ICSEditor::SetTorsionAngle; -void (ICSEditor::*rotate_torsion_a)(TorsionHandle, Real)=&ICSEditor::RotateTorsionAngle; +void (ICSEditor::*rotate_torsion_a)(TorsionHandle, Real, bool)=&ICSEditor::RotateTorsionAngle; void (ICSEditor::*rotate_torsion_b)(const AtomHandle&, const AtomHandle&, const AtomHandle&, const AtomHandle&, - Real)=&ICSEditor::RotateTorsionAngle; + Real, bool)=&ICSEditor::RotateTorsionAngle; #if OST_NUMPY_SUPPORT_ENABLED template<typename T, bool O> @@ -212,11 +212,15 @@ void export_Editors() .def("Connect", connect_c) .def("Connect", connect_d) .def("RenameChain", &EditorBase::RenameChain) + .def("SetChainType", &EditorBase::SetChainType) + .def("SetChainDescription", &EditorBase::SetChainDescription) .def("RenameResidue", &EditorBase::RenameResidue) + .def("SetResidueNumber", &EditorBase::SetResidueNumber) .def("RenameAtom", &EditorBase::RenameAtom) .def("AddTorsion", &EditorBase::AddTorsion) .def("ReorderResidues",&EditorBase::ReorderResidues) .def("ReorderAllResidues",&EditorBase::ReorderAllResidues) + .def("RenumberAllResidues",&EditorBase::RenumberAllResidues) ; class_<XCSEditor, bases<EditorBase> >("XCSEditor", no_init) @@ -232,10 +236,16 @@ void export_Editors() class_<ICSEditor, bases<EditorBase> >("ICSEditor", no_init) .def("SetAngle", &ICSEditor::SetAngle) .def("SetBondLength", &ICSEditor::SetBondLength) - .def("SetTorsionAngle", set_torsion_a) - .def("SetTorsionAngle", set_torsion_b) - .def("RotateTorsionAngle", rotate_torsion_a) - .def("RotateTorsionAngle", rotate_torsion_b) + .def("SetTorsionAngle", set_torsion_a, + (arg("torsion"),arg("angle"), arg("update_others")=true)) + .def("SetTorsionAngle", set_torsion_b, + (arg("atom_a"), arg("atom_b"), arg("atom_c"), arg("atom_d"), + arg("angle"), arg("update_others"))) + .def("RotateTorsionAngle", rotate_torsion_a, + (arg("torsion"),arg("angle"), arg("update_others")=true)) + .def("RotateTorsionAngle", rotate_torsion_b, + (arg("atom_a"), arg("atom_b"), arg("atom_c"), arg("atom_d"), + arg("angle"), arg("update_others"))) .def("UpdateXCS", &ICSEditor::UpdateXCS) .def("__exit__", &ICSEditor::UpdateXCS) ; diff --git a/modules/mol/base/pymod/export_entity.cc b/modules/mol/base/pymod/export_entity.cc index c46f07284aab3eec978e25d4d87c265d39133939..6fda49c793342259e0d3ab5078716d3dda8c0a5e 100644 --- a/modules/mol/base/pymod/export_entity.cc +++ b/modules/mol/base/pymod/export_entity.cc @@ -147,6 +147,7 @@ void export_Entity() .def("GetMass", &EntityHandle::GetMass) .def("GetCenterOfMass", &EntityHandle::GetCenterOfMass) .def("GetCenterOfAtoms", &EntityHandle::GetCenterOfAtoms) + .def("GetAtomPosList", &EntityHandle::GetAtomPosList) .def("GetGeometricCenter", geom_center<EntityHandle>) .add_property("geometric_center", geom_center<EntityHandle>) diff --git a/modules/mol/base/pymod/export_residue.cc b/modules/mol/base/pymod/export_residue.cc index 1e1b9f74a60d94c224b9aad51153a9e873b2a4a7..284c2f0bc294825e5751a3f441e377d1d1666517 100644 --- a/modules/mol/base/pymod/export_residue.cc +++ b/modules/mol/base/pymod/export_residue.cc @@ -21,6 +21,7 @@ using namespace boost::python; #include <ost/mol/chem_class.hh> +#include <ost/mol/chem_type.hh> #include <ost/mol/mol.hh> #include <ost/geom/export_helper/vector.hh> using namespace ost; @@ -64,7 +65,40 @@ namespace { void export_Residue() { + class_<ChemClass>("ChemClass", init<char>(args("chem_class"))) + .def(self!=self) + .def(self==self) + .def("IsPeptideLinking", &ChemClass::IsPeptideLinking) + .def("IsNucleotideLinking", &ChemClass::IsNucleotideLinking) + ; + implicitly_convertible<char, ChemClass>(); + object ct_class = class_<ChemType>("ChemType", init<char>(args("chem_type"))) + .def(self!=self) + .def(self==self) + .def(self_ns::str(self)) + .def("IsIon", &ChemType::IsIon) + .def("IsNucleotide", &ChemType::IsNucleotide) + .def("IsSaccharide", &ChemType::IsSaccharide) + .def("IsAminoAcid", &ChemType::IsAminoAcid) + .def("IsCoenzyme", &ChemType::IsCoenzyme) + .def("IsDrug", &ChemType::IsDrug) + .def("IsNonCanonical", &ChemType::IsNonCanonical) + .def("IsKnown", &ChemType::IsKnown) + .def("IsWater", &ChemType::IsWater) + ; + implicitly_convertible<char, ChemType>(); + ct_class.attr("IONS")=char(ChemType::IONS); + ct_class.attr("NONCANONICALMOLS")=char(ChemType::NONCANONICALMOLS); + ct_class.attr("SACCHARIDES")=char(ChemType::SACCHARIDES); + ct_class.attr("NUCLEOTIDES")=char(ChemType::NUCLEOTIDES); + ct_class.attr("AMINOACIDS")=char(ChemType::AMINOACIDS); + ct_class.attr("COENZYMES")=char(ChemType::COENZYMES); + ct_class.attr("WATERCOORDIONS")=char(ChemType::WATERCOORDIONS); + ct_class.attr("DRUGS")=char(ChemType::DRUGS); + ct_class.attr("WATERS")=char(ChemType::WATERS); + ct_class.attr("UNKNOWN")=char(ChemType::UNKNOWN); + class_<ResNum>("ResNum", init<int>(args("num"))) .def(init<int,char>(args("num", "ins_code"))) .def("GetNum", &ResNum::GetNum) @@ -79,6 +113,10 @@ void export_Residue() .def(self<=self) .def(self==self) .def(self!=self) + .def(self+=self) + .def(self-=self) + .def(self+self) + .def(self-self) .def(self+=int()) .def(self-=int()) .def(self+int()) @@ -133,7 +171,8 @@ void export_Residue() .def("SetOneLetterCode", &ResidueBase::SetOneLetterCode) .add_property("one_letter_code", &ResidueBase::GetOneLetterCode, &ResidueBase::SetOneLetterCode) - .def("GetQualifedName", &ResidueBase::GetQualifiedName) + .def("GetQualifiedName", &ResidueBase::GetQualifiedName) + .add_property("qualified_name", &ResidueBase::GetQualifiedName) .def("IsPeptideLinking", &ResidueBase::IsPeptideLinking) .add_property("peptide_linking", &ResidueBase::IsPeptideLinking) @@ -144,13 +183,15 @@ void export_Residue() .def("GetKey", &ResidueBase::GetKey, return_value_policy<copy_const_reference>()) - .def("GetName", &ResidueBase::GetName, + .def("GetName", &ResidueBase::GetName, return_value_policy<copy_const_reference>()) .def("GetNumber", &ResidueBase::GetNumber, return_value_policy<copy_const_reference>()) .def("GetChemClass", &ResidueBase::GetChemClass) + .add_property("chem_class", &ResidueBase::GetChemClass, set_chemclass) .def("SetChemClass", set_chemclass) - .add_property("chem_class",&ResidueBase::GetChemClass,set_chemclass) + .def("GetChemType", &ResidueBase::GetChemType) + .add_property("chem_type", &ResidueBase::GetChemType) .add_property("is_ligand", &ResidueBase::IsLigand, &ResidueBase::SetIsLigand) .def("IsLigand", &ResidueBase::IsLigand) .def("SetIsLigand", &ResidueBase::SetIsLigand) @@ -165,7 +206,6 @@ void export_Residue() .add_property("name", make_function(&ResidueBase::GetName, return_value_policy<copy_const_reference>())) - .add_property("qualified_name", &ResidueBase::GetQualifiedName) .def("IsValid", &ResidueBase::IsValid) .add_property("valid", &ResidueBase::IsValid) ; diff --git a/modules/mol/base/pymod/export_torsion.cc b/modules/mol/base/pymod/export_torsion.cc index e7b45e0fd4c3afb385410f688267e05406351250..fbf9e2b726880b9e56a430e3def0aa50f0c1fd7b 100644 --- a/modules/mol/base/pymod/export_torsion.cc +++ b/modules/mol/base/pymod/export_torsion.cc @@ -49,14 +49,8 @@ void export_Torsion() .add_property("third", &TorsionHandle::GetThird) .add_property("fourth", &TorsionHandle::GetFourth) .def("IsValid", &TorsionHandle::IsValid) - .def("SetAngle", &TorsionHandle::SetAngle) .def("GetAngle", &TorsionHandle::GetAngle) - .def("RotateAngle", &TorsionHandle::RotateAngle, - X_rotate_angle_overloads(args("angle", "up"))) - .add_property("angle", &TorsionHandle::GetAngle, - &TorsionHandle::SetAngle) - .def("SetAngle", &TorsionHandle::SetAngle, - X_set_angle_overloads(args("angle", "up"))) + .add_property("angle", &TorsionHandle::GetAngle) .def(self_ns::str(self)) ; diff --git a/modules/mol/base/pymod/export_visitor.cc b/modules/mol/base/pymod/export_visitor.cc index 0def51e95380ce057536b3de2395474f2cc84bb8..3a6d1e3285153e2bc71ff09f562d4e2e18b3645e 100644 --- a/modules/mol/base/pymod/export_visitor.cc +++ b/modules/mol/base/pymod/export_visitor.cc @@ -23,8 +23,6 @@ using namespace boost::python; using namespace ost; using namespace ost::mol; -namespace { - struct WrappedVisitor : EntityVisitor { WrappedVisitor(PyObject *p) @@ -63,7 +61,6 @@ struct WrappedVisitor : EntityVisitor PyObject* self; }; -} void export_Visitor() { class_<EntityVisitor, WrappedVisitor>("EntityVisitor", init<>()) diff --git a/modules/mol/base/pymod/wrap_mol.cc b/modules/mol/base/pymod/wrap_mol.cc index f29d1377f4bc0ccf14289b50df67e994208e99e5..33b09e2f20b4c1126f05cf501c04a599663048f9 100644 --- a/modules/mol/base/pymod/wrap_mol.cc +++ b/modules/mol/base/pymod/wrap_mol.cc @@ -19,7 +19,9 @@ #include <boost/python.hpp> #include <ost/mol/transform.hh> #include <ost/mol/editor_base.hh> +#if(OST_INFO_ENABLED) #include <ost/info/info.hh> +#endif using namespace boost::python; using namespace ost::mol; @@ -95,7 +97,9 @@ BOOST_PYTHON_MODULE(_ost_mol) .def("ApplyZAxisTranslation",&Transform::ApplyZAxisTranslation) .def("ApplyAxisRotation",&Transform::ApplyAxisRotation) ; +#if(OST_INFO_ENABLED) def("TransformToInfo", &TransformToInfo); def("TransformFromInfo", &TransformFromInfo); - +#endif + } diff --git a/modules/mol/base/src/CMakeLists.txt b/modules/mol/base/src/CMakeLists.txt index b11b6e54c28389f77a429affc569470c14499ae4..134eb4e25691507a50039077bdf58099b57ae9ea 100644 --- a/modules/mol/base/src/CMakeLists.txt +++ b/modules/mol/base/src/CMakeLists.txt @@ -8,6 +8,7 @@ bond_handle.cc chain_base.cc chain_handle.cc chain_view.cc +chain_type.cc coord_frame.cc coord_group.cc editor_base.cc @@ -47,7 +48,9 @@ bond_table.hh chain_base.hh chain_handle.hh chain_view.hh +chain_type.hh chem_class.hh +chem_type.hh coord_group.hh coord_source.hh in_mem_coord_source.hh @@ -97,7 +100,13 @@ foreach(_impl_src ${OST_MOL_IMPL_SOURCES}) list(APPEND OST_MOL_SOURCES impl/${_impl_src}) endforeach() +if(ENABLE_INFO) + set (INFO_DEPS ost_info) +else() + list(APPEND LINK ${Boost_REGEX_LIBRARY}) +endif() + module(NAME mol SOURCES ${OST_MOL_SOURCES} HEADERS ${OST_MOL_IMPL_HEADERS} IN_DIR impl ${OST_MOL_HEADERS} HEADER_OUTPUT_DIR ost/mol - DEPENDS_ON ost_geom ost_base ost_info) + DEPENDS_ON ost_geom ost_base ${INFO_DEPS}) diff --git a/modules/mol/base/src/atom_base.cc b/modules/mol/base/src/atom_base.cc index 642ea5aa93baad015633ab13caedbb2f7e3f704d..c818fbc1cec5ee0c0fa1be6fbb51eb59750133f0 100644 --- a/modules/mol/base/src/atom_base.cc +++ b/modules/mol/base/src/atom_base.cc @@ -69,6 +69,17 @@ geom::Vec3 AtomBase::GetAltPos(const String& alt_group) const return impl_->GetResidue()->GetAltAtomPos(Impl(), alt_group); } +Real AtomBase::GetAltBFactor(const String& alt_group) const +{ + this->CheckValidity(); + return impl_->GetResidue()->GetAltAtomBFactor(Impl(), alt_group); +} +Real AtomBase::GetAltOcc(const String& alt_group) const +{ + this->CheckValidity(); + return impl_->GetResidue()->GetAltAtomOcc(Impl(), alt_group); +} + std::vector<String> AtomBase::GetAltGroupNames() const { this->CheckValidity(); diff --git a/modules/mol/base/src/atom_base.hh b/modules/mol/base/src/atom_base.hh index 8d19514af07c9e58536cf505ee7f51f11098dd52..13795311560e4c81d46063156c75aa6459359131 100644 --- a/modules/mol/base/src/atom_base.hh +++ b/modules/mol/base/src/atom_base.hh @@ -87,6 +87,8 @@ public: const geom::Vec3& GetOriginalPos() const; /// \brief get alternative atom position geom::Vec3 GetAltPos(const String& alt_group) const; + Real GetAltBFactor(const String& alt_group) const; + Real GetAltOcc(const String& alt_group) const; std::vector<String> GetAltGroupNames() const; diff --git a/modules/mol/base/src/chain_base.cc b/modules/mol/base/src/chain_base.cc index a82f8c05b92d0028396375c087176bc4571e3cda..bbf0cfdad68397971844ba49fb5e2ba4b378d953 100644 --- a/modules/mol/base/src/chain_base.cc +++ b/modules/mol/base/src/chain_base.cc @@ -44,6 +44,14 @@ String ChainBase::GetName() const { return impl_->GetName(); } +ChainType ChainBase::GetType() const { + return impl_->GetType(); +} + +String ChainBase::GetDescription() const { + return impl_->GetDescription(); +} + void ChainBase::CheckValidity() const { if (!impl_) throw InvalidHandle(); @@ -59,5 +67,32 @@ std::ostream& operator<<(std::ostream& os, const ChainBase& chain) return os; } +bool ChainBase::IsPolymer() const +{ + this->CheckValidity(); + return impl_->IsPolymer(); + +} + +bool ChainBase::IsPolysaccharide() const +{ + this->CheckValidity(); + return impl_->IsPolysaccharide(); + +} + +bool ChainBase::IsPolypeptide() const +{ + this->CheckValidity(); + return impl_->IsPolypeptide(); + +} + +bool ChainBase::IsPolynucleotide() const +{ + this->CheckValidity(); + return impl_->IsPolynucleotide(); +} + }} // ns diff --git a/modules/mol/base/src/chain_base.hh b/modules/mol/base/src/chain_base.hh index 4a904a2a87e67e72b015deb7d643ebe8df5f8804..984c948fd94b934656f4920baf3e1da739efd89a 100644 --- a/modules/mol/base/src/chain_base.hh +++ b/modules/mol/base/src/chain_base.hh @@ -22,6 +22,7 @@ #include <ost/mol/module_config.hh> #include <ost/mol/impl/chain_impl_fw.hh> +#include <ost/mol/chain_type.hh> #include <ost/generic_property.hh> namespace ost { namespace mol { @@ -59,10 +60,35 @@ public: friend class ConstGenericPropContainer<ChainBase>; String GetName() const; + /// \brief Get the type of a chain. + /// + /// \return chain type of ChainType + ChainType GetType() const; + + /// \brief Get information about a chain. + /// + /// \return description + String GetDescription() const; + const impl::ChainImplPtr& Impl() const { return impl_; } + /// \brief whether the chain is a polymer + /// + /// True if one of IsPolysaccharide(), IsPolynucleotide(), IsPolypeptide() is + /// true or the chain is of type CHAINTYPE_POLYMER. + bool IsPolymer() const; + + /// \brief whether the chain is a polysaccharide + bool IsPolysaccharide() const; + + /// \brief whether the chain is a polypeptide + bool IsPolypeptide() const; + + /// \brief whether the chain is a polynucleotide + bool IsPolynucleotide() const; + impl::ChainImplPtr& Impl() { return impl_; } diff --git a/modules/mol/base/src/chain_handle.cc b/modules/mol/base/src/chain_handle.cc index 9ff209e3571e80fc5c653af540ce5027cabc6ff2..c1e745f2c2c4456fb765782d17caf13630d32d07 100644 --- a/modules/mol/base/src/chain_handle.cc +++ b/modules/mol/base/src/chain_handle.cc @@ -251,5 +251,11 @@ EntityView ChainHandle::Select(const String& q, QueryFlags flags) const { else return this->GetEntity().Select(Query("cname='"+Impl()->GetName()+"'"), flags); } +void ChainHandle::SetInSequence(const int index) +{ + this->CheckValidity(); + Impl()->SetInSequence(index); +} + }} diff --git a/modules/mol/base/src/chain_handle.hh b/modules/mol/base/src/chain_handle.hh index 576c4b6715a6b0a796abe6e1b78fc4bd41da11d5..8f88c6e3757473acd558c0d0b830e56f46235a29 100644 --- a/modules/mol/base/src/chain_handle.hh +++ b/modules/mol/base/src/chain_handle.hh @@ -193,7 +193,9 @@ public: bool operator==(const ChainHandle& ref) const; bool operator!=(const ChainHandle& ref) const; - + /// \brief checks whether res breaks the in sequence property + /// and updates it accordingly + void SetInSequence(const int index); }; }} // ns diff --git a/modules/mol/base/src/chain_type.cc b/modules/mol/base/src/chain_type.cc new file mode 100644 index 0000000000000000000000000000000000000000..6b3841d8909e4378db492db306efe86ece0bba44 --- /dev/null +++ b/modules/mol/base/src/chain_type.cc @@ -0,0 +1,98 @@ +//------------------------------------------------------------------------------ +// This file is part of the OpenStructure project <www.openstructure.org> +// +// Copyright (C) 2008-2011 by the OpenStructure authors +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License as published by the Free +// Software Foundation; either version 3.0 of the License, or (at your option) +// any later version. +// This library is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this library; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +//------------------------------------------------------------------------------ + +#include <stdexcept> +#include "chain_type.hh" + +namespace ost { namespace mol { + +ChainType ChainTypeFromString(StringRef identifier) +{ + + // chain types as found in the entity category of a mmcif file + if(StringRef("polymer", 7) == identifier) { + return CHAINTYPE_POLY; + }else if(StringRef("non-polymer", 11) == identifier) { + return CHAINTYPE_NON_POLY; + }else if(StringRef("water", 5) == identifier) { + return CHAINTYPE_WATER; + // chain types as found in the entity_poly category of a mmcif file + } else if(StringRef("polypeptide(D)", 14) == identifier) { + return CHAINTYPE_POLY_PEPTIDE_D; + } else if(StringRef("polypeptide(L)", 14) == identifier) { + return CHAINTYPE_POLY_PEPTIDE_L; + } else if(StringRef("polydeoxyribonucleotide", 23) == identifier) { + return CHAINTYPE_POLY_DN; + } else if(StringRef("polyribonucleotide", 18) == identifier) { + return CHAINTYPE_POLY_RN; + } else if(StringRef("polysaccharide(D)", 17) == identifier) { + return CHAINTYPE_POLY_SAC_D; + } else if(StringRef("polysaccharide(L)", 17) == identifier) { + return CHAINTYPE_POLY_SAC_L; + } else if(StringRef("polydeoxyribonucleotide/polyribonucleotide hybrid", + 49) == identifier) { + return CHAINTYPE_POLY_DN_RN; + } else if(StringRef("other", 5) == identifier) { + return CHAINTYPE_UNKNOWN; + } + + throw std::runtime_error("Unrecognised chain type descriptor found: '" + + identifier.str() +"'!"); +} + +ChainType ChainTypeFromString(const String& identifier) +{ + return ChainTypeFromString(StringRef(identifier.c_str(), + identifier.length())); +} + +String StringFromChainType(ChainType type) +{ + // chain types as found in the entity category of a mmcif file + if (CHAINTYPE_POLY == type) { + return "polymer"; + } else if (CHAINTYPE_NON_POLY == type) { + return "non-polymer"; + } else if (CHAINTYPE_WATER == type) { + return "water"; + // chain types as found in the entity_poly category of a mmcif file + } else if (CHAINTYPE_POLY_PEPTIDE_D == type) { + return "polypeptide(D)"; + } else if (CHAINTYPE_POLY_PEPTIDE_L == type) { + return "polypeptide(L)"; + } else if (CHAINTYPE_POLY_DN == type) { + return "polydeoxyribonucleotide"; + } else if (CHAINTYPE_POLY_RN == type) { + return "polyribonucleotide"; + } else if (CHAINTYPE_POLY_SAC_D == type) { + return "polysaccharide(D)"; + } else if (CHAINTYPE_POLY_SAC_L == type) { + return "polysaccharide(L)"; + } else if (CHAINTYPE_POLY_DN_RN == type) { + return "polydeoxyribonucleotide/polyribonucleotide hybrid"; + } else if (CHAINTYPE_UNKNOWN == type) { + return "other"; + } + + std::stringstream ss("Unknonw ChainType item found: '"); + ss << type << "'!"; + throw std::runtime_error(ss.str()); +} + +}} //ns diff --git a/modules/mol/base/src/chain_type.hh b/modules/mol/base/src/chain_type.hh new file mode 100644 index 0000000000000000000000000000000000000000..18a00fb457cd4f49ba261aab3f2f74c11cb91508 --- /dev/null +++ b/modules/mol/base/src/chain_type.hh @@ -0,0 +1,69 @@ +//------------------------------------------------------------------------------ +// This file is part of the OpenStructure project <www.openstructure.org> +// +// Copyright (C) 2008-2011 by the OpenStructure authors +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License as published by the Free +// Software Foundation; either version 3.0 of the License, or (at your option) +// any later version. +// This library is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this library; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +//------------------------------------------------------------------------------ +#ifndef OST_CHAIN_TYPE_HH +#define OST_CHAIN_TYPE_HH + +#include <ost/base.hh> +#include <ost/string_ref.hh> + +namespace ost { namespace mol { + +/// \enum different kinds of chains +typedef enum { + CHAINTYPE_POLY, ///< polymer + CHAINTYPE_NON_POLY, ///< non-polymer + CHAINTYPE_WATER, ///< water + CHAINTYPE_POLY_PEPTIDE_D, ///< (D) amino acid sequence + CHAINTYPE_POLY_PEPTIDE_L, ///< (L) amino acid sequence + CHAINTYPE_POLY_DN, ///< polydeoxyribonucleotide + CHAINTYPE_POLY_RN, ///< polyribonucleotide + CHAINTYPE_POLY_SAC_D, ///< polysaccharide(D) + CHAINTYPE_POLY_SAC_L, ///< polysaccharide(L) + CHAINTYPE_POLY_DN_RN, ///<polydeoxyribonucleotide/ -ribonucleotide hybrid + CHAINTYPE_UNKNOWN, ///< guess what + CHAINTYPE_N_CHAINTYPES ///< no. of chain types +} ChainType; + +/// \brief Create a ChainType item for a given string +/// +/// \param identifier StringRef to be translated +/// +/// \return The ChainType corresponding to the input, throws a +/// std::runtime_error on unknown type +ChainType ChainTypeFromString(const StringRef identifier); + +/// \brief Create a ChainType item for a given string +/// +/// \param identifier String to be translated +/// +/// \return The ChainType corresponding to the input, throws a +/// std::runtime_error on unknown type +ChainType ChainTypeFromString(const String& identifier); + +/// \brief Return the String identifier for a given type +/// +/// \param type ChainType to be translated +/// +/// \return String corresponding to the input, throws a std::runtime_error on +/// unknown type +String StringFromChainType(ChainType type); + +}} //ns + +#endif diff --git a/modules/mol/base/src/chain_view.cc b/modules/mol/base/src/chain_view.cc index b940a37ee37dd8f82c302ba4b5a51119169cb6f6..4727e31ddce6764bcdfc0e78bb5e7c3c31e0d83f 100644 --- a/modules/mol/base/src/chain_view.cc +++ b/modules/mol/base/src/chain_view.cc @@ -334,14 +334,10 @@ bool ChainView::operator!=(const ChainView& rhs) const Real ChainView::GetMass() const { this->CheckValidity(); - Real mass = 0; + double mass = 0; ResidueViewList::const_iterator i; for (i=data_->residues.begin(); i!=data_->residues.end(); ++i) { - ResidueView r=*i; - for (AtomViewList::const_iterator j=r.GetAtomList().begin(), - e2=r.GetAtomList().end(); j!=e2; ++j) { - mass+=j->GetMass(); - } + mass+=i->GetMass(); } return mass; } diff --git a/modules/mol/base/src/chem_type.hh b/modules/mol/base/src/chem_type.hh new file mode 100644 index 0000000000000000000000000000000000000000..eac806433400daeb1ead20ecf88ddff558b64fc7 --- /dev/null +++ b/modules/mol/base/src/chem_type.hh @@ -0,0 +1,104 @@ +//------------------------------------------------------------------------------ +// This file is part of the OpenStructure project <www.openstructure.org> +// +// Copyright (C) 2008-2010 by the OpenStructure authors +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License as published by the Free +// Software Foundation; either version 3.0 of the License, or (at your option) +// any later version. +// This library is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this library; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +//------------------------------------------------------------------------------ +#ifndef OST_BASE_CHEM_TYPE_HI +#define OST_BASE_CHEM_TYPE_HI +#include <vector> + +#include <boost/shared_ptr.hpp> + +#include <ost/mol/module_config.hh> + + +namespace ost { namespace mol { + +struct ChemType { + const static char IONS ='I'; + const static char NONCANONICALMOLS ='M'; + const static char SACCHARIDES ='S'; + const static char NUCLEOTIDES ='N'; + const static char AMINOACIDS ='A'; + const static char COENZYMES ='E'; + const static char WATERCOORDIONS ='C'; + const static char DRUGS ='D'; + const static char WATERS ='W'; + const static char UNKNOWN ='U'; + + explicit ChemType(char chem_type) + : chem_type_(chem_type) { + } + + ChemType() + : chem_type_(UNKNOWN) { + } + + bool operator==(const ChemType& cc) const { + return cc.chem_type_==chem_type_; + } + + bool operator!=(const ChemType& cc) const { + return this->operator!=(cc); + } + + bool IsIon() const { + return (chem_type_==ChemType::IONS || + chem_type_==ChemType::WATERCOORDIONS); + } + + bool IsNucleotide() const { + return (chem_type_==ChemType::NUCLEOTIDES); + } + + bool IsSaccharide() const { + return (chem_type_==ChemType::SACCHARIDES); + } + + bool IsAminoAcid() const { + return (chem_type_==ChemType::AMINOACIDS); + } + + bool IsCoenzyme() const { + return (chem_type_==ChemType::COENZYMES); + } + + bool IsDrug() const { + return (chem_type_==ChemType::DRUGS); + } + + bool IsWater() const { + return (chem_type_==ChemType::WATERS); + } + + bool IsNonCanonical() const { + return (chem_type_==ChemType::NONCANONICALMOLS); + } + + bool IsKnown() const { + return (chem_type_!=ChemType::UNKNOWN); + } + + operator char() const { + return chem_type_; + } + +private: + char chem_type_; +}; + +}} // ns +#endif diff --git a/modules/mol/base/src/coord_frame.cc b/modules/mol/base/src/coord_frame.cc index 80ef4f58f3ea3aed2b1ae691b6cc35c70107faf0..71b9ed9a64d4f21eeed7630e886f47c02ee96d8e 100644 --- a/modules/mol/base/src/coord_frame.cc +++ b/modules/mol/base/src/coord_frame.cc @@ -28,6 +28,7 @@ #include <ost/mol/view_op.hh> #include <ost/mol/mol.hh> #include "coord_frame.hh" +#include <ost/base.hh> namespace ost { namespace mol { @@ -84,7 +85,52 @@ namespace ost { namespace mol { indices.push_back(i->GetIndex()); } } + + void GetCaIndices(const EntityView& segment, std::vector<unsigned long>& indices_ca){ + mol::AtomView ca; + ResidueViewList residues=segment.GetResidueList(); + indices_ca.reserve(residues.size()); + //for (ResidueViewList::const_iterator res=residues.begin()+1, + // e=residues.end(); res!=e-1; ++res){ + // if (!InSequence((*res).GetHandle(),(*(res+1)).GetHandle())) throw std::runtime_error("Residues are not in a continuous sequence"); + //} + for (ResidueViewList::const_iterator res=residues.begin(), + e=residues.end(); res!=e; ++res) { + ca=res->FindAtom("CA"); + CheckHandleValidity(ca); + indices_ca.push_back(ca.GetIndex()); + } + } + void GetCaCONIndices(const EntityView& segment, std::vector<unsigned long>& indices_ca, + std::vector<unsigned long>& indices_c, std::vector<unsigned long>& indices_o, std::vector<unsigned long>& indices_n){ + mol::AtomView a,n,c,o; + ResidueViewList residues=segment.GetResidueList(); + indices_ca.reserve(residues.size()); + indices_n.reserve(residues.size()); + indices_c.reserve(residues.size()); + indices_o.reserve(residues.size()); + for (ResidueViewList::const_iterator res=residues.begin()+1, + e=residues.end(); res!=e-1; ++res){ + if (!InSequence((*res).GetHandle(),(*(res+1)).GetHandle())) throw std::runtime_error("Residues are not in a continuous sequence"); + } + for (ResidueViewList::const_iterator res=residues.begin(), + e=residues.end(); res!=e; ++res) { + a=res->FindAtom("CA"); + CheckHandleValidity(a); + indices_ca.push_back(a.GetIndex()); + c=res->FindAtom("C"); + CheckHandleValidity(c); + indices_c.push_back(c.GetIndex()); + o=res->FindAtom("O"); + CheckHandleValidity(o); + indices_o.push_back(o.GetIndex()); + n=res->FindAtom("N"); + CheckHandleValidity(n); + indices_n.push_back(n.GetIndex()); + } + } + void GetMasses(const EntityView& sele, std::vector<Real>& masses){ // This function returns a vector containing the atom masses of the atoms in an EntityView // It is used together with GetIndices to accelerate the extraction of RMSD from a trajectory @@ -218,5 +264,161 @@ namespace ost { namespace mol { GetIndicesAndMasses(view_cm,indices_cm,masses_cm); return this->GetMinDistBetwCenterOfMassAndView(indices_cm,masses_cm,indices_atoms); } + + geom::Line3 CoordFrame::GetODRLine(std::vector<unsigned long>& indices_ca){ + //Returns the best fit line to atoms with indices in indices_ca + geom::Vec3List atoms_pos_list; + atoms_pos_list.reserve(indices_ca.size()); + for (std::vector<unsigned long>::const_iterator i1=indices_ca.begin(),e=indices_ca.end(); i1!=e; ++i1) { + atoms_pos_list.push_back((*this)[*i1]); + } + return atoms_pos_list.GetODRLine(); + } + + geom::Line3 CoordFrame::GetODRLine(const mol::EntityView& view1){ + //Returns the best fit line to atoms in the EntityView view1 + std::vector<unsigned long> indices; + GetIndices(view1,indices); + return this->GetODRLine(indices); + } + + geom::Plane CoordFrame::GetODRPlane(std::vector<unsigned long>& indices_ca){ + //Returns the normal to the best fit plane to atoms with indices in indices_ca + geom::Vec3List atoms_pos_list; + atoms_pos_list.reserve(indices_ca.size()); + for (std::vector<unsigned long>::const_iterator i1=indices_ca.begin(),e=indices_ca.end(); i1!=e; ++i1) { + atoms_pos_list.push_back((*this)[*i1]); + } + return atoms_pos_list.GetODRPlane(); + } + + geom::Plane CoordFrame::GetODRPlane(const mol::EntityView& view1){ + //Returns the best fit plane to atoms in the EntityView view1 + std::vector<unsigned long> indices; + GetIndices(view1,indices); + return this->GetODRPlane(indices); + } + + geom::Line3 CoordFrame::FitCylinder(std::vector<unsigned long>& indices_ca){ + //Returns a line which is the axis of a fitted cylinder to the atoms with indices given in indices_ca + //It is assumed that we fit an alpha-helix and that the CA atoms are oredered sequentially + //This is used for the initial guess of the helix axis + geom::Vec3List atoms_pos_list; + int n_atoms=indices_ca.size(); + atoms_pos_list.reserve(n_atoms); + for (std::vector<unsigned long>::const_iterator i1=indices_ca.begin(),e=indices_ca.end(); i1!=e; ++i1) { + atoms_pos_list.push_back((*this)[*i1]); + } + //Initial guess + geom::Vec3 initial_axis=geom::Vec3(0.0,0.0,0.0),center=geom::Vec3(0.0,0.0,0.0); + if (n_atoms<5) { + initial_axis=atoms_pos_list[n_atoms-1]-atoms_pos_list[0]; + } + else { + for (geom::Vec3List::const_iterator i=atoms_pos_list.begin(),e=atoms_pos_list.end()-4; i!=e; ++i) { + initial_axis+=(*(i+4))-(*i); + } + } + for (geom::Vec3List::const_iterator i=atoms_pos_list.begin(),e=atoms_pos_list.end(); i!=e; ++i) { + center+=(*i); + } + center/=atoms_pos_list.size(); + return atoms_pos_list.FitCylinder(initial_axis,center); + } + + geom::Line3 CoordFrame::FitCylinder(const mol::EntityView& view1){ + // Return a lin which is the axis of the best fit cylinder to the CA atoms + // of the EntityView. + // It is assumed that we fit an alpha-helix and that the CA atoms are oredered sequentially + CheckHandleValidity(view1); + std::vector<unsigned long> indices_ca; + GetCaIndices(view1, indices_ca); + return CoordFrame::FitCylinder(indices_ca); + } + + Real CoordFrame::GetAlphaHelixContent(const mol::EntityView& segment){ + //Returns the percentage of residues in the EntityView (segment) that are in an alpha-helix + //Each residue is assigned as being in an alpha-helix or not, based on and backbone torsion angles + //and the hydrogen bonding (O-N) (this term is used only if the segment contains at least 8 residues + //The entity view should be a single segment with no gaps and no missing N,CA,C,O backbone atoms + //the first and last residues will not be asessed for helicity + CheckHandleValidity(segment); + std::vector<unsigned long> indices_c, indices_n, indices_ca, indices_o; + GetCaCONIndices(segment, indices_ca, indices_c, indices_o, indices_n); + return CoordFrame::GetAlphaHelixContent(indices_ca,indices_c,indices_o,indices_n); + } + + Real Eval2AngleDist(Real phi, Real phi0, Real psi, Real psi0, Real delta){ + //Returns a score between 0 and 1 measuring the distance between + //a pair of angles and a pair of reference angles + Real d1,d2,d; + d1=abs(phi-phi0); + d2=abs(psi-psi0); + if (d1>M_PI) d1=abs(d1-2.*M_PI); + if (d2>M_PI) d1=abs(d2-2.*M_PI); + d=(pow(d1,2.)+pow(d2,2.))/pow(delta,2.); + return 1./(1+d); + } + + Real CoordFrame::GetAlphaHelixContent(std::vector<unsigned long>& indices_ca, std::vector<unsigned long>& indices_c, + std::vector<unsigned long>& indices_o, std::vector<unsigned long>& indices_n){ + //See CoordFrame::GetAlphaHelixContent(const mol::EntityView) above. + unsigned long n_atoms=indices_ca.size(); + geom::Vec3 c_previous,n,ca,c,n_next; + Real phi,psi,phi_0=-1.2,psi_0=-0.785,delta=0.8,d_0=3.3; + unsigned long n_helical_res=0; + std::vector<Real> score,dist,score2,dist2; + score.reserve(n_atoms-2); + score2.reserve(n_atoms-2); + dist.reserve(n_atoms-2); + dist2.reserve(n_atoms-2); + if (n_atoms!=indices_n.size()||n_atoms!=indices_c.size()||n_atoms!=indices_o.size()){ + throw std::runtime_error("not same numbers of CA, C, O and N atoms in the selection"); + } + if (n_atoms<=5){ + throw std::runtime_error("At least five residues are needed to calulate an alpha helix similarity"); + } + c=(*this)[indices_c[0]]; + n_next=(*this)[indices_n[1]]; + for (unsigned long i=1; i!=n_atoms-1; ++i){ + c_previous=c; + n=n_next; + ca=(*this)[indices_ca[i]]; + c=(*this)[indices_c[i]]; + n_next=(*this)[indices_n[i+1]]; + phi=geom::DihedralAngle(c_previous,n,ca,c); + psi=geom::DihedralAngle(n,ca,c,n_next); + score.push_back(Eval2AngleDist(phi,phi_0,psi,psi_0,delta)); + } + score2[0]=pow(score[0]*score[1],3./2.); + score2[n_atoms-3]=pow(score[n_atoms-3]*score[n_atoms-4],3./2.); + for (unsigned long i=1; i!=n_atoms-3; ++i){ + score2[i]=score[i-1]*score[i]*score[i+1]; + } + if (n_atoms>=8){ + for (unsigned long i=1; i!=n_atoms-1; ++i){ + if (i<n_atoms-4){ + dist.push_back(geom::Distance((*this)[indices_o[i]],(*this)[indices_n[i+4]])); + if (i>=5) { + dist2.push_back(std::min(dist[i-1],dist[i-5])); + } + else dist2.push_back(dist[i-1]); + } + else dist2.push_back(geom::Distance((*this)[indices_n[i]],(*this)[indices_o[i-4]])); + } + for (unsigned long i=0; i!=n_atoms-2; ++i){ + if (dist2[i]<=d_0 || score2[i]>=0.3)n_helical_res+=1; + } + } + else { + for (unsigned long i=0; i!=n_atoms-2; ++i){ + if (score2[i]>=0.3)n_helical_res+=1; + } + } + return Real(n_helical_res)/Real(n_atoms-2); + } + + + }}//ns diff --git a/modules/mol/base/src/coord_frame.hh b/modules/mol/base/src/coord_frame.hh index 8b34cc52acb31086b8ee02d074fe0aac526e22f8..98eb0c25c5560dbce0ad43e8450e79b8994b46df 100644 --- a/modules/mol/base/src/coord_frame.hh +++ b/modules/mol/base/src/coord_frame.hh @@ -31,15 +31,28 @@ namespace ost { namespace mol { class DLLEXPORT_OST_MOL CoordFrame : public geom::Vec3List{ +private: + geom::Vec3 periodic_cell_sizes_; + geom::Vec3 periodic_cell_angles_; public: typedef geom::Vec3List base_type; - CoordFrame() : base_type() {} + CoordFrame() : base_type() {} CoordFrame(size_t size, const geom::Vec3& value=geom::Vec3()) : base_type(size, value) {} CoordFrame(base_type::iterator b, base_type::iterator e): base_type(b, e) { } CoordFrame(const base_type& rhs) : base_type(rhs) { } CoordFrame(const std::vector<geom::Vec3>& rhs) : base_type(rhs) { } + CoordFrame(const std::vector<geom::Vec3>& rhs,const geom::Vec3 box_size, const geom::Vec3 box_angles) : base_type(rhs) { + this->periodic_cell_sizes_=box_size; + this->periodic_cell_angles_=box_angles; + } + geom::Vec3 GetCellSize() { + return this->periodic_cell_sizes_; + } + geom::Vec3 GetCellAngles() { + return this->periodic_cell_angles_; + } geom::Vec3 GetAtomPos(const AtomHandle& atom); geom::Vec3 GetAtomPos(int atom_index); Real GetDistanceBetwAtoms(const AtomHandle& a1, const AtomHandle& a2); @@ -60,13 +73,25 @@ public: Real GetMinDistBetwCenterOfMassAndView(std::vector<unsigned long>& indices_cm, std::vector<Real>& masses_cm, std::vector<unsigned long>& indices_atoms); Real GetMinDistBetwCenterOfMassAndView(const mol::EntityView& view_cm, const mol::EntityView& view_atoms); + geom::Line3 GetODRLine(std::vector<unsigned long>& indices_ca); + geom::Plane GetODRPlane(std::vector<unsigned long>& indices_ca); + geom::Line3 GetODRLine(const mol::EntityView& view1); + geom::Plane GetODRPlane(const mol::EntityView& view1); + geom::Line3 FitCylinder(std::vector<unsigned long>& indices_ca); + geom::Line3 FitCylinder(const mol::EntityView& view1); + Real GetAlphaHelixContent(std::vector<unsigned long>& indices_ca, std::vector<unsigned long>& indices_c, + std::vector<unsigned long>& indices_o, std::vector<unsigned long>& indices_n); + Real GetAlphaHelixContent(const mol::EntityView& segment); }; void GetIndices(const EntityView& sele, std::vector<unsigned long>& indices); void GetMasses(const EntityView& sele, std::vector<Real>& masses); void GetIndicesAndMasses(const EntityView& sele, std::vector<unsigned long>& indices,std::vector<Real>& masses); void GetPositions(const EntityView& sele, std::vector<geom::Vec3>& ref_pos); - + void GetCaIndices(const EntityView& segment, std::vector<unsigned long>& indices_ca); + void GetCaCONIndices(const EntityView& segment, std::vector<unsigned long>& indices_ca, std::vector<unsigned long>& indices_c, + std::vector<unsigned long>& indices_o, std::vector<unsigned long>& indices_n); + typedef boost::shared_ptr<CoordFrame> CoordFramePtr; typedef std::vector<CoordFramePtr> CoordFrameList; diff --git a/modules/mol/base/src/coord_group.cc b/modules/mol/base/src/coord_group.cc index f92c58e22b44f9dc4cd81753e288acefd164be9a..db3fd341ce04a76c6e928ca1e0fd93e869b583c7 100644 --- a/modules/mol/base/src/coord_group.cc +++ b/modules/mol/base/src/coord_group.cc @@ -73,6 +73,14 @@ void CoordGroupHandle::SetFramePositions(uint frame, //source_->SetFramePositions(frame, clist); } + +geom::Vec3List CoordGroupHandle::GetFramePositions(uint frame) + { + this->CheckValidity(); + return *(this->GetFrame(frame)); + } + + void CoordGroupHandle::CopyFrame(uint frame) { this->CheckValidity(); @@ -95,6 +103,16 @@ CoordGroupHandle::operator bool() const } } + void CoordGroupHandle::AddFrame(const geom::Vec3List& clist, const geom::Vec3& cell_size, const geom::Vec3& cell_angles) +{ + this->CheckValidity(); + if (source_->IsMutable()) { + source_->AddFrame(clist,cell_size,cell_angles); + } else { + throw IntegrityError("Can't add frame to immutable CoordGroup"); + } +} + void CoordGroupHandle::AddFrames(const CoordGroupHandle& cg) { this->CheckValidity(); @@ -135,6 +153,12 @@ CoordFramePtr CoordGroupHandle::GetFrame(uint frame) const return source_->GetFrame(frame); } +CoordFrame CoordGroupHandle::GetFrame2(uint frame) +{ + this->CheckValidity(); + return *(source_->GetFrame(frame)); +} + AtomHandleList CoordGroupHandle::GetAtomList() const { this->CheckValidity(); @@ -171,7 +195,7 @@ void CoordGroupHandle::Capture(uint frame) } } -CoordGroupHandle CoordGroupHandle::Filter(const EntityView& selected) const +CoordGroupHandle CoordGroupHandle::Filter(const EntityView& selected, int first, int last) const { this->CheckValidity(); std::vector<unsigned long> indices; @@ -194,8 +218,9 @@ CoordGroupHandle CoordGroupHandle::Filter(const EntityView& selected) const CoordGroupHandle filtered_cg=CreateCoordGroup(new_ent.GetAtomList()); std::vector<geom::Vec3> vecs(indices.size()); - for (size_t i=0; i<this->GetFrameCount(); ++i) { - LOG_INFO("Filtering frame " << i << "/" << this->GetFrameCount()); + if (last==-1) last=this->GetFrameCount(); + for (int i=first; i<last; ++i) { + LOG_INFO("Filtering frame " << i << "/" << last); CoordFramePtr frame=this->GetFrame(i); for (std::vector<unsigned long>::const_iterator j=indices.begin(), e2=indices.end(); j!=e2; ++j) { diff --git a/modules/mol/base/src/coord_group.hh b/modules/mol/base/src/coord_group.hh index 2b6d6fe7f4c40a68e323151f299ffeb184943e45..652fe34636d3dc11c7fa5168c83c05d906b6524a 100644 --- a/modules/mol/base/src/coord_group.hh +++ b/modules/mol/base/src/coord_group.hh @@ -52,6 +52,9 @@ public: /// initial atomlist void SetFramePositions(uint frame, const std::vector<geom::Vec3>& clist); + /// \brief get the positions of all the atoms in the given frame + geom::Vec3List GetFramePositions(uint frame); + /// \brief copy atom positions of given frame to stored atoms in entity void CopyFrame(uint frame); @@ -66,7 +69,8 @@ public: /// \brief add frame //void AddFrame(const std::vector<geom::Vec3>& clist); void AddFrame(const geom::Vec3List& clist); - + void AddFrame(const geom::Vec3List& clist,const geom::Vec3& cell_size,const geom::Vec3& cell_angles); + void AddFrames(const CoordGroupHandle& cg); /// \brief set an indidivial atom position in the given frame void SetAtomPos(uint frame, AtomHandle atom, const geom::Vec3& pos); @@ -82,10 +86,11 @@ public: AtomHandleList GetAtomList() const; CoordFramePtr GetFrame(uint frame) const; + CoordFrame GetFrame2(uint frame); /// \brief return a filtered coord group, containing only the atoms in the /// view - CoordGroupHandle Filter(const EntityView& selected) const; + CoordGroupHandle Filter(const EntityView& selected,int first=0,int last=-1) const; CoordGroupHandle(CoordSourcePtr source); diff --git a/modules/mol/base/src/coord_source.hh b/modules/mol/base/src/coord_source.hh index 604817535d9bc2fc0bd12c20739135e287642862..fec0d9946cb2ecd275abb23d5ebb58b080422734 100644 --- a/modules/mol/base/src/coord_source.hh +++ b/modules/mol/base/src/coord_source.hh @@ -70,6 +70,7 @@ public: void Capture(uint f); virtual void AddFrame(const std::vector<geom::Vec3>& coords) = 0; + virtual void AddFrame(const std::vector<geom::Vec3>& coords,const geom::Vec3& cell_size,const geom::Vec3& cell_angles) = 0; virtual void InsertFrame(int pos, const std::vector<geom::Vec3>& coords) = 0; protected: void SetMutable(bool flag); diff --git a/modules/mol/base/src/editor_base.cc b/modules/mol/base/src/editor_base.cc index 7718234673d7e35c33aee25b113a33e1c2dc2d54..d75827806359c8dc5036fa7cf819abb0ce7ffcc6 100644 --- a/modules/mol/base/src/editor_base.cc +++ b/modules/mol/base/src/editor_base.cc @@ -76,12 +76,31 @@ void EditorBase::RenameResidue(ResidueHandle res, const String& new_name) res.Impl()->SetKey(new_name); } +void EditorBase::SetResidueNumber(ResidueHandle res, const ResNum& new_num) +{ + CheckHandleValidity(res); + int index=res.GetIndex(); + res.Impl()->SetNumber(new_num); + res.GetChain().SetInSequence(index); +} + void EditorBase::RenameChain(ChainHandle chain, const String& new_name) { CheckHandleValidity(chain); ent_.Impl()->RenameChain(chain.Impl(), new_name); } +void EditorBase::SetChainType(ChainHandle chain, const ChainType type) +{ + CheckHandleValidity(chain); + chain.Impl()->SetType(type); +} + +void EditorBase::SetChainDescription(ChainHandle chain, const String desc) +{ + CheckHandleValidity(chain); + chain.Impl()->SetDescription(desc); +} AtomHandle EditorBase::InsertAtom(ResidueHandle res, const String& name, const geom::Vec3& pos, const String& ele, @@ -100,21 +119,26 @@ AtomHandle EditorBase::InsertAtom(ResidueHandle res, const String& name, AtomHandle EditorBase::InsertAltAtom(ResidueHandle res, const String& name, const String& alt_group, const geom::Vec3& pos, - const String& ele) + const String& ele, Real occ, + Real b_factor) { CheckHandleValidity(res); ent_.Impl()->MarkTraceDirty(); - AtomHandle atom(res.Impl()->InsertAltAtom(name, alt_group, pos, ele)); + AtomHandle atom(res.Impl()->InsertAltAtom(name, alt_group, pos, + ele, occ, b_factor)); this->UpdateTrace(); return atom; } void EditorBase::AddAltAtomPos(const String& group, const AtomHandle& atom, - const geom::Vec3& position) + const geom::Vec3& position, Real occ, + Real b_factor) { CheckHandleValidity(atom); - atom.GetResidue().Impl()->AddAltAtomPos(group, atom.Impl(), position); + atom.GetResidue().Impl()->AddAltAtomPos(group, atom.Impl(), + position, occ, b_factor); + } void EditorBase::DeleteChain(const ChainHandle& chain) @@ -146,6 +170,11 @@ void EditorBase::ReorderAllResidues() ent_.Impl()->ReorderAllResidues(); } +void EditorBase::RenumberAllResidues(int start, bool keep_spacing) +{ + ent_.Impl()->RenumberAllResidues(start, keep_spacing); +} + void EditorBase::RenameAtom(AtomHandle atom, const String& new_name) { CheckHandleValidity(atom); @@ -206,6 +235,7 @@ void EditorBase::UpdateTrace() { if (mode_==UNBUFFERED_EDIT) { ent_.Impl()->TraceDirectionality(); + ent_.Impl()->UpdateICSIfNeeded(); } } diff --git a/modules/mol/base/src/editor_base.hh b/modules/mol/base/src/editor_base.hh index 48bf067bd19ea8c1957d60fe3ba3c439f86b4917..504311d547cf00f43e11fb5b1c49925a16564e34 100644 --- a/modules/mol/base/src/editor_base.hh +++ b/modules/mol/base/src/editor_base.hh @@ -124,7 +124,8 @@ public: /// \sa EditorBase::AddAltAtomPos(), ResidueHandle AtomHandle InsertAltAtom(ResidueHandle residue, const String& name, const String& alt_group, const geom::Vec3& pos, - const String& ele=""); + const String& ele="", Real occ=1.0, + Real b_factor=0.0); /// \brief Add alternative atom position /// \param group is the name of the alternative atom position group. If no /// group of that name exists, it will be created. @@ -136,7 +137,8 @@ public: /// is the alternative position /// \sa EditorBase::InsertAltAtom(), ResidueHandle void AddAltAtomPos(const String& group, const AtomHandle& atom, - const geom::Vec3& position); + const geom::Vec3& position, Real occ=1.0, + Real b_factor=0.0); //\} /// \brief connect two atoms with bond @@ -153,8 +155,23 @@ public: unsigned char bond_order); void RenameResidue(ResidueHandle res, const String& new_name); - + + void SetResidueNumber(ResidueHandle res, const ResNum& num); + void RenameChain(ChainHandle chain, const String& new_name); + + /// \brief Assign type of chain according to ChainType. + /// + /// \param chain chain to assign to + /// \param type type of the chain + void SetChainType(ChainHandle chain, const ChainType type); + + /// \brief Assign a description to a chain. + /// + /// \param chain chain to assign to + /// \param desc description + void SetChainDescription(ChainHandle chain, const String desc); + /// \brief Delete all atoms of residue /// /// All associated torsions and bonds will also be removed @@ -190,6 +207,17 @@ public: /// \brief reorder residues of all chains based on their residue number void ReorderAllResidues(); + + /// \brief renumber residues of all chains + /// + /// \param start + /// Residues of every chain will be renumbered, whereas the first + /// residue gets the residue number start. + /// + /// \param keep_spacing + /// If set to false, residues will continously be renumbered ongoing from start. + /// Otherwise the spacings between the residues are kept. + void RenumberAllResidues(int start, bool keep_spacing); /// \brief Get edit mode of editor EditMode GetMode() const {return mode_;} diff --git a/modules/mol/base/src/entity_handle.cc b/modules/mol/base/src/entity_handle.cc index e975132ea84a50c5ea7fb76026cff894645b6920..0abad5ede1b3241f05300b5768cf0b7c332f4c12 100644 --- a/modules/mol/base/src/entity_handle.cc +++ b/modules/mol/base/src/entity_handle.cc @@ -362,6 +362,18 @@ AtomHandleList EntityHandle::GetAtomList() const return atoms; } +geom::Vec3List EntityHandle::GetAtomPosList() const { + this->CheckValidity(); + geom::Vec3List atom_pos_list; + atom_pos_list.reserve(this->GetAtomCount()); + AtomHandleList atom_list=this->GetAtomList(); + for (AtomHandleList::const_iterator a=atom_list.begin(), e=atom_list.end(); a!=e; ++a) { + atom_pos_list.push_back(a->GetPos()); + } + return atom_pos_list; + //return Impl()->GetAtomPosList(); +} + EntityHandle EntityHandle::GetHandle() const { return *this; diff --git a/modules/mol/base/src/entity_handle.hh b/modules/mol/base/src/entity_handle.hh index 0fcadee77d9e68b69048b7c346d3d3c266919fd0..67b2a847e4ab4050d9dfd9043e9fa3ab46ae0bd6 100644 --- a/modules/mol/base/src/entity_handle.hh +++ b/modules/mol/base/src/entity_handle.hh @@ -280,6 +280,9 @@ public: /// \sa #AtomsBegin, #AtomsEnd AtomHandleList GetAtomList() const; + /// \brief get complete list of atom positions + geom::Vec3List GetAtomPosList() const; + /// \brief Get editor for external coordinate system to manipulate atom /// positions /// \sa editors diff --git a/modules/mol/base/src/entity_view.cc b/modules/mol/base/src/entity_view.cc index 3e5445b56a8936c7562c5e0d830ad0785c1b1ccb..a88f0b39553a438c0d51359fee91cacf9d85a7a1 100644 --- a/modules/mol/base/src/entity_view.cc +++ b/modules/mol/base/src/entity_view.cc @@ -187,10 +187,10 @@ geom::Vec3 EntityView::GetCenterOfMass() const Real EntityView::GetMass() const { - Real mass = 0; - AtomViewIter it=this->AtomsBegin(); - for(; it!=this->AtomsEnd(); ++it) { - mass+=(*it).GetMass(); + this->CheckValidity(); + double mass = 0; + for (ChainViewList::iterator i=data_->chains.begin();i!=data_->chains.end(); ++i) { + mass+=i->GetMass(); } return mass; } diff --git a/modules/mol/base/src/ics_editor.cc b/modules/mol/base/src/ics_editor.cc index c374a0f09697accb0f56fee925200d3b03df4879..910c7fd85365f747e12eed613147bde49b2a4fdb 100644 --- a/modules/mol/base/src/ics_editor.cc +++ b/modules/mol/base/src/ics_editor.cc @@ -23,6 +23,7 @@ #include "impl/torsion_impl.hh" #include "impl/entity_impl.hh" #include "impl/connector_impl.hh" +#include "impl/atom_impl.hh" /* Author: Marco Biasini */ @@ -96,18 +97,20 @@ bool ICSEditor::SetAngle(const AtomHandle& atom_a, const AtomHandle& atom_b, return return_value; } -void ICSEditor::SetTorsionAngle(TorsionHandle torsion, Real angle) +void ICSEditor::SetTorsionAngle(TorsionHandle torsion, Real angle, + bool update_others) { CheckHandleValidity(torsion); - torsion.Impl()->SetAngle(angle, false); + torsion.Impl()->SetAngle(angle, update_others); ent_.Impl()->MarkXCSDirty(); this->Update(); } -void ICSEditor::RotateTorsionAngle(TorsionHandle torsion, Real angle) +void ICSEditor::RotateTorsionAngle(TorsionHandle torsion, Real angle, + bool update_others) { CheckHandleValidity(torsion); - torsion.Impl()->RotateAngle(angle, false); + torsion.Impl()->RotateAngle(angle, update_others); ent_.Impl()->MarkXCSDirty(); this->Update(); } @@ -116,7 +119,9 @@ void ICSEditor::RotateTorsionAngle(TorsionHandle torsion, Real angle) void ICSEditor::RotateTorsionAngle(const AtomHandle& atom_a, const AtomHandle& atom_b, const AtomHandle& atom_c, - const AtomHandle& atom_d, Real angle) + const AtomHandle& atom_d, + Real angle, + bool update_others) { CheckHandleValidity(atom_a); CheckHandleValidity(atom_b); @@ -124,7 +129,7 @@ void ICSEditor::RotateTorsionAngle(const AtomHandle& atom_a, CheckHandleValidity(atom_d); impl::Dihedral d(atom_a.Impl(), atom_b.Impl(), atom_c.Impl(), atom_d.Impl()); Real cur_angle=d.GetAngleICS(); - d.SetAngleICS(cur_angle+angle); + d.SetAngleICS(cur_angle+angle, update_others); ent_.Impl()->MarkXCSDirty(); this->Update(); } @@ -133,16 +138,19 @@ void ICSEditor::RotateTorsionAngle(const AtomHandle& atom_a, void ICSEditor::SetTorsionAngle(const AtomHandle& atom_a, const AtomHandle& atom_b, const AtomHandle& atom_c, - const AtomHandle& atom_d, Real angle) + const AtomHandle& atom_d, + Real angle, + bool update_others) { CheckHandleValidity(atom_a); CheckHandleValidity(atom_b); CheckHandleValidity(atom_c); CheckHandleValidity(atom_d); impl::Dihedral d(atom_a.Impl(), atom_b.Impl(), atom_c.Impl(), atom_d.Impl()); - d.SetAngleICS(angle, false); + d.SetAngleICS(angle, update_others); ent_.Impl()->MarkXCSDirty(); this->Update(); } + }} // ns diff --git a/modules/mol/base/src/ics_editor.hh b/modules/mol/base/src/ics_editor.hh index 9643336949dbf2fe700187feee372f5baca235cc..eb51807432d2a9aa3f2ddeb08b48c5a8ea88d073 100644 --- a/modules/mol/base/src/ics_editor.hh +++ b/modules/mol/base/src/ics_editor.hh @@ -74,19 +74,22 @@ public: /// bonds untouched, use the SetDihedralAngle() function /// /// \sa RotateTorsionAngle - void SetTorsionAngle(TorsionHandle torsion, Real angle); + void SetTorsionAngle(TorsionHandle torsion, Real angle, + bool update_others=true); /// \brief rotate torsion angle - void RotateTorsionAngle(TorsionHandle torsion, Real delta); + void RotateTorsionAngle(TorsionHandle torsion, Real delta, + bool update_others=true); void RotateTorsionAngle(const AtomHandle& atom_a, const AtomHandle& atom_b, const AtomHandle& atom_c, const AtomHandle& atom_d, - Real angle); + Real angle, + bool update_others=true); void SetTorsionAngle(const AtomHandle& atom_a, const AtomHandle& atom_b, const AtomHandle& atom_c, const AtomHandle& atom_d, - Real angle); + Real angle, bool update_others=true); /// \brief immediately update external coordinate system void UpdateXCS(); diff --git a/modules/mol/base/src/impl/atom_group.hh b/modules/mol/base/src/impl/atom_group.hh index 934fda241c3c614185a2fe32a77ccdad6b0582e3..50a7c6338972313b36f41bed8072f60d42cdf21a 100644 --- a/modules/mol/base/src/impl/atom_group.hh +++ b/modules/mol/base/src/impl/atom_group.hh @@ -29,10 +29,13 @@ namespace ost { namespace mol {namespace impl { struct AtomGroupEntry { AtomGroupEntry() {} - AtomGroupEntry(const AtomImplPtr& a, const geom::Vec3& p) - : atom(a), pos(p) {} + AtomGroupEntry(const AtomImplPtr& a, const geom::Vec3& p, + Real o, Real b) + : atom(a), pos(p), occ(o), b_factor(b) {} impl::AtomImplW atom; geom::Vec3 pos; + Real occ; + Real b_factor; }; typedef std::vector<AtomGroupEntry> AtomGroupEntryList; diff --git a/modules/mol/base/src/impl/chain_impl.cc b/modules/mol/base/src/impl/chain_impl.cc index 421f98dd4a43bafb12537e1649b51aba49abb9d3..009f436a5406a42caeda27605574587d48decbe3 100644 --- a/modules/mol/base/src/impl/chain_impl.cc +++ b/modules/mol/base/src/impl/chain_impl.cc @@ -36,7 +36,9 @@ ChainImpl::ChainImpl(const EntityImplPtr& e, const String& name): ent_(e), name_(name), residue_list_(), - in_sequence_(true) + in_sequence_(true), + type_(CHAINTYPE_UNKNOWN), + description_() {} String ChainImpl::GetName() const @@ -398,14 +400,11 @@ void ChainImpl::AssignSecondaryStructure(SecStructure ss, Real ChainImpl::GetMass() const { - Real mass = 0; + double mass = 0; for (ResidueImplList::const_iterator i=residue_list_.begin(); i!=residue_list_.end(); ++i) { ResidueImplPtr r=*i; - for (AtomImplList::iterator j=r->GetAtomList().begin(); - j!=r->GetAtomList().end(); ++j) { - mass+=(*j)->GetMass(); - } + mass+=r->GetMass(); } return mass; } @@ -485,4 +484,41 @@ void ChainImpl::ReorderResidues() UpdateShifts(); } +void ChainImpl::RenumberAllResidues(int start, bool keep_spacing) +{ + ResNum actual_num=ResNum(start); + ResNum original_start_num=residue_list_[0]->GetNumber(); + ResNum start_diff=ResNum(start)-original_start_num; + + + for (ResidueImplList::const_iterator i=residue_list_.begin(); + i!=residue_list_.end(); ++i) { + + if(keep_spacing){ + ResNum temp=(*i)->GetNumber(); + (*i)->SetNumber(temp+start_diff); + continue; + } + + (*i)->SetNumber(actual_num); + actual_num++; + } + UpdateShifts(); +} + +void ChainImpl::SetInSequence(const int index) +{ + ResNum num=residue_list_[index]->GetNumber(); + //Check if rp is in sequence + if (in_sequence_) { + if (index>0 && residue_list_[index-1]->GetNumber()>=num) + in_sequence_=false; + if (index<static_cast<int>(residue_list_.size())-1 && residue_list_[index+1]->GetNumber()<=num) + in_sequence_=false; + } + if (in_sequence_) { + this->UpdateShifts(); + } +} + }}} // ns diff --git a/modules/mol/base/src/impl/chain_impl.hh b/modules/mol/base/src/impl/chain_impl.hh index d7d2ca64beeb0f464263c8ddedd9f3da8be5a2ae..bcb3436e2bc463dadcfe1ca6af4e1bbac48af24b 100644 --- a/modules/mol/base/src/impl/chain_impl.hh +++ b/modules/mol/base/src/impl/chain_impl.hh @@ -25,6 +25,7 @@ #include <ost/geom/geom.hh> #include <ost/mol/residue_prop.hh> +#include <ost/mol/chain_type.hh> #include <ost/mol/impl/chain_impl_fw.hh> #include <ost/mol/impl/residue_impl_fw.hh> #include <ost/mol/impl/entity_impl_fw.hh> @@ -46,7 +47,62 @@ public: void SetName(const String& new_name); String GetName() const; + + /// \brief Assign a type to a chain. + /// + /// \param type chain type of ChainType + void SetType(const ChainType type) + { + type_ = type; + } + + /// \brief Get the type of a chain. + /// + /// \return chain type of ChainType + ChainType GetType() const + { + return type_; + } + /// \brief whether the chain is a polymer + bool IsPolymer() const + { + return type_==CHAINTYPE_POLY || this->IsPolypeptide() || + this->IsPolynucleotide() || this->IsPolysaccharide(); + } + /// \brief whether the chain is a polysaccharide + bool IsPolysaccharide() const + { + return type_==CHAINTYPE_POLY_SAC_D || type_==CHAINTYPE_POLY_SAC_L; + } + /// \brief whether the chain is a polypeptide + bool IsPolypeptide() const + { + return type_==CHAINTYPE_POLY_PEPTIDE_D || type_==CHAINTYPE_POLY_PEPTIDE_L; + } + /// \brief whether the chain is a polynucleotide + bool IsPolynucleotide() const + { + return type_==CHAINTYPE_POLY_DN || type_==CHAINTYPE_POLY_RN || + type_==CHAINTYPE_POLY_DN_RN; + } + + /// \brief Assign a description to a chain. + /// + /// \param desc description + void SetDescription(const String desc) + { + description_ = desc; + } + + /// \brief Get information about a chain + /// + /// \return description + String GetDescription() const + { + return description_; + } + /// \brief append new residue with exactly the same parameters as res, but /// no atoms and bonds ResidueImplPtr AppendResidue(const ResidueImplPtr& res); @@ -113,13 +169,18 @@ public: void DeleteAllResidues(); void ReorderResidues(); + + void RenumberAllResidues(int start, bool keep_spacing); int GetIndex(const ResidueImplPtr& res) const; void AssignSecondaryStructure(SecStructure ss, const ResNum& start, const ResNum& end); int GetIndexForResNum(const ResNum& number) const; - + ///\brief checks if the residue with that index breaks the in_sequence + /// property and updates it accordingly + void SetInSequence(int index); + private: int GetIndexForResNumInSequence(const ResNum& number) const; void UpdateShifts(); @@ -134,6 +195,8 @@ private: /// \brief whether the residue numbers are in ascending order or not. Used /// to optimize residue by number lookup. bool in_sequence_; + ChainType type_; + String description_; ///< special aspects of the chain }; }}} // ns diff --git a/modules/mol/base/src/impl/connector_impl.cc b/modules/mol/base/src/impl/connector_impl.cc index 8bafe009b6a110edecd96cadc3492ed348dc1f19..3a5a61532b5e6f61c58b960c3b0ba0b3f41789c9 100644 --- a/modules/mol/base/src/impl/connector_impl.cc +++ b/modules/mol/base/src/impl/connector_impl.cc @@ -92,14 +92,22 @@ Real ConnectorImpl::GetLength() const } void ConnectorImpl::SetDir(const geom::Vec3& dir) { - geom::Vec3 v=Normalize(dir); - local_rot_=find_rotation(v); + if(Length(dir)==0) { + local_rot_=geom::Mat3(1,0,0,0,1,0,0,0,1); + } else { + geom::Vec3 v=Normalize(dir); + local_rot_=find_rotation(v); + } } void ConnectorImpl::SetDirAndLength(const geom::Vec3& dir) { len_=Length(dir); - geom::Vec3 v=dir/len_; - local_rot_=find_rotation(v); + if(len_==0) { + local_rot_=geom::Mat3(1,0,0,0,1,0,0,0,1); + } else { + geom::Vec3 v=dir/len_; + local_rot_=find_rotation(v); + } } bool ConnectorImpl::IsConnectorOf(const AtomImplPtr& a, diff --git a/modules/mol/base/src/impl/dihedral.hh b/modules/mol/base/src/impl/dihedral.hh index 2996205ba7e06cfd53c2a45829335c365a034d28..a722c93e60ff4b8d015d5f5bb97bc7d1b3a9709c 100644 --- a/modules/mol/base/src/impl/dihedral.hh +++ b/modules/mol/base/src/impl/dihedral.hh @@ -52,7 +52,7 @@ public: /// \param update_other /// If true, connectors of atom3 are updated accordingly, otherwise /// they will be left untouched - void SetAngleICS(Real angle, bool update_other=false); + void SetAngleICS(Real angle, bool update_other); geom::Vec3 GetPos() const; geom::Vec3 GetOriginalPos() const; diff --git a/modules/mol/base/src/impl/entity_impl.cc b/modules/mol/base/src/impl/entity_impl.cc index 305e3423041abfb58252cf417a861ada5d77967b..6942ce00fee8b3a93f45e31c083b90c51c80bdd3 100644 --- a/modules/mol/base/src/impl/entity_impl.cc +++ b/modules/mol/base/src/impl/entity_impl.cc @@ -307,11 +307,13 @@ geom::Vec3 EntityImpl::GetCenterOfMass() const { return center; } + Real EntityImpl::GetMass() const { - Real mass=0.0; - for (AtomImplMap::const_iterator it = atom_map_.begin(); - it!=atom_map_.end();++it) { - mass+=it->second->GetMass(); + double mass=0.0; + for (ChainImplList::const_iterator i=chain_list_.begin(), + e=chain_list_.end(); i!=e; ++i) { + ChainImplPtr chain=*i; + mass+=chain->GetMass(); } return mass; } @@ -1209,4 +1211,12 @@ void EntityImpl::ReorderAllResidues() } } +void EntityImpl::RenumberAllResidues(int start, bool keep_spacing) +{ + for(ChainImplList::iterator cit=chain_list_.begin();cit!=chain_list_.end();++cit) { + (*cit)->RenumberAllResidues(start, keep_spacing); + } + +} + }}} // ns diff --git a/modules/mol/base/src/impl/entity_impl.hh b/modules/mol/base/src/impl/entity_impl.hh index 3c5000920c23a959ab631e62874d54df6cce6878..d1d1ca050f30a7fdee8d7ab5d64bf417ee183dc8 100644 --- a/modules/mol/base/src/impl/entity_impl.hh +++ b/modules/mol/base/src/impl/entity_impl.hh @@ -93,7 +93,6 @@ public: Real GetMass() const; geom::Vec3 GetCenterOfMass() const; geom::Vec3 GetCenterOfAtoms() const; - /// \brief returns the axis-aligned bounding box of the entity geom::AlignedCuboid GetBounds() const; @@ -254,6 +253,8 @@ public: void ReorderAllResidues(); + void RenumberAllResidues(int start, bool keep_spacing); + private: void DoCopy(EntityImplPtr dest); diff --git a/modules/mol/base/src/impl/query_impl.cc b/modules/mol/base/src/impl/query_impl.cc index a70cfa813b39d63d9337cfb6135846d63796f8fb..965f1dbe418ce9bf391449d0bc1f46a215874c7b 100644 --- a/modules/mol/base/src/impl/query_impl.cc +++ b/modules/mol/base/src/impl/query_impl.cc @@ -283,12 +283,7 @@ bool QueryImpl::IsAlwaysUndef(const Node* ast, if (lop_node) { bool lhs = this->IsAlwaysUndef(lop_node->GetLHS(), target_level); bool rhs = this->IsAlwaysUndef(lop_node->GetRHS(), target_level); - switch (lop_node->GetOP()) { - case LOP_AND: - return lhs || rhs; - case LOP_OR: - return lhs && rhs; - } + return lhs && rhs; } else { const SelNode* sel_node = dynamic_cast<const SelNode*>(ast); diff --git a/modules/mol/base/src/impl/residue_impl.cc b/modules/mol/base/src/impl/residue_impl.cc index 28f0cc6f9047616848e8d0a334da946a6fdfea9f..1e0fa1d461662e1895f6d8dd5bbeb7d8a58479f6 100644 --- a/modules/mol/base/src/impl/residue_impl.cc +++ b/modules/mol/base/src/impl/residue_impl.cc @@ -91,7 +91,8 @@ Real ResidueImpl::GetAverageBFactor() const } void ResidueImpl::AddAltAtom(const String& group, const AtomImplPtr& atom, - const geom::Vec3& position) { + const geom::Vec3& position, + Real occ, Real b_factor) { if (group.length()==0) throw Error("alt atom group name can't be empty String"); @@ -106,7 +107,7 @@ void ResidueImpl::AddAltAtom(const String& group, const AtomImplPtr& atom, curr_group_=group; } } - i->second.atoms.push_back(AtomGroupEntry(atom, position)); + i->second.atoms.push_back(AtomGroupEntry(atom, position, occ, b_factor)); } geom::Vec3 ResidueImpl::GetAltAtomPos(const AtomImplPtr& atom, @@ -127,12 +128,47 @@ geom::Vec3 ResidueImpl::GetAltAtomPos(const AtomImplPtr& atom, " does not have alternative atom position '"+group+"'"); } +Real ResidueImpl::GetAltAtomOcc(const AtomImplPtr& atom, + const String& group) const +{ + AtomEntryGroups::const_iterator i=alt_groups_.find(group); + if (i==alt_groups_.end()) { + throw Error("No alt atom group '"+group+"'"); + } + const AtomGroup& g=i->second; + for (AtomGroupEntryList::const_iterator j=g.atoms.begin(), + e=g.atoms.end(); j!=e; ++j) { + if (atom==j->atom.lock()) { + return j->occ; + } + } + throw Error(atom->GetQualifiedName()+ + " does not have alternative atom position '"+group+"'"); +} +Real ResidueImpl::GetAltAtomBFactor(const AtomImplPtr& atom, + const String& group) const +{ + AtomEntryGroups::const_iterator i=alt_groups_.find(group); + if (i==alt_groups_.end()) { + throw Error("No alt atom group '"+group+"'"); + } + const AtomGroup& g=i->second; + for (AtomGroupEntryList::const_iterator j=g.atoms.begin(), + e=g.atoms.end(); j!=e; ++j) { + if (atom==j->atom.lock()) { + return j->b_factor; + } + } + throw Error(atom->GetQualifiedName()+ + " does not have alternative atom position '"+group+"'"); +} AtomImplPtr ResidueImpl::InsertAltAtom(const String& name, const String& alt_group, const geom::Vec3& pos, - const String& ele) { + const String& ele, + Real occupancy, Real b_factor) { AtomImplPtr atom=this->InsertAtom(name, pos, ele); - this->AddAltAtom(alt_group, atom, pos); + this->AddAltAtom(alt_group, atom, pos, occupancy, b_factor); return atom; } @@ -451,7 +487,7 @@ void ResidueImpl::RemoveAltPositionsForAtom(const AtomImplPtr& atom) { Real ResidueImpl::GetMass() const { - Real mass = 0; + double mass = 0; for (AtomImplList::const_iterator i=atom_list_.begin(); i!=atom_list_.end(); ++i) { mass+=(*i)->GetMass(); @@ -506,7 +542,8 @@ geom::Vec3 ResidueImpl::GetCenterOfMass() const void ResidueImpl::AddAltAtomPos(const String& group, const AtomImplPtr& atom, - const geom::Vec3& position) { + const geom::Vec3& position, + Real occ, Real b_factor) { // Make sure atom is already registered for having an alternative position. // Bail out, if this is not the case. AtomEntryGroups::iterator i=alt_groups_.begin(); @@ -522,7 +559,7 @@ void ResidueImpl::AddAltAtomPos(const String& group, } } if (found) - this->AddAltAtom(group, atom, position); + this->AddAltAtom(group, atom, position, occ, b_factor); else { String m="Definition of alternative position without prior call to " "InsertAltAtom is not allowed"; @@ -582,6 +619,8 @@ bool ResidueImpl::SwitchAtomPos(const String& group) { AtomGroupEntry& entry=*k; assert(!entry.atom.expired()); entry.pos=entry.atom.lock()->OriginalPos(); + entry.occ=entry.atom.lock()->GetOccupancy(); + entry.b_factor=entry.atom.lock()->GetBFactor(); } } AtomGroup& agr=i->second; @@ -595,6 +634,8 @@ bool ResidueImpl::SwitchAtomPos(const String& group) { geom::Mat4 transf_matrix = ent.GetTransformationMatrix(); geom::Vec3 transf_pos = geom::Vec3(transf_matrix*geom::Vec4(entry.pos)); entry.atom.lock()->TransformedPos()=transf_pos; + entry.atom.lock()->SetBFactor(j->b_factor); + entry.atom.lock()->SetOccupancy(j->occ); } curr_group_=group; return true; diff --git a/modules/mol/base/src/impl/residue_impl.hh b/modules/mol/base/src/impl/residue_impl.hh index 8b01d32d2f3d8873f8098805dbe62028334dc2ec..24f829c6922bdbfdcc0ee8645cbec80e4ff49f88 100644 --- a/modules/mol/base/src/impl/residue_impl.hh +++ b/modules/mol/base/src/impl/residue_impl.hh @@ -34,6 +34,7 @@ #include <ost/mol/impl/torsion_impl_fw.hh> #include <ost/mol/impl/atom_group.hh> #include <ost/mol/chem_class.hh> +#include <ost/mol/chem_type.hh> #include <ost/generic_property.hh> #include <ost/mol/property_id.hh> @@ -57,7 +58,8 @@ public: /// no bonds AtomImplPtr InsertAtom(const AtomImplPtr& atom); AtomImplPtr InsertAltAtom(const String& name, const String& alt_group, - const geom::Vec3& pos, const String& ele); + const geom::Vec3& pos, const String& ele, + Real occ, Real b_factor); const ResNum& GetNumber() const {return num_;} void SetNumber(const ResNum& num) {num_=num;} @@ -166,8 +168,11 @@ public: void AddAltAtomPos(const String& group, const AtomImplPtr& atom, - const geom::Vec3& position); + const geom::Vec3& position, + Real occ, Real b_factor); geom::Vec3 GetAltAtomPos(const AtomImplPtr& atom, const String& group) const; + Real GetAltAtomOcc(const AtomImplPtr& atom, const String& group) const; + Real GetAltAtomBFactor(const AtomImplPtr& atom, const String& group) const; const String& GetCurrentAltGroupName() const { @@ -196,6 +201,12 @@ public: ChemClass GetChemClass() const { return chem_class_; } + ChemType GetChemType() const { + return chem_type_; + } + void SetChemType(ChemType ct) { + chem_type_=ct; + } TorsionImplP FindTorsion(const String& torsion_name) const; @@ -214,7 +225,7 @@ public: void SetIsLigand(bool flag) { ligand_=flag; } private: void AddAltAtom(const String& group, const AtomImplPtr& atom, - const geom::Vec3& position); + const geom::Vec3& position, Real occ, Real b_factor); void RemoveAltPositionsForAtom(const AtomImplPtr& atom); String curr_group_; @@ -227,6 +238,7 @@ private: TorsionImplList torsion_list_; SecStructure sec_structure_; ChemClass chem_class_; + ChemType chem_type_; char olc_; // whether the residue is part of the protein. // TODO: this should be fixed to be a enum'ed type aka diff --git a/modules/mol/base/src/impl/torsion_impl.cc b/modules/mol/base/src/impl/torsion_impl.cc index 744d648f33f3139d1bb03c7327f8ef0a9a77b7f1..9f9ffcdd9b74fa46969ed70f934b1c0a434e4602 100644 --- a/modules/mol/base/src/impl/torsion_impl.cc +++ b/modules/mol/base/src/impl/torsion_impl.cc @@ -48,8 +48,8 @@ Real TorsionImpl::GetAngle() const { } } -void TorsionImpl::SetAngle(Real angle, bool up) { - this->SetAngleICS(angle, true); +void TorsionImpl::SetAngle(Real angle, bool update_others) { + this->SetAngleICS(angle, update_others); } void TorsionImpl::Apply(EntityVisitor& v) { @@ -57,8 +57,8 @@ void TorsionImpl::Apply(EntityVisitor& v) { v.VisitTorsion(TorsionHandle(shared_from_this())); } -void TorsionImpl::RotateAngle(Real angle, bool up) { - this->SetAngle(this->GetAngleICS()+angle, up); +void TorsionImpl::RotateAngle(Real angle, bool update_others) { + this->SetAngle(this->GetAngleICS()+angle, update_others); } }}} // ns diff --git a/modules/mol/base/src/in_mem_coord_source.cc b/modules/mol/base/src/in_mem_coord_source.cc index 1690c11048713795f5bf3d86bbef29b9fb82702f..ea01db894a69efa04189e126b3f2d6429df46f12 100644 --- a/modules/mol/base/src/in_mem_coord_source.cc +++ b/modules/mol/base/src/in_mem_coord_source.cc @@ -30,6 +30,12 @@ void InMemCoordSource::AddFrame(const std::vector<geom::Vec3>& coords) frames_.push_back(fp); } +void InMemCoordSource::AddFrame(const std::vector<geom::Vec3>& coords,const geom::Vec3& cell_size,const geom::Vec3& cell_angles) +{ + CoordFramePtr fp(new CoordFrame(coords,cell_size,cell_angles)); + frames_.push_back(fp); +} + void InMemCoordSource::InsertFrame(int pos, const std::vector<geom::Vec3>& coords) { CoordFrameList::iterator it = frames_.begin(); diff --git a/modules/mol/base/src/in_mem_coord_source.hh b/modules/mol/base/src/in_mem_coord_source.hh index dc032ebbea294fdc6b4bb7ba86d79847b5e818ca..0984791aae634bcf315efe08f55f10850ef77c5f 100644 --- a/modules/mol/base/src/in_mem_coord_source.hh +++ b/modules/mol/base/src/in_mem_coord_source.hh @@ -44,6 +44,7 @@ public: void AddFrame(const CoordFramePtr& frame); virtual void AddFrame(const std::vector<geom::Vec3>& coords); + virtual void AddFrame(const std::vector<geom::Vec3>& coords,const geom::Vec3& cell_size,const geom::Vec3& cell_angles); virtual void InsertFrame(int pos, const std::vector<geom::Vec3>& coords); private: diff --git a/modules/mol/base/src/query_state.cc b/modules/mol/base/src/query_state.cc index d8d4da028c2f727bde33cb8305a7bf8ae09a0b08..63a4be69387dd7a3e6aaf3865b8737fe8a5b58d6 100644 --- a/modules/mol/base/src/query_state.cc +++ b/modules/mol/base/src/query_state.cc @@ -321,7 +321,7 @@ boost::logic::tribool QueryState::EvalAtom(const AtomImplPtr& a) { case Prop::ANAME: str_value = a->Name(); s_[*i] = cmp_string(ss.comp_op,str_value, - boost::get<StringOrRegexParam>(ss.param)); + boost::get<StringOrRegexParam>(ss.param)); break; case Prop::AINDEX: int_value=(a->GetIndex()); @@ -330,27 +330,27 @@ boost::logic::tribool QueryState::EvalAtom(const AtomImplPtr& a) { case Prop::AX: float_value=(a->TransformedPos())[0]; s_[*i]=cmp_num<Real>(ss.comp_op, float_value, - boost::get<float>(ss.param)); + boost::get<float>(ss.param)); break; case Prop::AY: float_value=(a->TransformedPos())[1]; s_[*i]=cmp_num<Real>(ss.comp_op, float_value, - boost::get<float>(ss.param)); + boost::get<float>(ss.param)); break; case Prop::AZ: float_value=(a->TransformedPos())[2]; s_[*i]=cmp_num<Real>(ss.comp_op, float_value, - boost::get<float>(ss.param)); + boost::get<float>(ss.param)); break; case Prop::OCC: float_value=a->GetOccupancy(); s_[*i]=cmp_num<Real>(ss.comp_op, float_value, - boost::get<float>(ss.param)); + boost::get<float>(ss.param)); break; case Prop::ELE: str_value = a->GetElement(); s_[*i] = cmp_string(ss.comp_op,str_value, - boost::get<StringOrRegexParam>(ss.param)); + boost::get<StringOrRegexParam>(ss.param)); break; case Prop::ABFAC: float_value=a->GetBFactor(); diff --git a/modules/mol/base/src/residue_base.cc b/modules/mol/base/src/residue_base.cc index 7d15ad5f6fff00b62a223b8f41417f25d0703d8d..07950307d012a33735f6630a5d171d8e8ad8c7ce 100644 --- a/modules/mol/base/src/residue_base.cc +++ b/modules/mol/base/src/residue_base.cc @@ -104,6 +104,18 @@ void ResidueBase::SetChemClass(ChemClass cc) Impl()->SetChemClass(cc); } +void ResidueBase::SetChemType(ChemType ct) +{ + this->CheckValidity(); + Impl()->SetChemType(ct); +} + +ChemType ResidueBase::GetChemType() const +{ + this->CheckValidity(); + return Impl()->GetChemType(); +}; + SecStructure ResidueBase::GetSecStructure() const { this->CheckValidity(); diff --git a/modules/mol/base/src/residue_base.hh b/modules/mol/base/src/residue_base.hh index c994b9a3098b48479300c811d55583cc213ad16c..993683cb223aaf661704ce0c08c81d16f55f1bbf 100644 --- a/modules/mol/base/src/residue_base.hh +++ b/modules/mol/base/src/residue_base.hh @@ -27,6 +27,7 @@ #include <ost/mol/sec_structure.hh> #include <ost/mol/handle_type_fw.hh> #include <ost/mol/chem_class.hh> +#include <ost/mol/chem_type.hh> #include <ost/generic_property.hh> #include "property_id.hh" @@ -55,7 +56,12 @@ namespace ost { namespace mol { /// participate in a peptide bond. For nucleotides, the chemical class is either /// ChemClass::RNA_LINKING or ChemClass::DNA_LINKING. For unknown compounds the /// chemical class is ChemClass::UNKNOWN. -/// +/// +/// In addition, residues have a ChemType. A classification of all components into +/// nine categories (ions, non-canonical molecules, saccharised, nucleotides, +/// amino acids, co-enzymes, water coordinated ions, drugs, solvents) as obtained +/// from the PDB. +/// /// When loading an entity from file, the one-letter and chemical class of a /// residue are assigned by the \ref conop::Builder "default builder". class DLLEXPORT_OST_MOL ResidueBase: @@ -116,7 +122,12 @@ public: ChemClass GetChemClass() const; void SetChemClass(ChemClass cc); - + + /// \brief PDB ligand classification from component dictionary + ChemType GetChemType() const; + + void SetChemType(ChemType ct); + /// \brief Get secondary structure type. By default, the residue is in COIL /// conformation. SecStructure GetSecStructure() const; diff --git a/modules/mol/base/src/residue_prop.hh b/modules/mol/base/src/residue_prop.hh index 19bccc98e7e39e4f27c2001feb7efe58ceaf3fbe..e86eef5f11b16ba4eed55153e0cb38901faedd1e 100644 --- a/modules/mol/base/src/residue_prop.hh +++ b/modules/mol/base/src/residue_prop.hh @@ -28,9 +28,10 @@ namespace ost { namespace mol { class DLLEXPORT ResNum: private boost::additive<ResNum, int, + boost::additive<ResNum, boost::totally_ordered<ResNum, boost::totally_ordered<ResNum, int, - boost::unit_steppable<ResNum> > > > + boost::unit_steppable<ResNum> > > > > { public: ResNum(int n): @@ -74,7 +75,7 @@ public: num_-=r.num_; return num_; } - + ResNum& operator++() { ++num_; diff --git a/modules/mol/base/src/torsion_handle.cc b/modules/mol/base/src/torsion_handle.cc index c4bac5ff1455e70cf4ba5f3ba51c650d9cea3334..2830bc8211ef30477693f3610b76b46fdf79d27e 100644 --- a/modules/mol/base/src/torsion_handle.cc +++ b/modules/mol/base/src/torsion_handle.cc @@ -95,18 +95,6 @@ Real TorsionHandle::GetAngle() const this->CheckValidity(); return impl_->GetAngle(); } - -void TorsionHandle::SetAngle(Real a, bool up) -{ - this->CheckValidity(); - impl_->SetAngle(a, up); -} - -void TorsionHandle::RotateAngle(Real angle, bool up) -{ - this->CheckValidity(); - impl_->RotateAngle(angle, up); -} void TorsionHandle::CheckValidity() const { if (!impl_) diff --git a/modules/mol/base/src/torsion_handle.hh b/modules/mol/base/src/torsion_handle.hh index 856cd67e731983ee898213101d52764b214ddb07..06f7e7bf0eb7283318617f8fd0a4f222718f87ad 100644 --- a/modules/mol/base/src/torsion_handle.hh +++ b/modules/mol/base/src/torsion_handle.hh @@ -87,18 +87,6 @@ public: /// \brief get position, i.e midpoint between the second and third atom (original coordinates) geom::Vec3 GetOriginalPos() const; - /// \brief set absolute torsion angle - /// - /// All connectors at the third atom (A3) will be adjusted accordingly. If - /// you only want to adjust the bond between A3 and A4, and leave the other - /// bonds untouched, use the ost::SetDihedralAngle() function - /// - /// \sa RotateAngle - void SetAngle(Real a, bool up=true); - - /// relative rotation, either upstream or downstream - void RotateAngle(Real angle, bool up=true); - impl::TorsionImplP& Impl() { return impl_; } diff --git a/modules/mol/base/src/transform.cc b/modules/mol/base/src/transform.cc index ffee262dec1767ac26e6645ead08fb3d8bd3acf6..c1ffbff6b8a34bf6016d01fba72deeba8a2f4fdb 100644 --- a/modules/mol/base/src/transform.cc +++ b/modules/mol/base/src/transform.cc @@ -16,9 +16,12 @@ // along with this library; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA //------------------------------------------------------------------------------ + +#include <ost/config.hh> +#if(OST_INFO_ENABLED) #include <ost/info/info.hh> #include <ost/info/geom_info_conversion.hh> - +#endif #include "transform.hh" namespace ost { @@ -193,6 +196,7 @@ void Transform::update_tm() ttm_ = Transpose(tm_); } +#if(OST_INFO_ENABLED) Transform TransformFromInfo(const info::InfoGroup& group) { if (!group.HasItem("center")) { @@ -222,5 +226,6 @@ void TransformToInfo(const Transform& transform, info::InfoGroup& group) info::InfoGroup rot=group.CreateGroup("rotation"); info::Mat3ToInfo(transform.GetRot(), rot); } +#endif }} // ns diff --git a/modules/mol/base/src/transform.hh b/modules/mol/base/src/transform.hh index 5c9acd27605bbff805b40eaac297c83219cd5582..1ed33135e1ca1287f0e2c9debc151aeacca069cc 100644 --- a/modules/mol/base/src/transform.hh +++ b/modules/mol/base/src/transform.hh @@ -23,8 +23,11 @@ Author: Ansgar Philippsen */ +#include <ost/config.hh> #include <ost/geom/geom.hh> +#if(OST_INFO_ENABLED) #include <ost/info/info_fw.hh> +#endif #include <ost/mol/module_config.hh> namespace ost { namespace mol { @@ -81,6 +84,7 @@ private: void update_tm(); }; +#if(OST_INFO_ENABLED) /// \brief read transformation from info group /// \relates Transform Transform DLLEXPORT_OST_MOL TransformFromInfo(const info::InfoGroup& group); @@ -88,6 +92,7 @@ Transform DLLEXPORT_OST_MOL TransformFromInfo(const info::InfoGroup& group); /// \relates Transform void DLLEXPORT_OST_MOL TransformToInfo(const Transform& transform, info::InfoGroup& group); +#endif }} // ns #endif diff --git a/modules/mol/base/src/view_op.hh b/modules/mol/base/src/view_op.hh index b673f160c30ef63e0c9ea46ce3f78b3bce160262..1774b289dc7689166f075500f2ee3c96026e3a35 100644 --- a/modules/mol/base/src/view_op.hh +++ b/modules/mol/base/src/view_op.hh @@ -86,7 +86,8 @@ CompareViews(const EntityView& view1, const EntityView& view2); /// /// \param view is the view to be converted to a handle /// \param include_exlusive_atoms if true, atoms that are part of an exclusive -/// bond will also be included in the new entity handle. +/// bond (only one bond partner is included in the view) will also be included +/// in the new entity handle. /// \param handle If invalid a new entity will be created. If valid, the atoms, /// residues, chains, bonds and torsions will be added to handle. This is /// useful to combine several entities into one. diff --git a/modules/mol/base/tests/test_chain.cc b/modules/mol/base/tests/test_chain.cc index a2bdda81f87a8fb3b703a5489b232e8bd0ae00eb..3b7bbd85b15bee45ec61832548dfc97541893257 100644 --- a/modules/mol/base/tests/test_chain.cc +++ b/modules/mol/base/tests/test_chain.cc @@ -202,4 +202,136 @@ BOOST_AUTO_TEST_CASE(rename_chain) BOOST_CHECK_EQUAL(eh.GetChainCount(), 2); } +BOOST_AUTO_TEST_CASE(chain_type) +{ + EntityHandle eh = CreateEntity(); + XCSEditor e = eh.EditXCS(); + ChainHandle ch1 = e.InsertChain("A"); + + // setting/ getting + BOOST_CHECK(ch1.GetType() == CHAINTYPE_UNKNOWN); + BOOST_CHECK(!ch1.IsPolymer()); + BOOST_CHECK(!ch1.IsPolysaccharide()); + BOOST_CHECK(!ch1.IsPolypeptide()); + BOOST_CHECK(!ch1.IsPolynucleotide()); + e.SetChainType(ch1, CHAINTYPE_POLY); + BOOST_CHECK(ch1.GetType() == CHAINTYPE_POLY); + BOOST_CHECK(ch1.IsPolymer()); + BOOST_CHECK(!ch1.IsPolysaccharide()); + BOOST_CHECK(!ch1.IsPolypeptide()); + BOOST_CHECK(!ch1.IsPolynucleotide()); + e.SetChainType(ch1, CHAINTYPE_NON_POLY); + BOOST_CHECK(ch1.GetType() == CHAINTYPE_NON_POLY); + BOOST_CHECK(!ch1.IsPolymer()); + BOOST_CHECK(!ch1.IsPolysaccharide()); + BOOST_CHECK(!ch1.IsPolypeptide()); + BOOST_CHECK(!ch1.IsPolynucleotide()); + e.SetChainType(ch1, CHAINTYPE_WATER); + BOOST_CHECK(ch1.GetType() == CHAINTYPE_WATER); + BOOST_CHECK(!ch1.IsPolymer()); + BOOST_CHECK(!ch1.IsPolysaccharide()); + BOOST_CHECK(!ch1.IsPolypeptide()); + BOOST_CHECK(!ch1.IsPolynucleotide()); + e.SetChainType(ch1, CHAINTYPE_POLY_PEPTIDE_D); + BOOST_CHECK(ch1.IsPolymer()); + BOOST_CHECK(!ch1.IsPolysaccharide()); + BOOST_CHECK(ch1.IsPolypeptide()); + BOOST_CHECK(!ch1.IsPolynucleotide()); + BOOST_CHECK(ch1.GetType() == CHAINTYPE_POLY_PEPTIDE_D); + e.SetChainType(ch1, CHAINTYPE_POLY_PEPTIDE_L); + BOOST_CHECK(ch1.IsPolymer()); + BOOST_CHECK(!ch1.IsPolysaccharide()); + BOOST_CHECK(ch1.IsPolypeptide()); + BOOST_CHECK(!ch1.IsPolynucleotide()); + BOOST_CHECK(ch1.GetType() == CHAINTYPE_POLY_PEPTIDE_L); + e.SetChainType(ch1, CHAINTYPE_POLY_DN); + BOOST_CHECK(ch1.IsPolymer()); + BOOST_CHECK(!ch1.IsPolysaccharide()); + BOOST_CHECK(!ch1.IsPolypeptide()); + BOOST_CHECK(ch1.IsPolynucleotide()); + BOOST_CHECK(ch1.GetType() == CHAINTYPE_POLY_DN); + e.SetChainType(ch1, CHAINTYPE_POLY_RN); + BOOST_CHECK(ch1.IsPolymer()); + BOOST_CHECK(!ch1.IsPolysaccharide()); + BOOST_CHECK(!ch1.IsPolypeptide()); + BOOST_CHECK(ch1.IsPolynucleotide()); + BOOST_CHECK(ch1.GetType() == CHAINTYPE_POLY_RN); + e.SetChainType(ch1, CHAINTYPE_POLY_SAC_D); + BOOST_CHECK(ch1.IsPolymer()); + BOOST_CHECK(ch1.IsPolysaccharide()); + BOOST_CHECK(!ch1.IsPolypeptide()); + BOOST_CHECK(!ch1.IsPolynucleotide()); + BOOST_CHECK(ch1.GetType() == CHAINTYPE_POLY_SAC_D); + e.SetChainType(ch1, CHAINTYPE_POLY_SAC_L); + BOOST_CHECK(ch1.IsPolymer()); + BOOST_CHECK(ch1.IsPolysaccharide()); + BOOST_CHECK(!ch1.IsPolypeptide()); + BOOST_CHECK(!ch1.IsPolynucleotide()); + BOOST_CHECK(ch1.GetType() == CHAINTYPE_POLY_SAC_L); + e.SetChainType(ch1, CHAINTYPE_POLY_DN_RN); + BOOST_CHECK(ch1.GetType() == CHAINTYPE_POLY_DN_RN); + BOOST_CHECK(ch1.IsPolymer()); + BOOST_CHECK(!ch1.IsPolysaccharide()); + BOOST_CHECK(!ch1.IsPolypeptide()); + BOOST_CHECK(ch1.IsPolynucleotide()); + e.SetChainType(ch1, CHAINTYPE_N_CHAINTYPES); + BOOST_CHECK(ch1.GetType() == CHAINTYPE_N_CHAINTYPES); + e.SetChainType(ch1, CHAINTYPE_UNKNOWN); + BOOST_CHECK(ch1.GetType() == CHAINTYPE_UNKNOWN); + + // string -> chain type + BOOST_CHECK(ChainTypeFromString("polymer") == CHAINTYPE_POLY); + BOOST_CHECK(ChainTypeFromString("non-polymer") == CHAINTYPE_NON_POLY); + BOOST_CHECK(ChainTypeFromString("water") == CHAINTYPE_WATER); + BOOST_CHECK(ChainTypeFromString("polypeptide(D)") == + CHAINTYPE_POLY_PEPTIDE_D); + BOOST_CHECK(ChainTypeFromString("polypeptide(L)") == + CHAINTYPE_POLY_PEPTIDE_L); + BOOST_CHECK(ChainTypeFromString("polydeoxyribonucleotide") == + CHAINTYPE_POLY_DN); + BOOST_CHECK(ChainTypeFromString("polyribonucleotide") == + CHAINTYPE_POLY_RN); + BOOST_CHECK(ChainTypeFromString("polysaccharide(D)") == + CHAINTYPE_POLY_SAC_D); + BOOST_CHECK(ChainTypeFromString("polysaccharide(L)") == + CHAINTYPE_POLY_SAC_L); + BOOST_CHECK(ChainTypeFromString( + "polydeoxyribonucleotide/polyribonucleotide hybrid") == + CHAINTYPE_POLY_DN_RN); + BOOST_CHECK(ChainTypeFromString("other") == CHAINTYPE_UNKNOWN); + BOOST_CHECK_THROW(ChainTypeFromString("supposed to fail"), + std::runtime_error); + + // chain type -> string + BOOST_CHECK(StringFromChainType(CHAINTYPE_POLY) == "polymer"); + BOOST_CHECK(StringFromChainType(CHAINTYPE_NON_POLY) == "non-polymer"); + BOOST_CHECK(StringFromChainType(CHAINTYPE_WATER) == "water"); + BOOST_CHECK(StringFromChainType(CHAINTYPE_POLY_PEPTIDE_D) == + "polypeptide(D)"); + BOOST_CHECK(StringFromChainType(CHAINTYPE_POLY_PEPTIDE_L) == + "polypeptide(L)"); + BOOST_CHECK(StringFromChainType(CHAINTYPE_POLY_DN) == + "polydeoxyribonucleotide"); + BOOST_CHECK(StringFromChainType(CHAINTYPE_POLY_RN) == "polyribonucleotide"); + BOOST_CHECK(StringFromChainType(CHAINTYPE_POLY_SAC_D) == + "polysaccharide(D)"); + BOOST_CHECK(StringFromChainType(CHAINTYPE_POLY_SAC_L) == + "polysaccharide(L)"); + BOOST_CHECK(StringFromChainType(CHAINTYPE_POLY_DN_RN) == + "polydeoxyribonucleotide/polyribonucleotide hybrid"); + BOOST_CHECK(StringFromChainType(CHAINTYPE_UNKNOWN) == "other"); + BOOST_CHECK_THROW(StringFromChainType(CHAINTYPE_N_CHAINTYPES), + std::runtime_error); +} + +BOOST_AUTO_TEST_CASE(chain_description) +{ + EntityHandle eh=CreateEntity(); + XCSEditor e = eh.EditXCS(); + ChainHandle ch1 = e.InsertChain("A"); + String description = "Very important information"; + e.SetChainDescription(ch1, description); + BOOST_CHECK(ch1.GetDescription() == description); +} + BOOST_AUTO_TEST_SUITE_END() diff --git a/modules/mol/base/tests/test_ics.cc b/modules/mol/base/tests/test_ics.cc index 8c26db5d96c1738e8454487366989ca1041255c1..4f84f6a78bf0882302f9d5edce87ed13656b6064 100644 --- a/modules/mol/base/tests/test_ics.cc +++ b/modules/mol/base/tests/test_ics.cc @@ -59,6 +59,37 @@ struct Structure { AtomHandle a5; }; +struct TorsionStructure { + TorsionStructure() + { + e=CreateEntity(); + ICSEditor editor=e.EditICS(); + c=editor.InsertChain("A"); + r=editor.AppendResidue(c, "TORSTIN"); + a1=editor.InsertAtom(r, "X1", geom::Vec3( 0.0, -1.0, 0.0)); + a2=editor.InsertAtom(r, "X2", geom::Vec3( 1.0, 0.0, 0.0)); + a3=editor.InsertAtom(r, "X3", geom::Vec3( 2.0, 0.0, 0.0)); + a4=editor.InsertAtom(r, "X4", geom::Vec3( 3.0, 1.0, 0.0)); + a5=editor.InsertAtom(r, "X5", geom::Vec3( 3.0, -1.0, 0.0)); + editor.Connect(a1, a2); + editor.Connect(a2, a3); + editor.Connect(a3, a4); + editor.Connect(a3, a5); + t1 = editor.AddTorsion("T1", a1, a2, a3, a4); + t2 = editor.AddTorsion("T2", a1, a2, a3, a5); + } + EntityHandle e; + ChainHandle c; + ResidueHandle r; + AtomHandle a1; + AtomHandle a2; + AtomHandle a3; + AtomHandle a4; + AtomHandle a5; + TorsionHandle t1; + TorsionHandle t2; +}; + const static Real EPSILON=0.000001; Real angle_xcs(AtomHandle a1, AtomHandle a2, AtomHandle a3) { @@ -72,6 +103,118 @@ bool test_angle(Real a, Real e) { BOOST_AUTO_TEST_SUITE( mol_base ) +BOOST_AUTO_TEST_CASE(ics_update_icsbondlength) +{ + TorsionStructure s; + mol::BondHandle bond = s.a2.FindBondToAtom(s.a3); + BOOST_CHECK_CLOSE(bond.GetLength(), Real(1.0), Real(EPSILON)); +} + +BOOST_AUTO_TEST_CASE(ics_settorsion_unbuffered) +{ + Real eps = 0.0001; + TorsionStructure s; + ICSEditor e = s.e.EditICS(mol::UNBUFFERED_EDIT); + BOOST_CHECK_CLOSE(s.t1.GetAngle(), Real(M_PI), Real(eps)); + BOOST_CHECK_SMALL(s.t2.GetAngle(), eps); + e.SetTorsionAngle(s.t1,0); + BOOST_CHECK_SMALL(s.t1.GetAngle(), eps); + BOOST_CHECK_CLOSE(s.t2.GetAngle(), Real(M_PI), Real(eps)); + e.SetTorsionAngle(s.t2,M_PI/4); + BOOST_CHECK_CLOSE(s.t2.GetAngle(), Real(M_PI/4), Real(eps)); + BOOST_CHECK_CLOSE(s.t1.GetAngle(), Real(-M_PI+M_PI/4), Real(eps)); + e.SetTorsionAngle(s.t1,-M_PI/4); + BOOST_CHECK_CLOSE(s.t1.GetAngle(), Real(-M_PI/4), Real(eps)); + BOOST_CHECK_CLOSE(s.t2.GetAngle(), Real(3/4.*M_PI), Real(eps)); + e.RotateTorsionAngle(s.t1, M_PI/4); + BOOST_CHECK_SMALL(s.t1.GetAngle(), eps); + BOOST_CHECK_CLOSE(std::abs(s.t2.GetAngle()), Real(M_PI), Real(eps)); +} + +BOOST_AUTO_TEST_CASE(ics_settorsion_buffered) +{ + Real eps = 0.0001; + TorsionStructure s; + ICSEditor e = s.e.EditICS(mol::BUFFERED_EDIT); + BOOST_CHECK_CLOSE(s.t1.GetAngle(), Real(M_PI), Real(eps)); + BOOST_CHECK_SMALL(s.t2.GetAngle(), eps); + e.SetTorsionAngle(s.t1,0); + BOOST_CHECK_SMALL(s.t1.GetAngle(), eps); + BOOST_CHECK_CLOSE(s.t2.GetAngle(), Real(M_PI), Real(eps)); + e.SetTorsionAngle(s.t2,M_PI/4); + BOOST_CHECK_CLOSE(s.t2.GetAngle(), Real(M_PI/4), Real(eps)); + BOOST_CHECK_CLOSE(s.t1.GetAngle(), Real(-M_PI+M_PI/4), Real(eps)); + e.SetTorsionAngle(s.t1,-M_PI/4); + BOOST_CHECK_CLOSE(s.t1.GetAngle(), Real(-M_PI/4), Real(eps)); + BOOST_CHECK_CLOSE(s.t2.GetAngle(), Real(3/4.*M_PI), Real(eps)); + e.RotateTorsionAngle(s.t1, M_PI/4); + BOOST_CHECK_SMALL(s.t1.GetAngle(), eps); + BOOST_CHECK_CLOSE(std::abs(s.t2.GetAngle()), Real(M_PI), Real(eps)); +} + +BOOST_AUTO_TEST_CASE(ics_settorsion_unbuffered_update_others) +{ + Real eps = 0.0001; + TorsionStructure s; + ICSEditor e = s.e.EditICS(mol::UNBUFFERED_EDIT); + BOOST_CHECK_CLOSE(s.t1.GetAngle(), Real(M_PI), Real(eps)); + BOOST_CHECK_SMALL(s.t2.GetAngle(), eps); + e.SetTorsionAngle(s.t1,0,false); + BOOST_CHECK_SMALL(s.t1.GetAngle(), eps); + BOOST_CHECK_SMALL(s.t2.GetAngle(), eps); + e.SetTorsionAngle(s.t2,M_PI/4,false); + BOOST_CHECK_CLOSE(s.t2.GetAngle(), Real(M_PI/4), Real(eps)); + BOOST_CHECK_SMALL(s.t1.GetAngle(), eps); + e.SetTorsionAngle(s.t1,-M_PI/4,false); + BOOST_CHECK_CLOSE(s.t1.GetAngle(), Real(-M_PI/4), Real(eps)); + BOOST_CHECK_CLOSE(s.t2.GetAngle(), Real(M_PI/4), Real(eps)); + e.RotateTorsionAngle(s.t1, M_PI/4,false); + BOOST_CHECK_SMALL(s.t1.GetAngle(), eps); + BOOST_CHECK_CLOSE(s.t2.GetAngle(), Real(M_PI/4), Real(eps)); +} + +BOOST_AUTO_TEST_CASE(ics_settorsion_buffered_update_others) +{ + Real eps = 0.0001; + TorsionStructure s; + ICSEditor e = s.e.EditICS(mol::BUFFERED_EDIT); + BOOST_CHECK_CLOSE(s.t1.GetAngle(), Real(M_PI), Real(eps)); + BOOST_CHECK_SMALL(s.t2.GetAngle(), eps); + e.SetTorsionAngle(s.t1,0,false); + BOOST_CHECK_SMALL(s.t1.GetAngle(), eps); + BOOST_CHECK_SMALL(s.t2.GetAngle(), eps); + e.SetTorsionAngle(s.t2,M_PI/4,false); + BOOST_CHECK_CLOSE(s.t2.GetAngle(), Real(M_PI/4), Real(eps)); + BOOST_CHECK_SMALL(s.t1.GetAngle(), eps); + e.SetTorsionAngle(s.t1,-M_PI/4,false); + BOOST_CHECK_CLOSE(s.t1.GetAngle(), Real(-M_PI/4), Real(eps)); + BOOST_CHECK_CLOSE(s.t2.GetAngle(), Real(M_PI/4), Real(eps)); + e.RotateTorsionAngle(s.t1, M_PI/4,false); + BOOST_CHECK_SMALL(s.t1.GetAngle(), eps); + BOOST_CHECK_CLOSE(s.t2.GetAngle(), Real(M_PI/4), Real(eps)); +} + +BOOST_AUTO_TEST_CASE(ics_settorsion_linear_unbuffered) +{ + Real eps = 0.0001; + TorsionStructure s; + ICSEditor e = s.e.EditICS(mol::UNBUFFERED_EDIT); + e.SetAngle(s.a2,s.a3,s.a4,M_PI); + BOOST_CHECK_SMALL(s.t1.GetAngle(), eps); + BOOST_CHECK_SMALL(s.t2.GetAngle(), eps); + e.SetTorsionAngle(s.t1,0); + BOOST_CHECK_SMALL(s.t1.GetAngle(), eps); + BOOST_CHECK_SMALL(s.t2.GetAngle(), eps); + e.SetTorsionAngle(s.t2,M_PI/4); + BOOST_CHECK_SMALL(s.t1.GetAngle(), eps); + BOOST_CHECK_CLOSE(s.t2.GetAngle(), Real(M_PI/4), Real(eps)); + e.SetTorsionAngle(s.t1,-M_PI/4); + BOOST_CHECK_SMALL(s.t1.GetAngle(), eps); + BOOST_CHECK_SMALL(s.t2.GetAngle(), eps); + e.RotateTorsionAngle(s.t1, M_PI/4); + BOOST_CHECK_SMALL(s.t1.GetAngle(), eps); + BOOST_CHECK_CLOSE(s.t2.GetAngle(), Real(M_PI/4), Real(eps)); +} BOOST_AUTO_TEST_CASE(ics_angle_trivia) { @@ -147,4 +290,4 @@ BOOST_AUTO_TEST_CASE(ics_get_angle) << " found"); } -BOOST_AUTO_TEST_SUITE_END() \ No newline at end of file +BOOST_AUTO_TEST_SUITE_END() diff --git a/modules/mol/base/tests/test_numpy.py b/modules/mol/base/tests/test_numpy.py index 14496c0c0ef2d3cb3632ebbb620890d4a9e126a0..217ed89dd7adb6380b6fea22719e49f310b2c2cb 100644 --- a/modules/mol/base/tests/test_numpy.py +++ b/modules/mol/base/tests/test_numpy.py @@ -1,17 +1,25 @@ import unittest -from ost import * +if __name__== '__main__': + import sys + sys.path.insert(0,"../../../../stage/lib64/openstructure/") + sys.path.insert(0,"../../../../stage/lib/openstructure/") + +import ost -has_numpy=True -try: - import numpy -except ImportError: +if ost.WITH_NUMPY: + has_numpy=True + try: + import numpy + except ImportError, e: + has_numpy=False +else: has_numpy=False def v2v(v): - return geom.Vec3(float(v[0]),float(v[1]),float(v[2])) + return ost.geom.Vec3(float(v[0]),float(v[1]),float(v[2])) def dd(v1,v2): - return geom.Distance(v1,v2)<1e-8 + return ost.geom.Distance(v1,v2)<1e-8 class TestNumpy(unittest.TestCase): def setUp(self): @@ -20,46 +28,46 @@ class TestNumpy(unittest.TestCase): def test_(self): if not has_numpy: return - entity=mol.CreateEntity() + entity=ost.mol.CreateEntity() ed=entity.EditXCS() ch=ed.InsertChain("X") re=ed.AppendResidue(ch,"ALA") - a0=ed.InsertAtom(re,"A",geom.Vec3(0,0,0)) + a0=ed.InsertAtom(re,"A",ost.geom.Vec3(0,0,0)) self.assertEqual(a0.GetIndex(),0) - a1=ed.InsertAtom(re,"B",geom.Vec3(1,0,0)) + a1=ed.InsertAtom(re,"B",ost.geom.Vec3(1,0,0)) self.assertEqual(a1.GetIndex(),1) - a2=ed.InsertAtom(re,"C",geom.Vec3(2,0,0)) + a2=ed.InsertAtom(re,"C",ost.geom.Vec3(2,0,0)) self.assertEqual(a2.GetIndex(),2) - a3=ed.InsertAtom(re,"D",geom.Vec3(3,0,0)) + a3=ed.InsertAtom(re,"D",ost.geom.Vec3(3,0,0)) self.assertEqual(a3.GetIndex(),3) - self.assertTrue(dd(a0.pos,geom.Vec3(0,0,0))) - self.assertTrue(dd(a1.pos,geom.Vec3(1,0,0))) - self.assertTrue(dd(a2.pos,geom.Vec3(2,0,0))) - self.assertTrue(dd(a3.pos,geom.Vec3(3,0,0))) + self.assertTrue(dd(a0.pos,ost.geom.Vec3(0,0,0))) + self.assertTrue(dd(a1.pos,ost.geom.Vec3(1,0,0))) + self.assertTrue(dd(a2.pos,ost.geom.Vec3(2,0,0))) + self.assertTrue(dd(a3.pos,ost.geom.Vec3(3,0,0))) ed.SetAtomTransformedPos(entity.GetAtomList(), numpy.array([[0,1,0],[0,2,0],[0,3,0],[0,4,0]], dtype=numpy.float32)) - self.assertTrue(dd(a0.pos,geom.Vec3(0,1,0))) - self.assertTrue(dd(a1.pos,geom.Vec3(0,2,0))) - self.assertTrue(dd(a2.pos,geom.Vec3(0,3,0))) - self.assertTrue(dd(a3.pos,geom.Vec3(0,4,0))) + self.assertTrue(dd(a0.pos,ost.geom.Vec3(0,1,0))) + self.assertTrue(dd(a1.pos,ost.geom.Vec3(0,2,0))) + self.assertTrue(dd(a2.pos,ost.geom.Vec3(0,3,0))) + self.assertTrue(dd(a3.pos,ost.geom.Vec3(0,4,0))) na=entity.positions - self.assertTrue(dd(v2v(na[0]),geom.Vec3(0,1,0))) - self.assertTrue(dd(v2v(na[1]),geom.Vec3(0,2,0))) - self.assertTrue(dd(v2v(na[2]),geom.Vec3(0,3,0))) - self.assertTrue(dd(v2v(na[3]),geom.Vec3(0,4,0))) + self.assertTrue(dd(v2v(na[0]),ost.geom.Vec3(0,1,0))) + self.assertTrue(dd(v2v(na[1]),ost.geom.Vec3(0,2,0))) + self.assertTrue(dd(v2v(na[2]),ost.geom.Vec3(0,3,0))) + self.assertTrue(dd(v2v(na[3]),ost.geom.Vec3(0,4,0))) ed.SetAtomTransformedPos([3,99,2], numpy.array([[0,0,-3],[-1,-1,-1],[0,0,-2]], dtype=numpy.float32)) - self.assertTrue(dd(a0.pos,geom.Vec3(0,1,0))) - self.assertTrue(dd(a1.pos,geom.Vec3(0,2,0))) - self.assertTrue(dd(a2.pos,geom.Vec3(0,0,-2))) - self.assertTrue(dd(a3.pos,geom.Vec3(0,0,-3))) + self.assertTrue(dd(a0.pos,ost.geom.Vec3(0,1,0))) + self.assertTrue(dd(a1.pos,ost.geom.Vec3(0,2,0))) + self.assertTrue(dd(a2.pos,ost.geom.Vec3(0,0,-2))) + self.assertTrue(dd(a3.pos,ost.geom.Vec3(0,0,-3))) if __name__== '__main__': unittest.main() diff --git a/modules/seq/alg/doc/seqalg.rst b/modules/seq/alg/doc/seqalg.rst index 79e6ca62bb3d97082b37fcbb9afee719e12b276f..02f74c4f78015926f5faae38c54d5a4c72f24218 100644 --- a/modules/seq/alg/doc/seqalg.rst +++ b/modules/seq/alg/doc/seqalg.rst @@ -35,11 +35,32 @@ considered as aligned. There is no information in the pairwise alignment to guide the merging, the result is undefined. +.. autofunction:: ValidateSEQRESAlignment + .. autofunction:: AlignToSEQRES .. autofunction:: AlignmentFromChainView +.. function:: Conservation(aln, assign=true, prop_name="cons", ignore_gap=false) + Calculates conservation scores for each column in the alignment, according to + the ConSurf method (Armon et al., J. Mol. Biol. (2001) 307, 447-463). + + The conservation score is a value between 0 and 1. The bigger the number + the more conserved the aligned residues are. + + :param aln: An alignment handle + :type aln: :class:`~ost.seq.AlignmentHandle` + :param assign: If true, the conservation scores are assigned to attached + residues. The name of the property can be changed with the prop_name + parameter. Useful when coloring entities based on sequence conservation. + :param prop_name: The property name for assigning the conservation to + attached residues. Defaults to 'cons'. + :param ignore_gap: If true, the dissimilarity between two gaps is increased to + 6.0 instead of 0.5 as defined in the original version. Without this, a + stretch where in the alignment there is only one sequence which is + aligned to only gaps, is considered highly conserved (depending on the + number of gap sequences). .. function:: LocalAlign(seq1, seq2, subst_weight, gap_open=-5, gap_ext=-2) diff --git a/modules/seq/alg/pymod/CMakeLists.txt b/modules/seq/alg/pymod/CMakeLists.txt index dfe07488ea145a451a10f6bb6a47facbc9b3cf40..0821b510a21cb8ad806b21a958a3592f24f6679f 100644 --- a/modules/seq/alg/pymod/CMakeLists.txt +++ b/modules/seq/alg/pymod/CMakeLists.txt @@ -1,7 +1,8 @@ set(OST_SEQ_ALG_PYMOD_SOURCES wrap_seq_alg.cc ) - -pymod(NAME seq_alg OUTPUT_DIR ost/seq/alg - CPP ${OST_SEQ_ALG_PYMOD_SOURCES} - PY __init__.py mat.py renumber.py) +if (NOT ENABLE_STATIC) + pymod(NAME seq_alg OUTPUT_DIR ost/seq/alg + CPP ${OST_SEQ_ALG_PYMOD_SOURCES} + PY __init__.py mat.py renumber.py) +endif() diff --git a/modules/seq/alg/pymod/__init__.py b/modules/seq/alg/pymod/__init__.py index 24e79daac0e896b25b08b92caf51c3a0a9c46c6f..63157ea31e84892007da778d3ac09c00c51c52df 100644 --- a/modules/seq/alg/pymod/__init__.py +++ b/modules/seq/alg/pymod/__init__.py @@ -1,7 +1,61 @@ from _ost_seq_alg import * from ost.seq.alg.mat import * -def AlignToSEQRES(chain, seqres): +def ValidateSEQRESAlignment(aln, chain=None): + """ + Checks a sequence aligned to a SEQRES sequence to be free of strand breaks. + Residues divided by gaps are not considered as breakage but may also not be + connected. + + :param aln: Alignment + :type aln: :class:`~ost.seq.AlignmentHandle` + :param chain: Source of the sequence + :type chain: :class:`~ost.mol.ChainHandle` + + :returns: True if all residues (beside gaped ones) are connected, False + otherwise. + """ + from ost import LogWarning + from ost import seq + from ost import mol + if aln.GetCount() != 2: + raise ValueError('Alignment contains more than 2 sequences!') + sequence = aln.GetSequence(1) + if len(sequence) == 0: + return True + if chain == None: + if sequence.HasAttachedView() == False: + raise ValueError("Alignment is missing an attached chain view.") + chain = sequence.GetAttachedView() + residues = chain.residues + # eat up all beginning gaps + j = 1 + for s in sequence: + if s != '-': + break + j += 1; + l = sequence[j-1] + i = 0 + # run over sequence & alignment + for s in sequence[j:]: + if s != '-': + i += 1 + r1 = residues[i-1] + r2 = residues[i] + if r1.one_letter_code=='?' or r2.one_letter_code=='?': + continue + if l != '-': + if not mol.InSequence(r1.handle, r2.handle): + LogWarning('%s and %s are not connected by peptide bond' % (str(r1), str(r2))) + return False + else: + if mol.InSequence(r1.handle, r2.handle): + LogWarning('%s and %s are connected by peptide bond' % (str(r1), str(r2))) + return False + l = s + return True + +def AlignToSEQRES(chain, seqres, try_resnum_first=False, validate=True): """ Aligns the residues of chain to the SEQRES sequence, inserting gaps where needed. The function uses the connectivity of the protein backbone to find @@ -9,35 +63,73 @@ def AlignToSEQRES(chain, seqres): sequence. All the non-ligand, peptide-linking residues of the chain must be listed in - SEQRES. If there are any additional residues in the chain, the function raises - a ValueError. - + SEQRES. If there are any additional residues in the chain, the function + raises a ValueError. + + If 'try_resnum_first' is set, building the alignment following residue numbers + is tried first. + + If 'validate' is set (default), the alignment is checked using + :func:`~ost.seq.alg.ValidateSEQRESAlignment`. + + :param chain: Source of the sequence + :type chain: :class:`~ost.mol.ChainHandle` + :param seqres: SEQRES sequence + :type seqres: :class:`str` + :param try_resnum_first: Try to align by residue number + :type try_resnum_first: :class:`bool` + :param validate: Validate alignment by + :func:`~ost.seq.alg.ValidateSEQRESAlignment` + :type validate: :class:`bool` + :returns: The alignment of the residues in the chain and the SEQRES entries. :rtype: :class:`~ost.seq.AlignmentHandle` """ + + def IsEqual(olc1, olc2): + return olc1 in ('X', '?') or olc2 in ('X', '?') or olc1 == olc2 + from ost import seq from ost import mol - view=chain.Select('ligand=false and peptide=true') + from ost import LogWarning + view=chain residues=view.residues if len(residues)==0: return seq.CreateAlignment() - fragments=[residues[0].one_letter_code] - for r1, r2 in zip(residues[:-2], residues[1:]): - if not mol.InSequence(r1.handle, r2.handle): - fragments.append('') - fragments[-1]+=r2.one_letter_code - ss=str(seqres) - pos=0 - aln_seq='' - for frag in fragments: - new_pos=ss.find(frag, pos) - if new_pos==-1: - raise ValueError('"%s" is not a substring of "%s"' % (frag, ss)) - aln_seq+='-'*(new_pos-pos)+frag - pos=new_pos+len(frag) - aln_seq+='-'*(len(seqres)-len(aln_seq)) - return seq.CreateAlignment(seq.CreateSequence('SEQRES', str(seqres)), - seq.CreateSequence('atoms', aln_seq)) + if try_resnum_first: + aln_seq = seq.CreateSequence('atoms', '-'*len(seqres)) + for r1 in residues: + if r1.number.num <= len(seqres) and r1.number.num > 0: + if IsEqual(seqres[r1.number.num - 1], r1.one_letter_code): + aln_seq[r1.number.num - 1] = r1.one_letter_code + else: + LogWarning('Sequence mismatch: chain has "' + r1.one_letter_code + + '", while SEQRES is "' + seqres[r1.number.num - 1] + + '" at the corresponding position.') + try_resnum_first = False + break + if not try_resnum_first: + fragments=[residues[0].one_letter_code] + for r1, r2 in zip(residues[:-1], residues[1:]): + if not mol.InSequence(r1.handle, r2.handle): + fragments.append('') + fragments[-1]+=r2.one_letter_code + ss=str(seqres) + pos=0 + aln_seq='' + for frag in fragments: + new_pos=ss.find(frag, pos) + if new_pos==-1: + raise ValueError('"%s" is not a substring of "%s"' % (frag, ss)) + aln_seq+='-'*(new_pos-pos)+frag + pos=new_pos+len(frag) + aln_seq = seq.CreateSequence('atoms', + aln_seq+('-'*(len(seqres)-len(aln_seq)))) + alignment = seq.CreateAlignment(seq.CreateSequence('SEQRES', str(seqres)), + aln_seq) + if validate and not ValidateSEQRESAlignment(alignment, view): + raise ValueError("SEQRES cannot be aligned with its corresponding chain.") + return alignment def AlignmentFromChainView(chain, handle_seq_name='handle', diff --git a/modules/seq/alg/pymod/wrap_seq_alg.cc b/modules/seq/alg/pymod/wrap_seq_alg.cc index 5c1fba67787786393921b1c5710be59ba6079381..9239d1ec3d2e759729cfb1bcde0fb9005e52ded1 100644 --- a/modules/seq/alg/pymod/wrap_seq_alg.cc +++ b/modules/seq/alg/pymod/wrap_seq_alg.cc @@ -53,7 +53,7 @@ BOOST_PYTHON_MODULE(_ost_seq_alg) .def("SetWeight", &SubstWeightMatrix::SetWeight) ; def("MergePairwiseAlignments", &MergePairwiseAlignments); - def("Conservation", &Conservation, (arg("assign")=true, arg("prop_name")="cons")); + def("Conservation", &Conservation, (arg("assign")=true, arg("prop_name")="cons", arg("ignore_gap")=false)); def("LocalAlign", &LocalAlign, (arg("seq1"), arg("seq2"),arg("subst_weight"), arg("gap_open")=-5, arg("gap_ext")=-2)); def("GlobalAlign", &GlobalAlign,(arg("seq1"),arg("seq2"),arg("subst_weight"), diff --git a/modules/seq/alg/src/CMakeLists.txt b/modules/seq/alg/src/CMakeLists.txt index fe23aa52cce246216e0aeb8b10c578f795e27881..ccffcacf464cc22d85f62a6d5190067b76622cb7 100644 --- a/modules/seq/alg/src/CMakeLists.txt +++ b/modules/seq/alg/src/CMakeLists.txt @@ -16,10 +16,13 @@ local_align.cc global_align.cc sequence_identity.cc ins_del.cc -subst_weight_matrix.cc conservation.cc ) +if (ENABLE_INFO) + list (APPEND OST_SEQ_ALG_SOURCES subst_weight_matrix.cc) +endif() + module(NAME seq_alg HEADER_OUTPUT_DIR ost/seq/alg SOURCES ${OST_SEQ_ALG_SOURCES} HEADERS ${OST_SEQ_ALG_HEADERS} DEPENDS_ON ost_seq) diff --git a/modules/seq/alg/src/conservation.cc b/modules/seq/alg/src/conservation.cc index 2b5bf3481c22a5801176b1aa1f8ff227df1f7dc4..e80077efd254deead27d156cd556d0da2f90721f 100644 --- a/modules/seq/alg/src/conservation.cc +++ b/modules/seq/alg/src/conservation.cc @@ -75,7 +75,7 @@ static float CHEM_DISSIM[][24]={ -1.00,-1.00,-1.00,-1.00,-1.00,-1.00,-1.00,-1.00,-1.00,-1.00,-1.00} }; -float PhysicoChemicalDissim(char c1, char c2) +float PhysicoChemicalDissim(char c1, char c2, bool ignore_gap) { static int indices[]={2, 23, 0, 9, 7, 17, 3, 10, 15, -1, 11, 14, 16, 8, -1, 1, 6, 12, 4, 5, @@ -94,12 +94,15 @@ float PhysicoChemicalDissim(char c1, char c2) s=CHEM_DISSIM[idx_b][idx_a-idx_b]; else s=CHEM_DISSIM[idx_a][idx_b-idx_a]; + if (ignore_gap && idx_a==20 && idx_b==20) { + s=6.0; + } assert(s>=0.0); return s; } std::vector<Real> Conservation(const AlignmentHandle& aln, bool assign, - const String& prop) + const String& prop, bool ignore_gap) { std::vector<Real> cons(aln.GetLength(), 0.0); int comb=(aln.GetCount()*(aln.GetCount()-1))/2; @@ -108,7 +111,7 @@ std::vector<Real> Conservation(const AlignmentHandle& aln, bool assign, AlignedColumn c=aln[col]; for (int i=0; i<aln.GetCount(); ++i) { for (int j=i+1; j<aln.GetCount(); ++j) { - score+=PhysicoChemicalDissim(c[i], c[j]); + score+=PhysicoChemicalDissim(c[i], c[j], ignore_gap); } } score=1.0-score/(6.0*comb); diff --git a/modules/seq/alg/src/conservation.hh b/modules/seq/alg/src/conservation.hh index 8e4146ee790f68056ad55e1b6efa62466c5e3135..651b5bdd150348ef812bf839e37e458e2fc2eb86 100644 --- a/modules/seq/alg/src/conservation.hh +++ b/modules/seq/alg/src/conservation.hh @@ -35,9 +35,15 @@ namespace ost { namespace seq { namespace alg { /// parameter. Useful when coloring entities based on sequence conservation. /// \p prop_name The property name for assigning the conservation to /// attached residues. Defaults to 'cons'. +/// \p ignore_gap If true, the dissimilarity between two gaps is increased to +/// 6.0 instead of 0.5 as defined in the original version. Without this, a +/// stretch where in the alignment there is only one sequence which is +/// aligned to only gaps, is considered highly conserved (depending on the +/// number of gap sequences). /// std::vector<Real> DLLEXPORT_OST_SEQ_ALG Conservation(const AlignmentHandle& aln, bool assign=true, - const String& prop_name="cons"); + const String& prop_name="cons", + bool ignore_gap=false); }}} diff --git a/modules/seq/alg/src/merge_pairwise_alignments.cc b/modules/seq/alg/src/merge_pairwise_alignments.cc index 9d60859a07b99b7dda1724f54306f91a7605690b..c522869cfa50c64a6609d59fb856b733aa6288cf 100644 --- a/modules/seq/alg/src/merge_pairwise_alignments.cc +++ b/modules/seq/alg/src/merge_pairwise_alignments.cc @@ -87,7 +87,8 @@ SequenceHandle shift_reference(const ConstSequenceHandle& ref_seq, } new_sequence << ref_str.substr(last); SequenceHandle s=CreateSequence(ref_seq.GetName(), - new_sequence.str()); + new_sequence.str(), + ref_seq.GetRole()); if (ref_seq.HasAttachedView()) s.AttachView(ref_seq.GetAttachedView()); s.SetOffset(ref_seq.GetOffset()); @@ -122,7 +123,8 @@ SequenceHandle realign_sequence(const AlignmentHandle& aln, } new_sequence << s2.GetOneLetterCode(i); } - SequenceHandle s=CreateSequence(s2.GetName(), new_sequence.str()); + SequenceHandle s=CreateSequence(s2.GetName(), new_sequence.str(), + s2.GetRole()); if (s2.HasAttachedView()) s.AttachView(s2.GetAttachedView()); s.SetOffset(s2.GetOffset()); diff --git a/modules/seq/alg/src/subst_weight_matrix.hh b/modules/seq/alg/src/subst_weight_matrix.hh index f310893ab6a002a830d432a0b07d0547fbb3943d..97f0ef825cb45dda7e2572558b2917498e87a353 100644 --- a/modules/seq/alg/src/subst_weight_matrix.hh +++ b/modules/seq/alg/src/subst_weight_matrix.hh @@ -21,7 +21,11 @@ #include <ctype.h> #include <string.h> +#include <boost/shared_ptr.hpp> +#include <ost/config.hh> +#if(OST_INFO_ENABLED) #include <ost/info/info_fw.hh> +#endif #include <ost/seq/alg/module_config.hh> /* @@ -86,12 +90,14 @@ private: WeightType weights_[ALPHABET_SIZE*ALPHABET_SIZE]; }; +#if(OST_INFO_ENABLED) SubstWeightMatrixPtr DLLEXPORT_OST_SEQ_ALG SubstWeightMatrixFromInfo(const info::InfoGroup& group); void DLLEXPORT_OST_SEQ_ALG SubstWeightMatrixToInfo(const SubstWeightMatrixPtr& subst_mat, info::InfoGroup& group); +#endif }}} diff --git a/modules/seq/alg/tests/CMakeLists.txt b/modules/seq/alg/tests/CMakeLists.txt index 3a26d1d67c0f00c64b810a752eb38f7cfd174723..76b599790fd34347fcff9b518c3c72b8fb85811e 100644 --- a/modules/seq/alg/tests/CMakeLists.txt +++ b/modules/seq/alg/tests/CMakeLists.txt @@ -6,6 +6,7 @@ set(OST_SEQ_ALG_UNIT_TESTS test_local_align.py test_global_align.py test_weight_matrix.py + test_aligntoseqres.py ) ost_unittest(MODULE seq_alg SOURCES "${OST_SEQ_ALG_UNIT_TESTS}") diff --git a/modules/seq/alg/tests/test_aligntoseqres.py b/modules/seq/alg/tests/test_aligntoseqres.py new file mode 100644 index 0000000000000000000000000000000000000000..0f4b8ceaa9bdbdf61bec7a390127b6ebc6687f89 --- /dev/null +++ b/modules/seq/alg/tests/test_aligntoseqres.py @@ -0,0 +1,72 @@ +import unittest +from ost import * +from ost import settings +from ost import seq +from ost import io + +class TestAlignToSeqRes(unittest.TestCase): + def testAlignWorking(self): + ent, seqres = io.LoadMMCIF("testfiles/align_to_seqres.mmcif", seqres = True) + chain = ent.FindChain("A") + sequence = seqres.FindSequence(chain.GetName()); + seqres_aln = seq.alg.AlignToSEQRES(chain, sequence, try_resnum_first=False) + self.assertEqual(str(sequence), "MYTNSDFVVIKALEDGVNVIGLTRGADTRFHHSEKLDKGEV"+ + "LIAQFTEHTSAIKVRGKAYIQTRHGVIESEGKK") + self.assertEqual(str(seqres_aln.sequences[1]), "----SDFVVIKALEDGVNVIGLTR--"+ + "-TRFHHSEKLDKGEVLIAQFTEHTSAIKVRGKAYIQTRHGVIESEGK-") + + seqres_aln = seq.alg.AlignToSEQRES(chain, sequence, try_resnum_first=True) + self.assertEqual(str(seqres_aln.sequences[1]), "----SDFVVIKALEDGVNVIGLTR--"+ + "-TRFHHSEKLDKGEVLIAQFTEHTSAIKVRGKAYIQTRHGVIESEGK-") + + def testAlignFail(self): + ent, seqres = io.LoadMMCIF("testfiles/align_to_seqres_valueerror.mmcif", + seqres = True) + chain = ent.FindChain("A") + sequence = seqres.FindSequence(chain.GetName()); + ost.PushVerbosityLevel(0) + self.assertRaises(ValueError, seq.alg.AlignToSEQRES, chain, sequence, True) + ost.PopVerbosityLevel() + + def testValidateWorking(self): + ent, seqres = io.LoadMMCIF("testfiles/align_to_seqres.mmcif", seqres = True) + chain = ent.FindChain("A") + sequence = seqres.FindSequence(chain.GetName()); + seqres_aln = seq.alg.AlignToSEQRES(chain, sequence, try_resnum_first=False) + self.assertEqual(seq.alg.ValidateSEQRESAlignment(seqres_aln, chain), True) + + def testValidateWorkingOnAttachedView(self): + ent, seqres = io.LoadMMCIF("testfiles/align_to_seqres.mmcif", seqres = True) + chain = ent.FindChain("A") + sequence = seqres.FindSequence(chain.GetName()); + seqres_aln = seq.alg.AlignToSEQRES(chain, sequence, try_resnum_first=False) + seqres_aln.AttachView(1, chain.Select('')) + self.assertEqual(seq.alg.ValidateSEQRESAlignment(seqres_aln), True) + + def testValidateEmptySequenceWorking(self): + alignment = seq.CreateAlignment(seq.CreateSequence('SEQRES', ''), + seq.CreateSequence('atoms', '')) + chain = mol.ChainHandle() + self.assertEqual(seq.alg.ValidateSEQRESAlignment(alignment, chain), True) + + def testValidateStrandBreakageFail(self): + ent, seqres = io.LoadMMCIF("testfiles/validate_segres_aln_breakage.mmcif", + seqres = True) + chain = ent.FindChain("A") + sequence = seqres.FindSequence(chain.GetName()); + seqres_aln = seq.alg.AlignToSEQRES(chain, sequence, try_resnum_first = True, + validate = False) + self.assertEqual(seq.alg.ValidateSEQRESAlignment(seqres_aln, chain), False) + + def testValidateGapConnectedFail(self): + ent, seqres = io.LoadMMCIF("testfiles/validate_seqres_aln_connected.mmcif", + seqres = True,) + chain = ent.FindChain("A") + sequence = seqres.FindSequence(chain.GetName()); + seqres_aln = seq.alg.AlignToSEQRES(chain, sequence, try_resnum_first = True, + validate = False) + self.assertEqual(seq.alg.ValidateSEQRESAlignment(seqres_aln, chain), False) + +if __name__ == "__main__": + from ost import testutils + testutils.RunTests() diff --git a/modules/seq/alg/tests/test_global_align.py b/modules/seq/alg/tests/test_global_align.py index aed51741b8ef35f0afdbd02b250cc93ea1c05f23..b23503cd02c2fbd9684a4355cbb14e7e53120a02 100644 --- a/modules/seq/alg/tests/test_global_align.py +++ b/modules/seq/alg/tests/test_global_align.py @@ -44,7 +44,5 @@ class TestGlobalAlign(unittest.TestCase): self.assertEqual(alns[0].sequences[1].offset, 0) if __name__ == "__main__": - try: - unittest.main() - except Exception, e: - print e + from ost import testutils + testutils.RunTests() diff --git a/modules/seq/alg/tests/test_local_align.py b/modules/seq/alg/tests/test_local_align.py index ff6872f9df22b261947e9abdbda12319e22a6d5a..47f78f68668e17e7413cbd18bbf09f9dd94b0b46 100644 --- a/modules/seq/alg/tests/test_local_align.py +++ b/modules/seq/alg/tests/test_local_align.py @@ -43,7 +43,5 @@ class TestLocalAlign(unittest.TestCase): self.assertEqual(alns[0].sequences[1].offset, 2) if __name__ == "__main__": - try: - unittest.main() - except Exception, e: - print e + from ost import testutils + testutils.RunTests() diff --git a/modules/seq/alg/tests/test_merge_pairwise_alignments.cc b/modules/seq/alg/tests/test_merge_pairwise_alignments.cc index 851f5c9f163911f1166492a25fd94ebcf4c5ea5a..25f9b836bd361560531922e2215bd3001cc909f0 100644 --- a/modules/seq/alg/tests/test_merge_pairwise_alignments.cc +++ b/modules/seq/alg/tests/test_merge_pairwise_alignments.cc @@ -34,15 +34,15 @@ BOOST_AUTO_TEST_SUITE(ost_seq_alg) BOOST_AUTO_TEST_CASE(merge_pairwise_alignments_one) { - SequenceHandle ref=CreateSequence("REF", "abcdefghijklmn"); + SequenceHandle ref=CreateSequence("REF", "abcdefghijklmn", "R"); SequenceHandle s1=CreateSequence("S1", "abcd---efghijklmn"); - SequenceHandle s2=CreateSequence("S2", "abcdxyzefghijklmn"); + SequenceHandle s2=CreateSequence("S2", "abcdxyzefghijklmn", "X"); AlignmentHandle aln1=CreateAlignment(); aln1.AddSequence(s1); aln1.AddSequence(s2); SequenceHandle s3=CreateSequence("S1", "abcdefghij---klmn"); - SequenceHandle s4=CreateSequence("S2", "abcdefghijxyzklmn"); + SequenceHandle s4=CreateSequence("S2", "abcdefghijxyzklmn", "Y"); AlignmentHandle aln2=CreateAlignment(); aln2.AddSequence(s3); @@ -55,6 +55,9 @@ BOOST_AUTO_TEST_CASE(merge_pairwise_alignments_one) BOOST_CHECK_EQUAL(seqs[0].GetString(), "abcd---efghij---klmn"); BOOST_CHECK_EQUAL(seqs[1].GetString(), "abcdxyzefghij---klmn"); BOOST_CHECK_EQUAL(seqs[2].GetString(), "abcd---efghijxyzklmn"); + BOOST_CHECK_EQUAL(seqs[0].GetRole(), "R"); + BOOST_CHECK_EQUAL(seqs[1].GetRole(), "X"); + BOOST_CHECK_EQUAL(seqs[2].GetRole(), "Y"); } BOOST_AUTO_TEST_CASE(merge_pairwise_alignments_two) diff --git a/modules/seq/alg/tests/test_renumber.py b/modules/seq/alg/tests/test_renumber.py index 76a9bf1d1d37284914ff7f23f2d32923c451d4f4..51e4727d3cfb7b3f87fea3517f9664fe7c896b16 100644 --- a/modules/seq/alg/tests/test_renumber.py +++ b/modules/seq/alg/tests/test_renumber.py @@ -118,7 +118,5 @@ if __name__ == "__main__": except(settings.FileNotFound): print "Could not find clustalw executable: ignoring unit tests" sys.exit(0) - try: - unittest.main() - except Exception, e: - print e + from ost import testutils + testutils.RunTests() diff --git a/modules/seq/alg/tests/test_weight_matrix.py b/modules/seq/alg/tests/test_weight_matrix.py index 7d85996fb3e74d0aa3ee87eace30a04881b0918a..91cf830379b7e7a3dccb5de3694267497f4d480f 100644 --- a/modules/seq/alg/tests/test_weight_matrix.py +++ b/modules/seq/alg/tests/test_weight_matrix.py @@ -39,7 +39,5 @@ class TestWeightMatrix(unittest.TestCase): self.assertEqual(mat.GetWeight('?', 'E'), 0) if __name__ == "__main__": - try: - unittest.main() - except Exception, e: - print e + from ost import testutils + testutils.RunTests() diff --git a/modules/seq/alg/tests/testfiles/align_to_seqres.mmcif b/modules/seq/alg/tests/testfiles/align_to_seqres.mmcif new file mode 100644 index 0000000000000000000000000000000000000000..177b53a64ae4319b48350ac7e132badbbf20e2d4 --- /dev/null +++ b/modules/seq/alg/tests/testfiles/align_to_seqres.mmcif @@ -0,0 +1,564 @@ +data_3BAR +# based on 3AQD +_entry.id 3BAR +# +loop_ +_entity.id +_entity.type +_entity.src_method +_entity.pdbx_description +_entity.formula_weight +_entity.pdbx_number_of_molecules +_entity.details +1 polymer man 'Transcription attenuation protein mtrB' 8257.458 22 ? +2 water nat water 18.015 7 ? +# +_entity_poly.entity_id 1 +_entity_poly.type 'polypeptide(L)' +_entity_poly.nstd_linkage no +_entity_poly.nstd_monomer no +_entity_poly.pdbx_seq_one_letter_code MYTNSDFVVIKALEDGVNVIGLTRGADTRFHHSEKLDKGEVLIAQFTEHTSAIKVRGKAYIQTRHGVIESEGKK +_entity_poly.pdbx_seq_one_letter_code_can MYTNSDFVVIKALEDGVNVIGLTRGADTRFHHSEKLDKGEVLIAQFTEHTSAIKVRGKAYIQTRHGVIESEGKK +_entity_poly.pdbx_strand_id A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V +# +loop_ +_atom_site.group_PDB +_atom_site.id +_atom_site.type_symbol +_atom_site.label_atom_id +_atom_site.label_alt_id +_atom_site.label_comp_id +_atom_site.label_asym_id +_atom_site.label_entity_id +_atom_site.label_seq_id +_atom_site.pdbx_PDB_ins_code +_atom_site.Cartn_x +_atom_site.Cartn_y +_atom_site.Cartn_z +_atom_site.occupancy +_atom_site.B_iso_or_equiv +_atom_site.Cartn_x_esd +_atom_site.Cartn_y_esd +_atom_site.Cartn_z_esd +_atom_site.occupancy_esd +_atom_site.B_iso_or_equiv_esd +_atom_site.pdbx_formal_charge +_atom_site.auth_seq_id +_atom_site.auth_comp_id +_atom_site.auth_asym_id +_atom_site.auth_atom_id +_atom_site.pdbx_PDB_model_num +ATOM 1 N N . SER A 1 5 ? 8.892 13.236 -28.550 1.00 81.62 ? ? ? ? ? ? 7 SER A N 1 +ATOM 2 C CA . SER A 1 5 ? 8.449 14.550 -29.128 1.00 80.98 ? ? ? ? ? ? 7 SER A CA 1 +ATOM 3 C C . SER A 1 5 ? 7.181 15.159 -28.476 1.00 77.44 ? ? ? ? ? ? 7 SER A C 1 +ATOM 4 O O . SER A 1 5 ? 6.463 15.940 -29.117 1.00 76.80 ? ? ? ? ? ? 7 SER A O 1 +ATOM 5 C CB . SER A 1 5 ? 8.239 14.416 -30.651 1.00 81.96 ? ? ? ? ? ? 7 SER A CB 1 +ATOM 6 O OG . SER A 1 5 ? 9.441 14.629 -31.378 1.00 87.04 ? ? ? ? ? ? 7 SER A OG 1 +ATOM 7 N N . ASP A 1 6 ? 6.910 14.822 -27.217 1.00 73.87 ? ? ? ? ? ? 8 ASP A N 1 +ATOM 8 C CA . ASP A 1 6 ? 5.670 15.258 -26.582 1.00 69.40 ? ? ? ? ? ? 8 ASP A CA 1 +ATOM 9 C C . ASP A 1 6 ? 5.834 16.550 -25.785 1.00 68.43 ? ? ? ? ? ? 8 ASP A C 1 +ATOM 10 O O . ASP A 1 6 ? 6.944 16.907 -25.403 1.00 70.90 ? ? ? ? ? ? 8 ASP A O 1 +ATOM 11 C CB . ASP A 1 6 ? 5.104 14.146 -25.703 1.00 67.64 ? ? ? ? ? ? 8 ASP A CB 1 +ATOM 12 C CG . ASP A 1 6 ? 3.570 14.083 -25.751 1.00 64.57 ? ? ? ? ? ? 8 ASP A CG 1 +ATOM 13 O OD1 . ASP A 1 6 ? 2.949 15.085 -26.195 1.00 63.11 ? ? ? ? ? ? 8 ASP A OD1 1 +ATOM 14 O OD2 . ASP A 1 6 ? 2.984 13.032 -25.353 1.00 62.17 ? ? ? ? ? ? 8 ASP A OD2 1 +ATOM 15 N N . PHE A 1 7 ? 4.726 17.246 -25.545 1.00 64.53 ? ? ? ? ? ? 9 PHE A N 1 +ATOM 16 C CA . PHE A 1 7 ? 4.750 18.548 -24.879 1.00 61.94 ? ? ? ? ? ? 9 PHE A CA 1 +ATOM 17 C C . PHE A 1 7 ? 3.673 18.732 -23.796 1.00 57.92 ? ? ? ? ? ? 9 PHE A C 1 +ATOM 18 O O . PHE A 1 7 ? 2.693 17.987 -23.744 1.00 55.70 ? ? ? ? ? ? 9 PHE A O 1 +ATOM 19 C CB . PHE A 1 7 ? 4.618 19.664 -25.915 1.00 63.43 ? ? ? ? ? ? 9 PHE A CB 1 +ATOM 20 C CG . PHE A 1 7 ? 3.282 19.718 -26.567 1.00 62.41 ? ? ? ? ? ? 9 PHE A CG 1 +ATOM 21 C CD1 . PHE A 1 7 ? 2.231 20.382 -25.970 1.00 61.82 ? ? ? ? ? ? 9 PHE A CD1 1 +ATOM 22 C CD2 . PHE A 1 7 ? 3.075 19.105 -27.775 1.00 64.02 ? ? ? ? ? ? 9 PHE A CD2 1 +ATOM 23 C CE1 . PHE A 1 7 ? 0.988 20.428 -26.567 1.00 60.16 ? ? ? ? ? ? 9 PHE A CE1 1 +ATOM 24 C CE2 . PHE A 1 7 ? 1.832 19.145 -28.383 1.00 62.57 ? ? ? ? ? ? 9 PHE A CE2 1 +ATOM 25 C CZ . PHE A 1 7 ? 0.783 19.808 -27.775 1.00 60.25 ? ? ? ? ? ? 9 PHE A CZ 1 +ATOM 26 N N . VAL A 1 8 ? 3.861 19.735 -22.938 1.00 55.04 ? ? ? ? ? ? 10 VAL A N 1 +ATOM 27 C CA . VAL A 1 8 ? 2.861 20.095 -21.949 1.00 50.88 ? ? ? ? ? ? 10 VAL A CA 1 +ATOM 28 C C . VAL A 1 8 ? 2.487 21.551 -22.098 1.00 49.54 ? ? ? ? ? ? 10 VAL A C 1 +ATOM 29 O O . VAL A 1 8 ? 3.323 22.385 -22.446 1.00 50.85 ? ? ? ? ? ? 10 VAL A O 1 +ATOM 30 C CB . VAL A 1 8 ? 3.326 19.851 -20.511 1.00 51.03 ? ? ? ? ? ? 10 VAL A CB 1 +ATOM 31 C CG1 . VAL A 1 8 ? 3.832 18.442 -20.371 1.00 50.13 ? ? ? ? ? ? 10 VAL A CG1 1 +ATOM 32 C CG2 . VAL A 1 8 ? 4.402 20.826 -20.090 1.00 53.19 ? ? ? ? ? ? 10 VAL A CG2 1 +ATOM 33 N N . VAL A 1 9 ? 1.215 21.844 -21.842 1.00 46.06 ? ? ? ? ? ? 11 VAL A N 1 +ATOM 34 C CA . VAL A 1 9 ? 0.687 23.206 -21.880 1.00 44.00 ? ? ? ? ? ? 11 VAL A CA 1 +ATOM 35 C C . VAL A 1 9 ? 0.489 23.603 -20.434 1.00 44.21 ? ? ? ? ? ? 11 VAL A C 1 +ATOM 36 O O . VAL A 1 9 ? -0.170 22.877 -19.678 1.00 42.41 ? ? ? ? ? ? 11 VAL A O 1 +ATOM 37 C CB . VAL A 1 9 ? -0.661 23.252 -22.624 1.00 42.00 ? ? ? ? ? ? 11 VAL A CB 1 +ATOM 38 C CG1 . VAL A 1 9 ? -1.295 24.607 -22.528 1.00 40.79 ? ? ? ? ? ? 11 VAL A CG1 1 +ATOM 39 C CG2 . VAL A 1 9 ? -0.455 22.906 -24.078 1.00 40.13 ? ? ? ? ? ? 11 VAL A CG2 1 +ATOM 40 N N . ILE A 1 10 ? 1.076 24.738 -20.056 1.00 46.10 ? ? ? ? ? ? 12 ILE A N 1 +ATOM 41 C CA . ILE A 1 10 ? 1.003 25.240 -18.696 1.00 47.51 ? ? ? ? ? ? 12 ILE A CA 1 +ATOM 42 C C . ILE A 1 10 ? 0.516 26.657 -18.743 1.00 48.05 ? ? ? ? ? ? 12 ILE A C 1 +ATOM 43 O O . ILE A 1 10 ? 1.137 27.508 -19.380 1.00 49.65 ? ? ? ? ? ? 12 ILE A O 1 +ATOM 44 C CB . ILE A 1 10 ? 2.374 25.247 -18.012 1.00 49.28 ? ? ? ? ? ? 12 ILE A CB 1 +ATOM 45 C CG1 . ILE A 1 10 ? 2.981 23.848 -18.003 1.00 49.95 ? ? ? ? ? ? 12 ILE A CG1 1 +ATOM 46 C CG2 . ILE A 1 10 ? 2.247 25.753 -16.603 1.00 50.91 ? ? ? ? ? ? 12 ILE A CG2 1 +ATOM 47 C CD1 . ILE A 1 10 ? 4.435 23.827 -17.677 1.00 54.16 ? ? ? ? ? ? 12 ILE A CD1 1 +ATOM 48 N N . LYS A 1 11 ? -0.606 26.901 -18.076 1.00 47.39 ? ? ? ? ? ? 13 LYS A N 1 +ATOM 49 C CA . LYS A 1 11 ? -1.139 28.252 -17.917 1.00 48.23 ? ? ? ? ? ? 13 LYS A CA 1 +ATOM 50 C C . LYS A 1 11 ? -0.998 28.660 -16.473 1.00 50.10 ? ? ? ? ? ? 13 LYS A C 1 +ATOM 51 O O . LYS A 1 11 ? -1.441 27.931 -15.579 1.00 49.40 ? ? ? ? ? ? 13 LYS A O 1 +ATOM 52 C CB . LYS A 1 11 ? -2.609 28.311 -18.304 1.00 46.00 ? ? ? ? ? ? 13 LYS A CB 1 +ATOM 53 C CG . LYS A 1 11 ? -3.144 29.706 -18.267 1.00 45.91 ? ? ? ? ? ? 13 LYS A CG 1 +ATOM 54 C CD . LYS A 1 11 ? -4.640 29.741 -18.402 1.00 43.12 ? ? ? ? ? ? 13 LYS A CD 1 +ATOM 55 C CE . LYS A 1 11 ? -5.103 31.182 -18.619 1.00 44.02 ? ? ? ? ? ? 13 LYS A CE 1 +ATOM 56 N NZ . LYS A 1 11 ? -6.563 31.312 -18.363 1.00 43.35 ? ? ? ? ? ? 13 LYS A NZ 1 +ATOM 57 N N . ALA A 1 12 ? -0.379 29.818 -16.242 1.00 53.49 ? ? ? ? ? ? 14 ALA A N 1 +ATOM 58 C CA . ALA A 1 12 ? -0.115 30.296 -14.876 1.00 55.56 ? ? ? ? ? ? 14 ALA A CA 1 +ATOM 59 C C . ALA A 1 12 ? -1.354 30.960 -14.272 1.00 55.44 ? ? ? ? ? ? 14 ALA A C 1 +ATOM 60 O O . ALA A 1 12 ? -1.938 31.848 -14.881 1.00 55.76 ? ? ? ? ? ? 14 ALA A O 1 +ATOM 61 C CB . ALA A 1 12 ? 1.042 31.240 -14.890 1.00 58.43 ? ? ? ? ? ? 14 ALA A CB 1 +ATOM 62 N N . LEU A 1 13 ? -1.767 30.514 -13.093 1.00 55.02 ? ? ? ? ? ? 15 LEU A N 1 +ATOM 63 C CA . LEU A 1 13 ? -2.966 31.063 -12.438 1.00 55.23 ? ? ? ? ? ? 15 LEU A CA 1 +ATOM 64 C C . LEU A 1 13 ? -2.665 32.145 -11.380 1.00 58.70 ? ? ? ? ? ? 15 LEU A C 1 +ATOM 65 O O . LEU A 1 13 ? -3.574 32.758 -10.809 1.00 58.84 ? ? ? ? ? ? 15 LEU A O 1 +ATOM 66 C CB . LEU A 1 13 ? -3.811 29.932 -11.832 1.00 52.50 ? ? ? ? ? ? 15 LEU A CB 1 +ATOM 67 C CG . LEU A 1 13 ? -4.415 28.951 -12.839 1.00 47.91 ? ? ? ? ? ? 15 LEU A CG 1 +ATOM 68 C CD1 . LEU A 1 13 ? -4.953 27.698 -12.151 1.00 44.21 ? ? ? ? ? ? 15 LEU A CD1 1 +ATOM 69 C CD2 . LEU A 1 13 ? -5.494 29.672 -13.668 1.00 46.05 ? ? ? ? ? ? 15 LEU A CD2 1 +ATOM 70 N N . GLU A 1 14 ? -1.379 32.359 -11.120 1.00 62.66 ? ? ? ? ? ? 16 GLU A N 1 +ATOM 71 C CA . GLU A 1 14 ? -0.899 33.425 -10.252 1.00 67.00 ? ? ? ? ? ? 16 GLU A CA 1 +ATOM 72 C C . GLU A 1 14 ? 0.409 33.922 -10.836 1.00 70.32 ? ? ? ? ? ? 16 GLU A C 1 +ATOM 73 O O . GLU A 1 14 ? 0.914 33.339 -11.785 1.00 70.03 ? ? ? ? ? ? 16 GLU A O 1 +ATOM 74 C CB . GLU A 1 14 ? -0.696 32.923 -8.819 1.00 67.19 ? ? ? ? ? ? 16 GLU A CB 1 +ATOM 75 C CG . GLU A 1 14 ? 0.432 31.895 -8.625 1.00 68.58 ? ? ? ? ? ? 16 GLU A CG 1 +ATOM 76 C CD . GLU A 1 14 ? 0.454 31.270 -7.222 1.00 70.39 ? ? ? ? ? ? 16 GLU A CD 1 +ATOM 77 O OE1 . GLU A 1 14 ? -0.457 31.541 -6.412 1.00 71.02 ? ? ? ? ? ? 16 GLU A OE1 1 +ATOM 78 O OE2 . GLU A 1 14 ? 1.387 30.491 -6.926 1.00 71.29 ? ? ? ? ? ? 16 GLU A OE2 1 +ATOM 79 N N . ASP A 1 15 ? 0.955 35.001 -10.285 1.00 74.75 ? ? ? ? ? ? 17 ASP A N 1 +ATOM 80 C CA . ASP A 1 15 ? 2.250 35.491 -10.740 1.00 78.78 ? ? ? ? ? ? 17 ASP A CA 1 +ATOM 81 C C . ASP A 1 15 ? 3.325 34.615 -10.138 1.00 79.87 ? ? ? ? ? ? 17 ASP A C 1 +ATOM 82 O O . ASP A 1 15 ? 3.099 33.950 -9.124 1.00 79.33 ? ? ? ? ? ? 17 ASP A O 1 +ATOM 83 C CB . ASP A 1 15 ? 2.475 36.953 -10.336 1.00 81.65 ? ? ? ? ? ? 17 ASP A CB 1 +ATOM 84 C CG . ASP A 1 15 ? 1.621 37.937 -11.140 1.00 83.16 ? ? ? ? ? ? 17 ASP A CG 1 +ATOM 85 O OD1 . ASP A 1 15 ? 1.344 37.691 -12.326 1.00 82.40 ? ? ? ? ? ? 17 ASP A OD1 1 +ATOM 86 O OD2 . ASP A 1 15 ? 1.231 38.982 -10.589 1.00 86.46 ? ? ? ? ? ? 17 ASP A OD2 1 +ATOM 87 N N . GLY A 1 16 ? 4.489 34.606 -10.778 1.00 81.58 ? ? ? ? ? ? 18 GLY A N 1 +ATOM 88 C CA . GLY A 1 16 ? 5.660 33.903 -10.248 1.00 82.57 ? ? ? ? ? ? 18 GLY A CA 1 +ATOM 89 C C . GLY A 1 16 ? 5.555 32.392 -10.154 1.00 80.35 ? ? ? ? ? ? 18 GLY A C 1 +ATOM 90 O O . GLY A 1 16 ? 6.059 31.793 -9.215 1.00 81.29 ? ? ? ? ? ? 18 GLY A O 1 +ATOM 91 N N . VAL A 1 17 ? 4.892 31.781 -11.128 1.00 77.56 ? ? ? ? ? ? 19 VAL A N 1 +ATOM 92 C CA . VAL A 1 17 ? 4.885 30.336 -11.259 1.00 74.50 ? ? ? ? ? ? 19 VAL A CA 1 +ATOM 93 C C . VAL A 1 17 ? 6.239 29.942 -11.826 1.00 76.68 ? ? ? ? ? ? 19 VAL A C 1 +ATOM 94 O O . VAL A 1 17 ? 6.799 30.655 -12.655 1.00 78.24 ? ? ? ? ? ? 19 VAL A O 1 +ATOM 95 C CB . VAL A 1 17 ? 3.755 29.861 -12.187 1.00 71.56 ? ? ? ? ? ? 19 VAL A CB 1 +ATOM 96 C CG1 . VAL A 1 17 ? 3.820 28.364 -12.384 1.00 67.63 ? ? ? ? ? ? 19 VAL A CG1 1 +ATOM 97 C CG2 . VAL A 1 17 ? 2.409 30.247 -11.611 1.00 67.92 ? ? ? ? ? ? 19 VAL A CG2 1 +ATOM 98 N N . ASN A 1 18 ? 6.764 28.812 -11.381 1.00 77.33 ? ? ? ? ? ? 20 ASN A N 1 +ATOM 99 C CA . ASN A 1 18 ? 8.086 28.396 -11.775 1.00 79.46 ? ? ? ? ? ? 20 ASN A CA 1 +ATOM 100 C C . ASN A 1 18 ? 8.067 27.069 -12.528 1.00 77.29 ? ? ? ? ? ? 20 ASN A C 1 +ATOM 101 O O . ASN A 1 18 ? 7.635 26.058 -11.989 1.00 75.60 ? ? ? ? ? ? 20 ASN A O 1 +ATOM 102 C CB . ASN A 1 18 ? 8.941 28.291 -10.526 1.00 82.30 ? ? ? ? ? ? 20 ASN A CB 1 +ATOM 103 C CG . ASN A 1 18 ? 10.360 28.739 -10.753 1.00 89.13 ? ? ? ? ? ? 20 ASN A CG 1 +ATOM 104 O OD1 . ASN A 1 18 ? 10.690 29.305 -11.791 1.00 92.93 ? ? ? ? ? ? 20 ASN A OD1 1 +ATOM 105 N ND2 . ASN A 1 18 ? 11.217 28.488 -9.773 1.00 94.39 ? ? ? ? ? ? 20 ASN A ND2 1 +ATOM 106 N N . VAL A 1 19 ? 8.521 27.077 -13.779 1.00 76.88 ? ? ? ? ? ? 21 VAL A N 1 +ATOM 107 C CA . VAL A 1 19 ? 8.542 25.871 -14.600 1.00 75.28 ? ? ? ? ? ? 21 VAL A CA 1 +ATOM 108 C C . VAL A 1 19 ? 9.970 25.398 -14.720 1.00 78.52 ? ? ? ? ? ? 21 VAL A C 1 +ATOM 109 O O . VAL A 1 19 ? 10.747 25.948 -15.489 1.00 80.53 ? ? ? ? ? ? 21 VAL A O 1 +ATOM 110 C CB . VAL A 1 19 ? 7.946 26.104 -16.005 1.00 73.54 ? ? ? ? ? ? 21 VAL A CB 1 +ATOM 111 C CG1 . VAL A 1 19 ? 7.966 24.838 -16.807 1.00 70.33 ? ? ? ? ? ? 21 VAL A CG1 1 +ATOM 112 C CG2 . VAL A 1 19 ? 6.528 26.602 -15.913 1.00 69.44 ? ? ? ? ? ? 21 VAL A CG2 1 +ATOM 113 N N . ILE A 1 20 ? 10.305 24.368 -13.960 1.00 80.07 ? ? ? ? ? ? 22 ILE A N 1 +ATOM 114 C CA . ILE A 1 20 ? 11.683 23.949 -13.817 1.00 83.77 ? ? ? ? ? ? 22 ILE A CA 1 +ATOM 115 C C . ILE A 1 20 ? 12.004 22.729 -14.664 1.00 83.74 ? ? ? ? ? ? 22 ILE A C 1 +ATOM 116 O O . ILE A 1 20 ? 11.349 21.705 -14.536 1.00 81.42 ? ? ? ? ? ? 22 ILE A O 1 +ATOM 117 C CB . ILE A 1 20 ? 12.014 23.661 -12.348 1.00 84.59 ? ? ? ? ? ? 22 ILE A CB 1 +ATOM 118 C CG1 . ILE A 1 20 ? 11.522 24.802 -11.467 1.00 85.96 ? ? ? ? ? ? 22 ILE A CG1 1 +ATOM 119 C CG2 . ILE A 1 20 ? 13.511 23.484 -12.166 1.00 89.81 ? ? ? ? ? ? 22 ILE A CG2 1 +ATOM 120 C CD1 . ILE A 1 20 ? 11.484 24.464 -9.998 1.00 87.43 ? ? ? ? ? ? 22 ILE A CD1 1 +ATOM 121 N N . GLY A 1 21 ? 13.019 22.862 -15.520 1.00 86.57 ? ? ? ? ? ? 23 GLY A N 1 +ATOM 122 C CA . GLY A 1 21 ? 13.522 21.775 -16.358 1.00 88.60 ? ? ? ? ? ? 23 GLY A CA 1 +ATOM 123 C C . GLY A 1 21 ? 14.674 21.070 -15.675 1.00 91.29 ? ? ? ? ? ? 23 GLY A C 1 +ATOM 124 O O . GLY A 1 21 ? 15.573 21.716 -15.154 1.00 94.14 ? ? ? ? ? ? 23 GLY A O 1 +ATOM 125 N N . LEU A 1 22 ? 14.642 19.743 -15.672 1.00 91.36 ? ? ? ? ? ? 24 LEU A N 1 +ATOM 126 C CA . LEU A 1 22 ? 15.603 18.932 -14.926 1.00 92.96 ? ? ? ? ? ? 24 LEU A CA 1 +ATOM 127 C C . LEU A 1 22 ? 16.447 18.089 -15.876 1.00 94.68 ? ? ? ? ? ? 24 LEU A C 1 +ATOM 128 O O . LEU A 1 22 ? 15.939 17.601 -16.885 1.00 94.04 ? ? ? ? ? ? 24 LEU A O 1 +ATOM 129 C CB . LEU A 1 22 ? 14.860 18.047 -13.924 1.00 91.08 ? ? ? ? ? ? 24 LEU A CB 1 +ATOM 130 C CG . LEU A 1 22 ? 14.551 18.518 -12.493 1.00 90.38 ? ? ? ? ? ? 24 LEU A CG 1 +ATOM 131 C CD1 . LEU A 1 22 ? 14.342 20.009 -12.384 1.00 91.01 ? ? ? ? ? ? 24 LEU A CD1 1 +ATOM 132 C CD2 . LEU A 1 22 ? 13.342 17.791 -11.921 1.00 85.41 ? ? ? ? ? ? 24 LEU A CD2 1 +ATOM 133 N N . THR A 1 23 ? 17.733 17.926 -15.565 1.00 96.47 ? ? ? ? ? ? 25 THR A N 1 +ATOM 134 C CA . THR A 1 23 ? 18.688 17.343 -16.531 1.00 98.30 ? ? ? ? ? ? 25 THR A CA 1 +ATOM 135 C C . THR A 1 23 ? 19.007 15.862 -16.352 1.00 98.49 ? ? ? ? ? ? 25 THR A C 1 +ATOM 136 O O . THR A 1 23 ? 18.826 15.304 -15.266 1.00 98.19 ? ? ? ? ? ? 25 THR A O 1 +ATOM 137 C CB . THR A 1 23 ? 20.028 18.102 -16.553 1.00 100.21 ? ? ? ? ? ? 25 THR A CB 1 +ATOM 138 O OG1 . THR A 1 23 ? 20.490 18.282 -15.208 1.00 101.37 ? ? ? ? ? ? 25 THR A OG1 1 +ATOM 139 C CG2 . THR A 1 23 ? 19.883 19.457 -17.252 1.00 100.72 ? ? ? ? ? ? 25 THR A CG2 1 +ATOM 140 N N . ARG A 1 24 ? 19.501 15.246 -17.430 1.00 99.49 ? ? ? ? ? ? 26 ARG A N 1 +ATOM 141 C CA . ARG A 1 24 ? 19.857 13.819 -17.452 1.00 99.94 ? ? ? ? ? ? 26 ARG A CA 1 +ATOM 142 C C . ARG A 1 24 ? 21.154 13.541 -16.693 1.00 101.44 ? ? ? ? ? ? 26 ARG A C 1 +ATOM 143 O O . ARG A 1 24 ? 22.240 13.904 -17.147 1.00 103.26 ? ? ? ? ? ? 26 ARG A O 1 +ATOM 144 C CB . ARG A 1 24 ? 19.955 13.281 -18.893 1.00 100.14 ? ? ? ? ? ? 26 ARG A CB 1 +ATOM 145 C CG . ARG A 1 24 ? 18.620 13.217 -19.642 1.00 99.36 ? ? ? ? ? ? 26 ARG A CG 1 +ATOM 146 C CD . ARG A 1 24 ? 18.634 12.164 -20.759 1.00 100.98 ? ? ? ? ? ? 26 ARG A CD 1 +ATOM 147 N NE . ARG A 1 24 ? 17.552 12.352 -21.740 1.00 100.55 ? ? ? ? ? ? 26 ARG A NE 1 +ATOM 148 C CZ . ARG A 1 24 ? 17.231 11.494 -22.716 1.00 99.98 ? ? ? ? ? ? 26 ARG A CZ 1 +ATOM 149 N NH1 . ARG A 1 24 ? 17.891 10.344 -22.876 1.00 99.60 ? ? ? ? ? ? 26 ARG A NH1 1 +ATOM 150 N NH2 . ARG A 1 24 ? 16.229 11.791 -23.537 1.00 99.33 ? ? ? ? ? ? 26 ARG A NH2 1 +ATOM 151 N N . THR A 1 28 ? 22.527 16.428 -12.721 1.00 120.13 ? ? ? ? ? ? 30 THR A N 1 +ATOM 152 C CA . THR A 1 28 ? 21.235 15.835 -13.090 1.00 118.47 ? ? ? ? ? ? 30 THR A CA 1 +ATOM 153 C C . THR A 1 28 ? 20.021 16.467 -12.351 1.00 117.17 ? ? ? ? ? ? 30 THR A C 1 +ATOM 154 O O . THR A 1 28 ? 18.867 16.073 -12.593 1.00 115.70 ? ? ? ? ? ? 30 THR A O 1 +ATOM 155 C CB . THR A 1 28 ? 21.259 14.241 -13.007 1.00 118.06 ? ? ? ? ? ? 30 THR A CB 1 +ATOM 156 O OG1 . THR A 1 28 ? 19.946 13.697 -13.234 1.00 116.11 ? ? ? ? ? ? 30 THR A OG1 1 +ATOM 157 C CG2 . THR A 1 28 ? 21.822 13.727 -11.660 1.00 118.37 ? ? ? ? ? ? 30 THR A CG2 1 +ATOM 158 N N . ARG A 1 29 ? 20.289 17.464 -11.492 1.00 117.71 ? ? ? ? ? ? 31 ARG A N 1 +ATOM 159 C CA . ARG A 1 29 ? 19.261 18.091 -10.604 1.00 116.35 ? ? ? ? ? ? 31 ARG A CA 1 +ATOM 160 C C . ARG A 1 29 ? 18.477 19.294 -11.195 1.00 115.56 ? ? ? ? ? ? 31 ARG A C 1 +ATOM 161 O O . ARG A 1 29 ? 18.271 19.360 -12.420 1.00 115.47 ? ? ? ? ? ? 31 ARG A O 1 +ATOM 162 C CB . ARG A 1 29 ? 19.840 18.428 -9.204 1.00 117.16 ? ? ? ? ? ? 31 ARG A CB 1 +ATOM 163 C CG . ARG A 1 29 ? 21.320 18.904 -9.113 1.00 119.11 ? ? ? ? ? ? 31 ARG A CG 1 +ATOM 164 C CD . ARG A 1 29 ? 21.638 20.210 -9.857 1.00 119.60 ? ? ? ? ? ? 31 ARG A CD 1 +ATOM 165 N NE . ARG A 1 29 ? 22.419 19.952 -11.068 1.00 120.44 ? ? ? ? ? ? 31 ARG A NE 1 +ATOM 166 C CZ . ARG A 1 29 ? 21.980 20.123 -12.315 1.00 119.80 ? ? ? ? ? ? 31 ARG A CZ 1 +ATOM 167 N NH1 . ARG A 1 29 ? 22.780 19.853 -13.337 1.00 121.30 ? ? ? ? ? ? 31 ARG A NH1 1 +ATOM 168 N NH2 . ARG A 1 29 ? 20.756 20.576 -12.552 1.00 117.87 ? ? ? ? ? ? 31 ARG A NH2 1 +ATOM 169 N N . PHE A 1 30 ? 18.052 20.228 -10.323 1.00 114.83 ? ? ? ? ? ? 32 PHE A N 1 +ATOM 170 C CA . PHE A 1 30 ? 17.248 21.413 -10.728 1.00 113.80 ? ? ? ? ? ? 32 PHE A CA 1 +ATOM 171 C C . PHE A 1 30 ? 18.047 22.475 -11.541 1.00 114.52 ? ? ? ? ? ? 32 PHE A C 1 +ATOM 172 O O . PHE A 1 30 ? 18.937 23.145 -11.001 1.00 115.82 ? ? ? ? ? ? 32 PHE A O 1 +ATOM 173 C CB . PHE A 1 30 ? 16.487 22.093 -9.541 1.00 113.41 ? ? ? ? ? ? 32 PHE A CB 1 +ATOM 174 C CG . PHE A 1 30 ? 16.144 21.179 -8.346 1.00 112.64 ? ? ? ? ? ? 32 PHE A CG 1 +ATOM 175 C CD1 . PHE A 1 30 ? 15.540 21.740 -7.207 1.00 112.23 ? ? ? ? ? ? 32 PHE A CD1 1 +ATOM 176 C CD2 . PHE A 1 30 ? 16.423 19.805 -8.338 1.00 111.84 ? ? ? ? ? ? 32 PHE A CD2 1 +ATOM 177 C CE1 . PHE A 1 30 ? 15.212 20.957 -6.091 1.00 111.54 ? ? ? ? ? ? 32 PHE A CE1 1 +ATOM 178 C CE2 . PHE A 1 30 ? 16.110 19.015 -7.218 1.00 111.19 ? ? ? ? ? ? 32 PHE A CE2 1 +ATOM 179 C CZ . PHE A 1 30 ? 15.497 19.590 -6.097 1.00 111.08 ? ? ? ? ? ? 32 PHE A CZ 1 +ATOM 180 N N . HIS A 1 31 ? 17.677 22.645 -12.817 1.00 113.18 ? ? ? ? ? ? 33 HIS A N 1 +ATOM 181 C CA . HIS A 1 31 ? 18.505 23.317 -13.836 1.00 113.51 ? ? ? ? ? ? 33 HIS A CA 1 +ATOM 182 C C . HIS A 1 31 ? 17.843 24.573 -14.459 1.00 112.40 ? ? ? ? ? ? 33 HIS A C 1 +ATOM 183 O O . HIS A 1 31 ? 17.840 25.650 -13.849 1.00 112.91 ? ? ? ? ? ? 33 HIS A O 1 +ATOM 184 C CB . HIS A 1 31 ? 18.897 22.274 -14.908 1.00 113.74 ? ? ? ? ? ? 33 HIS A CB 1 +ATOM 185 C CG . HIS A 1 31 ? 19.881 22.761 -15.933 1.00 116.22 ? ? ? ? ? ? 33 HIS A CG 1 +ATOM 186 N ND1 . HIS A 1 31 ? 21.201 23.036 -15.635 1.00 118.98 ? ? ? ? ? ? 33 HIS A ND1 1 +ATOM 187 C CD2 . HIS A 1 31 ? 19.743 22.976 -17.264 1.00 116.72 ? ? ? ? ? ? 33 HIS A CD2 1 +ATOM 188 C CE1 . HIS A 1 31 ? 21.826 23.425 -16.734 1.00 120.25 ? ? ? ? ? ? 33 HIS A CE1 1 +ATOM 189 N NE2 . HIS A 1 31 ? 20.964 23.395 -17.736 1.00 119.10 ? ? ? ? ? ? 33 HIS A NE2 1 +ATOM 190 N N . HIS A 1 32 ? 17.298 24.431 -15.670 1.00 110.63 ? ? ? ? ? ? 34 HIS A N 1 +ATOM 191 C CA . HIS A 1 32 ? 16.630 25.529 -16.377 1.00 108.57 ? ? ? ? ? ? 34 HIS A CA 1 +ATOM 192 C C . HIS A 1 32 ? 15.315 25.908 -15.701 1.00 105.41 ? ? ? ? ? ? 34 HIS A C 1 +ATOM 193 O O . HIS A 1 32 ? 14.336 25.165 -15.760 1.00 102.47 ? ? ? ? ? ? 34 HIS A O 1 +ATOM 194 C CB . HIS A 1 32 ? 16.384 25.161 -17.858 1.00 108.29 ? ? ? ? ? ? 34 HIS A CB 1 +ATOM 195 C CG . HIS A 1 32 ? 15.859 26.296 -18.697 1.00 108.03 ? ? ? ? ? ? 34 HIS A CG 1 +ATOM 196 N ND1 . HIS A 1 32 ? 16.492 27.522 -18.778 1.00 111.34 ? ? ? ? ? ? 34 HIS A ND1 1 +ATOM 197 C CD2 . HIS A 1 32 ? 14.778 26.380 -19.511 1.00 103.90 ? ? ? ? ? ? 34 HIS A CD2 1 +ATOM 198 C CE1 . HIS A 1 32 ? 15.812 28.317 -19.586 1.00 109.77 ? ? ? ? ? ? 34 HIS A CE1 1 +ATOM 199 N NE2 . HIS A 1 32 ? 14.772 27.647 -20.051 1.00 105.66 ? ? ? ? ? ? 34 HIS A NE2 1 +ATOM 200 N N . SER A 1 33 ? 15.303 27.064 -15.056 1.00 104.75 ? ? ? ? ? ? 35 SER A N 1 +ATOM 201 C CA . SER A 1 33 ? 14.079 27.599 -14.485 1.00 101.92 ? ? ? ? ? ? 35 SER A CA 1 +ATOM 202 C C . SER A 1 33 ? 13.450 28.601 -15.456 1.00 99.94 ? ? ? ? ? ? 35 SER A C 1 +ATOM 203 O O . SER A 1 33 ? 14.146 29.196 -16.272 1.00 101.93 ? ? ? ? ? ? 35 SER A O 1 +ATOM 204 C CB . SER A 1 33 ? 14.372 28.236 -13.124 1.00 103.64 ? ? ? ? ? ? 35 SER A CB 1 +ATOM 205 O OG . SER A 1 33 ? 13.401 29.202 -12.771 1.00 103.74 ? ? ? ? ? ? 35 SER A OG 1 +ATOM 206 N N . GLU A 1 34 ? 12.136 28.778 -15.372 1.00 95.30 ? ? ? ? ? ? 36 GLU A N 1 +ATOM 207 C CA . GLU A 1 34 ? 11.425 29.699 -16.249 1.00 92.35 ? ? ? ? ? ? 36 GLU A CA 1 +ATOM 208 C C . GLU A 1 34 ? 10.221 30.272 -15.520 1.00 90.03 ? ? ? ? ? ? 36 GLU A C 1 +ATOM 209 O O . GLU A 1 34 ? 9.296 29.543 -15.201 1.00 87.29 ? ? ? ? ? ? 36 GLU A O 1 +ATOM 210 C CB . GLU A 1 34 ? 10.977 28.964 -17.511 1.00 90.67 ? ? ? ? ? ? 36 GLU A CB 1 +ATOM 211 C CG . GLU A 1 34 ? 10.555 29.867 -18.650 1.00 90.72 ? ? ? ? ? ? 36 GLU A CG 1 +ATOM 212 C CD . GLU A 1 34 ? 11.736 30.565 -19.310 1.00 96.24 ? ? ? ? ? ? 36 GLU A CD 1 +ATOM 213 O OE1 . GLU A 1 34 ? 12.815 29.937 -19.462 1.00 99.38 ? ? ? ? ? ? 36 GLU A OE1 1 +ATOM 214 O OE2 . GLU A 1 34 ? 11.578 31.748 -19.685 1.00 98.37 ? ? ? ? ? ? 36 GLU A OE2 1 +ATOM 215 N N . LYS A 1 35 ? 10.235 31.569 -15.239 1.00 90.36 ? ? ? ? ? ? 37 LYS A N 1 +ATOM 216 C CA . LYS A 1 35 ? 9.139 32.178 -14.506 1.00 88.38 ? ? ? ? ? ? 37 LYS A CA 1 +ATOM 217 C C . LYS A 1 35 ? 7.977 32.484 -15.433 1.00 85.67 ? ? ? ? ? ? 37 LYS A C 1 +ATOM 218 O O . LYS A 1 35 ? 8.172 32.833 -16.592 1.00 86.06 ? ? ? ? ? ? 37 LYS A O 1 +ATOM 219 C CB . LYS A 1 35 ? 9.601 33.433 -13.768 1.00 91.44 ? ? ? ? ? ? 37 LYS A CB 1 +ATOM 220 N N . LEU A 1 36 ? 6.766 32.325 -14.915 1.00 81.92 ? ? ? ? ? ? 38 LEU A N 1 +ATOM 221 C CA . LEU A 1 36 ? 5.539 32.641 -15.640 1.00 78.89 ? ? ? ? ? ? 38 LEU A CA 1 +ATOM 222 C C . LEU A 1 36 ? 4.640 33.528 -14.797 1.00 78.12 ? ? ? ? ? ? 38 LEU A C 1 +ATOM 223 O O . LEU A 1 36 ? 4.498 33.299 -13.601 1.00 77.83 ? ? ? ? ? ? 38 LEU A O 1 +ATOM 224 C CB . LEU A 1 36 ? 4.770 31.368 -15.979 1.00 77.62 ? ? ? ? ? ? 38 LEU A CB 1 +ATOM 225 C CG . LEU A 1 36 ? 4.861 30.675 -17.336 1.00 76.31 ? ? ? ? ? ? 38 LEU A CG 1 +ATOM 226 C CD1 . LEU A 1 36 ? 3.481 30.149 -17.653 1.00 74.28 ? ? ? ? ? ? 38 LEU A CD1 1 +ATOM 227 C CD2 . LEU A 1 36 ? 5.328 31.599 -18.436 1.00 76.23 ? ? ? ? ? ? 38 LEU A CD2 1 +ATOM 228 N N . ASP A 1 37 ? 4.015 34.523 -15.417 1.00 77.70 ? ? ? ? ? ? 39 ASP A N 1 +ATOM 229 C CA . ASP A 1 37 ? 3.127 35.429 -14.691 1.00 77.42 ? ? ? ? ? ? 39 ASP A CA 1 +ATOM 230 C C . ASP A 1 37 ? 1.666 35.169 -15.004 1.00 73.58 ? ? ? ? ? ? 39 ASP A C 1 +ATOM 231 O O . ASP A 1 37 ? 1.352 34.676 -16.075 1.00 72.04 ? ? ? ? ? ? 39 ASP A O 1 +ATOM 232 C CB . ASP A 1 37 ? 3.473 36.886 -14.995 1.00 80.86 ? ? ? ? ? ? 39 ASP A CB 1 +ATOM 233 C CG . ASP A 1 37 ? 4.632 37.408 -14.159 1.00 86.94 ? ? ? ? ? ? 39 ASP A CG 1 +ATOM 234 O OD1 . ASP A 1 37 ? 4.986 36.781 -13.125 1.00 88.70 ? ? ? ? ? ? 39 ASP A OD1 1 +ATOM 235 O OD2 . ASP A 1 37 ? 5.178 38.463 -14.548 1.00 92.58 ? ? ? ? ? ? 39 ASP A OD2 1 +ATOM 236 N N . LYS A 1 38 ? 0.788 35.520 -14.065 1.00 71.09 ? ? ? ? ? ? 40 LYS A N 1 +ATOM 237 C CA . LYS A 1 38 ? -0.646 35.219 -14.127 1.00 67.44 ? ? ? ? ? ? 40 LYS A CA 1 +ATOM 238 C C . LYS A 1 38 ? -1.246 35.395 -15.514 1.00 65.75 ? ? ? ? ? ? 40 LYS A C 1 +ATOM 239 O O . LYS A 1 38 ? -1.274 36.506 -16.038 1.00 66.82 ? ? ? ? ? ? 40 LYS A O 1 +ATOM 240 C CB . LYS A 1 38 ? -1.408 36.092 -13.130 1.00 67.43 ? ? ? ? ? ? 40 LYS A CB 1 +ATOM 241 C CG . LYS A 1 38 ? -2.847 35.692 -12.912 1.00 65.33 ? ? ? ? ? ? 40 LYS A CG 1 +ATOM 242 C CD . LYS A 1 38 ? -3.496 36.530 -11.819 1.00 65.17 ? ? ? ? ? ? 40 LYS A CD 1 +ATOM 243 C CE . LYS A 1 38 ? -4.727 35.828 -11.238 1.00 64.58 ? ? ? ? ? ? 40 LYS A CE 1 +ATOM 244 N NZ . LYS A 1 38 ? -5.911 36.738 -11.093 1.00 64.29 ? ? ? ? ? ? 40 LYS A NZ 1 +ATOM 245 N N . GLY A 1 39 ? -1.710 34.288 -16.097 1.00 62.75 ? ? ? ? ? ? 41 GLY A N 1 +ATOM 246 C CA . GLY A 1 39 ? -2.358 34.280 -17.410 1.00 60.49 ? ? ? ? ? ? 41 GLY A CA 1 +ATOM 247 C C . GLY A 1 39 ? -1.471 33.947 -18.599 1.00 60.30 ? ? ? ? ? ? 41 GLY A C 1 +ATOM 248 O O . GLY A 1 39 ? -1.957 33.805 -19.718 1.00 58.95 ? ? ? ? ? ? 41 GLY A O 1 +ATOM 249 N N . GLU A 1 40 ? -0.167 33.843 -18.366 1.00 61.59 ? ? ? ? ? ? 42 GLU A N 1 +ATOM 250 C CA . GLU A 1 40 ? 0.777 33.499 -19.424 1.00 62.43 ? ? ? ? ? ? 42 GLU A CA 1 +ATOM 251 C C . GLU A 1 40 ? 0.720 32.015 -19.667 1.00 59.62 ? ? ? ? ? ? 42 GLU A C 1 +ATOM 252 O O . GLU A 1 40 ? 0.425 31.239 -18.761 1.00 58.37 ? ? ? ? ? ? 42 GLU A O 1 +ATOM 253 C CB . GLU A 1 40 ? 2.200 33.917 -19.056 1.00 65.52 ? ? ? ? ? ? 42 GLU A CB 1 +ATOM 254 C CG . GLU A 1 40 ? 2.523 35.352 -19.404 1.00 71.75 ? ? ? ? ? ? 42 GLU A CG 1 +ATOM 255 C CD . GLU A 1 40 ? 3.754 35.879 -18.701 1.00 79.02 ? ? ? ? ? ? 42 GLU A CD 1 +ATOM 256 O OE1 . GLU A 1 40 ? 4.375 35.124 -17.926 1.00 79.96 ? ? ? ? ? ? 42 GLU A OE1 1 +ATOM 257 O OE2 . GLU A 1 40 ? 4.097 37.059 -18.923 1.00 83.29 ? ? ? ? ? ? 42 GLU A OE2 1 +ATOM 258 N N . VAL A 1 41 ? 1.004 31.619 -20.895 1.00 58.12 ? ? ? ? ? ? 43 VAL A N 1 +ATOM 259 C CA . VAL A 1 41 ? 0.931 30.221 -21.282 1.00 55.42 ? ? ? ? ? ? 43 VAL A CA 1 +ATOM 260 C C . VAL A 1 41 ? 2.254 29.747 -21.855 1.00 57.22 ? ? ? ? ? ? 43 VAL A C 1 +ATOM 261 O O . VAL A 1 41 ? 2.823 30.381 -22.755 1.00 58.88 ? ? ? ? ? ? 43 VAL A O 1 +ATOM 262 C CB . VAL A 1 41 ? -0.180 29.994 -22.309 1.00 53.28 ? ? ? ? ? ? 43 VAL A CB 1 +ATOM 263 C CG1 . VAL A 1 41 ? -0.060 28.645 -22.920 1.00 50.49 ? ? ? ? ? ? 43 VAL A CG1 1 +ATOM 264 C CG2 . VAL A 1 41 ? -1.523 30.132 -21.664 1.00 49.78 ? ? ? ? ? ? 43 VAL A CG2 1 +ATOM 265 N N . LEU A 1 42 ? 2.738 28.629 -21.323 1.00 57.21 ? ? ? ? ? ? 44 LEU A N 1 +ATOM 266 C CA . LEU A 1 42 ? 3.960 28.037 -21.813 1.00 58.54 ? ? ? ? ? ? 44 LEU A CA 1 +ATOM 267 C C . LEU A 1 42 ? 3.633 26.718 -22.458 1.00 56.54 ? ? ? ? ? ? 44 LEU A C 1 +ATOM 268 O O . LEU A 1 42 ? 2.882 25.928 -21.899 1.00 54.68 ? ? ? ? ? ? 44 LEU A O 1 +ATOM 269 C CB . LEU A 1 42 ? 4.954 27.852 -20.680 1.00 60.35 ? ? ? ? ? ? 44 LEU A CB 1 +ATOM 270 C CG . LEU A 1 42 ? 6.378 27.476 -21.074 1.00 64.66 ? ? ? ? ? ? 44 LEU A CG 1 +ATOM 271 C CD1 . LEU A 1 42 ? 7.071 28.595 -21.816 1.00 69.92 ? ? ? ? ? ? 44 LEU A CD1 1 +ATOM 272 C CD2 . LEU A 1 42 ? 7.171 27.112 -19.839 1.00 67.81 ? ? ? ? ? ? 44 LEU A CD2 1 +ATOM 273 N N . ILE A 1 43 ? 4.162 26.504 -23.657 1.00 56.61 ? ? ? ? ? ? 45 ILE A N 1 +ATOM 274 C CA . ILE A 1 43 ? 4.086 25.207 -24.298 1.00 55.49 ? ? ? ? ? ? 45 ILE A CA 1 +ATOM 275 C C . ILE A 1 43 ? 5.487 24.630 -24.267 1.00 57.96 ? ? ? ? ? ? 45 ILE A C 1 +ATOM 276 O O . ILE A 1 43 ? 6.345 25.038 -25.046 1.00 60.01 ? ? ? ? ? ? 45 ILE A O 1 +ATOM 277 C CB . ILE A 1 43 ? 3.621 25.276 -25.757 1.00 54.45 ? ? ? ? ? ? 45 ILE A CB 1 +ATOM 278 C CG1 . ILE A 1 43 ? 2.749 26.525 -26.016 1.00 53.11 ? ? ? ? ? ? 45 ILE A CG1 1 +ATOM 279 C CG2 . ILE A 1 43 ? 2.966 23.955 -26.167 1.00 50.96 ? ? ? ? ? ? 45 ILE A CG2 1 +ATOM 280 C CD1 . ILE A 1 43 ? 1.330 26.489 -25.511 1.00 48.47 ? ? ? ? ? ? 45 ILE A CD1 1 +ATOM 281 N N . ALA A 1 44 ? 5.708 23.687 -23.351 1.00 58.61 ? ? ? ? ? ? 46 ALA A N 1 +ATOM 282 C CA . ALA A 1 44 ? 7.019 23.104 -23.115 1.00 60.53 ? ? ? ? ? ? 46 ALA A CA 1 +ATOM 283 C C . ALA A 1 44 ? 7.098 21.728 -23.724 1.00 60.54 ? ? ? ? ? ? 46 ALA A C 1 +ATOM 284 O O . ALA A 1 44 ? 6.238 20.893 -23.489 1.00 58.05 ? ? ? ? ? ? 46 ALA A O 1 +ATOM 285 C CB . ALA A 1 44 ? 7.298 23.026 -21.643 1.00 61.04 ? ? ? ? ? ? 46 ALA A CB 1 +ATOM 286 N N . GLN A 1 45 ? 8.142 21.522 -24.518 1.00 63.39 ? ? ? ? ? ? 47 GLN A N 1 +ATOM 287 C CA . GLN A 1 45 ? 8.433 20.236 -25.131 1.00 64.77 ? ? ? ? ? ? 47 GLN A CA 1 +ATOM 288 C C . GLN A 1 45 ? 9.599 19.592 -24.406 1.00 67.08 ? ? ? ? ? ? 47 GLN A C 1 +ATOM 289 O O . GLN A 1 45 ? 10.492 20.287 -23.920 1.00 69.41 ? ? ? ? ? ? 47 GLN A O 1 +ATOM 290 C CB . GLN A 1 45 ? 8.791 20.423 -26.602 1.00 65.44 ? ? ? ? ? ? 47 GLN A CB 1 +ATOM 291 C CG . GLN A 1 45 ? 8.796 19.131 -27.399 1.00 65.31 ? ? ? ? ? ? 47 GLN A CG 1 +ATOM 292 C CD . GLN A 1 45 ? 9.318 19.305 -28.829 1.00 68.03 ? ? ? ? ? ? 47 GLN A CD 1 +ATOM 293 O OE1 . GLN A 1 45 ? 10.214 20.129 -29.090 1.00 70.64 ? ? ? ? ? ? 47 GLN A OE1 1 +ATOM 294 N NE2 . GLN A 1 45 ? 8.757 18.518 -29.767 1.00 65.95 ? ? ? ? ? ? 47 GLN A NE2 1 +ATOM 295 N N . PHE A 1 46 ? 9.590 18.266 -24.339 1.00 67.71 ? ? ? ? ? ? 48 PHE A N 1 +ATOM 296 C CA . PHE A 1 46 ? 10.706 17.526 -23.777 1.00 70.43 ? ? ? ? ? ? 48 PHE A CA 1 +ATOM 297 C C . PHE A 1 46 ? 11.857 17.437 -24.766 1.00 74.96 ? ? ? ? ? ? 48 PHE A C 1 +ATOM 298 O O . PHE A 1 46 ? 11.675 16.991 -25.907 1.00 74.94 ? ? ? ? ? ? 48 PHE A O 1 +ATOM 299 C CB . PHE A 1 46 ? 10.269 16.127 -23.384 1.00 67.85 ? ? ? ? ? ? 48 PHE A CB 1 +ATOM 300 C CG . PHE A 1 46 ? 9.527 16.081 -22.099 1.00 64.51 ? ? ? ? ? ? 48 PHE A CG 1 +ATOM 301 C CD1 . PHE A 1 46 ? 10.218 16.130 -20.894 1.00 65.87 ? ? ? ? ? ? 48 PHE A CD1 1 +ATOM 302 C CD2 . PHE A 1 46 ? 8.130 15.992 -22.085 1.00 59.45 ? ? ? ? ? ? 48 PHE A CD2 1 +ATOM 303 C CE1 . PHE A 1 46 ? 9.533 16.094 -19.687 1.00 63.95 ? ? ? ? ? ? 48 PHE A CE1 1 +ATOM 304 C CE2 . PHE A 1 46 ? 7.427 15.953 -20.885 1.00 57.67 ? ? ? ? ? ? 48 PHE A CE2 1 +ATOM 305 C CZ . PHE A 1 46 ? 8.130 16.002 -19.680 1.00 60.02 ? ? ? ? ? ? 48 PHE A CZ 1 +ATOM 306 N N . THR A 1 47 ? 13.038 17.869 -24.334 1.00 80.48 ? ? ? ? ? ? 49 THR A N 1 +ATOM 307 C CA . THR A 1 47 ? 14.238 17.712 -25.140 1.00 86.44 ? ? ? ? ? ? 49 THR A CA 1 +ATOM 308 C C . THR A 1 47 ? 14.993 16.474 -24.653 1.00 88.73 ? ? ? ? ? ? 49 THR A C 1 +ATOM 309 O O . THR A 1 47 ? 14.523 15.780 -23.752 1.00 86.98 ? ? ? ? ? ? 49 THR A O 1 +ATOM 310 C CB . THR A 1 47 ? 15.135 18.969 -25.068 1.00 89.11 ? ? ? ? ? ? 49 THR A CB 1 +ATOM 311 O OG1 . THR A 1 47 ? 15.953 18.934 -23.892 1.00 92.76 ? ? ? ? ? ? 49 THR A OG1 1 +ATOM 312 C CG2 . THR A 1 47 ? 14.285 20.230 -25.055 1.00 88.83 ? ? ? ? ? ? 49 THR A CG2 1 +ATOM 313 N N . GLU A 1 48 ? 16.145 16.187 -25.257 1.00 93.73 ? ? ? ? ? ? 50 GLU A N 1 +ATOM 314 C CA . GLU A 1 48 ? 17.052 15.170 -24.714 1.00 98.04 ? ? ? ? ? ? 50 GLU A CA 1 +ATOM 315 C C . GLU A 1 48 ? 17.700 15.685 -23.409 1.00 99.89 ? ? ? ? ? ? 50 GLU A C 1 +ATOM 316 O O . GLU A 1 48 ? 17.792 14.952 -22.420 1.00 99.46 ? ? ? ? ? ? 50 GLU A O 1 +ATOM 317 C CB . GLU A 1 48 ? 18.103 14.731 -25.754 1.00 100.79 ? ? ? ? ? ? 50 GLU A CB 1 +ATOM 318 C CG . GLU A 1 48 ? 19.096 15.818 -26.196 0.50 107.62 ? ? ? ? ? ? 50 GLU A CG 1 +ATOM 319 C CD . GLU A 1 48 ? 20.357 15.251 -26.838 0.50 115.10 ? ? ? ? ? ? 50 GLU A CD 1 +ATOM 320 O OE1 . GLU A 1 48 ? 21.467 15.702 -26.482 0.50 120.30 ? ? ? ? ? ? 50 GLU A OE1 1 +ATOM 321 O OE2 . GLU A 1 48 ? 20.241 14.354 -27.697 0.50 115.44 ? ? ? ? ? ? 50 GLU A OE2 1 +ATOM 322 N N . HIS A 1 49 ? 18.108 16.957 -23.422 1.00 102.54 ? ? ? ? ? ? 51 HIS A N 1 +ATOM 323 C CA . HIS A 1 49 ? 18.615 17.674 -22.247 1.00 104.56 ? ? ? ? ? ? 51 HIS A CA 1 +ATOM 324 C C . HIS A 1 49 ? 17.684 17.578 -21.032 1.00 100.90 ? ? ? ? ? ? 51 HIS A C 1 +ATOM 325 O O . HIS A 1 49 ? 18.145 17.604 -19.888 1.00 102.24 ? ? ? ? ? ? 51 HIS A O 1 +ATOM 326 C CB . HIS A 1 49 ? 18.790 19.162 -22.576 1.00 107.45 ? ? ? ? ? ? 51 HIS A CB 1 +ATOM 327 C CG . HIS A 1 49 ? 19.959 19.466 -23.458 1.00 115.35 ? ? ? ? ? ? 51 HIS A CG 1 +ATOM 328 N ND1 . HIS A 1 49 ? 19.964 19.199 -24.811 1.00 117.92 ? ? ? ? ? ? 51 HIS A ND1 1 +ATOM 329 C CD2 . HIS A 1 49 ? 21.153 20.047 -23.185 1.00 122.56 ? ? ? ? ? ? 51 HIS A CD2 1 +ATOM 330 C CE1 . HIS A 1 49 ? 21.117 19.586 -25.330 1.00 123.61 ? ? ? ? ? ? 51 HIS A CE1 1 +ATOM 331 N NE2 . HIS A 1 49 ? 21.855 20.106 -24.366 1.00 126.48 ? ? ? ? ? ? 51 HIS A NE2 1 +ATOM 332 N N . THR A 1 50 ? 16.377 17.481 -21.294 1.00 95.68 ? ? ? ? ? ? 52 THR A N 1 +ATOM 333 C CA . THR A 1 50 ? 15.340 17.640 -20.268 1.00 90.19 ? ? ? ? ? ? 52 THR A CA 1 +ATOM 334 C C . THR A 1 50 ? 14.528 16.370 -20.027 1.00 86.57 ? ? ? ? ? ? 52 THR A C 1 +ATOM 335 O O . THR A 1 50 ? 13.629 16.031 -20.795 1.00 83.93 ? ? ? ? ? ? 52 THR A O 1 +ATOM 336 C CB . THR A 1 50 ? 14.419 18.847 -20.596 1.00 89.09 ? ? ? ? ? ? 52 THR A CB 1 +ATOM 337 O OG1 . THR A 1 50 ? 15.128 20.061 -20.323 1.00 91.82 ? ? ? ? ? ? 52 THR A OG1 1 +ATOM 338 C CG2 . THR A 1 50 ? 13.158 18.832 -19.761 1.00 84.32 ? ? ? ? ? ? 52 THR A CG2 1 +ATOM 339 N N . SER A 1 51 ? 14.863 15.686 -18.938 1.00 85.07 ? ? ? ? ? ? 53 SER A N 1 +ATOM 340 C CA . SER A 1 51 ? 14.183 14.465 -18.518 1.00 82.20 ? ? ? ? ? ? 53 SER A CA 1 +ATOM 341 C C . SER A 1 51 ? 12.860 14.724 -17.792 1.00 78.23 ? ? ? ? ? ? 53 SER A C 1 +ATOM 342 O O . SER A 1 51 ? 11.863 14.057 -18.069 1.00 75.30 ? ? ? ? ? ? 53 SER A O 1 +ATOM 343 C CB . SER A 1 51 ? 15.103 13.617 -17.631 1.00 84.25 ? ? ? ? ? ? 53 SER A CB 1 +ATOM 344 O OG . SER A 1 51 ? 15.508 14.324 -16.475 1.00 87.22 ? ? ? ? ? ? 53 SER A OG 1 +ATOM 345 N N . ALA A 1 52 ? 12.855 15.681 -16.867 1.00 76.66 ? ? ? ? ? ? 54 ALA A N 1 +ATOM 346 C CA . ALA A 1 52 ? 11.660 15.983 -16.082 1.00 73.63 ? ? ? ? ? ? 54 ALA A CA 1 +ATOM 347 C C . ALA A 1 52 ? 11.347 17.470 -16.020 1.00 72.67 ? ? ? ? ? ? 54 ALA A C 1 +ATOM 348 O O . ALA A 1 52 ? 12.231 18.295 -16.168 1.00 74.97 ? ? ? ? ? ? 54 ALA A O 1 +ATOM 349 C CB . ALA A 1 52 ? 11.807 15.427 -14.697 1.00 73.72 ? ? ? ? ? ? 54 ALA A CB 1 +ATOM 350 N N . ILE A 1 53 ? 10.078 17.799 -15.808 1.00 69.28 ? ? ? ? ? ? 55 ILE A N 1 +ATOM 351 C CA . ILE A 1 53 ? 9.644 19.182 -15.648 1.00 67.60 ? ? ? ? ? ? 55 ILE A CA 1 +ATOM 352 C C . ILE A 1 53 ? 8.807 19.315 -14.386 1.00 66.31 ? ? ? ? ? ? 55 ILE A C 1 +ATOM 353 O O . ILE A 1 53 ? 7.813 18.615 -14.234 1.00 63.74 ? ? ? ? ? ? 55 ILE A O 1 +ATOM 354 C CB . ILE A 1 53 ? 8.816 19.679 -16.852 1.00 66.27 ? ? ? ? ? ? 55 ILE A CB 1 +ATOM 355 C CG1 . ILE A 1 53 ? 9.678 19.756 -18.104 1.00 67.47 ? ? ? ? ? ? 55 ILE A CG1 1 +ATOM 356 C CG2 . ILE A 1 53 ? 8.217 21.057 -16.579 1.00 65.21 ? ? ? ? ? ? 55 ILE A CG2 1 +ATOM 357 C CD1 . ILE A 1 53 ? 8.873 19.776 -19.383 1.00 65.20 ? ? ? ? ? ? 55 ILE A CD1 1 +ATOM 358 N N . LYS A 1 54 ? 9.212 20.225 -13.498 1.00 67.56 ? ? ? ? ? ? 56 LYS A N 1 +ATOM 359 C CA . LYS A 1 54 ? 8.518 20.471 -12.242 1.00 66.86 ? ? ? ? ? ? 56 LYS A CA 1 +ATOM 360 C C . LYS A 1 54 ? 7.790 21.787 -12.345 1.00 66.25 ? ? ? ? ? ? 56 LYS A C 1 +ATOM 361 O O . LYS A 1 54 ? 8.325 22.736 -12.899 1.00 67.88 ? ? ? ? ? ? 56 LYS A O 1 +ATOM 362 C CB . LYS A 1 54 ? 9.524 20.526 -11.091 1.00 69.15 ? ? ? ? ? ? 56 LYS A CB 1 +ATOM 363 C CG . LYS A 1 54 ? 8.919 20.527 -9.688 1.00 66.38 ? ? ? ? ? ? 56 LYS A CG 1 +ATOM 364 C CD . LYS A 1 54 ? 9.898 21.069 -8.644 1.00 66.41 ? ? ? ? ? ? 56 LYS A CD 1 +ATOM 365 C CE . LYS A 1 54 ? 10.805 19.996 -8.061 1.00 66.08 ? ? ? ? ? ? 56 LYS A CE 1 +ATOM 366 N NZ . LYS A 1 54 ? 11.738 20.531 -7.020 1.00 66.38 ? ? ? ? ? ? 56 LYS A NZ 1 +ATOM 367 N N . VAL A 1 55 ? 6.569 21.843 -11.826 1.00 63.79 ? ? ? ? ? ? 57 VAL A N 1 +ATOM 368 C CA . VAL A 1 55 ? 5.805 23.088 -11.783 1.00 62.60 ? ? ? ? ? ? 57 VAL A CA 1 +ATOM 369 C C . VAL A 1 55 ? 5.508 23.478 -10.335 1.00 63.99 ? ? ? ? ? ? 57 VAL A C 1 +ATOM 370 O O . VAL A 1 55 ? 4.827 22.751 -9.607 1.00 62.58 ? ? ? ? ? ? 57 VAL A O 1 +ATOM 371 C CB . VAL A 1 55 ? 4.491 22.999 -12.582 1.00 60.05 ? ? ? ? ? ? 57 VAL A CB 1 +ATOM 372 C CG1 . VAL A 1 55 ? 3.777 24.330 -12.592 1.00 58.65 ? ? ? ? ? ? 57 VAL A CG1 1 +ATOM 373 C CG2 . VAL A 1 55 ? 4.759 22.561 -14.001 1.00 57.89 ? ? ? ? ? ? 57 VAL A CG2 1 +ATOM 374 N N . ARG A 1 56 ? 6.046 24.625 -9.926 1.00 67.06 ? ? ? ? ? ? 58 ARG A N 1 +ATOM 375 C CA . ARG A 1 56 ? 5.822 25.201 -8.602 1.00 68.68 ? ? ? ? ? ? 58 ARG A CA 1 +ATOM 376 C C . ARG A 1 56 ? 4.944 26.430 -8.775 1.00 68.31 ? ? ? ? ? ? 58 ARG A C 1 +ATOM 377 O O . ARG A 1 56 ? 5.295 27.346 -9.516 1.00 69.78 ? ? ? ? ? ? 58 ARG A O 1 +ATOM 378 C CB . ARG A 1 56 ? 7.149 25.622 -7.961 1.00 71.82 ? ? ? ? ? ? 58 ARG A CB 1 +ATOM 379 C CG . ARG A 1 56 ? 7.919 24.540 -7.264 1.00 71.32 ? ? ? ? ? ? 58 ARG A CG 1 +ATOM 380 C CD . ARG A 1 56 ? 8.899 25.124 -6.251 1.00 74.34 ? ? ? ? ? ? 58 ARG A CD 1 +ATOM 381 N NE . ARG A 1 56 ? 10.303 24.967 -6.641 1.00 76.63 ? ? ? ? ? ? 58 ARG A NE 1 +ATOM 382 C CZ . ARG A 1 56 ? 11.114 24.011 -6.180 1.00 77.74 ? ? ? ? ? ? 58 ARG A CZ 1 +ATOM 383 N NH1 . ARG A 1 56 ? 10.668 23.111 -5.308 1.00 77.26 ? ? ? ? ? ? 58 ARG A NH1 1 +ATOM 384 N NH2 . ARG A 1 56 ? 12.380 23.947 -6.590 1.00 79.00 ? ? ? ? ? ? 58 ARG A NH2 1 +ATOM 385 N N . GLY A 1 57 ? 3.795 26.450 -8.116 1.00 66.23 ? ? ? ? ? ? 59 GLY A N 1 +ATOM 386 C CA . GLY A 1 57 ? 2.891 27.591 -8.224 1.00 64.54 ? ? ? ? ? ? 59 GLY A CA 1 +ATOM 387 C C . GLY A 1 57 ? 1.515 27.161 -8.671 1.00 61.40 ? ? ? ? ? ? 59 GLY A C 1 +ATOM 388 O O . GLY A 1 57 ? 1.324 26.011 -9.023 1.00 60.50 ? ? ? ? ? ? 59 GLY A O 1 +ATOM 389 N N . LYS A 1 58 ? 0.553 28.077 -8.652 1.00 59.63 ? ? ? ? ? ? 60 LYS A N 1 +ATOM 390 C CA . LYS A 1 58 ? -0.823 27.767 -9.030 1.00 56.33 ? ? ? ? ? ? 60 LYS A CA 1 +ATOM 391 C C . LYS A 1 58 ? -0.937 27.782 -10.560 1.00 54.36 ? ? ? ? ? ? 60 LYS A C 1 +ATOM 392 O O . LYS A 1 58 ? -0.806 28.840 -11.173 1.00 55.40 ? ? ? ? ? ? 60 LYS A O 1 +ATOM 393 C CB . LYS A 1 58 ? -1.776 28.800 -8.402 1.00 56.75 ? ? ? ? ? ? 60 LYS A CB 1 +ATOM 394 C CG . LYS A 1 58 ? -3.130 28.251 -7.937 1.00 56.71 ? ? ? ? ? ? 60 LYS A CG 1 +ATOM 395 C CD . LYS A 1 58 ? -3.097 27.743 -6.485 1.00 57.00 ? ? ? ? ? ? 60 LYS A CD 1 +ATOM 396 C CE . LYS A 1 58 ? -4.401 27.012 -6.119 1.00 56.07 ? ? ? ? ? ? 60 LYS A CE 1 +ATOM 397 N N . ALA A 1 59 ? -1.157 26.623 -11.185 1.00 50.90 ? ? ? ? ? ? 61 ALA A N 1 +ATOM 398 C CA . ALA A 1 59 ? -1.229 26.563 -12.652 1.00 48.01 ? ? ? ? ? ? 61 ALA A CA 1 +ATOM 399 C C . ALA A 1 59 ? -2.205 25.512 -13.166 1.00 44.63 ? ? ? ? ? ? 61 ALA A C 1 +ATOM 400 O O . ALA A 1 59 ? -2.516 24.556 -12.458 1.00 43.62 ? ? ? ? ? ? 61 ALA A O 1 +ATOM 401 C CB . ALA A 1 59 ? 0.153 26.320 -13.244 1.00 49.49 ? ? ? ? ? ? 61 ALA A CB 1 +ATOM 402 N N . TYR A 1 60 ? -2.667 25.686 -14.404 1.00 41.70 ? ? ? ? ? ? 62 TYR A N 1 +ATOM 403 C CA . TYR A 1 60 ? -3.493 24.707 -15.082 1.00 38.07 ? ? ? ? ? ? 62 TYR A CA 1 +ATOM 404 C C . TYR A 1 60 ? -2.627 24.044 -16.134 1.00 37.82 ? ? ? ? ? ? 62 TYR A C 1 +ATOM 405 O O . TYR A 1 60 ? -1.998 24.722 -16.954 1.00 38.91 ? ? ? ? ? ? 62 TYR A O 1 +ATOM 406 C CB . TYR A 1 60 ? -4.671 25.417 -15.716 1.00 36.81 ? ? ? ? ? ? 62 TYR A CB 1 +ATOM 407 C CG . TYR A 1 60 ? -5.719 24.566 -16.417 1.00 33.24 ? ? ? ? ? ? 62 TYR A CG 1 +ATOM 408 C CD1 . TYR A 1 60 ? -6.553 23.709 -15.702 1.00 30.81 ? ? ? ? ? ? 62 TYR A CD1 1 +ATOM 409 C CD2 . TYR A 1 60 ? -5.925 24.669 -17.795 1.00 32.16 ? ? ? ? ? ? 62 TYR A CD2 1 +ATOM 410 C CE1 . TYR A 1 60 ? -7.554 22.938 -16.349 1.00 26.98 ? ? ? ? ? ? 62 TYR A CE1 1 +ATOM 411 C CE2 . TYR A 1 60 ? -6.915 23.914 -18.446 1.00 29.38 ? ? ? ? ? ? 62 TYR A CE2 1 +ATOM 412 C CZ . TYR A 1 60 ? -7.728 23.053 -17.716 1.00 26.79 ? ? ? ? ? ? 62 TYR A CZ 1 +ATOM 413 O OH . TYR A 1 60 ? -8.701 22.329 -18.381 1.00 24.12 ? ? ? ? ? ? 62 TYR A OH 1 +ATOM 414 N N . ILE A 1 61 ? -2.579 22.717 -16.097 1.00 36.07 ? ? ? ? ? ? 63 ILE A N 1 +ATOM 415 C CA . ILE A 1 61 ? -1.662 21.980 -16.938 1.00 35.83 ? ? ? ? ? ? 63 ILE A CA 1 +ATOM 416 C C . ILE A 1 61 ? -2.384 20.971 -17.798 1.00 33.41 ? ? ? ? ? ? 63 ILE A C 1 +ATOM 417 O O . ILE A 1 61 ? -3.202 20.217 -17.298 1.00 31.94 ? ? ? ? ? ? 63 ILE A O 1 +ATOM 418 C CB . ILE A 1 61 ? -0.610 21.239 -16.097 1.00 37.09 ? ? ? ? ? ? 63 ILE A CB 1 +ATOM 419 C CG1 . ILE A 1 61 ? 0.153 22.208 -15.183 1.00 40.08 ? ? ? ? ? ? 63 ILE A CG1 1 +ATOM 420 C CG2 . ILE A 1 61 ? 0.358 20.461 -17.018 1.00 38.40 ? ? ? ? ? ? 63 ILE A CG2 1 +ATOM 421 C CD1 . ILE A 1 61 ? 0.912 21.521 -14.083 1.00 42.02 ? ? ? ? ? ? 63 ILE A CD1 1 +ATOM 422 N N . GLN A 1 62 ? -2.075 20.961 -19.094 1.00 32.65 ? ? ? ? ? ? 64 GLN A N 1 +ATOM 423 C CA . GLN A 1 62 ? -2.645 19.966 -20.035 1.00 31.02 ? ? ? ? ? ? 64 GLN A CA 1 +ATOM 424 C C . GLN A 1 62 ? -1.536 19.076 -20.577 1.00 31.29 ? ? ? ? ? ? 64 GLN A C 1 +ATOM 425 O O . GLN A 1 62 ? -0.503 19.573 -21.072 1.00 33.32 ? ? ? ? ? ? 64 GLN A O 1 +ATOM 426 C CB . GLN A 1 62 ? -3.321 20.649 -21.251 1.00 30.42 ? ? ? ? ? ? 64 GLN A CB 1 +ATOM 427 C CG . GLN A 1 62 ? -4.366 21.714 -20.928 1.00 29.89 ? ? ? ? ? ? 64 GLN A CG 1 +ATOM 428 C CD . GLN A 1 62 ? -5.024 22.308 -22.172 1.00 30.22 ? ? ? ? ? ? 64 GLN A CD 1 +ATOM 429 O OE1 . GLN A 1 62 ? -4.345 22.746 -23.129 1.00 31.89 ? ? ? ? ? ? 64 GLN A OE1 1 +ATOM 430 N NE2 . GLN A 1 62 ? -6.362 22.351 -22.155 1.00 28.53 ? ? ? ? ? ? 64 GLN A NE2 1 +ATOM 431 N N . THR A 1 63 ? -1.751 17.773 -20.518 1.00 29.70 ? ? ? ? ? ? 65 THR A N 1 +ATOM 432 C CA . THR A 1 63 ? -0.825 16.842 -21.142 1.00 29.95 ? ? ? ? ? ? 65 THR A CA 1 +ATOM 433 C C . THR A 1 63 ? -1.610 15.830 -21.967 1.00 28.22 ? ? ? ? ? ? 65 THR A C 1 +ATOM 434 O O . THR A 1 63 ? -2.852 15.745 -21.879 1.00 26.39 ? ? ? ? ? ? 65 THR A O 1 +ATOM 435 C CB . THR A 1 63 ? -0.010 16.071 -20.095 1.00 30.81 ? ? ? ? ? ? 65 THR A CB 1 +ATOM 436 O OG1 . THR A 1 63 ? -0.897 15.297 -19.248 1.00 30.42 ? ? ? ? ? ? 65 THR A OG1 1 +ATOM 437 C CG2 . THR A 1 63 ? 0.824 17.023 -19.275 1.00 33.74 ? ? ? ? ? ? 65 THR A CG2 1 +ATOM 438 N N . ARG A 1 64 ? -0.886 15.027 -22.737 1.00 28.10 ? ? ? ? ? ? 66 ARG A N 1 +ATOM 439 C CA . ARG A 1 64 ? -1.516 13.903 -23.389 1.00 26.73 ? ? ? ? ? ? 66 ARG A CA 1 +ATOM 440 C C . ARG A 1 64 ? -2.410 13.108 -22.409 1.00 25.08 ? ? ? ? ? ? 66 ARG A C 1 +ATOM 441 O O . ARG A 1 64 ? -3.376 12.454 -22.828 1.00 23.73 ? ? ? ? ? ? 66 ARG A O 1 +ATOM 442 C CB . ARG A 1 64 ? -0.460 13.014 -24.044 1.00 27.91 ? ? ? ? ? ? 66 ARG A CB 1 +ATOM 443 C CG . ARG A 1 64 ? -1.032 11.692 -24.648 1.00 29.01 ? ? ? ? ? ? 66 ARG A CG 1 +ATOM 444 C CD . ARG A 1 64 ? -0.213 11.224 -25.909 1.00 33.87 ? ? ? ? ? ? 66 ARG A CD 1 +ATOM 445 N NE . ARG A 1 64 ? 1.113 10.719 -25.542 1.00 39.87 ? ? ? ? ? ? 66 ARG A NE 1 +ATOM 446 C CZ . ARG A 1 64 ? 1.273 9.451 -25.149 1.00 45.46 ? ? ? ? ? ? 66 ARG A CZ 1 +ATOM 447 N NH1 . ARG A 1 64 ? 2.466 9.006 -24.775 1.00 48.49 ? ? ? ? ? ? 66 ARG A NH1 1 +ATOM 448 N NH2 . ARG A 1 64 ? 0.208 8.625 -25.112 1.00 45.95 ? ? ? ? ? ? 66 ARG A NH2 1 +ATOM 449 N N . HIS A 1 65 ? -2.111 13.173 -21.107 1.00 24.86 ? ? ? ? ? ? 67 HIS A N 1 +ATOM 450 C CA . HIS A 1 65 ? -2.841 12.331 -20.131 1.00 24.10 ? ? ? ? ? ? 67 HIS A CA 1 +ATOM 451 C C . HIS A 1 65 ? -4.020 13.013 -19.469 1.00 23.34 ? ? ? ? ? ? 67 HIS A C 1 +ATOM 452 O O . HIS A 1 65 ? -4.610 12.431 -18.508 1.00 22.91 ? ? ? ? ? ? 67 HIS A O 1 +ATOM 453 C CB . HIS A 1 65 ? -1.918 11.730 -19.064 1.00 24.80 ? ? ? ? ? ? 67 HIS A CB 1 +ATOM 454 C CG . HIS A 1 65 ? -0.816 10.907 -19.640 1.00 27.48 ? ? ? ? ? ? 67 HIS A CG 1 +ATOM 455 N ND1 . HIS A 1 65 ? -0.956 10.191 -20.818 1.00 28.09 ? ? ? ? ? ? 67 HIS A ND1 1 +ATOM 456 C CD2 . HIS A 1 65 ? 0.447 10.682 -19.209 1.00 30.60 ? ? ? ? ? ? 67 HIS A CD2 1 +ATOM 457 C CE1 . HIS A 1 65 ? 0.181 9.571 -21.091 1.00 30.69 ? ? ? ? ? ? 67 HIS A CE1 1 +ATOM 458 N NE2 . HIS A 1 65 ? 1.041 9.835 -20.121 1.00 32.56 ? ? ? ? ? ? 67 HIS A NE2 1 +ATOM 459 N N . GLY A 1 66 ? -4.357 14.217 -19.977 1.00 23.45 ? ? ? ? ? ? 68 GLY A N 1 +ATOM 460 C CA . GLY A 1 66 ? -5.543 14.957 -19.528 1.00 23.05 ? ? ? ? ? ? 68 GLY A CA 1 +ATOM 461 C C . GLY A 1 66 ? -5.125 16.212 -18.813 1.00 23.58 ? ? ? ? ? ? 68 GLY A C 1 +ATOM 462 O O . GLY A 1 66 ? -3.974 16.630 -18.952 1.00 24.68 ? ? ? ? ? ? 68 GLY A O 1 +ATOM 463 N N . VAL A 1 67 ? -6.046 16.822 -18.054 1.00 23.73 ? ? ? ? ? ? 69 VAL A N 1 +ATOM 464 C CA . VAL A 1 67 ? -5.685 18.035 -17.310 1.00 25.29 ? ? ? ? ? ? 69 VAL A CA 1 +ATOM 465 C C . VAL A 1 67 ? -5.378 17.774 -15.842 1.00 27.38 ? ? ? ? ? ? 69 VAL A C 1 +ATOM 466 O O . VAL A 1 67 ? -5.799 16.787 -15.265 1.00 26.03 ? ? ? ? ? ? 69 VAL A O 1 +ATOM 467 C CB . VAL A 1 67 ? -6.706 19.173 -17.463 1.00 24.18 ? ? ? ? ? ? 69 VAL A CB 1 +ATOM 468 C CG1 . VAL A 1 67 ? -7.328 19.087 -18.796 1.00 23.47 ? ? ? ? ? ? 69 VAL A CG1 1 +ATOM 469 C CG2 . VAL A 1 67 ? -7.792 19.078 -16.407 1.00 23.38 ? ? ? ? ? ? 69 VAL A CG2 1 +ATOM 470 N N . ILE A 1 68 ? -4.609 18.685 -15.274 1.00 31.58 ? ? ? ? ? ? 70 ILE A N 1 +ATOM 471 C CA . ILE A 1 68 ? -4.257 18.667 -13.875 1.00 35.85 ? ? ? ? ? ? 70 ILE A CA 1 +ATOM 472 C C . ILE A 1 68 ? -3.894 20.103 -13.437 1.00 40.48 ? ? ? ? ? ? 70 ILE A C 1 +ATOM 473 O O . ILE A 1 68 ? -3.442 20.943 -14.252 1.00 41.26 ? ? ? ? ? ? 70 ILE A O 1 +ATOM 474 C CB . ILE A 1 68 ? -3.137 17.660 -13.591 1.00 35.31 ? ? ? ? ? ? 70 ILE A CB 1 +ATOM 475 C CG1 . ILE A 1 68 ? -3.062 17.400 -12.099 1.00 34.94 ? ? ? ? ? ? 70 ILE A CG1 1 +ATOM 476 C CG2 . ILE A 1 68 ? -1.813 18.148 -14.144 1.00 36.89 ? ? ? ? ? ? 70 ILE A CG2 1 +ATOM 477 C CD1 . ILE A 1 68 ? -2.514 16.052 -11.774 1.00 34.03 ? ? ? ? ? ? 70 ILE A CD1 1 +ATOM 478 N N . GLU A 1 69 ? -4.123 20.367 -12.150 1.00 45.39 ? ? ? ? ? ? 71 GLU A N 1 +ATOM 479 C CA . GLU A 1 69 ? -3.959 21.684 -11.556 1.00 51.34 ? ? ? ? ? ? 71 GLU A CA 1 +ATOM 480 C C . GLU A 1 69 ? -2.832 21.594 -10.527 1.00 55.11 ? ? ? ? ? ? 71 GLU A C 1 +ATOM 481 O O . GLU A 1 69 ? -2.859 20.721 -9.664 1.00 55.41 ? ? ? ? ? ? 71 GLU A O 1 +ATOM 482 C CB . GLU A 1 69 ? -5.285 22.073 -10.896 1.00 50.78 ? ? ? ? ? ? 71 GLU A CB 1 +ATOM 483 C CG . GLU A 1 69 ? -5.358 23.453 -10.275 1.00 56.29 ? ? ? ? ? ? 71 GLU A CG 1 +ATOM 484 C CD . GLU A 1 69 ? -6.733 23.756 -9.687 1.00 59.81 ? ? ? ? ? ? 71 GLU A CD 1 +ATOM 485 O OE1 . GLU A 1 69 ? -6.805 24.062 -8.476 1.00 61.66 ? ? ? ? ? ? 71 GLU A OE1 1 +ATOM 486 O OE2 . GLU A 1 69 ? -7.742 23.685 -10.439 1.00 59.40 ? ? ? ? ? ? 71 GLU A OE2 1 +ATOM 487 N N . SER A 1 70 ? -1.830 22.463 -10.633 1.00 60.26 ? ? ? ? ? ? 72 SER A N 1 +ATOM 488 C CA . SER A 1 70 ? -0.785 22.528 -9.618 1.00 65.19 ? ? ? ? ? ? 72 SER A CA 1 +ATOM 489 C C . SER A 1 70 ? -1.191 23.554 -8.582 1.00 67.72 ? ? ? ? ? ? 72 SER A C 1 +ATOM 490 O O . SER A 1 70 ? -1.586 24.664 -8.933 1.00 68.67 ? ? ? ? ? ? 72 SER A O 1 +ATOM 491 C CB . SER A 1 70 ? 0.566 22.885 -10.232 1.00 66.81 ? ? ? ? ? ? 72 SER A CB 1 +ATOM 492 O OG . SER A 1 70 ? 0.520 24.141 -10.869 1.00 69.19 ? ? ? ? ? ? 72 SER A OG 1 +ATOM 493 N N . GLU A 1 71 ? -1.109 23.173 -7.312 1.00 70.07 ? ? ? ? ? ? 73 GLU A N 1 +ATOM 494 C CA . GLU A 1 71 ? -1.494 24.038 -6.212 1.00 72.36 ? ? ? ? ? ? 73 GLU A CA 1 +ATOM 495 C C . GLU A 1 71 ? -0.236 24.266 -5.347 1.00 75.16 ? ? ? ? ? ? 73 GLU A C 1 +ATOM 496 O O . GLU A 1 71 ? -0.249 24.010 -4.173 1.00 77.08 ? ? ? ? ? ? 73 GLU A O 1 +ATOM 497 C CB . GLU A 1 71 ? -2.606 23.360 -5.394 1.00 71.07 ? ? ? ? ? ? 73 GLU A CB 1 +ATOM 498 C CG . GLU A 1 71 ? -3.410 22.310 -6.167 1.00 69.29 ? ? ? ? ? ? 73 GLU A CG 1 +ATOM 499 C CD . GLU A 1 71 ? -4.836 22.110 -5.652 1.00 67.49 ? ? ? ? ? ? 73 GLU A CD 1 +ATOM 500 O OE1 . GLU A 1 71 ? -5.627 23.072 -5.780 1.00 67.26 ? ? ? ? ? ? 73 GLU A OE1 1 +ATOM 501 O OE2 . GLU A 1 71 ? -5.169 20.998 -5.157 1.00 64.72 ? ? ? ? ? ? 73 GLU A OE2 1 +ATOM 502 N N . GLY A 1 72 ? 0.917 24.600 -5.926 1.00 75.64 ? ? ? ? ? ? 74 GLY A N 1 +ATOM 503 C CA . GLY A 1 72 ? 2.179 24.627 -5.145 1.00 76.28 ? ? ? ? ? ? 74 GLY A CA 1 +ATOM 504 C C . GLY A 1 72 ? 2.532 25.958 -4.485 1.00 77.39 ? ? ? ? ? ? 74 GLY A C 1 +ATOM 505 O O . GLY A 1 72 ? 1.761 26.914 -4.592 1.00 77.60 ? ? ? ? ? ? 74 GLY A O 1 +ATOM 506 N N . LYS A 1 73 ? 3.692 26.048 -3.818 1.00 78.11 ? ? ? ? ? ? 75 LYS A N 1 +ATOM 507 C CA . LYS A 1 73 ? 4.129 27.336 -3.223 1.00 79.14 ? ? ? ? ? ? 75 LYS A CA 1 +ATOM 508 C C . LYS A 1 73 ? 4.479 28.474 -4.244 1.00 79.69 ? ? ? ? ? ? 75 LYS A C 1 +ATOM 509 O O . LYS A 1 73 ? 5.535 28.516 -4.903 1.00 79.72 ? ? ? ? ? ? 75 LYS A O 1 +ATOM 510 C CB . LYS A 1 73 ? 5.211 27.143 -2.149 1.00 79.82 ? ? ? ? ? ? 75 LYS A CB 1 +ATOM 511 C CG . LYS A 1 73 ? 6.646 27.001 -2.680 1.00 82.03 ? ? ? ? ? ? 75 LYS A CG 1 +ATOM 512 C CD . LYS A 1 73 ? 7.702 26.968 -1.556 1.00 83.81 ? ? ? ? ? ? 75 LYS A CD 1 +ATOM 513 C CE . LYS A 1 73 ? 9.130 26.847 -2.110 1.00 84.65 ? ? ? ? ? ? 75 LYS A CE 1 +ATOM 514 N NZ . LYS A 1 73 ? 10.106 26.489 -1.037 1.00 84.64 ? ? ? ? ? ? 75 LYS A NZ 1 diff --git a/modules/seq/alg/tests/testfiles/align_to_seqres_valueerror.mmcif b/modules/seq/alg/tests/testfiles/align_to_seqres_valueerror.mmcif new file mode 100644 index 0000000000000000000000000000000000000000..fd150386f4a9ee2b5b37be54323e96830d2ccd14 --- /dev/null +++ b/modules/seq/alg/tests/testfiles/align_to_seqres_valueerror.mmcif @@ -0,0 +1,564 @@ +data_3BAR +# based on 3AQD +_entry.id 3BAR +# +loop_ +_entity.id +_entity.type +_entity.src_method +_entity.pdbx_description +_entity.formula_weight +_entity.pdbx_number_of_molecules +_entity.details +1 polymer man 'Transcription attenuation protein mtrB' 8257.458 22 ? +2 water nat water 18.015 7 ? +# +_entity_poly.entity_id 1 +_entity_poly.type 'polypeptide(L)' +_entity_poly.nstd_linkage no +_entity_poly.nstd_monomer no +_entity_poly.pdbx_seq_one_letter_code MYTNSDFVVIKALEDWVNVIGLTRGADTRFHHSEKLDKGEVLIAQFTEHTSAIKVRGKAYIQTRHGVIESEGKK +_entity_poly.pdbx_seq_one_letter_code_can MYTNSDFVVIKALEDWVNVIGLTRGADTRFHHSEKLDKGEVLIAQFTEHTSAIKVRGKAYIQTRHGVIESEGKK +_entity_poly.pdbx_strand_id A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V +# +loop_ +_atom_site.group_PDB +_atom_site.id +_atom_site.type_symbol +_atom_site.label_atom_id +_atom_site.label_alt_id +_atom_site.label_comp_id +_atom_site.label_asym_id +_atom_site.label_entity_id +_atom_site.label_seq_id +_atom_site.pdbx_PDB_ins_code +_atom_site.Cartn_x +_atom_site.Cartn_y +_atom_site.Cartn_z +_atom_site.occupancy +_atom_site.B_iso_or_equiv +_atom_site.Cartn_x_esd +_atom_site.Cartn_y_esd +_atom_site.Cartn_z_esd +_atom_site.occupancy_esd +_atom_site.B_iso_or_equiv_esd +_atom_site.pdbx_formal_charge +_atom_site.auth_seq_id +_atom_site.auth_comp_id +_atom_site.auth_asym_id +_atom_site.auth_atom_id +_atom_site.pdbx_PDB_model_num +ATOM 1 N N . SER A 1 5 ? 8.892 13.236 -28.550 1.00 81.62 ? ? ? ? ? ? 7 SER A N 1 +ATOM 2 C CA . SER A 1 5 ? 8.449 14.550 -29.128 1.00 80.98 ? ? ? ? ? ? 7 SER A CA 1 +ATOM 3 C C . SER A 1 5 ? 7.181 15.159 -28.476 1.00 77.44 ? ? ? ? ? ? 7 SER A C 1 +ATOM 4 O O . SER A 1 5 ? 6.463 15.940 -29.117 1.00 76.80 ? ? ? ? ? ? 7 SER A O 1 +ATOM 5 C CB . SER A 1 5 ? 8.239 14.416 -30.651 1.00 81.96 ? ? ? ? ? ? 7 SER A CB 1 +ATOM 6 O OG . SER A 1 5 ? 9.441 14.629 -31.378 1.00 87.04 ? ? ? ? ? ? 7 SER A OG 1 +ATOM 7 N N . ASP A 1 6 ? 6.910 14.822 -27.217 1.00 73.87 ? ? ? ? ? ? 8 ASP A N 1 +ATOM 8 C CA . ASP A 1 6 ? 5.670 15.258 -26.582 1.00 69.40 ? ? ? ? ? ? 8 ASP A CA 1 +ATOM 9 C C . ASP A 1 6 ? 5.834 16.550 -25.785 1.00 68.43 ? ? ? ? ? ? 8 ASP A C 1 +ATOM 10 O O . ASP A 1 6 ? 6.944 16.907 -25.403 1.00 70.90 ? ? ? ? ? ? 8 ASP A O 1 +ATOM 11 C CB . ASP A 1 6 ? 5.104 14.146 -25.703 1.00 67.64 ? ? ? ? ? ? 8 ASP A CB 1 +ATOM 12 C CG . ASP A 1 6 ? 3.570 14.083 -25.751 1.00 64.57 ? ? ? ? ? ? 8 ASP A CG 1 +ATOM 13 O OD1 . ASP A 1 6 ? 2.949 15.085 -26.195 1.00 63.11 ? ? ? ? ? ? 8 ASP A OD1 1 +ATOM 14 O OD2 . ASP A 1 6 ? 2.984 13.032 -25.353 1.00 62.17 ? ? ? ? ? ? 8 ASP A OD2 1 +ATOM 15 N N . PHE A 1 7 ? 4.726 17.246 -25.545 1.00 64.53 ? ? ? ? ? ? 9 PHE A N 1 +ATOM 16 C CA . PHE A 1 7 ? 4.750 18.548 -24.879 1.00 61.94 ? ? ? ? ? ? 9 PHE A CA 1 +ATOM 17 C C . PHE A 1 7 ? 3.673 18.732 -23.796 1.00 57.92 ? ? ? ? ? ? 9 PHE A C 1 +ATOM 18 O O . PHE A 1 7 ? 2.693 17.987 -23.744 1.00 55.70 ? ? ? ? ? ? 9 PHE A O 1 +ATOM 19 C CB . PHE A 1 7 ? 4.618 19.664 -25.915 1.00 63.43 ? ? ? ? ? ? 9 PHE A CB 1 +ATOM 20 C CG . PHE A 1 7 ? 3.282 19.718 -26.567 1.00 62.41 ? ? ? ? ? ? 9 PHE A CG 1 +ATOM 21 C CD1 . PHE A 1 7 ? 2.231 20.382 -25.970 1.00 61.82 ? ? ? ? ? ? 9 PHE A CD1 1 +ATOM 22 C CD2 . PHE A 1 7 ? 3.075 19.105 -27.775 1.00 64.02 ? ? ? ? ? ? 9 PHE A CD2 1 +ATOM 23 C CE1 . PHE A 1 7 ? 0.988 20.428 -26.567 1.00 60.16 ? ? ? ? ? ? 9 PHE A CE1 1 +ATOM 24 C CE2 . PHE A 1 7 ? 1.832 19.145 -28.383 1.00 62.57 ? ? ? ? ? ? 9 PHE A CE2 1 +ATOM 25 C CZ . PHE A 1 7 ? 0.783 19.808 -27.775 1.00 60.25 ? ? ? ? ? ? 9 PHE A CZ 1 +ATOM 26 N N . VAL A 1 8 ? 3.861 19.735 -22.938 1.00 55.04 ? ? ? ? ? ? 10 VAL A N 1 +ATOM 27 C CA . VAL A 1 8 ? 2.861 20.095 -21.949 1.00 50.88 ? ? ? ? ? ? 10 VAL A CA 1 +ATOM 28 C C . VAL A 1 8 ? 2.487 21.551 -22.098 1.00 49.54 ? ? ? ? ? ? 10 VAL A C 1 +ATOM 29 O O . VAL A 1 8 ? 3.323 22.385 -22.446 1.00 50.85 ? ? ? ? ? ? 10 VAL A O 1 +ATOM 30 C CB . VAL A 1 8 ? 3.326 19.851 -20.511 1.00 51.03 ? ? ? ? ? ? 10 VAL A CB 1 +ATOM 31 C CG1 . VAL A 1 8 ? 3.832 18.442 -20.371 1.00 50.13 ? ? ? ? ? ? 10 VAL A CG1 1 +ATOM 32 C CG2 . VAL A 1 8 ? 4.402 20.826 -20.090 1.00 53.19 ? ? ? ? ? ? 10 VAL A CG2 1 +ATOM 33 N N . VAL A 1 9 ? 1.215 21.844 -21.842 1.00 46.06 ? ? ? ? ? ? 11 VAL A N 1 +ATOM 34 C CA . VAL A 1 9 ? 0.687 23.206 -21.880 1.00 44.00 ? ? ? ? ? ? 11 VAL A CA 1 +ATOM 35 C C . VAL A 1 9 ? 0.489 23.603 -20.434 1.00 44.21 ? ? ? ? ? ? 11 VAL A C 1 +ATOM 36 O O . VAL A 1 9 ? -0.170 22.877 -19.678 1.00 42.41 ? ? ? ? ? ? 11 VAL A O 1 +ATOM 37 C CB . VAL A 1 9 ? -0.661 23.252 -22.624 1.00 42.00 ? ? ? ? ? ? 11 VAL A CB 1 +ATOM 38 C CG1 . VAL A 1 9 ? -1.295 24.607 -22.528 1.00 40.79 ? ? ? ? ? ? 11 VAL A CG1 1 +ATOM 39 C CG2 . VAL A 1 9 ? -0.455 22.906 -24.078 1.00 40.13 ? ? ? ? ? ? 11 VAL A CG2 1 +ATOM 40 N N . ILE A 1 10 ? 1.076 24.738 -20.056 1.00 46.10 ? ? ? ? ? ? 12 ILE A N 1 +ATOM 41 C CA . ILE A 1 10 ? 1.003 25.240 -18.696 1.00 47.51 ? ? ? ? ? ? 12 ILE A CA 1 +ATOM 42 C C . ILE A 1 10 ? 0.516 26.657 -18.743 1.00 48.05 ? ? ? ? ? ? 12 ILE A C 1 +ATOM 43 O O . ILE A 1 10 ? 1.137 27.508 -19.380 1.00 49.65 ? ? ? ? ? ? 12 ILE A O 1 +ATOM 44 C CB . ILE A 1 10 ? 2.374 25.247 -18.012 1.00 49.28 ? ? ? ? ? ? 12 ILE A CB 1 +ATOM 45 C CG1 . ILE A 1 10 ? 2.981 23.848 -18.003 1.00 49.95 ? ? ? ? ? ? 12 ILE A CG1 1 +ATOM 46 C CG2 . ILE A 1 10 ? 2.247 25.753 -16.603 1.00 50.91 ? ? ? ? ? ? 12 ILE A CG2 1 +ATOM 47 C CD1 . ILE A 1 10 ? 4.435 23.827 -17.677 1.00 54.16 ? ? ? ? ? ? 12 ILE A CD1 1 +ATOM 48 N N . LYS A 1 11 ? -0.606 26.901 -18.076 1.00 47.39 ? ? ? ? ? ? 13 LYS A N 1 +ATOM 49 C CA . LYS A 1 11 ? -1.139 28.252 -17.917 1.00 48.23 ? ? ? ? ? ? 13 LYS A CA 1 +ATOM 50 C C . LYS A 1 11 ? -0.998 28.660 -16.473 1.00 50.10 ? ? ? ? ? ? 13 LYS A C 1 +ATOM 51 O O . LYS A 1 11 ? -1.441 27.931 -15.579 1.00 49.40 ? ? ? ? ? ? 13 LYS A O 1 +ATOM 52 C CB . LYS A 1 11 ? -2.609 28.311 -18.304 1.00 46.00 ? ? ? ? ? ? 13 LYS A CB 1 +ATOM 53 C CG . LYS A 1 11 ? -3.144 29.706 -18.267 1.00 45.91 ? ? ? ? ? ? 13 LYS A CG 1 +ATOM 54 C CD . LYS A 1 11 ? -4.640 29.741 -18.402 1.00 43.12 ? ? ? ? ? ? 13 LYS A CD 1 +ATOM 55 C CE . LYS A 1 11 ? -5.103 31.182 -18.619 1.00 44.02 ? ? ? ? ? ? 13 LYS A CE 1 +ATOM 56 N NZ . LYS A 1 11 ? -6.563 31.312 -18.363 1.00 43.35 ? ? ? ? ? ? 13 LYS A NZ 1 +ATOM 57 N N . ALA A 1 12 ? -0.379 29.818 -16.242 1.00 53.49 ? ? ? ? ? ? 14 ALA A N 1 +ATOM 58 C CA . ALA A 1 12 ? -0.115 30.296 -14.876 1.00 55.56 ? ? ? ? ? ? 14 ALA A CA 1 +ATOM 59 C C . ALA A 1 12 ? -1.354 30.960 -14.272 1.00 55.44 ? ? ? ? ? ? 14 ALA A C 1 +ATOM 60 O O . ALA A 1 12 ? -1.938 31.848 -14.881 1.00 55.76 ? ? ? ? ? ? 14 ALA A O 1 +ATOM 61 C CB . ALA A 1 12 ? 1.042 31.240 -14.890 1.00 58.43 ? ? ? ? ? ? 14 ALA A CB 1 +ATOM 62 N N . LEU A 1 13 ? -1.767 30.514 -13.093 1.00 55.02 ? ? ? ? ? ? 15 LEU A N 1 +ATOM 63 C CA . LEU A 1 13 ? -2.966 31.063 -12.438 1.00 55.23 ? ? ? ? ? ? 15 LEU A CA 1 +ATOM 64 C C . LEU A 1 13 ? -2.665 32.145 -11.380 1.00 58.70 ? ? ? ? ? ? 15 LEU A C 1 +ATOM 65 O O . LEU A 1 13 ? -3.574 32.758 -10.809 1.00 58.84 ? ? ? ? ? ? 15 LEU A O 1 +ATOM 66 C CB . LEU A 1 13 ? -3.811 29.932 -11.832 1.00 52.50 ? ? ? ? ? ? 15 LEU A CB 1 +ATOM 67 C CG . LEU A 1 13 ? -4.415 28.951 -12.839 1.00 47.91 ? ? ? ? ? ? 15 LEU A CG 1 +ATOM 68 C CD1 . LEU A 1 13 ? -4.953 27.698 -12.151 1.00 44.21 ? ? ? ? ? ? 15 LEU A CD1 1 +ATOM 69 C CD2 . LEU A 1 13 ? -5.494 29.672 -13.668 1.00 46.05 ? ? ? ? ? ? 15 LEU A CD2 1 +ATOM 70 N N . GLU A 1 14 ? -1.379 32.359 -11.120 1.00 62.66 ? ? ? ? ? ? 16 GLU A N 1 +ATOM 71 C CA . GLU A 1 14 ? -0.899 33.425 -10.252 1.00 67.00 ? ? ? ? ? ? 16 GLU A CA 1 +ATOM 72 C C . GLU A 1 14 ? 0.409 33.922 -10.836 1.00 70.32 ? ? ? ? ? ? 16 GLU A C 1 +ATOM 73 O O . GLU A 1 14 ? 0.914 33.339 -11.785 1.00 70.03 ? ? ? ? ? ? 16 GLU A O 1 +ATOM 74 C CB . GLU A 1 14 ? -0.696 32.923 -8.819 1.00 67.19 ? ? ? ? ? ? 16 GLU A CB 1 +ATOM 75 C CG . GLU A 1 14 ? 0.432 31.895 -8.625 1.00 68.58 ? ? ? ? ? ? 16 GLU A CG 1 +ATOM 76 C CD . GLU A 1 14 ? 0.454 31.270 -7.222 1.00 70.39 ? ? ? ? ? ? 16 GLU A CD 1 +ATOM 77 O OE1 . GLU A 1 14 ? -0.457 31.541 -6.412 1.00 71.02 ? ? ? ? ? ? 16 GLU A OE1 1 +ATOM 78 O OE2 . GLU A 1 14 ? 1.387 30.491 -6.926 1.00 71.29 ? ? ? ? ? ? 16 GLU A OE2 1 +ATOM 79 N N . ASP A 1 15 ? 0.955 35.001 -10.285 1.00 74.75 ? ? ? ? ? ? 17 ASP A N 1 +ATOM 80 C CA . ASP A 1 15 ? 2.250 35.491 -10.740 1.00 78.78 ? ? ? ? ? ? 17 ASP A CA 1 +ATOM 81 C C . ASP A 1 15 ? 3.325 34.615 -10.138 1.00 79.87 ? ? ? ? ? ? 17 ASP A C 1 +ATOM 82 O O . ASP A 1 15 ? 3.099 33.950 -9.124 1.00 79.33 ? ? ? ? ? ? 17 ASP A O 1 +ATOM 83 C CB . ASP A 1 15 ? 2.475 36.953 -10.336 1.00 81.65 ? ? ? ? ? ? 17 ASP A CB 1 +ATOM 84 C CG . ASP A 1 15 ? 1.621 37.937 -11.140 1.00 83.16 ? ? ? ? ? ? 17 ASP A CG 1 +ATOM 85 O OD1 . ASP A 1 15 ? 1.344 37.691 -12.326 1.00 82.40 ? ? ? ? ? ? 17 ASP A OD1 1 +ATOM 86 O OD2 . ASP A 1 15 ? 1.231 38.982 -10.589 1.00 86.46 ? ? ? ? ? ? 17 ASP A OD2 1 +ATOM 87 N N . GLY A 1 16 ? 4.489 34.606 -10.778 1.00 81.58 ? ? ? ? ? ? 18 GLY A N 1 +ATOM 88 C CA . GLY A 1 16 ? 5.660 33.903 -10.248 1.00 82.57 ? ? ? ? ? ? 18 GLY A CA 1 +ATOM 89 C C . GLY A 1 16 ? 5.555 32.392 -10.154 1.00 80.35 ? ? ? ? ? ? 18 GLY A C 1 +ATOM 90 O O . GLY A 1 16 ? 6.059 31.793 -9.215 1.00 81.29 ? ? ? ? ? ? 18 GLY A O 1 +ATOM 91 N N . VAL A 1 17 ? 4.892 31.781 -11.128 1.00 77.56 ? ? ? ? ? ? 19 VAL A N 1 +ATOM 92 C CA . VAL A 1 17 ? 4.885 30.336 -11.259 1.00 74.50 ? ? ? ? ? ? 19 VAL A CA 1 +ATOM 93 C C . VAL A 1 17 ? 6.239 29.942 -11.826 1.00 76.68 ? ? ? ? ? ? 19 VAL A C 1 +ATOM 94 O O . VAL A 1 17 ? 6.799 30.655 -12.655 1.00 78.24 ? ? ? ? ? ? 19 VAL A O 1 +ATOM 95 C CB . VAL A 1 17 ? 3.755 29.861 -12.187 1.00 71.56 ? ? ? ? ? ? 19 VAL A CB 1 +ATOM 96 C CG1 . VAL A 1 17 ? 3.820 28.364 -12.384 1.00 67.63 ? ? ? ? ? ? 19 VAL A CG1 1 +ATOM 97 C CG2 . VAL A 1 17 ? 2.409 30.247 -11.611 1.00 67.92 ? ? ? ? ? ? 19 VAL A CG2 1 +ATOM 98 N N . ASN A 1 18 ? 6.764 28.812 -11.381 1.00 77.33 ? ? ? ? ? ? 20 ASN A N 1 +ATOM 99 C CA . ASN A 1 18 ? 8.086 28.396 -11.775 1.00 79.46 ? ? ? ? ? ? 20 ASN A CA 1 +ATOM 100 C C . ASN A 1 18 ? 8.067 27.069 -12.528 1.00 77.29 ? ? ? ? ? ? 20 ASN A C 1 +ATOM 101 O O . ASN A 1 18 ? 7.635 26.058 -11.989 1.00 75.60 ? ? ? ? ? ? 20 ASN A O 1 +ATOM 102 C CB . ASN A 1 18 ? 8.941 28.291 -10.526 1.00 82.30 ? ? ? ? ? ? 20 ASN A CB 1 +ATOM 103 C CG . ASN A 1 18 ? 10.360 28.739 -10.753 1.00 89.13 ? ? ? ? ? ? 20 ASN A CG 1 +ATOM 104 O OD1 . ASN A 1 18 ? 10.690 29.305 -11.791 1.00 92.93 ? ? ? ? ? ? 20 ASN A OD1 1 +ATOM 105 N ND2 . ASN A 1 18 ? 11.217 28.488 -9.773 1.00 94.39 ? ? ? ? ? ? 20 ASN A ND2 1 +ATOM 106 N N . VAL A 1 19 ? 8.521 27.077 -13.779 1.00 76.88 ? ? ? ? ? ? 21 VAL A N 1 +ATOM 107 C CA . VAL A 1 19 ? 8.542 25.871 -14.600 1.00 75.28 ? ? ? ? ? ? 21 VAL A CA 1 +ATOM 108 C C . VAL A 1 19 ? 9.970 25.398 -14.720 1.00 78.52 ? ? ? ? ? ? 21 VAL A C 1 +ATOM 109 O O . VAL A 1 19 ? 10.747 25.948 -15.489 1.00 80.53 ? ? ? ? ? ? 21 VAL A O 1 +ATOM 110 C CB . VAL A 1 19 ? 7.946 26.104 -16.005 1.00 73.54 ? ? ? ? ? ? 21 VAL A CB 1 +ATOM 111 C CG1 . VAL A 1 19 ? 7.966 24.838 -16.807 1.00 70.33 ? ? ? ? ? ? 21 VAL A CG1 1 +ATOM 112 C CG2 . VAL A 1 19 ? 6.528 26.602 -15.913 1.00 69.44 ? ? ? ? ? ? 21 VAL A CG2 1 +ATOM 113 N N . ILE A 1 20 ? 10.305 24.368 -13.960 1.00 80.07 ? ? ? ? ? ? 22 ILE A N 1 +ATOM 114 C CA . ILE A 1 20 ? 11.683 23.949 -13.817 1.00 83.77 ? ? ? ? ? ? 22 ILE A CA 1 +ATOM 115 C C . ILE A 1 20 ? 12.004 22.729 -14.664 1.00 83.74 ? ? ? ? ? ? 22 ILE A C 1 +ATOM 116 O O . ILE A 1 20 ? 11.349 21.705 -14.536 1.00 81.42 ? ? ? ? ? ? 22 ILE A O 1 +ATOM 117 C CB . ILE A 1 20 ? 12.014 23.661 -12.348 1.00 84.59 ? ? ? ? ? ? 22 ILE A CB 1 +ATOM 118 C CG1 . ILE A 1 20 ? 11.522 24.802 -11.467 1.00 85.96 ? ? ? ? ? ? 22 ILE A CG1 1 +ATOM 119 C CG2 . ILE A 1 20 ? 13.511 23.484 -12.166 1.00 89.81 ? ? ? ? ? ? 22 ILE A CG2 1 +ATOM 120 C CD1 . ILE A 1 20 ? 11.484 24.464 -9.998 1.00 87.43 ? ? ? ? ? ? 22 ILE A CD1 1 +ATOM 121 N N . GLY A 1 21 ? 13.019 22.862 -15.520 1.00 86.57 ? ? ? ? ? ? 23 GLY A N 1 +ATOM 122 C CA . GLY A 1 21 ? 13.522 21.775 -16.358 1.00 88.60 ? ? ? ? ? ? 23 GLY A CA 1 +ATOM 123 C C . GLY A 1 21 ? 14.674 21.070 -15.675 1.00 91.29 ? ? ? ? ? ? 23 GLY A C 1 +ATOM 124 O O . GLY A 1 21 ? 15.573 21.716 -15.154 1.00 94.14 ? ? ? ? ? ? 23 GLY A O 1 +ATOM 125 N N . LEU A 1 22 ? 14.642 19.743 -15.672 1.00 91.36 ? ? ? ? ? ? 24 LEU A N 1 +ATOM 126 C CA . LEU A 1 22 ? 15.603 18.932 -14.926 1.00 92.96 ? ? ? ? ? ? 24 LEU A CA 1 +ATOM 127 C C . LEU A 1 22 ? 16.447 18.089 -15.876 1.00 94.68 ? ? ? ? ? ? 24 LEU A C 1 +ATOM 128 O O . LEU A 1 22 ? 15.939 17.601 -16.885 1.00 94.04 ? ? ? ? ? ? 24 LEU A O 1 +ATOM 129 C CB . LEU A 1 22 ? 14.860 18.047 -13.924 1.00 91.08 ? ? ? ? ? ? 24 LEU A CB 1 +ATOM 130 C CG . LEU A 1 22 ? 14.551 18.518 -12.493 1.00 90.38 ? ? ? ? ? ? 24 LEU A CG 1 +ATOM 131 C CD1 . LEU A 1 22 ? 14.342 20.009 -12.384 1.00 91.01 ? ? ? ? ? ? 24 LEU A CD1 1 +ATOM 132 C CD2 . LEU A 1 22 ? 13.342 17.791 -11.921 1.00 85.41 ? ? ? ? ? ? 24 LEU A CD2 1 +ATOM 133 N N . THR A 1 23 ? 17.733 17.926 -15.565 1.00 96.47 ? ? ? ? ? ? 25 THR A N 1 +ATOM 134 C CA . THR A 1 23 ? 18.688 17.343 -16.531 1.00 98.30 ? ? ? ? ? ? 25 THR A CA 1 +ATOM 135 C C . THR A 1 23 ? 19.007 15.862 -16.352 1.00 98.49 ? ? ? ? ? ? 25 THR A C 1 +ATOM 136 O O . THR A 1 23 ? 18.826 15.304 -15.266 1.00 98.19 ? ? ? ? ? ? 25 THR A O 1 +ATOM 137 C CB . THR A 1 23 ? 20.028 18.102 -16.553 1.00 100.21 ? ? ? ? ? ? 25 THR A CB 1 +ATOM 138 O OG1 . THR A 1 23 ? 20.490 18.282 -15.208 1.00 101.37 ? ? ? ? ? ? 25 THR A OG1 1 +ATOM 139 C CG2 . THR A 1 23 ? 19.883 19.457 -17.252 1.00 100.72 ? ? ? ? ? ? 25 THR A CG2 1 +ATOM 140 N N . ARG A 1 24 ? 19.501 15.246 -17.430 1.00 99.49 ? ? ? ? ? ? 26 ARG A N 1 +ATOM 141 C CA . ARG A 1 24 ? 19.857 13.819 -17.452 1.00 99.94 ? ? ? ? ? ? 26 ARG A CA 1 +ATOM 142 C C . ARG A 1 24 ? 21.154 13.541 -16.693 1.00 101.44 ? ? ? ? ? ? 26 ARG A C 1 +ATOM 143 O O . ARG A 1 24 ? 22.240 13.904 -17.147 1.00 103.26 ? ? ? ? ? ? 26 ARG A O 1 +ATOM 144 C CB . ARG A 1 24 ? 19.955 13.281 -18.893 1.00 100.14 ? ? ? ? ? ? 26 ARG A CB 1 +ATOM 145 C CG . ARG A 1 24 ? 18.620 13.217 -19.642 1.00 99.36 ? ? ? ? ? ? 26 ARG A CG 1 +ATOM 146 C CD . ARG A 1 24 ? 18.634 12.164 -20.759 1.00 100.98 ? ? ? ? ? ? 26 ARG A CD 1 +ATOM 147 N NE . ARG A 1 24 ? 17.552 12.352 -21.740 1.00 100.55 ? ? ? ? ? ? 26 ARG A NE 1 +ATOM 148 C CZ . ARG A 1 24 ? 17.231 11.494 -22.716 1.00 99.98 ? ? ? ? ? ? 26 ARG A CZ 1 +ATOM 149 N NH1 . ARG A 1 24 ? 17.891 10.344 -22.876 1.00 99.60 ? ? ? ? ? ? 26 ARG A NH1 1 +ATOM 150 N NH2 . ARG A 1 24 ? 16.229 11.791 -23.537 1.00 99.33 ? ? ? ? ? ? 26 ARG A NH2 1 +ATOM 151 N N . THR A 1 28 ? 22.527 16.428 -12.721 1.00 120.13 ? ? ? ? ? ? 30 THR A N 1 +ATOM 152 C CA . THR A 1 28 ? 21.235 15.835 -13.090 1.00 118.47 ? ? ? ? ? ? 30 THR A CA 1 +ATOM 153 C C . THR A 1 28 ? 20.021 16.467 -12.351 1.00 117.17 ? ? ? ? ? ? 30 THR A C 1 +ATOM 154 O O . THR A 1 28 ? 18.867 16.073 -12.593 1.00 115.70 ? ? ? ? ? ? 30 THR A O 1 +ATOM 155 C CB . THR A 1 28 ? 21.259 14.241 -13.007 1.00 118.06 ? ? ? ? ? ? 30 THR A CB 1 +ATOM 156 O OG1 . THR A 1 28 ? 19.946 13.697 -13.234 1.00 116.11 ? ? ? ? ? ? 30 THR A OG1 1 +ATOM 157 C CG2 . THR A 1 28 ? 21.822 13.727 -11.660 1.00 118.37 ? ? ? ? ? ? 30 THR A CG2 1 +ATOM 158 N N . ARG A 1 29 ? 20.289 17.464 -11.492 1.00 117.71 ? ? ? ? ? ? 31 ARG A N 1 +ATOM 159 C CA . ARG A 1 29 ? 19.261 18.091 -10.604 1.00 116.35 ? ? ? ? ? ? 31 ARG A CA 1 +ATOM 160 C C . ARG A 1 29 ? 18.477 19.294 -11.195 1.00 115.56 ? ? ? ? ? ? 31 ARG A C 1 +ATOM 161 O O . ARG A 1 29 ? 18.271 19.360 -12.420 1.00 115.47 ? ? ? ? ? ? 31 ARG A O 1 +ATOM 162 C CB . ARG A 1 29 ? 19.840 18.428 -9.204 1.00 117.16 ? ? ? ? ? ? 31 ARG A CB 1 +ATOM 163 C CG . ARG A 1 29 ? 21.320 18.904 -9.113 1.00 119.11 ? ? ? ? ? ? 31 ARG A CG 1 +ATOM 164 C CD . ARG A 1 29 ? 21.638 20.210 -9.857 1.00 119.60 ? ? ? ? ? ? 31 ARG A CD 1 +ATOM 165 N NE . ARG A 1 29 ? 22.419 19.952 -11.068 1.00 120.44 ? ? ? ? ? ? 31 ARG A NE 1 +ATOM 166 C CZ . ARG A 1 29 ? 21.980 20.123 -12.315 1.00 119.80 ? ? ? ? ? ? 31 ARG A CZ 1 +ATOM 167 N NH1 . ARG A 1 29 ? 22.780 19.853 -13.337 1.00 121.30 ? ? ? ? ? ? 31 ARG A NH1 1 +ATOM 168 N NH2 . ARG A 1 29 ? 20.756 20.576 -12.552 1.00 117.87 ? ? ? ? ? ? 31 ARG A NH2 1 +ATOM 169 N N . PHE A 1 30 ? 18.052 20.228 -10.323 1.00 114.83 ? ? ? ? ? ? 32 PHE A N 1 +ATOM 170 C CA . PHE A 1 30 ? 17.248 21.413 -10.728 1.00 113.80 ? ? ? ? ? ? 32 PHE A CA 1 +ATOM 171 C C . PHE A 1 30 ? 18.047 22.475 -11.541 1.00 114.52 ? ? ? ? ? ? 32 PHE A C 1 +ATOM 172 O O . PHE A 1 30 ? 18.937 23.145 -11.001 1.00 115.82 ? ? ? ? ? ? 32 PHE A O 1 +ATOM 173 C CB . PHE A 1 30 ? 16.487 22.093 -9.541 1.00 113.41 ? ? ? ? ? ? 32 PHE A CB 1 +ATOM 174 C CG . PHE A 1 30 ? 16.144 21.179 -8.346 1.00 112.64 ? ? ? ? ? ? 32 PHE A CG 1 +ATOM 175 C CD1 . PHE A 1 30 ? 15.540 21.740 -7.207 1.00 112.23 ? ? ? ? ? ? 32 PHE A CD1 1 +ATOM 176 C CD2 . PHE A 1 30 ? 16.423 19.805 -8.338 1.00 111.84 ? ? ? ? ? ? 32 PHE A CD2 1 +ATOM 177 C CE1 . PHE A 1 30 ? 15.212 20.957 -6.091 1.00 111.54 ? ? ? ? ? ? 32 PHE A CE1 1 +ATOM 178 C CE2 . PHE A 1 30 ? 16.110 19.015 -7.218 1.00 111.19 ? ? ? ? ? ? 32 PHE A CE2 1 +ATOM 179 C CZ . PHE A 1 30 ? 15.497 19.590 -6.097 1.00 111.08 ? ? ? ? ? ? 32 PHE A CZ 1 +ATOM 180 N N . HIS A 1 31 ? 17.677 22.645 -12.817 1.00 113.18 ? ? ? ? ? ? 33 HIS A N 1 +ATOM 181 C CA . HIS A 1 31 ? 18.505 23.317 -13.836 1.00 113.51 ? ? ? ? ? ? 33 HIS A CA 1 +ATOM 182 C C . HIS A 1 31 ? 17.843 24.573 -14.459 1.00 112.40 ? ? ? ? ? ? 33 HIS A C 1 +ATOM 183 O O . HIS A 1 31 ? 17.840 25.650 -13.849 1.00 112.91 ? ? ? ? ? ? 33 HIS A O 1 +ATOM 184 C CB . HIS A 1 31 ? 18.897 22.274 -14.908 1.00 113.74 ? ? ? ? ? ? 33 HIS A CB 1 +ATOM 185 C CG . HIS A 1 31 ? 19.881 22.761 -15.933 1.00 116.22 ? ? ? ? ? ? 33 HIS A CG 1 +ATOM 186 N ND1 . HIS A 1 31 ? 21.201 23.036 -15.635 1.00 118.98 ? ? ? ? ? ? 33 HIS A ND1 1 +ATOM 187 C CD2 . HIS A 1 31 ? 19.743 22.976 -17.264 1.00 116.72 ? ? ? ? ? ? 33 HIS A CD2 1 +ATOM 188 C CE1 . HIS A 1 31 ? 21.826 23.425 -16.734 1.00 120.25 ? ? ? ? ? ? 33 HIS A CE1 1 +ATOM 189 N NE2 . HIS A 1 31 ? 20.964 23.395 -17.736 1.00 119.10 ? ? ? ? ? ? 33 HIS A NE2 1 +ATOM 190 N N . HIS A 1 32 ? 17.298 24.431 -15.670 1.00 110.63 ? ? ? ? ? ? 34 HIS A N 1 +ATOM 191 C CA . HIS A 1 32 ? 16.630 25.529 -16.377 1.00 108.57 ? ? ? ? ? ? 34 HIS A CA 1 +ATOM 192 C C . HIS A 1 32 ? 15.315 25.908 -15.701 1.00 105.41 ? ? ? ? ? ? 34 HIS A C 1 +ATOM 193 O O . HIS A 1 32 ? 14.336 25.165 -15.760 1.00 102.47 ? ? ? ? ? ? 34 HIS A O 1 +ATOM 194 C CB . HIS A 1 32 ? 16.384 25.161 -17.858 1.00 108.29 ? ? ? ? ? ? 34 HIS A CB 1 +ATOM 195 C CG . HIS A 1 32 ? 15.859 26.296 -18.697 1.00 108.03 ? ? ? ? ? ? 34 HIS A CG 1 +ATOM 196 N ND1 . HIS A 1 32 ? 16.492 27.522 -18.778 1.00 111.34 ? ? ? ? ? ? 34 HIS A ND1 1 +ATOM 197 C CD2 . HIS A 1 32 ? 14.778 26.380 -19.511 1.00 103.90 ? ? ? ? ? ? 34 HIS A CD2 1 +ATOM 198 C CE1 . HIS A 1 32 ? 15.812 28.317 -19.586 1.00 109.77 ? ? ? ? ? ? 34 HIS A CE1 1 +ATOM 199 N NE2 . HIS A 1 32 ? 14.772 27.647 -20.051 1.00 105.66 ? ? ? ? ? ? 34 HIS A NE2 1 +ATOM 200 N N . SER A 1 33 ? 15.303 27.064 -15.056 1.00 104.75 ? ? ? ? ? ? 35 SER A N 1 +ATOM 201 C CA . SER A 1 33 ? 14.079 27.599 -14.485 1.00 101.92 ? ? ? ? ? ? 35 SER A CA 1 +ATOM 202 C C . SER A 1 33 ? 13.450 28.601 -15.456 1.00 99.94 ? ? ? ? ? ? 35 SER A C 1 +ATOM 203 O O . SER A 1 33 ? 14.146 29.196 -16.272 1.00 101.93 ? ? ? ? ? ? 35 SER A O 1 +ATOM 204 C CB . SER A 1 33 ? 14.372 28.236 -13.124 1.00 103.64 ? ? ? ? ? ? 35 SER A CB 1 +ATOM 205 O OG . SER A 1 33 ? 13.401 29.202 -12.771 1.00 103.74 ? ? ? ? ? ? 35 SER A OG 1 +ATOM 206 N N . GLU A 1 34 ? 12.136 28.778 -15.372 1.00 95.30 ? ? ? ? ? ? 36 GLU A N 1 +ATOM 207 C CA . GLU A 1 34 ? 11.425 29.699 -16.249 1.00 92.35 ? ? ? ? ? ? 36 GLU A CA 1 +ATOM 208 C C . GLU A 1 34 ? 10.221 30.272 -15.520 1.00 90.03 ? ? ? ? ? ? 36 GLU A C 1 +ATOM 209 O O . GLU A 1 34 ? 9.296 29.543 -15.201 1.00 87.29 ? ? ? ? ? ? 36 GLU A O 1 +ATOM 210 C CB . GLU A 1 34 ? 10.977 28.964 -17.511 1.00 90.67 ? ? ? ? ? ? 36 GLU A CB 1 +ATOM 211 C CG . GLU A 1 34 ? 10.555 29.867 -18.650 1.00 90.72 ? ? ? ? ? ? 36 GLU A CG 1 +ATOM 212 C CD . GLU A 1 34 ? 11.736 30.565 -19.310 1.00 96.24 ? ? ? ? ? ? 36 GLU A CD 1 +ATOM 213 O OE1 . GLU A 1 34 ? 12.815 29.937 -19.462 1.00 99.38 ? ? ? ? ? ? 36 GLU A OE1 1 +ATOM 214 O OE2 . GLU A 1 34 ? 11.578 31.748 -19.685 1.00 98.37 ? ? ? ? ? ? 36 GLU A OE2 1 +ATOM 215 N N . LYS A 1 35 ? 10.235 31.569 -15.239 1.00 90.36 ? ? ? ? ? ? 37 LYS A N 1 +ATOM 216 C CA . LYS A 1 35 ? 9.139 32.178 -14.506 1.00 88.38 ? ? ? ? ? ? 37 LYS A CA 1 +ATOM 217 C C . LYS A 1 35 ? 7.977 32.484 -15.433 1.00 85.67 ? ? ? ? ? ? 37 LYS A C 1 +ATOM 218 O O . LYS A 1 35 ? 8.172 32.833 -16.592 1.00 86.06 ? ? ? ? ? ? 37 LYS A O 1 +ATOM 219 C CB . LYS A 1 35 ? 9.601 33.433 -13.768 1.00 91.44 ? ? ? ? ? ? 37 LYS A CB 1 +ATOM 220 N N . LEU A 1 36 ? 6.766 32.325 -14.915 1.00 81.92 ? ? ? ? ? ? 38 LEU A N 1 +ATOM 221 C CA . LEU A 1 36 ? 5.539 32.641 -15.640 1.00 78.89 ? ? ? ? ? ? 38 LEU A CA 1 +ATOM 222 C C . LEU A 1 36 ? 4.640 33.528 -14.797 1.00 78.12 ? ? ? ? ? ? 38 LEU A C 1 +ATOM 223 O O . LEU A 1 36 ? 4.498 33.299 -13.601 1.00 77.83 ? ? ? ? ? ? 38 LEU A O 1 +ATOM 224 C CB . LEU A 1 36 ? 4.770 31.368 -15.979 1.00 77.62 ? ? ? ? ? ? 38 LEU A CB 1 +ATOM 225 C CG . LEU A 1 36 ? 4.861 30.675 -17.336 1.00 76.31 ? ? ? ? ? ? 38 LEU A CG 1 +ATOM 226 C CD1 . LEU A 1 36 ? 3.481 30.149 -17.653 1.00 74.28 ? ? ? ? ? ? 38 LEU A CD1 1 +ATOM 227 C CD2 . LEU A 1 36 ? 5.328 31.599 -18.436 1.00 76.23 ? ? ? ? ? ? 38 LEU A CD2 1 +ATOM 228 N N . ASP A 1 37 ? 4.015 34.523 -15.417 1.00 77.70 ? ? ? ? ? ? 39 ASP A N 1 +ATOM 229 C CA . ASP A 1 37 ? 3.127 35.429 -14.691 1.00 77.42 ? ? ? ? ? ? 39 ASP A CA 1 +ATOM 230 C C . ASP A 1 37 ? 1.666 35.169 -15.004 1.00 73.58 ? ? ? ? ? ? 39 ASP A C 1 +ATOM 231 O O . ASP A 1 37 ? 1.352 34.676 -16.075 1.00 72.04 ? ? ? ? ? ? 39 ASP A O 1 +ATOM 232 C CB . ASP A 1 37 ? 3.473 36.886 -14.995 1.00 80.86 ? ? ? ? ? ? 39 ASP A CB 1 +ATOM 233 C CG . ASP A 1 37 ? 4.632 37.408 -14.159 1.00 86.94 ? ? ? ? ? ? 39 ASP A CG 1 +ATOM 234 O OD1 . ASP A 1 37 ? 4.986 36.781 -13.125 1.00 88.70 ? ? ? ? ? ? 39 ASP A OD1 1 +ATOM 235 O OD2 . ASP A 1 37 ? 5.178 38.463 -14.548 1.00 92.58 ? ? ? ? ? ? 39 ASP A OD2 1 +ATOM 236 N N . LYS A 1 38 ? 0.788 35.520 -14.065 1.00 71.09 ? ? ? ? ? ? 40 LYS A N 1 +ATOM 237 C CA . LYS A 1 38 ? -0.646 35.219 -14.127 1.00 67.44 ? ? ? ? ? ? 40 LYS A CA 1 +ATOM 238 C C . LYS A 1 38 ? -1.246 35.395 -15.514 1.00 65.75 ? ? ? ? ? ? 40 LYS A C 1 +ATOM 239 O O . LYS A 1 38 ? -1.274 36.506 -16.038 1.00 66.82 ? ? ? ? ? ? 40 LYS A O 1 +ATOM 240 C CB . LYS A 1 38 ? -1.408 36.092 -13.130 1.00 67.43 ? ? ? ? ? ? 40 LYS A CB 1 +ATOM 241 C CG . LYS A 1 38 ? -2.847 35.692 -12.912 1.00 65.33 ? ? ? ? ? ? 40 LYS A CG 1 +ATOM 242 C CD . LYS A 1 38 ? -3.496 36.530 -11.819 1.00 65.17 ? ? ? ? ? ? 40 LYS A CD 1 +ATOM 243 C CE . LYS A 1 38 ? -4.727 35.828 -11.238 1.00 64.58 ? ? ? ? ? ? 40 LYS A CE 1 +ATOM 244 N NZ . LYS A 1 38 ? -5.911 36.738 -11.093 1.00 64.29 ? ? ? ? ? ? 40 LYS A NZ 1 +ATOM 245 N N . GLY A 1 39 ? -1.710 34.288 -16.097 1.00 62.75 ? ? ? ? ? ? 41 GLY A N 1 +ATOM 246 C CA . GLY A 1 39 ? -2.358 34.280 -17.410 1.00 60.49 ? ? ? ? ? ? 41 GLY A CA 1 +ATOM 247 C C . GLY A 1 39 ? -1.471 33.947 -18.599 1.00 60.30 ? ? ? ? ? ? 41 GLY A C 1 +ATOM 248 O O . GLY A 1 39 ? -1.957 33.805 -19.718 1.00 58.95 ? ? ? ? ? ? 41 GLY A O 1 +ATOM 249 N N . GLU A 1 40 ? -0.167 33.843 -18.366 1.00 61.59 ? ? ? ? ? ? 42 GLU A N 1 +ATOM 250 C CA . GLU A 1 40 ? 0.777 33.499 -19.424 1.00 62.43 ? ? ? ? ? ? 42 GLU A CA 1 +ATOM 251 C C . GLU A 1 40 ? 0.720 32.015 -19.667 1.00 59.62 ? ? ? ? ? ? 42 GLU A C 1 +ATOM 252 O O . GLU A 1 40 ? 0.425 31.239 -18.761 1.00 58.37 ? ? ? ? ? ? 42 GLU A O 1 +ATOM 253 C CB . GLU A 1 40 ? 2.200 33.917 -19.056 1.00 65.52 ? ? ? ? ? ? 42 GLU A CB 1 +ATOM 254 C CG . GLU A 1 40 ? 2.523 35.352 -19.404 1.00 71.75 ? ? ? ? ? ? 42 GLU A CG 1 +ATOM 255 C CD . GLU A 1 40 ? 3.754 35.879 -18.701 1.00 79.02 ? ? ? ? ? ? 42 GLU A CD 1 +ATOM 256 O OE1 . GLU A 1 40 ? 4.375 35.124 -17.926 1.00 79.96 ? ? ? ? ? ? 42 GLU A OE1 1 +ATOM 257 O OE2 . GLU A 1 40 ? 4.097 37.059 -18.923 1.00 83.29 ? ? ? ? ? ? 42 GLU A OE2 1 +ATOM 258 N N . VAL A 1 41 ? 1.004 31.619 -20.895 1.00 58.12 ? ? ? ? ? ? 43 VAL A N 1 +ATOM 259 C CA . VAL A 1 41 ? 0.931 30.221 -21.282 1.00 55.42 ? ? ? ? ? ? 43 VAL A CA 1 +ATOM 260 C C . VAL A 1 41 ? 2.254 29.747 -21.855 1.00 57.22 ? ? ? ? ? ? 43 VAL A C 1 +ATOM 261 O O . VAL A 1 41 ? 2.823 30.381 -22.755 1.00 58.88 ? ? ? ? ? ? 43 VAL A O 1 +ATOM 262 C CB . VAL A 1 41 ? -0.180 29.994 -22.309 1.00 53.28 ? ? ? ? ? ? 43 VAL A CB 1 +ATOM 263 C CG1 . VAL A 1 41 ? -0.060 28.645 -22.920 1.00 50.49 ? ? ? ? ? ? 43 VAL A CG1 1 +ATOM 264 C CG2 . VAL A 1 41 ? -1.523 30.132 -21.664 1.00 49.78 ? ? ? ? ? ? 43 VAL A CG2 1 +ATOM 265 N N . LEU A 1 42 ? 2.738 28.629 -21.323 1.00 57.21 ? ? ? ? ? ? 44 LEU A N 1 +ATOM 266 C CA . LEU A 1 42 ? 3.960 28.037 -21.813 1.00 58.54 ? ? ? ? ? ? 44 LEU A CA 1 +ATOM 267 C C . LEU A 1 42 ? 3.633 26.718 -22.458 1.00 56.54 ? ? ? ? ? ? 44 LEU A C 1 +ATOM 268 O O . LEU A 1 42 ? 2.882 25.928 -21.899 1.00 54.68 ? ? ? ? ? ? 44 LEU A O 1 +ATOM 269 C CB . LEU A 1 42 ? 4.954 27.852 -20.680 1.00 60.35 ? ? ? ? ? ? 44 LEU A CB 1 +ATOM 270 C CG . LEU A 1 42 ? 6.378 27.476 -21.074 1.00 64.66 ? ? ? ? ? ? 44 LEU A CG 1 +ATOM 271 C CD1 . LEU A 1 42 ? 7.071 28.595 -21.816 1.00 69.92 ? ? ? ? ? ? 44 LEU A CD1 1 +ATOM 272 C CD2 . LEU A 1 42 ? 7.171 27.112 -19.839 1.00 67.81 ? ? ? ? ? ? 44 LEU A CD2 1 +ATOM 273 N N . ILE A 1 43 ? 4.162 26.504 -23.657 1.00 56.61 ? ? ? ? ? ? 45 ILE A N 1 +ATOM 274 C CA . ILE A 1 43 ? 4.086 25.207 -24.298 1.00 55.49 ? ? ? ? ? ? 45 ILE A CA 1 +ATOM 275 C C . ILE A 1 43 ? 5.487 24.630 -24.267 1.00 57.96 ? ? ? ? ? ? 45 ILE A C 1 +ATOM 276 O O . ILE A 1 43 ? 6.345 25.038 -25.046 1.00 60.01 ? ? ? ? ? ? 45 ILE A O 1 +ATOM 277 C CB . ILE A 1 43 ? 3.621 25.276 -25.757 1.00 54.45 ? ? ? ? ? ? 45 ILE A CB 1 +ATOM 278 C CG1 . ILE A 1 43 ? 2.749 26.525 -26.016 1.00 53.11 ? ? ? ? ? ? 45 ILE A CG1 1 +ATOM 279 C CG2 . ILE A 1 43 ? 2.966 23.955 -26.167 1.00 50.96 ? ? ? ? ? ? 45 ILE A CG2 1 +ATOM 280 C CD1 . ILE A 1 43 ? 1.330 26.489 -25.511 1.00 48.47 ? ? ? ? ? ? 45 ILE A CD1 1 +ATOM 281 N N . ALA A 1 44 ? 5.708 23.687 -23.351 1.00 58.61 ? ? ? ? ? ? 46 ALA A N 1 +ATOM 282 C CA . ALA A 1 44 ? 7.019 23.104 -23.115 1.00 60.53 ? ? ? ? ? ? 46 ALA A CA 1 +ATOM 283 C C . ALA A 1 44 ? 7.098 21.728 -23.724 1.00 60.54 ? ? ? ? ? ? 46 ALA A C 1 +ATOM 284 O O . ALA A 1 44 ? 6.238 20.893 -23.489 1.00 58.05 ? ? ? ? ? ? 46 ALA A O 1 +ATOM 285 C CB . ALA A 1 44 ? 7.298 23.026 -21.643 1.00 61.04 ? ? ? ? ? ? 46 ALA A CB 1 +ATOM 286 N N . GLN A 1 45 ? 8.142 21.522 -24.518 1.00 63.39 ? ? ? ? ? ? 47 GLN A N 1 +ATOM 287 C CA . GLN A 1 45 ? 8.433 20.236 -25.131 1.00 64.77 ? ? ? ? ? ? 47 GLN A CA 1 +ATOM 288 C C . GLN A 1 45 ? 9.599 19.592 -24.406 1.00 67.08 ? ? ? ? ? ? 47 GLN A C 1 +ATOM 289 O O . GLN A 1 45 ? 10.492 20.287 -23.920 1.00 69.41 ? ? ? ? ? ? 47 GLN A O 1 +ATOM 290 C CB . GLN A 1 45 ? 8.791 20.423 -26.602 1.00 65.44 ? ? ? ? ? ? 47 GLN A CB 1 +ATOM 291 C CG . GLN A 1 45 ? 8.796 19.131 -27.399 1.00 65.31 ? ? ? ? ? ? 47 GLN A CG 1 +ATOM 292 C CD . GLN A 1 45 ? 9.318 19.305 -28.829 1.00 68.03 ? ? ? ? ? ? 47 GLN A CD 1 +ATOM 293 O OE1 . GLN A 1 45 ? 10.214 20.129 -29.090 1.00 70.64 ? ? ? ? ? ? 47 GLN A OE1 1 +ATOM 294 N NE2 . GLN A 1 45 ? 8.757 18.518 -29.767 1.00 65.95 ? ? ? ? ? ? 47 GLN A NE2 1 +ATOM 295 N N . PHE A 1 46 ? 9.590 18.266 -24.339 1.00 67.71 ? ? ? ? ? ? 48 PHE A N 1 +ATOM 296 C CA . PHE A 1 46 ? 10.706 17.526 -23.777 1.00 70.43 ? ? ? ? ? ? 48 PHE A CA 1 +ATOM 297 C C . PHE A 1 46 ? 11.857 17.437 -24.766 1.00 74.96 ? ? ? ? ? ? 48 PHE A C 1 +ATOM 298 O O . PHE A 1 46 ? 11.675 16.991 -25.907 1.00 74.94 ? ? ? ? ? ? 48 PHE A O 1 +ATOM 299 C CB . PHE A 1 46 ? 10.269 16.127 -23.384 1.00 67.85 ? ? ? ? ? ? 48 PHE A CB 1 +ATOM 300 C CG . PHE A 1 46 ? 9.527 16.081 -22.099 1.00 64.51 ? ? ? ? ? ? 48 PHE A CG 1 +ATOM 301 C CD1 . PHE A 1 46 ? 10.218 16.130 -20.894 1.00 65.87 ? ? ? ? ? ? 48 PHE A CD1 1 +ATOM 302 C CD2 . PHE A 1 46 ? 8.130 15.992 -22.085 1.00 59.45 ? ? ? ? ? ? 48 PHE A CD2 1 +ATOM 303 C CE1 . PHE A 1 46 ? 9.533 16.094 -19.687 1.00 63.95 ? ? ? ? ? ? 48 PHE A CE1 1 +ATOM 304 C CE2 . PHE A 1 46 ? 7.427 15.953 -20.885 1.00 57.67 ? ? ? ? ? ? 48 PHE A CE2 1 +ATOM 305 C CZ . PHE A 1 46 ? 8.130 16.002 -19.680 1.00 60.02 ? ? ? ? ? ? 48 PHE A CZ 1 +ATOM 306 N N . THR A 1 47 ? 13.038 17.869 -24.334 1.00 80.48 ? ? ? ? ? ? 49 THR A N 1 +ATOM 307 C CA . THR A 1 47 ? 14.238 17.712 -25.140 1.00 86.44 ? ? ? ? ? ? 49 THR A CA 1 +ATOM 308 C C . THR A 1 47 ? 14.993 16.474 -24.653 1.00 88.73 ? ? ? ? ? ? 49 THR A C 1 +ATOM 309 O O . THR A 1 47 ? 14.523 15.780 -23.752 1.00 86.98 ? ? ? ? ? ? 49 THR A O 1 +ATOM 310 C CB . THR A 1 47 ? 15.135 18.969 -25.068 1.00 89.11 ? ? ? ? ? ? 49 THR A CB 1 +ATOM 311 O OG1 . THR A 1 47 ? 15.953 18.934 -23.892 1.00 92.76 ? ? ? ? ? ? 49 THR A OG1 1 +ATOM 312 C CG2 . THR A 1 47 ? 14.285 20.230 -25.055 1.00 88.83 ? ? ? ? ? ? 49 THR A CG2 1 +ATOM 313 N N . GLU A 1 48 ? 16.145 16.187 -25.257 1.00 93.73 ? ? ? ? ? ? 50 GLU A N 1 +ATOM 314 C CA . GLU A 1 48 ? 17.052 15.170 -24.714 1.00 98.04 ? ? ? ? ? ? 50 GLU A CA 1 +ATOM 315 C C . GLU A 1 48 ? 17.700 15.685 -23.409 1.00 99.89 ? ? ? ? ? ? 50 GLU A C 1 +ATOM 316 O O . GLU A 1 48 ? 17.792 14.952 -22.420 1.00 99.46 ? ? ? ? ? ? 50 GLU A O 1 +ATOM 317 C CB . GLU A 1 48 ? 18.103 14.731 -25.754 1.00 100.79 ? ? ? ? ? ? 50 GLU A CB 1 +ATOM 318 C CG . GLU A 1 48 ? 19.096 15.818 -26.196 0.50 107.62 ? ? ? ? ? ? 50 GLU A CG 1 +ATOM 319 C CD . GLU A 1 48 ? 20.357 15.251 -26.838 0.50 115.10 ? ? ? ? ? ? 50 GLU A CD 1 +ATOM 320 O OE1 . GLU A 1 48 ? 21.467 15.702 -26.482 0.50 120.30 ? ? ? ? ? ? 50 GLU A OE1 1 +ATOM 321 O OE2 . GLU A 1 48 ? 20.241 14.354 -27.697 0.50 115.44 ? ? ? ? ? ? 50 GLU A OE2 1 +ATOM 322 N N . HIS A 1 49 ? 18.108 16.957 -23.422 1.00 102.54 ? ? ? ? ? ? 51 HIS A N 1 +ATOM 323 C CA . HIS A 1 49 ? 18.615 17.674 -22.247 1.00 104.56 ? ? ? ? ? ? 51 HIS A CA 1 +ATOM 324 C C . HIS A 1 49 ? 17.684 17.578 -21.032 1.00 100.90 ? ? ? ? ? ? 51 HIS A C 1 +ATOM 325 O O . HIS A 1 49 ? 18.145 17.604 -19.888 1.00 102.24 ? ? ? ? ? ? 51 HIS A O 1 +ATOM 326 C CB . HIS A 1 49 ? 18.790 19.162 -22.576 1.00 107.45 ? ? ? ? ? ? 51 HIS A CB 1 +ATOM 327 C CG . HIS A 1 49 ? 19.959 19.466 -23.458 1.00 115.35 ? ? ? ? ? ? 51 HIS A CG 1 +ATOM 328 N ND1 . HIS A 1 49 ? 19.964 19.199 -24.811 1.00 117.92 ? ? ? ? ? ? 51 HIS A ND1 1 +ATOM 329 C CD2 . HIS A 1 49 ? 21.153 20.047 -23.185 1.00 122.56 ? ? ? ? ? ? 51 HIS A CD2 1 +ATOM 330 C CE1 . HIS A 1 49 ? 21.117 19.586 -25.330 1.00 123.61 ? ? ? ? ? ? 51 HIS A CE1 1 +ATOM 331 N NE2 . HIS A 1 49 ? 21.855 20.106 -24.366 1.00 126.48 ? ? ? ? ? ? 51 HIS A NE2 1 +ATOM 332 N N . THR A 1 50 ? 16.377 17.481 -21.294 1.00 95.68 ? ? ? ? ? ? 52 THR A N 1 +ATOM 333 C CA . THR A 1 50 ? 15.340 17.640 -20.268 1.00 90.19 ? ? ? ? ? ? 52 THR A CA 1 +ATOM 334 C C . THR A 1 50 ? 14.528 16.370 -20.027 1.00 86.57 ? ? ? ? ? ? 52 THR A C 1 +ATOM 335 O O . THR A 1 50 ? 13.629 16.031 -20.795 1.00 83.93 ? ? ? ? ? ? 52 THR A O 1 +ATOM 336 C CB . THR A 1 50 ? 14.419 18.847 -20.596 1.00 89.09 ? ? ? ? ? ? 52 THR A CB 1 +ATOM 337 O OG1 . THR A 1 50 ? 15.128 20.061 -20.323 1.00 91.82 ? ? ? ? ? ? 52 THR A OG1 1 +ATOM 338 C CG2 . THR A 1 50 ? 13.158 18.832 -19.761 1.00 84.32 ? ? ? ? ? ? 52 THR A CG2 1 +ATOM 339 N N . SER A 1 51 ? 14.863 15.686 -18.938 1.00 85.07 ? ? ? ? ? ? 53 SER A N 1 +ATOM 340 C CA . SER A 1 51 ? 14.183 14.465 -18.518 1.00 82.20 ? ? ? ? ? ? 53 SER A CA 1 +ATOM 341 C C . SER A 1 51 ? 12.860 14.724 -17.792 1.00 78.23 ? ? ? ? ? ? 53 SER A C 1 +ATOM 342 O O . SER A 1 51 ? 11.863 14.057 -18.069 1.00 75.30 ? ? ? ? ? ? 53 SER A O 1 +ATOM 343 C CB . SER A 1 51 ? 15.103 13.617 -17.631 1.00 84.25 ? ? ? ? ? ? 53 SER A CB 1 +ATOM 344 O OG . SER A 1 51 ? 15.508 14.324 -16.475 1.00 87.22 ? ? ? ? ? ? 53 SER A OG 1 +ATOM 345 N N . ALA A 1 52 ? 12.855 15.681 -16.867 1.00 76.66 ? ? ? ? ? ? 54 ALA A N 1 +ATOM 346 C CA . ALA A 1 52 ? 11.660 15.983 -16.082 1.00 73.63 ? ? ? ? ? ? 54 ALA A CA 1 +ATOM 347 C C . ALA A 1 52 ? 11.347 17.470 -16.020 1.00 72.67 ? ? ? ? ? ? 54 ALA A C 1 +ATOM 348 O O . ALA A 1 52 ? 12.231 18.295 -16.168 1.00 74.97 ? ? ? ? ? ? 54 ALA A O 1 +ATOM 349 C CB . ALA A 1 52 ? 11.807 15.427 -14.697 1.00 73.72 ? ? ? ? ? ? 54 ALA A CB 1 +ATOM 350 N N . ILE A 1 53 ? 10.078 17.799 -15.808 1.00 69.28 ? ? ? ? ? ? 55 ILE A N 1 +ATOM 351 C CA . ILE A 1 53 ? 9.644 19.182 -15.648 1.00 67.60 ? ? ? ? ? ? 55 ILE A CA 1 +ATOM 352 C C . ILE A 1 53 ? 8.807 19.315 -14.386 1.00 66.31 ? ? ? ? ? ? 55 ILE A C 1 +ATOM 353 O O . ILE A 1 53 ? 7.813 18.615 -14.234 1.00 63.74 ? ? ? ? ? ? 55 ILE A O 1 +ATOM 354 C CB . ILE A 1 53 ? 8.816 19.679 -16.852 1.00 66.27 ? ? ? ? ? ? 55 ILE A CB 1 +ATOM 355 C CG1 . ILE A 1 53 ? 9.678 19.756 -18.104 1.00 67.47 ? ? ? ? ? ? 55 ILE A CG1 1 +ATOM 356 C CG2 . ILE A 1 53 ? 8.217 21.057 -16.579 1.00 65.21 ? ? ? ? ? ? 55 ILE A CG2 1 +ATOM 357 C CD1 . ILE A 1 53 ? 8.873 19.776 -19.383 1.00 65.20 ? ? ? ? ? ? 55 ILE A CD1 1 +ATOM 358 N N . LYS A 1 54 ? 9.212 20.225 -13.498 1.00 67.56 ? ? ? ? ? ? 56 LYS A N 1 +ATOM 359 C CA . LYS A 1 54 ? 8.518 20.471 -12.242 1.00 66.86 ? ? ? ? ? ? 56 LYS A CA 1 +ATOM 360 C C . LYS A 1 54 ? 7.790 21.787 -12.345 1.00 66.25 ? ? ? ? ? ? 56 LYS A C 1 +ATOM 361 O O . LYS A 1 54 ? 8.325 22.736 -12.899 1.00 67.88 ? ? ? ? ? ? 56 LYS A O 1 +ATOM 362 C CB . LYS A 1 54 ? 9.524 20.526 -11.091 1.00 69.15 ? ? ? ? ? ? 56 LYS A CB 1 +ATOM 363 C CG . LYS A 1 54 ? 8.919 20.527 -9.688 1.00 66.38 ? ? ? ? ? ? 56 LYS A CG 1 +ATOM 364 C CD . LYS A 1 54 ? 9.898 21.069 -8.644 1.00 66.41 ? ? ? ? ? ? 56 LYS A CD 1 +ATOM 365 C CE . LYS A 1 54 ? 10.805 19.996 -8.061 1.00 66.08 ? ? ? ? ? ? 56 LYS A CE 1 +ATOM 366 N NZ . LYS A 1 54 ? 11.738 20.531 -7.020 1.00 66.38 ? ? ? ? ? ? 56 LYS A NZ 1 +ATOM 367 N N . VAL A 1 55 ? 6.569 21.843 -11.826 1.00 63.79 ? ? ? ? ? ? 57 VAL A N 1 +ATOM 368 C CA . VAL A 1 55 ? 5.805 23.088 -11.783 1.00 62.60 ? ? ? ? ? ? 57 VAL A CA 1 +ATOM 369 C C . VAL A 1 55 ? 5.508 23.478 -10.335 1.00 63.99 ? ? ? ? ? ? 57 VAL A C 1 +ATOM 370 O O . VAL A 1 55 ? 4.827 22.751 -9.607 1.00 62.58 ? ? ? ? ? ? 57 VAL A O 1 +ATOM 371 C CB . VAL A 1 55 ? 4.491 22.999 -12.582 1.00 60.05 ? ? ? ? ? ? 57 VAL A CB 1 +ATOM 372 C CG1 . VAL A 1 55 ? 3.777 24.330 -12.592 1.00 58.65 ? ? ? ? ? ? 57 VAL A CG1 1 +ATOM 373 C CG2 . VAL A 1 55 ? 4.759 22.561 -14.001 1.00 57.89 ? ? ? ? ? ? 57 VAL A CG2 1 +ATOM 374 N N . ARG A 1 56 ? 6.046 24.625 -9.926 1.00 67.06 ? ? ? ? ? ? 58 ARG A N 1 +ATOM 375 C CA . ARG A 1 56 ? 5.822 25.201 -8.602 1.00 68.68 ? ? ? ? ? ? 58 ARG A CA 1 +ATOM 376 C C . ARG A 1 56 ? 4.944 26.430 -8.775 1.00 68.31 ? ? ? ? ? ? 58 ARG A C 1 +ATOM 377 O O . ARG A 1 56 ? 5.295 27.346 -9.516 1.00 69.78 ? ? ? ? ? ? 58 ARG A O 1 +ATOM 378 C CB . ARG A 1 56 ? 7.149 25.622 -7.961 1.00 71.82 ? ? ? ? ? ? 58 ARG A CB 1 +ATOM 379 C CG . ARG A 1 56 ? 7.919 24.540 -7.264 1.00 71.32 ? ? ? ? ? ? 58 ARG A CG 1 +ATOM 380 C CD . ARG A 1 56 ? 8.899 25.124 -6.251 1.00 74.34 ? ? ? ? ? ? 58 ARG A CD 1 +ATOM 381 N NE . ARG A 1 56 ? 10.303 24.967 -6.641 1.00 76.63 ? ? ? ? ? ? 58 ARG A NE 1 +ATOM 382 C CZ . ARG A 1 56 ? 11.114 24.011 -6.180 1.00 77.74 ? ? ? ? ? ? 58 ARG A CZ 1 +ATOM 383 N NH1 . ARG A 1 56 ? 10.668 23.111 -5.308 1.00 77.26 ? ? ? ? ? ? 58 ARG A NH1 1 +ATOM 384 N NH2 . ARG A 1 56 ? 12.380 23.947 -6.590 1.00 79.00 ? ? ? ? ? ? 58 ARG A NH2 1 +ATOM 385 N N . GLY A 1 57 ? 3.795 26.450 -8.116 1.00 66.23 ? ? ? ? ? ? 59 GLY A N 1 +ATOM 386 C CA . GLY A 1 57 ? 2.891 27.591 -8.224 1.00 64.54 ? ? ? ? ? ? 59 GLY A CA 1 +ATOM 387 C C . GLY A 1 57 ? 1.515 27.161 -8.671 1.00 61.40 ? ? ? ? ? ? 59 GLY A C 1 +ATOM 388 O O . GLY A 1 57 ? 1.324 26.011 -9.023 1.00 60.50 ? ? ? ? ? ? 59 GLY A O 1 +ATOM 389 N N . LYS A 1 58 ? 0.553 28.077 -8.652 1.00 59.63 ? ? ? ? ? ? 60 LYS A N 1 +ATOM 390 C CA . LYS A 1 58 ? -0.823 27.767 -9.030 1.00 56.33 ? ? ? ? ? ? 60 LYS A CA 1 +ATOM 391 C C . LYS A 1 58 ? -0.937 27.782 -10.560 1.00 54.36 ? ? ? ? ? ? 60 LYS A C 1 +ATOM 392 O O . LYS A 1 58 ? -0.806 28.840 -11.173 1.00 55.40 ? ? ? ? ? ? 60 LYS A O 1 +ATOM 393 C CB . LYS A 1 58 ? -1.776 28.800 -8.402 1.00 56.75 ? ? ? ? ? ? 60 LYS A CB 1 +ATOM 394 C CG . LYS A 1 58 ? -3.130 28.251 -7.937 1.00 56.71 ? ? ? ? ? ? 60 LYS A CG 1 +ATOM 395 C CD . LYS A 1 58 ? -3.097 27.743 -6.485 1.00 57.00 ? ? ? ? ? ? 60 LYS A CD 1 +ATOM 396 C CE . LYS A 1 58 ? -4.401 27.012 -6.119 1.00 56.07 ? ? ? ? ? ? 60 LYS A CE 1 +ATOM 397 N N . ALA A 1 59 ? -1.157 26.623 -11.185 1.00 50.90 ? ? ? ? ? ? 61 ALA A N 1 +ATOM 398 C CA . ALA A 1 59 ? -1.229 26.563 -12.652 1.00 48.01 ? ? ? ? ? ? 61 ALA A CA 1 +ATOM 399 C C . ALA A 1 59 ? -2.205 25.512 -13.166 1.00 44.63 ? ? ? ? ? ? 61 ALA A C 1 +ATOM 400 O O . ALA A 1 59 ? -2.516 24.556 -12.458 1.00 43.62 ? ? ? ? ? ? 61 ALA A O 1 +ATOM 401 C CB . ALA A 1 59 ? 0.153 26.320 -13.244 1.00 49.49 ? ? ? ? ? ? 61 ALA A CB 1 +ATOM 402 N N . TYR A 1 60 ? -2.667 25.686 -14.404 1.00 41.70 ? ? ? ? ? ? 62 TYR A N 1 +ATOM 403 C CA . TYR A 1 60 ? -3.493 24.707 -15.082 1.00 38.07 ? ? ? ? ? ? 62 TYR A CA 1 +ATOM 404 C C . TYR A 1 60 ? -2.627 24.044 -16.134 1.00 37.82 ? ? ? ? ? ? 62 TYR A C 1 +ATOM 405 O O . TYR A 1 60 ? -1.998 24.722 -16.954 1.00 38.91 ? ? ? ? ? ? 62 TYR A O 1 +ATOM 406 C CB . TYR A 1 60 ? -4.671 25.417 -15.716 1.00 36.81 ? ? ? ? ? ? 62 TYR A CB 1 +ATOM 407 C CG . TYR A 1 60 ? -5.719 24.566 -16.417 1.00 33.24 ? ? ? ? ? ? 62 TYR A CG 1 +ATOM 408 C CD1 . TYR A 1 60 ? -6.553 23.709 -15.702 1.00 30.81 ? ? ? ? ? ? 62 TYR A CD1 1 +ATOM 409 C CD2 . TYR A 1 60 ? -5.925 24.669 -17.795 1.00 32.16 ? ? ? ? ? ? 62 TYR A CD2 1 +ATOM 410 C CE1 . TYR A 1 60 ? -7.554 22.938 -16.349 1.00 26.98 ? ? ? ? ? ? 62 TYR A CE1 1 +ATOM 411 C CE2 . TYR A 1 60 ? -6.915 23.914 -18.446 1.00 29.38 ? ? ? ? ? ? 62 TYR A CE2 1 +ATOM 412 C CZ . TYR A 1 60 ? -7.728 23.053 -17.716 1.00 26.79 ? ? ? ? ? ? 62 TYR A CZ 1 +ATOM 413 O OH . TYR A 1 60 ? -8.701 22.329 -18.381 1.00 24.12 ? ? ? ? ? ? 62 TYR A OH 1 +ATOM 414 N N . ILE A 1 61 ? -2.579 22.717 -16.097 1.00 36.07 ? ? ? ? ? ? 63 ILE A N 1 +ATOM 415 C CA . ILE A 1 61 ? -1.662 21.980 -16.938 1.00 35.83 ? ? ? ? ? ? 63 ILE A CA 1 +ATOM 416 C C . ILE A 1 61 ? -2.384 20.971 -17.798 1.00 33.41 ? ? ? ? ? ? 63 ILE A C 1 +ATOM 417 O O . ILE A 1 61 ? -3.202 20.217 -17.298 1.00 31.94 ? ? ? ? ? ? 63 ILE A O 1 +ATOM 418 C CB . ILE A 1 61 ? -0.610 21.239 -16.097 1.00 37.09 ? ? ? ? ? ? 63 ILE A CB 1 +ATOM 419 C CG1 . ILE A 1 61 ? 0.153 22.208 -15.183 1.00 40.08 ? ? ? ? ? ? 63 ILE A CG1 1 +ATOM 420 C CG2 . ILE A 1 61 ? 0.358 20.461 -17.018 1.00 38.40 ? ? ? ? ? ? 63 ILE A CG2 1 +ATOM 421 C CD1 . ILE A 1 61 ? 0.912 21.521 -14.083 1.00 42.02 ? ? ? ? ? ? 63 ILE A CD1 1 +ATOM 422 N N . GLN A 1 62 ? -2.075 20.961 -19.094 1.00 32.65 ? ? ? ? ? ? 64 GLN A N 1 +ATOM 423 C CA . GLN A 1 62 ? -2.645 19.966 -20.035 1.00 31.02 ? ? ? ? ? ? 64 GLN A CA 1 +ATOM 424 C C . GLN A 1 62 ? -1.536 19.076 -20.577 1.00 31.29 ? ? ? ? ? ? 64 GLN A C 1 +ATOM 425 O O . GLN A 1 62 ? -0.503 19.573 -21.072 1.00 33.32 ? ? ? ? ? ? 64 GLN A O 1 +ATOM 426 C CB . GLN A 1 62 ? -3.321 20.649 -21.251 1.00 30.42 ? ? ? ? ? ? 64 GLN A CB 1 +ATOM 427 C CG . GLN A 1 62 ? -4.366 21.714 -20.928 1.00 29.89 ? ? ? ? ? ? 64 GLN A CG 1 +ATOM 428 C CD . GLN A 1 62 ? -5.024 22.308 -22.172 1.00 30.22 ? ? ? ? ? ? 64 GLN A CD 1 +ATOM 429 O OE1 . GLN A 1 62 ? -4.345 22.746 -23.129 1.00 31.89 ? ? ? ? ? ? 64 GLN A OE1 1 +ATOM 430 N NE2 . GLN A 1 62 ? -6.362 22.351 -22.155 1.00 28.53 ? ? ? ? ? ? 64 GLN A NE2 1 +ATOM 431 N N . THR A 1 63 ? -1.751 17.773 -20.518 1.00 29.70 ? ? ? ? ? ? 65 THR A N 1 +ATOM 432 C CA . THR A 1 63 ? -0.825 16.842 -21.142 1.00 29.95 ? ? ? ? ? ? 65 THR A CA 1 +ATOM 433 C C . THR A 1 63 ? -1.610 15.830 -21.967 1.00 28.22 ? ? ? ? ? ? 65 THR A C 1 +ATOM 434 O O . THR A 1 63 ? -2.852 15.745 -21.879 1.00 26.39 ? ? ? ? ? ? 65 THR A O 1 +ATOM 435 C CB . THR A 1 63 ? -0.010 16.071 -20.095 1.00 30.81 ? ? ? ? ? ? 65 THR A CB 1 +ATOM 436 O OG1 . THR A 1 63 ? -0.897 15.297 -19.248 1.00 30.42 ? ? ? ? ? ? 65 THR A OG1 1 +ATOM 437 C CG2 . THR A 1 63 ? 0.824 17.023 -19.275 1.00 33.74 ? ? ? ? ? ? 65 THR A CG2 1 +ATOM 438 N N . ARG A 1 64 ? -0.886 15.027 -22.737 1.00 28.10 ? ? ? ? ? ? 66 ARG A N 1 +ATOM 439 C CA . ARG A 1 64 ? -1.516 13.903 -23.389 1.00 26.73 ? ? ? ? ? ? 66 ARG A CA 1 +ATOM 440 C C . ARG A 1 64 ? -2.410 13.108 -22.409 1.00 25.08 ? ? ? ? ? ? 66 ARG A C 1 +ATOM 441 O O . ARG A 1 64 ? -3.376 12.454 -22.828 1.00 23.73 ? ? ? ? ? ? 66 ARG A O 1 +ATOM 442 C CB . ARG A 1 64 ? -0.460 13.014 -24.044 1.00 27.91 ? ? ? ? ? ? 66 ARG A CB 1 +ATOM 443 C CG . ARG A 1 64 ? -1.032 11.692 -24.648 1.00 29.01 ? ? ? ? ? ? 66 ARG A CG 1 +ATOM 444 C CD . ARG A 1 64 ? -0.213 11.224 -25.909 1.00 33.87 ? ? ? ? ? ? 66 ARG A CD 1 +ATOM 445 N NE . ARG A 1 64 ? 1.113 10.719 -25.542 1.00 39.87 ? ? ? ? ? ? 66 ARG A NE 1 +ATOM 446 C CZ . ARG A 1 64 ? 1.273 9.451 -25.149 1.00 45.46 ? ? ? ? ? ? 66 ARG A CZ 1 +ATOM 447 N NH1 . ARG A 1 64 ? 2.466 9.006 -24.775 1.00 48.49 ? ? ? ? ? ? 66 ARG A NH1 1 +ATOM 448 N NH2 . ARG A 1 64 ? 0.208 8.625 -25.112 1.00 45.95 ? ? ? ? ? ? 66 ARG A NH2 1 +ATOM 449 N N . HIS A 1 65 ? -2.111 13.173 -21.107 1.00 24.86 ? ? ? ? ? ? 67 HIS A N 1 +ATOM 450 C CA . HIS A 1 65 ? -2.841 12.331 -20.131 1.00 24.10 ? ? ? ? ? ? 67 HIS A CA 1 +ATOM 451 C C . HIS A 1 65 ? -4.020 13.013 -19.469 1.00 23.34 ? ? ? ? ? ? 67 HIS A C 1 +ATOM 452 O O . HIS A 1 65 ? -4.610 12.431 -18.508 1.00 22.91 ? ? ? ? ? ? 67 HIS A O 1 +ATOM 453 C CB . HIS A 1 65 ? -1.918 11.730 -19.064 1.00 24.80 ? ? ? ? ? ? 67 HIS A CB 1 +ATOM 454 C CG . HIS A 1 65 ? -0.816 10.907 -19.640 1.00 27.48 ? ? ? ? ? ? 67 HIS A CG 1 +ATOM 455 N ND1 . HIS A 1 65 ? -0.956 10.191 -20.818 1.00 28.09 ? ? ? ? ? ? 67 HIS A ND1 1 +ATOM 456 C CD2 . HIS A 1 65 ? 0.447 10.682 -19.209 1.00 30.60 ? ? ? ? ? ? 67 HIS A CD2 1 +ATOM 457 C CE1 . HIS A 1 65 ? 0.181 9.571 -21.091 1.00 30.69 ? ? ? ? ? ? 67 HIS A CE1 1 +ATOM 458 N NE2 . HIS A 1 65 ? 1.041 9.835 -20.121 1.00 32.56 ? ? ? ? ? ? 67 HIS A NE2 1 +ATOM 459 N N . GLY A 1 66 ? -4.357 14.217 -19.977 1.00 23.45 ? ? ? ? ? ? 68 GLY A N 1 +ATOM 460 C CA . GLY A 1 66 ? -5.543 14.957 -19.528 1.00 23.05 ? ? ? ? ? ? 68 GLY A CA 1 +ATOM 461 C C . GLY A 1 66 ? -5.125 16.212 -18.813 1.00 23.58 ? ? ? ? ? ? 68 GLY A C 1 +ATOM 462 O O . GLY A 1 66 ? -3.974 16.630 -18.952 1.00 24.68 ? ? ? ? ? ? 68 GLY A O 1 +ATOM 463 N N . VAL A 1 67 ? -6.046 16.822 -18.054 1.00 23.73 ? ? ? ? ? ? 69 VAL A N 1 +ATOM 464 C CA . VAL A 1 67 ? -5.685 18.035 -17.310 1.00 25.29 ? ? ? ? ? ? 69 VAL A CA 1 +ATOM 465 C C . VAL A 1 67 ? -5.378 17.774 -15.842 1.00 27.38 ? ? ? ? ? ? 69 VAL A C 1 +ATOM 466 O O . VAL A 1 67 ? -5.799 16.787 -15.265 1.00 26.03 ? ? ? ? ? ? 69 VAL A O 1 +ATOM 467 C CB . VAL A 1 67 ? -6.706 19.173 -17.463 1.00 24.18 ? ? ? ? ? ? 69 VAL A CB 1 +ATOM 468 C CG1 . VAL A 1 67 ? -7.328 19.087 -18.796 1.00 23.47 ? ? ? ? ? ? 69 VAL A CG1 1 +ATOM 469 C CG2 . VAL A 1 67 ? -7.792 19.078 -16.407 1.00 23.38 ? ? ? ? ? ? 69 VAL A CG2 1 +ATOM 470 N N . ILE A 1 68 ? -4.609 18.685 -15.274 1.00 31.58 ? ? ? ? ? ? 70 ILE A N 1 +ATOM 471 C CA . ILE A 1 68 ? -4.257 18.667 -13.875 1.00 35.85 ? ? ? ? ? ? 70 ILE A CA 1 +ATOM 472 C C . ILE A 1 68 ? -3.894 20.103 -13.437 1.00 40.48 ? ? ? ? ? ? 70 ILE A C 1 +ATOM 473 O O . ILE A 1 68 ? -3.442 20.943 -14.252 1.00 41.26 ? ? ? ? ? ? 70 ILE A O 1 +ATOM 474 C CB . ILE A 1 68 ? -3.137 17.660 -13.591 1.00 35.31 ? ? ? ? ? ? 70 ILE A CB 1 +ATOM 475 C CG1 . ILE A 1 68 ? -3.062 17.400 -12.099 1.00 34.94 ? ? ? ? ? ? 70 ILE A CG1 1 +ATOM 476 C CG2 . ILE A 1 68 ? -1.813 18.148 -14.144 1.00 36.89 ? ? ? ? ? ? 70 ILE A CG2 1 +ATOM 477 C CD1 . ILE A 1 68 ? -2.514 16.052 -11.774 1.00 34.03 ? ? ? ? ? ? 70 ILE A CD1 1 +ATOM 478 N N . GLU A 1 69 ? -4.123 20.367 -12.150 1.00 45.39 ? ? ? ? ? ? 71 GLU A N 1 +ATOM 479 C CA . GLU A 1 69 ? -3.959 21.684 -11.556 1.00 51.34 ? ? ? ? ? ? 71 GLU A CA 1 +ATOM 480 C C . GLU A 1 69 ? -2.832 21.594 -10.527 1.00 55.11 ? ? ? ? ? ? 71 GLU A C 1 +ATOM 481 O O . GLU A 1 69 ? -2.859 20.721 -9.664 1.00 55.41 ? ? ? ? ? ? 71 GLU A O 1 +ATOM 482 C CB . GLU A 1 69 ? -5.285 22.073 -10.896 1.00 50.78 ? ? ? ? ? ? 71 GLU A CB 1 +ATOM 483 C CG . GLU A 1 69 ? -5.358 23.453 -10.275 1.00 56.29 ? ? ? ? ? ? 71 GLU A CG 1 +ATOM 484 C CD . GLU A 1 69 ? -6.733 23.756 -9.687 1.00 59.81 ? ? ? ? ? ? 71 GLU A CD 1 +ATOM 485 O OE1 . GLU A 1 69 ? -6.805 24.062 -8.476 1.00 61.66 ? ? ? ? ? ? 71 GLU A OE1 1 +ATOM 486 O OE2 . GLU A 1 69 ? -7.742 23.685 -10.439 1.00 59.40 ? ? ? ? ? ? 71 GLU A OE2 1 +ATOM 487 N N . SER A 1 70 ? -1.830 22.463 -10.633 1.00 60.26 ? ? ? ? ? ? 72 SER A N 1 +ATOM 488 C CA . SER A 1 70 ? -0.785 22.528 -9.618 1.00 65.19 ? ? ? ? ? ? 72 SER A CA 1 +ATOM 489 C C . SER A 1 70 ? -1.191 23.554 -8.582 1.00 67.72 ? ? ? ? ? ? 72 SER A C 1 +ATOM 490 O O . SER A 1 70 ? -1.586 24.664 -8.933 1.00 68.67 ? ? ? ? ? ? 72 SER A O 1 +ATOM 491 C CB . SER A 1 70 ? 0.566 22.885 -10.232 1.00 66.81 ? ? ? ? ? ? 72 SER A CB 1 +ATOM 492 O OG . SER A 1 70 ? 0.520 24.141 -10.869 1.00 69.19 ? ? ? ? ? ? 72 SER A OG 1 +ATOM 493 N N . GLU A 1 71 ? -1.109 23.173 -7.312 1.00 70.07 ? ? ? ? ? ? 73 GLU A N 1 +ATOM 494 C CA . GLU A 1 71 ? -1.494 24.038 -6.212 1.00 72.36 ? ? ? ? ? ? 73 GLU A CA 1 +ATOM 495 C C . GLU A 1 71 ? -0.236 24.266 -5.347 1.00 75.16 ? ? ? ? ? ? 73 GLU A C 1 +ATOM 496 O O . GLU A 1 71 ? -0.249 24.010 -4.173 1.00 77.08 ? ? ? ? ? ? 73 GLU A O 1 +ATOM 497 C CB . GLU A 1 71 ? -2.606 23.360 -5.394 1.00 71.07 ? ? ? ? ? ? 73 GLU A CB 1 +ATOM 498 C CG . GLU A 1 71 ? -3.410 22.310 -6.167 1.00 69.29 ? ? ? ? ? ? 73 GLU A CG 1 +ATOM 499 C CD . GLU A 1 71 ? -4.836 22.110 -5.652 1.00 67.49 ? ? ? ? ? ? 73 GLU A CD 1 +ATOM 500 O OE1 . GLU A 1 71 ? -5.627 23.072 -5.780 1.00 67.26 ? ? ? ? ? ? 73 GLU A OE1 1 +ATOM 501 O OE2 . GLU A 1 71 ? -5.169 20.998 -5.157 1.00 64.72 ? ? ? ? ? ? 73 GLU A OE2 1 +ATOM 502 N N . GLY A 1 72 ? 0.917 24.600 -5.926 1.00 75.64 ? ? ? ? ? ? 74 GLY A N 1 +ATOM 503 C CA . GLY A 1 72 ? 2.179 24.627 -5.145 1.00 76.28 ? ? ? ? ? ? 74 GLY A CA 1 +ATOM 504 C C . GLY A 1 72 ? 2.532 25.958 -4.485 1.00 77.39 ? ? ? ? ? ? 74 GLY A C 1 +ATOM 505 O O . GLY A 1 72 ? 1.761 26.914 -4.592 1.00 77.60 ? ? ? ? ? ? 74 GLY A O 1 +ATOM 506 N N . LYS A 1 73 ? 3.692 26.048 -3.818 1.00 78.11 ? ? ? ? ? ? 75 LYS A N 1 +ATOM 507 C CA . LYS A 1 73 ? 4.129 27.336 -3.223 1.00 79.14 ? ? ? ? ? ? 75 LYS A CA 1 +ATOM 508 C C . LYS A 1 73 ? 4.479 28.474 -4.244 1.00 79.69 ? ? ? ? ? ? 75 LYS A C 1 +ATOM 509 O O . LYS A 1 73 ? 5.535 28.516 -4.903 1.00 79.72 ? ? ? ? ? ? 75 LYS A O 1 +ATOM 510 C CB . LYS A 1 73 ? 5.211 27.143 -2.149 1.00 79.82 ? ? ? ? ? ? 75 LYS A CB 1 +ATOM 511 C CG . LYS A 1 73 ? 6.646 27.001 -2.680 1.00 82.03 ? ? ? ? ? ? 75 LYS A CG 1 +ATOM 512 C CD . LYS A 1 73 ? 7.702 26.968 -1.556 1.00 83.81 ? ? ? ? ? ? 75 LYS A CD 1 +ATOM 513 C CE . LYS A 1 73 ? 9.130 26.847 -2.110 1.00 84.65 ? ? ? ? ? ? 75 LYS A CE 1 +ATOM 514 N NZ . LYS A 1 73 ? 10.106 26.489 -1.037 1.00 84.64 ? ? ? ? ? ? 75 LYS A NZ 1 diff --git a/modules/seq/alg/tests/testfiles/validate_segres_aln_breakage.mmcif b/modules/seq/alg/tests/testfiles/validate_segres_aln_breakage.mmcif new file mode 100644 index 0000000000000000000000000000000000000000..0d66b8fa227e343ff23e6c413a9de746b19c68af --- /dev/null +++ b/modules/seq/alg/tests/testfiles/validate_segres_aln_breakage.mmcif @@ -0,0 +1,560 @@ +data_3BAR +# based on 3AQD +_entry.id 3BAR +# +loop_ +_entity.id +_entity.type +_entity.src_method +_entity.pdbx_description +_entity.formula_weight +_entity.pdbx_number_of_molecules +_entity.details +1 polymer man 'Transcription attenuation protein mtrB' 8257.458 22 ? +2 water nat water 18.015 7 ? +# +_entity_poly.entity_id 1 +_entity_poly.type 'polypeptide(L)' +_entity_poly.nstd_linkage no +_entity_poly.nstd_monomer no +_entity_poly.pdbx_seq_one_letter_code MYTNSDFVVIKALEDGVNVIGLTRGADTRFHHSEKLDKGEVLIAQFTEHTSAIKVRGKAYIQTRHGVIESEKK +_entity_poly.pdbx_seq_one_letter_code_can MYTNSDFVVIKALEDGVNVIGLTRGADTRFHHSEKLDKGEVLIAQFTEHTSAIKVRGKAYIQTRHGVIESEKK +_entity_poly.pdbx_strand_id A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V +# +loop_ +_atom_site.group_PDB +_atom_site.id +_atom_site.type_symbol +_atom_site.label_atom_id +_atom_site.label_alt_id +_atom_site.label_comp_id +_atom_site.label_asym_id +_atom_site.label_entity_id +_atom_site.label_seq_id +_atom_site.pdbx_PDB_ins_code +_atom_site.Cartn_x +_atom_site.Cartn_y +_atom_site.Cartn_z +_atom_site.occupancy +_atom_site.B_iso_or_equiv +_atom_site.Cartn_x_esd +_atom_site.Cartn_y_esd +_atom_site.Cartn_z_esd +_atom_site.occupancy_esd +_atom_site.B_iso_or_equiv_esd +_atom_site.pdbx_formal_charge +_atom_site.auth_seq_id +_atom_site.auth_comp_id +_atom_site.auth_asym_id +_atom_site.auth_atom_id +_atom_site.pdbx_PDB_model_num +ATOM 1 N N . SER A 1 5 ? 8.892 13.236 -28.550 1.00 81.62 ? ? ? ? ? ? 7 SER A N 1 +ATOM 2 C CA . SER A 1 5 ? 8.449 14.550 -29.128 1.00 80.98 ? ? ? ? ? ? 7 SER A CA 1 +ATOM 3 C C . SER A 1 5 ? 7.181 15.159 -28.476 1.00 77.44 ? ? ? ? ? ? 7 SER A C 1 +ATOM 4 O O . SER A 1 5 ? 6.463 15.940 -29.117 1.00 76.80 ? ? ? ? ? ? 7 SER A O 1 +ATOM 5 C CB . SER A 1 5 ? 8.239 14.416 -30.651 1.00 81.96 ? ? ? ? ? ? 7 SER A CB 1 +ATOM 6 O OG . SER A 1 5 ? 9.441 14.629 -31.378 1.00 87.04 ? ? ? ? ? ? 7 SER A OG 1 +ATOM 7 N N . ASP A 1 6 ? 6.910 14.822 -27.217 1.00 73.87 ? ? ? ? ? ? 8 ASP A N 1 +ATOM 8 C CA . ASP A 1 6 ? 5.670 15.258 -26.582 1.00 69.40 ? ? ? ? ? ? 8 ASP A CA 1 +ATOM 9 C C . ASP A 1 6 ? 5.834 16.550 -25.785 1.00 68.43 ? ? ? ? ? ? 8 ASP A C 1 +ATOM 10 O O . ASP A 1 6 ? 6.944 16.907 -25.403 1.00 70.90 ? ? ? ? ? ? 8 ASP A O 1 +ATOM 11 C CB . ASP A 1 6 ? 5.104 14.146 -25.703 1.00 67.64 ? ? ? ? ? ? 8 ASP A CB 1 +ATOM 12 C CG . ASP A 1 6 ? 3.570 14.083 -25.751 1.00 64.57 ? ? ? ? ? ? 8 ASP A CG 1 +ATOM 13 O OD1 . ASP A 1 6 ? 2.949 15.085 -26.195 1.00 63.11 ? ? ? ? ? ? 8 ASP A OD1 1 +ATOM 14 O OD2 . ASP A 1 6 ? 2.984 13.032 -25.353 1.00 62.17 ? ? ? ? ? ? 8 ASP A OD2 1 +ATOM 15 N N . PHE A 1 7 ? 4.726 17.246 -25.545 1.00 64.53 ? ? ? ? ? ? 9 PHE A N 1 +ATOM 16 C CA . PHE A 1 7 ? 4.750 18.548 -24.879 1.00 61.94 ? ? ? ? ? ? 9 PHE A CA 1 +ATOM 17 C C . PHE A 1 7 ? 3.673 18.732 -23.796 1.00 57.92 ? ? ? ? ? ? 9 PHE A C 1 +ATOM 18 O O . PHE A 1 7 ? 2.693 17.987 -23.744 1.00 55.70 ? ? ? ? ? ? 9 PHE A O 1 +ATOM 19 C CB . PHE A 1 7 ? 4.618 19.664 -25.915 1.00 63.43 ? ? ? ? ? ? 9 PHE A CB 1 +ATOM 20 C CG . PHE A 1 7 ? 3.282 19.718 -26.567 1.00 62.41 ? ? ? ? ? ? 9 PHE A CG 1 +ATOM 21 C CD1 . PHE A 1 7 ? 2.231 20.382 -25.970 1.00 61.82 ? ? ? ? ? ? 9 PHE A CD1 1 +ATOM 22 C CD2 . PHE A 1 7 ? 3.075 19.105 -27.775 1.00 64.02 ? ? ? ? ? ? 9 PHE A CD2 1 +ATOM 23 C CE1 . PHE A 1 7 ? 0.988 20.428 -26.567 1.00 60.16 ? ? ? ? ? ? 9 PHE A CE1 1 +ATOM 24 C CE2 . PHE A 1 7 ? 1.832 19.145 -28.383 1.00 62.57 ? ? ? ? ? ? 9 PHE A CE2 1 +ATOM 25 C CZ . PHE A 1 7 ? 0.783 19.808 -27.775 1.00 60.25 ? ? ? ? ? ? 9 PHE A CZ 1 +ATOM 26 N N . VAL A 1 8 ? 3.861 19.735 -22.938 1.00 55.04 ? ? ? ? ? ? 10 VAL A N 1 +ATOM 27 C CA . VAL A 1 8 ? 2.861 20.095 -21.949 1.00 50.88 ? ? ? ? ? ? 10 VAL A CA 1 +ATOM 28 C C . VAL A 1 8 ? 2.487 21.551 -22.098 1.00 49.54 ? ? ? ? ? ? 10 VAL A C 1 +ATOM 29 O O . VAL A 1 8 ? 3.323 22.385 -22.446 1.00 50.85 ? ? ? ? ? ? 10 VAL A O 1 +ATOM 30 C CB . VAL A 1 8 ? 3.326 19.851 -20.511 1.00 51.03 ? ? ? ? ? ? 10 VAL A CB 1 +ATOM 31 C CG1 . VAL A 1 8 ? 3.832 18.442 -20.371 1.00 50.13 ? ? ? ? ? ? 10 VAL A CG1 1 +ATOM 32 C CG2 . VAL A 1 8 ? 4.402 20.826 -20.090 1.00 53.19 ? ? ? ? ? ? 10 VAL A CG2 1 +ATOM 33 N N . VAL A 1 9 ? 1.215 21.844 -21.842 1.00 46.06 ? ? ? ? ? ? 11 VAL A N 1 +ATOM 34 C CA . VAL A 1 9 ? 0.687 23.206 -21.880 1.00 44.00 ? ? ? ? ? ? 11 VAL A CA 1 +ATOM 35 C C . VAL A 1 9 ? 0.489 23.603 -20.434 1.00 44.21 ? ? ? ? ? ? 11 VAL A C 1 +ATOM 36 O O . VAL A 1 9 ? -0.170 22.877 -19.678 1.00 42.41 ? ? ? ? ? ? 11 VAL A O 1 +ATOM 37 C CB . VAL A 1 9 ? -0.661 23.252 -22.624 1.00 42.00 ? ? ? ? ? ? 11 VAL A CB 1 +ATOM 38 C CG1 . VAL A 1 9 ? -1.295 24.607 -22.528 1.00 40.79 ? ? ? ? ? ? 11 VAL A CG1 1 +ATOM 39 C CG2 . VAL A 1 9 ? -0.455 22.906 -24.078 1.00 40.13 ? ? ? ? ? ? 11 VAL A CG2 1 +ATOM 40 N N . ILE A 1 10 ? 1.076 24.738 -20.056 1.00 46.10 ? ? ? ? ? ? 12 ILE A N 1 +ATOM 41 C CA . ILE A 1 10 ? 1.003 25.240 -18.696 1.00 47.51 ? ? ? ? ? ? 12 ILE A CA 1 +ATOM 42 C C . ILE A 1 10 ? 0.516 26.657 -18.743 1.00 48.05 ? ? ? ? ? ? 12 ILE A C 1 +ATOM 43 O O . ILE A 1 10 ? 1.137 27.508 -19.380 1.00 49.65 ? ? ? ? ? ? 12 ILE A O 1 +ATOM 44 C CB . ILE A 1 10 ? 2.374 25.247 -18.012 1.00 49.28 ? ? ? ? ? ? 12 ILE A CB 1 +ATOM 45 C CG1 . ILE A 1 10 ? 2.981 23.848 -18.003 1.00 49.95 ? ? ? ? ? ? 12 ILE A CG1 1 +ATOM 46 C CG2 . ILE A 1 10 ? 2.247 25.753 -16.603 1.00 50.91 ? ? ? ? ? ? 12 ILE A CG2 1 +ATOM 47 C CD1 . ILE A 1 10 ? 4.435 23.827 -17.677 1.00 54.16 ? ? ? ? ? ? 12 ILE A CD1 1 +ATOM 48 N N . LYS A 1 11 ? -0.606 26.901 -18.076 1.00 47.39 ? ? ? ? ? ? 13 LYS A N 1 +ATOM 49 C CA . LYS A 1 11 ? -1.139 28.252 -17.917 1.00 48.23 ? ? ? ? ? ? 13 LYS A CA 1 +ATOM 50 C C . LYS A 1 11 ? -0.998 28.660 -16.473 1.00 50.10 ? ? ? ? ? ? 13 LYS A C 1 +ATOM 51 O O . LYS A 1 11 ? -1.441 27.931 -15.579 1.00 49.40 ? ? ? ? ? ? 13 LYS A O 1 +ATOM 52 C CB . LYS A 1 11 ? -2.609 28.311 -18.304 1.00 46.00 ? ? ? ? ? ? 13 LYS A CB 1 +ATOM 53 C CG . LYS A 1 11 ? -3.144 29.706 -18.267 1.00 45.91 ? ? ? ? ? ? 13 LYS A CG 1 +ATOM 54 C CD . LYS A 1 11 ? -4.640 29.741 -18.402 1.00 43.12 ? ? ? ? ? ? 13 LYS A CD 1 +ATOM 55 C CE . LYS A 1 11 ? -5.103 31.182 -18.619 1.00 44.02 ? ? ? ? ? ? 13 LYS A CE 1 +ATOM 56 N NZ . LYS A 1 11 ? -6.563 31.312 -18.363 1.00 43.35 ? ? ? ? ? ? 13 LYS A NZ 1 +ATOM 57 N N . ALA A 1 12 ? -0.379 29.818 -16.242 1.00 53.49 ? ? ? ? ? ? 14 ALA A N 1 +ATOM 58 C CA . ALA A 1 12 ? -0.115 30.296 -14.876 1.00 55.56 ? ? ? ? ? ? 14 ALA A CA 1 +ATOM 59 C C . ALA A 1 12 ? -1.354 30.960 -14.272 1.00 55.44 ? ? ? ? ? ? 14 ALA A C 1 +ATOM 60 O O . ALA A 1 12 ? -1.938 31.848 -14.881 1.00 55.76 ? ? ? ? ? ? 14 ALA A O 1 +ATOM 61 C CB . ALA A 1 12 ? 1.042 31.240 -14.890 1.00 58.43 ? ? ? ? ? ? 14 ALA A CB 1 +ATOM 62 N N . LEU A 1 13 ? -1.767 30.514 -13.093 1.00 55.02 ? ? ? ? ? ? 15 LEU A N 1 +ATOM 63 C CA . LEU A 1 13 ? -2.966 31.063 -12.438 1.00 55.23 ? ? ? ? ? ? 15 LEU A CA 1 +ATOM 64 C C . LEU A 1 13 ? -2.665 32.145 -11.380 1.00 58.70 ? ? ? ? ? ? 15 LEU A C 1 +ATOM 65 O O . LEU A 1 13 ? -3.574 32.758 -10.809 1.00 58.84 ? ? ? ? ? ? 15 LEU A O 1 +ATOM 66 C CB . LEU A 1 13 ? -3.811 29.932 -11.832 1.00 52.50 ? ? ? ? ? ? 15 LEU A CB 1 +ATOM 67 C CG . LEU A 1 13 ? -4.415 28.951 -12.839 1.00 47.91 ? ? ? ? ? ? 15 LEU A CG 1 +ATOM 68 C CD1 . LEU A 1 13 ? -4.953 27.698 -12.151 1.00 44.21 ? ? ? ? ? ? 15 LEU A CD1 1 +ATOM 69 C CD2 . LEU A 1 13 ? -5.494 29.672 -13.668 1.00 46.05 ? ? ? ? ? ? 15 LEU A CD2 1 +ATOM 70 N N . GLU A 1 14 ? -1.379 32.359 -11.120 1.00 62.66 ? ? ? ? ? ? 16 GLU A N 1 +ATOM 71 C CA . GLU A 1 14 ? -0.899 33.425 -10.252 1.00 67.00 ? ? ? ? ? ? 16 GLU A CA 1 +ATOM 72 C C . GLU A 1 14 ? 0.409 33.922 -10.836 1.00 70.32 ? ? ? ? ? ? 16 GLU A C 1 +ATOM 73 O O . GLU A 1 14 ? 0.914 33.339 -11.785 1.00 70.03 ? ? ? ? ? ? 16 GLU A O 1 +ATOM 74 C CB . GLU A 1 14 ? -0.696 32.923 -8.819 1.00 67.19 ? ? ? ? ? ? 16 GLU A CB 1 +ATOM 75 C CG . GLU A 1 14 ? 0.432 31.895 -8.625 1.00 68.58 ? ? ? ? ? ? 16 GLU A CG 1 +ATOM 76 C CD . GLU A 1 14 ? 0.454 31.270 -7.222 1.00 70.39 ? ? ? ? ? ? 16 GLU A CD 1 +ATOM 77 O OE1 . GLU A 1 14 ? -0.457 31.541 -6.412 1.00 71.02 ? ? ? ? ? ? 16 GLU A OE1 1 +ATOM 78 O OE2 . GLU A 1 14 ? 1.387 30.491 -6.926 1.00 71.29 ? ? ? ? ? ? 16 GLU A OE2 1 +ATOM 79 N N . ASP A 1 15 ? 0.955 35.001 -10.285 1.00 74.75 ? ? ? ? ? ? 17 ASP A N 1 +ATOM 80 C CA . ASP A 1 15 ? 2.250 35.491 -10.740 1.00 78.78 ? ? ? ? ? ? 17 ASP A CA 1 +ATOM 81 C C . ASP A 1 15 ? 3.325 34.615 -10.138 1.00 79.87 ? ? ? ? ? ? 17 ASP A C 1 +ATOM 82 O O . ASP A 1 15 ? 3.099 33.950 -9.124 1.00 79.33 ? ? ? ? ? ? 17 ASP A O 1 +ATOM 83 C CB . ASP A 1 15 ? 2.475 36.953 -10.336 1.00 81.65 ? ? ? ? ? ? 17 ASP A CB 1 +ATOM 84 C CG . ASP A 1 15 ? 1.621 37.937 -11.140 1.00 83.16 ? ? ? ? ? ? 17 ASP A CG 1 +ATOM 85 O OD1 . ASP A 1 15 ? 1.344 37.691 -12.326 1.00 82.40 ? ? ? ? ? ? 17 ASP A OD1 1 +ATOM 86 O OD2 . ASP A 1 15 ? 1.231 38.982 -10.589 1.00 86.46 ? ? ? ? ? ? 17 ASP A OD2 1 +ATOM 87 N N . GLY A 1 16 ? 4.489 34.606 -10.778 1.00 81.58 ? ? ? ? ? ? 18 GLY A N 1 +ATOM 88 C CA . GLY A 1 16 ? 5.660 33.903 -10.248 1.00 82.57 ? ? ? ? ? ? 18 GLY A CA 1 +ATOM 89 C C . GLY A 1 16 ? 5.555 32.392 -10.154 1.00 80.35 ? ? ? ? ? ? 18 GLY A C 1 +ATOM 90 O O . GLY A 1 16 ? 6.059 31.793 -9.215 1.00 81.29 ? ? ? ? ? ? 18 GLY A O 1 +ATOM 91 N N . VAL A 1 17 ? 4.892 31.781 -11.128 1.00 77.56 ? ? ? ? ? ? 19 VAL A N 1 +ATOM 92 C CA . VAL A 1 17 ? 4.885 30.336 -11.259 1.00 74.50 ? ? ? ? ? ? 19 VAL A CA 1 +ATOM 93 C C . VAL A 1 17 ? 6.239 29.942 -11.826 1.00 76.68 ? ? ? ? ? ? 19 VAL A C 1 +ATOM 94 O O . VAL A 1 17 ? 6.799 30.655 -12.655 1.00 78.24 ? ? ? ? ? ? 19 VAL A O 1 +ATOM 95 C CB . VAL A 1 17 ? 3.755 29.861 -12.187 1.00 71.56 ? ? ? ? ? ? 19 VAL A CB 1 +ATOM 96 C CG1 . VAL A 1 17 ? 3.820 28.364 -12.384 1.00 67.63 ? ? ? ? ? ? 19 VAL A CG1 1 +ATOM 97 C CG2 . VAL A 1 17 ? 2.409 30.247 -11.611 1.00 67.92 ? ? ? ? ? ? 19 VAL A CG2 1 +ATOM 98 N N . ASN A 1 18 ? 6.764 28.812 -11.381 1.00 77.33 ? ? ? ? ? ? 20 ASN A N 1 +ATOM 99 C CA . ASN A 1 18 ? 8.086 28.396 -11.775 1.00 79.46 ? ? ? ? ? ? 20 ASN A CA 1 +ATOM 100 C C . ASN A 1 18 ? 8.067 27.069 -12.528 1.00 77.29 ? ? ? ? ? ? 20 ASN A C 1 +ATOM 101 O O . ASN A 1 18 ? 7.635 26.058 -11.989 1.00 75.60 ? ? ? ? ? ? 20 ASN A O 1 +ATOM 102 C CB . ASN A 1 18 ? 8.941 28.291 -10.526 1.00 82.30 ? ? ? ? ? ? 20 ASN A CB 1 +ATOM 103 C CG . ASN A 1 18 ? 10.360 28.739 -10.753 1.00 89.13 ? ? ? ? ? ? 20 ASN A CG 1 +ATOM 104 O OD1 . ASN A 1 18 ? 10.690 29.305 -11.791 1.00 92.93 ? ? ? ? ? ? 20 ASN A OD1 1 +ATOM 105 N ND2 . ASN A 1 18 ? 11.217 28.488 -9.773 1.00 94.39 ? ? ? ? ? ? 20 ASN A ND2 1 +ATOM 106 N N . VAL A 1 19 ? 8.521 27.077 -13.779 1.00 76.88 ? ? ? ? ? ? 21 VAL A N 1 +ATOM 107 C CA . VAL A 1 19 ? 8.542 25.871 -14.600 1.00 75.28 ? ? ? ? ? ? 21 VAL A CA 1 +ATOM 108 C C . VAL A 1 19 ? 9.970 25.398 -14.720 1.00 78.52 ? ? ? ? ? ? 21 VAL A C 1 +ATOM 109 O O . VAL A 1 19 ? 10.747 25.948 -15.489 1.00 80.53 ? ? ? ? ? ? 21 VAL A O 1 +ATOM 110 C CB . VAL A 1 19 ? 7.946 26.104 -16.005 1.00 73.54 ? ? ? ? ? ? 21 VAL A CB 1 +ATOM 111 C CG1 . VAL A 1 19 ? 7.966 24.838 -16.807 1.00 70.33 ? ? ? ? ? ? 21 VAL A CG1 1 +ATOM 112 C CG2 . VAL A 1 19 ? 6.528 26.602 -15.913 1.00 69.44 ? ? ? ? ? ? 21 VAL A CG2 1 +ATOM 113 N N . ILE A 1 20 ? 10.305 24.368 -13.960 1.00 80.07 ? ? ? ? ? ? 22 ILE A N 1 +ATOM 114 C CA . ILE A 1 20 ? 11.683 23.949 -13.817 1.00 83.77 ? ? ? ? ? ? 22 ILE A CA 1 +ATOM 115 C C . ILE A 1 20 ? 12.004 22.729 -14.664 1.00 83.74 ? ? ? ? ? ? 22 ILE A C 1 +ATOM 116 O O . ILE A 1 20 ? 11.349 21.705 -14.536 1.00 81.42 ? ? ? ? ? ? 22 ILE A O 1 +ATOM 117 C CB . ILE A 1 20 ? 12.014 23.661 -12.348 1.00 84.59 ? ? ? ? ? ? 22 ILE A CB 1 +ATOM 118 C CG1 . ILE A 1 20 ? 11.522 24.802 -11.467 1.00 85.96 ? ? ? ? ? ? 22 ILE A CG1 1 +ATOM 119 C CG2 . ILE A 1 20 ? 13.511 23.484 -12.166 1.00 89.81 ? ? ? ? ? ? 22 ILE A CG2 1 +ATOM 120 C CD1 . ILE A 1 20 ? 11.484 24.464 -9.998 1.00 87.43 ? ? ? ? ? ? 22 ILE A CD1 1 +ATOM 121 N N . GLY A 1 21 ? 13.019 22.862 -15.520 1.00 86.57 ? ? ? ? ? ? 23 GLY A N 1 +ATOM 122 C CA . GLY A 1 21 ? 13.522 21.775 -16.358 1.00 88.60 ? ? ? ? ? ? 23 GLY A CA 1 +ATOM 123 C C . GLY A 1 21 ? 14.674 21.070 -15.675 1.00 91.29 ? ? ? ? ? ? 23 GLY A C 1 +ATOM 124 O O . GLY A 1 21 ? 15.573 21.716 -15.154 1.00 94.14 ? ? ? ? ? ? 23 GLY A O 1 +ATOM 125 N N . LEU A 1 22 ? 14.642 19.743 -15.672 1.00 91.36 ? ? ? ? ? ? 24 LEU A N 1 +ATOM 126 C CA . LEU A 1 22 ? 15.603 18.932 -14.926 1.00 92.96 ? ? ? ? ? ? 24 LEU A CA 1 +ATOM 127 C C . LEU A 1 22 ? 16.447 18.089 -15.876 1.00 94.68 ? ? ? ? ? ? 24 LEU A C 1 +ATOM 128 O O . LEU A 1 22 ? 15.939 17.601 -16.885 1.00 94.04 ? ? ? ? ? ? 24 LEU A O 1 +ATOM 129 C CB . LEU A 1 22 ? 14.860 18.047 -13.924 1.00 91.08 ? ? ? ? ? ? 24 LEU A CB 1 +ATOM 130 C CG . LEU A 1 22 ? 14.551 18.518 -12.493 1.00 90.38 ? ? ? ? ? ? 24 LEU A CG 1 +ATOM 131 C CD1 . LEU A 1 22 ? 14.342 20.009 -12.384 1.00 91.01 ? ? ? ? ? ? 24 LEU A CD1 1 +ATOM 132 C CD2 . LEU A 1 22 ? 13.342 17.791 -11.921 1.00 85.41 ? ? ? ? ? ? 24 LEU A CD2 1 +ATOM 133 N N . THR A 1 23 ? 17.733 17.926 -15.565 1.00 96.47 ? ? ? ? ? ? 25 THR A N 1 +ATOM 134 C CA . THR A 1 23 ? 18.688 17.343 -16.531 1.00 98.30 ? ? ? ? ? ? 25 THR A CA 1 +ATOM 135 C C . THR A 1 23 ? 19.007 15.862 -16.352 1.00 98.49 ? ? ? ? ? ? 25 THR A C 1 +ATOM 136 O O . THR A 1 23 ? 18.826 15.304 -15.266 1.00 98.19 ? ? ? ? ? ? 25 THR A O 1 +ATOM 137 C CB . THR A 1 23 ? 20.028 18.102 -16.553 1.00 100.21 ? ? ? ? ? ? 25 THR A CB 1 +ATOM 138 O OG1 . THR A 1 23 ? 20.490 18.282 -15.208 1.00 101.37 ? ? ? ? ? ? 25 THR A OG1 1 +ATOM 139 C CG2 . THR A 1 23 ? 19.883 19.457 -17.252 1.00 100.72 ? ? ? ? ? ? 25 THR A CG2 1 +ATOM 140 N N . ARG A 1 24 ? 19.501 15.246 -17.430 1.00 99.49 ? ? ? ? ? ? 26 ARG A N 1 +ATOM 141 C CA . ARG A 1 24 ? 19.857 13.819 -17.452 1.00 99.94 ? ? ? ? ? ? 26 ARG A CA 1 +ATOM 142 C C . ARG A 1 24 ? 21.154 13.541 -16.693 1.00 101.44 ? ? ? ? ? ? 26 ARG A C 1 +ATOM 143 O O . ARG A 1 24 ? 22.240 13.904 -17.147 1.00 103.26 ? ? ? ? ? ? 26 ARG A O 1 +ATOM 144 C CB . ARG A 1 24 ? 19.955 13.281 -18.893 1.00 100.14 ? ? ? ? ? ? 26 ARG A CB 1 +ATOM 145 C CG . ARG A 1 24 ? 18.620 13.217 -19.642 1.00 99.36 ? ? ? ? ? ? 26 ARG A CG 1 +ATOM 146 C CD . ARG A 1 24 ? 18.634 12.164 -20.759 1.00 100.98 ? ? ? ? ? ? 26 ARG A CD 1 +ATOM 147 N NE . ARG A 1 24 ? 17.552 12.352 -21.740 1.00 100.55 ? ? ? ? ? ? 26 ARG A NE 1 +ATOM 148 C CZ . ARG A 1 24 ? 17.231 11.494 -22.716 1.00 99.98 ? ? ? ? ? ? 26 ARG A CZ 1 +ATOM 149 N NH1 . ARG A 1 24 ? 17.891 10.344 -22.876 1.00 99.60 ? ? ? ? ? ? 26 ARG A NH1 1 +ATOM 150 N NH2 . ARG A 1 24 ? 16.229 11.791 -23.537 1.00 99.33 ? ? ? ? ? ? 26 ARG A NH2 1 +ATOM 151 N N . THR A 1 28 ? 22.527 16.428 -12.721 1.00 120.13 ? ? ? ? ? ? 30 THR A N 1 +ATOM 152 C CA . THR A 1 28 ? 21.235 15.835 -13.090 1.00 118.47 ? ? ? ? ? ? 30 THR A CA 1 +ATOM 153 C C . THR A 1 28 ? 20.021 16.467 -12.351 1.00 117.17 ? ? ? ? ? ? 30 THR A C 1 +ATOM 154 O O . THR A 1 28 ? 18.867 16.073 -12.593 1.00 115.70 ? ? ? ? ? ? 30 THR A O 1 +ATOM 155 C CB . THR A 1 28 ? 21.259 14.241 -13.007 1.00 118.06 ? ? ? ? ? ? 30 THR A CB 1 +ATOM 156 O OG1 . THR A 1 28 ? 19.946 13.697 -13.234 1.00 116.11 ? ? ? ? ? ? 30 THR A OG1 1 +ATOM 157 C CG2 . THR A 1 28 ? 21.822 13.727 -11.660 1.00 118.37 ? ? ? ? ? ? 30 THR A CG2 1 +ATOM 158 N N . ARG A 1 29 ? 20.289 17.464 -11.492 1.00 117.71 ? ? ? ? ? ? 31 ARG A N 1 +ATOM 159 C CA . ARG A 1 29 ? 19.261 18.091 -10.604 1.00 116.35 ? ? ? ? ? ? 31 ARG A CA 1 +ATOM 160 C C . ARG A 1 29 ? 18.477 19.294 -11.195 1.00 115.56 ? ? ? ? ? ? 31 ARG A C 1 +ATOM 161 O O . ARG A 1 29 ? 18.271 19.360 -12.420 1.00 115.47 ? ? ? ? ? ? 31 ARG A O 1 +ATOM 162 C CB . ARG A 1 29 ? 19.840 18.428 -9.204 1.00 117.16 ? ? ? ? ? ? 31 ARG A CB 1 +ATOM 163 C CG . ARG A 1 29 ? 21.320 18.904 -9.113 1.00 119.11 ? ? ? ? ? ? 31 ARG A CG 1 +ATOM 164 C CD . ARG A 1 29 ? 21.638 20.210 -9.857 1.00 119.60 ? ? ? ? ? ? 31 ARG A CD 1 +ATOM 165 N NE . ARG A 1 29 ? 22.419 19.952 -11.068 1.00 120.44 ? ? ? ? ? ? 31 ARG A NE 1 +ATOM 166 C CZ . ARG A 1 29 ? 21.980 20.123 -12.315 1.00 119.80 ? ? ? ? ? ? 31 ARG A CZ 1 +ATOM 167 N NH1 . ARG A 1 29 ? 22.780 19.853 -13.337 1.00 121.30 ? ? ? ? ? ? 31 ARG A NH1 1 +ATOM 168 N NH2 . ARG A 1 29 ? 20.756 20.576 -12.552 1.00 117.87 ? ? ? ? ? ? 31 ARG A NH2 1 +ATOM 169 N N . PHE A 1 30 ? 18.052 20.228 -10.323 1.00 114.83 ? ? ? ? ? ? 32 PHE A N 1 +ATOM 170 C CA . PHE A 1 30 ? 17.248 21.413 -10.728 1.00 113.80 ? ? ? ? ? ? 32 PHE A CA 1 +ATOM 171 C C . PHE A 1 30 ? 18.047 22.475 -11.541 1.00 114.52 ? ? ? ? ? ? 32 PHE A C 1 +ATOM 172 O O . PHE A 1 30 ? 18.937 23.145 -11.001 1.00 115.82 ? ? ? ? ? ? 32 PHE A O 1 +ATOM 173 C CB . PHE A 1 30 ? 16.487 22.093 -9.541 1.00 113.41 ? ? ? ? ? ? 32 PHE A CB 1 +ATOM 174 C CG . PHE A 1 30 ? 16.144 21.179 -8.346 1.00 112.64 ? ? ? ? ? ? 32 PHE A CG 1 +ATOM 175 C CD1 . PHE A 1 30 ? 15.540 21.740 -7.207 1.00 112.23 ? ? ? ? ? ? 32 PHE A CD1 1 +ATOM 176 C CD2 . PHE A 1 30 ? 16.423 19.805 -8.338 1.00 111.84 ? ? ? ? ? ? 32 PHE A CD2 1 +ATOM 177 C CE1 . PHE A 1 30 ? 15.212 20.957 -6.091 1.00 111.54 ? ? ? ? ? ? 32 PHE A CE1 1 +ATOM 178 C CE2 . PHE A 1 30 ? 16.110 19.015 -7.218 1.00 111.19 ? ? ? ? ? ? 32 PHE A CE2 1 +ATOM 179 C CZ . PHE A 1 30 ? 15.497 19.590 -6.097 1.00 111.08 ? ? ? ? ? ? 32 PHE A CZ 1 +ATOM 180 N N . HIS A 1 31 ? 17.677 22.645 -12.817 1.00 113.18 ? ? ? ? ? ? 33 HIS A N 1 +ATOM 181 C CA . HIS A 1 31 ? 18.505 23.317 -13.836 1.00 113.51 ? ? ? ? ? ? 33 HIS A CA 1 +ATOM 182 C C . HIS A 1 31 ? 17.843 24.573 -14.459 1.00 112.40 ? ? ? ? ? ? 33 HIS A C 1 +ATOM 183 O O . HIS A 1 31 ? 17.840 25.650 -13.849 1.00 112.91 ? ? ? ? ? ? 33 HIS A O 1 +ATOM 184 C CB . HIS A 1 31 ? 18.897 22.274 -14.908 1.00 113.74 ? ? ? ? ? ? 33 HIS A CB 1 +ATOM 185 C CG . HIS A 1 31 ? 19.881 22.761 -15.933 1.00 116.22 ? ? ? ? ? ? 33 HIS A CG 1 +ATOM 186 N ND1 . HIS A 1 31 ? 21.201 23.036 -15.635 1.00 118.98 ? ? ? ? ? ? 33 HIS A ND1 1 +ATOM 187 C CD2 . HIS A 1 31 ? 19.743 22.976 -17.264 1.00 116.72 ? ? ? ? ? ? 33 HIS A CD2 1 +ATOM 188 C CE1 . HIS A 1 31 ? 21.826 23.425 -16.734 1.00 120.25 ? ? ? ? ? ? 33 HIS A CE1 1 +ATOM 189 N NE2 . HIS A 1 31 ? 20.964 23.395 -17.736 1.00 119.10 ? ? ? ? ? ? 33 HIS A NE2 1 +ATOM 190 N N . HIS A 1 32 ? 17.298 24.431 -15.670 1.00 110.63 ? ? ? ? ? ? 34 HIS A N 1 +ATOM 191 C CA . HIS A 1 32 ? 16.630 25.529 -16.377 1.00 108.57 ? ? ? ? ? ? 34 HIS A CA 1 +ATOM 192 C C . HIS A 1 32 ? 15.315 25.908 -15.701 1.00 105.41 ? ? ? ? ? ? 34 HIS A C 1 +ATOM 193 O O . HIS A 1 32 ? 14.336 25.165 -15.760 1.00 102.47 ? ? ? ? ? ? 34 HIS A O 1 +ATOM 194 C CB . HIS A 1 32 ? 16.384 25.161 -17.858 1.00 108.29 ? ? ? ? ? ? 34 HIS A CB 1 +ATOM 195 C CG . HIS A 1 32 ? 15.859 26.296 -18.697 1.00 108.03 ? ? ? ? ? ? 34 HIS A CG 1 +ATOM 196 N ND1 . HIS A 1 32 ? 16.492 27.522 -18.778 1.00 111.34 ? ? ? ? ? ? 34 HIS A ND1 1 +ATOM 197 C CD2 . HIS A 1 32 ? 14.778 26.380 -19.511 1.00 103.90 ? ? ? ? ? ? 34 HIS A CD2 1 +ATOM 198 C CE1 . HIS A 1 32 ? 15.812 28.317 -19.586 1.00 109.77 ? ? ? ? ? ? 34 HIS A CE1 1 +ATOM 199 N NE2 . HIS A 1 32 ? 14.772 27.647 -20.051 1.00 105.66 ? ? ? ? ? ? 34 HIS A NE2 1 +ATOM 200 N N . SER A 1 33 ? 15.303 27.064 -15.056 1.00 104.75 ? ? ? ? ? ? 35 SER A N 1 +ATOM 201 C CA . SER A 1 33 ? 14.079 27.599 -14.485 1.00 101.92 ? ? ? ? ? ? 35 SER A CA 1 +ATOM 202 C C . SER A 1 33 ? 13.450 28.601 -15.456 1.00 99.94 ? ? ? ? ? ? 35 SER A C 1 +ATOM 203 O O . SER A 1 33 ? 14.146 29.196 -16.272 1.00 101.93 ? ? ? ? ? ? 35 SER A O 1 +ATOM 204 C CB . SER A 1 33 ? 14.372 28.236 -13.124 1.00 103.64 ? ? ? ? ? ? 35 SER A CB 1 +ATOM 205 O OG . SER A 1 33 ? 13.401 29.202 -12.771 1.00 103.74 ? ? ? ? ? ? 35 SER A OG 1 +ATOM 206 N N . GLU A 1 34 ? 12.136 28.778 -15.372 1.00 95.30 ? ? ? ? ? ? 36 GLU A N 1 +ATOM 207 C CA . GLU A 1 34 ? 11.425 29.699 -16.249 1.00 92.35 ? ? ? ? ? ? 36 GLU A CA 1 +ATOM 208 C C . GLU A 1 34 ? 10.221 30.272 -15.520 1.00 90.03 ? ? ? ? ? ? 36 GLU A C 1 +ATOM 209 O O . GLU A 1 34 ? 9.296 29.543 -15.201 1.00 87.29 ? ? ? ? ? ? 36 GLU A O 1 +ATOM 210 C CB . GLU A 1 34 ? 10.977 28.964 -17.511 1.00 90.67 ? ? ? ? ? ? 36 GLU A CB 1 +ATOM 211 C CG . GLU A 1 34 ? 10.555 29.867 -18.650 1.00 90.72 ? ? ? ? ? ? 36 GLU A CG 1 +ATOM 212 C CD . GLU A 1 34 ? 11.736 30.565 -19.310 1.00 96.24 ? ? ? ? ? ? 36 GLU A CD 1 +ATOM 213 O OE1 . GLU A 1 34 ? 12.815 29.937 -19.462 1.00 99.38 ? ? ? ? ? ? 36 GLU A OE1 1 +ATOM 214 O OE2 . GLU A 1 34 ? 11.578 31.748 -19.685 1.00 98.37 ? ? ? ? ? ? 36 GLU A OE2 1 +ATOM 215 N N . LYS A 1 35 ? 10.235 31.569 -15.239 1.00 90.36 ? ? ? ? ? ? 37 LYS A N 1 +ATOM 216 C CA . LYS A 1 35 ? 9.139 32.178 -14.506 1.00 88.38 ? ? ? ? ? ? 37 LYS A CA 1 +ATOM 217 C C . LYS A 1 35 ? 7.977 32.484 -15.433 1.00 85.67 ? ? ? ? ? ? 37 LYS A C 1 +ATOM 218 O O . LYS A 1 35 ? 8.172 32.833 -16.592 1.00 86.06 ? ? ? ? ? ? 37 LYS A O 1 +ATOM 219 C CB . LYS A 1 35 ? 9.601 33.433 -13.768 1.00 91.44 ? ? ? ? ? ? 37 LYS A CB 1 +ATOM 220 N N . LEU A 1 36 ? 6.766 32.325 -14.915 1.00 81.92 ? ? ? ? ? ? 38 LEU A N 1 +ATOM 221 C CA . LEU A 1 36 ? 5.539 32.641 -15.640 1.00 78.89 ? ? ? ? ? ? 38 LEU A CA 1 +ATOM 222 C C . LEU A 1 36 ? 4.640 33.528 -14.797 1.00 78.12 ? ? ? ? ? ? 38 LEU A C 1 +ATOM 223 O O . LEU A 1 36 ? 4.498 33.299 -13.601 1.00 77.83 ? ? ? ? ? ? 38 LEU A O 1 +ATOM 224 C CB . LEU A 1 36 ? 4.770 31.368 -15.979 1.00 77.62 ? ? ? ? ? ? 38 LEU A CB 1 +ATOM 225 C CG . LEU A 1 36 ? 4.861 30.675 -17.336 1.00 76.31 ? ? ? ? ? ? 38 LEU A CG 1 +ATOM 226 C CD1 . LEU A 1 36 ? 3.481 30.149 -17.653 1.00 74.28 ? ? ? ? ? ? 38 LEU A CD1 1 +ATOM 227 C CD2 . LEU A 1 36 ? 5.328 31.599 -18.436 1.00 76.23 ? ? ? ? ? ? 38 LEU A CD2 1 +ATOM 228 N N . ASP A 1 37 ? 4.015 34.523 -15.417 1.00 77.70 ? ? ? ? ? ? 39 ASP A N 1 +ATOM 229 C CA . ASP A 1 37 ? 3.127 35.429 -14.691 1.00 77.42 ? ? ? ? ? ? 39 ASP A CA 1 +ATOM 230 C C . ASP A 1 37 ? 1.666 35.169 -15.004 1.00 73.58 ? ? ? ? ? ? 39 ASP A C 1 +ATOM 231 O O . ASP A 1 37 ? 1.352 34.676 -16.075 1.00 72.04 ? ? ? ? ? ? 39 ASP A O 1 +ATOM 232 C CB . ASP A 1 37 ? 3.473 36.886 -14.995 1.00 80.86 ? ? ? ? ? ? 39 ASP A CB 1 +ATOM 233 C CG . ASP A 1 37 ? 4.632 37.408 -14.159 1.00 86.94 ? ? ? ? ? ? 39 ASP A CG 1 +ATOM 234 O OD1 . ASP A 1 37 ? 4.986 36.781 -13.125 1.00 88.70 ? ? ? ? ? ? 39 ASP A OD1 1 +ATOM 235 O OD2 . ASP A 1 37 ? 5.178 38.463 -14.548 1.00 92.58 ? ? ? ? ? ? 39 ASP A OD2 1 +ATOM 236 N N . LYS A 1 38 ? 0.788 35.520 -14.065 1.00 71.09 ? ? ? ? ? ? 40 LYS A N 1 +ATOM 237 C CA . LYS A 1 38 ? -0.646 35.219 -14.127 1.00 67.44 ? ? ? ? ? ? 40 LYS A CA 1 +ATOM 238 C C . LYS A 1 38 ? -1.246 35.395 -15.514 1.00 65.75 ? ? ? ? ? ? 40 LYS A C 1 +ATOM 239 O O . LYS A 1 38 ? -1.274 36.506 -16.038 1.00 66.82 ? ? ? ? ? ? 40 LYS A O 1 +ATOM 240 C CB . LYS A 1 38 ? -1.408 36.092 -13.130 1.00 67.43 ? ? ? ? ? ? 40 LYS A CB 1 +ATOM 241 C CG . LYS A 1 38 ? -2.847 35.692 -12.912 1.00 65.33 ? ? ? ? ? ? 40 LYS A CG 1 +ATOM 242 C CD . LYS A 1 38 ? -3.496 36.530 -11.819 1.00 65.17 ? ? ? ? ? ? 40 LYS A CD 1 +ATOM 243 C CE . LYS A 1 38 ? -4.727 35.828 -11.238 1.00 64.58 ? ? ? ? ? ? 40 LYS A CE 1 +ATOM 244 N NZ . LYS A 1 38 ? -5.911 36.738 -11.093 1.00 64.29 ? ? ? ? ? ? 40 LYS A NZ 1 +ATOM 245 N N . GLY A 1 39 ? -1.710 34.288 -16.097 1.00 62.75 ? ? ? ? ? ? 41 GLY A N 1 +ATOM 246 C CA . GLY A 1 39 ? -2.358 34.280 -17.410 1.00 60.49 ? ? ? ? ? ? 41 GLY A CA 1 +ATOM 247 C C . GLY A 1 39 ? -1.471 33.947 -18.599 1.00 60.30 ? ? ? ? ? ? 41 GLY A C 1 +ATOM 248 O O . GLY A 1 39 ? -1.957 33.805 -19.718 1.00 58.95 ? ? ? ? ? ? 41 GLY A O 1 +ATOM 249 N N . GLU A 1 40 ? -0.167 33.843 -18.366 1.00 61.59 ? ? ? ? ? ? 42 GLU A N 1 +ATOM 250 C CA . GLU A 1 40 ? 0.777 33.499 -19.424 1.00 62.43 ? ? ? ? ? ? 42 GLU A CA 1 +ATOM 251 C C . GLU A 1 40 ? 0.720 32.015 -19.667 1.00 59.62 ? ? ? ? ? ? 42 GLU A C 1 +ATOM 252 O O . GLU A 1 40 ? 0.425 31.239 -18.761 1.00 58.37 ? ? ? ? ? ? 42 GLU A O 1 +ATOM 253 C CB . GLU A 1 40 ? 2.200 33.917 -19.056 1.00 65.52 ? ? ? ? ? ? 42 GLU A CB 1 +ATOM 254 C CG . GLU A 1 40 ? 2.523 35.352 -19.404 1.00 71.75 ? ? ? ? ? ? 42 GLU A CG 1 +ATOM 255 C CD . GLU A 1 40 ? 3.754 35.879 -18.701 1.00 79.02 ? ? ? ? ? ? 42 GLU A CD 1 +ATOM 256 O OE1 . GLU A 1 40 ? 4.375 35.124 -17.926 1.00 79.96 ? ? ? ? ? ? 42 GLU A OE1 1 +ATOM 257 O OE2 . GLU A 1 40 ? 4.097 37.059 -18.923 1.00 83.29 ? ? ? ? ? ? 42 GLU A OE2 1 +ATOM 258 N N . VAL A 1 41 ? 1.004 31.619 -20.895 1.00 58.12 ? ? ? ? ? ? 43 VAL A N 1 +ATOM 259 C CA . VAL A 1 41 ? 0.931 30.221 -21.282 1.00 55.42 ? ? ? ? ? ? 43 VAL A CA 1 +ATOM 260 C C . VAL A 1 41 ? 2.254 29.747 -21.855 1.00 57.22 ? ? ? ? ? ? 43 VAL A C 1 +ATOM 261 O O . VAL A 1 41 ? 2.823 30.381 -22.755 1.00 58.88 ? ? ? ? ? ? 43 VAL A O 1 +ATOM 262 C CB . VAL A 1 41 ? -0.180 29.994 -22.309 1.00 53.28 ? ? ? ? ? ? 43 VAL A CB 1 +ATOM 263 C CG1 . VAL A 1 41 ? -0.060 28.645 -22.920 1.00 50.49 ? ? ? ? ? ? 43 VAL A CG1 1 +ATOM 264 C CG2 . VAL A 1 41 ? -1.523 30.132 -21.664 1.00 49.78 ? ? ? ? ? ? 43 VAL A CG2 1 +ATOM 265 N N . LEU A 1 42 ? 2.738 28.629 -21.323 1.00 57.21 ? ? ? ? ? ? 44 LEU A N 1 +ATOM 266 C CA . LEU A 1 42 ? 3.960 28.037 -21.813 1.00 58.54 ? ? ? ? ? ? 44 LEU A CA 1 +ATOM 267 C C . LEU A 1 42 ? 3.633 26.718 -22.458 1.00 56.54 ? ? ? ? ? ? 44 LEU A C 1 +ATOM 268 O O . LEU A 1 42 ? 2.882 25.928 -21.899 1.00 54.68 ? ? ? ? ? ? 44 LEU A O 1 +ATOM 269 C CB . LEU A 1 42 ? 4.954 27.852 -20.680 1.00 60.35 ? ? ? ? ? ? 44 LEU A CB 1 +ATOM 270 C CG . LEU A 1 42 ? 6.378 27.476 -21.074 1.00 64.66 ? ? ? ? ? ? 44 LEU A CG 1 +ATOM 271 C CD1 . LEU A 1 42 ? 7.071 28.595 -21.816 1.00 69.92 ? ? ? ? ? ? 44 LEU A CD1 1 +ATOM 272 C CD2 . LEU A 1 42 ? 7.171 27.112 -19.839 1.00 67.81 ? ? ? ? ? ? 44 LEU A CD2 1 +ATOM 273 N N . ILE A 1 43 ? 4.162 26.504 -23.657 1.00 56.61 ? ? ? ? ? ? 45 ILE A N 1 +ATOM 274 C CA . ILE A 1 43 ? 4.086 25.207 -24.298 1.00 55.49 ? ? ? ? ? ? 45 ILE A CA 1 +ATOM 275 C C . ILE A 1 43 ? 5.487 24.630 -24.267 1.00 57.96 ? ? ? ? ? ? 45 ILE A C 1 +ATOM 276 O O . ILE A 1 43 ? 6.345 25.038 -25.046 1.00 60.01 ? ? ? ? ? ? 45 ILE A O 1 +ATOM 277 C CB . ILE A 1 43 ? 3.621 25.276 -25.757 1.00 54.45 ? ? ? ? ? ? 45 ILE A CB 1 +ATOM 278 C CG1 . ILE A 1 43 ? 2.749 26.525 -26.016 1.00 53.11 ? ? ? ? ? ? 45 ILE A CG1 1 +ATOM 279 C CG2 . ILE A 1 43 ? 2.966 23.955 -26.167 1.00 50.96 ? ? ? ? ? ? 45 ILE A CG2 1 +ATOM 280 C CD1 . ILE A 1 43 ? 1.330 26.489 -25.511 1.00 48.47 ? ? ? ? ? ? 45 ILE A CD1 1 +ATOM 281 N N . ALA A 1 44 ? 5.708 23.687 -23.351 1.00 58.61 ? ? ? ? ? ? 46 ALA A N 1 +ATOM 282 C CA . ALA A 1 44 ? 7.019 23.104 -23.115 1.00 60.53 ? ? ? ? ? ? 46 ALA A CA 1 +ATOM 283 C C . ALA A 1 44 ? 7.098 21.728 -23.724 1.00 60.54 ? ? ? ? ? ? 46 ALA A C 1 +ATOM 284 O O . ALA A 1 44 ? 6.238 20.893 -23.489 1.00 58.05 ? ? ? ? ? ? 46 ALA A O 1 +ATOM 285 C CB . ALA A 1 44 ? 7.298 23.026 -21.643 1.00 61.04 ? ? ? ? ? ? 46 ALA A CB 1 +ATOM 286 N N . GLN A 1 45 ? 8.142 21.522 -24.518 1.00 63.39 ? ? ? ? ? ? 47 GLN A N 1 +ATOM 287 C CA . GLN A 1 45 ? 8.433 20.236 -25.131 1.00 64.77 ? ? ? ? ? ? 47 GLN A CA 1 +ATOM 288 C C . GLN A 1 45 ? 9.599 19.592 -24.406 1.00 67.08 ? ? ? ? ? ? 47 GLN A C 1 +ATOM 289 O O . GLN A 1 45 ? 10.492 20.287 -23.920 1.00 69.41 ? ? ? ? ? ? 47 GLN A O 1 +ATOM 290 C CB . GLN A 1 45 ? 8.791 20.423 -26.602 1.00 65.44 ? ? ? ? ? ? 47 GLN A CB 1 +ATOM 291 C CG . GLN A 1 45 ? 8.796 19.131 -27.399 1.00 65.31 ? ? ? ? ? ? 47 GLN A CG 1 +ATOM 292 C CD . GLN A 1 45 ? 9.318 19.305 -28.829 1.00 68.03 ? ? ? ? ? ? 47 GLN A CD 1 +ATOM 293 O OE1 . GLN A 1 45 ? 10.214 20.129 -29.090 1.00 70.64 ? ? ? ? ? ? 47 GLN A OE1 1 +ATOM 294 N NE2 . GLN A 1 45 ? 8.757 18.518 -29.767 1.00 65.95 ? ? ? ? ? ? 47 GLN A NE2 1 +ATOM 295 N N . PHE A 1 46 ? 9.590 18.266 -24.339 1.00 67.71 ? ? ? ? ? ? 48 PHE A N 1 +ATOM 296 C CA . PHE A 1 46 ? 10.706 17.526 -23.777 1.00 70.43 ? ? ? ? ? ? 48 PHE A CA 1 +ATOM 297 C C . PHE A 1 46 ? 11.857 17.437 -24.766 1.00 74.96 ? ? ? ? ? ? 48 PHE A C 1 +ATOM 298 O O . PHE A 1 46 ? 11.675 16.991 -25.907 1.00 74.94 ? ? ? ? ? ? 48 PHE A O 1 +ATOM 299 C CB . PHE A 1 46 ? 10.269 16.127 -23.384 1.00 67.85 ? ? ? ? ? ? 48 PHE A CB 1 +ATOM 300 C CG . PHE A 1 46 ? 9.527 16.081 -22.099 1.00 64.51 ? ? ? ? ? ? 48 PHE A CG 1 +ATOM 301 C CD1 . PHE A 1 46 ? 10.218 16.130 -20.894 1.00 65.87 ? ? ? ? ? ? 48 PHE A CD1 1 +ATOM 302 C CD2 . PHE A 1 46 ? 8.130 15.992 -22.085 1.00 59.45 ? ? ? ? ? ? 48 PHE A CD2 1 +ATOM 303 C CE1 . PHE A 1 46 ? 9.533 16.094 -19.687 1.00 63.95 ? ? ? ? ? ? 48 PHE A CE1 1 +ATOM 304 C CE2 . PHE A 1 46 ? 7.427 15.953 -20.885 1.00 57.67 ? ? ? ? ? ? 48 PHE A CE2 1 +ATOM 305 C CZ . PHE A 1 46 ? 8.130 16.002 -19.680 1.00 60.02 ? ? ? ? ? ? 48 PHE A CZ 1 +ATOM 306 N N . THR A 1 47 ? 13.038 17.869 -24.334 1.00 80.48 ? ? ? ? ? ? 49 THR A N 1 +ATOM 307 C CA . THR A 1 47 ? 14.238 17.712 -25.140 1.00 86.44 ? ? ? ? ? ? 49 THR A CA 1 +ATOM 308 C C . THR A 1 47 ? 14.993 16.474 -24.653 1.00 88.73 ? ? ? ? ? ? 49 THR A C 1 +ATOM 309 O O . THR A 1 47 ? 14.523 15.780 -23.752 1.00 86.98 ? ? ? ? ? ? 49 THR A O 1 +ATOM 310 C CB . THR A 1 47 ? 15.135 18.969 -25.068 1.00 89.11 ? ? ? ? ? ? 49 THR A CB 1 +ATOM 311 O OG1 . THR A 1 47 ? 15.953 18.934 -23.892 1.00 92.76 ? ? ? ? ? ? 49 THR A OG1 1 +ATOM 312 C CG2 . THR A 1 47 ? 14.285 20.230 -25.055 1.00 88.83 ? ? ? ? ? ? 49 THR A CG2 1 +ATOM 313 N N . GLU A 1 48 ? 16.145 16.187 -25.257 1.00 93.73 ? ? ? ? ? ? 50 GLU A N 1 +ATOM 314 C CA . GLU A 1 48 ? 17.052 15.170 -24.714 1.00 98.04 ? ? ? ? ? ? 50 GLU A CA 1 +ATOM 315 C C . GLU A 1 48 ? 17.700 15.685 -23.409 1.00 99.89 ? ? ? ? ? ? 50 GLU A C 1 +ATOM 316 O O . GLU A 1 48 ? 17.792 14.952 -22.420 1.00 99.46 ? ? ? ? ? ? 50 GLU A O 1 +ATOM 317 C CB . GLU A 1 48 ? 18.103 14.731 -25.754 1.00 100.79 ? ? ? ? ? ? 50 GLU A CB 1 +ATOM 318 C CG . GLU A 1 48 ? 19.096 15.818 -26.196 0.50 107.62 ? ? ? ? ? ? 50 GLU A CG 1 +ATOM 319 C CD . GLU A 1 48 ? 20.357 15.251 -26.838 0.50 115.10 ? ? ? ? ? ? 50 GLU A CD 1 +ATOM 320 O OE1 . GLU A 1 48 ? 21.467 15.702 -26.482 0.50 120.30 ? ? ? ? ? ? 50 GLU A OE1 1 +ATOM 321 O OE2 . GLU A 1 48 ? 20.241 14.354 -27.697 0.50 115.44 ? ? ? ? ? ? 50 GLU A OE2 1 +ATOM 322 N N . HIS A 1 49 ? 18.108 16.957 -23.422 1.00 102.54 ? ? ? ? ? ? 51 HIS A N 1 +ATOM 323 C CA . HIS A 1 49 ? 18.615 17.674 -22.247 1.00 104.56 ? ? ? ? ? ? 51 HIS A CA 1 +ATOM 324 C C . HIS A 1 49 ? 17.684 17.578 -21.032 1.00 100.90 ? ? ? ? ? ? 51 HIS A C 1 +ATOM 325 O O . HIS A 1 49 ? 18.145 17.604 -19.888 1.00 102.24 ? ? ? ? ? ? 51 HIS A O 1 +ATOM 326 C CB . HIS A 1 49 ? 18.790 19.162 -22.576 1.00 107.45 ? ? ? ? ? ? 51 HIS A CB 1 +ATOM 327 C CG . HIS A 1 49 ? 19.959 19.466 -23.458 1.00 115.35 ? ? ? ? ? ? 51 HIS A CG 1 +ATOM 328 N ND1 . HIS A 1 49 ? 19.964 19.199 -24.811 1.00 117.92 ? ? ? ? ? ? 51 HIS A ND1 1 +ATOM 329 C CD2 . HIS A 1 49 ? 21.153 20.047 -23.185 1.00 122.56 ? ? ? ? ? ? 51 HIS A CD2 1 +ATOM 330 C CE1 . HIS A 1 49 ? 21.117 19.586 -25.330 1.00 123.61 ? ? ? ? ? ? 51 HIS A CE1 1 +ATOM 331 N NE2 . HIS A 1 49 ? 21.855 20.106 -24.366 1.00 126.48 ? ? ? ? ? ? 51 HIS A NE2 1 +ATOM 332 N N . THR A 1 50 ? 16.377 17.481 -21.294 1.00 95.68 ? ? ? ? ? ? 52 THR A N 1 +ATOM 333 C CA . THR A 1 50 ? 15.340 17.640 -20.268 1.00 90.19 ? ? ? ? ? ? 52 THR A CA 1 +ATOM 334 C C . THR A 1 50 ? 14.528 16.370 -20.027 1.00 86.57 ? ? ? ? ? ? 52 THR A C 1 +ATOM 335 O O . THR A 1 50 ? 13.629 16.031 -20.795 1.00 83.93 ? ? ? ? ? ? 52 THR A O 1 +ATOM 336 C CB . THR A 1 50 ? 14.419 18.847 -20.596 1.00 89.09 ? ? ? ? ? ? 52 THR A CB 1 +ATOM 337 O OG1 . THR A 1 50 ? 15.128 20.061 -20.323 1.00 91.82 ? ? ? ? ? ? 52 THR A OG1 1 +ATOM 338 C CG2 . THR A 1 50 ? 13.158 18.832 -19.761 1.00 84.32 ? ? ? ? ? ? 52 THR A CG2 1 +ATOM 339 N N . SER A 1 51 ? 14.863 15.686 -18.938 1.00 85.07 ? ? ? ? ? ? 53 SER A N 1 +ATOM 340 C CA . SER A 1 51 ? 14.183 14.465 -18.518 1.00 82.20 ? ? ? ? ? ? 53 SER A CA 1 +ATOM 341 C C . SER A 1 51 ? 12.860 14.724 -17.792 1.00 78.23 ? ? ? ? ? ? 53 SER A C 1 +ATOM 342 O O . SER A 1 51 ? 11.863 14.057 -18.069 1.00 75.30 ? ? ? ? ? ? 53 SER A O 1 +ATOM 343 C CB . SER A 1 51 ? 15.103 13.617 -17.631 1.00 84.25 ? ? ? ? ? ? 53 SER A CB 1 +ATOM 344 O OG . SER A 1 51 ? 15.508 14.324 -16.475 1.00 87.22 ? ? ? ? ? ? 53 SER A OG 1 +ATOM 345 N N . ALA A 1 52 ? 12.855 15.681 -16.867 1.00 76.66 ? ? ? ? ? ? 54 ALA A N 1 +ATOM 346 C CA . ALA A 1 52 ? 11.660 15.983 -16.082 1.00 73.63 ? ? ? ? ? ? 54 ALA A CA 1 +ATOM 347 C C . ALA A 1 52 ? 11.347 17.470 -16.020 1.00 72.67 ? ? ? ? ? ? 54 ALA A C 1 +ATOM 348 O O . ALA A 1 52 ? 12.231 18.295 -16.168 1.00 74.97 ? ? ? ? ? ? 54 ALA A O 1 +ATOM 349 C CB . ALA A 1 52 ? 11.807 15.427 -14.697 1.00 73.72 ? ? ? ? ? ? 54 ALA A CB 1 +ATOM 350 N N . ILE A 1 53 ? 10.078 17.799 -15.808 1.00 69.28 ? ? ? ? ? ? 55 ILE A N 1 +ATOM 351 C CA . ILE A 1 53 ? 9.644 19.182 -15.648 1.00 67.60 ? ? ? ? ? ? 55 ILE A CA 1 +ATOM 352 C C . ILE A 1 53 ? 8.807 19.315 -14.386 1.00 66.31 ? ? ? ? ? ? 55 ILE A C 1 +ATOM 353 O O . ILE A 1 53 ? 7.813 18.615 -14.234 1.00 63.74 ? ? ? ? ? ? 55 ILE A O 1 +ATOM 354 C CB . ILE A 1 53 ? 8.816 19.679 -16.852 1.00 66.27 ? ? ? ? ? ? 55 ILE A CB 1 +ATOM 355 C CG1 . ILE A 1 53 ? 9.678 19.756 -18.104 1.00 67.47 ? ? ? ? ? ? 55 ILE A CG1 1 +ATOM 356 C CG2 . ILE A 1 53 ? 8.217 21.057 -16.579 1.00 65.21 ? ? ? ? ? ? 55 ILE A CG2 1 +ATOM 357 C CD1 . ILE A 1 53 ? 8.873 19.776 -19.383 1.00 65.20 ? ? ? ? ? ? 55 ILE A CD1 1 +ATOM 358 N N . LYS A 1 54 ? 9.212 20.225 -13.498 1.00 67.56 ? ? ? ? ? ? 56 LYS A N 1 +ATOM 359 C CA . LYS A 1 54 ? 8.518 20.471 -12.242 1.00 66.86 ? ? ? ? ? ? 56 LYS A CA 1 +ATOM 360 C C . LYS A 1 54 ? 7.790 21.787 -12.345 1.00 66.25 ? ? ? ? ? ? 56 LYS A C 1 +ATOM 361 O O . LYS A 1 54 ? 8.325 22.736 -12.899 1.00 67.88 ? ? ? ? ? ? 56 LYS A O 1 +ATOM 362 C CB . LYS A 1 54 ? 9.524 20.526 -11.091 1.00 69.15 ? ? ? ? ? ? 56 LYS A CB 1 +ATOM 363 C CG . LYS A 1 54 ? 8.919 20.527 -9.688 1.00 66.38 ? ? ? ? ? ? 56 LYS A CG 1 +ATOM 364 C CD . LYS A 1 54 ? 9.898 21.069 -8.644 1.00 66.41 ? ? ? ? ? ? 56 LYS A CD 1 +ATOM 365 C CE . LYS A 1 54 ? 10.805 19.996 -8.061 1.00 66.08 ? ? ? ? ? ? 56 LYS A CE 1 +ATOM 366 N NZ . LYS A 1 54 ? 11.738 20.531 -7.020 1.00 66.38 ? ? ? ? ? ? 56 LYS A NZ 1 +ATOM 367 N N . VAL A 1 55 ? 6.569 21.843 -11.826 1.00 63.79 ? ? ? ? ? ? 57 VAL A N 1 +ATOM 368 C CA . VAL A 1 55 ? 5.805 23.088 -11.783 1.00 62.60 ? ? ? ? ? ? 57 VAL A CA 1 +ATOM 369 C C . VAL A 1 55 ? 5.508 23.478 -10.335 1.00 63.99 ? ? ? ? ? ? 57 VAL A C 1 +ATOM 370 O O . VAL A 1 55 ? 4.827 22.751 -9.607 1.00 62.58 ? ? ? ? ? ? 57 VAL A O 1 +ATOM 371 C CB . VAL A 1 55 ? 4.491 22.999 -12.582 1.00 60.05 ? ? ? ? ? ? 57 VAL A CB 1 +ATOM 372 C CG1 . VAL A 1 55 ? 3.777 24.330 -12.592 1.00 58.65 ? ? ? ? ? ? 57 VAL A CG1 1 +ATOM 373 C CG2 . VAL A 1 55 ? 4.759 22.561 -14.001 1.00 57.89 ? ? ? ? ? ? 57 VAL A CG2 1 +ATOM 374 N N . ARG A 1 56 ? 6.046 24.625 -9.926 1.00 67.06 ? ? ? ? ? ? 58 ARG A N 1 +ATOM 375 C CA . ARG A 1 56 ? 5.822 25.201 -8.602 1.00 68.68 ? ? ? ? ? ? 58 ARG A CA 1 +ATOM 376 C C . ARG A 1 56 ? 4.944 26.430 -8.775 1.00 68.31 ? ? ? ? ? ? 58 ARG A C 1 +ATOM 377 O O . ARG A 1 56 ? 5.295 27.346 -9.516 1.00 69.78 ? ? ? ? ? ? 58 ARG A O 1 +ATOM 378 C CB . ARG A 1 56 ? 7.149 25.622 -7.961 1.00 71.82 ? ? ? ? ? ? 58 ARG A CB 1 +ATOM 379 C CG . ARG A 1 56 ? 7.919 24.540 -7.264 1.00 71.32 ? ? ? ? ? ? 58 ARG A CG 1 +ATOM 380 C CD . ARG A 1 56 ? 8.899 25.124 -6.251 1.00 74.34 ? ? ? ? ? ? 58 ARG A CD 1 +ATOM 381 N NE . ARG A 1 56 ? 10.303 24.967 -6.641 1.00 76.63 ? ? ? ? ? ? 58 ARG A NE 1 +ATOM 382 C CZ . ARG A 1 56 ? 11.114 24.011 -6.180 1.00 77.74 ? ? ? ? ? ? 58 ARG A CZ 1 +ATOM 383 N NH1 . ARG A 1 56 ? 10.668 23.111 -5.308 1.00 77.26 ? ? ? ? ? ? 58 ARG A NH1 1 +ATOM 384 N NH2 . ARG A 1 56 ? 12.380 23.947 -6.590 1.00 79.00 ? ? ? ? ? ? 58 ARG A NH2 1 +ATOM 385 N N . GLY A 1 57 ? 3.795 26.450 -8.116 1.00 66.23 ? ? ? ? ? ? 59 GLY A N 1 +ATOM 386 C CA . GLY A 1 57 ? 2.891 27.591 -8.224 1.00 64.54 ? ? ? ? ? ? 59 GLY A CA 1 +ATOM 387 C C . GLY A 1 57 ? 1.515 27.161 -8.671 1.00 61.40 ? ? ? ? ? ? 59 GLY A C 1 +ATOM 388 O O . GLY A 1 57 ? 1.324 26.011 -9.023 1.00 60.50 ? ? ? ? ? ? 59 GLY A O 1 +ATOM 389 N N . LYS A 1 58 ? 0.553 28.077 -8.652 1.00 59.63 ? ? ? ? ? ? 60 LYS A N 1 +ATOM 390 C CA . LYS A 1 58 ? -0.823 27.767 -9.030 1.00 56.33 ? ? ? ? ? ? 60 LYS A CA 1 +ATOM 391 C C . LYS A 1 58 ? -0.937 27.782 -10.560 1.00 54.36 ? ? ? ? ? ? 60 LYS A C 1 +ATOM 392 O O . LYS A 1 58 ? -0.806 28.840 -11.173 1.00 55.40 ? ? ? ? ? ? 60 LYS A O 1 +ATOM 393 C CB . LYS A 1 58 ? -1.776 28.800 -8.402 1.00 56.75 ? ? ? ? ? ? 60 LYS A CB 1 +ATOM 394 C CG . LYS A 1 58 ? -3.130 28.251 -7.937 1.00 56.71 ? ? ? ? ? ? 60 LYS A CG 1 +ATOM 395 C CD . LYS A 1 58 ? -3.097 27.743 -6.485 1.00 57.00 ? ? ? ? ? ? 60 LYS A CD 1 +ATOM 396 C CE . LYS A 1 58 ? -4.401 27.012 -6.119 1.00 56.07 ? ? ? ? ? ? 60 LYS A CE 1 +ATOM 397 N N . ALA A 1 59 ? -1.157 26.623 -11.185 1.00 50.90 ? ? ? ? ? ? 61 ALA A N 1 +ATOM 398 C CA . ALA A 1 59 ? -1.229 26.563 -12.652 1.00 48.01 ? ? ? ? ? ? 61 ALA A CA 1 +ATOM 399 C C . ALA A 1 59 ? -2.205 25.512 -13.166 1.00 44.63 ? ? ? ? ? ? 61 ALA A C 1 +ATOM 400 O O . ALA A 1 59 ? -2.516 24.556 -12.458 1.00 43.62 ? ? ? ? ? ? 61 ALA A O 1 +ATOM 401 C CB . ALA A 1 59 ? 0.153 26.320 -13.244 1.00 49.49 ? ? ? ? ? ? 61 ALA A CB 1 +ATOM 402 N N . TYR A 1 60 ? -2.667 25.686 -14.404 1.00 41.70 ? ? ? ? ? ? 62 TYR A N 1 +ATOM 403 C CA . TYR A 1 60 ? -3.493 24.707 -15.082 1.00 38.07 ? ? ? ? ? ? 62 TYR A CA 1 +ATOM 404 C C . TYR A 1 60 ? -2.627 24.044 -16.134 1.00 37.82 ? ? ? ? ? ? 62 TYR A C 1 +ATOM 405 O O . TYR A 1 60 ? -1.998 24.722 -16.954 1.00 38.91 ? ? ? ? ? ? 62 TYR A O 1 +ATOM 406 C CB . TYR A 1 60 ? -4.671 25.417 -15.716 1.00 36.81 ? ? ? ? ? ? 62 TYR A CB 1 +ATOM 407 C CG . TYR A 1 60 ? -5.719 24.566 -16.417 1.00 33.24 ? ? ? ? ? ? 62 TYR A CG 1 +ATOM 408 C CD1 . TYR A 1 60 ? -6.553 23.709 -15.702 1.00 30.81 ? ? ? ? ? ? 62 TYR A CD1 1 +ATOM 409 C CD2 . TYR A 1 60 ? -5.925 24.669 -17.795 1.00 32.16 ? ? ? ? ? ? 62 TYR A CD2 1 +ATOM 410 C CE1 . TYR A 1 60 ? -7.554 22.938 -16.349 1.00 26.98 ? ? ? ? ? ? 62 TYR A CE1 1 +ATOM 411 C CE2 . TYR A 1 60 ? -6.915 23.914 -18.446 1.00 29.38 ? ? ? ? ? ? 62 TYR A CE2 1 +ATOM 412 C CZ . TYR A 1 60 ? -7.728 23.053 -17.716 1.00 26.79 ? ? ? ? ? ? 62 TYR A CZ 1 +ATOM 413 O OH . TYR A 1 60 ? -8.701 22.329 -18.381 1.00 24.12 ? ? ? ? ? ? 62 TYR A OH 1 +ATOM 414 N N . ILE A 1 61 ? -2.579 22.717 -16.097 1.00 36.07 ? ? ? ? ? ? 63 ILE A N 1 +ATOM 415 C CA . ILE A 1 61 ? -1.662 21.980 -16.938 1.00 35.83 ? ? ? ? ? ? 63 ILE A CA 1 +ATOM 416 C C . ILE A 1 61 ? -2.384 20.971 -17.798 1.00 33.41 ? ? ? ? ? ? 63 ILE A C 1 +ATOM 417 O O . ILE A 1 61 ? -3.202 20.217 -17.298 1.00 31.94 ? ? ? ? ? ? 63 ILE A O 1 +ATOM 418 C CB . ILE A 1 61 ? -0.610 21.239 -16.097 1.00 37.09 ? ? ? ? ? ? 63 ILE A CB 1 +ATOM 419 C CG1 . ILE A 1 61 ? 0.153 22.208 -15.183 1.00 40.08 ? ? ? ? ? ? 63 ILE A CG1 1 +ATOM 420 C CG2 . ILE A 1 61 ? 0.358 20.461 -17.018 1.00 38.40 ? ? ? ? ? ? 63 ILE A CG2 1 +ATOM 421 C CD1 . ILE A 1 61 ? 0.912 21.521 -14.083 1.00 42.02 ? ? ? ? ? ? 63 ILE A CD1 1 +ATOM 422 N N . GLN A 1 62 ? -2.075 20.961 -19.094 1.00 32.65 ? ? ? ? ? ? 64 GLN A N 1 +ATOM 423 C CA . GLN A 1 62 ? -2.645 19.966 -20.035 1.00 31.02 ? ? ? ? ? ? 64 GLN A CA 1 +ATOM 424 C C . GLN A 1 62 ? -1.536 19.076 -20.577 1.00 31.29 ? ? ? ? ? ? 64 GLN A C 1 +ATOM 425 O O . GLN A 1 62 ? -0.503 19.573 -21.072 1.00 33.32 ? ? ? ? ? ? 64 GLN A O 1 +ATOM 426 C CB . GLN A 1 62 ? -3.321 20.649 -21.251 1.00 30.42 ? ? ? ? ? ? 64 GLN A CB 1 +ATOM 427 C CG . GLN A 1 62 ? -4.366 21.714 -20.928 1.00 29.89 ? ? ? ? ? ? 64 GLN A CG 1 +ATOM 428 C CD . GLN A 1 62 ? -5.024 22.308 -22.172 1.00 30.22 ? ? ? ? ? ? 64 GLN A CD 1 +ATOM 429 O OE1 . GLN A 1 62 ? -4.345 22.746 -23.129 1.00 31.89 ? ? ? ? ? ? 64 GLN A OE1 1 +ATOM 430 N NE2 . GLN A 1 62 ? -6.362 22.351 -22.155 1.00 28.53 ? ? ? ? ? ? 64 GLN A NE2 1 +ATOM 431 N N . THR A 1 63 ? -1.751 17.773 -20.518 1.00 29.70 ? ? ? ? ? ? 65 THR A N 1 +ATOM 432 C CA . THR A 1 63 ? -0.825 16.842 -21.142 1.00 29.95 ? ? ? ? ? ? 65 THR A CA 1 +ATOM 433 C C . THR A 1 63 ? -1.610 15.830 -21.967 1.00 28.22 ? ? ? ? ? ? 65 THR A C 1 +ATOM 434 O O . THR A 1 63 ? -2.852 15.745 -21.879 1.00 26.39 ? ? ? ? ? ? 65 THR A O 1 +ATOM 435 C CB . THR A 1 63 ? -0.010 16.071 -20.095 1.00 30.81 ? ? ? ? ? ? 65 THR A CB 1 +ATOM 436 O OG1 . THR A 1 63 ? -0.897 15.297 -19.248 1.00 30.42 ? ? ? ? ? ? 65 THR A OG1 1 +ATOM 437 C CG2 . THR A 1 63 ? 0.824 17.023 -19.275 1.00 33.74 ? ? ? ? ? ? 65 THR A CG2 1 +ATOM 438 N N . ARG A 1 64 ? -0.886 15.027 -22.737 1.00 28.10 ? ? ? ? ? ? 66 ARG A N 1 +ATOM 439 C CA . ARG A 1 64 ? -1.516 13.903 -23.389 1.00 26.73 ? ? ? ? ? ? 66 ARG A CA 1 +ATOM 440 C C . ARG A 1 64 ? -2.410 13.108 -22.409 1.00 25.08 ? ? ? ? ? ? 66 ARG A C 1 +ATOM 441 O O . ARG A 1 64 ? -3.376 12.454 -22.828 1.00 23.73 ? ? ? ? ? ? 66 ARG A O 1 +ATOM 442 C CB . ARG A 1 64 ? -0.460 13.014 -24.044 1.00 27.91 ? ? ? ? ? ? 66 ARG A CB 1 +ATOM 443 C CG . ARG A 1 64 ? -1.032 11.692 -24.648 1.00 29.01 ? ? ? ? ? ? 66 ARG A CG 1 +ATOM 444 C CD . ARG A 1 64 ? -0.213 11.224 -25.909 1.00 33.87 ? ? ? ? ? ? 66 ARG A CD 1 +ATOM 445 N NE . ARG A 1 64 ? 1.113 10.719 -25.542 1.00 39.87 ? ? ? ? ? ? 66 ARG A NE 1 +ATOM 446 C CZ . ARG A 1 64 ? 1.273 9.451 -25.149 1.00 45.46 ? ? ? ? ? ? 66 ARG A CZ 1 +ATOM 447 N NH1 . ARG A 1 64 ? 2.466 9.006 -24.775 1.00 48.49 ? ? ? ? ? ? 66 ARG A NH1 1 +ATOM 448 N NH2 . ARG A 1 64 ? 0.208 8.625 -25.112 1.00 45.95 ? ? ? ? ? ? 66 ARG A NH2 1 +ATOM 449 N N . HIS A 1 65 ? -2.111 13.173 -21.107 1.00 24.86 ? ? ? ? ? ? 67 HIS A N 1 +ATOM 450 C CA . HIS A 1 65 ? -2.841 12.331 -20.131 1.00 24.10 ? ? ? ? ? ? 67 HIS A CA 1 +ATOM 451 C C . HIS A 1 65 ? -4.020 13.013 -19.469 1.00 23.34 ? ? ? ? ? ? 67 HIS A C 1 +ATOM 452 O O . HIS A 1 65 ? -4.610 12.431 -18.508 1.00 22.91 ? ? ? ? ? ? 67 HIS A O 1 +ATOM 453 C CB . HIS A 1 65 ? -1.918 11.730 -19.064 1.00 24.80 ? ? ? ? ? ? 67 HIS A CB 1 +ATOM 454 C CG . HIS A 1 65 ? -0.816 10.907 -19.640 1.00 27.48 ? ? ? ? ? ? 67 HIS A CG 1 +ATOM 455 N ND1 . HIS A 1 65 ? -0.956 10.191 -20.818 1.00 28.09 ? ? ? ? ? ? 67 HIS A ND1 1 +ATOM 456 C CD2 . HIS A 1 65 ? 0.447 10.682 -19.209 1.00 30.60 ? ? ? ? ? ? 67 HIS A CD2 1 +ATOM 457 C CE1 . HIS A 1 65 ? 0.181 9.571 -21.091 1.00 30.69 ? ? ? ? ? ? 67 HIS A CE1 1 +ATOM 458 N NE2 . HIS A 1 65 ? 1.041 9.835 -20.121 1.00 32.56 ? ? ? ? ? ? 67 HIS A NE2 1 +ATOM 459 N N . GLY A 1 66 ? -4.357 14.217 -19.977 1.00 23.45 ? ? ? ? ? ? 68 GLY A N 1 +ATOM 460 C CA . GLY A 1 66 ? -5.543 14.957 -19.528 1.00 23.05 ? ? ? ? ? ? 68 GLY A CA 1 +ATOM 461 C C . GLY A 1 66 ? -5.125 16.212 -18.813 1.00 23.58 ? ? ? ? ? ? 68 GLY A C 1 +ATOM 462 O O . GLY A 1 66 ? -3.974 16.630 -18.952 1.00 24.68 ? ? ? ? ? ? 68 GLY A O 1 +ATOM 463 N N . VAL A 1 67 ? -6.046 16.822 -18.054 1.00 23.73 ? ? ? ? ? ? 69 VAL A N 1 +ATOM 464 C CA . VAL A 1 67 ? -5.685 18.035 -17.310 1.00 25.29 ? ? ? ? ? ? 69 VAL A CA 1 +ATOM 465 C C . VAL A 1 67 ? -5.378 17.774 -15.842 1.00 27.38 ? ? ? ? ? ? 69 VAL A C 1 +ATOM 466 O O . VAL A 1 67 ? -5.799 16.787 -15.265 1.00 26.03 ? ? ? ? ? ? 69 VAL A O 1 +ATOM 467 C CB . VAL A 1 67 ? -6.706 19.173 -17.463 1.00 24.18 ? ? ? ? ? ? 69 VAL A CB 1 +ATOM 468 C CG1 . VAL A 1 67 ? -7.328 19.087 -18.796 1.00 23.47 ? ? ? ? ? ? 69 VAL A CG1 1 +ATOM 469 C CG2 . VAL A 1 67 ? -7.792 19.078 -16.407 1.00 23.38 ? ? ? ? ? ? 69 VAL A CG2 1 +ATOM 470 N N . ILE A 1 68 ? -4.609 18.685 -15.274 1.00 31.58 ? ? ? ? ? ? 70 ILE A N 1 +ATOM 471 C CA . ILE A 1 68 ? -4.257 18.667 -13.875 1.00 35.85 ? ? ? ? ? ? 70 ILE A CA 1 +ATOM 472 C C . ILE A 1 68 ? -3.894 20.103 -13.437 1.00 40.48 ? ? ? ? ? ? 70 ILE A C 1 +ATOM 473 O O . ILE A 1 68 ? -3.442 20.943 -14.252 1.00 41.26 ? ? ? ? ? ? 70 ILE A O 1 +ATOM 474 C CB . ILE A 1 68 ? -3.137 17.660 -13.591 1.00 35.31 ? ? ? ? ? ? 70 ILE A CB 1 +ATOM 475 C CG1 . ILE A 1 68 ? -3.062 17.400 -12.099 1.00 34.94 ? ? ? ? ? ? 70 ILE A CG1 1 +ATOM 476 C CG2 . ILE A 1 68 ? -1.813 18.148 -14.144 1.00 36.89 ? ? ? ? ? ? 70 ILE A CG2 1 +ATOM 477 C CD1 . ILE A 1 68 ? -2.514 16.052 -11.774 1.00 34.03 ? ? ? ? ? ? 70 ILE A CD1 1 +ATOM 478 N N . GLU A 1 69 ? -4.123 20.367 -12.150 1.00 45.39 ? ? ? ? ? ? 71 GLU A N 1 +ATOM 479 C CA . GLU A 1 69 ? -3.959 21.684 -11.556 1.00 51.34 ? ? ? ? ? ? 71 GLU A CA 1 +ATOM 480 C C . GLU A 1 69 ? -2.832 21.594 -10.527 1.00 55.11 ? ? ? ? ? ? 71 GLU A C 1 +ATOM 481 O O . GLU A 1 69 ? -2.859 20.721 -9.664 1.00 55.41 ? ? ? ? ? ? 71 GLU A O 1 +ATOM 482 C CB . GLU A 1 69 ? -5.285 22.073 -10.896 1.00 50.78 ? ? ? ? ? ? 71 GLU A CB 1 +ATOM 483 C CG . GLU A 1 69 ? -5.358 23.453 -10.275 1.00 56.29 ? ? ? ? ? ? 71 GLU A CG 1 +ATOM 484 C CD . GLU A 1 69 ? -6.733 23.756 -9.687 1.00 59.81 ? ? ? ? ? ? 71 GLU A CD 1 +ATOM 485 O OE1 . GLU A 1 69 ? -6.805 24.062 -8.476 1.00 61.66 ? ? ? ? ? ? 71 GLU A OE1 1 +ATOM 486 O OE2 . GLU A 1 69 ? -7.742 23.685 -10.439 1.00 59.40 ? ? ? ? ? ? 71 GLU A OE2 1 +ATOM 487 N N . SER A 1 70 ? -1.830 22.463 -10.633 1.00 60.26 ? ? ? ? ? ? 72 SER A N 1 +ATOM 488 C CA . SER A 1 70 ? -0.785 22.528 -9.618 1.00 65.19 ? ? ? ? ? ? 72 SER A CA 1 +ATOM 489 C C . SER A 1 70 ? -1.191 23.554 -8.582 1.00 67.72 ? ? ? ? ? ? 72 SER A C 1 +ATOM 490 O O . SER A 1 70 ? -1.586 24.664 -8.933 1.00 68.67 ? ? ? ? ? ? 72 SER A O 1 +ATOM 491 C CB . SER A 1 70 ? 0.566 22.885 -10.232 1.00 66.81 ? ? ? ? ? ? 72 SER A CB 1 +ATOM 492 O OG . SER A 1 70 ? 0.520 24.141 -10.869 1.00 69.19 ? ? ? ? ? ? 72 SER A OG 1 +ATOM 493 N N . GLU A 1 71 ? -1.109 23.173 -7.312 1.00 70.07 ? ? ? ? ? ? 73 GLU A N 1 +ATOM 494 C CA . GLU A 1 71 ? -1.494 24.038 -6.212 1.00 72.36 ? ? ? ? ? ? 73 GLU A CA 1 +ATOM 495 C C . GLU A 1 71 ? -0.236 24.266 -5.347 1.00 75.16 ? ? ? ? ? ? 73 GLU A C 1 +ATOM 496 O O . GLU A 1 71 ? -0.249 24.010 -4.173 1.00 77.08 ? ? ? ? ? ? 73 GLU A O 1 +ATOM 497 C CB . GLU A 1 71 ? -2.606 23.360 -5.394 1.00 71.07 ? ? ? ? ? ? 73 GLU A CB 1 +ATOM 498 C CG . GLU A 1 71 ? -3.410 22.310 -6.167 1.00 69.29 ? ? ? ? ? ? 73 GLU A CG 1 +ATOM 499 C CD . GLU A 1 71 ? -4.836 22.110 -5.652 1.00 67.49 ? ? ? ? ? ? 73 GLU A CD 1 +ATOM 500 O OE1 . GLU A 1 71 ? -5.627 23.072 -5.780 1.00 67.26 ? ? ? ? ? ? 73 GLU A OE1 1 +ATOM 501 O OE2 . GLU A 1 71 ? -5.169 20.998 -5.157 1.00 64.72 ? ? ? ? ? ? 73 GLU A OE2 1 +ATOM 506 N N . LYS A 1 72 ? 3.692 26.048 -3.818 1.00 78.11 ? ? ? ? ? ? 75 LYS A N 1 +ATOM 507 C CA . LYS A 1 72 ? 4.129 27.336 -3.223 1.00 79.14 ? ? ? ? ? ? 75 LYS A CA 1 +ATOM 508 C C . LYS A 1 72 ? 4.479 28.474 -4.244 1.00 79.69 ? ? ? ? ? ? 75 LYS A C 1 +ATOM 509 O O . LYS A 1 72 ? 5.535 28.516 -4.903 1.00 79.72 ? ? ? ? ? ? 75 LYS A O 1 +ATOM 510 C CB . LYS A 1 72 ? 5.211 27.143 -2.149 1.00 79.82 ? ? ? ? ? ? 75 LYS A CB 1 +ATOM 511 C CG . LYS A 1 72 ? 6.646 27.001 -2.680 1.00 82.03 ? ? ? ? ? ? 75 LYS A CG 1 +ATOM 512 C CD . LYS A 1 72 ? 7.702 26.968 -1.556 1.00 83.81 ? ? ? ? ? ? 75 LYS A CD 1 +ATOM 513 C CE . LYS A 1 72 ? 9.130 26.847 -2.110 1.00 84.65 ? ? ? ? ? ? 75 LYS A CE 1 +ATOM 514 N NZ . LYS A 1 72 ? 10.106 26.489 -1.037 1.00 84.64 ? ? ? ? ? ? 75 LYS A NZ 1 diff --git a/modules/seq/alg/tests/testfiles/validate_seqres_aln_connected.mmcif b/modules/seq/alg/tests/testfiles/validate_seqres_aln_connected.mmcif new file mode 100644 index 0000000000000000000000000000000000000000..2e76cf323b55cd273db4cfd97b9b9d53a6aac9f3 --- /dev/null +++ b/modules/seq/alg/tests/testfiles/validate_seqres_aln_connected.mmcif @@ -0,0 +1,564 @@ +data_3BAR +# based on 3AQD +_entry.id 3BAR +# +loop_ +_entity.id +_entity.type +_entity.src_method +_entity.pdbx_description +_entity.formula_weight +_entity.pdbx_number_of_molecules +_entity.details +1 polymer man 'Transcription attenuation protein mtrB' 8257.458 22 ? +2 water nat water 18.015 7 ? +# +_entity_poly.entity_id 1 +_entity_poly.type 'polypeptide(L)' +_entity_poly.nstd_linkage no +_entity_poly.nstd_monomer no +_entity_poly.pdbx_seq_one_letter_code MYTNSDFVVIKALEDGVNVIGLTRGADTRFHHSEKLDKGEVLIAQFTEHTSAIKVRGKAYIQTRHGVIESEGGKK +_entity_poly.pdbx_seq_one_letter_code_can MYTNSDFVVIKALEDGVNVIGLTRGADTRFHHSEKLDKGEVLIAQFTEHTSAIKVRGKAYIQTRHGVIESEGGKK +_entity_poly.pdbx_strand_id A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V +# +loop_ +_atom_site.group_PDB +_atom_site.id +_atom_site.type_symbol +_atom_site.label_atom_id +_atom_site.label_alt_id +_atom_site.label_comp_id +_atom_site.label_asym_id +_atom_site.label_entity_id +_atom_site.label_seq_id +_atom_site.pdbx_PDB_ins_code +_atom_site.Cartn_x +_atom_site.Cartn_y +_atom_site.Cartn_z +_atom_site.occupancy +_atom_site.B_iso_or_equiv +_atom_site.Cartn_x_esd +_atom_site.Cartn_y_esd +_atom_site.Cartn_z_esd +_atom_site.occupancy_esd +_atom_site.B_iso_or_equiv_esd +_atom_site.pdbx_formal_charge +_atom_site.auth_seq_id +_atom_site.auth_comp_id +_atom_site.auth_asym_id +_atom_site.auth_atom_id +_atom_site.pdbx_PDB_model_num +ATOM 1 N N . SER A 1 5 ? 8.892 13.236 -28.550 1.00 81.62 ? ? ? ? ? ? 7 SER A N 1 +ATOM 2 C CA . SER A 1 5 ? 8.449 14.550 -29.128 1.00 80.98 ? ? ? ? ? ? 7 SER A CA 1 +ATOM 3 C C . SER A 1 5 ? 7.181 15.159 -28.476 1.00 77.44 ? ? ? ? ? ? 7 SER A C 1 +ATOM 4 O O . SER A 1 5 ? 6.463 15.940 -29.117 1.00 76.80 ? ? ? ? ? ? 7 SER A O 1 +ATOM 5 C CB . SER A 1 5 ? 8.239 14.416 -30.651 1.00 81.96 ? ? ? ? ? ? 7 SER A CB 1 +ATOM 6 O OG . SER A 1 5 ? 9.441 14.629 -31.378 1.00 87.04 ? ? ? ? ? ? 7 SER A OG 1 +ATOM 7 N N . ASP A 1 6 ? 6.910 14.822 -27.217 1.00 73.87 ? ? ? ? ? ? 8 ASP A N 1 +ATOM 8 C CA . ASP A 1 6 ? 5.670 15.258 -26.582 1.00 69.40 ? ? ? ? ? ? 8 ASP A CA 1 +ATOM 9 C C . ASP A 1 6 ? 5.834 16.550 -25.785 1.00 68.43 ? ? ? ? ? ? 8 ASP A C 1 +ATOM 10 O O . ASP A 1 6 ? 6.944 16.907 -25.403 1.00 70.90 ? ? ? ? ? ? 8 ASP A O 1 +ATOM 11 C CB . ASP A 1 6 ? 5.104 14.146 -25.703 1.00 67.64 ? ? ? ? ? ? 8 ASP A CB 1 +ATOM 12 C CG . ASP A 1 6 ? 3.570 14.083 -25.751 1.00 64.57 ? ? ? ? ? ? 8 ASP A CG 1 +ATOM 13 O OD1 . ASP A 1 6 ? 2.949 15.085 -26.195 1.00 63.11 ? ? ? ? ? ? 8 ASP A OD1 1 +ATOM 14 O OD2 . ASP A 1 6 ? 2.984 13.032 -25.353 1.00 62.17 ? ? ? ? ? ? 8 ASP A OD2 1 +ATOM 15 N N . PHE A 1 7 ? 4.726 17.246 -25.545 1.00 64.53 ? ? ? ? ? ? 9 PHE A N 1 +ATOM 16 C CA . PHE A 1 7 ? 4.750 18.548 -24.879 1.00 61.94 ? ? ? ? ? ? 9 PHE A CA 1 +ATOM 17 C C . PHE A 1 7 ? 3.673 18.732 -23.796 1.00 57.92 ? ? ? ? ? ? 9 PHE A C 1 +ATOM 18 O O . PHE A 1 7 ? 2.693 17.987 -23.744 1.00 55.70 ? ? ? ? ? ? 9 PHE A O 1 +ATOM 19 C CB . PHE A 1 7 ? 4.618 19.664 -25.915 1.00 63.43 ? ? ? ? ? ? 9 PHE A CB 1 +ATOM 20 C CG . PHE A 1 7 ? 3.282 19.718 -26.567 1.00 62.41 ? ? ? ? ? ? 9 PHE A CG 1 +ATOM 21 C CD1 . PHE A 1 7 ? 2.231 20.382 -25.970 1.00 61.82 ? ? ? ? ? ? 9 PHE A CD1 1 +ATOM 22 C CD2 . PHE A 1 7 ? 3.075 19.105 -27.775 1.00 64.02 ? ? ? ? ? ? 9 PHE A CD2 1 +ATOM 23 C CE1 . PHE A 1 7 ? 0.988 20.428 -26.567 1.00 60.16 ? ? ? ? ? ? 9 PHE A CE1 1 +ATOM 24 C CE2 . PHE A 1 7 ? 1.832 19.145 -28.383 1.00 62.57 ? ? ? ? ? ? 9 PHE A CE2 1 +ATOM 25 C CZ . PHE A 1 7 ? 0.783 19.808 -27.775 1.00 60.25 ? ? ? ? ? ? 9 PHE A CZ 1 +ATOM 26 N N . VAL A 1 8 ? 3.861 19.735 -22.938 1.00 55.04 ? ? ? ? ? ? 10 VAL A N 1 +ATOM 27 C CA . VAL A 1 8 ? 2.861 20.095 -21.949 1.00 50.88 ? ? ? ? ? ? 10 VAL A CA 1 +ATOM 28 C C . VAL A 1 8 ? 2.487 21.551 -22.098 1.00 49.54 ? ? ? ? ? ? 10 VAL A C 1 +ATOM 29 O O . VAL A 1 8 ? 3.323 22.385 -22.446 1.00 50.85 ? ? ? ? ? ? 10 VAL A O 1 +ATOM 30 C CB . VAL A 1 8 ? 3.326 19.851 -20.511 1.00 51.03 ? ? ? ? ? ? 10 VAL A CB 1 +ATOM 31 C CG1 . VAL A 1 8 ? 3.832 18.442 -20.371 1.00 50.13 ? ? ? ? ? ? 10 VAL A CG1 1 +ATOM 32 C CG2 . VAL A 1 8 ? 4.402 20.826 -20.090 1.00 53.19 ? ? ? ? ? ? 10 VAL A CG2 1 +ATOM 33 N N . VAL A 1 9 ? 1.215 21.844 -21.842 1.00 46.06 ? ? ? ? ? ? 11 VAL A N 1 +ATOM 34 C CA . VAL A 1 9 ? 0.687 23.206 -21.880 1.00 44.00 ? ? ? ? ? ? 11 VAL A CA 1 +ATOM 35 C C . VAL A 1 9 ? 0.489 23.603 -20.434 1.00 44.21 ? ? ? ? ? ? 11 VAL A C 1 +ATOM 36 O O . VAL A 1 9 ? -0.170 22.877 -19.678 1.00 42.41 ? ? ? ? ? ? 11 VAL A O 1 +ATOM 37 C CB . VAL A 1 9 ? -0.661 23.252 -22.624 1.00 42.00 ? ? ? ? ? ? 11 VAL A CB 1 +ATOM 38 C CG1 . VAL A 1 9 ? -1.295 24.607 -22.528 1.00 40.79 ? ? ? ? ? ? 11 VAL A CG1 1 +ATOM 39 C CG2 . VAL A 1 9 ? -0.455 22.906 -24.078 1.00 40.13 ? ? ? ? ? ? 11 VAL A CG2 1 +ATOM 40 N N . ILE A 1 10 ? 1.076 24.738 -20.056 1.00 46.10 ? ? ? ? ? ? 12 ILE A N 1 +ATOM 41 C CA . ILE A 1 10 ? 1.003 25.240 -18.696 1.00 47.51 ? ? ? ? ? ? 12 ILE A CA 1 +ATOM 42 C C . ILE A 1 10 ? 0.516 26.657 -18.743 1.00 48.05 ? ? ? ? ? ? 12 ILE A C 1 +ATOM 43 O O . ILE A 1 10 ? 1.137 27.508 -19.380 1.00 49.65 ? ? ? ? ? ? 12 ILE A O 1 +ATOM 44 C CB . ILE A 1 10 ? 2.374 25.247 -18.012 1.00 49.28 ? ? ? ? ? ? 12 ILE A CB 1 +ATOM 45 C CG1 . ILE A 1 10 ? 2.981 23.848 -18.003 1.00 49.95 ? ? ? ? ? ? 12 ILE A CG1 1 +ATOM 46 C CG2 . ILE A 1 10 ? 2.247 25.753 -16.603 1.00 50.91 ? ? ? ? ? ? 12 ILE A CG2 1 +ATOM 47 C CD1 . ILE A 1 10 ? 4.435 23.827 -17.677 1.00 54.16 ? ? ? ? ? ? 12 ILE A CD1 1 +ATOM 48 N N . LYS A 1 11 ? -0.606 26.901 -18.076 1.00 47.39 ? ? ? ? ? ? 13 LYS A N 1 +ATOM 49 C CA . LYS A 1 11 ? -1.139 28.252 -17.917 1.00 48.23 ? ? ? ? ? ? 13 LYS A CA 1 +ATOM 50 C C . LYS A 1 11 ? -0.998 28.660 -16.473 1.00 50.10 ? ? ? ? ? ? 13 LYS A C 1 +ATOM 51 O O . LYS A 1 11 ? -1.441 27.931 -15.579 1.00 49.40 ? ? ? ? ? ? 13 LYS A O 1 +ATOM 52 C CB . LYS A 1 11 ? -2.609 28.311 -18.304 1.00 46.00 ? ? ? ? ? ? 13 LYS A CB 1 +ATOM 53 C CG . LYS A 1 11 ? -3.144 29.706 -18.267 1.00 45.91 ? ? ? ? ? ? 13 LYS A CG 1 +ATOM 54 C CD . LYS A 1 11 ? -4.640 29.741 -18.402 1.00 43.12 ? ? ? ? ? ? 13 LYS A CD 1 +ATOM 55 C CE . LYS A 1 11 ? -5.103 31.182 -18.619 1.00 44.02 ? ? ? ? ? ? 13 LYS A CE 1 +ATOM 56 N NZ . LYS A 1 11 ? -6.563 31.312 -18.363 1.00 43.35 ? ? ? ? ? ? 13 LYS A NZ 1 +ATOM 57 N N . ALA A 1 12 ? -0.379 29.818 -16.242 1.00 53.49 ? ? ? ? ? ? 14 ALA A N 1 +ATOM 58 C CA . ALA A 1 12 ? -0.115 30.296 -14.876 1.00 55.56 ? ? ? ? ? ? 14 ALA A CA 1 +ATOM 59 C C . ALA A 1 12 ? -1.354 30.960 -14.272 1.00 55.44 ? ? ? ? ? ? 14 ALA A C 1 +ATOM 60 O O . ALA A 1 12 ? -1.938 31.848 -14.881 1.00 55.76 ? ? ? ? ? ? 14 ALA A O 1 +ATOM 61 C CB . ALA A 1 12 ? 1.042 31.240 -14.890 1.00 58.43 ? ? ? ? ? ? 14 ALA A CB 1 +ATOM 62 N N . LEU A 1 13 ? -1.767 30.514 -13.093 1.00 55.02 ? ? ? ? ? ? 15 LEU A N 1 +ATOM 63 C CA . LEU A 1 13 ? -2.966 31.063 -12.438 1.00 55.23 ? ? ? ? ? ? 15 LEU A CA 1 +ATOM 64 C C . LEU A 1 13 ? -2.665 32.145 -11.380 1.00 58.70 ? ? ? ? ? ? 15 LEU A C 1 +ATOM 65 O O . LEU A 1 13 ? -3.574 32.758 -10.809 1.00 58.84 ? ? ? ? ? ? 15 LEU A O 1 +ATOM 66 C CB . LEU A 1 13 ? -3.811 29.932 -11.832 1.00 52.50 ? ? ? ? ? ? 15 LEU A CB 1 +ATOM 67 C CG . LEU A 1 13 ? -4.415 28.951 -12.839 1.00 47.91 ? ? ? ? ? ? 15 LEU A CG 1 +ATOM 68 C CD1 . LEU A 1 13 ? -4.953 27.698 -12.151 1.00 44.21 ? ? ? ? ? ? 15 LEU A CD1 1 +ATOM 69 C CD2 . LEU A 1 13 ? -5.494 29.672 -13.668 1.00 46.05 ? ? ? ? ? ? 15 LEU A CD2 1 +ATOM 70 N N . GLU A 1 14 ? -1.379 32.359 -11.120 1.00 62.66 ? ? ? ? ? ? 16 GLU A N 1 +ATOM 71 C CA . GLU A 1 14 ? -0.899 33.425 -10.252 1.00 67.00 ? ? ? ? ? ? 16 GLU A CA 1 +ATOM 72 C C . GLU A 1 14 ? 0.409 33.922 -10.836 1.00 70.32 ? ? ? ? ? ? 16 GLU A C 1 +ATOM 73 O O . GLU A 1 14 ? 0.914 33.339 -11.785 1.00 70.03 ? ? ? ? ? ? 16 GLU A O 1 +ATOM 74 C CB . GLU A 1 14 ? -0.696 32.923 -8.819 1.00 67.19 ? ? ? ? ? ? 16 GLU A CB 1 +ATOM 75 C CG . GLU A 1 14 ? 0.432 31.895 -8.625 1.00 68.58 ? ? ? ? ? ? 16 GLU A CG 1 +ATOM 76 C CD . GLU A 1 14 ? 0.454 31.270 -7.222 1.00 70.39 ? ? ? ? ? ? 16 GLU A CD 1 +ATOM 77 O OE1 . GLU A 1 14 ? -0.457 31.541 -6.412 1.00 71.02 ? ? ? ? ? ? 16 GLU A OE1 1 +ATOM 78 O OE2 . GLU A 1 14 ? 1.387 30.491 -6.926 1.00 71.29 ? ? ? ? ? ? 16 GLU A OE2 1 +ATOM 79 N N . ASP A 1 15 ? 0.955 35.001 -10.285 1.00 74.75 ? ? ? ? ? ? 17 ASP A N 1 +ATOM 80 C CA . ASP A 1 15 ? 2.250 35.491 -10.740 1.00 78.78 ? ? ? ? ? ? 17 ASP A CA 1 +ATOM 81 C C . ASP A 1 15 ? 3.325 34.615 -10.138 1.00 79.87 ? ? ? ? ? ? 17 ASP A C 1 +ATOM 82 O O . ASP A 1 15 ? 3.099 33.950 -9.124 1.00 79.33 ? ? ? ? ? ? 17 ASP A O 1 +ATOM 83 C CB . ASP A 1 15 ? 2.475 36.953 -10.336 1.00 81.65 ? ? ? ? ? ? 17 ASP A CB 1 +ATOM 84 C CG . ASP A 1 15 ? 1.621 37.937 -11.140 1.00 83.16 ? ? ? ? ? ? 17 ASP A CG 1 +ATOM 85 O OD1 . ASP A 1 15 ? 1.344 37.691 -12.326 1.00 82.40 ? ? ? ? ? ? 17 ASP A OD1 1 +ATOM 86 O OD2 . ASP A 1 15 ? 1.231 38.982 -10.589 1.00 86.46 ? ? ? ? ? ? 17 ASP A OD2 1 +ATOM 87 N N . GLY A 1 16 ? 4.489 34.606 -10.778 1.00 81.58 ? ? ? ? ? ? 18 GLY A N 1 +ATOM 88 C CA . GLY A 1 16 ? 5.660 33.903 -10.248 1.00 82.57 ? ? ? ? ? ? 18 GLY A CA 1 +ATOM 89 C C . GLY A 1 16 ? 5.555 32.392 -10.154 1.00 80.35 ? ? ? ? ? ? 18 GLY A C 1 +ATOM 90 O O . GLY A 1 16 ? 6.059 31.793 -9.215 1.00 81.29 ? ? ? ? ? ? 18 GLY A O 1 +ATOM 91 N N . VAL A 1 17 ? 4.892 31.781 -11.128 1.00 77.56 ? ? ? ? ? ? 19 VAL A N 1 +ATOM 92 C CA . VAL A 1 17 ? 4.885 30.336 -11.259 1.00 74.50 ? ? ? ? ? ? 19 VAL A CA 1 +ATOM 93 C C . VAL A 1 17 ? 6.239 29.942 -11.826 1.00 76.68 ? ? ? ? ? ? 19 VAL A C 1 +ATOM 94 O O . VAL A 1 17 ? 6.799 30.655 -12.655 1.00 78.24 ? ? ? ? ? ? 19 VAL A O 1 +ATOM 95 C CB . VAL A 1 17 ? 3.755 29.861 -12.187 1.00 71.56 ? ? ? ? ? ? 19 VAL A CB 1 +ATOM 96 C CG1 . VAL A 1 17 ? 3.820 28.364 -12.384 1.00 67.63 ? ? ? ? ? ? 19 VAL A CG1 1 +ATOM 97 C CG2 . VAL A 1 17 ? 2.409 30.247 -11.611 1.00 67.92 ? ? ? ? ? ? 19 VAL A CG2 1 +ATOM 98 N N . ASN A 1 18 ? 6.764 28.812 -11.381 1.00 77.33 ? ? ? ? ? ? 20 ASN A N 1 +ATOM 99 C CA . ASN A 1 18 ? 8.086 28.396 -11.775 1.00 79.46 ? ? ? ? ? ? 20 ASN A CA 1 +ATOM 100 C C . ASN A 1 18 ? 8.067 27.069 -12.528 1.00 77.29 ? ? ? ? ? ? 20 ASN A C 1 +ATOM 101 O O . ASN A 1 18 ? 7.635 26.058 -11.989 1.00 75.60 ? ? ? ? ? ? 20 ASN A O 1 +ATOM 102 C CB . ASN A 1 18 ? 8.941 28.291 -10.526 1.00 82.30 ? ? ? ? ? ? 20 ASN A CB 1 +ATOM 103 C CG . ASN A 1 18 ? 10.360 28.739 -10.753 1.00 89.13 ? ? ? ? ? ? 20 ASN A CG 1 +ATOM 104 O OD1 . ASN A 1 18 ? 10.690 29.305 -11.791 1.00 92.93 ? ? ? ? ? ? 20 ASN A OD1 1 +ATOM 105 N ND2 . ASN A 1 18 ? 11.217 28.488 -9.773 1.00 94.39 ? ? ? ? ? ? 20 ASN A ND2 1 +ATOM 106 N N . VAL A 1 19 ? 8.521 27.077 -13.779 1.00 76.88 ? ? ? ? ? ? 21 VAL A N 1 +ATOM 107 C CA . VAL A 1 19 ? 8.542 25.871 -14.600 1.00 75.28 ? ? ? ? ? ? 21 VAL A CA 1 +ATOM 108 C C . VAL A 1 19 ? 9.970 25.398 -14.720 1.00 78.52 ? ? ? ? ? ? 21 VAL A C 1 +ATOM 109 O O . VAL A 1 19 ? 10.747 25.948 -15.489 1.00 80.53 ? ? ? ? ? ? 21 VAL A O 1 +ATOM 110 C CB . VAL A 1 19 ? 7.946 26.104 -16.005 1.00 73.54 ? ? ? ? ? ? 21 VAL A CB 1 +ATOM 111 C CG1 . VAL A 1 19 ? 7.966 24.838 -16.807 1.00 70.33 ? ? ? ? ? ? 21 VAL A CG1 1 +ATOM 112 C CG2 . VAL A 1 19 ? 6.528 26.602 -15.913 1.00 69.44 ? ? ? ? ? ? 21 VAL A CG2 1 +ATOM 113 N N . ILE A 1 20 ? 10.305 24.368 -13.960 1.00 80.07 ? ? ? ? ? ? 22 ILE A N 1 +ATOM 114 C CA . ILE A 1 20 ? 11.683 23.949 -13.817 1.00 83.77 ? ? ? ? ? ? 22 ILE A CA 1 +ATOM 115 C C . ILE A 1 20 ? 12.004 22.729 -14.664 1.00 83.74 ? ? ? ? ? ? 22 ILE A C 1 +ATOM 116 O O . ILE A 1 20 ? 11.349 21.705 -14.536 1.00 81.42 ? ? ? ? ? ? 22 ILE A O 1 +ATOM 117 C CB . ILE A 1 20 ? 12.014 23.661 -12.348 1.00 84.59 ? ? ? ? ? ? 22 ILE A CB 1 +ATOM 118 C CG1 . ILE A 1 20 ? 11.522 24.802 -11.467 1.00 85.96 ? ? ? ? ? ? 22 ILE A CG1 1 +ATOM 119 C CG2 . ILE A 1 20 ? 13.511 23.484 -12.166 1.00 89.81 ? ? ? ? ? ? 22 ILE A CG2 1 +ATOM 120 C CD1 . ILE A 1 20 ? 11.484 24.464 -9.998 1.00 87.43 ? ? ? ? ? ? 22 ILE A CD1 1 +ATOM 121 N N . GLY A 1 21 ? 13.019 22.862 -15.520 1.00 86.57 ? ? ? ? ? ? 23 GLY A N 1 +ATOM 122 C CA . GLY A 1 21 ? 13.522 21.775 -16.358 1.00 88.60 ? ? ? ? ? ? 23 GLY A CA 1 +ATOM 123 C C . GLY A 1 21 ? 14.674 21.070 -15.675 1.00 91.29 ? ? ? ? ? ? 23 GLY A C 1 +ATOM 124 O O . GLY A 1 21 ? 15.573 21.716 -15.154 1.00 94.14 ? ? ? ? ? ? 23 GLY A O 1 +ATOM 125 N N . LEU A 1 22 ? 14.642 19.743 -15.672 1.00 91.36 ? ? ? ? ? ? 24 LEU A N 1 +ATOM 126 C CA . LEU A 1 22 ? 15.603 18.932 -14.926 1.00 92.96 ? ? ? ? ? ? 24 LEU A CA 1 +ATOM 127 C C . LEU A 1 22 ? 16.447 18.089 -15.876 1.00 94.68 ? ? ? ? ? ? 24 LEU A C 1 +ATOM 128 O O . LEU A 1 22 ? 15.939 17.601 -16.885 1.00 94.04 ? ? ? ? ? ? 24 LEU A O 1 +ATOM 129 C CB . LEU A 1 22 ? 14.860 18.047 -13.924 1.00 91.08 ? ? ? ? ? ? 24 LEU A CB 1 +ATOM 130 C CG . LEU A 1 22 ? 14.551 18.518 -12.493 1.00 90.38 ? ? ? ? ? ? 24 LEU A CG 1 +ATOM 131 C CD1 . LEU A 1 22 ? 14.342 20.009 -12.384 1.00 91.01 ? ? ? ? ? ? 24 LEU A CD1 1 +ATOM 132 C CD2 . LEU A 1 22 ? 13.342 17.791 -11.921 1.00 85.41 ? ? ? ? ? ? 24 LEU A CD2 1 +ATOM 133 N N . THR A 1 23 ? 17.733 17.926 -15.565 1.00 96.47 ? ? ? ? ? ? 25 THR A N 1 +ATOM 134 C CA . THR A 1 23 ? 18.688 17.343 -16.531 1.00 98.30 ? ? ? ? ? ? 25 THR A CA 1 +ATOM 135 C C . THR A 1 23 ? 19.007 15.862 -16.352 1.00 98.49 ? ? ? ? ? ? 25 THR A C 1 +ATOM 136 O O . THR A 1 23 ? 18.826 15.304 -15.266 1.00 98.19 ? ? ? ? ? ? 25 THR A O 1 +ATOM 137 C CB . THR A 1 23 ? 20.028 18.102 -16.553 1.00 100.21 ? ? ? ? ? ? 25 THR A CB 1 +ATOM 138 O OG1 . THR A 1 23 ? 20.490 18.282 -15.208 1.00 101.37 ? ? ? ? ? ? 25 THR A OG1 1 +ATOM 139 C CG2 . THR A 1 23 ? 19.883 19.457 -17.252 1.00 100.72 ? ? ? ? ? ? 25 THR A CG2 1 +ATOM 140 N N . ARG A 1 24 ? 19.501 15.246 -17.430 1.00 99.49 ? ? ? ? ? ? 26 ARG A N 1 +ATOM 141 C CA . ARG A 1 24 ? 19.857 13.819 -17.452 1.00 99.94 ? ? ? ? ? ? 26 ARG A CA 1 +ATOM 142 C C . ARG A 1 24 ? 21.154 13.541 -16.693 1.00 101.44 ? ? ? ? ? ? 26 ARG A C 1 +ATOM 143 O O . ARG A 1 24 ? 22.240 13.904 -17.147 1.00 103.26 ? ? ? ? ? ? 26 ARG A O 1 +ATOM 144 C CB . ARG A 1 24 ? 19.955 13.281 -18.893 1.00 100.14 ? ? ? ? ? ? 26 ARG A CB 1 +ATOM 145 C CG . ARG A 1 24 ? 18.620 13.217 -19.642 1.00 99.36 ? ? ? ? ? ? 26 ARG A CG 1 +ATOM 146 C CD . ARG A 1 24 ? 18.634 12.164 -20.759 1.00 100.98 ? ? ? ? ? ? 26 ARG A CD 1 +ATOM 147 N NE . ARG A 1 24 ? 17.552 12.352 -21.740 1.00 100.55 ? ? ? ? ? ? 26 ARG A NE 1 +ATOM 148 C CZ . ARG A 1 24 ? 17.231 11.494 -22.716 1.00 99.98 ? ? ? ? ? ? 26 ARG A CZ 1 +ATOM 149 N NH1 . ARG A 1 24 ? 17.891 10.344 -22.876 1.00 99.60 ? ? ? ? ? ? 26 ARG A NH1 1 +ATOM 150 N NH2 . ARG A 1 24 ? 16.229 11.791 -23.537 1.00 99.33 ? ? ? ? ? ? 26 ARG A NH2 1 +ATOM 151 N N . THR A 1 28 ? 22.527 16.428 -12.721 1.00 120.13 ? ? ? ? ? ? 30 THR A N 1 +ATOM 152 C CA . THR A 1 28 ? 21.235 15.835 -13.090 1.00 118.47 ? ? ? ? ? ? 30 THR A CA 1 +ATOM 153 C C . THR A 1 28 ? 20.021 16.467 -12.351 1.00 117.17 ? ? ? ? ? ? 30 THR A C 1 +ATOM 154 O O . THR A 1 28 ? 18.867 16.073 -12.593 1.00 115.70 ? ? ? ? ? ? 30 THR A O 1 +ATOM 155 C CB . THR A 1 28 ? 21.259 14.241 -13.007 1.00 118.06 ? ? ? ? ? ? 30 THR A CB 1 +ATOM 156 O OG1 . THR A 1 28 ? 19.946 13.697 -13.234 1.00 116.11 ? ? ? ? ? ? 30 THR A OG1 1 +ATOM 157 C CG2 . THR A 1 28 ? 21.822 13.727 -11.660 1.00 118.37 ? ? ? ? ? ? 30 THR A CG2 1 +ATOM 158 N N . ARG A 1 29 ? 20.289 17.464 -11.492 1.00 117.71 ? ? ? ? ? ? 31 ARG A N 1 +ATOM 159 C CA . ARG A 1 29 ? 19.261 18.091 -10.604 1.00 116.35 ? ? ? ? ? ? 31 ARG A CA 1 +ATOM 160 C C . ARG A 1 29 ? 18.477 19.294 -11.195 1.00 115.56 ? ? ? ? ? ? 31 ARG A C 1 +ATOM 161 O O . ARG A 1 29 ? 18.271 19.360 -12.420 1.00 115.47 ? ? ? ? ? ? 31 ARG A O 1 +ATOM 162 C CB . ARG A 1 29 ? 19.840 18.428 -9.204 1.00 117.16 ? ? ? ? ? ? 31 ARG A CB 1 +ATOM 163 C CG . ARG A 1 29 ? 21.320 18.904 -9.113 1.00 119.11 ? ? ? ? ? ? 31 ARG A CG 1 +ATOM 164 C CD . ARG A 1 29 ? 21.638 20.210 -9.857 1.00 119.60 ? ? ? ? ? ? 31 ARG A CD 1 +ATOM 165 N NE . ARG A 1 29 ? 22.419 19.952 -11.068 1.00 120.44 ? ? ? ? ? ? 31 ARG A NE 1 +ATOM 166 C CZ . ARG A 1 29 ? 21.980 20.123 -12.315 1.00 119.80 ? ? ? ? ? ? 31 ARG A CZ 1 +ATOM 167 N NH1 . ARG A 1 29 ? 22.780 19.853 -13.337 1.00 121.30 ? ? ? ? ? ? 31 ARG A NH1 1 +ATOM 168 N NH2 . ARG A 1 29 ? 20.756 20.576 -12.552 1.00 117.87 ? ? ? ? ? ? 31 ARG A NH2 1 +ATOM 169 N N . PHE A 1 30 ? 18.052 20.228 -10.323 1.00 114.83 ? ? ? ? ? ? 32 PHE A N 1 +ATOM 170 C CA . PHE A 1 30 ? 17.248 21.413 -10.728 1.00 113.80 ? ? ? ? ? ? 32 PHE A CA 1 +ATOM 171 C C . PHE A 1 30 ? 18.047 22.475 -11.541 1.00 114.52 ? ? ? ? ? ? 32 PHE A C 1 +ATOM 172 O O . PHE A 1 30 ? 18.937 23.145 -11.001 1.00 115.82 ? ? ? ? ? ? 32 PHE A O 1 +ATOM 173 C CB . PHE A 1 30 ? 16.487 22.093 -9.541 1.00 113.41 ? ? ? ? ? ? 32 PHE A CB 1 +ATOM 174 C CG . PHE A 1 30 ? 16.144 21.179 -8.346 1.00 112.64 ? ? ? ? ? ? 32 PHE A CG 1 +ATOM 175 C CD1 . PHE A 1 30 ? 15.540 21.740 -7.207 1.00 112.23 ? ? ? ? ? ? 32 PHE A CD1 1 +ATOM 176 C CD2 . PHE A 1 30 ? 16.423 19.805 -8.338 1.00 111.84 ? ? ? ? ? ? 32 PHE A CD2 1 +ATOM 177 C CE1 . PHE A 1 30 ? 15.212 20.957 -6.091 1.00 111.54 ? ? ? ? ? ? 32 PHE A CE1 1 +ATOM 178 C CE2 . PHE A 1 30 ? 16.110 19.015 -7.218 1.00 111.19 ? ? ? ? ? ? 32 PHE A CE2 1 +ATOM 179 C CZ . PHE A 1 30 ? 15.497 19.590 -6.097 1.00 111.08 ? ? ? ? ? ? 32 PHE A CZ 1 +ATOM 180 N N . HIS A 1 31 ? 17.677 22.645 -12.817 1.00 113.18 ? ? ? ? ? ? 33 HIS A N 1 +ATOM 181 C CA . HIS A 1 31 ? 18.505 23.317 -13.836 1.00 113.51 ? ? ? ? ? ? 33 HIS A CA 1 +ATOM 182 C C . HIS A 1 31 ? 17.843 24.573 -14.459 1.00 112.40 ? ? ? ? ? ? 33 HIS A C 1 +ATOM 183 O O . HIS A 1 31 ? 17.840 25.650 -13.849 1.00 112.91 ? ? ? ? ? ? 33 HIS A O 1 +ATOM 184 C CB . HIS A 1 31 ? 18.897 22.274 -14.908 1.00 113.74 ? ? ? ? ? ? 33 HIS A CB 1 +ATOM 185 C CG . HIS A 1 31 ? 19.881 22.761 -15.933 1.00 116.22 ? ? ? ? ? ? 33 HIS A CG 1 +ATOM 186 N ND1 . HIS A 1 31 ? 21.201 23.036 -15.635 1.00 118.98 ? ? ? ? ? ? 33 HIS A ND1 1 +ATOM 187 C CD2 . HIS A 1 31 ? 19.743 22.976 -17.264 1.00 116.72 ? ? ? ? ? ? 33 HIS A CD2 1 +ATOM 188 C CE1 . HIS A 1 31 ? 21.826 23.425 -16.734 1.00 120.25 ? ? ? ? ? ? 33 HIS A CE1 1 +ATOM 189 N NE2 . HIS A 1 31 ? 20.964 23.395 -17.736 1.00 119.10 ? ? ? ? ? ? 33 HIS A NE2 1 +ATOM 190 N N . HIS A 1 32 ? 17.298 24.431 -15.670 1.00 110.63 ? ? ? ? ? ? 34 HIS A N 1 +ATOM 191 C CA . HIS A 1 32 ? 16.630 25.529 -16.377 1.00 108.57 ? ? ? ? ? ? 34 HIS A CA 1 +ATOM 192 C C . HIS A 1 32 ? 15.315 25.908 -15.701 1.00 105.41 ? ? ? ? ? ? 34 HIS A C 1 +ATOM 193 O O . HIS A 1 32 ? 14.336 25.165 -15.760 1.00 102.47 ? ? ? ? ? ? 34 HIS A O 1 +ATOM 194 C CB . HIS A 1 32 ? 16.384 25.161 -17.858 1.00 108.29 ? ? ? ? ? ? 34 HIS A CB 1 +ATOM 195 C CG . HIS A 1 32 ? 15.859 26.296 -18.697 1.00 108.03 ? ? ? ? ? ? 34 HIS A CG 1 +ATOM 196 N ND1 . HIS A 1 32 ? 16.492 27.522 -18.778 1.00 111.34 ? ? ? ? ? ? 34 HIS A ND1 1 +ATOM 197 C CD2 . HIS A 1 32 ? 14.778 26.380 -19.511 1.00 103.90 ? ? ? ? ? ? 34 HIS A CD2 1 +ATOM 198 C CE1 . HIS A 1 32 ? 15.812 28.317 -19.586 1.00 109.77 ? ? ? ? ? ? 34 HIS A CE1 1 +ATOM 199 N NE2 . HIS A 1 32 ? 14.772 27.647 -20.051 1.00 105.66 ? ? ? ? ? ? 34 HIS A NE2 1 +ATOM 200 N N . SER A 1 33 ? 15.303 27.064 -15.056 1.00 104.75 ? ? ? ? ? ? 35 SER A N 1 +ATOM 201 C CA . SER A 1 33 ? 14.079 27.599 -14.485 1.00 101.92 ? ? ? ? ? ? 35 SER A CA 1 +ATOM 202 C C . SER A 1 33 ? 13.450 28.601 -15.456 1.00 99.94 ? ? ? ? ? ? 35 SER A C 1 +ATOM 203 O O . SER A 1 33 ? 14.146 29.196 -16.272 1.00 101.93 ? ? ? ? ? ? 35 SER A O 1 +ATOM 204 C CB . SER A 1 33 ? 14.372 28.236 -13.124 1.00 103.64 ? ? ? ? ? ? 35 SER A CB 1 +ATOM 205 O OG . SER A 1 33 ? 13.401 29.202 -12.771 1.00 103.74 ? ? ? ? ? ? 35 SER A OG 1 +ATOM 206 N N . GLU A 1 34 ? 12.136 28.778 -15.372 1.00 95.30 ? ? ? ? ? ? 36 GLU A N 1 +ATOM 207 C CA . GLU A 1 34 ? 11.425 29.699 -16.249 1.00 92.35 ? ? ? ? ? ? 36 GLU A CA 1 +ATOM 208 C C . GLU A 1 34 ? 10.221 30.272 -15.520 1.00 90.03 ? ? ? ? ? ? 36 GLU A C 1 +ATOM 209 O O . GLU A 1 34 ? 9.296 29.543 -15.201 1.00 87.29 ? ? ? ? ? ? 36 GLU A O 1 +ATOM 210 C CB . GLU A 1 34 ? 10.977 28.964 -17.511 1.00 90.67 ? ? ? ? ? ? 36 GLU A CB 1 +ATOM 211 C CG . GLU A 1 34 ? 10.555 29.867 -18.650 1.00 90.72 ? ? ? ? ? ? 36 GLU A CG 1 +ATOM 212 C CD . GLU A 1 34 ? 11.736 30.565 -19.310 1.00 96.24 ? ? ? ? ? ? 36 GLU A CD 1 +ATOM 213 O OE1 . GLU A 1 34 ? 12.815 29.937 -19.462 1.00 99.38 ? ? ? ? ? ? 36 GLU A OE1 1 +ATOM 214 O OE2 . GLU A 1 34 ? 11.578 31.748 -19.685 1.00 98.37 ? ? ? ? ? ? 36 GLU A OE2 1 +ATOM 215 N N . LYS A 1 35 ? 10.235 31.569 -15.239 1.00 90.36 ? ? ? ? ? ? 37 LYS A N 1 +ATOM 216 C CA . LYS A 1 35 ? 9.139 32.178 -14.506 1.00 88.38 ? ? ? ? ? ? 37 LYS A CA 1 +ATOM 217 C C . LYS A 1 35 ? 7.977 32.484 -15.433 1.00 85.67 ? ? ? ? ? ? 37 LYS A C 1 +ATOM 218 O O . LYS A 1 35 ? 8.172 32.833 -16.592 1.00 86.06 ? ? ? ? ? ? 37 LYS A O 1 +ATOM 219 C CB . LYS A 1 35 ? 9.601 33.433 -13.768 1.00 91.44 ? ? ? ? ? ? 37 LYS A CB 1 +ATOM 220 N N . LEU A 1 36 ? 6.766 32.325 -14.915 1.00 81.92 ? ? ? ? ? ? 38 LEU A N 1 +ATOM 221 C CA . LEU A 1 36 ? 5.539 32.641 -15.640 1.00 78.89 ? ? ? ? ? ? 38 LEU A CA 1 +ATOM 222 C C . LEU A 1 36 ? 4.640 33.528 -14.797 1.00 78.12 ? ? ? ? ? ? 38 LEU A C 1 +ATOM 223 O O . LEU A 1 36 ? 4.498 33.299 -13.601 1.00 77.83 ? ? ? ? ? ? 38 LEU A O 1 +ATOM 224 C CB . LEU A 1 36 ? 4.770 31.368 -15.979 1.00 77.62 ? ? ? ? ? ? 38 LEU A CB 1 +ATOM 225 C CG . LEU A 1 36 ? 4.861 30.675 -17.336 1.00 76.31 ? ? ? ? ? ? 38 LEU A CG 1 +ATOM 226 C CD1 . LEU A 1 36 ? 3.481 30.149 -17.653 1.00 74.28 ? ? ? ? ? ? 38 LEU A CD1 1 +ATOM 227 C CD2 . LEU A 1 36 ? 5.328 31.599 -18.436 1.00 76.23 ? ? ? ? ? ? 38 LEU A CD2 1 +ATOM 228 N N . ASP A 1 37 ? 4.015 34.523 -15.417 1.00 77.70 ? ? ? ? ? ? 39 ASP A N 1 +ATOM 229 C CA . ASP A 1 37 ? 3.127 35.429 -14.691 1.00 77.42 ? ? ? ? ? ? 39 ASP A CA 1 +ATOM 230 C C . ASP A 1 37 ? 1.666 35.169 -15.004 1.00 73.58 ? ? ? ? ? ? 39 ASP A C 1 +ATOM 231 O O . ASP A 1 37 ? 1.352 34.676 -16.075 1.00 72.04 ? ? ? ? ? ? 39 ASP A O 1 +ATOM 232 C CB . ASP A 1 37 ? 3.473 36.886 -14.995 1.00 80.86 ? ? ? ? ? ? 39 ASP A CB 1 +ATOM 233 C CG . ASP A 1 37 ? 4.632 37.408 -14.159 1.00 86.94 ? ? ? ? ? ? 39 ASP A CG 1 +ATOM 234 O OD1 . ASP A 1 37 ? 4.986 36.781 -13.125 1.00 88.70 ? ? ? ? ? ? 39 ASP A OD1 1 +ATOM 235 O OD2 . ASP A 1 37 ? 5.178 38.463 -14.548 1.00 92.58 ? ? ? ? ? ? 39 ASP A OD2 1 +ATOM 236 N N . LYS A 1 38 ? 0.788 35.520 -14.065 1.00 71.09 ? ? ? ? ? ? 40 LYS A N 1 +ATOM 237 C CA . LYS A 1 38 ? -0.646 35.219 -14.127 1.00 67.44 ? ? ? ? ? ? 40 LYS A CA 1 +ATOM 238 C C . LYS A 1 38 ? -1.246 35.395 -15.514 1.00 65.75 ? ? ? ? ? ? 40 LYS A C 1 +ATOM 239 O O . LYS A 1 38 ? -1.274 36.506 -16.038 1.00 66.82 ? ? ? ? ? ? 40 LYS A O 1 +ATOM 240 C CB . LYS A 1 38 ? -1.408 36.092 -13.130 1.00 67.43 ? ? ? ? ? ? 40 LYS A CB 1 +ATOM 241 C CG . LYS A 1 38 ? -2.847 35.692 -12.912 1.00 65.33 ? ? ? ? ? ? 40 LYS A CG 1 +ATOM 242 C CD . LYS A 1 38 ? -3.496 36.530 -11.819 1.00 65.17 ? ? ? ? ? ? 40 LYS A CD 1 +ATOM 243 C CE . LYS A 1 38 ? -4.727 35.828 -11.238 1.00 64.58 ? ? ? ? ? ? 40 LYS A CE 1 +ATOM 244 N NZ . LYS A 1 38 ? -5.911 36.738 -11.093 1.00 64.29 ? ? ? ? ? ? 40 LYS A NZ 1 +ATOM 245 N N . GLY A 1 39 ? -1.710 34.288 -16.097 1.00 62.75 ? ? ? ? ? ? 41 GLY A N 1 +ATOM 246 C CA . GLY A 1 39 ? -2.358 34.280 -17.410 1.00 60.49 ? ? ? ? ? ? 41 GLY A CA 1 +ATOM 247 C C . GLY A 1 39 ? -1.471 33.947 -18.599 1.00 60.30 ? ? ? ? ? ? 41 GLY A C 1 +ATOM 248 O O . GLY A 1 39 ? -1.957 33.805 -19.718 1.00 58.95 ? ? ? ? ? ? 41 GLY A O 1 +ATOM 249 N N . GLU A 1 40 ? -0.167 33.843 -18.366 1.00 61.59 ? ? ? ? ? ? 42 GLU A N 1 +ATOM 250 C CA . GLU A 1 40 ? 0.777 33.499 -19.424 1.00 62.43 ? ? ? ? ? ? 42 GLU A CA 1 +ATOM 251 C C . GLU A 1 40 ? 0.720 32.015 -19.667 1.00 59.62 ? ? ? ? ? ? 42 GLU A C 1 +ATOM 252 O O . GLU A 1 40 ? 0.425 31.239 -18.761 1.00 58.37 ? ? ? ? ? ? 42 GLU A O 1 +ATOM 253 C CB . GLU A 1 40 ? 2.200 33.917 -19.056 1.00 65.52 ? ? ? ? ? ? 42 GLU A CB 1 +ATOM 254 C CG . GLU A 1 40 ? 2.523 35.352 -19.404 1.00 71.75 ? ? ? ? ? ? 42 GLU A CG 1 +ATOM 255 C CD . GLU A 1 40 ? 3.754 35.879 -18.701 1.00 79.02 ? ? ? ? ? ? 42 GLU A CD 1 +ATOM 256 O OE1 . GLU A 1 40 ? 4.375 35.124 -17.926 1.00 79.96 ? ? ? ? ? ? 42 GLU A OE1 1 +ATOM 257 O OE2 . GLU A 1 40 ? 4.097 37.059 -18.923 1.00 83.29 ? ? ? ? ? ? 42 GLU A OE2 1 +ATOM 258 N N . VAL A 1 41 ? 1.004 31.619 -20.895 1.00 58.12 ? ? ? ? ? ? 43 VAL A N 1 +ATOM 259 C CA . VAL A 1 41 ? 0.931 30.221 -21.282 1.00 55.42 ? ? ? ? ? ? 43 VAL A CA 1 +ATOM 260 C C . VAL A 1 41 ? 2.254 29.747 -21.855 1.00 57.22 ? ? ? ? ? ? 43 VAL A C 1 +ATOM 261 O O . VAL A 1 41 ? 2.823 30.381 -22.755 1.00 58.88 ? ? ? ? ? ? 43 VAL A O 1 +ATOM 262 C CB . VAL A 1 41 ? -0.180 29.994 -22.309 1.00 53.28 ? ? ? ? ? ? 43 VAL A CB 1 +ATOM 263 C CG1 . VAL A 1 41 ? -0.060 28.645 -22.920 1.00 50.49 ? ? ? ? ? ? 43 VAL A CG1 1 +ATOM 264 C CG2 . VAL A 1 41 ? -1.523 30.132 -21.664 1.00 49.78 ? ? ? ? ? ? 43 VAL A CG2 1 +ATOM 265 N N . LEU A 1 42 ? 2.738 28.629 -21.323 1.00 57.21 ? ? ? ? ? ? 44 LEU A N 1 +ATOM 266 C CA . LEU A 1 42 ? 3.960 28.037 -21.813 1.00 58.54 ? ? ? ? ? ? 44 LEU A CA 1 +ATOM 267 C C . LEU A 1 42 ? 3.633 26.718 -22.458 1.00 56.54 ? ? ? ? ? ? 44 LEU A C 1 +ATOM 268 O O . LEU A 1 42 ? 2.882 25.928 -21.899 1.00 54.68 ? ? ? ? ? ? 44 LEU A O 1 +ATOM 269 C CB . LEU A 1 42 ? 4.954 27.852 -20.680 1.00 60.35 ? ? ? ? ? ? 44 LEU A CB 1 +ATOM 270 C CG . LEU A 1 42 ? 6.378 27.476 -21.074 1.00 64.66 ? ? ? ? ? ? 44 LEU A CG 1 +ATOM 271 C CD1 . LEU A 1 42 ? 7.071 28.595 -21.816 1.00 69.92 ? ? ? ? ? ? 44 LEU A CD1 1 +ATOM 272 C CD2 . LEU A 1 42 ? 7.171 27.112 -19.839 1.00 67.81 ? ? ? ? ? ? 44 LEU A CD2 1 +ATOM 273 N N . ILE A 1 43 ? 4.162 26.504 -23.657 1.00 56.61 ? ? ? ? ? ? 45 ILE A N 1 +ATOM 274 C CA . ILE A 1 43 ? 4.086 25.207 -24.298 1.00 55.49 ? ? ? ? ? ? 45 ILE A CA 1 +ATOM 275 C C . ILE A 1 43 ? 5.487 24.630 -24.267 1.00 57.96 ? ? ? ? ? ? 45 ILE A C 1 +ATOM 276 O O . ILE A 1 43 ? 6.345 25.038 -25.046 1.00 60.01 ? ? ? ? ? ? 45 ILE A O 1 +ATOM 277 C CB . ILE A 1 43 ? 3.621 25.276 -25.757 1.00 54.45 ? ? ? ? ? ? 45 ILE A CB 1 +ATOM 278 C CG1 . ILE A 1 43 ? 2.749 26.525 -26.016 1.00 53.11 ? ? ? ? ? ? 45 ILE A CG1 1 +ATOM 279 C CG2 . ILE A 1 43 ? 2.966 23.955 -26.167 1.00 50.96 ? ? ? ? ? ? 45 ILE A CG2 1 +ATOM 280 C CD1 . ILE A 1 43 ? 1.330 26.489 -25.511 1.00 48.47 ? ? ? ? ? ? 45 ILE A CD1 1 +ATOM 281 N N . ALA A 1 44 ? 5.708 23.687 -23.351 1.00 58.61 ? ? ? ? ? ? 46 ALA A N 1 +ATOM 282 C CA . ALA A 1 44 ? 7.019 23.104 -23.115 1.00 60.53 ? ? ? ? ? ? 46 ALA A CA 1 +ATOM 283 C C . ALA A 1 44 ? 7.098 21.728 -23.724 1.00 60.54 ? ? ? ? ? ? 46 ALA A C 1 +ATOM 284 O O . ALA A 1 44 ? 6.238 20.893 -23.489 1.00 58.05 ? ? ? ? ? ? 46 ALA A O 1 +ATOM 285 C CB . ALA A 1 44 ? 7.298 23.026 -21.643 1.00 61.04 ? ? ? ? ? ? 46 ALA A CB 1 +ATOM 286 N N . GLN A 1 45 ? 8.142 21.522 -24.518 1.00 63.39 ? ? ? ? ? ? 47 GLN A N 1 +ATOM 287 C CA . GLN A 1 45 ? 8.433 20.236 -25.131 1.00 64.77 ? ? ? ? ? ? 47 GLN A CA 1 +ATOM 288 C C . GLN A 1 45 ? 9.599 19.592 -24.406 1.00 67.08 ? ? ? ? ? ? 47 GLN A C 1 +ATOM 289 O O . GLN A 1 45 ? 10.492 20.287 -23.920 1.00 69.41 ? ? ? ? ? ? 47 GLN A O 1 +ATOM 290 C CB . GLN A 1 45 ? 8.791 20.423 -26.602 1.00 65.44 ? ? ? ? ? ? 47 GLN A CB 1 +ATOM 291 C CG . GLN A 1 45 ? 8.796 19.131 -27.399 1.00 65.31 ? ? ? ? ? ? 47 GLN A CG 1 +ATOM 292 C CD . GLN A 1 45 ? 9.318 19.305 -28.829 1.00 68.03 ? ? ? ? ? ? 47 GLN A CD 1 +ATOM 293 O OE1 . GLN A 1 45 ? 10.214 20.129 -29.090 1.00 70.64 ? ? ? ? ? ? 47 GLN A OE1 1 +ATOM 294 N NE2 . GLN A 1 45 ? 8.757 18.518 -29.767 1.00 65.95 ? ? ? ? ? ? 47 GLN A NE2 1 +ATOM 295 N N . PHE A 1 46 ? 9.590 18.266 -24.339 1.00 67.71 ? ? ? ? ? ? 48 PHE A N 1 +ATOM 296 C CA . PHE A 1 46 ? 10.706 17.526 -23.777 1.00 70.43 ? ? ? ? ? ? 48 PHE A CA 1 +ATOM 297 C C . PHE A 1 46 ? 11.857 17.437 -24.766 1.00 74.96 ? ? ? ? ? ? 48 PHE A C 1 +ATOM 298 O O . PHE A 1 46 ? 11.675 16.991 -25.907 1.00 74.94 ? ? ? ? ? ? 48 PHE A O 1 +ATOM 299 C CB . PHE A 1 46 ? 10.269 16.127 -23.384 1.00 67.85 ? ? ? ? ? ? 48 PHE A CB 1 +ATOM 300 C CG . PHE A 1 46 ? 9.527 16.081 -22.099 1.00 64.51 ? ? ? ? ? ? 48 PHE A CG 1 +ATOM 301 C CD1 . PHE A 1 46 ? 10.218 16.130 -20.894 1.00 65.87 ? ? ? ? ? ? 48 PHE A CD1 1 +ATOM 302 C CD2 . PHE A 1 46 ? 8.130 15.992 -22.085 1.00 59.45 ? ? ? ? ? ? 48 PHE A CD2 1 +ATOM 303 C CE1 . PHE A 1 46 ? 9.533 16.094 -19.687 1.00 63.95 ? ? ? ? ? ? 48 PHE A CE1 1 +ATOM 304 C CE2 . PHE A 1 46 ? 7.427 15.953 -20.885 1.00 57.67 ? ? ? ? ? ? 48 PHE A CE2 1 +ATOM 305 C CZ . PHE A 1 46 ? 8.130 16.002 -19.680 1.00 60.02 ? ? ? ? ? ? 48 PHE A CZ 1 +ATOM 306 N N . THR A 1 47 ? 13.038 17.869 -24.334 1.00 80.48 ? ? ? ? ? ? 49 THR A N 1 +ATOM 307 C CA . THR A 1 47 ? 14.238 17.712 -25.140 1.00 86.44 ? ? ? ? ? ? 49 THR A CA 1 +ATOM 308 C C . THR A 1 47 ? 14.993 16.474 -24.653 1.00 88.73 ? ? ? ? ? ? 49 THR A C 1 +ATOM 309 O O . THR A 1 47 ? 14.523 15.780 -23.752 1.00 86.98 ? ? ? ? ? ? 49 THR A O 1 +ATOM 310 C CB . THR A 1 47 ? 15.135 18.969 -25.068 1.00 89.11 ? ? ? ? ? ? 49 THR A CB 1 +ATOM 311 O OG1 . THR A 1 47 ? 15.953 18.934 -23.892 1.00 92.76 ? ? ? ? ? ? 49 THR A OG1 1 +ATOM 312 C CG2 . THR A 1 47 ? 14.285 20.230 -25.055 1.00 88.83 ? ? ? ? ? ? 49 THR A CG2 1 +ATOM 313 N N . GLU A 1 48 ? 16.145 16.187 -25.257 1.00 93.73 ? ? ? ? ? ? 50 GLU A N 1 +ATOM 314 C CA . GLU A 1 48 ? 17.052 15.170 -24.714 1.00 98.04 ? ? ? ? ? ? 50 GLU A CA 1 +ATOM 315 C C . GLU A 1 48 ? 17.700 15.685 -23.409 1.00 99.89 ? ? ? ? ? ? 50 GLU A C 1 +ATOM 316 O O . GLU A 1 48 ? 17.792 14.952 -22.420 1.00 99.46 ? ? ? ? ? ? 50 GLU A O 1 +ATOM 317 C CB . GLU A 1 48 ? 18.103 14.731 -25.754 1.00 100.79 ? ? ? ? ? ? 50 GLU A CB 1 +ATOM 318 C CG . GLU A 1 48 ? 19.096 15.818 -26.196 0.50 107.62 ? ? ? ? ? ? 50 GLU A CG 1 +ATOM 319 C CD . GLU A 1 48 ? 20.357 15.251 -26.838 0.50 115.10 ? ? ? ? ? ? 50 GLU A CD 1 +ATOM 320 O OE1 . GLU A 1 48 ? 21.467 15.702 -26.482 0.50 120.30 ? ? ? ? ? ? 50 GLU A OE1 1 +ATOM 321 O OE2 . GLU A 1 48 ? 20.241 14.354 -27.697 0.50 115.44 ? ? ? ? ? ? 50 GLU A OE2 1 +ATOM 322 N N . HIS A 1 49 ? 18.108 16.957 -23.422 1.00 102.54 ? ? ? ? ? ? 51 HIS A N 1 +ATOM 323 C CA . HIS A 1 49 ? 18.615 17.674 -22.247 1.00 104.56 ? ? ? ? ? ? 51 HIS A CA 1 +ATOM 324 C C . HIS A 1 49 ? 17.684 17.578 -21.032 1.00 100.90 ? ? ? ? ? ? 51 HIS A C 1 +ATOM 325 O O . HIS A 1 49 ? 18.145 17.604 -19.888 1.00 102.24 ? ? ? ? ? ? 51 HIS A O 1 +ATOM 326 C CB . HIS A 1 49 ? 18.790 19.162 -22.576 1.00 107.45 ? ? ? ? ? ? 51 HIS A CB 1 +ATOM 327 C CG . HIS A 1 49 ? 19.959 19.466 -23.458 1.00 115.35 ? ? ? ? ? ? 51 HIS A CG 1 +ATOM 328 N ND1 . HIS A 1 49 ? 19.964 19.199 -24.811 1.00 117.92 ? ? ? ? ? ? 51 HIS A ND1 1 +ATOM 329 C CD2 . HIS A 1 49 ? 21.153 20.047 -23.185 1.00 122.56 ? ? ? ? ? ? 51 HIS A CD2 1 +ATOM 330 C CE1 . HIS A 1 49 ? 21.117 19.586 -25.330 1.00 123.61 ? ? ? ? ? ? 51 HIS A CE1 1 +ATOM 331 N NE2 . HIS A 1 49 ? 21.855 20.106 -24.366 1.00 126.48 ? ? ? ? ? ? 51 HIS A NE2 1 +ATOM 332 N N . THR A 1 50 ? 16.377 17.481 -21.294 1.00 95.68 ? ? ? ? ? ? 52 THR A N 1 +ATOM 333 C CA . THR A 1 50 ? 15.340 17.640 -20.268 1.00 90.19 ? ? ? ? ? ? 52 THR A CA 1 +ATOM 334 C C . THR A 1 50 ? 14.528 16.370 -20.027 1.00 86.57 ? ? ? ? ? ? 52 THR A C 1 +ATOM 335 O O . THR A 1 50 ? 13.629 16.031 -20.795 1.00 83.93 ? ? ? ? ? ? 52 THR A O 1 +ATOM 336 C CB . THR A 1 50 ? 14.419 18.847 -20.596 1.00 89.09 ? ? ? ? ? ? 52 THR A CB 1 +ATOM 337 O OG1 . THR A 1 50 ? 15.128 20.061 -20.323 1.00 91.82 ? ? ? ? ? ? 52 THR A OG1 1 +ATOM 338 C CG2 . THR A 1 50 ? 13.158 18.832 -19.761 1.00 84.32 ? ? ? ? ? ? 52 THR A CG2 1 +ATOM 339 N N . SER A 1 51 ? 14.863 15.686 -18.938 1.00 85.07 ? ? ? ? ? ? 53 SER A N 1 +ATOM 340 C CA . SER A 1 51 ? 14.183 14.465 -18.518 1.00 82.20 ? ? ? ? ? ? 53 SER A CA 1 +ATOM 341 C C . SER A 1 51 ? 12.860 14.724 -17.792 1.00 78.23 ? ? ? ? ? ? 53 SER A C 1 +ATOM 342 O O . SER A 1 51 ? 11.863 14.057 -18.069 1.00 75.30 ? ? ? ? ? ? 53 SER A O 1 +ATOM 343 C CB . SER A 1 51 ? 15.103 13.617 -17.631 1.00 84.25 ? ? ? ? ? ? 53 SER A CB 1 +ATOM 344 O OG . SER A 1 51 ? 15.508 14.324 -16.475 1.00 87.22 ? ? ? ? ? ? 53 SER A OG 1 +ATOM 345 N N . ALA A 1 52 ? 12.855 15.681 -16.867 1.00 76.66 ? ? ? ? ? ? 54 ALA A N 1 +ATOM 346 C CA . ALA A 1 52 ? 11.660 15.983 -16.082 1.00 73.63 ? ? ? ? ? ? 54 ALA A CA 1 +ATOM 347 C C . ALA A 1 52 ? 11.347 17.470 -16.020 1.00 72.67 ? ? ? ? ? ? 54 ALA A C 1 +ATOM 348 O O . ALA A 1 52 ? 12.231 18.295 -16.168 1.00 74.97 ? ? ? ? ? ? 54 ALA A O 1 +ATOM 349 C CB . ALA A 1 52 ? 11.807 15.427 -14.697 1.00 73.72 ? ? ? ? ? ? 54 ALA A CB 1 +ATOM 350 N N . ILE A 1 53 ? 10.078 17.799 -15.808 1.00 69.28 ? ? ? ? ? ? 55 ILE A N 1 +ATOM 351 C CA . ILE A 1 53 ? 9.644 19.182 -15.648 1.00 67.60 ? ? ? ? ? ? 55 ILE A CA 1 +ATOM 352 C C . ILE A 1 53 ? 8.807 19.315 -14.386 1.00 66.31 ? ? ? ? ? ? 55 ILE A C 1 +ATOM 353 O O . ILE A 1 53 ? 7.813 18.615 -14.234 1.00 63.74 ? ? ? ? ? ? 55 ILE A O 1 +ATOM 354 C CB . ILE A 1 53 ? 8.816 19.679 -16.852 1.00 66.27 ? ? ? ? ? ? 55 ILE A CB 1 +ATOM 355 C CG1 . ILE A 1 53 ? 9.678 19.756 -18.104 1.00 67.47 ? ? ? ? ? ? 55 ILE A CG1 1 +ATOM 356 C CG2 . ILE A 1 53 ? 8.217 21.057 -16.579 1.00 65.21 ? ? ? ? ? ? 55 ILE A CG2 1 +ATOM 357 C CD1 . ILE A 1 53 ? 8.873 19.776 -19.383 1.00 65.20 ? ? ? ? ? ? 55 ILE A CD1 1 +ATOM 358 N N . LYS A 1 54 ? 9.212 20.225 -13.498 1.00 67.56 ? ? ? ? ? ? 56 LYS A N 1 +ATOM 359 C CA . LYS A 1 54 ? 8.518 20.471 -12.242 1.00 66.86 ? ? ? ? ? ? 56 LYS A CA 1 +ATOM 360 C C . LYS A 1 54 ? 7.790 21.787 -12.345 1.00 66.25 ? ? ? ? ? ? 56 LYS A C 1 +ATOM 361 O O . LYS A 1 54 ? 8.325 22.736 -12.899 1.00 67.88 ? ? ? ? ? ? 56 LYS A O 1 +ATOM 362 C CB . LYS A 1 54 ? 9.524 20.526 -11.091 1.00 69.15 ? ? ? ? ? ? 56 LYS A CB 1 +ATOM 363 C CG . LYS A 1 54 ? 8.919 20.527 -9.688 1.00 66.38 ? ? ? ? ? ? 56 LYS A CG 1 +ATOM 364 C CD . LYS A 1 54 ? 9.898 21.069 -8.644 1.00 66.41 ? ? ? ? ? ? 56 LYS A CD 1 +ATOM 365 C CE . LYS A 1 54 ? 10.805 19.996 -8.061 1.00 66.08 ? ? ? ? ? ? 56 LYS A CE 1 +ATOM 366 N NZ . LYS A 1 54 ? 11.738 20.531 -7.020 1.00 66.38 ? ? ? ? ? ? 56 LYS A NZ 1 +ATOM 367 N N . VAL A 1 55 ? 6.569 21.843 -11.826 1.00 63.79 ? ? ? ? ? ? 57 VAL A N 1 +ATOM 368 C CA . VAL A 1 55 ? 5.805 23.088 -11.783 1.00 62.60 ? ? ? ? ? ? 57 VAL A CA 1 +ATOM 369 C C . VAL A 1 55 ? 5.508 23.478 -10.335 1.00 63.99 ? ? ? ? ? ? 57 VAL A C 1 +ATOM 370 O O . VAL A 1 55 ? 4.827 22.751 -9.607 1.00 62.58 ? ? ? ? ? ? 57 VAL A O 1 +ATOM 371 C CB . VAL A 1 55 ? 4.491 22.999 -12.582 1.00 60.05 ? ? ? ? ? ? 57 VAL A CB 1 +ATOM 372 C CG1 . VAL A 1 55 ? 3.777 24.330 -12.592 1.00 58.65 ? ? ? ? ? ? 57 VAL A CG1 1 +ATOM 373 C CG2 . VAL A 1 55 ? 4.759 22.561 -14.001 1.00 57.89 ? ? ? ? ? ? 57 VAL A CG2 1 +ATOM 374 N N . ARG A 1 56 ? 6.046 24.625 -9.926 1.00 67.06 ? ? ? ? ? ? 58 ARG A N 1 +ATOM 375 C CA . ARG A 1 56 ? 5.822 25.201 -8.602 1.00 68.68 ? ? ? ? ? ? 58 ARG A CA 1 +ATOM 376 C C . ARG A 1 56 ? 4.944 26.430 -8.775 1.00 68.31 ? ? ? ? ? ? 58 ARG A C 1 +ATOM 377 O O . ARG A 1 56 ? 5.295 27.346 -9.516 1.00 69.78 ? ? ? ? ? ? 58 ARG A O 1 +ATOM 378 C CB . ARG A 1 56 ? 7.149 25.622 -7.961 1.00 71.82 ? ? ? ? ? ? 58 ARG A CB 1 +ATOM 379 C CG . ARG A 1 56 ? 7.919 24.540 -7.264 1.00 71.32 ? ? ? ? ? ? 58 ARG A CG 1 +ATOM 380 C CD . ARG A 1 56 ? 8.899 25.124 -6.251 1.00 74.34 ? ? ? ? ? ? 58 ARG A CD 1 +ATOM 381 N NE . ARG A 1 56 ? 10.303 24.967 -6.641 1.00 76.63 ? ? ? ? ? ? 58 ARG A NE 1 +ATOM 382 C CZ . ARG A 1 56 ? 11.114 24.011 -6.180 1.00 77.74 ? ? ? ? ? ? 58 ARG A CZ 1 +ATOM 383 N NH1 . ARG A 1 56 ? 10.668 23.111 -5.308 1.00 77.26 ? ? ? ? ? ? 58 ARG A NH1 1 +ATOM 384 N NH2 . ARG A 1 56 ? 12.380 23.947 -6.590 1.00 79.00 ? ? ? ? ? ? 58 ARG A NH2 1 +ATOM 385 N N . GLY A 1 57 ? 3.795 26.450 -8.116 1.00 66.23 ? ? ? ? ? ? 59 GLY A N 1 +ATOM 386 C CA . GLY A 1 57 ? 2.891 27.591 -8.224 1.00 64.54 ? ? ? ? ? ? 59 GLY A CA 1 +ATOM 387 C C . GLY A 1 57 ? 1.515 27.161 -8.671 1.00 61.40 ? ? ? ? ? ? 59 GLY A C 1 +ATOM 388 O O . GLY A 1 57 ? 1.324 26.011 -9.023 1.00 60.50 ? ? ? ? ? ? 59 GLY A O 1 +ATOM 389 N N . LYS A 1 58 ? 0.553 28.077 -8.652 1.00 59.63 ? ? ? ? ? ? 60 LYS A N 1 +ATOM 390 C CA . LYS A 1 58 ? -0.823 27.767 -9.030 1.00 56.33 ? ? ? ? ? ? 60 LYS A CA 1 +ATOM 391 C C . LYS A 1 58 ? -0.937 27.782 -10.560 1.00 54.36 ? ? ? ? ? ? 60 LYS A C 1 +ATOM 392 O O . LYS A 1 58 ? -0.806 28.840 -11.173 1.00 55.40 ? ? ? ? ? ? 60 LYS A O 1 +ATOM 393 C CB . LYS A 1 58 ? -1.776 28.800 -8.402 1.00 56.75 ? ? ? ? ? ? 60 LYS A CB 1 +ATOM 394 C CG . LYS A 1 58 ? -3.130 28.251 -7.937 1.00 56.71 ? ? ? ? ? ? 60 LYS A CG 1 +ATOM 395 C CD . LYS A 1 58 ? -3.097 27.743 -6.485 1.00 57.00 ? ? ? ? ? ? 60 LYS A CD 1 +ATOM 396 C CE . LYS A 1 58 ? -4.401 27.012 -6.119 1.00 56.07 ? ? ? ? ? ? 60 LYS A CE 1 +ATOM 397 N N . ALA A 1 59 ? -1.157 26.623 -11.185 1.00 50.90 ? ? ? ? ? ? 61 ALA A N 1 +ATOM 398 C CA . ALA A 1 59 ? -1.229 26.563 -12.652 1.00 48.01 ? ? ? ? ? ? 61 ALA A CA 1 +ATOM 399 C C . ALA A 1 59 ? -2.205 25.512 -13.166 1.00 44.63 ? ? ? ? ? ? 61 ALA A C 1 +ATOM 400 O O . ALA A 1 59 ? -2.516 24.556 -12.458 1.00 43.62 ? ? ? ? ? ? 61 ALA A O 1 +ATOM 401 C CB . ALA A 1 59 ? 0.153 26.320 -13.244 1.00 49.49 ? ? ? ? ? ? 61 ALA A CB 1 +ATOM 402 N N . TYR A 1 60 ? -2.667 25.686 -14.404 1.00 41.70 ? ? ? ? ? ? 62 TYR A N 1 +ATOM 403 C CA . TYR A 1 60 ? -3.493 24.707 -15.082 1.00 38.07 ? ? ? ? ? ? 62 TYR A CA 1 +ATOM 404 C C . TYR A 1 60 ? -2.627 24.044 -16.134 1.00 37.82 ? ? ? ? ? ? 62 TYR A C 1 +ATOM 405 O O . TYR A 1 60 ? -1.998 24.722 -16.954 1.00 38.91 ? ? ? ? ? ? 62 TYR A O 1 +ATOM 406 C CB . TYR A 1 60 ? -4.671 25.417 -15.716 1.00 36.81 ? ? ? ? ? ? 62 TYR A CB 1 +ATOM 407 C CG . TYR A 1 60 ? -5.719 24.566 -16.417 1.00 33.24 ? ? ? ? ? ? 62 TYR A CG 1 +ATOM 408 C CD1 . TYR A 1 60 ? -6.553 23.709 -15.702 1.00 30.81 ? ? ? ? ? ? 62 TYR A CD1 1 +ATOM 409 C CD2 . TYR A 1 60 ? -5.925 24.669 -17.795 1.00 32.16 ? ? ? ? ? ? 62 TYR A CD2 1 +ATOM 410 C CE1 . TYR A 1 60 ? -7.554 22.938 -16.349 1.00 26.98 ? ? ? ? ? ? 62 TYR A CE1 1 +ATOM 411 C CE2 . TYR A 1 60 ? -6.915 23.914 -18.446 1.00 29.38 ? ? ? ? ? ? 62 TYR A CE2 1 +ATOM 412 C CZ . TYR A 1 60 ? -7.728 23.053 -17.716 1.00 26.79 ? ? ? ? ? ? 62 TYR A CZ 1 +ATOM 413 O OH . TYR A 1 60 ? -8.701 22.329 -18.381 1.00 24.12 ? ? ? ? ? ? 62 TYR A OH 1 +ATOM 414 N N . ILE A 1 61 ? -2.579 22.717 -16.097 1.00 36.07 ? ? ? ? ? ? 63 ILE A N 1 +ATOM 415 C CA . ILE A 1 61 ? -1.662 21.980 -16.938 1.00 35.83 ? ? ? ? ? ? 63 ILE A CA 1 +ATOM 416 C C . ILE A 1 61 ? -2.384 20.971 -17.798 1.00 33.41 ? ? ? ? ? ? 63 ILE A C 1 +ATOM 417 O O . ILE A 1 61 ? -3.202 20.217 -17.298 1.00 31.94 ? ? ? ? ? ? 63 ILE A O 1 +ATOM 418 C CB . ILE A 1 61 ? -0.610 21.239 -16.097 1.00 37.09 ? ? ? ? ? ? 63 ILE A CB 1 +ATOM 419 C CG1 . ILE A 1 61 ? 0.153 22.208 -15.183 1.00 40.08 ? ? ? ? ? ? 63 ILE A CG1 1 +ATOM 420 C CG2 . ILE A 1 61 ? 0.358 20.461 -17.018 1.00 38.40 ? ? ? ? ? ? 63 ILE A CG2 1 +ATOM 421 C CD1 . ILE A 1 61 ? 0.912 21.521 -14.083 1.00 42.02 ? ? ? ? ? ? 63 ILE A CD1 1 +ATOM 422 N N . GLN A 1 62 ? -2.075 20.961 -19.094 1.00 32.65 ? ? ? ? ? ? 64 GLN A N 1 +ATOM 423 C CA . GLN A 1 62 ? -2.645 19.966 -20.035 1.00 31.02 ? ? ? ? ? ? 64 GLN A CA 1 +ATOM 424 C C . GLN A 1 62 ? -1.536 19.076 -20.577 1.00 31.29 ? ? ? ? ? ? 64 GLN A C 1 +ATOM 425 O O . GLN A 1 62 ? -0.503 19.573 -21.072 1.00 33.32 ? ? ? ? ? ? 64 GLN A O 1 +ATOM 426 C CB . GLN A 1 62 ? -3.321 20.649 -21.251 1.00 30.42 ? ? ? ? ? ? 64 GLN A CB 1 +ATOM 427 C CG . GLN A 1 62 ? -4.366 21.714 -20.928 1.00 29.89 ? ? ? ? ? ? 64 GLN A CG 1 +ATOM 428 C CD . GLN A 1 62 ? -5.024 22.308 -22.172 1.00 30.22 ? ? ? ? ? ? 64 GLN A CD 1 +ATOM 429 O OE1 . GLN A 1 62 ? -4.345 22.746 -23.129 1.00 31.89 ? ? ? ? ? ? 64 GLN A OE1 1 +ATOM 430 N NE2 . GLN A 1 62 ? -6.362 22.351 -22.155 1.00 28.53 ? ? ? ? ? ? 64 GLN A NE2 1 +ATOM 431 N N . THR A 1 63 ? -1.751 17.773 -20.518 1.00 29.70 ? ? ? ? ? ? 65 THR A N 1 +ATOM 432 C CA . THR A 1 63 ? -0.825 16.842 -21.142 1.00 29.95 ? ? ? ? ? ? 65 THR A CA 1 +ATOM 433 C C . THR A 1 63 ? -1.610 15.830 -21.967 1.00 28.22 ? ? ? ? ? ? 65 THR A C 1 +ATOM 434 O O . THR A 1 63 ? -2.852 15.745 -21.879 1.00 26.39 ? ? ? ? ? ? 65 THR A O 1 +ATOM 435 C CB . THR A 1 63 ? -0.010 16.071 -20.095 1.00 30.81 ? ? ? ? ? ? 65 THR A CB 1 +ATOM 436 O OG1 . THR A 1 63 ? -0.897 15.297 -19.248 1.00 30.42 ? ? ? ? ? ? 65 THR A OG1 1 +ATOM 437 C CG2 . THR A 1 63 ? 0.824 17.023 -19.275 1.00 33.74 ? ? ? ? ? ? 65 THR A CG2 1 +ATOM 438 N N . ARG A 1 64 ? -0.886 15.027 -22.737 1.00 28.10 ? ? ? ? ? ? 66 ARG A N 1 +ATOM 439 C CA . ARG A 1 64 ? -1.516 13.903 -23.389 1.00 26.73 ? ? ? ? ? ? 66 ARG A CA 1 +ATOM 440 C C . ARG A 1 64 ? -2.410 13.108 -22.409 1.00 25.08 ? ? ? ? ? ? 66 ARG A C 1 +ATOM 441 O O . ARG A 1 64 ? -3.376 12.454 -22.828 1.00 23.73 ? ? ? ? ? ? 66 ARG A O 1 +ATOM 442 C CB . ARG A 1 64 ? -0.460 13.014 -24.044 1.00 27.91 ? ? ? ? ? ? 66 ARG A CB 1 +ATOM 443 C CG . ARG A 1 64 ? -1.032 11.692 -24.648 1.00 29.01 ? ? ? ? ? ? 66 ARG A CG 1 +ATOM 444 C CD . ARG A 1 64 ? -0.213 11.224 -25.909 1.00 33.87 ? ? ? ? ? ? 66 ARG A CD 1 +ATOM 445 N NE . ARG A 1 64 ? 1.113 10.719 -25.542 1.00 39.87 ? ? ? ? ? ? 66 ARG A NE 1 +ATOM 446 C CZ . ARG A 1 64 ? 1.273 9.451 -25.149 1.00 45.46 ? ? ? ? ? ? 66 ARG A CZ 1 +ATOM 447 N NH1 . ARG A 1 64 ? 2.466 9.006 -24.775 1.00 48.49 ? ? ? ? ? ? 66 ARG A NH1 1 +ATOM 448 N NH2 . ARG A 1 64 ? 0.208 8.625 -25.112 1.00 45.95 ? ? ? ? ? ? 66 ARG A NH2 1 +ATOM 449 N N . HIS A 1 65 ? -2.111 13.173 -21.107 1.00 24.86 ? ? ? ? ? ? 67 HIS A N 1 +ATOM 450 C CA . HIS A 1 65 ? -2.841 12.331 -20.131 1.00 24.10 ? ? ? ? ? ? 67 HIS A CA 1 +ATOM 451 C C . HIS A 1 65 ? -4.020 13.013 -19.469 1.00 23.34 ? ? ? ? ? ? 67 HIS A C 1 +ATOM 452 O O . HIS A 1 65 ? -4.610 12.431 -18.508 1.00 22.91 ? ? ? ? ? ? 67 HIS A O 1 +ATOM 453 C CB . HIS A 1 65 ? -1.918 11.730 -19.064 1.00 24.80 ? ? ? ? ? ? 67 HIS A CB 1 +ATOM 454 C CG . HIS A 1 65 ? -0.816 10.907 -19.640 1.00 27.48 ? ? ? ? ? ? 67 HIS A CG 1 +ATOM 455 N ND1 . HIS A 1 65 ? -0.956 10.191 -20.818 1.00 28.09 ? ? ? ? ? ? 67 HIS A ND1 1 +ATOM 456 C CD2 . HIS A 1 65 ? 0.447 10.682 -19.209 1.00 30.60 ? ? ? ? ? ? 67 HIS A CD2 1 +ATOM 457 C CE1 . HIS A 1 65 ? 0.181 9.571 -21.091 1.00 30.69 ? ? ? ? ? ? 67 HIS A CE1 1 +ATOM 458 N NE2 . HIS A 1 65 ? 1.041 9.835 -20.121 1.00 32.56 ? ? ? ? ? ? 67 HIS A NE2 1 +ATOM 459 N N . GLY A 1 66 ? -4.357 14.217 -19.977 1.00 23.45 ? ? ? ? ? ? 68 GLY A N 1 +ATOM 460 C CA . GLY A 1 66 ? -5.543 14.957 -19.528 1.00 23.05 ? ? ? ? ? ? 68 GLY A CA 1 +ATOM 461 C C . GLY A 1 66 ? -5.125 16.212 -18.813 1.00 23.58 ? ? ? ? ? ? 68 GLY A C 1 +ATOM 462 O O . GLY A 1 66 ? -3.974 16.630 -18.952 1.00 24.68 ? ? ? ? ? ? 68 GLY A O 1 +ATOM 463 N N . VAL A 1 67 ? -6.046 16.822 -18.054 1.00 23.73 ? ? ? ? ? ? 69 VAL A N 1 +ATOM 464 C CA . VAL A 1 67 ? -5.685 18.035 -17.310 1.00 25.29 ? ? ? ? ? ? 69 VAL A CA 1 +ATOM 465 C C . VAL A 1 67 ? -5.378 17.774 -15.842 1.00 27.38 ? ? ? ? ? ? 69 VAL A C 1 +ATOM 466 O O . VAL A 1 67 ? -5.799 16.787 -15.265 1.00 26.03 ? ? ? ? ? ? 69 VAL A O 1 +ATOM 467 C CB . VAL A 1 67 ? -6.706 19.173 -17.463 1.00 24.18 ? ? ? ? ? ? 69 VAL A CB 1 +ATOM 468 C CG1 . VAL A 1 67 ? -7.328 19.087 -18.796 1.00 23.47 ? ? ? ? ? ? 69 VAL A CG1 1 +ATOM 469 C CG2 . VAL A 1 67 ? -7.792 19.078 -16.407 1.00 23.38 ? ? ? ? ? ? 69 VAL A CG2 1 +ATOM 470 N N . ILE A 1 68 ? -4.609 18.685 -15.274 1.00 31.58 ? ? ? ? ? ? 70 ILE A N 1 +ATOM 471 C CA . ILE A 1 68 ? -4.257 18.667 -13.875 1.00 35.85 ? ? ? ? ? ? 70 ILE A CA 1 +ATOM 472 C C . ILE A 1 68 ? -3.894 20.103 -13.437 1.00 40.48 ? ? ? ? ? ? 70 ILE A C 1 +ATOM 473 O O . ILE A 1 68 ? -3.442 20.943 -14.252 1.00 41.26 ? ? ? ? ? ? 70 ILE A O 1 +ATOM 474 C CB . ILE A 1 68 ? -3.137 17.660 -13.591 1.00 35.31 ? ? ? ? ? ? 70 ILE A CB 1 +ATOM 475 C CG1 . ILE A 1 68 ? -3.062 17.400 -12.099 1.00 34.94 ? ? ? ? ? ? 70 ILE A CG1 1 +ATOM 476 C CG2 . ILE A 1 68 ? -1.813 18.148 -14.144 1.00 36.89 ? ? ? ? ? ? 70 ILE A CG2 1 +ATOM 477 C CD1 . ILE A 1 68 ? -2.514 16.052 -11.774 1.00 34.03 ? ? ? ? ? ? 70 ILE A CD1 1 +ATOM 478 N N . GLU A 1 69 ? -4.123 20.367 -12.150 1.00 45.39 ? ? ? ? ? ? 71 GLU A N 1 +ATOM 479 C CA . GLU A 1 69 ? -3.959 21.684 -11.556 1.00 51.34 ? ? ? ? ? ? 71 GLU A CA 1 +ATOM 480 C C . GLU A 1 69 ? -2.832 21.594 -10.527 1.00 55.11 ? ? ? ? ? ? 71 GLU A C 1 +ATOM 481 O O . GLU A 1 69 ? -2.859 20.721 -9.664 1.00 55.41 ? ? ? ? ? ? 71 GLU A O 1 +ATOM 482 C CB . GLU A 1 69 ? -5.285 22.073 -10.896 1.00 50.78 ? ? ? ? ? ? 71 GLU A CB 1 +ATOM 483 C CG . GLU A 1 69 ? -5.358 23.453 -10.275 1.00 56.29 ? ? ? ? ? ? 71 GLU A CG 1 +ATOM 484 C CD . GLU A 1 69 ? -6.733 23.756 -9.687 1.00 59.81 ? ? ? ? ? ? 71 GLU A CD 1 +ATOM 485 O OE1 . GLU A 1 69 ? -6.805 24.062 -8.476 1.00 61.66 ? ? ? ? ? ? 71 GLU A OE1 1 +ATOM 486 O OE2 . GLU A 1 69 ? -7.742 23.685 -10.439 1.00 59.40 ? ? ? ? ? ? 71 GLU A OE2 1 +ATOM 487 N N . SER A 1 70 ? -1.830 22.463 -10.633 1.00 60.26 ? ? ? ? ? ? 72 SER A N 1 +ATOM 488 C CA . SER A 1 70 ? -0.785 22.528 -9.618 1.00 65.19 ? ? ? ? ? ? 72 SER A CA 1 +ATOM 489 C C . SER A 1 70 ? -1.191 23.554 -8.582 1.00 67.72 ? ? ? ? ? ? 72 SER A C 1 +ATOM 490 O O . SER A 1 70 ? -1.586 24.664 -8.933 1.00 68.67 ? ? ? ? ? ? 72 SER A O 1 +ATOM 491 C CB . SER A 1 70 ? 0.566 22.885 -10.232 1.00 66.81 ? ? ? ? ? ? 72 SER A CB 1 +ATOM 492 O OG . SER A 1 70 ? 0.520 24.141 -10.869 1.00 69.19 ? ? ? ? ? ? 72 SER A OG 1 +ATOM 493 N N . GLU A 1 71 ? -1.109 23.173 -7.312 1.00 70.07 ? ? ? ? ? ? 73 GLU A N 1 +ATOM 494 C CA . GLU A 1 71 ? -1.494 24.038 -6.212 1.00 72.36 ? ? ? ? ? ? 73 GLU A CA 1 +ATOM 495 C C . GLU A 1 71 ? -0.236 24.266 -5.347 1.00 75.16 ? ? ? ? ? ? 73 GLU A C 1 +ATOM 496 O O . GLU A 1 71 ? -0.249 24.010 -4.173 1.00 77.08 ? ? ? ? ? ? 73 GLU A O 1 +ATOM 497 C CB . GLU A 1 71 ? -2.606 23.360 -5.394 1.00 71.07 ? ? ? ? ? ? 73 GLU A CB 1 +ATOM 498 C CG . GLU A 1 71 ? -3.410 22.310 -6.167 1.00 69.29 ? ? ? ? ? ? 73 GLU A CG 1 +ATOM 499 C CD . GLU A 1 71 ? -4.836 22.110 -5.652 1.00 67.49 ? ? ? ? ? ? 73 GLU A CD 1 +ATOM 500 O OE1 . GLU A 1 71 ? -5.627 23.072 -5.780 1.00 67.26 ? ? ? ? ? ? 73 GLU A OE1 1 +ATOM 501 O OE2 . GLU A 1 71 ? -5.169 20.998 -5.157 1.00 64.72 ? ? ? ? ? ? 73 GLU A OE2 1 +ATOM 502 N N . GLY A 1 72 ? 0.917 24.600 -5.926 1.00 75.64 ? ? ? ? ? ? 74 GLY A N 1 +ATOM 503 C CA . GLY A 1 72 ? 2.179 24.627 -5.145 1.00 76.28 ? ? ? ? ? ? 74 GLY A CA 1 +ATOM 504 C C . GLY A 1 72 ? 2.532 25.958 -4.485 1.00 77.39 ? ? ? ? ? ? 74 GLY A C 1 +ATOM 505 O O . GLY A 1 72 ? 1.761 26.914 -4.592 1.00 77.60 ? ? ? ? ? ? 74 GLY A O 1 +ATOM 506 N N . LYS A 1 74 ? 3.692 26.048 -3.818 1.00 78.11 ? ? ? ? ? ? 75 LYS A N 1 +ATOM 507 C CA . LYS A 1 74 ? 4.129 27.336 -3.223 1.00 79.14 ? ? ? ? ? ? 75 LYS A CA 1 +ATOM 508 C C . LYS A 1 74 ? 4.479 28.474 -4.244 1.00 79.69 ? ? ? ? ? ? 75 LYS A C 1 +ATOM 509 O O . LYS A 1 74 ? 5.535 28.516 -4.903 1.00 79.72 ? ? ? ? ? ? 75 LYS A O 1 +ATOM 510 C CB . LYS A 1 74 ? 5.211 27.143 -2.149 1.00 79.82 ? ? ? ? ? ? 75 LYS A CB 1 +ATOM 511 C CG . LYS A 1 74 ? 6.646 27.001 -2.680 1.00 82.03 ? ? ? ? ? ? 75 LYS A CG 1 +ATOM 512 C CD . LYS A 1 74 ? 7.702 26.968 -1.556 1.00 83.81 ? ? ? ? ? ? 75 LYS A CD 1 +ATOM 513 C CE . LYS A 1 74 ? 9.130 26.847 -2.110 1.00 84.65 ? ? ? ? ? ? 75 LYS A CE 1 +ATOM 514 N NZ . LYS A 1 74 ? 10.106 26.489 -1.037 1.00 84.64 ? ? ? ? ? ? 75 LYS A NZ 1 diff --git a/modules/seq/base/doc/seq.rst b/modules/seq/base/doc/seq.rst index 64ac6d3a7d974446f95657f30748d3ddc508f325..e84cfe6747c627a07f7c756eb26397ce95e1598d 100644 --- a/modules/seq/base/doc/seq.rst +++ b/modules/seq/base/doc/seq.rst @@ -54,7 +54,7 @@ methods, sequences can also be loaded from a string: seq_string='''>sequence abcdefghiklmnop''' - s=io.LoadSequenceFromString(seq_string, 'fasta') + s=io.SequenceFromString(seq_string, 'fasta') print s.name, s # will print "sequence abcdefghiklmnop" Note that, in that case specifying the format is mandatory. diff --git a/modules/seq/base/pymod/CMakeLists.txt b/modules/seq/base/pymod/CMakeLists.txt index af105daed127eca4d4bd3d0fb7e11656d6e5e05a..f2aac4ea51cb0cd57fed4d304199db0a420158fb 100644 --- a/modules/seq/base/pymod/CMakeLists.txt +++ b/modules/seq/base/pymod/CMakeLists.txt @@ -3,4 +3,6 @@ set(OST_SEQ_PYMOD_SOURCES wrap_seq.cc ) -pymod(NAME seq CPP ${OST_SEQ_PYMOD_SOURCES} PY __init__.py) +if (NOT ENABLE_STATIC) + pymod(NAME seq CPP ${OST_SEQ_PYMOD_SOURCES} PY __init__.py) +endif() diff --git a/modules/seq/base/pymod/export_sequence.cc b/modules/seq/base/pymod/export_sequence.cc index 38a0e34ff3c211e649294c2d4f72b05b8f06e429..269ce3a7cb584704d5074505180d653ffe93539c 100644 --- a/modules/seq/base/pymod/export_sequence.cc +++ b/modules/seq/base/pymod/export_sequence.cc @@ -25,7 +25,10 @@ #include <ost/export_helper/pair_to_tuple_conv.hh> #include <ost/generic_property.hh> #include <ost/export_helper/generic_property_def.hh> +#include <ost/config.hh> +#if(OST_INFO_ENABLED) #include <ost/info/info.hh> +#endif #include <ost/mol/mol.hh> #include <ost/seq/sequence_handle.hh> #include <ost/seq/alignment_handle.hh> @@ -38,7 +41,6 @@ using namespace ost; using namespace ost::seq; using namespace boost::python; -namespace { void (SequenceHandle::*attach_one)(const mol::EntityView&)=&SequenceHandle::AttachView; void (SequenceHandle::*attach_two)(const mol::EntityView&, @@ -255,6 +257,8 @@ void const_seq_handle_def(O& bp_class) .add_property("last_non_gap", &C::GetLastNonGap) .def("GetAttachedView", &C::GetAttachedView) .def("GetGaplessString", &C::GetGaplessString) + .add_property("role", make_function(&C::GetRole, + return_value_policy<copy_const_reference>())) .def("GetString", &C::GetString, return_value_policy<copy_const_reference>()) .def("GetName", &C::GetName, @@ -276,7 +280,6 @@ void const_seq_handle_def(O& bp_class) ; } -} void export_sequence() { @@ -298,6 +301,9 @@ void export_sequence() make_function(&SequenceHandle::GetString, return_value_policy<copy_const_reference>()), &SequenceHandle::SetString) + .add_property("role", make_function(&SequenceHandle::GetRole, + return_value_policy<copy_const_reference>()), + &SequenceHandle::SetRole) .def("SetName", &SequenceHandle::SetName) .add_property("name", make_function(&SequenceHandle::GetName, @@ -311,7 +317,8 @@ void export_sequence() implicitly_convertible<SequenceHandle, ConstSequenceHandle>(); - def("CreateSequence", &CreateSequence); + def("CreateSequence", &CreateSequence, + (arg("name"), arg("seq"), arg("role")="UNKNOWN")); /*class_<SequenceHandleList>("SequenceHandleList", init<>()) .def(vector_indexing_suite<SequenceHandleList>()) ;*/ @@ -339,6 +346,7 @@ void export_sequence() .def("GetResidue", &AlignmentHandle::GetResidue) .def("AddSequence", &AlignmentHandle::AddSequence) .def("FindSequence", &AlignmentHandle::FindSequence) + .def("FindSequenceIndex", &AlignmentHandle::FindSequenceIndex) .def("Copy", &AlignmentHandle::Copy) .def("ToString", &AlignmentHandle::ToString) .def("GetLength", &AlignmentHandle::GetLength) @@ -346,6 +354,9 @@ void export_sequence() .def("GetSequences", &AlignmentHandle::GetSequences) .def("GetCoverage", &AlignmentHandle::GetCoverage) .def("AttachView", attach_view_a) + .def("SetSequenceRole", &AlignmentHandle::SetSequenceRole) + .def("GetSequenceRole", &AlignmentHandle::GetSequenceRole, + return_value_policy<copy_const_reference>()) .def("AttachView", attach_view_b) .def("Cut", &AlignmentHandle::Cut) .def("MakeRegion", &AlignmentHandle::MakeRegion) @@ -404,13 +415,15 @@ void export_sequence() def("CreateSequenceList", &CreateSequenceList); def("SequenceFromChain", seq_from_chain_a); def("SequenceFromChain", seq_from_chain_b); +#if(OST_INFO_ENABLED) def("SequenceToInfo", &SequenceToInfo); + def("SequenceListToInfo", &SequenceListToInfo); + def("SequenceFromInfo", &SequenceFromInfo); + def("SequenceListFromInfo", &SequenceListFromInfo); +#endif def("ViewsFromSequences", &ViewsFromSequences, (arg("seq1"), arg("seq2"))); def("ViewsFromAlignment", &ViewsFromAlignment, (arg("aln"), arg("index1")=0, arg("index2")=1)); - def("SequenceListToInfo", &SequenceListToInfo); - def("SequenceFromInfo", &SequenceFromInfo); def("CreateAlignment", &CreateAlignment); def("AlignmentFromSequenceList", &AlignmentFromSequenceList); - def("SequenceListFromInfo", &SequenceListFromInfo); } diff --git a/modules/seq/base/src/CMakeLists.txt b/modules/seq/base/src/CMakeLists.txt index 6a22a5ad2a575ca7f633a6bde5c00ae31d1ed2b9..8ef75076e739e4cf90e01e97f5e9582f22cd67cf 100644 --- a/modules/seq/base/src/CMakeLists.txt +++ b/modules/seq/base/src/CMakeLists.txt @@ -29,8 +29,13 @@ alignment_handle.cc sequence_op.cc views_from_sequences.cc ) -module(NAME seq SOURCES ${OST_SEQ_SOURCES} - HEADERS ${OST_SEQ_IMPL_HEADERS} IN_DIR impl - ${OST_SEQ_HEADERS} - DEPENDS_ON ost_info ost_mol) +if (ENABLE_INFO) + set(INFO_DEPS ost_info) +endif() + + +module(NAME seq SOURCES ${OST_SEQ_SOURCES} + HEADERS ${OST_SEQ_IMPL_HEADERS} IN_DIR impl + ${OST_SEQ_HEADERS} + DEPENDS_ON ost_mol ${INFO_DEPS}) \ No newline at end of file diff --git a/modules/seq/base/src/alignment_handle.cc b/modules/seq/base/src/alignment_handle.cc index 3e4ed4256f05bcef1128cdccef5585a3b1d8e582..47a4fd0dd371747b35761519f15c696751fa3a4a 100644 --- a/modules/seq/base/src/alignment_handle.cc +++ b/modules/seq/base/src/alignment_handle.cc @@ -166,6 +166,11 @@ ConstSequenceHandle AlignmentHandle::FindSequence(const String& name) const return ConstSequenceHandle(impl_->FindSequence(name)); } +int AlignmentHandle::FindSequenceIndex(const String& name) const +{ + this->CheckValidity(); + return impl_->FindSequenceIndex(name); +} void AlignmentHandle::Cut(int start, int end) { @@ -308,4 +313,20 @@ mol::EntityViewPair AlignmentHandle::GetMatchingBackboneViews(int idx0, int idx1 return mol::EntityViewPair(v1, v2); } + +const String& AlignmentHandle::GetSequenceRole(int seq_index) +{ + this->CheckValidity(); + return impl_->GetSequence(seq_index)->GetRole(); + +} + +void AlignmentHandle::SetSequenceRole(int seq_index, const String& role) +{ + this->CheckValidity(); + impl_->GetSequence(seq_index)->SetRole(role); + +} + + }} diff --git a/modules/seq/base/src/alignment_handle.hh b/modules/seq/base/src/alignment_handle.hh index 9a109215b7236dd7ccd3b7a9acf9ea838df48532..9990e170570d4c19f4c0f4a9eaf5129ea1b2f60f 100644 --- a/modules/seq/base/src/alignment_handle.hh +++ b/modules/seq/base/src/alignment_handle.hh @@ -97,7 +97,9 @@ public: /// If several sequences have the same name, the first matching sequence will /// be returned. ConstSequenceHandle FindSequence(const String& name) const; - + + int FindSequenceIndex(const String& name) const; + /// \brief attach view to given sequence /// \sa SequenceHandle::AttachView(const mol::EntityView&) void AttachView(int seq_index, const mol::EntityView& view); @@ -168,6 +170,10 @@ public: /// between 0 (no coverage) and 1 (full coverage) Real GetCoverage(int seq_index) const; + + const String& GetSequenceRole(int seq_index); + + void SetSequenceRole(int seq_index, const String& role); private: void CheckValidity() const; impl::SequenceListImplPtr impl_; diff --git a/modules/seq/base/src/impl/sequence_impl.cc b/modules/seq/base/src/impl/sequence_impl.cc index df8cabe0aa3c87481ddc562d29c9829969ac5396..733eaf1b8e17f765581a4cb1e527beb2bf3483ef 100644 --- a/modules/seq/base/src/impl/sequence_impl.cc +++ b/modules/seq/base/src/impl/sequence_impl.cc @@ -21,8 +21,11 @@ */ #include <boost/format.hpp> - +#include <ost/config.hh> +#if(OST_INFO_ENABLED) #include <ost/info/info.hh> +#endif + #include <ost/integrity_error.hh> #include <ost/mol/chain_view.hh> @@ -52,11 +55,12 @@ bool SequenceImpl::IsSequenceStringSane(const String& seq_string) } SequenceImplPtr SequenceImpl::FromString(const String& seq_name, - const String& seq_string) + const String& seq_string, + const String& role) { if (SequenceImpl::IsSequenceStringSane(seq_string)) { - return SequenceImplPtr(new SequenceImpl(seq_name, seq_string)); + return SequenceImplPtr(new SequenceImpl(seq_name, seq_string, role)); } throw InvalidSequence(); } @@ -99,15 +103,15 @@ void SequenceImpl::SetString(const String& seq) } SequenceImpl::SequenceImpl(const String& seq_name, - const String& seq_string) - : seq_name_(seq_name), seq_string_(seq_string), offset_(0) + const String& seq_string, const String& role) + : seq_name_(seq_name), seq_string_(seq_string), seq_role_(role), offset_(0) { this->ShiftsFromSequence(); } SequenceImplPtr SequenceImpl::Copy() const { - SequenceImplPtr new_seq(new SequenceImpl(seq_name_, seq_string_)); + SequenceImplPtr new_seq(new SequenceImpl(seq_name_, seq_string_, seq_role_)); new_seq->offset_=offset_; new_seq->shifts_=shifts_; new_seq->attached_view_=attached_view_; @@ -280,6 +284,7 @@ bool SequenceImpl::HasAttachedView() const return attached_view_.IsValid(); } +#if(OST_INFO_ENABLED) void SequenceImplToInfo(const SequenceImplPtr& sequence, info::InfoGroup& group) { group.SetTextData(sequence->GetString()); @@ -300,6 +305,7 @@ SequenceImplPtr SequenceImplFromInfo(const info::InfoGroup& group) sequence->SetOffset(offset); return sequence; } +#endif int SequenceImpl::GetFirstNonGap() const { diff --git a/modules/seq/base/src/impl/sequence_impl.hh b/modules/seq/base/src/impl/sequence_impl.hh index beae61e03033f4820f36b2c062b6368cf155dd0e..fecad2ca921599ecd85c58ee33e6c184bdbd5a52 100644 --- a/modules/seq/base/src/impl/sequence_impl.hh +++ b/modules/seq/base/src/impl/sequence_impl.hh @@ -27,7 +27,10 @@ #include <boost/shared_ptr.hpp> #include <ost/generic_property.hh> +#include <ost/config.hh> +#if(OST_INFO_ENABLED) #include <ost/info/info_fw.hh> +#endif #include <ost/mol/residue_prop.hh> #include <ost/mol/entity_view.hh> #include <ost/mol/residue_view.hh> @@ -47,7 +50,8 @@ class DLLEXPORT_OST_SEQ SequenceImpl : public GenericPropContainerImpl { public: /// \brief Construct new sequence object from sequence_string. static SequenceImplPtr FromString(const String& seq_name, - const String& sequence_string); + const String& sequence_string, + const String& role="UNKNOWN"); /// \brief Get residue index corresponding to given sequence position /// \param pos zero-based index @@ -102,7 +106,8 @@ public: /// /// If you want to check whether the sequence String does only contain /// valid characters use \c CreateSequence instead. - SequenceImpl(const String& seq_name, const String& sequence_string); + SequenceImpl(const String& seq_name, const String& sequence_string, + const String& role); /// \brief get one letter code of residue at position char GetOneLetterCode(int position) const; @@ -145,7 +150,15 @@ public: { return seq_string_[index]; } + const String& GetRole() const + { + return seq_role_; + } + void SetRole(const String& role) + { + seq_role_=role; + } private: /// \brief Recalculates gap shifts from sequence. @@ -166,6 +179,7 @@ private: } Shift; String seq_name_; String seq_string_; + String seq_role_; std::list<Shift> shifts_; bool editing_; int offset_; @@ -175,14 +189,15 @@ private: /// \internal typedef std::vector<SequenceImplPtr> SequenceList; +#if(OST_INFO_ENABLED) /// \internal -void DLLEXPORT_OST_SEQ SequenceImplToInfo(const SequenceImplPtr& sequence, - info::InfoGroup& group); -/// \internal -SequenceImplPtr DLLEXPORT_OST_SEQ +SequenceImplPtr DLLEXPORT_OST_SEQ SequenceImplFromInfo(const info::InfoGroup& group); /// \internal -SequenceImplFromInfo(const info::InfoGroup& group); +void DLLEXPORT_OST_SEQ SequenceImplToInfo(const SequenceImplPtr& sequence, + info::InfoGroup& group); +#endif + }}} //ns #endif diff --git a/modules/seq/base/src/impl/sequence_list_impl.cc b/modules/seq/base/src/impl/sequence_list_impl.cc index f0ef01531e91cedb69c0039d78edfc9673e6c1fb..6580aac92bf8032f3b40de53a28a3df23670565f 100644 --- a/modules/seq/base/src/impl/sequence_list_impl.cc +++ b/modules/seq/base/src/impl/sequence_list_impl.cc @@ -18,7 +18,10 @@ //------------------------------------------------------------------------------ #include <limits> +#include <ost/config.hh> +#if(OST_INFO_ENABLED) #include <ost/info/info.hh> +#endif #include <ost/seq/impl/sequence_list_impl.hh> namespace ost { namespace seq { namespace impl { @@ -58,6 +61,18 @@ SequenceImplPtr SequenceListImpl::FindSequence(const String& name) const return SequenceImplPtr(); } + +int SequenceListImpl::FindSequenceIndex(const String& name) const +{ + for (size_t i=0; i<list_.size(); ++i) { + if (list_[i]->GetName()==name) { + return int(i); + } + } + return -1; +} + + String SequenceListImpl::ToString(int width) const { std::stringstream buffer; @@ -142,6 +157,7 @@ SequenceListImplPtr SequenceListImpl::Copy() const return new_ali; } +#if(OST_INFO_ENABLED) void SequenceListImplToInfo(const SequenceListImplPtr& seq_list, info::InfoGroup& group) { @@ -163,6 +179,7 @@ SequenceListImplPtr SequenceListImplFromInfo(info::InfoGroup& group) } return seq_list; } +#endif SequenceListImplPtr SequenceListImpl::Slice(int first, int n) const { diff --git a/modules/seq/base/src/impl/sequence_list_impl.hh b/modules/seq/base/src/impl/sequence_list_impl.hh index 7be941f730778218dfda4d7a54b1dead9f8c45f0..cb69e41ead9bfbc91975b3ce5062bde00b836eef 100644 --- a/modules/seq/base/src/impl/sequence_list_impl.hh +++ b/modules/seq/base/src/impl/sequence_list_impl.hh @@ -65,6 +65,8 @@ public: SequenceImplPtr FindSequence(const String& name) const; + int FindSequenceIndex(const String& name) const; + String ToString(int width=80) const; SequenceListImplPtr Slice(int first, int n) const; @@ -92,6 +94,7 @@ private: std::vector<SequenceImplPtr> list_; }; +#if(OST_INFO_ENABLED) /// \brief export sequence list impl to info /// \internal void DLLEXPORT_OST_SEQ @@ -102,6 +105,7 @@ SequenceListImplToInfo(const SequenceListImplPtr& seq_list, /// \internal SequenceListImplPtr DLLEXPORT_OST_SEQ SequenceListImplFromInfo(info::InfoGroup& group); +#endif }}} diff --git a/modules/seq/base/src/sequence_handle.cc b/modules/seq/base/src/sequence_handle.cc index acd2b13e7b44d2baa53ec57c64b8cc3d4a7b3f60..627ebdc36ee0501a7ff5fcf2926af7c199dae592 100644 --- a/modules/seq/base/src/sequence_handle.cc +++ b/modules/seq/base/src/sequence_handle.cc @@ -59,6 +59,25 @@ char ConstSequenceHandle::operator[](int index) const +const String& ConstSequenceHandle::GetRole() const +{ + this->CheckValidity(); + return Impl()->GetRole(); +} + + +const String& SequenceHandle::GetRole() const +{ + this->CheckValidity(); + return Impl()->GetRole(); +} + +void SequenceHandle::SetRole(const String& role) const +{ + this->CheckValidity(); + Impl()->SetRole(role); +} + void ConstSequenceHandle::CheckValidity() const { @@ -78,9 +97,10 @@ impl::SequenceImplPtr& ConstSequenceHandle::Impl() const } -SequenceHandle CreateSequence(const String& name, const String& seq) +SequenceHandle CreateSequence(const String& name, const String& seq, + const String& role) { - return SequenceHandle(impl::SequenceImpl::FromString(name, seq)); + return SequenceHandle(impl::SequenceImpl::FromString(name, seq, role)); } @@ -206,6 +226,8 @@ void SequenceHandle::AttachView(const mol::EntityView& view, Impl()->AttachView(view, chain_name); } +#if(OST_INFO_ENABLED) + /// \brief export sequence to info void SequenceToInfo(const ConstSequenceHandle& sequence, info::InfoGroup& group) @@ -218,6 +240,9 @@ SequenceHandle SequenceFromInfo(info::InfoGroup& group) { return SequenceHandle(impl::SequenceImplFromInfo(group)); } +#endif + + std::ostream& operator<<(std::ostream& os, const ConstSequenceHandle& sequence) { diff --git a/modules/seq/base/src/sequence_handle.hh b/modules/seq/base/src/sequence_handle.hh index 1c2cee610fbe20e92b9e446bf4af894d710fb433..937387c797bc42f28b0fe902f1e9af256d6fa416 100644 --- a/modules/seq/base/src/sequence_handle.hh +++ b/modules/seq/base/src/sequence_handle.hh @@ -25,7 +25,10 @@ #include <ost/base.hh> #include <ost/generic_property.hh> +#include <ost/config.hh> +#if(OST_INFO_ENABLED) #include <ost/info/info_fw.hh> +#endif #include <ost/seq/module_config.hh> #include <ost/mol/residue_view.hh> @@ -119,6 +122,8 @@ public: /// \sa SequenceHandle::AttachView(const mol::EntityView&, const String&) bool HasAttachedView() const; + const String& GetRole() const; + bool operator==(const ConstSequenceHandle& rhs) const; bool operator!=(const ConstSequenceHandle& rhs) const; @@ -283,6 +288,10 @@ public: /// \internal SequenceHandle(const impl::SequenceImplPtr& impl); + const String& GetRole() const; + + void SetRole(const String& role) const; + impl::SequenceImplPtr& Impl() const; GenericPropContainerImpl* GpImpl(); @@ -294,14 +303,17 @@ private: }; SequenceHandle DLLEXPORT_OST_SEQ CreateSequence(const String& name, - const String& seq); - + const String& seq, + const String& role="UNKNOWN"); +#if(OST_INFO_ENABLED) /// \brief export sequence to info void DLLEXPORT_OST_SEQ SequenceToInfo(const ConstSequenceHandle& sequence, info::InfoGroup& group); /// \brief create sequence from info SequenceHandle DLLEXPORT_OST_SEQ SequenceFromInfo(info::InfoGroup& group); +#endif + DLLEXPORT_OST_SEQ std::ostream& operator<<(std::ostream& os, const ConstSequenceHandle& sequence); diff --git a/modules/seq/base/src/sequence_list.cc b/modules/seq/base/src/sequence_list.cc index eb45568fdbb639c1a14eab4732f076f9d500bcee..52474a3d71b40ccb2498bcc245f4564755fda048 100644 --- a/modules/seq/base/src/sequence_list.cc +++ b/modules/seq/base/src/sequence_list.cc @@ -22,7 +22,10 @@ */ #include <ost/invalid_handle.hh> +#include <ost/config.hh> +#if(OST_INFO_ENABLED) #include <ost/info/info.hh> +#endif #include <ost/seq/impl/sequence_list_impl.hh> #include <ost/seq/sequence_list.hh> @@ -180,6 +183,7 @@ int SequenceList::GetMaxLength() const return impl_->GetMaxLength(); } +#if(OST_INFO_ENABLED) /// \brief export sequence list to info void SequenceListToInfo(const ConstSequenceList& seq_list, info::InfoGroup& group) @@ -192,6 +196,7 @@ SequenceList SequenceListFromInfo(info::InfoGroup& group) { return SequenceList(impl::SequenceListImplFromInfo(group)); } +#endif SequenceList::operator ConstSequenceList() const { diff --git a/modules/seq/base/src/sequence_list.hh b/modules/seq/base/src/sequence_list.hh index 71067438d0404a0af7c41a6138b3fb09c403433f..2e6895c6e62b19b52e31aad3cebc1d9de8904cec 100644 --- a/modules/seq/base/src/sequence_list.hh +++ b/modules/seq/base/src/sequence_list.hh @@ -124,12 +124,14 @@ protected: SequenceList DLLEXPORT_OST_SEQ CreateSequenceList(); ConstSequenceList DLLEXPORT_OST_SEQ CreateConstSequenceList(); +#if(OST_INFO_ENABLED) /// \brief export sequence list to info void DLLEXPORT_OST_SEQ SequenceListToInfo(const ConstSequenceList& seq_list, info::InfoGroup& group); /// \brief create sequence list object from info SequenceList DLLEXPORT_OST_SEQ SequenceListFromInfo(info::InfoGroup& group); +#endif }} #endif diff --git a/modules/seq/base/tests/test_seq.py b/modules/seq/base/tests/test_seq.py index 7cc73a5cedb9cad4044948f840693b63bc72b16b..bfd80d7bf70461211962f6b36c2c603584b4fe4c 100644 --- a/modules/seq/base/tests/test_seq.py +++ b/modules/seq/base/tests/test_seq.py @@ -174,6 +174,8 @@ class TestSeq(unittest.TestCase): string_b=''.join([r.one_letter_code for r in b.residues]) self.assertEqual(string_a, 'BDFH') self.assertEqual(string_b, 'BDFH') -suite = unittest.TestLoader().loadTestsFromTestCase(TestSeq) -unittest.TextTestRunner().run(suite) + +if __name__== '__main__': + from ost import testutils + testutils.RunTests() diff --git a/scripts/CMakeLists.txt b/scripts/CMakeLists.txt index f71f153277224ae97a8e7155b15e653ec504123d..0b6b429a45beebc7c2233d65218dba89fa86f32d 100644 --- a/scripts/CMakeLists.txt +++ b/scripts/CMakeLists.txt @@ -1,4 +1,5 @@ -set(SUBST_DICT BUILD_TYPE=${CMAKE_BUILD_TYPE} PYTHON_BINARY=${PYTHON_BINARY} LIBDIR=${LIB_DIR} LIBEXEC_PATH=${LIBEXEC_PATH}) +set(SUBST_DICT BUILD_TYPE=${CMAKE_BUILD_TYPE} PYTHON_BINARY=${PYTHON_BINARY} +PYTHON_VERSION=${PYTHON_VERSION} LIBDIR=${LIB_DIR} LIBEXEC_PATH=${LIBEXEC_PATH}) message("${BUILD_TYPE}") add_custom_target(ost_scripts ALL) @@ -11,32 +12,34 @@ else() add_dependencies(ost_scripts _ost_io) endif() -if(WIN32) - script(NAME dng.bat INPUT dng.bat.in SUBSTITUTE ${SUBST_DICT} - TARGET ost_scripts) - script(NAME ost.bat INPUT ost.bat.in SUBSTITUTE ${SUBST_DICT} - TARGET ost_scripts) - script(NAME gipltng.bat INPUT gipltng.bat.in SUBSTITUTE ${SUBST_DICT}) -else() - script(NAME ost_config INPUT ost_config.in SUBSTITUTE ${SUBST_DICT} - TARGET ost_scripts OUTPUT_DIR ${LIBEXEC_PATH}) - script(NAME ost INPUT ost.in SUBSTITUTE ${SUBST_DICT} - TARGET ost_scripts) - if (ENABLE_GUI) - script(NAME dng INPUT dng.in SUBSTITUTE ${SUBST_DICT} +if (NOT ENABLE_STATIC) + if(WIN32) + script(NAME dng.bat INPUT dng.bat.in SUBSTITUTE ${SUBST_DICT} + TARGET ost_scripts) + script(NAME ost.bat INPUT ost.bat.in SUBSTITUTE ${SUBST_DICT} TARGET ost_scripts) + script(NAME gipltng.bat INPUT gipltng.bat.in SUBSTITUTE ${SUBST_DICT}) + else() + script(NAME ost_config INPUT ost_config.in SUBSTITUTE ${SUBST_DICT} + TARGET ost_scripts OUTPUT_DIR ${LIBEXEC_PATH}) + script(NAME ost INPUT ost.in SUBSTITUTE ${SUBST_DICT} + TARGET ost_scripts) + if (ENABLE_GUI) + script(NAME dng INPUT dng.in SUBSTITUTE ${SUBST_DICT} + TARGET ost_scripts) + endif() endif() -endif() -set(INIT_SCRIPTS - init_cl.py -) + set(INIT_SCRIPTS + init_cl.py + ) -if (ENABLE_GUI) - list(APPEND INIT_SCRIPTS init.py) -endif() -copy_if_different("./" "${STAGE_DIR}/${LIB_DIR}/openstructure" + if (ENABLE_GUI) + list(APPEND INIT_SCRIPTS init.py) + endif() + copy_if_different("./" "${STAGE_DIR}/${LIB_DIR}/openstructure" "${INIT_SCRIPTS}" "python init scripts" ost_scripts) -install(FILES ${INIT_SCRIPTS} DESTINATION "${LIB_DIR}/openstructure") + install(FILES ${INIT_SCRIPTS} DESTINATION "${LIB_DIR}/openstructure") +endif() diff --git a/scripts/README.txt b/scripts/README.txt new file mode 100644 index 0000000000000000000000000000000000000000..5258171c4e6d10fd9d21b7c877ddc4db7691d2cc --- /dev/null +++ b/scripts/README.txt @@ -0,0 +1,10 @@ +1. Setup the rpm build environment (See guides on the web) +2. Checkout openstructure source in a fodler called 'openstructure-1.1d' +3. Copy the compounds.chemlib into the folder +4. Remove '.git' and '.gitignore' from the folder +5. COmpress the source with 'tar -cJvf openstructuere.tar.xz openstructure-1.1d' +6. Put the zipped source in '~/rpmbuild/SOURCES' +7. Put the desktop file in '~/rpmbuild/SOURCES' +8. Put the spec file in '~/rpmbuild/SPECS' +9. Go the the 'SPECS' directory and build with 'rpmbuild -ba openstructure.spec' + diff --git a/scripts/ost_config.in b/scripts/ost_config.in index b7b8b7c3ef001947e5310375c787e43e5d936aa6..faaae8e264e655496fe35471dc0bb685c6a6f59b 100644 --- a/scripts/ost_config.in +++ b/scripts/ost_config.in @@ -26,15 +26,13 @@ export DNG_BINDIR="$DNG_ROOT/bin" export DNG_LIBDIR="$DNG_ROOT/@LIBDIR@" export DNG_INITDIR="$DNG_LIBDIR/openstructure" -export PATH="$DNG_BINDIR:$PATH" -export DYLD_FRAMEWORK_PATH="$BIN_LIBDIR:${DYLD_FRAMEWORK_PATH}" -export DYLD_LIBRARY_PATH="$BIN_LIBDIR:${DYLD_LIBRARY_PATH}" -export LD_LIBRARY_PATH="$DNG_LIBDIR:$LD_LIBRARY_PATH" -# set QT_PLUGIN_PATH PYTHONHOME and PYTHONPATH for bundle (commented except in linux bundles) -# set QT_PLUGIN_PATH and pythonpath for bundle (commented except in linux bundles) -#export QT_PLUGIN_PATH="$BIN_DIR/plugins" -#export PYTHONPATH="$DNG_ROOT/@LIBDIR@/python2.6:$OST_ADDITIONAL_PYTHONPATH" +export PATH="$DNG_BINDIR:${PATH}" +export DYLD_FRAMEWORK_PATH="$DNG_LIBDIR:${DYLD_FRAMEWORK_PATH}" +export DYLD_LIBRARY_PATH="$DNG_LIBDIR:${DYLD_LIBRARY_PATH}" +export LD_LIBRARY_PATH="$DNG_LIBDIR:${LD_LIBRARY_PATH}" +# set QT_PLUGIN_PATH and PYTHONPATH for bundle (commented except in linux bundles) #export QT_PLUGIN_PATH="$BIN_DIR/plugins" +#export PYTHONPATH="$DNG_ROOT/@LIBDIR@/python@PYTHON_VERSION@:$OST_ADDITIONAL_PYTHONPATH" # retrieve absolute path to python executable pyexec="@PYTHON_BINARY@"