pax_global_header00006660000000000000000000000064143665477040014532gustar00rootroot0000000000000052 comment=c4dd5b0e1f1971c06c7ab85725c185e47211814e coordgenlibs-3.0.2/000077500000000000000000000000001436654770400142065ustar00rootroot00000000000000coordgenlibs-3.0.2/.azure-pipelines/000077500000000000000000000000001436654770400174005ustar00rootroot00000000000000coordgenlibs-3.0.2/.azure-pipelines/linux_build.yml000066400000000000000000000027501436654770400224450ustar00rootroot00000000000000steps: - bash: | source ${CONDA}/etc/profile.d/conda.sh sudo chown -R ${USER} ${CONDA} conda config --set always_yes yes --set changeps1 no conda update -q conda conda info -a conda create --name coordgen_build $(compiler) cmake \ boost-cpp=$(boost_version) boost=$(boost_version) \ libboost=$(boost_version) displayName: Setup build environment - bash: | source ${CONDA}/etc/profile.d/conda.sh conda activate coordgen_build export BASE_PATH=$(pwd) mkdir build && cd build && \ cmake .. \ -DCMAKE_BUILD_TYPE=Release \ -DCOORDGEN_RIGOROUS_BUILD=ON \ -DBoost_NO_SYSTEM_PATHS=ON \ -DCMAKE_INCLUDE_PATH="${CONDA_PREFIX}/include" \ -DCMAKE_LIBRARY_PATH="${CONDA_PREFIX}/lib" \ -DCMAKE_INSTALL_PREFIX="${BASE_PATH}/install" \ -DCOORDGEN_BUILD_SHARED_LIBS=$(shared_lib) displayName: Configure build (Run CMake) - bash: | source ${CONDA}/etc/profile.d/conda.sh conda activate coordgen_build cd build make -j $( $(number_of_cores) ) install displayName: Build - bash: | source ${CONDA}/etc/profile.d/conda.sh conda activate coordgen_build cd build ctest -j $( $(number_of_cores) ) --output-on-failure -T Test displayName: Run tests - task: PublishTestResults@2 inputs: testResultsFormat: "CTest" testResultsFiles: "build/Testing/*/Test.xml" testRunTitle: $(system.phasedisplayname) CTest Test Run coordgenlibs-3.0.2/.azure-pipelines/mac_build.yml000066400000000000000000000051011436654770400220370ustar00rootroot00000000000000steps: - bash: | wget https://github.com/phracker/MacOSX-SDKs/releases/download/10.15/MacOSX$(target_platform).sdk.tar.xz tar Jxvf MacOSX$(target_platform).sdk.tar.xz displayName: Install MacOSX $(target_platform) SDK - script: | echo "Removing homebrew from Azure to avoid conflicts." curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/uninstall > ~/uninstall_homebrew chmod +x ~/uninstall_homebrew ~/uninstall_homebrew -fq rm ~/uninstall_homebrew displayName: Remove homebrew - bash: | source ${CONDA}/etc/profile.d/conda.sh sudo chown -R ${USER} ${CONDA} echo -e "backend: TkAgg\n" > $HOME/.matplotlib/matplotlibrc conda config --set always_yes yes --set changeps1 no conda update -q conda conda create --name coordgen_build $(compiler) cmake \ boost-cpp=$(boost_version) boost=$(boost_version) \ py-boost=$(boost_version) libboost=$(boost_version) displayName: Setup build environment - bash: | source ${CONDA}/etc/profile.d/conda.sh conda activate coordgen_build export BASE_PATH=$(pwd) export SDKROOT="$(pwd)/MacOSX$(target_platform).sdk/" export CONDA_BUILD_SYSROOT=${SDKROOT} mkdir build && cd build && \ cmake .. \ -DCMAKE_BUILD_TYPE=Release \ -DCOORDGEN_RIGOROUS_BUILD=ON \ -DBoost_NO_SYSTEM_PATHS=ON \ -DCMAKE_OSX_SYSROOT=${SDKROOT} \ -DCMAKE_OSX_DEPLOYMENT_TARGET=$(target_platform) \ -DCMAKE_INCLUDE_PATH="${CONDA_PREFIX}/include" \ -DCMAKE_LIBRARY_PATH="${CONDA_PREFIX}/lib" \ -DCMAKE_INSTALL_PREFIX="${BASE_PATH}/install" \ -DCOORDGEN_BUILD_SHARED_LIBS=$(shared_lib) displayName: Configure build (Run CMake) - bash: | source ${CONDA}/etc/profile.d/conda.sh conda activate coordgen_build export SDKROOT="$(pwd)/MacOSX$(target_platform).sdk/" export CONDA_BUILD_SYSROOT=${SDKROOT} cd build make -j $( $(number_of_cores) ) install displayName: Build - bash: | source ${CONDA}/etc/profile.d/conda.sh conda activate coordgen_build export DYLD_FALLBACK_LIBRARY_PATH=${CONDA_PREFIX}/lib:${DYLD_FALLBACK_LIBRARY_PATH} export SDKROOT="$(pwd)/MacOSX$(target_platform).sdk/" export CONDA_BUILD_SYSROOT=${SDKROOT} cd build ctest -j $( $(number_of_cores) ) --output-on-failure -T Test displayName: Run tests - task: PublishTestResults@2 inputs: testResultsFormat: "CTest" testResultsFiles: "build/Testing/*/Test.xml" testRunTitle: $(system.phasedisplayname) CTest Test Run coordgenlibs-3.0.2/.azure-pipelines/vs_build.yml000066400000000000000000000030641436654770400217350ustar00rootroot00000000000000steps: - powershell: Write-Host "##vso[task.prependpath]$env:CONDA\Scripts" displayName: Setup build environment - script: | conda config --set always_yes yes --set changeps1 no conda info -a conda create --name coordgen_build $(compiler) cmake ^ boost-cpp=$(boost_version) boost=$(boost_version) ^ py-boost=$(boost_version) libboost=$(boost_version) displayName: Install dependencies - script: | set Boost_ROOT= set BASE_PATH=%cd% mkdir build && cd build call activate coordgen_build cmake .. ^ -G "Visual Studio 16 2019" ^ -DCMAKE_BUILD_TYPE=Release ^ -DCOORDGEN_RIGOROUS_BUILD=ON ^ -DBoost_NO_SYSTEM_PATHS=ON ^ -DCMAKE_INCLUDE_PATH=%CONDA_PREFIX%/Library/include ^ -DCMAKE_LIBRARY_PATH=%CONDA_PREFIX%/Library/lib ^ -DCMAKE_INSTALL_PREFIX=%BASE_PATH%/install ^ -DCOORDGEN_BUILD_SHARED_LIBS=$(shared_lib) ^ -DBoost_LIB_PREFIX="$(boost_lib_prefix)" displayName: Configure build (Run CMake) - script: | call activate coordgen_build cd build cmake --build . --config Release --target install -j $(number_of_cores) displayName: Build - script: | call activate coordgen_build set PATH=%cd%/install/bin;%PATH% cd build ctest -j $(number_of_cores) --output-on-failure -T Test -C Release displayName: Run tests - task: PublishTestResults@2 inputs: testResultsFormat: "CTest" testResultsFiles: "build/Testing/*/Test.xml" testRunTitle: $(system.phasedisplayname) CTest Test Run coordgenlibs-3.0.2/.clang-format000066400000000000000000000035271436654770400165700ustar00rootroot00000000000000--- Language: Cpp AccessModifierOffset: -2 ConstructorInitializerIndentWidth: 4 AlignEscapedNewlinesLeft: false AlignTrailingComments: true AllowAllParametersOfDeclarationOnNextLine: true AllowShortBlocksOnASingleLine: false AllowShortCaseLabelsOnASingleLine: false AllowShortIfStatementsOnASingleLine: false AllowShortLoopsOnASingleLine: false AllowShortFunctionsOnASingleLine: Inline AlwaysBreakAfterDefinitionReturnType: false AlwaysBreakTemplateDeclarations: false AlwaysBreakBeforeMultilineStrings: false BreakBeforeBraces: Linux BreakBeforeBinaryOperators: None BreakBeforeTernaryOperators: true BreakConstructorInitializersBeforeComma: false BinPackParameters: true BinPackArguments: true ColumnLimit: 80 ConstructorInitializerAllOnOneLineOrOnePerLine: false DerivePointerAlignment: false ExperimentalAutoDetectBinPacking: false IndentCaseLabels: false IndentWrappedFunctionNames: false IndentFunctionDeclarationAfterType: false MaxEmptyLinesToKeep: 1 KeepEmptyLinesAtTheStartOfBlocks: true NamespaceIndentation: None ObjCSpaceAfterProperty: false ObjCSpaceBeforeProtocolList: true PenaltyBreakBeforeFirstCallParameter: 19 PenaltyBreakComment: 300 PenaltyBreakString: 1000 PenaltyBreakFirstLessLess: 120 PenaltyExcessCharacter: 1000000 PenaltyReturnTypeOnItsOwnLine: 60 PointerAlignment: Left SpacesBeforeTrailingComments: 1 Cpp11BracedListStyle: true Standard: Cpp11 IndentWidth: 4 TabWidth: 8 UseTab: Never SpacesInParentheses: false SpacesInSquareBrackets: false SpacesInAngles: false SpaceInEmptyParentheses: false SpacesInCStyleCastParentheses: false SpaceAfterCStyleCast: true SpacesInContainerLiterals: true SpaceBeforeAssignmentOperators: true ContinuationIndentWidth: 4 CommentPragmas: '^ IWYU pragma:' ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ] SpaceBeforeParens: ControlStatements DisableFormat: false ... coordgenlibs-3.0.2/.gitignore000066400000000000000000000000551436654770400161760ustar00rootroot00000000000000*.build *.pro *.swp *.xc* Debug build qt*.mk coordgenlibs-3.0.2/CMakeLists.txt000066400000000000000000000107221436654770400167500ustar00rootroot00000000000000cmake_minimum_required(VERSION 3.2) project(coordgen) set(CMAKE_CXX_STANDARD 11) set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake) # Options option(COORDGEN_RIGOROUS_BUILD "Abort the build if the compiler issues \ any warnings" ON ) option(COORDGEN_BUILD_TESTS "Whether test executables should be built" ON) option(COORDGEN_BUILD_EXAMPLE "Whether to build the sample executable" ON) option(COORDGEN_USE_MAEPARSER "Whether to allow loading of run-time templates" OFF) option(COORDGEN_BUILD_SHARED_LIBS "Build coordgen as a shared library \ (turn off for a static one)" ON) option(DEBUG_COORDS "Whether to print minimization data and atom mapping to file" OFF) # Use the maeparser_DIR variable to tell CMake where to search for the # maeparser library. if (COORDGEN_USE_MAEPARSER OR COORDGEN_BUILD_TESTS) set(USE_MAEPARSER ON) else() set(USE_MAEPARSER OFF) endif() if (USE_MAEPARSER) set(MAEPARSER_VERSION "master" CACHE STRING "maeparser tag to build if \ a compiled library is not found") endif() if(MSVC) # C4251 disables warnings for export STL containers as arguments # (returning a vector of things) add_definitions(/wd4251 /wd4275 /wd4996 /D_SCL_SECURE_NO_WARNINGS /D_CRT_SECURE_NO_WARNINGS) add_definitions(-DBOOST_ALL_NO_LIB) endif(MSVC) if(COORDGEN_RIGOROUS_BUILD) if(MSVC) add_definitions(/WX) else(MSVC) add_definitions(-Wall -Wextra -Werror) endif(MSVC) endif(COORDGEN_RIGOROUS_BUILD) # Source files & headers file(GLOB SOURCES "*.cpp") # Build Targets & Configuration -- coordgen library if(COORDGEN_BUILD_SHARED_LIBS) add_library(coordgen SHARED ${SOURCES}) target_compile_definitions(coordgen PRIVATE "IN_COORDGEN") set_property(TARGET coordgen PROPERTY CXX_VISIBILITY_PRESET "hidden") else(COORDGEN_BUILD_SHARED_LIBS) add_library(coordgen STATIC ${SOURCES}) if (USE_MAEPARSER) target_compile_definitions(coordgen PRIVATE "STATIC_MAEPARSER") endif(USE_MAEPARSER) target_compile_definitions(coordgen PRIVATE "STATIC_COORDGEN") endif(COORDGEN_BUILD_SHARED_LIBS) if (DEBUG_COORDS) target_compile_definitions(coordgen PRIVATE "DEBUG_MINIMIZATION_COORDINATES") endif() # Dependencies if (USE_MAEPARSER) if(TARGET maeparser) message(STATUS "Using externally defined maeparser target to " "build coordgen") else() include(CoordgenUtils) set(MAEPARSER_BUILD_SHARED_LIBS ${COORDGEN_BUILD_SHARED_LIBS} CACHE BOOL "Library type for maeparser") find_or_clone_maeparser() endif() include_directories(${maeparser_INCLUDE_DIRS}) find_package(Boost REQUIRED) include_directories(${Boost_INCLUDE_DIRS}) endif (USE_MAEPARSER) if (COORDGEN_USE_MAEPARSER) target_link_libraries(coordgen ${maeparser_LIBRARIES}) target_compile_definitions(coordgen PRIVATE "USE_MAEPARSER") endif() set_target_properties(coordgen PROPERTIES VERSION 3.0.2 SOVERSION 3 ) if(MSVC) set(CMAKE_INSTALL_LIBDIR lib) set(CMAKE_INSTALL_BINDIR bin) else(MSVC) include(GNUInstallDirs) endif(MSVC) # Install configuration install(TARGETS coordgen EXPORT coordgen-targets ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}) install(FILES CoordgenConfig.hpp CoordgenFragmentBuilder.h CoordgenFragmenter.h CoordgenMacrocycleBuilder.h CoordgenMinimizer.h sketcherMinimizerAtom.h sketcherMinimizerBendInteraction.h sketcherMinimizerBond.h sketcherMinimizerClashInteraction.h sketcherMinimizerEZConstrainInteraction.h sketcherMinimizerFragment.h sketcherMinimizer.h sketcherMinimizerInteraction.h sketcherMinimizerMarchingSquares.h sketcherMinimizerMaths.h sketcherMinimizerMolecule.h sketcherMinimizerResidue.h sketcherMinimizerResidueInteraction.h sketcherMinimizerRing.h sketcherMinimizerStretchInteraction.h DESTINATION include/coordgen) install(EXPORT coordgen-targets FILE ${PROJECT_NAME}-config.cmake DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake) # Example if(COORDGEN_BUILD_EXAMPLE) add_subdirectory(example_dir) endif(COORDGEN_BUILD_EXAMPLE) # Tests if(COORDGEN_BUILD_TESTS) set(MEMORYCHECK_COMMAND_OPTIONS "--tool=memcheck --time-stamp=yes \ --num-callers=20 --gen-suppressions=all --leak-check=full \ --show-reachable=no --trace-children=yes --error-exitcode=29") include(CTest) add_subdirectory(test) endif(COORDGEN_BUILD_TESTS) coordgenlibs-3.0.2/CoordgenConfig.hpp000066400000000000000000000005221436654770400176040ustar00rootroot00000000000000#pragma once #ifndef STATIC_COORDGEN #ifdef WIN32 #ifdef IN_COORDGEN #define EXPORT_COORDGEN __declspec(dllexport) #else #define EXPORT_COORDGEN __declspec(dllimport) #endif // IN_COORDGEN #else #define EXPORT_COORDGEN __attribute__((visibility("default"))) #endif // WIN32 #else #define EXPORT_COORDGEN #endif // STATIC_COORDGEN coordgenlibs-3.0.2/CoordgenFragmentBuilder.cpp000066400000000000000000001161561436654770400214570ustar00rootroot00000000000000/* Contributors: Nicola Zonta Copyright Schrodinger, LLC. All rights reserved */ #include #include #include #include "CoordgenFragmentBuilder.h" #include "CoordgenMinimizer.h" #include "sketcherMinimizer.h" #include "sketcherMinimizerFragment.h" #include "sketcherMinimizerRing.h" #include "sketcherMinimizerStretchInteraction.h" using namespace std; const int bondLength = BONDLENGTH; const int PERFECTLY_PLANAR_SYSTEM_SCORE = 50; const int NON_PLANAR_SYSTEM_SCORE = 1000; const int UNTREATABLE_SYSTEM_PLANARITY_SCORE = 200000; const int MACROCYCLE_CENTRAL_RING_SCORE = 1000; const int NUMBER_OF_FUSED_RINGS_CENTRAL_RING_SCORE = 40; const int NUMBER_OF_FUSION_ATOMS_CENTRAL_RING_SCORE = 15; const int NEIGHBOR_ALREADY_BUILT_RING_SCORE = 100000; void CoordgenFragmentBuilder::initializeCoordinates( sketcherMinimizerFragment* fragment) const { assert(!fragment->getAtoms().empty()); buildFragment(fragment); fragment->storeCoordinateInformation(); } void CoordgenFragmentBuilder::rotateMainFragment( sketcherMinimizerFragment* f) const { if (f->fixed) { return; } if (f->isTemplated) { return; } if (!f->constrained) { return; } sketcherMinimizerPointF constrainOldCenter(0.f, 0.f); sketcherMinimizerPointF constrainNewCenter(0.f, 0.f); vector constrainedAtoms; for (const auto& atom : f->getAtoms()) { if (atom->constrained) { constrainedAtoms.push_back(atom); } } for (const auto& child : f->_children) { sketcherMinimizerAtom* atom = child->_bondToParent->endAtom; if (atom->constrained) { constrainedAtoms.push_back(atom); } } for (const auto& a : constrainedAtoms) { constrainOldCenter += a->templateCoordinates; constrainNewCenter += a->coordinates; } if (!constrainedAtoms.empty()) { constrainOldCenter /= constrainedAtoms.size(); constrainNewCenter /= constrainedAtoms.size(); } vector v1, v2; for (const auto& a : constrainedAtoms) { v2.push_back(a->coordinates - constrainNewCenter); v1.push_back(a->templateCoordinates - constrainOldCenter); } float rotMat[4]; sketcherMinimizer::alignmentMatrix(v1, v2, rotMat); vector rotatedV2; for (const auto& p : v2) { auto rotatedPoint = sketcherMinimizerPointF(p.x() * rotMat[0] + p.y() * rotMat[1], p.x() * rotMat[2] + p.y() * rotMat[3]); rotatedV2.push_back(rotatedPoint); } for (sketcherMinimizerAtom* a : f->getAtoms()) { sketcherMinimizerPointF v = a->getCoordinates() - constrainNewCenter; v = sketcherMinimizerPointF(v.x() * rotMat[0] + v.y() * rotMat[1], v.x() * rotMat[2] + v.y() * rotMat[3]); a->setCoordinates(v + constrainOldCenter); } for (sketcherMinimizerFragment* child : f->_children) { sketcherMinimizerAtom* at = child->_bondToParent->endAtom; sketcherMinimizerPointF v = at->getCoordinates() - constrainNewCenter; v = sketcherMinimizerPointF(v.x() * rotMat[0] + v.y() * rotMat[1], v.x() * rotMat[2] + v.y() * rotMat[3]); at->setCoordinates(v + constrainOldCenter); at->coordinatesSet = false; } } bool CoordgenFragmentBuilder::findTemplate( const vector& rings) const { vector allAtoms = rings[0]->_atoms[0]->fragment->getAtoms(); bool foundTemplate = false; sketcherMinimizer::loadTemplates(); vector atoms; vector bonds; map isVisited; vector oldIndices; for (sketcherMinimizerRing* r : rings) { for (sketcherMinimizerAtom* a : r->_atoms) { if (!isVisited[a]) { isVisited[a] = true; oldIndices.push_back(a->_generalUseN); a->_generalUseN = static_cast(atoms.size()); atoms.push_back(a); } } } for (sketcherMinimizerRing* r : rings) { for (sketcherMinimizerBond* b : r->_bonds) { bool found = false; for (sketcherMinimizerBond* b2 : bonds) { if (b2 == b) { found = true; break; } } if (!found) { bonds.push_back(b); } } } vector mapping; for (auto& temp : sketcherMinimizer::m_templates.getTemplates()) { foundTemplate = sketcherMinimizer::compare(atoms, bonds, temp, mapping); if (foundTemplate) { if (!atoms.empty()) { atoms[0]->fragment->isTemplated = true; } for (unsigned int i = 0; i < atoms.size(); i++) { atoms[i]->setCoordinates(temp->_atoms[mapping[i]]->coordinates * bondLength); atoms[i]->rigid = true; } for (sketcherMinimizerRing* r : rings) { r->coordinatesGenerated = true; } break; } } for (unsigned int i = 0; i < oldIndices.size(); i++) { atoms[i]->_generalUseN = oldIndices[i]; } return foundTemplate; } sketcherMinimizerRing* CoordgenFragmentBuilder::findCentralRingOfSystem( const vector& rings) const { sketcherMinimizerRing* highest = nullptr; size_t high_score = 0; for (sketcherMinimizerRing* r : rings) { size_t priority = 0; /*keep growing the system building rings neighboring already built * rings*/ for (auto neighborRing : r->fusedWith) { if (neighborRing->coordinatesGenerated) { priority += NEIGHBOR_ALREADY_BUILT_RING_SCORE; break; } } if (r->isMacrocycle()) { priority += MACROCYCLE_CENTRAL_RING_SCORE; } if (r->_atoms.size() == 6) { priority += 10; } priority += r->_atoms.size(); priority += NUMBER_OF_FUSED_RINGS_CENTRAL_RING_SCORE * (r->fusedWith.size()); for (auto fusionAtoms : r->fusionAtoms) { priority += NUMBER_OF_FUSION_ATOMS_CENTRAL_RING_SCORE * fusionAtoms.size(); } if (priority > high_score || highest == nullptr) { highest = r; high_score = priority; } } if (highest == nullptr) { return rings.at(0); } return highest; } void CoordgenFragmentBuilder::generateCoordinatesCentralRings( vector rings) const { if (rings.size() == 1) { // linearfusedRings buildRing(rings[0]); } else { bool foundTemplate = findTemplate(rings); if (!foundTemplate) { float planarityScore = newScorePlanarity(rings); if (planarityScore < NON_PLANAR_SYSTEM_SCORE) { bool needsTemplate = planarityScore > PERFECTLY_PLANAR_SYSTEM_SCORE; if (needsTemplate) { findTemplate(rings); } while (!rings.empty()) { auto centralRing = findCentralRingOfSystem(rings); buildRing(centralRing); rings.erase( std::remove(rings.begin(), rings.end(), centralRing), rings.end()); } CoordgenMinimizer::maybeMinimizeRings(rings); } else if (planarityScore > UNTREATABLE_SYSTEM_PLANARITY_SCORE) { return; } else { sketcherMinimizerRing* firstRing = findCentralRingOfSystem(rings); m_macrocycleBuilder.openCycleAndGenerateCoords(firstRing); firstRing->getAtoms() .at(0) ->getMolecule() ->requireMinimization(); } } } } float CoordgenFragmentBuilder::newScorePlanarity( const vector& rings) const // if score > 1000 then it is not planar { float score = 0.f; for (const auto& ring : rings) { if (ring->isMacrocycle() && m_macrocycleBuilder.findBondToOpen(ring) == nullptr) { continue; } if (ring->isMacrocycle()) { for (const auto& otherRing : ring->fusedWith) { if (otherRing->isMacrocycle()) { score += NON_PLANAR_SYSTEM_SCORE; } } } for (const auto& bond : ring->_bonds) { if (bond->rings.size() > 2) { score += NON_PLANAR_SYSTEM_SCORE * (bond->rings.size() - 2); } } for (const auto& atom : ring->getAtoms()) { if (atom->neighbors.size() > 3) { float angle = 0; for (sketcherMinimizerRing* r : atom->rings) { angle += static_cast(M_PI - (2 * M_PI / r->_atoms.size())); } if (angle >= 1.99 * M_PI) { score += NON_PLANAR_SYSTEM_SCORE; } } } } return score; } void CoordgenFragmentBuilder::generateCoordinatesSideRings( stack sideRings) const { while (!sideRings.empty()) { sketcherMinimizerRing* ring = sideRings.top(); sideRings.pop(); buildRing(ring); } } sketcherMinimizerRing* CoordgenFragmentBuilder::getSharedAtomsWithAlreadyDrawnRing( const sketcherMinimizerRing* ring, vector& fusionAtoms, sketcherMinimizerBond*& fusionBond) const { sketcherMinimizerRing* parent = nullptr; for (auto i : ring->fusedWith) { if (i->coordinatesGenerated) { if (parent != nullptr) { if (i->getFusionAtomsWith(ring).size() < parent->getFusionAtomsWith(ring).size() || (i->size() < parent->size())) continue; } parent = i; } } if (parent) { for (unsigned int i = 0; i < parent->fusedWith.size(); i++) { if (parent->fusedWith[i] == ring) { fusionAtoms = parent->fusionAtoms[i]; } } for (sketcherMinimizerBond* b : parent->fusionBonds) { if (ring->containsAtom(b->startAtom) || ring->containsAtom(b->endAtom)) { fusionBond = b; break; } } } return parent; } vector CoordgenFragmentBuilder::orderChainOfAtoms( const vector& atoms, sketcherMinimizerAtom* startAtom) { vector orderedAtoms; map stillToAdd; for (sketcherMinimizerAtom* a : atoms) { stillToAdd[a] = true; } sketcherMinimizerAtom* atomToAdd = startAtom; while (orderedAtoms.size() < atoms.size()) { orderedAtoms.push_back(atomToAdd); stillToAdd[atomToAdd] = false; if (orderedAtoms.size() >= atoms.size()) { break; } for (sketcherMinimizerAtom* neighbor : atomToAdd->neighbors) { if (stillToAdd[neighbor]) { atomToAdd = neighbor; break; } } } return orderedAtoms; } vector CoordgenFragmentBuilder::orderRingAtoms(const sketcherMinimizerRing* ring) { vector ringAtoms = ring->getAtoms(); assert(!ringAtoms.empty()); return orderChainOfAtoms(ringAtoms, ringAtoms.at(0)); } void CoordgenFragmentBuilder::buildRing(sketcherMinimizerRing* ring) const { if (ring->coordinatesGenerated) { return; } vector atoms; sketcherMinimizerRing* parent = nullptr; sketcherMinimizerBond* fusionBond = nullptr; vector fusionAtoms; parent = getSharedAtomsWithAlreadyDrawnRing(ring, fusionAtoms, fusionBond); atoms = orderRingAtoms(ring); vector coords; if (atoms.size() >= MACROCYCLE) { coords = m_macrocycleBuilder.newMacrocycle(ring, atoms); } else { coords = listOfCoordinatesFromListofRingAtoms(atoms); } if (parent) { if (fusionAtoms.size() < 2) { sketcherMinimizerPointF coordinatesOfPivotAtom; sketcherMinimizerAtom* pivotAtom = nullptr; sketcherMinimizerAtom* pivotAtomOnParent = nullptr; if (!fusionAtoms.empty()) { pivotAtom = fusionAtoms.at(0); pivotAtomOnParent = fusionAtoms.at(0); } else { assert(fusionBond != nullptr); if (find(atoms.begin(), atoms.end(), fusionBond->getStartAtom()) != atoms.end()) { pivotAtom = fusionBond->getStartAtom(); pivotAtomOnParent = fusionBond->getEndAtom(); } else { pivotAtom = fusionBond->getEndAtom(); pivotAtomOnParent = fusionBond->getStartAtom(); } } assert(find(atoms.begin(), atoms.end(), pivotAtom) != atoms.end()); assert(parent->containsAtom(pivotAtomOnParent)); for (unsigned int i = 0; i < atoms.size(); i++) { if (atoms[i] == pivotAtom) { coordinatesOfPivotAtom = coords[i]; break; } } for (auto& coord : coords) { coord -= coordinatesOfPivotAtom; } sketcherMinimizerPointF center = accumulate(coords.begin(), coords.end(), sketcherMinimizerPointF(0, 0)) / coords.size(); center.normalize(); sketcherMinimizerPointF neighborsMean(0.f, 0.f); for (sketcherMinimizerAtom* neighbor : pivotAtomOnParent->neighbors) { if (parent->containsAtom(neighbor)) { neighborsMean += neighbor->getCoordinates(); } } neighborsMean *= 0.5; sketcherMinimizerPointF pivotAtomCoordinates = pivotAtomOnParent->getCoordinates(); sketcherMinimizerPointF direction = pivotAtomCoordinates - neighborsMean; direction.normalize(); sketcherMinimizerPointF bondVector(0.f, 0.f); if (fusionBond != nullptr) { bondVector = direction * bondLength; } for (auto& coord : coords) { sketcherMinimizerPointF coordinates = coord; coordinates.rotate(center.y(), center.x()); coordinates.rotate(-direction.y(), direction.x()); coord = coordinates + pivotAtomCoordinates + bondVector; } for (unsigned int i = 0; i < coords.size(); i++) { atoms[i]->setCoordinates(coords[i]); } if (fusionBond) { // check ZE inversions if (!fusionBond->checkStereoChemistry()) { for (sketcherMinimizerAtom* atom : atoms) { sketcherMinimizerAtom::mirrorCoordinates(atom, fusionBond); } } } } else { // build 2 lists of coordinates, mirror of each other. vector coords2 = coords; for (auto& i : coords2) { i = sketcherMinimizerPointF(i.x(), -i.y()); } map map1, map2; for (unsigned int i = 0; i < atoms.size(); i++) { map1[atoms[i]] = coords[i]; map2[atoms[i]] = coords2[i]; } assert(!fusionAtoms.empty()); size_t lastI = fusionAtoms.size() - 1; sketcherMinimizerPointF mean = (fusionAtoms[0]->coordinates + fusionAtoms[lastI]->coordinates) * 0.5; sketcherMinimizerPointF newMean = (map1[fusionAtoms[0]] + map1[fusionAtoms[lastI]]) * 0.5; sketcherMinimizerPointF v = fusionAtoms[lastI]->coordinates - fusionAtoms[0]->coordinates; float distance = v.length(); if (distance < SKETCHER_EPSILON) { distance = SKETCHER_EPSILON; } float sine = v.y() / distance; float cosine = v.x() / distance; sketcherMinimizerPointF newV = (map1[fusionAtoms[lastI]] - map1[fusionAtoms[0]]); float newDistance = newV.length(); float newSine = newV.y() / newDistance; float newCosine = newV.x() / newDistance; for (unsigned int i = 0; i < atoms.size(); i++) { // rotate and translate coords sketcherMinimizerPointF d = coords[i] - newMean; d.rotate(newSine, newCosine); d.rotate(-sine, cosine); coords[i] = mean + d; } newV = (map2[fusionAtoms[lastI]] - map2[fusionAtoms[0]]); newMean = (map2[fusionAtoms[0]] + map2[fusionAtoms[lastI]]) * 0.5; newDistance = newV.length(); newSine = newV.y() / newDistance; newCosine = newV.x() / newDistance; for (unsigned int i = 0; i < atoms.size(); i++) { // rotate and translate coords2 sketcherMinimizerPointF d = coords2[i] - newMean; d.rotate(newSine, newCosine); d.rotate(-sine, cosine); coords2[i] = mean + d; } // pick the list of coordinates that will place the ring outside the // parent i.e further away from its center. sketcherMinimizerPointF center = parent->findCenter(); map fusionMap; for (auto fusionAtom : fusionAtoms) { fusionMap[fusionAtom] = true; } float distance1 = 0.f, distance2 = 0.f; for (unsigned int i = 0; i < atoms.size(); i++) { if (fusionMap[atoms[i]]) { continue; } sketcherMinimizerPointF v1 = coords[i] - center; sketcherMinimizerPointF v2 = coords2[i] - center; distance1 += v1.length(); distance2 += v2.length(); } vector* targetCoords = &coords; if (distance1 < distance2) { targetCoords = &coords2; } for (unsigned int i = 0; i < atoms.size(); i++) { atoms[i]->setCoordinates((*targetCoords)[i]); } } } else { for (unsigned int i = 0; i < coords.size(); i++) { atoms[i]->setCoordinates(coords[i]); } } ring->coordinatesGenerated = true; } vector CoordgenFragmentBuilder::listOfCoordinatesFromListofRingAtoms( const vector& atoms) { vector out; assert(!atoms.empty()); auto a = static_cast(2 * M_PI / atoms.size()); sketcherMinimizerPointF coords(0.f, 0.f); float angle = 0; for (unsigned int n = 0; n < atoms.size(); n++) { out.push_back(coords); angle = a * n; coords += sketcherMinimizerPointF(cos(angle) * bondLength, -sin(angle) * bondLength); } return out; } void CoordgenFragmentBuilder::buildNonRingAtoms( sketcherMinimizerFragment* fragment) const { set isAtomVisited; queue q; for (sketcherMinimizerAtom* atom : fragment->getAtoms()) { if (!atom->getRings().empty()) { q.push(atom); isAtomVisited.insert(atom); } } if (q.empty()) { if (fragment->getParent()) { fragment->_bondToParent->getStartAtom()->setCoordinates( sketcherMinimizerPointF(-bondLength, 0)); } sketcherMinimizerAtom* atomToStartFrom = (fragment->getParent() ? fragment->_bondToParent->getEndAtom() : fragment->getAtoms()[0]); atomToStartFrom->setCoordinates(sketcherMinimizerPointF(0, 0)); q.push(atomToStartFrom); isAtomVisited.insert(atomToStartFrom); } while (!q.empty()) { generateCoordinatesNeighborsOfFirstAtomInQueue(q, isAtomVisited, fragment); } } vector CoordgenFragmentBuilder::neighborsAnglesAtCenter( const sketcherMinimizerAtom* atom) const { size_t angleDivision = atom->neighbors.size(); vector angles; if (!m_evenAngles) { if (atom->neighbors.size() == 2) { if (atom->getAtomicNumber() == 6 || !atom->neighbors.at(0)->crossLayout || !atom->neighbors.at(1)->crossLayout) { angleDivision = 3; } if (atom->bonds[0]->getBondOrder() + atom->bonds[1]->getBondOrder() >= 4) { angleDivision = 2; } } else if (atom->neighbors.size() == 4 && !atom->crossLayout) { angles.push_back(static_cast(M_PI / 3)); angles.push_back(static_cast(M_PI * 0.5)); angles.push_back(static_cast(2 * M_PI / 3)); angles.push_back(static_cast(M_PI * 0.5)); } } if (angles.empty()) { for (unsigned int i = 0; i < atom->neighbors.size(); i++) { angles.push_back(static_cast(2 * M_PI / angleDivision)); } } return angles; } void CoordgenFragmentBuilder::initializeVariablesForNeighboursCoordinates( sketcherMinimizerAtom* atom, set& isAtomVisited, sketcherMinimizerPointF& startCoordinates, vector& orderedNeighbors, vector& angles) const { if (!atom->rings.empty()) { return initializeVariablesForNeighboursCoordinatesRingAtom( atom, isAtomVisited, startCoordinates, orderedNeighbors, angles); } orderedNeighbors.clear(); if (atom->neighbors.size() != 4) { orderedNeighbors = atom->neighbors; } else { vector atomPriorities; for (auto& neighbor : atom->neighbors) { sketcherMinimizerAtomPriority p; p.a = neighbor; atomPriorities.push_back(p); } sketcherMinimizerAtom::orderAtomPriorities(atomPriorities, atom); for (sketcherMinimizerAtomPriority ap : atomPriorities) { orderedNeighbors.push_back(ap.a); } } unsigned int startN = 0; for (unsigned int i = 0; i < orderedNeighbors.size(); i++) { if (isAtomVisited.find(orderedNeighbors[i]) != isAtomVisited.end()) { startCoordinates = orderedNeighbors[i]->getCoordinates() - atom->getCoordinates(); startN = i; break; } } for (unsigned int i = 0; i < startN; i++) { orderedNeighbors.push_back(orderedNeighbors.at(0)); orderedNeighbors.erase(orderedNeighbors.begin()); } angles = neighborsAnglesAtCenter(atom); } void CoordgenFragmentBuilder:: initializeVariablesForNeighboursCoordinatesRingAtom( const sketcherMinimizerAtom* atom, set&, sketcherMinimizerPointF& startCoordinates, vector& orderedNeighbors, vector& angles) const { vector> ringNeighboursAndAngles; orderedNeighbors.clear(); for (sketcherMinimizerAtom* neigh : atom->neighbors) { if (sketcherMinimizer::sameRing(neigh, atom)) { float ang = atan2(neigh->coordinates.y() - atom->coordinates.y(), neigh->coordinates.x() - atom->coordinates.x()); if (ang < 0) { ang += static_cast(2 * M_PI); } pair pairToAdd(ang, neigh); ringNeighboursAndAngles.push_back(pairToAdd); } else { orderedNeighbors.push_back(neigh); } } stable_sort(ringNeighboursAndAngles.begin(), ringNeighboursAndAngles.end()); vector gaps; vector scaledGaps; for (unsigned int i = 0; i < ringNeighboursAndAngles.size(); i++) { int next = (i + 1) % ringNeighboursAndAngles.size(); float gap = ringNeighboursAndAngles[next].first - ringNeighboursAndAngles[i].first; if (gap < 0) { gap += static_cast(2 * M_PI); } gaps.push_back(gap); bool rin = false; float mid = ringNeighboursAndAngles[i].first + gap * 0.5f; float sine = sin(-mid); float cosine = cos(-mid); sketcherMinimizerPointF p(bondLength * 0.1f, 0); p.rotate(sine, cosine); sketcherMinimizerPointF point = atom->coordinates + p; vector rings = atom->getFragment()->getRings(); for (sketcherMinimizerRing* r : rings) { if (r->isMacrocycle()) { continue; } if (r->contains(point)) { rin = true; break; } } float scaledGap = gap; if (gap > M_PI) { scaledGap *= 10.f; } else if (rin) { scaledGap *= 0.2f; } scaledGaps.push_back(scaledGap); } int bestI = 0; for (unsigned int i = 0; i < gaps.size(); i++) { if (scaledGaps[i] > scaledGaps[bestI]) { bestI = i; } } angles.clear(); float biggestGap = gaps[bestI]; startCoordinates = ringNeighboursAndAngles[bestI].second->getCoordinates() - atom->getCoordinates(); for (unsigned int i = 0; i < orderedNeighbors.size(); i++) { angles.push_back(-biggestGap / (orderedNeighbors.size() + 1)); } } void CoordgenFragmentBuilder::generateCoordinatesNeighborsOfFirstAtomInQueue( queue& atomQueue, set& isAtomVisited, const sketcherMinimizerFragment* fragment) const { sketcherMinimizerAtom* at = atomQueue.front(); atomQueue.pop(); sketcherMinimizerPointF initialCoords(-bondLength, 0.f); vector orderedNeighbors; vector angles; initializeVariablesForNeighboursCoordinates( at, isAtomVisited, initialCoords, orderedNeighbors, angles); for (unsigned int i = 0; i < orderedNeighbors.size(); i++) { int n = i; sketcherMinimizerAtom* neigh = orderedNeighbors[n]; if (isAtomVisited.find(neigh) != isAtomVisited.end()) { continue; } float s = sin(angles[n]); float c = cos(angles[n]); initialCoords.rotate(s, c); neigh->setCoordinates(at->coordinates + initialCoords); if (neigh->fragment == fragment) { isAtomVisited.insert(neigh); atomQueue.push(neigh); } else { neigh->coordinatesSet = false; } if (at->needsCheckForClashes) { neigh->needsCheckForClashes = true; CoordgenMinimizer::checkForClashes(neigh); } for (auto& dof : at->fragment->getDofsOfAtom(at)) { if (dof->getFragment() == fragment) { dof->addAtom(neigh); } } } avoidZEInversions(at, isAtomVisited); maybeAddMacrocycleDOF(at); for (auto& neighbor : at->neighbors) { if (!sketcherMinimizerAtom::shareARing(at, neighbor) && at->getFragment() == neighbor->getFragment()) { auto* dof = new CoordgenScaleAtomsDOF(at); dof->addAtom(neighbor); at->fragment->addDof(dof); } } } void CoordgenFragmentBuilder::maybeAddMacrocycleDOF( sketcherMinimizerAtom* atom) const { if (atom->getRings().size() == 1 && atom->getRings().at(0)->isMacrocycle() && atom->neighbors.size() == 3) { for (auto& bond : atom->getBonds()) { if (bond->isStereo() && !bond->isTerminal()) { return; } } for (auto& neighbor : atom->neighbors) { if (!sketcherMinimizerAtom::shareARing(atom, neighbor)) { auto* dof = new CoordgenInvertBondDOF(atom, neighbor); atom->fragment->addDof(dof); } } } } void CoordgenFragmentBuilder::avoidZEInversions( const sketcherMinimizerAtom* at, set& isAtomVisited) const { if (!at->getRings().empty()) { return; } sketcherMinimizerBond* doubleBond = nullptr; vector atomsToMirror; for (unsigned int i = 0; i < at->bonds.size(); i++) { if (at->bonds[i]->isStereo() && isAtomVisited.find(at->neighbors[i]) != isAtomVisited.end()) { doubleBond = at->bonds[i]; } else { atomsToMirror.push_back(at->neighbors[i]); } } if (doubleBond == nullptr) { return; } if (!atomsToMirror.empty() && doubleBond) { sketcherMinimizerAtom* firstCIPNeighborStart = doubleBond->startAtomCIPFirstNeighbor(); if (firstCIPNeighborStart == nullptr) { return; } sketcherMinimizerAtom* firstCIPNeighborEnd = doubleBond->endAtomCIPFirstNeighbor(); if (firstCIPNeighborEnd == nullptr) { return; } if (!doubleBond->checkStereoChemistry()) { for (sketcherMinimizerAtom* a : atomsToMirror) { sketcherMinimizerAtom::mirrorCoordinates(a, doubleBond); } } } } void CoordgenFragmentBuilder::buildFragment( sketcherMinimizerFragment* fragment) const { buildRings(fragment); buildNonRingAtoms(fragment); CoordgenMinimizer::avoidInternalClashes(fragment); fallbackIfNanCoordinates(fragment); if (!fragment->getParent() && fragment->constrained) { rotateMainFragment(fragment); } // reset coordinates for fixed fragments: if (fragment->fixed) { fragment->setAllCoordinatesToTemplate(); } } void CoordgenFragmentBuilder::fallbackIfNanCoordinates( sketcherMinimizerFragment* fragment) const { vector fragmentAtoms = fragment->getAtoms(); if (CoordgenMinimizer::hasNaNCoordinates(fragmentAtoms) && CoordgenMinimizer::hasValid3DCoordinates(fragmentAtoms)) { CoordgenMinimizer::fallbackOn3DCoordinates(fragmentAtoms); } } void CoordgenFragmentBuilder::initializeFusedRingInformation( sketcherMinimizerFragment* fragment) const { /* for each ring in the fragment find out which other rings it shares atoms with, or if they are connected in other ways (i.e. via a double bond). */ if (fragment->getRings().size() < 2) { return; } vector fragmentAtoms = fragment->getAtoms(); for (sketcherMinimizerAtom* atom : fragmentAtoms) { if (atom->rings.size() > 1) { for (unsigned int i = 0; i < atom->rings.size(); i++) { for (unsigned int j = i + 1; j < atom->rings.size(); j++) { bool found = false; for (unsigned int r = 0; r < atom->rings[i]->fusedWith.size(); r++) { if (atom->rings[i]->fusedWith[r] == atom->rings[j]) { atom->rings[i]->fusionAtoms[r].push_back(atom); for (unsigned int rr = 0; rr < atom->rings[j]->fusedWith.size(); rr++) { if (atom->rings[j]->fusedWith[rr] == atom->rings[i]) { atom->rings[j]->fusionAtoms[rr].push_back( atom); break; } } found = true; break; } } if (!found) { atom->rings[i]->fusedWith.push_back(atom->rings[j]); atom->rings[j]->fusedWith.push_back(atom->rings[i]); vector ats; ats.push_back(atom); atom->rings[i]->fusionAtoms.push_back(ats); atom->rings[j]->fusionAtoms.push_back(ats); } } } } } vector bonds = fragment->getBonds(); for (sketcherMinimizerBond* b : bonds) { if ((b->bondOrder != 1) && (b->startAtom->rings.size()) && (b->endAtom->rings.size()) && (!sketcherMinimizer::sameRing(b->startAtom, b->endAtom))) { for (sketcherMinimizerRing* r : b->startAtom->rings) { for (sketcherMinimizerRing* r2 : b->endAtom->rings) { r->fusedWith.push_back(r2); r2->fusedWith.push_back(r); vector ats; r->fusionAtoms.push_back(ats); r2->fusionAtoms.push_back(ats); r->fusionBonds.push_back(b); r2->fusionBonds.push_back(b); } } } } vector fragmentRings = fragment->getRings(); for (sketcherMinimizerRing* r : fragmentRings) { for (unsigned int i = 0; i < r->fusedWith.size(); i++) { vector fusionAtoms = r->fusionAtoms[i]; if (fusionAtoms.size() <= 2) { continue; } // find an atom with only one neighbor in the vector sketcherMinimizerAtom* startAtom = nullptr; for (sketcherMinimizerAtom* a : fusionAtoms) { int counter = 0; for (sketcherMinimizerAtom* n : a->neighbors) { if (find(fusionAtoms.begin(), fusionAtoms.end(), n) != fusionAtoms.end()) { counter++; } } if (counter == 1) { startAtom = a; break; } } assert(startAtom != nullptr); r->fusionAtoms[i] = orderChainOfAtoms(fusionAtoms, startAtom); } } for (sketcherMinimizerRing* r : fragmentRings) { for (unsigned int ii = 0; ii < r->fusedWith.size(); ii++) { if (r->fusionAtoms[ii].size() > 2) { for (sketcherMinimizerAtom* a : r->fusionAtoms[ii]) { // looking for atoms with no // neighbors in r but not in // r->fusedWith[ii] bool found = false; for (sketcherMinimizerAtom* n : a->neighbors) { int nn = 0; for (sketcherMinimizerRing* nr : n->rings) { if (nr == r) { nn++; } else if (nr == r->fusedWith[ii]) { nn++; } } if (nn == 1) { found = true; break; } } if (!found) { a->isSharedAndInner = true; } } } } } } void CoordgenFragmentBuilder::simplifyRingSystem( const vector& allRings, stack& sideRings, vector& centralRings) const { map alreadyChosenAsSide; bool found = true; /* simplify the structure by iteratively removing rings that have only one fusion partner. These side rings will have coordinates generated separately, one at a time, starting from the closest to the core. If we think of rings as atoms and fusion between two rings as bonds, this is the same as stripping away non-ring atoms from a fragment to generate coordinate for the ring system first */ while (found) { found = false; for (sketcherMinimizerRing* r : allRings) { if (alreadyChosenAsSide[r]) { continue; } if (r->isMacrocycle()) { continue; } int n = 0; for (auto ringCounter = 0u; ringCounter < r->fusedWith.size(); ++ringCounter) { auto fusedRing = r->fusedWith.at(ringCounter); if (!alreadyChosenAsSide[fusedRing]) { n++; if (fusedRing->isMacrocycle()) { /* disable macrocycles */ n++; } if (r->fusionAtoms.at(ringCounter).size() > 3) { /* disable rings that share too many atoms */ n++; } if (r->fusionAtoms.at(ringCounter).size() == 3 && r->size() == 4 && fusedRing->size() == 4) { /* don't separate rings of bicyclo (1,1,1) pentane so we * can use a template instead */ n++; } } } if (n == 1) /* ring is fused with only one ring, it will be removed from the core of the system and treated as a side ring */ { sideRings.push(r); found = true; alreadyChosenAsSide[r] = true; r->side = true; } } } /* everything that is left after removing the side rings is the core of the ring system */ for (sketcherMinimizerRing* ring : allRings) { if (!alreadyChosenAsSide[ring]) { centralRings.push_back(ring); } } } void CoordgenFragmentBuilder::buildRings( sketcherMinimizerFragment* fragment) const { if (fragment->getRings().empty()) { return; } initializeFusedRingInformation(fragment); vector fragmentRings = fragment->getRings(); if (fragmentRings.size() == 1) { buildRing(fragmentRings[0]); } else { // more than 1 ring stack sideRings; vector centralRings; simplifyRingSystem(fragmentRings, sideRings, centralRings); generateCoordinatesCentralRings(centralRings); generateCoordinatesSideRings(sideRings); } } coordgenlibs-3.0.2/CoordgenFragmentBuilder.h000066400000000000000000000150451436654770400211170ustar00rootroot00000000000000/* Contributors: Nicola Zonta Copyright Schrodinger, LLC. All rights reserved */ #ifndef COORDGEN_FRAGMENT_BUILDER_H #define COORDGEN_FRAGMENT_BUILDER_H #include #include #include #include #include "CoordgenConfig.hpp" #include "CoordgenMacrocycleBuilder.h" class sketcherMinimizerAtom; class sketcherMinimizerBond; class sketcherMinimizerRing; class sketcherMinimizerFragment; class sketcherMinimizerPointF; /* class that handles the creation of 2d coordinates for a molecular fragment */ class EXPORT_COORDGEN CoordgenFragmentBuilder { public: /* create coordinates for a molecular fragment */ void initializeCoordinates(sketcherMinimizerFragment* fragment) const; /* return a vector of ring atoms so that bound atoms are placed next to each other */ static std::vector orderRingAtoms(const sketcherMinimizerRing* r); /* return a vector of atoms so that bound atoms are placed next to each other */ static std::vector orderChainOfAtoms(const std::vector& atoms, sketcherMinimizerAtom* startAtom); /* return a list of coordinates representing a regular polygon for the given atoms in a ring */ static std::vector listOfCoordinatesFromListofRingAtoms( const std::vector& atoms); /* set a flag that forces the macrocycle builder to skip expensive polyomino matching routines and go straight to the breaking a bond approach */ void setForceOpenMacrocycles(bool b) { m_macrocycleBuilder.m_forceOpenMacrocycles = b; } /* set precision of the calculations. Higher precisions settings result better quality but slower calculations */ void setPrecision(float f) { m_macrocycleBuilder.setPrecision(f); } /* all bonds are placed at even intervals around the atom, as opposed for instance to the 90°-90°-120°-60° around tetracoordinated centers */ bool m_evenAngles; private: /* find if the present ring is fused with another than has already gotten coordinates for */ sketcherMinimizerRing* getSharedAtomsWithAlreadyDrawnRing( const sketcherMinimizerRing* ring, std::vector& fusionAtoms, sketcherMinimizerBond*& fusionBond) const; /* assign coordinates to a ring */ void buildRing(sketcherMinimizerRing* ring) const; /* generate coordinates for a group of fused rings that share more than two atoms with each other */ void generateCoordinatesCentralRings( std::vector centralRings) const; sketcherMinimizerRing* findCentralRingOfSystem( const std::vector& rings) const; /* find a template to generate coordinates for a ring system */ bool findTemplate(const std::vector& rings) const; /* generate coordinates for rings that have been stripped away from the core (see buildRings) */ void generateCoordinatesSideRings( std::stack sideRings) const; /* after coordinates are generated, find an orientation for the main fragment */ void rotateMainFragment(sketcherMinimizerFragment* fragment) const; /* assign coordinates to a fragment */ void buildFragment(sketcherMinimizerFragment* fragment) const; /* assign coordinates to all ring atoms. Start by stripping out side rings that only share two atoms with other rings to find a core of central rings */ void buildRings(sketcherMinimizerFragment* fragment) const; /* assign coordinates to atoms that are not in rings */ void buildNonRingAtoms(sketcherMinimizerFragment* fragment) const; /* initialize information about connectivity of rings */ void initializeFusedRingInformation(sketcherMinimizerFragment* fragment) const; /* split ring system into side rings and central rings by stripping away recursively rings that only share two atoms with other rings */ void simplifyRingSystem(const std::vector& allRings, std::stack& sideRings, std::vector& centralRings) const; /* if the fragment contains any NaN coordinates and 3d coords are available, * use thouse instead */ void fallbackIfNanCoordinates(sketcherMinimizerFragment* fragment) const; /* generate the coordinates of atoms bound to the first atom in the queue */ void generateCoordinatesNeighborsOfFirstAtomInQueue( std::queue& atomQueue, std::set& isAtomVisited, const sketcherMinimizerFragment* fragment) const; /* return a list of angles that bonds from the given atoms should form */ std::vector neighborsAnglesAtCenter(const sketcherMinimizerAtom* atom) const; /* initialize data to generate coordinates of atoms bound to a non-ring atom */ void initializeVariablesForNeighboursCoordinates( sketcherMinimizerAtom* atom, std::set& isAtomVisited, sketcherMinimizerPointF& startCoordinates, std::vector& orderedNeighbors, std::vector& angles) const; /* initialize data to generate coordinates of atoms bound to a ring atom */ void initializeVariablesForNeighboursCoordinatesRingAtom( const sketcherMinimizerAtom* atom, std::set& isAtomVisited, sketcherMinimizerPointF& startCoordinates, std::vector& orderedNeighbors, std::vector& angles) const; /* check if the atom is part of a macrocycle and has some degrees of freedom that can be added to be used in the minimizer */ void maybeAddMacrocycleDOF(sketcherMinimizerAtom* atom) const; /* make sure ZE chirality is maintained */ void avoidZEInversions(const sketcherMinimizerAtom* at, std::set& isAtomVisited) const; /* assign a score to the possibility of rings to be drawn on a plane */ float newScorePlanarity(const std::vector& rings) const; /* the macrocycle builder */ CoordgenMacrocycleBuilder m_macrocycleBuilder; }; #endif /* defined(COORDGEN_FRAGMENT_BUILDER_H) */ coordgenlibs-3.0.2/CoordgenFragmenter.cpp000066400000000000000000000357371436654770400205040ustar00rootroot00000000000000/* Contributors: Nicola Zonta Copyright Schrodinger, LLC. All rights reserved */ #include "CoordgenFragmenter.h" #include "sketcherMinimizerAtom.h" #include "sketcherMinimizerBond.h" #include "sketcherMinimizerFragment.h" #include "sketcherMinimizerMolecule.h" #include "sketcherMinimizerRing.h" #include "sketcherMinimizerMaths.h" #include #include using namespace std; void CoordgenFragmenter::splitIntoFragments(sketcherMinimizerMolecule* molecule) { /* split input molecule into rigid fragments */ vector fragments; for (sketcherMinimizerAtom* atom : molecule->getAtoms()) { atom->setFragment(nullptr); } /* molecule with a single atom and no bonds */ if (molecule->getAtoms().size() == 1) { auto* fragment = new sketcherMinimizerFragment(); sketcherMinimizerAtom* onlyAtom = molecule->getAtoms().at(0); fragment->addAtom(onlyAtom); fragments.push_back(fragment); } for (sketcherMinimizerBond* bond : molecule->_bonds) { if (bond->isResidueInteraction()) { continue; } if (bond->isInterFragment()) { processInterFragmentBond(bond, fragments); } else { processBondInternalToFragment(bond, fragments); } } #ifndef NDEBUG for (auto atom : molecule->getAtoms()) { assert(atom->getFragment() != nullptr); } #endif if (!fragments.empty()) { initializeInformation(fragments, molecule); } } void CoordgenFragmenter::addBondInformation(sketcherMinimizerBond* bond) { if (bond->isResidueInteraction()) { return; } if (bond->getStartAtom()->getFragment() == bond->getEndAtom()->getFragment()) { bond->getStartAtom()->getFragment()->addBond(bond); } else { bond->getStartAtom()->getFragment()->addInterFragmentBond(bond); bond->getEndAtom()->getFragment()->addInterFragmentBond(bond); } } void CoordgenFragmenter::addRingInformation(sketcherMinimizerRing* ring) { ring->_atoms.at(0)->getFragment()->addRing(ring); } void CoordgenFragmenter::processInterFragmentBond( sketcherMinimizerBond* bond, vector& fragments) { if (bond->getStartAtom()->getFragment() == nullptr) { auto* fragment = new sketcherMinimizerFragment(); fragment->addAtom(bond->getStartAtom()); fragments.push_back(fragment); } if (bond->getEndAtom()->getFragment() == nullptr) { auto* fragment = new sketcherMinimizerFragment(); fragment->addAtom(bond->getEndAtom()); fragments.push_back(fragment); } } void CoordgenFragmenter::processBondInternalToFragment( sketcherMinimizerBond* bond, vector& fragments) { if (bond->getStartAtom()->getFragment() == nullptr && bond->getEndAtom()->getFragment() == nullptr) { /* add the two atoms to a new fragment */ auto* fragment = new sketcherMinimizerFragment(); fragment->addAtom(bond->getStartAtom()); fragment->addAtom(bond->getEndAtom()); fragments.push_back(fragment); } else if (bond->getEndAtom()->getFragment() == nullptr) { /* extend fragment of start atom */ bond->getStartAtom()->getFragment()->addAtom(bond->getEndAtom()); } else if (bond->getStartAtom()->getFragment() == nullptr) { /* extend fragment of end atom */ bond->getEndAtom()->getFragment()->addAtom(bond->getStartAtom()); } else if (bond->getStartAtom()->getFragment() != bond->getEndAtom()->getFragment()) { /* join the two fragments */ joinFragments(bond->getStartAtom()->getFragment(), bond->getEndAtom()->getFragment(), fragments); } } void CoordgenFragmenter::joinFragments( sketcherMinimizerFragment* fragment1, sketcherMinimizerFragment* fragment2, vector& fragments) { for (sketcherMinimizerAtom* atom : fragment2->atoms()) { fragment1->addAtom(atom); } // remove fragment2 from fragments and free memory auto positionOfFragment2 = remove(fragments.begin(), fragments.end(), fragment2); fragments.erase(positionOfFragment2, fragments.end()); delete fragment2; } // Check if atom has fixed cooordinates static bool isAtomFixed(const sketcherMinimizerAtom* atom) { // needed for the find_if algorithm return atom->fixed; } // Check if atom has constrained cooordinates static bool isAtomConstrained(const sketcherMinimizerAtom* atom) { // needed for the find_if algorithm return atom->constrained; } // Check if fragment is part of an aliphatic chain static bool isChain(const sketcherMinimizerFragment* fragment) { /* can this fragment be part of a zig-zag chain, e.g. exane? */ vector fragmentAtoms = fragment->getAtoms(); if (fragmentAtoms.size() > 3) { return false; } for (sketcherMinimizerAtom* atom : fragmentAtoms) { if (atom->getBonds().size() > 3) { return false; } if (!atom->getRings().empty()) { return false; } } vector fragmentBonds = fragment->getBonds(); for (sketcherMinimizerBond* bond : fragmentBonds) { if (bond->getBondOrder() > 2) { return false; } } return true; } // Check if fragment can be flipped and sets the appropriate flag static void setFlipInfo(sketcherMinimizerFragment* fragment) { fragment->constrainedFlip = false; if (fragment->getAtoms().size() == 1 && fragment->countConstrainedAtoms() == 1) { // fragment has exactly 1 atom. should only be constrained if a child is constrained for (auto child : fragment->_children) { if(child->constrained) { fragment->constrainedFlip = true; } } } else { fragment->constrainedFlip = (fragment->countConstrainedAtoms() > 1); } } // Check if fragment has fixed coordinates and sets the appropriate flag static bool setFixedInfo(sketcherMinimizerFragment* fragment) { fragment->fixed = (find_if(fragment->atoms().begin(), fragment->atoms().end(), isAtomFixed) != fragment->atoms().end()); return fragment->fixed; } // Check if fragment has constrained coordinates and set the appropriate flag static bool setConstrainedInfo(sketcherMinimizerFragment* fragment) { fragment->constrained = (find_if(fragment->atoms().begin(), fragment->atoms().end(), isAtomConstrained) != fragment->atoms().end()); return fragment->constrained; } // Check if fragment is part of an aliphatic chain and sets the appropriate // flag static void setChainInfo(sketcherMinimizerFragment* fragment) { fragment->isChain = isChain(fragment); } void CoordgenFragmenter::initializeInformation( vector fragments, sketcherMinimizerMolecule* molecule) { for_each(molecule->getBonds().begin(), molecule->getBonds().end(), addBondInformation); for_each(molecule->getRings().begin(), molecule->getRings().end(), addRingInformation); for_each(fragments.begin(), fragments.end(), setChainInfo); molecule->hasConstrainedFragments = count_if(fragments.begin(), fragments.end(), setConstrainedInfo) > 0; molecule->hasFixedFragments = count_if(fragments.begin(), fragments.end(), setFixedInfo) > 0; sketcherMinimizerFragment* mainFragment = findMainFragment(fragments); addParentRelationsToFragments(mainFragment, fragments); orderFragments(fragments, mainFragment); molecule->setMainFragment(mainFragment); molecule->setFragments(fragments); for_each(fragments.begin(), fragments.end(), setFlipInfo); } bool CoordgenFragmenter::hasPriority(const sketcherMinimizerFragment* fragment1, const sketcherMinimizerFragment* fragment2) { bool checkNoMore = false; int checkN = 0; while (!checkNoMore) { size_t leftValue = getValueOfCheck(fragment1, checkN, checkNoMore); size_t rightValue = getValueOfCheck(fragment2, checkN, checkNoMore); if (leftValue > rightValue) { return true; } if (leftValue < rightValue) { return false; } ++checkN; } return false; } size_t CoordgenFragmenter::getValueOfCheck(const sketcherMinimizerFragment* fragment, int checkN, bool& checkNoMore) { switch (checkN) { case 0: return fragment->countFixedAtoms(); case 1: return fragment->countConstrainedAtoms(); case 2: return fragment->getRings().size(); case 3: return fragment->getAtoms().size(); case 4: return fragment->_interFragmentBonds.size(); case 5: return fragment->countHeavyAtoms(); case 6: return fragment->totalWeight(); case 7: return fragment->countDoubleBonds(); default: checkNoMore = true; return 0; } } sketcherMinimizerFragment* CoordgenFragmenter::findMainFragment( const vector& fragments) { sketcherMinimizerFragment* mainFragment = *(min_element(fragments.begin(), fragments.end(), hasPriority)); mainFragment = considerChains(fragments, mainFragment); return mainFragment; } sketcherMinimizerFragment* CoordgenFragmenter::considerChains( const vector& fragments, sketcherMinimizerFragment* mainFragment) { for (sketcherMinimizerFragment* fragment : fragments) { if (fragment->fixed || fragment->constrained) { return mainFragment; } } vector longestChain = findLongestChain(fragments); if (longestChain.size() >= acceptableChainLength(mainFragment)) { mainFragment = longestChain.at(0); } return mainFragment; } unsigned int CoordgenFragmenter::acceptableChainLength( sketcherMinimizerFragment* mainFragment) { switch (mainFragment->getRings().size()) { case 0: return 1; case 1: return 5; case 2: return 8; case 3: return 10; default: return 12; } } vector CoordgenFragmenter::findLongestChain( const vector& fragments) { vector longestChain; for (sketcherMinimizerFragment* fragment : fragments) { if (!fragment->isChain) { continue; } int chainN = 0; for (sketcherMinimizerBond* b : fragment->_interFragmentBonds) { sketcherMinimizerFragment* childFragment = (b->getStartAtom()->getFragment() != fragment ? b->getStartAtom()->getFragment() : b->getEndAtom()->getFragment()); if (childFragment->isChain) { ++chainN; } } if (chainN > 1) { continue; // it's in the middle of a chain } queue q; map parentMap; parentMap[fragment] = fragment; // mark first fragment as parent of // itself so it results visited q.push(fragment); sketcherMinimizerFragment* lastFragment = nullptr; while (!q.empty()) { lastFragment = q.front(); q.pop(); for (sketcherMinimizerBond* b : lastFragment->_interFragmentBonds) { sketcherMinimizerFragment* childFragment = (b->getStartAtom()->getFragment() != lastFragment ? b->getStartAtom()->getFragment() : b->getEndAtom()->getFragment()); if (parentMap[childFragment] != nullptr) { continue; } if (!childFragment->isChain) { continue; } parentMap[childFragment] = lastFragment; q.push(childFragment); } } vector chain; sketcherMinimizerFragment* recursiveFragment = lastFragment; if (recursiveFragment) { while (recursiveFragment != fragment) { chain.insert(chain.begin(), recursiveFragment); recursiveFragment = parentMap[recursiveFragment]; } chain.insert(chain.begin(), recursiveFragment); } if (chain.size() > longestChain.size()) { longestChain = chain; } } return longestChain; } void CoordgenFragmenter::addParentRelationsToFragments( sketcherMinimizerFragment* mainFragment, const vector& fragments) { queue fragmentsQueue; fragmentsQueue.push(mainFragment); while (!fragmentsQueue.empty()) { sketcherMinimizerFragment* fragment = fragmentsQueue.front(); fragmentsQueue.pop(); for (sketcherMinimizerBond* bond : fragment->_interFragmentBonds) { sketcherMinimizerFragment* childFragment = (bond->getStartAtom()->getFragment() == fragment ? bond->getEndAtom()->getFragment() : bond->getStartAtom()->getFragment()); if (childFragment == fragment->getParent()) { continue; } fragment->_children.push_back(childFragment); childFragment->setParent(fragment); childFragment->_bondToParent = bond; fragmentsQueue.push(childFragment); } } for (sketcherMinimizerFragment* fragment : fragments) { /* swap bonds to parent so that startAtom is always the parent's and * endAtom always the child's */ if (fragment->_bondToParent) { if (fragment->_bondToParent->getEndAtom()->getFragment() != fragment) { sketcherMinimizerAtom* swap = fragment->_bondToParent->endAtom; fragment->_bondToParent->endAtom = fragment->_bondToParent->startAtom; fragment->_bondToParent->startAtom = swap; fragment->_bondToParent->isReversed = !fragment->_bondToParent ->isReversed; // bond stereochemistry } assert(fragment->_bondToParent->getEndAtom()->getFragment() == fragment); } } } void CoordgenFragmenter::orderFragments( vector& fragments, sketcherMinimizerFragment* mainFragment) { queue q; vector new_fragments; q.push(mainFragment); while (!q.empty()) { sketcherMinimizerFragment* fragment = q.front(); q.pop(); new_fragments.push_back(fragment); for (sketcherMinimizerFragment* child : fragment->_children) q.push(child); } assert(fragments.size() == new_fragments.size()); fragments = new_fragments; } coordgenlibs-3.0.2/CoordgenFragmenter.h000066400000000000000000000070411436654770400201340ustar00rootroot00000000000000/* Contributors: Nicola Zonta Copyright Schrodinger, LLC. All rights reserved */ #pragma once #include "CoordgenConfig.hpp" #include #include class sketcherMinimizerFragment; class sketcherMinimizerMolecule; class sketcherMinimizerBond; class sketcherMinimizerRing; class sketcherMinimizerAtom; /* class to divide a molecule into rigid fragments */ class EXPORT_COORDGEN CoordgenFragmenter { public: /* divide the molecule into rigid fragments */ static void splitIntoFragments(sketcherMinimizerMolecule* molecule); private: /* put all atoms and bonds of fragment2 into fragment1 and delete it */ static void joinFragments(sketcherMinimizerFragment* fragment1, sketcherMinimizerFragment* fragment2, std::vector& fragments); /* process bond between two fragments */ static void processInterFragmentBond( sketcherMinimizerBond* bond, std::vector& fragments); /* process bond internal a fragment */ static void processBondInternalToFragment( sketcherMinimizerBond* bond, std::vector& fragments); /* initialize info from bond */ static void addBondInformation(sketcherMinimizerBond* bond); /* initialize info from ring */ static void addRingInformation(sketcherMinimizerRing* ring); /* initialize info of molecule */ static void initializeInformation(std::vector fragments, sketcherMinimizerMolecule* molecule); /* compare two fragments for priority (e.g. to find the main fragment) */ static bool hasPriority(const sketcherMinimizerFragment* fragment1, const sketcherMinimizerFragment* fragment2); /* get the score of a particular descriptor for the given fragment (used to assign priorities) */ static size_t getValueOfCheck(const sketcherMinimizerFragment* fragment, int checkN, bool& checkNoMore); /* find the main fragment */ static sketcherMinimizerFragment* findMainFragment(const std::vector& fragments); /* if molecule has a long enough chain return the start of the chain as main fragment instead */ static sketcherMinimizerFragment* considerChains(const std::vector& fragments, sketcherMinimizerFragment* mainFragment); /* empirical minimum length of zigzag chain of fragments that makes the chain get priority over the main fragment in determining the molecule's layout */ static unsigned int acceptableChainLength(sketcherMinimizerFragment* mainFragment); /* find the longest chain of connected fragments */ static std::vector findLongestChain(const std::vector& fragments); /* initialize parent-child info of bound fragments */ static void addParentRelationsToFragments( sketcherMinimizerFragment* mainFragment, const std::vector& fragments); /* order the vector of fragments so that bound fragments are consecutive, starting from the main fragment */ static void orderFragments(std::vector& fragments, sketcherMinimizerFragment* mainFragment); }; coordgenlibs-3.0.2/CoordgenMacrocycleBuilder.cpp000066400000000000000000001262021436654770400217660ustar00rootroot00000000000000/* Contributors: Nicola Zonta Copyright Schrodinger, LLC. All rights reserved */ #include #include #include "CoordgenMacrocycleBuilder.h" #include "CoordgenMinimizer.h" #include "sketcherMinimizer.h" #include "sketcherMinimizerMaths.h" #include "sketcherMinimizerRing.h" #include "sketcherMinimizerStretchInteraction.h" #define MAX_MACROCYCLES 40 #define PATH_FAILED -1000 #define HETEROATOM_RESTRAINT 1 #define SUBSTITUTED_ATOM_RESTRAINT 10 #define SUBSTITUENTS_TO_SAME_VERTEX_RESTRAINT 200 #define SUBSTITUENT_CLASH_WITH_PATH_RESTRAINT 400 #define SQRT3HALF 0.8660254037844386 using namespace std; std::ostream& operator<<(std::ostream& os, const vertexCoords& v) { os << "(" << v.x << "," << v.y << "," << v.z << ")"; return os; } std::ostream& operator<<(std::ostream& os, const hexCoords& h) { os << "(" << h.x << "," << h.y << ")"; return os; } Polyomino::Polyomino() { resizeGrid(1); } Polyomino::Polyomino(const Polyomino& rhs) { clear(); pentagonVertices = rhs.pentagonVertices; resizeGrid(1); for (auto i : rhs.m_list) { addHex(i->coords()); } reassignHexs(); } Polyomino& Polyomino::operator=(const Polyomino& rhs) { clear(); resizeGrid(1); pentagonVertices = rhs.pentagonVertices; for (auto i : rhs.m_list) { addHex(i->coords()); } reassignHexs(); return *this; } Polyomino::~Polyomino() { clear(); } void Polyomino::clear() { for (auto& i : m_list) { delete i; } m_list.clear(); } size_t Polyomino::size() const { return m_list.size(); } void Polyomino::resizeGrid(int i) const { m_grid.resize((2 * i + 1) * (2 * i + 1)); // grid can hold coordinates from -i to i m_gridSize = i; reassignHexs(); } void Polyomino::reassignHexs() const { for (auto& j : m_grid) { j = nullptr; } for (auto hex : m_list) { m_grid[getIndexInList(hex->coords())] = hex; } } bool Polyomino::isTheSameAs(Polyomino& p) const { // mirrored polyominoes are considered to be different if (size() != p.size()) { return false; } vector targetCoords; for (Hex* hex : p.m_list) { targetCoords.push_back(hex->coords()); } if (targetCoords.empty()) { return true; // both polyominoes are empty } int lowestx = m_list[0]->coords().x; int lowesty = m_list[0]->coords().y; for (Hex* hex : m_list) { int x = hex->coords().x; int y = hex->coords().y; if (x < lowestx) { lowestx = x; } if (y < lowesty) { lowesty = y; } } for (unsigned int i = 0; i < 6; i++) { // explore 6 possible positions rotating the coordinates 30 // degrees int lowestTargetX = 0, lowestTargetY = 0; for (unsigned int j = 0; j < targetCoords.size(); j++) { if (j == 0 || targetCoords[j].x < lowestTargetX) { lowestTargetX = targetCoords[j].x; } if (j == 0 || targetCoords[j].y < lowestTargetY) { lowestTargetY = targetCoords[j].y; } } // translate for (auto& targetCoord : targetCoords) { targetCoord = hexCoords(targetCoord.x + lowestx - lowestTargetX, targetCoord.y + lowesty - lowestTargetY); } // check bool same = true; for (auto targetCoord : targetCoords) { if (!getHex(targetCoord)) { same = false; break; } } if (same) { return true; } // rotate for (auto& targetCoord : targetCoords) { targetCoord = targetCoord.rotate30Degrees(); } } return false; } Hex* Polyomino::getHex(hexCoords coords) const { return m_grid[getIndexInList(coords)]; } void Polyomino::buildSkewedBoxShape(int x, int y, bool pentagon) { clear(); for (int yy = 0; yy < y; yy++) { for (int xx = 0; xx < x; xx++) { addHex(hexCoords(xx, yy)); } } if (pentagon) { markOneVertexAsPentagon(); } } void Polyomino::buildRaggedSmallerBoxShape( int x, int y, bool pentagon) // box alternating rows of length x and x-1 { clear(); int startx = 0; for (int yy = 0; yy < y; yy++) { // bigger row for (int xx = 0; xx < x; xx++) { addHex(hexCoords(startx + xx, yy)); } yy++; if (yy >= y) { break; } for (int xx = 0; xx < x - 1; xx++) { addHex(hexCoords(startx + xx, yy)); } startx--; } if (pentagon) { markOneVertexAsPentagon(); } } void Polyomino::buildRaggedBiggerBoxShape( int x, int y, bool pentagon) // box alternating rows of length x and x+1 { clear(); int startx = 0; for (int yy = 0; yy < y; yy++) { // smaller row for (int xx = 0; xx < x; xx++) { addHex(hexCoords(startx + xx, yy)); } yy++; if (yy >= y) { break; } for (int xx = 0; xx < x + 1; xx++) { addHex(hexCoords(startx + xx - 1, yy)); } startx--; } if (pentagon) { markOneVertexAsPentagon(); } } void Polyomino::buildRaggedBoxShape(int x, int y, bool pentagon) { clear(); int startx = 0; for (int yy = 0; yy < y; yy++) { for (int xx = 0; xx < x; xx++) { addHex(hexCoords(startx + xx, yy)); } yy++; if (yy >= y) { break; } for (int xx = 0; xx < x; xx++) { addHex(hexCoords(startx + xx, yy)); } startx--; } if (pentagon) { markOneVertexAsPentagon(); } } void Polyomino::buildWithVerticesN(int totVertices) { clear(); addHex(hexCoords(0, 0)); addHex(hexCoords(1, 0)); int vertices = 10; while (vertices < totVertices) { // find a hexagon with 2 neighbors to add. std::vector nextCoords = allFreeNeighbors(); int lowestDistance = -1; unsigned int bestI = 0; for (unsigned int i = 0; i < nextCoords.size(); i++) { hexCoords c = nextCoords[i]; if (countNeighbors(c) != 2) { continue; } int distance = c.distanceFrom(hexCoords(0, 0)); if (lowestDistance == -1 || distance < lowestDistance) { lowestDistance = distance; bestI = i; } } assert(lowestDistance != -1); addHex(nextCoords[bestI]); for (unsigned int i = 0; i < nextCoords.size(); i++) { if (i == bestI) { continue; } hexCoords c = nextCoords[i]; if (countNeighbors(c) == 3) { addHex(c); } } vertices += 2; } if ((vertices - totVertices) == 1) { markOneVertexAsPentagon(); } } void Polyomino::markOneVertexAsPentagon() // TO DO: should check if one vertex // is already marked to avoid marking // it again. Not a problem while we // only mark one vertex per polyomino { vector pathV = getPath(); size_t previousMultiplicity = hexagonsAtVertex(pathV[pathV.size() - 1]); size_t thisMultiplicity = hexagonsAtVertex(pathV[0]); size_t nextMultiplicity = 0; for (size_t i = 0; i < pathV.size(); i++) { size_t nextI = (i >= pathV.size() - 1) ? 0 : i + 1; nextMultiplicity = hexagonsAtVertex(pathV[nextI]); if (previousMultiplicity == 2 && thisMultiplicity == 1 && nextMultiplicity == 2) { setPentagon(pathV[i]); return; } previousMultiplicity = thisMultiplicity; thisMultiplicity = nextMultiplicity; } previousMultiplicity = hexagonsAtVertex(pathV[pathV.size() - 1]); thisMultiplicity = hexagonsAtVertex(pathV[0]); nextMultiplicity = 0; for (size_t i = 0; i < pathV.size(); i++) { size_t nextI = (i >= pathV.size() - 1) ? 0 : i + 1; nextMultiplicity = hexagonsAtVertex(pathV[nextI]); if (previousMultiplicity == 1 && thisMultiplicity == 2 && nextMultiplicity == 1) { setPentagon(pathV[i]); return; } previousMultiplicity = thisMultiplicity; thisMultiplicity = nextMultiplicity; } } void Polyomino::setPentagon(vertexCoords c) // the marked vertex and the // following one will count as a // single vertex to turn the hexagon // into a pentagon { pentagonVertices.push_back(c); } size_t Polyomino::hexagonsAtVertex(vertexCoords v) const { return vertexNeighbors(v).size(); } vector Polyomino::freeVertexNeighborPositions(vertexCoords v) const { vector out; int direction = v.x + v.y + v.z; if (direction != 1 && direction != -1) { cerr << "wrong input to free vertex neighbor positions " << v << endl; return out; } Hex* h = getHex(hexCoords(v.x - direction, v.y)); if (!h) { out.emplace_back(v.x - direction, v.y); } h = getHex(hexCoords(v.x, v.y - direction)); if (!h) { out.emplace_back(v.x, v.y - direction); } h = getHex(hexCoords(v.x, v.y)); // z - direction if (!h) { out.emplace_back(v.x, v.y); } return out; } vector Polyomino::vertexNeighbors(vertexCoords v) const { vector out; int direction = v.x + v.y + v.z; if (direction != 1 && direction != -1) { cerr << "wrong input to vertex Neighbors " << v << endl; return out; } Hex* h = getHex(hexCoords(v.x - direction, v.y)); if (h) { out.push_back(h); } h = getHex(hexCoords(v.x, v.y - direction)); if (h) { out.push_back(h); } h = getHex(hexCoords(v.x, v.y)); // z - direction if (h) { out.push_back(h); } return out; } vertexCoords Polyomino::findOuterVertex() const // find an outer vertex. Used to start path around polyomino. { // find a hexagon with a free vertex in direction (1, 0, 0). Such a hexagon // is guarateed to exist in a polyomino. for (auto h : m_list) { vertexCoords vert(h->x() + 1, h->y(), h->z()); if (hexagonsAtVertex(vert) == 1) { return vert; } } cerr << "something went wrong in finding the outer vertex" << endl; return {0, 0, 0}; } int Polyomino::countNeighbors(hexCoords h) const { int out = 0; vector neighs = Hex::neighboringPositions(h); for (auto neigh : neighs) { if (getHex(neigh) != nullptr) { out++; } } return out; } std::vector Polyomino::allFreeNeighbors() const { for (auto i : m_list) { // make sure that the grid is big enough to store // every neighbor getIndexInList(hexCoords(i->x() + 1, i->y() + 1)); getIndexInList(hexCoords(i->x() - 1, i->y() - 1)); } std::vector out; std::vector visited( m_grid.size(), false); // keep track if a neighbors has already been checked or not for (auto i : m_list) { std::vector neighborsCoords = i->neighbors(); for (auto neighborsCoord : neighborsCoords) { bool isPresent = (getHex(neighborsCoord) != nullptr); if (isPresent) { continue; } int index = getIndexInList(neighborsCoord); if (visited[index]) { continue; } visited[index] = true; out.push_back(neighborsCoord); } } return out; } int Polyomino::getIndexInList(hexCoords coords) const { int x = coords.x; int y = coords.y; if (abs(x) > m_gridSize) { resizeGrid(abs(x)); } if (abs(y) > m_gridSize) { resizeGrid(abs(y)); } int a = m_gridSize + x; int b = m_gridSize + y; int i = (2 * m_gridSize + 1) * a + b; return i; } void Polyomino::addHex(hexCoords coords) { int index = getIndexInList(coords); assert(m_grid[index] == nullptr); Hex* h = new Hex(coords); m_list.push_back(h); m_grid[index] = h; } void Polyomino::removeHex(hexCoords coords) { int index = getIndexInList(coords); Hex* hex = m_grid[getIndexInList(coords)]; assert(hex != nullptr); for (unsigned int i = 0; i < m_list.size(); i++) { if (m_list[i] == hex) { m_list.erase(m_list.begin() + i); break; } } delete hex; m_grid[index] = nullptr; } bool Polyomino::isEquivalentWithout(hexCoords c) const { /* does removing this hexagon yield another polyomino with the same number of vertices? true if hte hexagon has 3 neighbors all next to each other */ if (countNeighbors(c) != 3) { return false; } vector neighs = Hex::neighboringPositions(c); for (unsigned int i = 0; i < neighs.size(); i++) { int i2 = (i - 1 + 6) % 6; int i3 = (i - 2 + 6) % 6; if (getHex(neighs[i]) != nullptr && getHex(neighs[i2]) != nullptr && getHex(neighs[i3]) != nullptr) { return true; } } return false; } vertexCoords Polyomino::coordinatesOfSubstituent(const vertexCoords pos) const { vector neighbors = vertexNeighbors(pos); assert(!neighbors.empty()); assert(neighbors.size() < 3); vertexCoords out = pos; if (neighbors.size() == 1) { /* the vertex coordinates differ from its parent's by a single +1 or -1 (d). The substituent will be along the same direction, so the other two coordinates will be incremented by -d. e.g. (1, 0, 0)-> (1, -1, -1) or (0, -1, 0)-> (1, -1, 1) */ vertexCoords parentCoords = neighbors[0]->coords().toVertexCoords(); vertexCoords v = pos - parentCoords; int d = -1; if (v.x + v.y + v.z > 0) { d = 1; } if (v.x == 0) { v.x -= d; } if (v.y == 0) { v.y -= d; } if (v.z == 0) { v.z -= d; } out = parentCoords + v; } else if (neighbors.size() == 2) { /* the two parents share two vertices. One is pos, the other one is the neighbor we are looking for */ vertexCoords parent1Coords = neighbors[0]->coords().toVertexCoords(); vertexCoords v = pos - parent1Coords; vertexCoords parent2Coords = neighbors[1]->coords().toVertexCoords(); out = parent2Coords - v; } return out; } vector Polyomino::getPath() const { vector out; vertexCoords firstVertex = findOuterVertex(); vertexCoords currentVertex = firstVertex; vector neighbors = vertexNeighbors(firstVertex); assert(neighbors.size() == 1); Hex* currentHex = neighbors[0]; vertexCoords nextVertex = currentHex->followingVertex(currentVertex); do { bool skip = false; if (!pentagonVertices.empty()) { for (auto pentagonVertice : pentagonVertices) { if (pentagonVertice == currentVertex) { skip = true; break; } } } if (!skip) { out.push_back(currentVertex); } currentVertex = nextVertex; neighbors = vertexNeighbors(currentVertex); assert(neighbors.size() <= 2); if (neighbors.size() == 2) { currentHex = (neighbors[0] != currentHex ? neighbors[0] : neighbors[1]); } nextVertex = currentHex->followingVertex(currentVertex); } while (currentVertex != firstVertex); return out; } vector Hex::neighboringPositions(hexCoords h) { int xx = h.x; int yy = h.y; vector out; out.emplace_back(xx + 1, yy); // z-1 out.emplace_back(xx + 1, yy - 1); out.emplace_back(xx, yy - 1); // z+1 out.emplace_back(xx - 1, yy); // z+1 out.emplace_back(xx - 1, yy + 1); out.emplace_back(xx, yy + 1); // z-1 return out; } vector Hex::neighbors() const { return neighboringPositions(m_coords); } vertexCoords Hex::followingVertex(vertexCoords v) const { int dx = v.x - x(); int dy = v.y - y(); int dz = v.z - z(); if (dx + dy + dz != 1 && dx + dy + dz != -1) { cerr << "wrong input to transform to following vertex" << endl; } if (dx == 0 && dy == 0) { dx = -dz; dy = 0; dz = 0; } else if (dx == 0 && dz == 0) { dz = -dy; dx = 0; dy = 0; } else if (dy == 0 && dz == 0) { dy = -dx; dx = 0; dz = 0; } else { cerr << "wrong input to transform to following vertex" << endl; } return {x() + dx, y() + dy, z() + dz}; } float CoordgenMacrocycleBuilder::getPrecision() const { return m_precision; } void CoordgenMacrocycleBuilder::setPrecision(float f) { m_precision = f; } vector CoordgenMacrocycleBuilder::newMacrocycle( sketcherMinimizerRing* ring, vector atoms) const { // TODO the coordinates should be built on the returned vector, never saved // to the atoms in atoms. int natoms = static_cast(atoms.size()); Polyomino p; p.buildWithVerticesN(natoms); vector pols; pols.push_back(p); vector squarePols = buildSquaredShapes(natoms); for (unsigned int i = 0; i < squarePols.size(); i++) { assert(squarePols[i].getPath().size() == atoms.size()); } pols.reserve(pols.size() + squarePols.size()); pols.insert(pols.end(), squarePols.begin(), squarePols.end()); pols = removeDuplicates(pols); bool found = false; pathRestraints pr = getPathRestraints(atoms); pathConstraints pc = getPathConstraints(atoms); int scoreOfChosen = PATH_FAILED; int startOfChosen = 0; int bestStart = 0; int bestScore = PATH_FAILED; Polyomino chosenP = pols[0]; int acceptableScore = acceptableShapeScore(natoms); int checkedMacrocycles = 0; if (!m_forceOpenMacrocycles) { do { int bestP = 0; found = matchPolyominoes(pols, pc, pr, bestP, bestScore, bestStart, checkedMacrocycles); if (bestScore > scoreOfChosen) { startOfChosen = bestStart; scoreOfChosen = bestScore; chosenP = pols[bestP]; if (bestScore > acceptableScore) { break; } } if (checkedMacrocycles > MAX_MACROCYCLES) { break; } pols = listOfEquivalents(pols); pols = removeDuplicates(pols); } while (!pols.empty()); } if (found) { vector path = chosenP.getPath(); writePolyominoCoordinates(path, atoms, startOfChosen); if (!chosenP.pentagonVertices.empty()) { atoms.at(0)->molecule->requireMinimization(); } } else { // could not find a shape. fallback methods if (!openCycleAndGenerateCoords(ring)) { vector coords = CoordgenFragmentBuilder::listOfCoordinatesFromListofRingAtoms( atoms); int i = 0; for (sketcherMinimizerAtom* atom : atoms) { atom->setCoordinates(coords[i]); ++i; } } atoms.at(0)->molecule->requireMinimization(); } vector coordinates; coordinates.reserve(atoms.size()); for (sketcherMinimizerAtom* atom : atoms) { coordinates.push_back(atom->getCoordinates()); } return coordinates; } sketcherMinimizerBond* CoordgenMacrocycleBuilder::findBondToOpen(sketcherMinimizerRing* ring) const { sketcherMinimizerBond* bestBond = nullptr; float bestScore = 0.f; for (sketcherMinimizerBond* bond : ring->_bonds) { float score = 0.f; if (ring->isMacrocycle()) { if (bond->getBondOrder() != 1) { continue; } bool nextToMultipleBond = false; for (auto otherBond : bond->getStartAtom()->bonds) { if (otherBond->isStereo()) { nextToMultipleBond = true; break; } } for (auto otherBond : bond->getEndAtom()->bonds) { if (otherBond->isStereo()) { nextToMultipleBond = true; break; } } if (nextToMultipleBond) { continue; } } score += bond->rings.size() * 10; score += bond->getStartAtom()->neighbors.size(); score += bond->getEndAtom()->neighbors.size(); score /= bond->crossingBondPenaltyMultiplier; if (bestBond == nullptr || score < bestScore) { bestScore = score; bestBond = bond; } } return bestBond; } bool CoordgenMacrocycleBuilder::openCycleAndGenerateCoords( sketcherMinimizerRing* ring) const // generate coordinates of whole fragment // by opening one bond of the macrocycle { map atomMap; sketcherMinimizer min(getPrecision()); min.setSkipMinimization(true); min.setForceOpenMacrocycles(true); sketcherMinimizerBond* bondToBreak = findBondToOpen(ring); if (!bondToBreak) { return false; } auto* minMol = new sketcherMinimizerMolecule; sketcherMinimizerAtom* a = ring->_atoms[0]; // vector atoms = a->getFragment()->getAtoms(); vector atoms = a->molecule->getAtoms(); for (sketcherMinimizerAtom* at : atoms) { if (at->isResidue()) { continue; } auto* new_at = new sketcherMinimizerAtom; atomMap[at] = new_at; new_at->templateCoordinates = at->coordinates; new_at->coordinates = at->coordinates; new_at->atomicNumber = at->atomicNumber; new_at->_generalUseN = at->_generalUseN; new_at->molecule = minMol; new_at->_implicitHs = at->_implicitHs; minMol->_atoms.push_back(new_at); } // vector bonds = a->getFragment()->getBonds(); vector bonds = a->molecule->getBonds(); for (sketcherMinimizerBond* bo : bonds) { if (bo == bondToBreak || bo->isResidueInteraction()) { continue; } auto* new_bo = new sketcherMinimizerBond; new_bo->bondOrder = bo->bondOrder; new_bo->startAtom = atomMap[bo->startAtom]; new_bo->endAtom = atomMap[bo->endAtom]; new_bo->isZ = bo->isZ; new_bo->m_ignoreZE = bo->m_ignoreZE; minMol->_bonds.push_back(new_bo); } min.initialize(minMol); min.findFragments(); min.buildFromFragments(true); auto* brokenBond = new sketcherMinimizerBond; brokenBond->bondOrder = bondToBreak->bondOrder; brokenBond->startAtom = atomMap[bondToBreak->startAtom]; brokenBond->endAtom = atomMap[bondToBreak->endAtom]; brokenBond->isZ = bondToBreak->isZ; minMol->_bonds.push_back(brokenBond); minMol->forceUpdateStruct(minMol->_atoms, minMol->_bonds, minMol->_rings); std::vector extraInteractions; extraInteractions.push_back(new sketcherMinimizerStretchInteraction( brokenBond->startAtom, brokenBond->endAtom)); min.avoidClashesOfMolecule(minMol, extraInteractions); for (sketcherMinimizerAtom* atom : atoms) { sketcherMinimizerAtom* otherAtom = atomMap[atom]; if (otherAtom->rigid) { atom->rigid = true; } atom->setCoordinates(otherAtom->getCoordinates()); } for (auto r : ring->getAtoms()[0]->fragment->getRings()) { r->coordinatesGenerated = true; } for (auto bondRing : bondToBreak->rings) { if (!bondRing->isMacrocycle() && bondRing != ring) { bondRing->coordinatesGenerated = false; } } delete brokenBond; return true; } vector CoordgenMacrocycleBuilder::listOfEquivalents(const vector& l) const { vector out; for (const auto& i : l) { vector newV = listOfEquivalent(i); out.reserve(out.size() + newV.size()); out.insert(out.end(), newV.begin(), newV.end()); } return out; } vector CoordgenMacrocycleBuilder::listOfEquivalent(const Polyomino& p) const // build a list of polyominoes with the same number of // vertices by removing hexagons with 3 neighbors { vector out; vector l = p.m_list; size_t pentagonVs = p.pentagonVertices.size(); for (auto& i : l) { hexCoords c = i->coords(); if (p.isEquivalentWithout(c)) { Polyomino newP = p; newP.pentagonVertices.clear(); newP.removeHex(c); for (size_t i = 0; i < pentagonVs; i++) { newP.markOneVertexAsPentagon(); } out.push_back(newP); } } return out; } pathConstraints CoordgenMacrocycleBuilder::getPathConstraints( vector& atoms) const { pathConstraints pc; pc.doubleBonds = getDoubleBondConstraints(atoms); pc.ringConstraints = getRingConstraints(atoms); return pc; } vector CoordgenMacrocycleBuilder::getRingConstraints( vector& atoms) const { vector out; for (int i = 0; i < static_cast(atoms.size()); i++) { sketcherMinimizerAtom* a = atoms[i]; if (a->rings.size() > 1) { for (unsigned int rr = 0; rr < a->rings.size(); rr++) { sketcherMinimizerRing* r = a->rings[rr]; if (r->_atoms.size() < MACROCYCLE) { // this excludes the // current cycle and all // fused macrocycles bool forceOutside = false; for (auto n : a->neighbors) { if (find(atoms.begin(), atoms.end(), n) == atoms.end()) { if (r->containsAtom(n)) { forceOutside = true; } break; } } out.emplace_back(i, r, forceOutside); } } } } return out; } vector CoordgenMacrocycleBuilder::getDoubleBondConstraints( vector& atoms) const { vector out; if (atoms.size() >= MACROCYCLE) { for (unsigned int i = 0; i < atoms.size(); i++) { unsigned int index = i; unsigned int index2 = (i + 1) % atoms.size(); sketcherMinimizerBond* b = sketcherMinimizer::getBond(atoms[i], atoms[index2]); if (!b) { cerr << "bad input to get double bond constraints" << endl; break; } if (b->bondOrder != 2) { continue; } bool smallRingBond = false; if (b->rings.size() > 1) { for (auto& ring : b->rings) { if (ring->_atoms.size() < MACROCYCLE) { smallRingBond = true; break; } } } if (smallRingBond) { continue; } int previousI = static_cast((i + atoms.size() - 1) % atoms.size()); int followingI = (i + 2) % atoms.size(); bool isTrans = !b->isZ; // is the atom trans in the ring? (isZ // stores the absolute chirality) if (b->startAtom != atoms[i]) { // atoms[i] could be the end atom of b int swap = previousI; previousI = followingI; followingI = swap; index = index2; index2 = i; } if (b->startAtomCIPFirstNeighbor() != atoms[previousI]) { isTrans = !isTrans; } if (b->endAtomCIPFirstNeighbor() != atoms[followingI]) { isTrans = !isTrans; } doubleBondConstraint constraint; constraint.trans = isTrans; constraint.atom1 = index; constraint.atom2 = index2; constraint.previousAtom = previousI; constraint.followingAtom = followingI; out.push_back(constraint); } } return out; } int CoordgenMacrocycleBuilder::getNumberOfChildren( sketcherMinimizerAtom* a, sketcherMinimizerAtom* parent) const { int n = 0; map visited; queue q; q.push(a); visited[parent] = true; while (!q.empty()) { sketcherMinimizerAtom* thisA = q.front(); q.pop(); visited[thisA] = true; n++; for (auto n : thisA->neighbors) { if (visited[n]) { continue; } q.push(n); } } return n; } pathRestraints CoordgenMacrocycleBuilder::getPathRestraints( vector& atoms) const { pathRestraints pr; vector heteroAtoms; vector> substitutedAtoms; for (unsigned int i = 0; i < atoms.size(); i++) { if (atoms[i]->atomicNumber != 6) { heteroAtoms.push_back(i); } if (atoms[i]->neighbors.size() != 2) { int totN = 0; int prevI = static_cast((i + atoms.size() - 1) % atoms.size()); int postI = (i + 1) % atoms.size(); for (unsigned int j = 0; j < atoms[i]->neighbors.size(); j++) { sketcherMinimizerAtom* n = atoms[i]->neighbors[j]; if (n == atoms[prevI]) { continue; } if (n == atoms[postI]) { continue; } totN += getNumberOfChildren(n, atoms[i]); } substitutedAtoms.emplace_back(i, totN); } } pr.heteroAtoms = heteroAtoms; pr.substitutedAtoms = substitutedAtoms; return pr; } bool CoordgenMacrocycleBuilder::checkDoubleBoundConstraints( vector& dbConstraints, vector& vertices, int& startI) const { for (auto& dbConstraint : dbConstraints) { size_t counter = (startI + dbConstraint.previousAtom) % vertices.size(); sketcherMinimizerPointF p1 = coordsOfVertex(vertices[counter]); counter = (startI + dbConstraint.atom1) % vertices.size(); sketcherMinimizerPointF p2 = coordsOfVertex(vertices[counter]); counter = startI + dbConstraint.atom2; if (counter >= vertices.size()) { counter -= vertices.size(); } sketcherMinimizerPointF p3 = coordsOfVertex(vertices[counter]); counter = startI + dbConstraint.followingAtom; if (counter >= vertices.size()) { counter -= vertices.size(); } sketcherMinimizerPointF p4 = coordsOfVertex(vertices[counter]); if (sketcherMinimizerMaths::sameSide(p1, p4, p2, p3) == dbConstraint.trans) { return false; } } return true; } int CoordgenMacrocycleBuilder::scorePath(Polyomino& p, vector& path, vector& neighborNs, int& startI, pathConstraints& pc, pathRestraints& pr) const { if (!scorePathConstraints(pc, p, path, neighborNs, startI)) { return PATH_FAILED; } return scorePathRestraints(pr, p, path, neighborNs, startI); } int CoordgenMacrocycleBuilder::scorePathRestraints(pathRestraints& pr, Polyomino& p, vector& path, vector& neighborNs, int& startI) const { int score = 0; set usedSubstituentCoordinates; for (int heteroAtom : pr.heteroAtoms) { int counter = (heteroAtom + startI) % neighborNs.size(); if (neighborNs[counter] == 1) { score -= HETEROATOM_RESTRAINT; // heteroatom placed towards outside } } for (unsigned int i = 0; i < pr.substitutedAtoms.size(); i++) { int counter = (pr.substitutedAtoms[i].first + startI) % neighborNs.size(); if (neighborNs[counter] == 2) { score -= SUBSTITUTED_ATOM_RESTRAINT * pr.substitutedAtoms[i] .second; // substituted atoms placed towards inside vertexCoords substituentsCoordinates = p.coordinatesOfSubstituent(path[i]); if (usedSubstituentCoordinates.find(substituentsCoordinates) != usedSubstituentCoordinates.end()) { score -= SUBSTITUENTS_TO_SAME_VERTEX_RESTRAINT; } if (find(path.begin(), path.end(), substituentsCoordinates) != path.end()) { // substituent would clash with path score -= SUBSTITUENT_CLASH_WITH_PATH_RESTRAINT; } usedSubstituentCoordinates.insert(substituentsCoordinates); } } return score; } bool CoordgenMacrocycleBuilder::scorePathConstraints(pathConstraints& pc, Polyomino& p, vector& path, vector& neighborNs, int& startI) const { if (!checkRingConstraints(pc.ringConstraints, p, path, neighborNs, startI)) { return false; } if (!checkDoubleBoundConstraints(pc.doubleBonds, path, startI)) { return false; } return true; } bool CoordgenMacrocycleBuilder::checkRingConstraints( vector& ringConstraints, Polyomino& p, vector& path, vector& neighborNs, int& startI) const // make sure that all shared atoms with a fused small // ring map to the same hexagon { std::map> allowedHexs; for (auto& ringConstraint : ringConstraints) { unsigned int counter = (ringConstraint.atom + startI) % path.size(); if (ringConstraint.forceOutside) { if (neighborNs[counter] != 1) { return false; } } sketcherMinimizerRing* r = ringConstraint.ring; vector newPos = p.freeVertexNeighborPositions(path[counter]); vector oldPos = allowedHexs[r]; vector nextPos; if (oldPos.empty()) { nextPos = newPos; } else { for (auto toCheck : newPos) { if (find(oldPos.begin(), oldPos.end(), toCheck) != oldPos.end()) { // hexCoords was already marked as allowed and is now // confirmed nextPos.push_back(toCheck); } } } if (nextPos.empty()) { return false; } allowedHexs[r] = nextPos; } return true; } vector CoordgenMacrocycleBuilder::getVertexNeighborNs(Polyomino& p, vector& path) const { vector out; out.reserve(path.size()); for (auto i : path) { out.push_back(static_cast(p.hexagonsAtVertex(i))); } return out; } int CoordgenMacrocycleBuilder::getLowestPeriod( std::vector& neighbors) const { for (unsigned int period = 1; period < neighbors.size(); period++) { bool hasDifference = false; for (unsigned int i = 0; i < neighbors.size(); i++) { unsigned int i2 = (i + period) % neighbors.size(); if (neighbors[i] != neighbors[i2]) { hasDifference = true; break; } } if (!hasDifference) { return period; } } return static_cast(neighbors.size()); } bool CoordgenMacrocycleBuilder::matchPolyominoes(vector& pols, pathConstraints& pc, pathRestraints& pr, int& bestP, int& bestScore, int& bestStart, int& checkedMacrocycles) const { bestStart = 0; bestP = 0; bestScore = PATH_FAILED; int bestScoreOfThis = PATH_FAILED; int bestStartOfThis = 0; bool matched = false; for (unsigned int i = 0; i < pols.size(); i++) { if (matchPolyomino(pols[i], pc, pr, bestStartOfThis, bestScoreOfThis)) { matched = true; if (bestScoreOfThis > bestScore) { bestScore = bestScoreOfThis; bestStart = bestStartOfThis; bestP = i; if (bestScore == 0) { return true; } } } if (checkedMacrocycles++ > MAX_MACROCYCLES) { break; } } return matched; } bool CoordgenMacrocycleBuilder::matchPolyomino(Polyomino& p, pathConstraints& pc, pathRestraints& pr, int& bestStart, int& bestScore) const { vector path = p.getPath(); vector neighborNs = getVertexNeighborNs(p, path); bestStart = 0; bestScore = PATH_FAILED; for (int startI = 0; startI < getLowestPeriod(neighborNs); startI++) { // test starting from every vertex. int score = scorePath(p, path, neighborNs, startI, pc, pr); if (score > bestScore) { bestScore = score; bestStart = startI; if (bestScore == 0) { break; } } } return bestScore > PATH_FAILED; } sketcherMinimizerPointF CoordgenMacrocycleBuilder::coordsOfVertex(vertexCoords& v) const { return sketcherMinimizerPointF( static_cast(BONDLENGTH * SQRT3HALF * v.x - BONDLENGTH * SQRT3HALF * v.z), static_cast(-BONDLENGTH * 0.5 * v.x + BONDLENGTH * v.y + -BONDLENGTH * 0.5 * v.z)); } void CoordgenMacrocycleBuilder::writePolyominoCoordinates( vector& path, const vector& atoms, int startI) const { for (unsigned int n = 0; n < atoms.size(); n++) { unsigned int counter = (n + startI) % path.size(); vertexCoords hCoords = path[counter]; if (!atoms[n]->coordinatesSet) { atoms[n]->setCoordinates(coordsOfVertex(hCoords)); } } } vector CoordgenMacrocycleBuilder::removeDuplicates(vector& pols) const { // This algorithm has potential to be n^2 Could be a potential bottleneck // for performance vector out; for (auto& pol : pols) { bool duplicate = false; for (auto& j : out) { if (pol.isTheSameAs(j)) { duplicate = true; break; } } if (!duplicate) { out.push_back(pol); } } return out; } vector CoordgenMacrocycleBuilder::buildSquaredShapes(int totVertices) const { // a square like this has 4x + 4 y - 2 vertices. Only do if number of // vertices (or number of vertices+1) is divisible by 2 but not by 4. x + y // = (N + 2)/ 4 vector out; bool pentagon = false; if ((totVertices % 2) > 0) { pentagon = true; totVertices++; } if (totVertices % 4 == 0) { if (totVertices >= 12) { // we can build one with ragged borders and even number of y. We'll // only build the ones alternating rows with length x, x+1, because // the x, x-1 one is equivant int xandy = totVertices / 4; int mid = xandy / 2; // truncate for (int i = 1; i < mid; ++i) { int i2 = xandy - i; if ((i2 % 2) == 0 && i > 1) { Polyomino p; p.buildRaggedBiggerBoxShape(i, i2, pentagon); out.insert(out.begin(), p); } if ((i % 2) == 0 && i2 > 1) { Polyomino p; p.buildRaggedBiggerBoxShape(i2, i, pentagon); out.insert(out.begin(), p); } } } } else { // we'll build the skewed box, the ragged box, the boxes with odd y // alternating x and x+1, and the boxes with odd y alternating x and x-1 int xandy = (totVertices + 2) / 4; int mid = xandy / 2; // truncate for (int i = 1; i < mid + 1; i++) { // build all possible combinations of shapes Polyomino p; p.buildSkewedBoxShape(i, xandy - i, pentagon); out.insert(out.begin(), p); // add at the beginning because we want rounder // shapes to be evaluated first (they have more space // inside and less risk of substituents clashes int i2 = xandy - i; if (i < 2 || i2 < 2) { continue; } { Polyomino p; p.buildRaggedBoxShape(i, i2, pentagon); out.insert(out.begin(), p); } { Polyomino p; p.buildRaggedBoxShape(i2, i, pentagon); out.insert(out.begin(), p); } if (i2 % 2 > 0) { Polyomino p; p.buildRaggedBiggerBoxShape(i, i2, pentagon); out.insert(out.begin(), p); } if (i % 2 > 0) { Polyomino p; p.buildRaggedBiggerBoxShape(i2, i, pentagon); out.insert(out.begin(), p); } if (i > 2 && i2 % 2 > 0) { Polyomino p; p.buildRaggedSmallerBoxShape(i, i2, pentagon); out.insert(out.begin(), p); } if (i2 > 2 && i % 2 > 0) { Polyomino p; p.buildRaggedSmallerBoxShape(i2, i, pentagon); out.insert(out.begin(), p); } } } return out; } int CoordgenMacrocycleBuilder::acceptableShapeScore(int numberOfAtoms) const { if (numberOfAtoms < 10) { return 0; } else { return numberOfAtoms * SUBSTITUTED_ATOM_RESTRAINT / 2; } } coordgenlibs-3.0.2/CoordgenMacrocycleBuilder.h000066400000000000000000000306271436654770400214400ustar00rootroot00000000000000/* Contributors: Nicola Zonta Copyright Schrodinger, LLC. All rights reserved */ #ifndef COORDGEN_MACROCYCLE_BUILDER_H #define COORDGEN_MACROCYCLE_BUILDER_H #include "CoordgenConfig.hpp" #include #include #include class sketcherMinimizerAtom; class sketcherMinimizerRing; class sketcherMinimizerBond; class sketcherMinimizerPointF; struct doubleBondConstraint { bool trans; int previousAtom, atom1, atom2, followingAtom; }; struct ringConstraint { ringConstraint(int a, sketcherMinimizerRing* r, bool fo) { ring = r; atom = a; forceOutside = fo; } bool forceOutside; int atom; sketcherMinimizerRing* ring; }; struct vertexCoords { bool operator!=(const vertexCoords& rhs) const { if (x != rhs.x) { return true; } if (y != rhs.y) { return true; } if (z != rhs.z) { return true; } return false; } bool operator<(const vertexCoords& rhs) const { if (x < rhs.x) { return true; } if (y < rhs.y) { return true; } if (z < rhs.z) { return true; } return false; } friend const vertexCoords operator+(const vertexCoords& v1, const vertexCoords& v2) { return vertexCoords(v1.x + v2.x, v1.y + v2.y, v1.z + v2.z); } friend const vertexCoords operator-(const vertexCoords& v1, const vertexCoords& v2) { return vertexCoords(v1.x - v2.x, v1.y - v2.y, v1.z - v2.z); } bool operator==(const vertexCoords& rhs) const { return x == rhs.x && y == rhs.y && z == rhs.z; } vertexCoords(int ix, int iy, int iz) { x = ix; y = iy; z = iz; } int x, y, z; private: friend std::ostream& operator<<(std::ostream& os, const vertexCoords& v); }; struct pathRestraints { std::vector heteroAtoms; std::vector> substitutedAtoms; }; struct pathConstraints { std::vector doubleBonds; std::vector ringConstraints; std::vector forceOutside; }; struct hexCoords { hexCoords(int ix, int iy) { x = ix; y = iy; } bool operator==(const hexCoords& rhs) const { return x == rhs.x && y == rhs.y; } int x, y; int distanceFrom(const hexCoords& origin) const { int dx = abs(x - origin.x); int dy = abs(y - origin.y); int dz = abs((-x - y) - (-origin.x - origin.y)); int max = (dx > dy) ? dx : dy; return (dz > max) ? dz : max; } hexCoords rotate30Degrees() { int z = -x - y; return {-z, -x}; } vertexCoords toVertexCoords() const { return {x, y, -x - y}; } private: friend std::ostream& operator<<(std::ostream& os, const hexCoords& h); }; /* unit hexagon used to build polyominoes for macrocycle shapes */ struct Hex { Hex(hexCoords coords) : m_coords(coords) {} void setCoords(hexCoords coords) { m_coords = coords; } int x() const { return m_coords.x; } int y() const { return m_coords.y; } int z() const { return -x() - y(); } hexCoords coords() const { return m_coords; } hexCoords m_coords; std::vector neighbors() const; static std::vector neighboringPositions(hexCoords h); vertexCoords followingVertex(vertexCoords v) const; }; /* hex polyomino (geometrical figure built on a hexagon lattice). All functions assume that the polyomino has no holes */ class EXPORT_COORDGEN Polyomino { public: Polyomino(); Polyomino(const Polyomino& rhs); ~Polyomino(); Polyomino& operator=(const Polyomino& rhs); /* explore the topology of the polyominoes and returns true if they have the same. Takes into account translations, rotations and mirroring */ bool isTheSameAs(Polyomino& p) const; /* returns the number of hexagons in the polyomino */ size_t size() const; /* empties the polyomino */ void clear(); /* marks one hexagon to be a pentagon */ void markOneVertexAsPentagon(); // to get a path with an odd number of vertices /* returns all hexagons that share the given vertex */ std::vector vertexNeighbors(vertexCoords v) const; /* returns neighboring positions that are not shared with other hexagons */ std::vector freeVertexNeighborPositions(vertexCoords v) const; /* return the contour path of the polyomino */ std::vector getPath() const; /* return the hexagon at the given position */ Hex* getHex(hexCoords coords) const; /* find an outer vertex. Used to start path around polyomino. */ vertexCoords findOuterVertex() const; /* number of Hexs present at the given vertex */ size_t hexagonsAtVertex(vertexCoords v) const; /* build a round-ish polyomino with the given number of vertices */ void buildWithVerticesN(int totVertices); /* build a box-like polyomino of the given size */ void buildSkewedBoxShape(int x, int y, bool pentagon = false); // squared shape /* build a zig-zag box polyomino of the given size */ void buildRaggedBoxShape(int x, int y, bool pentagon = false); /* build a zig-zag box polyomino of the given size */ void buildRaggedSmallerBoxShape( int x, int y, bool pentagon = false); // box alternating rows of length x and x-1 /* build a zig-zag box polyomino of the given size */ void buildRaggedBiggerBoxShape( int x, int y, bool pentagon = false); // box alternating rows of length x and x+1 /* return vector of coordinates of unoccupied hexagons bordering the polyomino */ std::vector allFreeNeighbors() const; /* return number of neighbors of hexagon at given coordinates */ int countNeighbors(hexCoords) const; /* add an hexagon at given coordinates */ void addHex(hexCoords coords); /* remove the hexagon at given coordinates */ void removeHex(hexCoords coords); /* does removing this hexagon yield another polyomino with the same number of vertices? true if the hexagon has 3 neighbors all next to each other */ bool isEquivalentWithout(hexCoords c) const; /* give the coordinates of an hypotetical substituent bound to an atom in * position pos */ vertexCoords coordinatesOfSubstituent(vertexCoords pos) const; // holds pointers to all hexagons std::vector m_list; // holds coordinates to vertices marked as pentagonal std::vector pentagonVertices; private: /* mark vertex as pentagon (i.e. fuse it with neighbor vertex) */ void setPentagon(vertexCoords c); /* resize the grid to new size i */ void resizeGrid(int i) const; /* reassign hexagons to the grid */ void reassignHexs() const; /* get index of hexagon at the given coordinates */ int getIndexInList(hexCoords coords) const; /* hold pointers to all positions in the grid, NULL pointers for empty positions */ std::vector mutable m_grid; /* size of the grid */ mutable int m_gridSize; }; /* class that builds coordinates for macrocycles */ class EXPORT_COORDGEN CoordgenMacrocycleBuilder { public: CoordgenMacrocycleBuilder() = default; ~CoordgenMacrocycleBuilder() = default; /* assign coordinates to macrocycle */ std::vector newMacrocycle(sketcherMinimizerRing* r, std::vector atoms) const; /* assign coordinates by removing one bond, generating the coordinates of the resulting molecule and re-adding the missing bond */ bool openCycleAndGenerateCoords(sketcherMinimizerRing* ring) const; /* find most suitable bond to be broken */ sketcherMinimizerBond* findBondToOpen(sketcherMinimizerRing* ring) const; /* Add constraints to stereoactive double bonds to avoid inversions public to be accessed by tests */ std::vector getDoubleBondConstraints(std::vector& atoms) const; /* Skip the polyomino approach and fall back to opening the macrocycle when * generating coordinates */ bool m_forceOpenMacrocycles = false; float getPrecision() const; void setPrecision(float f); private: /* precision of calculation. Higher values result in better results but longer calculation times */ float m_precision; /* build polyominos with the given number of vertices */ std::vector buildSquaredShapes(int totVertices) const; /* remove duplicate polyominos from the list */ std::vector removeDuplicates(std::vector& pols) const; std::vector getRingConstraints(std::vector& atoms) const; /* get total number of atoms bound to a that are not on parent size */ int getNumberOfChildren(sketcherMinimizerAtom* a, sketcherMinimizerAtom* parent) const; /* get restraints to try to avoid things like having heteroatoms or * substituents pointing inside of the macrocycle */ pathRestraints getPathRestraints(std::vector& atoms) const; /* a shape is not allowed to break a constraint (i.e. invert stereochemistry on a double bond or put a fused ring inside the macrocycle) */ pathConstraints getPathConstraints(std::vector& atoms) const; /* build a list of polyominoes with the same number of vertices by removing * hexagons with 3 neighbors */ std::vector listOfEquivalent(const Polyomino& p) const; std::vector listOfEquivalents(const std::vector& l) const; /* check that no ring constraints are violated */ bool checkRingConstraints(std::vector& ringConstraints, Polyomino& p, std::vector& path, std::vector& neighborNs, int& startI) const; /* check that no double bond constraints are violated */ bool checkDoubleBoundConstraints( std::vector& dbConstraints, std::vector& vertices, int& startI) const; /* score the path restraints */ int scorePathRestraints(pathRestraints& pr, Polyomino& p, std::vector& path, std::vector& neighborNs, int& startI) const; /* check that no path constraints are violated */ bool scorePathConstraints(pathConstraints& pc, Polyomino& p, std::vector& path, std::vector& neighborNs, int& startI) const; /* score restraints and constraints of the given path */ int scorePath(Polyomino& p, std::vector& path, std::vector& neighborNs, int& startI, pathConstraints& pc, pathRestraints& pr) const; /* acceptable score to consider a shape appropriate */ int acceptableShapeScore(int numberOfAtoms) const; std::vector getVertexNeighborNs(Polyomino& p, std::vector& path) const; /* return lowest period after which there is a rotation symmetry */ int getLowestPeriod(std::vector& neighbors) const; /* explore the given polyominoes and score them */ bool matchPolyominoes(std::vector& pols, pathConstraints& pc, pathRestraints& pr, int& bestP, int& bestScore, int& bestStart, int& checkedMacrocycles) const; /* explore the best starting point to place atoms around the given polyomino */ bool matchPolyomino(Polyomino& p, pathConstraints& pc, pathRestraints& pr, int& bestStart, int& bestScore) const; /* write the coordinates of the given path */ void writePolyominoCoordinates(std::vector& path, const std::vector& atoms, int startI) const; /* return the coordinates of the given vertex */ sketcherMinimizerPointF coordsOfVertex(vertexCoords& v) const; }; #endif /* defined(COORDGEN_MACROCYCLE_BUILDER_H) */ coordgenlibs-3.0.2/CoordgenMinimizer.cpp000066400000000000000000001702661436654770400203520ustar00rootroot00000000000000/* Contributors: Nicola Zonta Copyright Schrodinger, LLC. All rights reserved */ #include "CoordgenMinimizer.h" #include "sketcherMinimizer.h" // should be removed at the end of refactoring #include "sketcherMinimizerAtom.h" #include "sketcherMinimizerBendInteraction.h" #include "sketcherMinimizerBond.h" #include "sketcherMinimizerClashInteraction.h" #include "sketcherMinimizerConstraintInteraction.h" #include "sketcherMinimizerEZConstrainInteraction.h" #include "sketcherMinimizerFragment.h" #include "sketcherMinimizerMaths.h" #include "sketcherMinimizerResidue.h" #include "sketcherMinimizerResidueInteraction.h" #include "sketcherMinimizerRing.h" #include "sketcherMinimizerStretchInteraction.h" #include #include #include using namespace std; static const float bondLength = BONDLENGTH; static const float clashEnergyThreshold = 10; #define SAME_SIDE_DPR_PENALTY 100 #define SAME_SIDE_DPR_PENALTY_2 50 static const float FORCE_MULTIPLIER = 0.3f; static const float STANDARD_CROSSING_BOND_PENALTY = 2500.f; static const float TERMINAL_BOND_CROSSING_MULTIPLIER = 0.5f; static const float MACROCYCLE_BOND_CROSSING_MULTIPLIER = 8.f; static const float RING_BOND_CROSSING_MULTIPLIER = 2.f; static const unsigned int MAXIMUM_NUMBER_OF_SCORED_SOLUTIONS = 10000; static const float REJECTED_SOLUTION_SCORE = 99999999.f; static const unsigned int ITERATION_HISTORY_SIZE = 100; static const float MAX_NET_ENERGY_CHANGE = 20.f; CoordgenMinimizer::CoordgenMinimizer() { m_maxIterations = 1000; skipMinimization = false; skipFlipFragments = false; skipAvoidClashes = false; m_scoreResidueInteractions = true; m_precision = 1.f; energy_list = {}; all_coordinates = {}; } CoordgenMinimizer::~CoordgenMinimizer() { clearInteractions(); } void CoordgenMinimizer::clearInteractions() { for (auto& _interaction : _interactions) { delete _interaction; } _interactions.clear(); _intramolecularClashInteractions.clear(); _extraInteractions.clear(); _stretchInteractions.clear(); _bendInteractions.clear(); } void CoordgenMinimizer::run() { if (skipMinimization) { return; } if (_interactions.empty()) { setupInteractions(); } #ifdef DEBUG_MINIMIZATION_COORDINATES // to seperate energy and DOF minimization energy_list.push_back(-1.f); all_coordinates.push_back({sketcherMinimizerPointF(0,0)}); #endif std::vector local_energy_list(m_maxIterations); std::vector lowest_energy_coords(m_atoms.size()); float min_energy = std::numeric_limits::max(); for (unsigned int iterations = 0; iterations < m_maxIterations; ++iterations) { local_energy_list[iterations] = scoreInteractions(); // track coordinates with lowest energy if (local_energy_list[iterations] < min_energy) { for (size_t i = 0; i < m_atoms.size(); ++i) { lowest_energy_coords[i] = m_atoms[i]->coordinates; } } #ifdef DEBUG_MINIMIZATION_COORDINATES // store data from this minimization step to be written to a file later energy_list.push_back(local_energy_list[iterations]); std::vector these_coordinates; for (auto atom : m_atoms) { these_coordinates.push_back(atom->coordinates); } all_coordinates.push_back(these_coordinates); #endif if (!applyForces(0.1f)) { break; } if (iterations < 2 * ITERATION_HISTORY_SIZE) { continue; } if (local_energy_list[iterations - ITERATION_HISTORY_SIZE] - local_energy_list[iterations] < MAX_NET_ENERGY_CHANGE) { break; } } // set coordinates back to lowest energy state if (min_energy < std::numeric_limits::max()) { for (size_t i = 0; i < m_atoms.size(); ++i) { m_atoms[i]->coordinates = lowest_energy_coords[i]; } } } bool CoordgenMinimizer::applyForces(float maxd) { float delta = 0.001f; // minimum squared displacement float distance = 0.f; for (auto atom : m_atoms) { if (atom->fixed) { continue; } sketcherMinimizerPointF displacement = atom->force * FORCE_MULTIPLIER; if (displacement.x() != displacement.x() || displacement.y() != displacement.y()) { displacement = sketcherMinimizerPointF(0.f, 0.f); } float dsquare = displacement.x() * displacement.x() + displacement.y() * displacement.y(); if (dsquare < SKETCHER_EPSILON) { dsquare = SKETCHER_EPSILON; } if (dsquare > maxd * maxd) { displacement *= maxd / sqrt(dsquare); } atom->coordinates += displacement; distance += displacement.squareLength(); atom->force = sketcherMinimizerPointF(0, 0); } return distance >= delta; } /* store extra interaction to be used when minimizing molecule. cis amides constraints are an example as they need 3d coordinates to be detected */ void CoordgenMinimizer::addExtraInteraction( sketcherMinimizerMolecule* molecule, sketcherMinimizerInteraction* interaction) { _extraInteractionsOfMolecule[molecule].push_back(interaction); } void CoordgenMinimizer::addClashInteractionsOfMolecule( sketcherMinimizerMolecule* molecule, bool intrafragmentClashes) { vector atoms = molecule->getAtoms(); vector bonds = molecule->getBonds(); if (atoms.size() > 1) { for (sketcherMinimizerAtom* atom : atoms) { if (atom->isResidue()) { continue; } for (sketcherMinimizerBond* bond : bonds) { if (bond->isResidueInteraction()) { continue; } sketcherMinimizerAtom* at2 = atom; sketcherMinimizerAtom* at1 = bond->startAtom; sketcherMinimizerAtom* at3 = bond->endAtom; if (at1 == at2 || at1 == at3 || at2 == at3) { continue; } if (at1->fragment->getDofsOfAtom(at1).empty() && at2->fragment->getDofsOfAtom(at2).empty() && at3->fragment->getDofsOfAtom(at3).empty() && !intrafragmentClashes) { if (at1->fragment == at2->fragment) { continue; } if (at3->fragment == at2->fragment) { continue; } } if (at2->fixed && at1->fixed && at3->fixed) { continue; } if (at1->isNeighborOf(at2)) { continue; } for (sketcherMinimizerAtom* n : at1->neighbors) { if (n->isNeighborOf(at2)) { continue; } } if (at3->isNeighborOf(at2)) { continue; } for (sketcherMinimizerAtom* n : at3->neighbors) { if (n->isNeighborOf(at2)) { continue; } } if (!(at1->rigid && at2->rigid && at3->rigid)) { // } auto* interaction = new sketcherMinimizerClashInteraction(at1, at2, at3); float restVK = 0.8f; if (at2->atomicNumber == 6 && at2->charge == 0) { restVK -= 0.1f; } if (at1->atomicNumber == 6 && at1->charge == 0 && at3->atomicNumber == 6 && at3->charge == 0) { restVK -= 0.1f; } interaction->restV = (bondLength * restVK) * (bondLength * restVK); _intramolecularClashInteractions.push_back(interaction); _interactions.push_back(interaction); } } } } } void CoordgenMinimizer::addStretchInteractionsOfMolecule( sketcherMinimizerMolecule* molecule) { vector bonds = molecule->getBonds(); for (sketcherMinimizerBond* bo : bonds) { if (bo->isResidueInteraction()) { continue; } sketcherMinimizerAtom* at1 = bo->startAtom; sketcherMinimizerAtom* at2 = bo->endAtom; auto* interaction = new sketcherMinimizerStretchInteraction(at1, at2); interaction->k *= 0.1f; interaction->restV = bondLength; if (at1->rigid && at2->rigid) { sketcherMinimizerPointF v = at2->coordinates - at1->coordinates; interaction->restV = v.length(); } auto sharedRing = sketcherMinimizer::sameRing(at1, at2); if (sharedRing && !sharedRing->isMacrocycle()) { interaction->k *= 50; } _interactions.push_back(interaction); _stretchInteractions.push_back(interaction); } } /* return a set of all carbons part of a carbonyl group, i.e. doubly bonded to * an oxygen. */ std::set CoordgenMinimizer::getChetoCs( const std::vector& allAtoms) const { std::set chetoCs; for (auto atom : allAtoms) { if (atom->atomicNumber != 6) { continue; } for (auto bondedAtom : atom->neighbors) { if (bondedAtom->atomicNumber == 8) { auto bond = sketcherMinimizer::getBond(atom, bondedAtom); if (bond && bond->bondOrder == 2) { chetoCs.insert(atom); continue; } } } } return chetoCs; } /* return a set of all amino nitrogens. Not chemically accurate, doesn't filter * out nitro Ns for instance. */ std::set CoordgenMinimizer::getAminoNs( const std::vector& allAtoms) const { std::set aminoNs; for (auto atom : allAtoms) { if (atom->atomicNumber == 7) { aminoNs.insert(atom); } } return aminoNs; } /* return a set of all aminoacid alpha carbon, i.e. a carbon that is bound to a nitrogen and a cheto carbon. */ std::set CoordgenMinimizer::getAlphaCs( const std::vector& allAtoms, const std::set& chetoCs, const std::set& aminoNs) const { std::set alphaCs; for (auto atom : allAtoms) { bool bondedToCheto = false; bool bondedToAminoN = false; if (atom->atomicNumber != 6) { continue; } if (chetoCs.find(atom) != chetoCs.end()) { continue; } for (auto bondedAtom : atom->neighbors) { if (chetoCs.find(bondedAtom) != chetoCs.end()) { bondedToCheto = true; } if (aminoNs.find(bondedAtom) != aminoNs.end()) { bondedToAminoN = true; } } if (bondedToCheto && bondedToAminoN) { alphaCs.insert(atom); } } return alphaCs; } /* add constraints to keep all backbone atoms of a peptide in a straight trans * line. */ void CoordgenMinimizer::addPeptideBondInversionConstraintsOfMolecule( sketcherMinimizerMolecule* molecule) { auto atoms = molecule->getAtoms(); auto chetoCs = getChetoCs(atoms); if (chetoCs.size() < 2) { return; } auto aminoNs = getAminoNs(atoms); if (aminoNs.size() < 2) { return; } auto alphaCs = getAlphaCs(atoms, chetoCs, aminoNs); if (alphaCs.size() < 2) { return; } std::vector> consecutiveAtomsGroups; getFourConsecutiveAtomsThatMatchSequence(consecutiveAtomsGroups, chetoCs, aminoNs, alphaCs, chetoCs); getFourConsecutiveAtomsThatMatchSequence(consecutiveAtomsGroups, aminoNs, alphaCs, chetoCs, aminoNs); getFourConsecutiveAtomsThatMatchSequence(consecutiveAtomsGroups, alphaCs, chetoCs, aminoNs, alphaCs); for (auto torsionAtoms : consecutiveAtomsGroups) { bool cis = false; auto interaction = new sketcherMinimizerEZConstrainInteraction( torsionAtoms[0], torsionAtoms[1], torsionAtoms[2], torsionAtoms[3], cis); _extraInteractions.push_back(interaction); _interactions.push_back(interaction); } } /* find chains of four bound atoms that are part of the four provided sets. Useful to detect portions of a peptide backbone for instance. */ void CoordgenMinimizer::getFourConsecutiveAtomsThatMatchSequence( std::vector>& consecutiveAtomsGroups, const std::set& firstSet, const std::set& secondSet, const std::set& thirdSet, const std::set& fourthSet) const { for (auto firstAtom : firstSet) { for (auto secondAtom : firstAtom->neighbors) { if (secondSet.find(secondAtom) == secondSet.end()) { continue; } for (auto thirdAtom : secondAtom->neighbors) { if (thirdSet.find(thirdAtom) == thirdSet.end()) { continue; } for (auto fourthAtom : thirdAtom->neighbors) { if (fourthSet.find(fourthAtom) == fourthSet.end()) { continue; } std::vector fourMatchingAtoms(4); fourMatchingAtoms.at(0) = firstAtom; fourMatchingAtoms.at(1) = secondAtom; fourMatchingAtoms.at(2) = thirdAtom; fourMatchingAtoms.at(3) = fourthAtom; consecutiveAtomsGroups.push_back(fourMatchingAtoms); } } } } } void CoordgenMinimizer::addConstrainedInteractionsOfMolecule( sketcherMinimizerMolecule* molecule) { for (auto atom : molecule->getAtoms()) { if (atom->constrained) { auto interaction = new sketcherMinimizerConstraintInteraction( atom, atom->templateCoordinates); _intramolecularClashInteractions.push_back(interaction); _interactions.push_back(interaction); } } } void CoordgenMinimizer::addChiralInversionConstraintsOfMolecule( sketcherMinimizerMolecule* molecule) { for (auto ring : molecule->getRings()) { if (ring->isMacrocycle()) { vector atoms = CoordgenFragmentBuilder::orderRingAtoms(ring); for (unsigned int i = 0; i < atoms.size(); i++) { int size = static_cast(atoms.size()); int a1 = (i - 1 + size) % size; int a11 = (i - 2 + size) % size; int a2 = (i + 1) % size; sketcherMinimizerBond* bond = sketcherMinimizer::getBond(atoms[a1], atoms[i]); if (bond->isStereo()) { bool cis = bond->markedAsCis(atoms[a11], atoms[a2]); auto* ezint = new sketcherMinimizerEZConstrainInteraction( atoms[a11], atoms[a1], atoms[i], atoms[a2], cis); _interactions.push_back(ezint); } } } } } void CoordgenMinimizer::addBendInteractionsOfMolecule( sketcherMinimizerMolecule* molecule) { vector atoms = molecule->getAtoms(); vector bonds = molecule->getBonds(); for (sketcherMinimizerAtom* at : atoms) { vector interactions; vector ringInteractions; vector nonRingInteractions; int nbonds = static_cast(at->neighbors.size()); bool invertedMacrocycleBond = false; if (nbonds > 1) { // order bonds so that they appear in clockwise order. vector orderedNeighs = at->clockwiseOrderedNeighbors(); float angle = 120.f; if (nbonds == 2) { if (at->bonds[0]->bondOrder + at->bonds[1]->bondOrder > 3) { angle = 180.f; } } if (nbonds > 2) { angle = 360.f / nbonds; } for (int i = 0; i < nbonds; i++) { int j = (i - 1 + nbonds) % nbonds; if (nbonds == 2 && i == 1) { continue; // first and last interaction are the same if } // there is just one interaction sketcherMinimizerAtom* at1 = orderedNeighs[i]; sketcherMinimizerAtom* at2 = at; sketcherMinimizerAtom* at3 = orderedNeighs[j]; auto* interaction = new sketcherMinimizerBendInteraction(at1, at2, at3); interactions.push_back(interaction); interaction->restV = angle; sketcherMinimizerRing* r = sketcherMinimizer::sameRing( at, orderedNeighs[i], orderedNeighs[j]); if (r) { if (!r->isMacrocycle()) { int extraAtoms = 0; /* if the rings are to be drawn as fused, they will * result in a bigger ring */ for (unsigned int i = 0; i < r->fusedWith.size(); i++) { if (r->fusedWith[i]->isMacrocycle()) { continue; } if (r->fusionAtoms[i].size() > 2) { extraAtoms += static_cast( r->fusedWith[i]->_atoms.size() - r->fusionAtoms[i].size()); } } interaction->isRing = true; interaction->k *= 100; interaction->restV = static_cast( 180. - (360. / (r->size() + extraAtoms))); ringInteractions.push_back(interaction); } else { if (nbonds == 3) { sketcherMinimizerAtom* otherAtom = nullptr; for (auto atom : orderedNeighs) { if (atom != at1 && atom != at3) { otherAtom = atom; break; } } if (otherAtom) { if (sketcherMinimizerMaths::sameSide( at3->coordinates, otherAtom->coordinates, at1->coordinates, at2->coordinates)) { invertedMacrocycleBond = true; } } } bool fusedToRing = false; if (orderedNeighs.size() > 2) { fusedToRing = true; } for (auto atom : orderedNeighs) { if (!sketcherMinimizer::sameRing(at, atom)) { fusedToRing = false; break; } } if (fusedToRing || invertedMacrocycleBond) { ringInteractions.push_back(interaction); } else { /* macrocycles are treated as non rings */ nonRingInteractions.push_back(interaction); } } } else { nonRingInteractions.push_back(interaction); } if (interaction->atom1->rigid && interaction->atom2->rigid && interaction->atom3->rigid) { interaction->restV = sketcherMinimizerMaths::unsignedAngle( interaction->atom1->coordinates, interaction->atom2->coordinates, interaction->atom3->coordinates); } } } if (ringInteractions.size() != 1 || nonRingInteractions.size() != 2) { invertedMacrocycleBond = false; } if (!ringInteractions.empty()) { // subtract all the ring angles from 360 // and divide the remaining equally // between the other interactions float totalAngleInRings = 0; for (sketcherMinimizerBendInteraction* i : ringInteractions) { totalAngleInRings += i->restV; } if (invertedMacrocycleBond) { totalAngleInRings = 360 - totalAngleInRings; } for (sketcherMinimizerBendInteraction* i : nonRingInteractions) { i->restV = (360 - totalAngleInRings) / nonRingInteractions.size(); } } else { // do nothing if 1 or 3 interactions (defaults to 120 degrees) // if 4 or more set angles accordingly if (nonRingInteractions.size() == 4) { if (at->crossLayout || m_evenAngles) { nonRingInteractions[0]->restV = 90; nonRingInteractions[1]->restV = 90; nonRingInteractions[2]->restV = 90; nonRingInteractions[3]->restV = 90; } else { int indexOfBiggestAngle = 0; float biggestAngle = 0; int counter = 0; for (auto interaction : nonRingInteractions) { float angle = sketcherMinimizerMaths::unsignedAngle( interaction->atom1->coordinates, interaction->atom2->coordinates, interaction->atom3->coordinates); if (angle > biggestAngle) { biggestAngle = angle; indexOfBiggestAngle = counter; } counter++; } nonRingInteractions[indexOfBiggestAngle]->restV = 120; nonRingInteractions[(indexOfBiggestAngle + 1) % 4]->restV = 90; nonRingInteractions[(indexOfBiggestAngle + 2) % 4]->restV = 60; nonRingInteractions[(indexOfBiggestAngle + 3) % 4]->restV = 90; } } else if (nonRingInteractions.size() > 4) { for (sketcherMinimizerBendInteraction* i : nonRingInteractions) { i->restV = static_cast(360. / nonRingInteractions.size()); } } } for (auto interaction : interactions) { if (!(interaction->atom1->fixed && interaction->atom2->fixed && interaction->atom3->fixed)) { _interactions.push_back(interaction); _bendInteractions.push_back(interaction); } else { delete interaction; } } } } void CoordgenMinimizer::minimizeMolecule(sketcherMinimizerMolecule* molecule) { std::map previousCoordinates; for (auto atom : molecule->getAtoms()) { previousCoordinates[atom] = atom->getCoordinates(); } clearInteractions(); addInteractionsOfMolecule(molecule, true); run(); for (auto bond : molecule->getBonds()) { if (!bond->checkStereoChemistry()) { for (auto atom : molecule->getAtoms()) { atom->setCoordinates(previousCoordinates[atom]); } break; } } } void CoordgenMinimizer::minimizeResidues() { setupInteractionsOnlyResidues(); run(); } void CoordgenMinimizer::minimizeProteinOnlyLID( const std::map>& chains) { setupInteractionsProteinOnly(chains); run(); } void CoordgenMinimizer::minimizeAll() { setupInteractions(true); run(); } void CoordgenMinimizer::addInteractionsOfMolecule( sketcherMinimizerMolecule* molecule, bool intrafragmentClashes) { addClashInteractionsOfMolecule(molecule, intrafragmentClashes); addStretchInteractionsOfMolecule(molecule); addBendInteractionsOfMolecule(molecule); addChiralInversionConstraintsOfMolecule(molecule); } void CoordgenMinimizer::setupInteractionsOnlyResidues() { const float CLASH_DISTANCE = bondLength * 1.5f; for (auto res : m_residues) { for (auto res2 : m_residues) { if (res2 >= res) { continue; } auto* minimizerInteraction = new sketcherMinimizerClashInteraction(res, res2, res); minimizerInteraction->restV = CLASH_DISTANCE * CLASH_DISTANCE; _interactions.push_back(minimizerInteraction); } } } void CoordgenMinimizer::setupInteractionsProteinOnly( const std::map>& chains) { clearInteractions(); std::set interactions; std::set residues; for (const auto& chain : chains) { for (auto res : chain.second) { residues.insert(res); for (auto interaction : res->residueInteractions) { interactions.insert(interaction); } } } for (auto res : residues) { for (auto interaction : interactions) { if (res == interaction->startAtom || res == interaction->endAtom) { continue; } auto* minimizerInteraction = new sketcherMinimizerClashInteraction( interaction->startAtom, res, interaction->endAtom); minimizerInteraction->restV = bondLength * bondLength; _interactions.push_back(minimizerInteraction); } } } void CoordgenMinimizer::setupInteractions(bool intrafragmentClashes) { clearInteractions(); for (sketcherMinimizerMolecule* molecule : m_molecules) { addInteractionsOfMolecule(molecule, intrafragmentClashes); } } float CoordgenMinimizer::scoreInteractions() { float totalEnergy = 0.f; for (auto interaction : _interactions) { interaction->score(totalEnergy); } return totalEnergy; } // returns true if the two molecules have a atom-atoms or atom-bond pair with // distance < threshold or crossing bonds bool CoordgenMinimizer::findIntermolecularClashes( sketcherMinimizerMolecule* mol1, sketcherMinimizerMolecule* mol2, float threshold) { // could be made faster for instance checking the molecules bounding boxes // first if (mol1 == mol2) { return false; } float threshold2 = threshold * threshold; for (sketcherMinimizerAtom* a : mol1->_atoms) { for (sketcherMinimizerAtom* a2 : mol2->_atoms) { if (sketcherMinimizerMaths::squaredDistance( a->coordinates, a2->coordinates) < threshold2) { return true; } } } for (sketcherMinimizerAtom* a : mol1->_atoms) { for (sketcherMinimizerBond* b : mol2->_bonds) { if (sketcherMinimizerMaths::squaredDistancePointSegment( a->coordinates, b->startAtom->coordinates, b->endAtom->coordinates) < threshold2) { return true; } } } for (sketcherMinimizerAtom* a : mol2->_atoms) { for (sketcherMinimizerBond* b : mol1->_bonds) { if (sketcherMinimizerMaths::squaredDistancePointSegment( a->coordinates, b->startAtom->coordinates, b->endAtom->coordinates) < threshold2) { return true; } } } for (sketcherMinimizerBond* b : mol1->_bonds) { for (sketcherMinimizerBond* b2 : mol2->_bonds) { if (sketcherMinimizerMaths::intersectionOfSegments( b->startAtom->coordinates, b->endAtom->coordinates, b2->startAtom->coordinates, b2->endAtom->coordinates)) { return true; } } } return false; } bool CoordgenMinimizer::findIntermolecularClashes( const vector& mols, float threshold) { for (unsigned int i = 0; i < mols.size(); i++) { for (unsigned int j = i + 1; j < mols.size(); j++) { if (findIntermolecularClashes(mols[i], mols[j], threshold)) { return true; } } } return false; } float CoordgenMinimizer::scoreClashes( sketcherMinimizerMolecule* molecule, bool residueInteractions, bool scoreProximityRelationsOnOppositeSid) const { float E = 0.f; for (auto i : _intramolecularClashInteractions) { i->score(E, true); } for (sketcherMinimizerInteraction* i : _extraInteractions) { i->score(E, true); } E += scoreDofs(molecule); E += scoreCrossBonds(molecule, residueInteractions); E += scoreAtomsInsideRings(); if (scoreProximityRelationsOnOppositeSid) { E += scoreProximityRelationsOnOppositeSides(); } return E; } float CoordgenMinimizer::scoreDofs(sketcherMinimizerMolecule* molecule) const { float E = 0.f; for (const auto& fragment : molecule->getFragments()) { for (const auto& dof : fragment->getDofs()) { E += dof->getCurrentPenalty(); } } return E; } float CoordgenMinimizer::scoreCrossBonds(sketcherMinimizerMolecule* molecule, bool residueInteractions) const { if (!m_scoreResidueInteractions) { residueInteractions = false; } float out = 0.f; vector bonds = molecule->getBonds(); if (molecule->getBonds().size() > 2) { for (unsigned int b = 0; b < bonds.size() - 1; b++) { sketcherMinimizerBond* b1 = bonds[b]; if (b1->isResidueInteraction()) { continue; } for (unsigned int bb = b + 1; bb < bonds.size(); bb++) { sketcherMinimizerBond* b2 = bonds[bb]; if (b2->isResidueInteraction()) { continue; } if (b2->startAtom->molecule != b1->startAtom->molecule) { continue; } if (bondsClash(b1, b2)) { float penalty = STANDARD_CROSSING_BOND_PENALTY * b1->crossingBondPenaltyMultiplier * b2->crossingBondPenaltyMultiplier; if (b1->isTerminal() || b2->isTerminal()) { penalty *= TERMINAL_BOND_CROSSING_MULTIPLIER; } if (b1->isInMacrocycle() || b2->isInMacrocycle()) { penalty *= MACROCYCLE_BOND_CROSSING_MULTIPLIER; } if (b1->isInSmallRing() || b2->isInSmallRing()) { penalty *= RING_BOND_CROSSING_MULTIPLIER; } out += penalty; } } } } if (!m_residueInteractions.empty() && residueInteractions) { for (auto r : m_residues) { if (r->residueInteractions.size() > 1) { for (unsigned int ri1 = 0; ri1 < r->residueInteractions.size() - 1; ri1++) { for (unsigned int ri2 = 1; ri2 < r->residueInteractions.size(); ri2++) { sketcherMinimizerAtom* a1 = r->residueInteractions[ri1]->endAtom; sketcherMinimizerAtom* a2 = r->residueInteractions[ri2]->endAtom; if (sketcherMinimizerMaths::intersectionOfSegments( a1->coordinates + a1->getSingleAdditionVector() * 0.2f, a2->coordinates + a2->getSingleAdditionVector() * 0.2f, a1->coordinates, a2->coordinates)) { out += 15.f; } for (auto b2 : m_bonds) { if (b2->startAtom == r->residueInteractions[ri1]->endAtom) { continue; } if (b2->endAtom == r->residueInteractions[ri1]->endAtom) { continue; } if (b2->startAtom == r->residueInteractions[ri2]->endAtom) { continue; } if (b2->endAtom == r->residueInteractions[ri2]->endAtom) { continue; } if (sketcherMinimizerMaths::intersectionOfSegments( a1->coordinates, a2->coordinates, b2->startAtom->coordinates, b2->endAtom->coordinates)) { out += 10.f; } } } } } } } return out; } float CoordgenMinimizer::scoreAtomsInsideRings() const { float out = 0.f; float cutOff = bondLength; for (sketcherMinimizerMolecule* m : m_molecules) { for (sketcherMinimizerRing* r : m->_rings) { if (r->_atoms.size() > MACROCYCLE) { continue; } if (r->_atoms.size() < 3) { continue; } sketcherMinimizerPointF c = r->findCenter(); for (sketcherMinimizerAtom* a : m->_atoms) { if (a->fragment == r->_atoms[0]->fragment) { continue; } sketcherMinimizerPointF d = c - a->coordinates; if (d.x() > cutOff) { continue; } if (d.y() > cutOff) { continue; } if (d.x() < -cutOff) { continue; } if (d.y() < -cutOff) { continue; } float sq = d.squareLength(); if (sq > cutOff * cutOff) { continue; } float dist = d.length(); if (dist < cutOff) { out += 50 + 100 * (1 - (dist / cutOff)); } } } } return out; } float CoordgenMinimizer::scoreProximityRelationsOnOppositeSides() const { float out = 0.f; for (sketcherMinimizerMolecule* m : m_molecules) { if (m->_atoms.size() < 2) { continue; } for (unsigned int i = 0; i < m->m_proximityRelations.size(); i++) { sketcherMinimizerPointF v1, v2; sketcherMinimizerMolecule* otherMol1 = nullptr; sketcherMinimizerBond* pr1 = m->m_proximityRelations[i]; sketcherMinimizerFragment* f1 = nullptr; if (pr1->startAtom->molecule == m) { f1 = pr1->startAtom->fragment; v1 = pr1->startAtom->getSingleAdditionVector(); otherMol1 = pr1->endAtom->molecule; } else { f1 = pr1->endAtom->fragment; v1 = pr1->endAtom->getSingleAdditionVector(); otherMol1 = pr1->startAtom->molecule; } if (otherMol1 == m) { continue; } for (unsigned int j = i + 1; j < m->m_proximityRelations.size(); j++) { sketcherMinimizerMolecule* otherMol2 = nullptr; sketcherMinimizerBond* pr2 = m->m_proximityRelations[j]; if (pr2->startAtom->molecule == m) { if (pr2->startAtom->fragment == f1) { continue; } v2 = pr2->startAtom->getSingleAdditionVector(); otherMol2 = pr2->endAtom->molecule; } else { if (pr2->endAtom->fragment == f1) { continue; } v2 = pr2->endAtom->getSingleAdditionVector(); otherMol2 = pr2->startAtom->molecule; } if (otherMol2 == m) { continue; } if (otherMol1 != otherMol2) { continue; } float angle = sketcherMinimizerMaths::unsignedAngle( v1, sketcherMinimizerPointF(0.f, 0.f), v2); if (angle > 90) { out += SAME_SIDE_DPR_PENALTY + SAME_SIDE_DPR_PENALTY_2 * (angle - 90); } } } } return out; } bool CoordgenMinimizer::runExhaustiveSearch(sketcherMinimizerMolecule* molecule, vector dofs, float& clashE, CoordgenDOFSolutions& solutions) { float bestResult = clashE; bool abort = false; runExhaustiveSearchLevel(molecule, dofs.begin(), dofs, bestResult, abort, solutions); for (auto dof : dofs) { dof->setToOptimalValue(); } clashE = bestResult; return (bestResult < clashEnergyThreshold); } void CoordgenMinimizer::runExhaustiveSearchLevel( sketcherMinimizerMolecule* molecule, const vector::iterator& iterator, vector& dofs, float& bestResult, bool& abort, CoordgenDOFSolutions& solutions) { if (abort) { return; } if (iterator == dofs.end()) { float result = solutions.scoreCurrentSolution(); if (result < clashEnergyThreshold) { for (auto dof : dofs) { dof->storeCurrentValueAsOptimal(); } abort = true; } else if (result < bestResult - SKETCHER_EPSILON) { bestResult = result; for (auto dof : dofs) { dof->storeCurrentValueAsOptimal(); } } } else { vector::iterator nextIter = iterator; ++nextIter; for (int i = 0; i < (*iterator)->numberOfStates(); ++i) { runExhaustiveSearchLevel(molecule, nextIter, dofs, bestResult, abort, solutions); (*iterator)->changeState(); } } } std::vector> CoordgenMinimizer::buildTuplesOfDofs(const vector& dofs, unsigned int order) const { std::vector> growingVector, lastOrderVector; for (auto dof : dofs) { std::vector tuple; tuple.push_back(dof); growingVector.push_back(tuple); } for (unsigned int i = 1; i < order; ++i) { lastOrderVector = growingVector; growingVector.clear(); for (auto lastOrderTuple : lastOrderVector) { bool copy = false; for (auto dof : dofs) { if (copy) { auto newTuple = lastOrderTuple; newTuple.push_back(dof); growingVector.push_back(newTuple); } else if (dof == *(lastOrderTuple.rbegin())) { copy = true; } } } } return growingVector; } bool CoordgenMinimizer::growSolutions( std::set>& allScoredSolutions, int& currentTier, std::map, float>& growingSolutions, CoordgenDOFSolutions& solutions, float& bestScore) { std::map, float> oldGrowingSolutions = growingSolutions; float bestScoreForRun = bestScore; std::vector>> bestSolutions; bestSolutions.reserve(growingSolutions.size()); for (const auto& solution : growingSolutions) { bestSolutions.emplace_back(solution.second, solution.first); } sort(bestSolutions.begin(), bestSolutions.end()); growingSolutions.clear(); int maxN = static_cast(6 * getPrecision()); if (maxN < 1) { maxN = 1; } int n = 0; for (const auto& solution : bestSolutions) { if (n > maxN) { break; } for (auto dof : solutions.getAllDofs()) { if (dof->tier() > currentTier) { continue; } solutions.loadSolution(solution.second); for (int i = 1; i < dof->numberOfStates(); ++i) { dof->changeState(); auto newSolution = solutions.getCurrentSolution(); if (allScoredSolutions.find(newSolution) == allScoredSolutions.end()) { float score = solutions.scoreCurrentSolution(); if (score == REJECTED_SOLUTION_SCORE) { return false; } allScoredSolutions.insert(newSolution); if (score < bestScore) { bestScore = score; } if (score < bestScoreForRun && score < REJECTED_SOLUTION_SCORE) { growingSolutions[newSolution] = score; } } } } n++; } if (growingSolutions.empty() && currentTier < 5) { currentTier += 3; growingSolutions = oldGrowingSolutions; } return true; } bool CoordgenMinimizer::runSearch(int tier, CoordgenDOFSolutions& solutions) { std::map, float> growingSolutions; std::set> allScoredSolutions; float bestScore = solutions.scoreCurrentSolution(); growingSolutions[solutions.getCurrentSolution()] = bestScore; int i = 0; bool hasValidSolution = true; do { #ifdef DEBUG_MINIMIZATION_COORDINATES // store data from this minimization step to be written to a file later energy_list.push_back(solutions.scoreCurrentSolution()); std::vector these_coordinates; for (auto atom : _atoms) { these_coordinates.push_back(atom->coordinates); } all_coordinates.push_back(these_coordinates); #endif ++i; hasValidSolution = growSolutions( allScoredSolutions, tier, growingSolutions, solutions, bestScore); } while ((hasValidSolution && !growingSolutions.empty()) && i < 100); std::pair, float> bestSolution = solutions.findBestSolution(); solutions.loadSolution(bestSolution.first); return bestSolution.second < clashEnergyThreshold; } bool CoordgenMinimizer::runLocalSearch(sketcherMinimizerMolecule* molecule, const vector& dofs, int levels, float& clashE, CoordgenDOFSolutions& solutions) { bool downhill = false; auto combinationsOfDofs = buildTuplesOfDofs(dofs, levels); do { downhill = false; for (const auto& combinationOfDofs : combinationsOfDofs) { float lastResult = clashE; bool foundOptimalPosition = runExhaustiveSearch( molecule, combinationOfDofs, clashE, solutions); if (foundOptimalPosition) { return true; } else if (clashE < lastResult - SKETCHER_EPSILON) { downhill = true; } } } while (downhill); return false; } bool CoordgenMinimizer::flipFragments(sketcherMinimizerMolecule* molecule, float& clashE) { float bestResult = clashE; if (skipFlipFragments) { return true; } if (bestResult < clashEnergyThreshold) { return true; } vector dofs, onlyFlipDofs; vector fragments = molecule->getFragments(); reverse(fragments.begin(), fragments.end()); for (auto fragment : fragments) { if (!fragment->fixed) { for (auto dof : fragment->getDofs()) { if (dof->numberOfStates() > 1) { dofs.push_back(dof); if (dof == *(fragment->getDofs().begin())) { onlyFlipDofs.push_back(dof); } } } } } CoordgenDOFSolutions solutions(this, molecule, dofs); bool cleanPose = runSearch(0, solutions); // if (!cleanPose) cleanPose = runSearch(6, solutions); buildMoleculeFromFragments(molecule, false); return cleanPose; } bool CoordgenMinimizer::avoidClashesOfMolecule( sketcherMinimizerMolecule* molecule, const std::vector& extraInteractions) { clearInteractions(); addClashInteractionsOfMolecule(molecule, false); addPeptideBondInversionConstraintsOfMolecule(molecule); for (sketcherMinimizerInteraction* interaction : extraInteractions) { _interactions.push_back(interaction); _extraInteractions.push_back(interaction); } for (auto interaction : _extraInteractionsOfMolecule[molecule]) { _extraInteractions.push_back(interaction); _interactions.push_back(interaction); } bool scoreResidueInteractions = true; bool doNotComputeForces = true; float clashE = scoreClashes(molecule, scoreResidueInteractions, doNotComputeForces); bool cleanPose = flipFragments(molecule, clashE); if (!cleanPose) { avoidTerminalClashes(molecule, clashE); molecule->requireMinimization(); } if (molecule->minimizationIsRequired()) { minimizeMolecule(molecule); } return cleanPose; } bool CoordgenMinimizer::avoidClashes() { bool allCleanPoses = true; if (skipAvoidClashes) { return true; } for (sketcherMinimizerMolecule* molecule : m_molecules) { auto cleanPose = avoidClashesOfMolecule(molecule); allCleanPoses = allCleanPoses && cleanPose; } return allCleanPoses; } void CoordgenMinimizer::avoidInternalClashes( sketcherMinimizerFragment* fragment) { // avoid intraFragmentClashes vector fragmentAtoms = fragment->getAtoms(); for (sketcherMinimizerAtom* a : fragmentAtoms) { if (a->neighbors.size() != 1) { continue; } if (a->needsCheckForClashes) { continue; } if (a->fixed) { continue; } if (!fragment->getDofsOfAtom(a).empty()) { continue; } for (sketcherMinimizerAtom* a2 : fragmentAtoms) { if (a == a2) { continue; } if (!fragment->getDofsOfAtom(a2).empty()) { continue; } if (sketcherMinimizer::getBond(a, a2)) { continue; } float dx = a2->coordinates.x() - a->coordinates.x(); if (dx > bondLength * 0.5f) { continue; } if (dx < -bondLength * 0.5f) { continue; } float dy = a2->coordinates.y() - a->coordinates.y(); if (dy > bondLength * 0.5f) { continue; } if (dy < -bondLength * 0.5f) { continue; } float squareD = dx * dx + dy * dy; if (squareD > bondLength * 0.5f * bondLength * 0.5f) { continue; } sketcherMinimizerPointF vec = a->coordinates - a->neighbors[0]->coordinates; vec *= 0.3f; a->coordinates -= vec; if (a2->neighbors.size() == 1) { a2->coordinates += vec; a2->coordinates.round(); } } } } bool CoordgenMinimizer::bondsClash(sketcherMinimizerBond* bond, sketcherMinimizerBond* bond2) const { if (bond == bond2) { return false; } if (bond->getStartAtom() == bond2->getStartAtom() || bond->getStartAtom() == bond2->getEndAtom() || bond->getEndAtom() == bond2->getStartAtom() || bond->getEndAtom() == bond2->getEndAtom()) { return false; } auto& start1 = bond->getStartAtom()->coordinates; auto& start2 = bond2->getStartAtom()->coordinates; auto& end1 = bond->getEndAtom()->coordinates; auto& end2 = bond2->getEndAtom()->coordinates; // coincidence and intersection calculations are expensive. Often bonds // are nowhere near each other, so skip the remaining work if a bond is // strictly to the left or right of another bond. if (max(start1.x(), end1.x()) < min(start2.x(), end2.x()) || max(start1.y(), end1.y()) < min(start2.y(), end2.y()) || min(start1.x(), end1.x()) > max(start2.x(), end2.x()) || min(start1.y(), end1.y()) > max(start2.y(), end2.y())) { return false; } if (sketcherMinimizerMaths::pointsCoincide( bond->getStartAtom()->coordinates, bond2->getStartAtom()->coordinates) || sketcherMinimizerMaths::pointsCoincide( bond->getStartAtom()->coordinates, bond2->getEndAtom()->coordinates) || sketcherMinimizerMaths::pointsCoincide( bond->getEndAtom()->coordinates, bond2->getStartAtom()->coordinates) || sketcherMinimizerMaths::pointsCoincide( bond->getEndAtom()->coordinates, bond2->getEndAtom()->coordinates)) { return true; } return (sketcherMinimizerMaths::intersectionOfSegments( bond->startAtom->coordinates, bond->endAtom->coordinates, bond2->startAtom->coordinates, bond2->endAtom->coordinates)); } void CoordgenMinimizer::avoidTerminalClashes( sketcherMinimizerMolecule* molecule, float& clashE) { if (clashE < 0.1) { return; } for (auto bond : molecule->getBonds()) { if (bond->isResidueInteraction()) { continue; } if (!bond->isTerminal()) { continue; } sketcherMinimizerAtom* terminalAtom = bond->getEndAtom(); sketcherMinimizerAtom* rootAtom = bond->getStartAtom(); if (terminalAtom->getBonds().size() != 1) { terminalAtom = bond->getStartAtom(); rootAtom = bond->getEndAtom(); } if (terminalAtom->fixed) { continue; } for (auto bond2 : molecule->getBonds()) { if (bond2->isResidueInteraction()) { continue; } if (bondsClash(bond, bond2)) { terminalAtom->setCoordinates(rootAtom->getCoordinates() + (terminalAtom->getCoordinates() - rootAtom->getCoordinates()) * 0.1); } } } clashE = scoreClashes(molecule); } void CoordgenMinimizer::maybeMinimizeRings( const vector& rings) { bool found = false; for (auto r : rings) { if (r->_atoms.size() == 5) { for (auto& _atom : r->_atoms) { if (_atom->rings.size() > 2) { found = true; } } } if (r->isMacrocycle() && r->_atoms.size() % 2 != 0) { for (auto& _atom : r->_atoms) { if (_atom->rings.size() > 2) { found = true; } } } } if (!found) { return; } rings.at(0)->getAtoms().at(0)->molecule->requireMinimization(); } void CoordgenMinimizer::buildMoleculeFromFragments( sketcherMinimizerMolecule* molecule, bool firstTime) const { for (auto fragment : molecule->getFragments()) { float angle = 0; sketcherMinimizerPointF position(0.f, 0.f); if (fragment->getParent()) { sketcherMinimizerPointF p1 = fragment->_bondToParent->startAtom->coordinates; sketcherMinimizerPointF p2 = fragment->_bondToParent->endAtom->coordinates; sketcherMinimizerPointF p = p2 - p1; angle = atan2(-p.y(), p.x()); position = fragment->_bondToParent->endAtom->coordinates; if (firstTime) { sketcherMinimizer::alignWithParentDirection(fragment, position, angle); } } fragment->setCoordinates(position, angle); } } void CoordgenMinimizer::buildFromFragments(bool firstTime) const { for (sketcherMinimizerMolecule* molecule : m_molecules) { buildMoleculeFromFragments(molecule, firstTime); } } bool CoordgenMinimizer::hasValid3DCoordinates( const vector& atoms) { for (sketcherMinimizerAtom* atom : atoms) { if (!atom->hasValid3DCoordinates()) { return false; } } return true; } void CoordgenMinimizer::fallbackOn3DCoordinates( const vector& atoms) { float scale = 35.f; // ratio between average bond length and 2d bond length /* TODO find best projection */ for (sketcherMinimizerAtom* atom : atoms) { atom->setCoordinates( sketcherMinimizerPointF(atom->m_x3D * scale, -atom->m_y3D * scale)); } } bool CoordgenMinimizer::hasNaNCoordinates( const std::vector& atoms) { for (sketcherMinimizerAtom* a : atoms) { if (std::isnan(a->coordinates.x()) || std::isnan(a->coordinates.y())) { return true; } } return false; } bool CoordgenMinimizer::hasNaNCoordinates() { return hasNaNCoordinates(m_atoms); } void CoordgenMinimizer::checkForClashes(sketcherMinimizerAtom* a) { if (a->fixed) { return; } sketcherMinimizerPointF oldCoordinates = a->coordinates; vector coordsVect; coordsVect.push_back(oldCoordinates); coordsVect.push_back(oldCoordinates + sketcherMinimizerPointF(bondLength * 0.25f, 0.f)); coordsVect.push_back(oldCoordinates + sketcherMinimizerPointF(-bondLength * 0.25f, 0.f)); coordsVect.push_back(oldCoordinates + sketcherMinimizerPointF(0.f, bondLength * 0.25f)); coordsVect.push_back(oldCoordinates + sketcherMinimizerPointF(0.f, -bondLength * 0.25f)); coordsVect.push_back(oldCoordinates + sketcherMinimizerPointF( bondLength * 0.25f * 0.7071f, -bondLength * 0.25f * 0.7071f)); coordsVect.push_back(oldCoordinates + sketcherMinimizerPointF( -bondLength * 0.25f * 0.7071f, -bondLength * 0.25f * 0.7071f)); coordsVect.push_back(oldCoordinates + sketcherMinimizerPointF(-bondLength * 0.25f * 0.7071f, bondLength * 0.25f * 0.7071f)); coordsVect.push_back(oldCoordinates + sketcherMinimizerPointF(bondLength * 0.25f * 0.7071f, bondLength * 0.25f * 0.7071f)); float bestE = 999999.f; int bestI = 0; for (unsigned int i = 0; i < coordsVect.size(); i++) { a->coordinates = coordsVect[i]; // solves intrafragment clashes by shifting the atomic coordinates up // down left right or diagonally sketcherMinimizerClashInteraction clashI(a, a, a); clashI.restV = 300; float clashE = 0; vector bonds = a->getFragment()->getBonds(); for (sketcherMinimizerBond* b : bonds) { if (!b->startAtom->coordinatesSet) { continue; } if (!b->endAtom->coordinatesSet) { continue; } if (b->startAtom == a) { continue; } if (b->endAtom == a) { continue; } clashI.atom1 = b->startAtom; clashI.atom2 = a; clashI.atom3 = b->endAtom; clashI.energy(clashE); } for (sketcherMinimizerBond* b : a->bonds) { vector atoms = a->getFragment()->getAtoms(); for (sketcherMinimizerAtom* atom : atoms) { if (atom == a) { continue; } if (!b->startAtom->coordinatesSet) { continue; } if (!b->endAtom->coordinatesSet) { continue; } if (b->startAtom == atom) { continue; } if (b->endAtom == atom) { continue; } clashI.atom1 = b->startAtom; clashI.atom2 = atom; clashI.atom3 = b->endAtom; clashI.energy(clashE); } } if (clashE < SKETCHER_EPSILON) { return; } if (i == 0) { bestE = clashE; } if (clashE < bestE) { bestE = clashE; bestI = i; } } a->setCoordinates(coordsVect[bestI]); } float CoordgenMinimizer::getPrecision() const { return m_precision; } void CoordgenMinimizer::setPrecision(float f) { m_precision = f; } std::pair, float> CoordgenDOFSolutions::findBestSolution() const { std::pair, float> bestSolution = *m_solutions.begin(); for (auto solution : m_solutions) { if (solution.second < bestSolution.second) { bestSolution = solution; } } return bestSolution; } std::vector CoordgenDOFSolutions::getCurrentSolution() { std::vector solution; for (auto dof : m_allDofs) { solution.push_back(dof->getCurrentState()); } return solution; } void CoordgenDOFSolutions::loadSolution( const std::vector& solution) { assert(solution.size() == m_allDofs.size()); for (unsigned int i = 0; i < solution.size(); ++i) { m_allDofs.at(i)->setState(solution.at(i)); } } bool CoordgenDOFSolutions::hasSolution( const std::vector& solution) { return m_solutions.find(solution) != m_solutions.end(); } float CoordgenDOFSolutions::scoreCurrentSolution() { std::vector solution; for (auto dof : m_allDofs) { solution.push_back(dof->getCurrentState()); } // for (auto dof : solution) cerr <second; } else { if (m_solutions.size() > MAXIMUM_NUMBER_OF_SCORED_SOLUTIONS * m_minimizer->getPrecision()) { return REJECTED_SOLUTION_SCORE; } m_minimizer->buildMoleculeFromFragments(m_molecule, false); float result = m_minimizer->scoreClashes(m_molecule, true); m_solutions[solution] = result; return result; } } coordgenlibs-3.0.2/CoordgenMinimizer.h000066400000000000000000000336301436654770400200100ustar00rootroot00000000000000/* Contributors: Nicola Zonta Copyright Schrodinger, LLC. All rights reserved */ #ifndef COORDGEN_MINIMIZER_H #define COORDGEN_MINIMIZER_H #include "CoordgenConfig.hpp" #include #include #include #include class sketcherMinimizerInteraction; class sketcherMinimizerStretchInteraction; class sketcherMinimizerBendInteraction; class sketcherMinimizerClashInteraction; class sketcherMinimizerMolecule; class sketcherMinimizerResidue; class sketcherMinimizerResidueInteraction; class sketcherMinimizerAtom; class sketcherMinimizerBond; class sketcherMinimizerRing; class sketcherMinimizerFragment; class sketcherMinimizerPointF; class CoordgenFragmentDOF; class CoordgenMinimizer; /* class to manage the solutions to a minimization problem. Each solution is a vector that contains values for each of the degrees of freedom of the problem */ class CoordgenDOFSolutions { public: CoordgenDOFSolutions(const CoordgenMinimizer* minimizer, sketcherMinimizerMolecule* molecule, std::vector allDofs) : m_minimizer(minimizer), m_molecule(molecule), m_allDofs(std::move(allDofs)) { } /* calculate the value of the scoring function on the currently loaded solution */ float scoreCurrentSolution(); /* get the solution that is currently loaded */ std::vector getCurrentSolution(); /* load the given solution (i.e. set each degree of freedom in the molecule to the given value) */ void loadSolution(const std::vector& solution); /* return the best scoring solution that has been found so far */ std::pair, float> findBestSolution() const; /* check if the given solution has already been scored */ bool hasSolution(const std::vector& solution); std::vector& getAllDofs() { return m_allDofs; } private: const CoordgenMinimizer* m_minimizer; sketcherMinimizerMolecule* m_molecule; std::map, float> m_solutions; std::vector m_allDofs; }; /* minimizer class that resolves clashes in a molecule. It can explore degrees of freedom conformations (e.g. flip around single bonds) and perform a force-field based free atom minimization */ class EXPORT_COORDGEN CoordgenMinimizer { public: CoordgenMinimizer(); ~CoordgenMinimizer(); /* clear all the interactions loaded in the minimizer and free memory */ void clearInteractions(); /* run a force-field based minimization */ void run(); /* Apply forces and take a step in the minimization. Returns false if * converged, true if not. */ bool applyForces(float maxd = 3); /* run a force-field based minimization on residues only */ void minimizeResidues(); /* run a force-field based minimization on the given molecule */ void minimizeMolecule(sketcherMinimizerMolecule* molecule); /* solve clashes of residues in a protein-protein interaction LID */ void minimizeProteinOnlyLID( const std::map>& chains); /* setup constraints and run a force-field based minimization */ void minimizeAll(); /* setup constraints on residues only */ void setupInteractionsOnlyResidues(); /* setup constraints on residues in a protein-protein interaction scenario */ void setupInteractionsProteinOnly( const std::map>& chains); /* setup all constraints */ void setupInteractions(bool intrafragmentClashes = false); /* setup all constraints of given molecule */ void addInteractionsOfMolecule(sketcherMinimizerMolecule* molecule, bool intrafragmentClashes = false); /* score the forcefield value of the current conformation */ float scoreInteractions(); /* add a list of intermolecular clash constraints between two given * molecules */ bool findIntermolecularClashes(sketcherMinimizerMolecule* mol1, sketcherMinimizerMolecule* mol2, float threshold); /* add a list of intermolecular clash constraints between given molecules */ bool findIntermolecularClashes( const std::vector& mols, float threshold); /* precision of the minimization. Higher values result in higher times and * better results */ float getPrecision() const; void setPrecision(float f); /* score all clashes of the given molecule */ float scoreClashes(sketcherMinimizerMolecule* molecule, bool residueInteractions = false, bool scoreProximityRelationsOnOppositeSides = true) const; /* score the penalty for intersecting bonds */ float scoreCrossBonds(sketcherMinimizerMolecule* molecule, bool residueInteractions = false) const; /* score the penalty for degrees of freedom set to non-ideal values */ float scoreDofs(sketcherMinimizerMolecule* molecule) const; /* score the penalty of atoms placed inside rings */ float scoreAtomsInsideRings() const; /* assign a penalty if a molecule (A) is bound to another (B) with more than * a proximity relation and they are on different sides of A and involving * different fragments. This forces the algorithm to look for poses where * all the atoms of A that have proximity relations with B are on the same * side of A. */ float scoreProximityRelationsOnOppositeSides() const; /* run the minimization and return true if the result is considered ideal */ bool avoidClashes(); /* run the minimization on the given molecule. Returns true if the result is considered ideal */ bool avoidClashesOfMolecule( sketcherMinimizerMolecule* molecule, const std::vector& extraInteractions = std::vector()); /* set up the DoF list and run a minimization on the given molecule */ bool flipFragments(sketcherMinimizerMolecule* molecule, float& clashE); /* run a search on the degrees of freedom, exploring combinations of degrees of freedom */ bool runLocalSearch(sketcherMinimizerMolecule* molecule, const std::vector& dofs, int levels, float& clashE, CoordgenDOFSolutions& solutions); /* iteratively grow the pool of solutions by mutating the best scoring one by one degree of freedom */ bool growSolutions( std::set>& allScoredSolutions, int& currentTier, std::map, float>& growingSolutions, CoordgenDOFSolutions& solutions, float& bestScore); /* run the search to find good scoring solutions to the problem. Each degree of freedom has a tier value that ensures that simpler and more aesthetic pleasing ones (e.g. flipping fragments) are searched before more complex ones (i.e. putting substituents inside macrocycles). This is alternative and preferred to runExhaustiveSearch and runLocalSearch */ bool runSearch(int tier, CoordgenDOFSolutions& solutions); /* build a list of tuples of the given order representing all combinations * of dofs */ std::vector> buildTuplesOfDofs(const std::vector& dofs, unsigned int order) const; /* run en exhaustive search on all combinations of DoFs. */ bool runExhaustiveSearch(sketcherMinimizerMolecule* molecule, std::vector dofs, float& clashE, CoordgenDOFSolutions& solutions); void runExhaustiveSearchLevel( sketcherMinimizerMolecule* molecule, const std::vector::iterator& iterator, std::vector& dofs, float& bestResult, bool& abort, CoordgenDOFSolutions& solutions); /* return true if the given bonds clash */ bool bondsClash(sketcherMinimizerBond* bond, sketcherMinimizerBond* bond2) const; /* quick function to avoid clashes of terminal atoms without running a minimization */ void avoidTerminalClashes(sketcherMinimizerMolecule* molecule, float& clashE); /* check if the ring system cannot be drown with regular polygons and needs a FF based minimization */ static void maybeMinimizeRings(const std::vector& rings); /* avoid clashes of terminal atoms of the same fragment without running a minimization */ static void avoidInternalClashes(sketcherMinimizerFragment* fragment); /* assign coordinates to each atom from the current values of DoFs of the fragments */ void buildFromFragments(bool firstTime = false) const; /* assign coordinates to each atom from the current values of DoFs of the fragments */ void buildMoleculeFromFragments(sketcherMinimizerMolecule* molecule, bool firstTime = false) const; /* find a list of carbons from the backbone C=O of a peptide */ std::set getChetoCs(const std::vector& allAtoms) const; /* find a list of nitrogens from the backbon NH of a peptide */ std::set getAminoNs(const std::vector& allAtoms) const; /* find a list of alpha carbons of a peptide */ std::set getAlphaCs(const std::vector& allAtoms, const std::set& chetoCs, const std::set& aminoNs) const; /* check the atom for clashes with other atoms */ static void checkForClashes(sketcherMinimizerAtom* a); /* return true if atoms have NaN coordinates */ static bool hasNaNCoordinates(const std::vector& atoms); bool hasNaNCoordinates(); /* return true if the atom has valid 3d coordinates */ static bool hasValid3DCoordinates(const std::vector& atoms); /* use 3d coordinates in 2d (e.g. when a reasonable 2d structure cannot be * found) */ static void fallbackOn3DCoordinates(const std::vector& atoms); /* add the given constraint to the minimizer */ void addExtraInteraction(sketcherMinimizerMolecule* molecule, sketcherMinimizerInteraction* interaction); std::vector m_atoms; std::vector m_bonds; bool m_evenAngles; std::vector m_residues; std::vector m_residueInteractions; std::vector m_fragments; std::vector m_molecules; std::vector energy_list; std::vector> all_coordinates; bool skipMinimization, skipAvoidClashes, skipFlipFragments, m_scoreResidueInteractions; const std::vector& getBendInteractions() const {return _bendInteractions;}; const std::vector& getStretchInteractions() const {return _stretchInteractions;}; const std::vector& getInteractions() const {return _interactions;}; /* add clash constraints of the given molecule */ void addClashInteractionsOfMolecule(sketcherMinimizerMolecule* molecule, bool intrafragmentClashes); /* add stretch constraints of the given molecule */ void addStretchInteractionsOfMolecule(sketcherMinimizerMolecule* molecule); /* add angle bend constraints of the given molecule */ void addBendInteractionsOfMolecule(sketcherMinimizerMolecule* molecule); /* add constraints to avoid deviating from constrained coordinates (e.g. for alignment) */ void addConstrainedInteractionsOfMolecule(sketcherMinimizerMolecule* molecule); /* add constraints to avoid chiral inversion of the given molecule */ void addChiralInversionConstraintsOfMolecule( sketcherMinimizerMolecule* molecule); /* add constraints to keep peptide chains linear */ void addPeptideBondInversionConstraintsOfMolecule( sketcherMinimizerMolecule* molecule); private: /* get lists of four atoms that form a chain and are each present in one of the four sets respectively */ void getFourConsecutiveAtomsThatMatchSequence( std::vector>& consecutiveAtomsGroups, const std::set& firstSet, const std::set& secondSet, const std::set& thirdSet, const std::set& fourthSet) const; std::vector _interactions; std::vector _stretchInteractions; std::vector _bendInteractions; std::vector _intramolecularClashInteractions; std::vector _extraInteractions; std::map> _extraInteractionsOfMolecule; unsigned int m_maxIterations; float m_precision; }; #endif /* defined(COORDGEN_MINIMIZER_H) */ coordgenlibs-3.0.2/CoordgenTemplates.cpp000066400000000000000000005420231436654770400203370ustar00rootroot00000000000000 /// // Find the templates for coordinate generation // // Autogenerated, do not edit. // // $SCHRODINGER/run mol_generator.py templates.mae // // generated using templates.mae version ad51e1ccece0b7b5f872. // #include "CoordgenTemplates.h" #include #include "sketcherMinimizerMolecule.h" #include "sketcherMinimizerAtom.h" #include "sketcherMinimizerBond.h" using std::array; using std::tuple; template void add_atoms(sketcherMinimizerMolecule* molecule, const T& atoms) { for (const auto& a: atoms) { auto atom = molecule->addNewAtom(); atom->setAtomicNumber(std::get<0>(a)); atom->setCoordinates(sketcherMinimizerPointF(std::get<1>(a), std::get<2>(a))); } } template void add_bonds(sketcherMinimizerMolecule* molecule, const T& bonds) { for (const auto& b: bonds) { auto* from_atom = molecule->getAtoms().at(b[0]); auto* to_atom = molecule->getAtoms().at(b[1]); auto bond = molecule->addNewBond(from_atom, to_atom); bond->setBondOrder(b[2]); } } namespace schrodinger { std::vector coordgen_templates() { std::vector molecules(82); size_t i = 0; { auto molecule = new sketcherMinimizerMolecule(); std::array, 36> atoms = {{ tuple(6, 5.4331f, -5.9998f), tuple(6, 4.1959f, -5.2856f), tuple(6, 4.1959f, -3.857f), tuple(6, 5.4331f, -3.1427f), tuple(6, 6.6703f, -3.857f), tuple(6, 6.6703f, -5.2856f), tuple(6, 3.2084f, -6.993f), tuple(6, 1.9704f, -7.7058f), tuple(6, 1.9686f, -9.1343f), tuple(6, 3.205f, -9.8501f), tuple(6, 4.443f, -9.1373f), tuple(6, 4.4447f, -7.7087f), tuple(6, -0.0072f, -7.7056f), tuple(6, -1.2451f, -6.9926f), tuple(6, -2.4815f, -7.7081f), tuple(6, -2.48f, -9.1367f), tuple(6, -1.2421f, -9.8497f), tuple(6, -0.0057f, -9.1341f), tuple(6, -3.4698f, -5.9991f), tuple(6, -2.2326f, -5.2849f), tuple(6, -2.2325f, -3.8563f), tuple(6, -3.4697f, -3.142f), tuple(6, -4.7069f, -3.8562f), tuple(6, -4.7069f, -5.2848f), tuple(6, -2.4796f, -0.0045f), tuple(6, -2.4813f, -1.4331f), tuple(6, -1.2449f, -2.1488f), tuple(6, -0.0069f, -1.436f), tuple(6, -0.0052f, -0.0074f), tuple(6, -1.2416f, 0.7083f), tuple(6, 3.2084f, -2.1492f), tuple(6, 1.9705f, -1.4362f), tuple(6, 1.9691f, -0.0076f), tuple(6, 3.2055f, 0.7079f), tuple(6, 4.4434f, -0.0051f), tuple(6, 4.4449f, -1.4337f) }}; std::array, 42> bonds = {{ { 0, 1, 1 }, { 0, 5, 2 }, { 0, 11, 1 }, { 1, 2, 2 }, { 2, 3, 1 }, { 3, 4, 2 }, { 3, 35, 1 }, { 4, 5, 1 }, { 6, 7, 1 }, { 6, 11, 2 }, { 7, 8, 2 }, { 8, 9, 1 }, { 8, 17, 1 }, { 9, 10, 2 }, { 10, 11, 1 }, { 12, 13, 1 }, { 12, 17, 2 }, { 13, 14, 2 }, { 14, 15, 1 }, { 14, 18, 1 }, { 15, 16, 2 }, { 16, 17, 1 }, { 18, 19, 1 }, { 18, 23, 2 }, { 19, 20, 2 }, { 20, 21, 1 }, { 21, 22, 2 }, { 21, 25, 1 }, { 22, 23, 1 }, { 24, 25, 1 }, { 24, 29, 2 }, { 25, 26, 2 }, { 26, 27, 1 }, { 27, 28, 2 }, { 28, 29, 1 }, { 28, 32, 1 }, { 30, 31, 1 }, { 30, 35, 2 }, { 31, 32, 2 }, { 32, 33, 1 }, { 33, 34, 2 }, { 34, 35, 1 } }}; add_atoms(molecule, atoms); add_bonds(molecule, bonds); molecules[i] = molecule; ++i; } { auto molecule = new sketcherMinimizerMolecule(); std::array, 20> atoms = {{ tuple(6, -6.1782f, 2.1898f), tuple(6, -6.7726f, 1.6177f), tuple(6, -6.5745f, 0.8169f), tuple(6, -5.7818f, 0.5881f), tuple(6, -5.1874f, 1.1601f), tuple(6, -5.3855f, 1.9609f), tuple(7, -6.2055f, 3.0143f), tuple(6, -5.4297f, 3.2951f), tuple(6, -4.791f, 2.533f), tuple(6, -3.8805f, 2.6283f), tuple(7, -4.2474f, 0.6956f), tuple(6, -3.8135f, -0.1347f), tuple(6, -2.6968f, -0.0689f), tuple(6, -3.1131f, 2.2969f), tuple(6, -2.8996f, 1.5f), tuple(6, -2.1027f, 1.2865f), tuple(6, -1.8892f, 0.4896f), tuple(6, -1.0923f, 0.2761f), tuple(6, -1.4004f, -0.5109f), tuple(6, 0.1037f, 0.5426f) }}; std::array, 22> bonds = {{ { 0, 1, 2 }, { 0, 5, 1 }, { 0, 6, 1 }, { 1, 2, 1 }, { 2, 3, 2 }, { 3, 4, 1 }, { 4, 5, 2 }, { 4, 10, 1 }, { 5, 8, 1 }, { 6, 7, 1 }, { 7, 8, 1 }, { 8, 9, 1 }, { 9, 13, 2 }, { 10, 11, 1 }, { 11, 12, 1 }, { 12, 18, 1 }, { 13, 14, 1 }, { 14, 15, 2 }, { 15, 16, 1 }, { 16, 17, 2 }, { 17, 19, 1 }, { 18, 19, 1 } }}; add_atoms(molecule, atoms); add_bonds(molecule, bonds); molecules[i] = molecule; ++i; } { auto molecule = new sketcherMinimizerMolecule(); std::array, 23> atoms = {{ tuple(6, -0.5614f, 2.2242f), tuple(6, -0.5614f, 1.3992f), tuple(6, 0.153f, 0.9867f), tuple(6, 0.8675f, 1.3992f), tuple(6, 0.8675f, 2.2242f), tuple(6, 0.153f, 2.6367f), tuple(6, 0.153f, 3.4617f), tuple(6, 0.8675f, 3.8742f), tuple(6, 1.582f, 2.6367f), tuple(6, 1.582f, 3.4617f), tuple(6, 2.2964f, 3.8742f), tuple(6, 2.2964f, 4.6992f), tuple(6, 1.582f, 5.1117f), tuple(6, 0.8675f, 4.6992f), tuple(6, 0.153f, 5.1117f), tuple(6, -0.5614f, 4.6992f), tuple(6, -0.5614f, 3.8742f), tuple(6, -1.2759f, 3.4617f), tuple(6, -1.2759f, 2.6367f), tuple(6, -1.9904f, 3.8742f), tuple(6, -2.7049f, 3.4617f), tuple(6, -2.7049f, 2.6367f), tuple(6, -1.9904f, 2.2242f) }}; std::array, 25> bonds = {{ { 0, 1, 1 }, { 0, 18, 1 }, { 1, 2, 1 }, { 2, 3, 1 }, { 3, 4, 1 }, { 4, 5, 1 }, { 4, 8, 1 }, { 5, 6, 1 }, { 6, 7, 1 }, { 7, 9, 1 }, { 8, 9, 1 }, { 9, 10, 1 }, { 10, 11, 1 }, { 11, 12, 1 }, { 12, 13, 1 }, { 13, 14, 1 }, { 14, 15, 1 }, { 15, 16, 1 }, { 16, 17, 1 }, { 17, 18, 1 }, { 17, 19, 1 }, { 18, 22, 1 }, { 19, 20, 1 }, { 20, 21, 1 }, { 21, 22, 1 } }}; add_atoms(molecule, atoms); add_bonds(molecule, bonds); molecules[i] = molecule; ++i; } { auto molecule = new sketcherMinimizerMolecule(); std::array, 25> atoms = {{ tuple(6, -1.6638f, -1.7467f), tuple(6, -1.6638f, -2.5717f), tuple(6, -0.8388f, -2.5717f), tuple(6, -0.4263f, -3.2862f), tuple(6, 0.3987f, -3.2862f), tuple(6, 0.769f, -4.0234f), tuple(6, 1.592f, -4.0809f), tuple(6, 2.0613f, -3.4024f), tuple(6, 0.8112f, -2.5717f), tuple(6, 1.7171f, -2.6526f), tuple(6, 2.1296f, -1.9381f), tuple(6, 1.7171f, -1.2237f), tuple(6, 0.8921f, -1.2237f), tuple(6, 0.4796f, -0.5092f), tuple(6, -0.2349f, -0.0967f), tuple(6, -0.2349f, 0.7283f), tuple(6, -0.9494f, 1.1408f), tuple(6, -1.6638f, 0.7283f), tuple(6, -1.6638f, -0.0967f), tuple(6, -2.3783f, -0.5092f), tuple(6, -2.3783f, -1.3342f), tuple(6, -3.0928f, -0.0967f), tuple(6, -3.8072f, -0.5092f), tuple(6, -3.8072f, -1.3342f), tuple(6, -3.0928f, -1.7467f) }}; std::array, 27> bonds = {{ { 0, 1, 1 }, { 0, 20, 1 }, { 1, 2, 1 }, { 2, 3, 1 }, { 3, 4, 1 }, { 4, 5, 1 }, { 4, 8, 1 }, { 5, 6, 1 }, { 6, 7, 1 }, { 7, 9, 1 }, { 8, 9, 1 }, { 9, 10, 1 }, { 10, 11, 1 }, { 11, 12, 1 }, { 12, 13, 1 }, { 13, 14, 1 }, { 14, 15, 1 }, { 15, 16, 1 }, { 16, 17, 1 }, { 17, 18, 1 }, { 18, 19, 1 }, { 19, 20, 1 }, { 19, 21, 1 }, { 20, 24, 1 }, { 21, 22, 1 }, { 22, 23, 1 }, { 23, 24, 1 } }}; add_atoms(molecule, atoms); add_bonds(molecule, bonds); molecules[i] = molecule; ++i; } { auto molecule = new sketcherMinimizerMolecule(); std::array, 27> atoms = {{ tuple(6, 0.0716f, -7.5625f), tuple(6, 0.0716f, -8.3875f), tuple(6, 0.7861f, -8.8f), tuple(6, 1.5005f, -8.3875f), tuple(6, 2.215f, -8.8f), tuple(6, 2.215f, -9.625f), tuple(6, 2.9295f, -10.0375f), tuple(6, 3.6439f, -9.625f), tuple(6, 2.9295f, -8.3875f), tuple(6, 3.6439f, -8.8f), tuple(6, 4.3584f, -8.3875f), tuple(6, 4.3584f, -7.5625f), tuple(6, 3.6439f, -7.15f), tuple(6, 3.6439f, -6.325f), tuple(6, 2.9295f, -5.9125f), tuple(6, 2.9295f, -5.0875f), tuple(6, 2.215f, -4.675f), tuple(6, 1.5005f, -5.0875f), tuple(6, 1.5005f, -5.9125f), tuple(6, 0.7861f, -6.325f), tuple(6, 0.0716f, -5.9125f), tuple(6, -0.6429f, -6.325f), tuple(6, -0.6429f, -7.15f), tuple(6, -1.3574f, -5.9125f), tuple(6, -2.0718f, -6.325f), tuple(6, -2.0718f, -7.15f), tuple(6, -1.3574f, -7.5625f) }}; std::array, 29> bonds = {{ { 0, 1, 1 }, { 0, 22, 1 }, { 1, 2, 1 }, { 2, 3, 1 }, { 3, 4, 1 }, { 4, 5, 1 }, { 4, 8, 1 }, { 5, 6, 1 }, { 6, 7, 1 }, { 7, 9, 1 }, { 8, 9, 1 }, { 9, 10, 1 }, { 10, 11, 1 }, { 11, 12, 1 }, { 12, 13, 1 }, { 13, 14, 1 }, { 14, 15, 1 }, { 15, 16, 1 }, { 16, 17, 1 }, { 17, 18, 2 }, { 18, 19, 1 }, { 19, 20, 1 }, { 20, 21, 1 }, { 21, 22, 1 }, { 21, 23, 1 }, { 22, 26, 1 }, { 23, 24, 1 }, { 24, 25, 1 }, { 25, 26, 1 } }}; add_atoms(molecule, atoms); add_bonds(molecule, bonds); molecules[i] = molecule; ++i; } { auto molecule = new sketcherMinimizerMolecule(); std::array, 24> atoms = {{ tuple(6, -2.1593f, 7.9068f), tuple(6, -1.7468f, 7.1923f), tuple(6, -0.9218f, 7.1923f), tuple(6, -0.5093f, 6.4778f), tuple(6, 0.3157f, 6.4778f), tuple(6, 0.7282f, 5.7633f), tuple(6, 1.5532f, 5.7633f), tuple(6, 1.9657f, 6.4778f), tuple(6, 0.7282f, 7.1923f), tuple(6, 1.5532f, 7.1923f), tuple(6, 1.9657f, 7.9068f), tuple(6, 1.5532f, 8.6086f), tuple(6, 0.7282f, 8.6086f), tuple(6, 0.3157f, 9.3231f), tuple(6, -0.5093f, 9.3231f), tuple(6, -0.9218f, 10.0375f), tuple(6, -1.7468f, 10.0375f), tuple(6, -2.1593f, 9.3231f), tuple(6, -2.9295f, 9.0274f), tuple(6, -2.9295f, 8.2024f), tuple(6, -3.6439f, 9.4399f), tuple(6, -4.3584f, 9.0274f), tuple(6, -4.3584f, 8.2024f), tuple(6, -3.6439f, 7.7899f) }}; std::array, 26> bonds = {{ { 0, 1, 1 }, { 0, 19, 1 }, { 1, 2, 1 }, { 2, 3, 1 }, { 3, 4, 1 }, { 4, 5, 1 }, { 4, 8, 1 }, { 5, 6, 1 }, { 6, 7, 1 }, { 7, 9, 1 }, { 8, 9, 1 }, { 9, 10, 1 }, { 10, 11, 1 }, { 11, 12, 1 }, { 12, 13, 1 }, { 13, 14, 1 }, { 14, 15, 1 }, { 15, 16, 1 }, { 16, 17, 1 }, { 17, 18, 1 }, { 18, 19, 1 }, { 18, 20, 1 }, { 19, 23, 1 }, { 20, 21, 1 }, { 21, 22, 1 }, { 22, 23, 1 } }}; add_atoms(molecule, atoms); add_bonds(molecule, bonds); molecules[i] = molecule; ++i; } { auto molecule = new sketcherMinimizerMolecule(); std::array, 27> atoms = {{ tuple(6, -0.7145f, 1.0312f), tuple(6, -0.7145f, 0.2062f), tuple(6, -1.4289f, -0.2063f), tuple(6, -1.4289f, -1.0313f), tuple(6, -0.7145f, -1.4438f), tuple(6, -0.7145f, -2.2688f), tuple(6, -0.0f, -2.6812f), tuple(6, 0.7145f, -2.2688f), tuple(6, 0.0f, -1.0313f), tuple(6, 0.7145f, -1.4438f), tuple(6, 1.4289f, -1.0313f), tuple(6, 2.1434f, -1.4438f), tuple(6, 2.8579f, -1.0313f), tuple(6, 2.8579f, -0.2063f), tuple(6, 2.1434f, 0.2062f), tuple(6, 2.1434f, 1.0312f), tuple(6, 1.4289f, 1.4437f), tuple(6, 1.4289f, 2.2687f), tuple(6, 0.7145f, 2.6812f), tuple(6, 0.0f, 2.2687f), tuple(6, -0.7145f, 2.6812f), tuple(6, -1.4289f, 2.2687f), tuple(6, -1.4289f, 1.4437f), tuple(6, -2.1434f, 2.6812f), tuple(6, -2.8579f, 2.2687f), tuple(6, -2.8579f, 1.4437f), tuple(6, -2.1434f, 1.0312f) }}; std::array, 29> bonds = {{ { 0, 1, 1 }, { 0, 22, 1 }, { 1, 2, 1 }, { 2, 3, 1 }, { 3, 4, 1 }, { 4, 5, 1 }, { 4, 8, 1 }, { 5, 6, 1 }, { 6, 7, 1 }, { 7, 9, 1 }, { 8, 9, 1 }, { 9, 10, 1 }, { 10, 11, 1 }, { 11, 12, 1 }, { 12, 13, 1 }, { 13, 14, 1 }, { 14, 15, 1 }, { 15, 16, 1 }, { 16, 17, 1 }, { 17, 18, 1 }, { 18, 19, 1 }, { 19, 20, 1 }, { 20, 21, 1 }, { 21, 22, 1 }, { 21, 23, 1 }, { 22, 26, 1 }, { 23, 24, 1 }, { 24, 25, 1 }, { 25, 26, 1 } }}; add_atoms(molecule, atoms); add_bonds(molecule, bonds); molecules[i] = molecule; ++i; } { auto molecule = new sketcherMinimizerMolecule(); std::array, 26> atoms = {{ tuple(6, -1.4289f, -0.5914f), tuple(6, -0.7144f, -0.1789f), tuple(6, -0.0f, -0.5914f), tuple(6, 0.7144f, -0.1789f), tuple(6, 1.4289f, -0.5914f), tuple(6, 1.4289f, -1.4164f), tuple(6, 2.1433f, -1.8288f), tuple(6, 2.8578f, -1.4164f), tuple(6, 2.1433f, -0.1789f), tuple(6, 2.8578f, -0.5914f), tuple(6, 3.5723f, -0.1789f), tuple(6, 3.5723f, 0.6461f), tuple(6, 2.8452f, 1.0586f), tuple(6, 2.5495f, 1.8288f), tuple(6, 1.7245f, 1.8288f), tuple(6, 1.4289f, 1.0586f), tuple(6, 0.7144f, 0.6461f), tuple(6, -0.0f, 1.0586f), tuple(6, -0.7144f, 0.6461f), tuple(6, -1.4289f, 1.0586f), tuple(6, -2.1434f, 0.6461f), tuple(6, -2.1434f, -0.1789f), tuple(6, -2.8578f, 1.0586f), tuple(6, -3.5723f, 0.6461f), tuple(6, -3.5723f, -0.1789f), tuple(6, -2.8578f, -0.5914f) }}; std::array, 28> bonds = {{ { 0, 1, 1 }, { 0, 21, 1 }, { 1, 2, 1 }, { 2, 3, 1 }, { 3, 4, 1 }, { 4, 5, 1 }, { 4, 8, 1 }, { 5, 6, 1 }, { 6, 7, 1 }, { 7, 9, 1 }, { 8, 9, 1 }, { 9, 10, 1 }, { 10, 11, 1 }, { 11, 12, 1 }, { 12, 13, 1 }, { 13, 14, 1 }, { 14, 15, 1 }, { 15, 16, 1 }, { 16, 17, 1 }, { 17, 18, 1 }, { 18, 19, 1 }, { 19, 20, 1 }, { 20, 21, 1 }, { 20, 22, 1 }, { 21, 25, 1 }, { 22, 23, 1 }, { 23, 24, 1 }, { 24, 25, 1 } }}; add_atoms(molecule, atoms); add_bonds(molecule, bonds); molecules[i] = molecule; ++i; } { auto molecule = new sketcherMinimizerMolecule(); std::array, 34> atoms = {{ tuple(6, -0.7496f, -1.3082f), tuple(6, -1.464f, -1.7207f), tuple(6, -2.1785f, -1.3082f), tuple(6, -2.1785f, -0.4832f), tuple(6, -2.893f, -0.0707f), tuple(6, -2.893f, 0.7543f), tuple(6, -2.1785f, 1.1668f), tuple(6, -1.464f, 0.7543f), tuple(8, -0.6482f, 0.8767f), tuple(6, -1.464f, -0.0707f), tuple(7, -0.7496f, -0.4832f), tuple(13, 0.5871f, 0.1009f), tuple(7, 0.7496f, 1.5504f), tuple(6, 1.464f, 1.9629f), tuple(6, 1.464f, 2.7879f), tuple(6, 0.7496f, 3.2004f), tuple(6, 0.0351f, 2.7879f), tuple(6, 0.0351f, 1.9629f), tuple(6, 2.1785f, 3.2004f), tuple(6, 2.893f, 2.7879f), tuple(6, 2.893f, 1.9629f), tuple(6, 2.1785f, 1.5504f), tuple(8, 1.8765f, 0.7827f), tuple(7, 0.5328f, -1.3568f), tuple(6, 1.1782f, -1.8707f), tuple(6, 1.9459f, -1.5687f), tuple(8, 1.7612f, -0.7646f), tuple(6, 2.5913f, -2.0826f), tuple(6, 2.4689f, -2.8985f), tuple(6, 1.7012f, -3.2004f), tuple(6, 1.0558f, -2.6865f), tuple(6, 0.2881f, -2.9885f), tuple(6, -0.3573f, -2.4746f), tuple(6, -0.235f, -1.6587f) }}; std::array, 42> bonds = {{ { 0, 1, 2 }, { 0, 10, 1 }, { 1, 2, 1 }, { 2, 3, 2 }, { 3, 4, 1 }, { 3, 9, 1 }, { 4, 5, 2 }, { 5, 6, 1 }, { 6, 7, 2 }, { 7, 8, 1 }, { 7, 9, 1 }, { 8, 11, 1 }, { 9, 10, 2 }, { 10, 11, 1 }, { 11, 12, 1 }, { 11, 22, 1 }, { 11, 23, 1 }, { 11, 26, 1 }, { 12, 13, 2 }, { 12, 17, 1 }, { 13, 14, 1 }, { 13, 21, 1 }, { 14, 15, 2 }, { 14, 18, 1 }, { 15, 16, 1 }, { 16, 17, 2 }, { 18, 19, 2 }, { 19, 20, 1 }, { 20, 21, 2 }, { 21, 22, 1 }, { 23, 24, 2 }, { 23, 33, 1 }, { 24, 25, 1 }, { 24, 30, 1 }, { 25, 26, 1 }, { 25, 27, 2 }, { 27, 28, 1 }, { 28, 29, 2 }, { 29, 30, 1 }, { 30, 31, 2 }, { 31, 32, 1 }, { 32, 33, 2 } }}; add_atoms(molecule, atoms); add_bonds(molecule, bonds); molecules[i] = molecule; ++i; } { auto molecule = new sketcherMinimizerMolecule(); std::array, 22> atoms = {{ tuple(6, 0.1593f, 3.0569f), tuple(6, 0.8597f, 2.621f), tuple(6, 0.8597f, 1.796f), tuple(6, -0.581f, 2.6926f), tuple(6, -0.6628f, 1.8717f), tuple(6, 0.0827f, 1.5185f), tuple(6, -1.3415f, 1.4026f), tuple(6, -1.2746f, 0.5804f), tuple(7, -1.8093f, -0.0488f), tuple(6, -1.5319f, -0.8258f), tuple(6, -0.7203f, -0.9739f), tuple(6, -0.2512f, -1.6526f), tuple(6, 0.5596f, -1.5001f), tuple(6, 1.097f, -2.126f), tuple(6, 0.8237f, -2.9044f), tuple(6, 0.0129f, -3.0569f), tuple(6, -0.5245f, -2.431f), tuple(6, 1.7757f, -1.6569f), tuple(6, 1.3801f, -0.933f), tuple(6, 1.8093f, -0.2284f), tuple(6, 1.3402f, 0.4503f), tuple(6, 1.4884f, 1.2619f) }}; std::array, 24> bonds = {{ { 0, 1, 2 }, { 0, 3, 1 }, { 1, 2, 1 }, { 2, 5, 2 }, { 2, 21, 1 }, { 3, 4, 2 }, { 4, 5, 1 }, { 4, 6, 1 }, { 6, 7, 1 }, { 7, 8, 1 }, { 8, 9, 1 }, { 9, 10, 1 }, { 10, 11, 1 }, { 11, 12, 2 }, { 11, 16, 1 }, { 12, 13, 1 }, { 13, 14, 2 }, { 13, 17, 1 }, { 14, 15, 1 }, { 15, 16, 2 }, { 17, 18, 1 }, { 18, 19, 1 }, { 19, 20, 1 }, { 20, 21, 1 } }}; add_atoms(molecule, atoms); add_bonds(molecule, bonds); molecules[i] = molecule; ++i; } { auto molecule = new sketcherMinimizerMolecule(); std::array, 22> atoms = {{ tuple(6, 0.7145f, 1.65f), tuple(7, 0.7145f, 0.825f), tuple(6, 1.4289f, 0.4125f), tuple(6, 0.0f, 2.0625f), tuple(6, -0.7145f, 1.65f), tuple(6, -1.4289f, 2.0625f), tuple(6, -2.1434f, 1.65f), tuple(6, -2.1434f, 0.825f), tuple(6, -0.7145f, 0.825f), tuple(6, -1.4289f, 0.4125f), tuple(8, -1.4289f, -0.4125f), tuple(6, -2.1434f, -0.825f), tuple(6, -2.1434f, -1.65f), tuple(6, -1.4289f, -2.0625f), tuple(6, -0.7145f, -1.65f), tuple(7, 0.0f, -2.0625f), tuple(6, 0.7145f, -1.65f), tuple(6, 0.7145f, -0.825f), tuple(6, 1.4289f, -2.0625f), tuple(6, 2.1434f, -1.65f), tuple(6, 2.1434f, -0.825f), tuple(6, 1.4289f, -0.4125f) }}; std::array, 24> bonds = {{ { 0, 1, 1 }, { 0, 3, 1 }, { 1, 2, 1 }, { 2, 21, 1 }, { 3, 4, 1 }, { 4, 5, 1 }, { 4, 8, 1 }, { 5, 6, 1 }, { 6, 7, 1 }, { 7, 9, 1 }, { 8, 9, 1 }, { 9, 10, 1 }, { 10, 11, 1 }, { 11, 12, 1 }, { 12, 13, 1 }, { 13, 14, 1 }, { 14, 15, 1 }, { 15, 16, 1 }, { 16, 17, 1 }, { 16, 18, 1 }, { 17, 21, 1 }, { 18, 19, 1 }, { 19, 20, 1 }, { 20, 21, 1 } }}; add_atoms(molecule, atoms); add_bonds(molecule, bonds); molecules[i] = molecule; ++i; } { auto molecule = new sketcherMinimizerMolecule(); std::array, 19> atoms = {{ tuple(6, -0.2062f, 1.7862f), tuple(6, 0.2063f, 1.0717f), tuple(7, 1.0313f, 1.0717f), tuple(6, -1.0312f, 1.7862f), tuple(6, -1.4437f, 1.0717f), tuple(6, -2.2687f, 1.0717f), tuple(6, -2.6812f, 0.3572f), tuple(6, -2.2687f, -0.3572f), tuple(6, -1.4437f, -0.3572f), tuple(6, -1.0312f, -1.0717f), tuple(7, -0.2062f, -1.0717f), tuple(6, 0.2063f, -1.7862f), tuple(6, 1.0313f, -1.7862f), tuple(6, 1.4438f, -1.0717f), tuple(6, 1.0313f, -0.3572f), tuple(6, 1.4438f, 0.3572f), tuple(6, 2.2688f, -1.0717f), tuple(6, 2.6812f, -0.3572f), tuple(6, 2.2688f, 0.3572f) }}; std::array, 20> bonds = {{ { 0, 1, 1 }, { 0, 3, 1 }, { 1, 2, 1 }, { 2, 15, 1 }, { 3, 4, 1 }, { 4, 5, 1 }, { 5, 6, 1 }, { 6, 7, 1 }, { 7, 8, 1 }, { 8, 9, 1 }, { 9, 10, 1 }, { 10, 11, 1 }, { 11, 12, 1 }, { 12, 13, 1 }, { 13, 14, 2 }, { 13, 16, 1 }, { 14, 15, 1 }, { 15, 18, 2 }, { 16, 17, 2 }, { 17, 18, 1 } }}; add_atoms(molecule, atoms); add_bonds(molecule, bonds); molecules[i] = molecule; ++i; } { auto molecule = new sketcherMinimizerMolecule(); std::array, 12> atoms = {{ tuple(7, 2.2594f, -2.751f), tuple(7, 3.2304f, -1.7031f), tuple(7, 0.9479f, -2.3215f), tuple(6, 0.6005f, -1.1462f), tuple(6, -0.5154f, -2.8288f), tuple(6, -1.5255f, -1.8186f), tuple(6, 1.3803f, -0.3684f), tuple(6, 0.0f, 0.0f), tuple(6, -2.9054f, -2.1883f), tuple(6, -3.2752f, -3.5682f), tuple(6, -2.2651f, -4.5784f), tuple(6, -0.8852f, -4.2087f) }}; std::array, 14> bonds = {{ { 0, 1, 1 }, { 0, 2, 1 }, { 1, 3, 1 }, { 2, 6, 1 }, { 2, 4, 1 }, { 3, 7, 1 }, { 3, 5, 1 }, { 4, 5, 1 }, { 4, 11, 1 }, { 5, 8, 1 }, { 6, 7, 1 }, { 8, 9, 1 }, { 9, 10, 1 }, { 10, 11, 1 } }}; add_atoms(molecule, atoms); add_bonds(molecule, bonds); molecules[i] = molecule; ++i; } { auto molecule = new sketcherMinimizerMolecule(); std::array, 22> atoms = {{ tuple(6, -17.6528f, -2.5809f), tuple(6, -16.8634f, -2.422f), tuple(6, -16.2566f, -0.9952f), tuple(6, -16.6642f, -0.3065f), tuple(6, -13.3058f, -3.061f), tuple(6, -13.37f, -1.8602f), tuple(6, -14.1606f, -1.6244f), tuple(6, -13.9248f, -0.8338f), tuple(6, -14.684f, -0.5109f), tuple(6, -13.7895f, -3.7293f), tuple(6, -14.5153f, -4.1216f), tuple(6, -15.3394f, -4.1601f), tuple(6, -16.0986f, -3.8372f), tuple(6, -16.6425f, -3.2169f), tuple(6, -16.3003f, -1.819f), tuple(6, -15.5081f, -0.5494f), tuple(6, -13.1342f, -1.0697f), tuple(6, -18.4792f, -2.3085f), tuple(6, -17.336f, 0.0706f), tuple(6, -18.9447f, -1.6662f), tuple(6, -18.8636f, -0.722f), tuple(6, -18.2199f, -0.0178f) }}; std::array, 24> bonds = {{ { 0, 1, 1 }, { 0, 17, 1 }, { 1, 13, 1 }, { 1, 14, 1 }, { 2, 3, 1 }, { 2, 15, 1 }, { 2, 14, 1 }, { 3, 18, 1 }, { 4, 9, 1 }, { 4, 5, 1 }, { 5, 6, 1 }, { 5, 16, 1 }, { 6, 7, 1 }, { 7, 8, 1 }, { 7, 16, 1 }, { 8, 15, 1 }, { 9, 10, 1 }, { 10, 11, 1 }, { 11, 12, 1 }, { 12, 13, 1 }, { 17, 19, 1 }, { 18, 21, 1 }, { 19, 20, 1 }, { 20, 21, 1 } }}; add_atoms(molecule, atoms); add_bonds(molecule, bonds); molecules[i] = molecule; ++i; } { auto molecule = new sketcherMinimizerMolecule(); std::array, 21> atoms = {{ tuple(6, -18.3739f, -2.0722f), tuple(6, -17.6823f, -2.522f), tuple(6, -16.8634f, -2.422f), tuple(6, -16.2566f, -0.9952f), tuple(6, -16.7526f, -0.336f), tuple(6, -17.5564f, -0.1498f), tuple(6, -18.2917f, -0.5239f), tuple(6, -18.6146f, -1.2831f), tuple(6, -13.3058f, -3.061f), tuple(6, -13.37f, -1.8602f), tuple(6, -14.1606f, -1.6244f), tuple(6, -13.9248f, -0.8338f), tuple(6, -14.684f, -0.5109f), tuple(6, -13.7895f, -3.7293f), tuple(6, -14.5153f, -4.1216f), tuple(6, -15.3394f, -4.1601f), tuple(6, -16.0986f, -3.8372f), tuple(6, -16.6425f, -3.2169f), tuple(6, -16.3003f, -1.819f), tuple(6, -15.5081f, -0.5494f), tuple(6, -13.1342f, -1.0697f) }}; std::array, 23> bonds = {{ { 0, 1, 1 }, { 0, 7, 1 }, { 1, 2, 1 }, { 2, 17, 1 }, { 2, 18, 1 }, { 3, 4, 1 }, { 3, 19, 1 }, { 3, 18, 1 }, { 4, 5, 1 }, { 5, 6, 1 }, { 6, 7, 1 }, { 8, 13, 1 }, { 8, 9, 1 }, { 9, 10, 1 }, { 9, 20, 1 }, { 10, 11, 1 }, { 11, 12, 1 }, { 11, 20, 1 }, { 12, 19, 1 }, { 13, 14, 1 }, { 14, 15, 1 }, { 15, 16, 1 }, { 16, 17, 1 } }}; add_atoms(molecule, atoms); add_bonds(molecule, bonds); molecules[i] = molecule; ++i; } { auto molecule = new sketcherMinimizerMolecule(); std::array, 17> atoms = {{ tuple(6, -2.0218f, 0.7835f), tuple(6, -1.8205f, -0.0165f), tuple(6, -1.027f, -0.2422f), tuple(6, -0.4348f, 0.3321f), tuple(6, -0.6361f, 1.1322f), tuple(6, -1.4296f, 1.3579f), tuple(6, 0.3884f, 0.2763f), tuple(6, 0.6958f, 1.0419f), tuple(6, 0.0626f, 1.5709f), tuple(6, 0.8977f, -0.3727f), tuple(6, 1.7144f, -0.2561f), tuple(6, 2.0218f, 0.5095f), tuple(6, 1.5125f, 1.1585f), tuple(6, -1.0777f, -1.0657f), tuple(6, 0.5897f, -0.5237f), tuple(6, 0.3591f, -1.3159f), tuple(6, -0.4255f, -1.5709f) }}; std::array, 20> bonds = {{ { 0, 1, 1 }, { 0, 5, 1 }, { 1, 2, 1 }, { 2, 3, 1 }, { 2, 13, 1 }, { 3, 4, 1 }, { 3, 6, 1 }, { 4, 5, 1 }, { 4, 8, 1 }, { 6, 7, 1 }, { 6, 9, 1 }, { 6, 14, 1 }, { 7, 8, 1 }, { 7, 12, 1 }, { 9, 10, 1 }, { 10, 11, 1 }, { 11, 12, 1 }, { 13, 16, 1 }, { 14, 15, 1 }, { 15, 16, 1 } }}; add_atoms(molecule, atoms); add_bonds(molecule, bonds); molecules[i] = molecule; ++i; } { auto molecule = new sketcherMinimizerMolecule(); std::array, 15> atoms = {{ tuple(6, 1.1864f, 1.0359f), tuple(6, 0.3703f, 1.157f), tuple(6, -0.3265f, 0.7153f), tuple(6, 0.0851f, 0.0004f), tuple(7, -0.3283f, -0.7136f), tuple(6, -1.1515f, 0.7164f), tuple(6, -1.5649f, 0.0024f), tuple(6, -1.1533f, -0.7126f), tuple(6, 1.7248f, 0.4108f), tuple(6, 1.7238f, -0.4142f), tuple(6, 1.1838f, -1.0379f), tuple(6, 0.3674f, -1.157f), tuple(6, 2.5081f, -0.6701f), tuple(6, 2.9938f, -0.0033f), tuple(7, 2.5097f, 0.6648f) }}; std::array, 17> bonds = {{ { 0, 1, 1 }, { 0, 8, 1 }, { 1, 2, 1 }, { 2, 3, 1 }, { 2, 5, 1 }, { 3, 4, 1 }, { 4, 7, 1 }, { 4, 11, 1 }, { 5, 6, 1 }, { 6, 7, 1 }, { 8, 9, 2 }, { 8, 14, 1 }, { 9, 10, 1 }, { 9, 12, 1 }, { 10, 11, 1 }, { 12, 13, 2 }, { 13, 14, 1 } }}; add_atoms(molecule, atoms); add_bonds(molecule, bonds); molecules[i] = molecule; ++i; } { auto molecule = new sketcherMinimizerMolecule(); std::array, 21> atoms = {{ tuple(6, -1.1557f, -2.1853f), tuple(6, -1.1557f, -1.3604f), tuple(6, -0.4413f, -2.5978f), tuple(6, 0.2731f, -2.1853f), tuple(6, 0.2731f, -1.3604f), tuple(6, -0.4413f, -0.9479f), tuple(6, -0.2278f, -1.8009f), tuple(6, -0.0288f, -0.2334f), tuple(6, -0.0288f, 0.5916f), tuple(6, -0.7433f, 1.0041f), tuple(6, -1.1557f, 0.2896f), tuple(6, -1.1557f, -0.5354f), tuple(6, -0.1599f, 1.5875f), tuple(7, -0.3735f, 2.3842f), tuple(6, -1.1703f, 2.5978f), tuple(6, -1.7536f, 2.0144f), tuple(6, -1.5401f, 1.2176f), tuple(6, -1.8702f, -0.9479f), tuple(6, -2.5846f, -1.3604f), tuple(6, -2.5846f, -2.1853f), tuple(6, -1.8702f, -2.5978f) }}; std::array, 24> bonds = {{ { 0, 1, 1 }, { 0, 2, 1 }, { 0, 20, 1 }, { 1, 5, 1 }, { 1, 17, 1 }, { 2, 3, 1 }, { 2, 6, 1 }, { 3, 4, 1 }, { 4, 5, 1 }, { 5, 7, 1 }, { 6, 11, 1 }, { 7, 8, 1 }, { 8, 9, 1 }, { 9, 10, 1 }, { 9, 12, 1 }, { 9, 16, 1 }, { 10, 11, 1 }, { 12, 13, 1 }, { 13, 14, 1 }, { 14, 15, 1 }, { 15, 16, 1 }, { 17, 18, 1 }, { 18, 19, 1 }, { 19, 20, 1 } }}; add_atoms(molecule, atoms); add_bonds(molecule, bonds); molecules[i] = molecule; ++i; } { auto molecule = new sketcherMinimizerMolecule(); std::array, 28> atoms = {{ tuple(6, -1.1557f, -2.1853f), tuple(6, -1.1557f, -1.3604f), tuple(6, -0.4413f, -2.5978f), tuple(6, 0.2731f, -2.1853f), tuple(6, 0.2731f, -1.3604f), tuple(6, -0.4413f, -0.9479f), tuple(6, 0.9876f, -2.5978f), tuple(6, 1.7021f, -2.1853f), tuple(6, 1.7021f, -1.3604f), tuple(6, 0.9876f, -0.9479f), tuple(6, 1.8703f, -0.4804f), tuple(6, 2.5846f, -0.8929f), tuple(6, 2.5846f, -1.7178f), tuple(6, -0.2278f, -1.8009f), tuple(6, -0.0288f, -0.2334f), tuple(6, -0.0288f, 0.5916f), tuple(6, -0.7433f, 1.0041f), tuple(6, -1.1557f, 0.2896f), tuple(6, -1.1557f, -0.5354f), tuple(6, -0.1599f, 1.5875f), tuple(7, -0.3735f, 2.3842f), tuple(6, -1.1703f, 2.5978f), tuple(6, -1.7536f, 2.0144f), tuple(6, -1.5401f, 1.2176f), tuple(6, -1.8702f, -0.9479f), tuple(6, -2.5846f, -1.3604f), tuple(6, -2.5846f, -2.1853f), tuple(6, -1.8702f, -2.5978f) }}; std::array, 33> bonds = {{ { 0, 1, 1 }, { 0, 2, 1 }, { 0, 27, 1 }, { 1, 5, 1 }, { 1, 24, 1 }, { 2, 3, 1 }, { 2, 13, 1 }, { 3, 4, 1 }, { 3, 6, 1 }, { 4, 5, 1 }, { 4, 9, 1 }, { 5, 14, 1 }, { 6, 7, 1 }, { 7, 8, 1 }, { 7, 12, 1 }, { 8, 9, 1 }, { 9, 10, 1 }, { 10, 11, 1 }, { 11, 12, 1 }, { 13, 18, 1 }, { 14, 15, 1 }, { 15, 16, 1 }, { 16, 17, 1 }, { 16, 19, 1 }, { 16, 23, 1 }, { 17, 18, 1 }, { 19, 20, 1 }, { 20, 21, 1 }, { 21, 22, 1 }, { 22, 23, 1 }, { 24, 25, 1 }, { 25, 26, 1 }, { 26, 27, 1 } }}; add_atoms(molecule, atoms); add_bonds(molecule, bonds); molecules[i] = molecule; ++i; } { auto molecule = new sketcherMinimizerMolecule(); std::array, 23> atoms = {{ tuple(6, -1.1557f, -2.1853f), tuple(6, -1.1557f, -1.3604f), tuple(6, -0.4413f, -2.5978f), tuple(6, 0.2731f, -2.1853f), tuple(6, 0.2731f, -1.3604f), tuple(6, -0.4413f, -0.9479f), tuple(6, 0.9876f, -2.5978f), tuple(6, 1.7021f, -2.1853f), tuple(6, 1.7021f, -1.3604f), tuple(6, 0.9876f, -0.9479f), tuple(6, 1.8703f, -0.4804f), tuple(6, 2.5846f, -0.8929f), tuple(6, 2.5846f, -1.7178f), tuple(6, -0.2278f, -1.8009f), tuple(6, -0.0288f, -0.2334f), tuple(6, -0.0288f, 0.5916f), tuple(6, -0.7433f, 1.0041f), tuple(6, -1.1557f, 0.2896f), tuple(6, -1.1557f, -0.5354f), tuple(6, -1.8702f, -0.9479f), tuple(6, -2.5846f, -1.3604f), tuple(6, -2.5846f, -2.1853f), tuple(6, -1.8702f, -2.5978f) }}; std::array, 27> bonds = {{ { 0, 1, 1 }, { 0, 2, 1 }, { 0, 22, 1 }, { 1, 5, 1 }, { 1, 19, 1 }, { 2, 3, 1 }, { 2, 13, 1 }, { 3, 4, 1 }, { 3, 6, 1 }, { 4, 5, 1 }, { 4, 9, 1 }, { 5, 14, 1 }, { 6, 7, 1 }, { 7, 8, 1 }, { 7, 12, 1 }, { 8, 9, 1 }, { 9, 10, 1 }, { 10, 11, 1 }, { 11, 12, 1 }, { 13, 18, 1 }, { 14, 15, 1 }, { 15, 16, 1 }, { 16, 17, 1 }, { 17, 18, 1 }, { 19, 20, 1 }, { 20, 21, 1 }, { 21, 22, 1 } }}; add_atoms(molecule, atoms); add_bonds(molecule, bonds); molecules[i] = molecule; ++i; } { auto molecule = new sketcherMinimizerMolecule(); std::array, 19> atoms = {{ tuple(6, -1.1557f, -2.1853f), tuple(6, -1.1557f, -1.3604f), tuple(6, -0.4413f, -2.5978f), tuple(6, 0.2731f, -2.1853f), tuple(6, 0.2731f, -1.3604f), tuple(6, -0.4413f, -0.9479f), tuple(6, 0.9876f, -2.5978f), tuple(6, 1.7021f, -2.1853f), tuple(6, 1.7021f, -1.3604f), tuple(6, 0.9876f, -0.9479f), tuple(6, 1.8703f, -0.4804f), tuple(6, 2.5846f, -0.8929f), tuple(6, 2.5846f, -1.7178f), tuple(6, -0.2278f, -1.8009f), tuple(6, -0.0288f, -0.2334f), tuple(6, -0.0288f, 0.5916f), tuple(6, -0.7433f, 1.0041f), tuple(6, -1.1557f, 0.2896f), tuple(6, -1.1557f, -0.5354f) }}; std::array, 22> bonds = {{ { 0, 1, 1 }, { 0, 2, 1 }, { 1, 5, 1 }, { 2, 3, 1 }, { 2, 13, 1 }, { 3, 4, 1 }, { 3, 6, 1 }, { 4, 5, 1 }, { 4, 9, 1 }, { 5, 14, 1 }, { 6, 7, 1 }, { 7, 8, 1 }, { 7, 12, 1 }, { 8, 9, 1 }, { 9, 10, 1 }, { 10, 11, 1 }, { 11, 12, 1 }, { 13, 18, 1 }, { 14, 15, 1 }, { 15, 16, 1 }, { 16, 17, 1 }, { 17, 18, 1 } }}; add_atoms(molecule, atoms); add_bonds(molecule, bonds); molecules[i] = molecule; ++i; } { auto molecule = new sketcherMinimizerMolecule(); std::array, 16> atoms = {{ tuple(6, -1.6619f, 0.54f), tuple(6, -1.6619f, -0.285f), tuple(6, -0.8772f, -0.54f), tuple(6, -0.3923f, 0.1275f), tuple(6, -0.8772f, 0.7949f), tuple(6, -0.3923f, -1.2074f), tuple(6, 0.3923f, -0.9525f), tuple(6, 0.3923f, -0.1275f), tuple(6, 1.1769f, -1.2074f), tuple(6, 1.6619f, -0.54f), tuple(6, 1.1769f, 0.1275f), tuple(6, 0.8772f, 0.54f), tuple(6, 0.3923f, 1.2074f), tuple(6, -0.3923f, 0.9525f), tuple(6, 0.1911f, 0.3691f), tuple(6, -0.0803f, -0.3264f) }}; std::array, 20> bonds = {{ { 0, 1, 1 }, { 0, 4, 1 }, { 1, 2, 1 }, { 2, 3, 1 }, { 2, 5, 1 }, { 2, 15, 1 }, { 3, 4, 1 }, { 3, 7, 1 }, { 3, 13, 1 }, { 5, 6, 1 }, { 6, 7, 1 }, { 6, 8, 1 }, { 7, 10, 1 }, { 7, 11, 1 }, { 8, 9, 1 }, { 9, 10, 1 }, { 11, 12, 1 }, { 12, 13, 1 }, { 13, 14, 1 }, { 14, 15, 1 } }}; add_atoms(molecule, atoms); add_bonds(molecule, bonds); molecules[i] = molecule; ++i; } { auto molecule = new sketcherMinimizerMolecule(); std::array, 33> atoms = {{ tuple(6, 4.9621f, -4.7103f), tuple(6, 4.9621f, -6.1389f), tuple(6, 5.9212f, -3.5981f), tuple(6, 3.6968f, -6.9449f), tuple(6, 2.3169f, -6.32f), tuple(6, 0.9365f, -6.9621f), tuple(6, -0.4126f, -6.3711f), tuple(6, -1.9385f, -6.8286f), tuple(6, -3.0544f, -5.8603f), tuple(6, -3.3986f, -4.4171f), tuple(6, -5.285f, -2.4894f), tuple(6, -5.1939f, -0.9591f), tuple(6, -4.7605f, -3.8655f), tuple(7, -4.2857f, 0.0f), tuple(6, -0.7143f, -1.2372f), tuple(6, 0.0f, -2.4745f), tuple(6, 0.0f, 0.0f), tuple(6, -2.1429f, -1.2372f), tuple(6, 1.4286f, 0.0f), tuple(6, -0.7143f, 1.2372f), tuple(6, 2.1429f, -1.2372f), tuple(6, 2.3274f, 1.1101f), tuple(6, 3.6611f, 0.5983f), tuple(8, 3.5865f, -0.8284f), tuple(6, 1.4286f, -2.4745f), tuple(6, -2.8571f, 0.0f), tuple(6, -2.1429f, 1.2372f), tuple(6, 5.9721f, -2.0675f), tuple(6, 5.041f, -1.2002f), tuple(8, 5.143f, 0.1264f), tuple(6, -0.2728f, 2.5959f), tuple(6, -1.4286f, 3.4356f), tuple(6, -2.5843f, 2.5959f) }}; std::array, 37> bonds = {{ { 0, 1, 1 }, { 0, 2, 1 }, { 1, 3, 1 }, { 2, 27, 1 }, { 3, 4, 1 }, { 4, 5, 1 }, { 5, 6, 1 }, { 6, 7, 1 }, { 7, 8, 1 }, { 8, 9, 2 }, { 9, 12, 1 }, { 10, 11, 1 }, { 10, 12, 2 }, { 11, 13, 1 }, { 13, 25, 1 }, { 14, 15, 1 }, { 14, 16, 2 }, { 14, 17, 1 }, { 15, 24, 2 }, { 16, 18, 1 }, { 16, 19, 1 }, { 17, 25, 1 }, { 18, 20, 2 }, { 18, 21, 1 }, { 19, 30, 1 }, { 19, 26, 1 }, { 20, 23, 1 }, { 20, 24, 1 }, { 21, 22, 1 }, { 22, 23, 1 }, { 22, 29, 1 }, { 25, 26, 2 }, { 26, 32, 1 }, { 27, 28, 2 }, { 28, 29, 1 }, { 30, 31, 1 }, { 31, 32, 1 } }}; add_atoms(molecule, atoms); add_bonds(molecule, bonds); molecules[i] = molecule; ++i; } { auto molecule = new sketcherMinimizerMolecule(); std::array, 22> atoms = {{ tuple(6, -0.5954f, 2.0369f), tuple(6, 0.1067f, 1.6036f), tuple(6, 0.9095f, 1.7937f), tuple(6, -0.1301f, 0.8134f), tuple(6, 0.4359f, 0.2131f), tuple(6, -1.2768f, 1.5718f), tuple(8, -2.0667f, 1.771f), tuple(6, -2.5732f, 0.9006f), tuple(6, -1.8434f, 0.2015f), tuple(6, -2.041f, -0.7786f), tuple(6, -1.0523f, -1.0654f), tuple(6, -0.4916f, -0.4603f), tuple(6, 0.3129f, -0.6432f), tuple(6, -0.8088f, -1.8537f), tuple(6, -0.0044f, -2.0369f), tuple(6, 0.5568f, -1.4313f), tuple(8, 1.509f, -1.201f), tuple(6, 1.2387f, 0.4032f), tuple(6, 1.4755f, 1.1935f), tuple(6, 1.9171f, -0.0662f), tuple(6, 2.5732f, 0.4339f), tuple(6, 2.2928f, 1.2146f) }}; std::array, 25> bonds = {{ { 0, 1, 1 }, { 0, 5, 1 }, { 1, 2, 2 }, { 1, 3, 1 }, { 2, 18, 1 }, { 3, 4, 2 }, { 4, 17, 1 }, { 5, 6, 1 }, { 6, 7, 1 }, { 7, 8, 1 }, { 8, 9, 1 }, { 9, 10, 1 }, { 10, 11, 2 }, { 10, 13, 1 }, { 11, 12, 1 }, { 12, 15, 2 }, { 13, 14, 2 }, { 14, 15, 1 }, { 15, 16, 1 }, { 16, 19, 1 }, { 17, 18, 2 }, { 17, 19, 1 }, { 18, 21, 1 }, { 19, 20, 1 }, { 20, 21, 1 } }}; add_atoms(molecule, atoms); add_bonds(molecule, bonds); molecules[i] = molecule; ++i; } { auto molecule = new sketcherMinimizerMolecule(); std::array, 12> atoms = {{ tuple(6, 0.6671f, 1.194f), tuple(6, 1.3729f, 0.7668f), tuple(6, 1.6278f, -0.0178f), tuple(6, -0.1463f, 1.056f), tuple(6, -0.6717f, 0.42f), tuple(6, -1.4563f, 0.165f), tuple(6, -1.6278f, -0.6419f), tuple(6, -1.0147f, -1.194f), tuple(7, -0.2301f, -0.939f), tuple(6, -0.0586f, -0.1321f), tuple(6, 0.5688f, -1.1448f), tuple(6, 1.308f, -0.7783f) }}; std::array, 13> bonds = {{ { 0, 1, 1 }, { 0, 3, 1 }, { 1, 2, 1 }, { 2, 11, 1 }, { 3, 4, 1 }, { 4, 5, 1 }, { 4, 9, 1 }, { 5, 6, 1 }, { 6, 7, 1 }, { 7, 8, 1 }, { 8, 9, 1 }, { 8, 10, 1 }, { 10, 11, 1 } }}; add_atoms(molecule, atoms); add_bonds(molecule, bonds); molecules[i] = molecule; ++i; } { auto molecule = new sketcherMinimizerMolecule(); std::array, 13> atoms = {{ tuple(6, 0.7206f, 1.0259f), tuple(6, 0.0041f, 0.617f), tuple(6, -0.0f, -0.208f), tuple(6, 0.7124f, -0.6241f), tuple(6, 1.4289f, -0.2152f), tuple(6, 1.433f, 0.6098f), tuple(6, -0.7083f, 1.033f), tuple(6, -1.4248f, 0.6241f), tuple(6, -1.4289f, -0.2009f), tuple(6, -0.7165f, -0.617f), tuple(6, -0.7124f, 0.208f), tuple(6, -0.0041f, -1.033f), tuple(6, -1.433f, -1.0259f) }}; std::array, 16> bonds = {{ { 0, 1, 1 }, { 0, 5, 1 }, { 1, 2, 1 }, { 1, 6, 1 }, { 2, 3, 1 }, { 2, 9, 1 }, { 2, 11, 1 }, { 3, 4, 1 }, { 4, 5, 1 }, { 6, 7, 1 }, { 6, 10, 1 }, { 7, 8, 1 }, { 8, 9, 1 }, { 8, 12, 1 }, { 10, 12, 1 }, { 11, 12, 1 } }}; add_atoms(molecule, atoms); add_bonds(molecule, bonds); molecules[i] = molecule; ++i; } { auto molecule = new sketcherMinimizerMolecule(); std::array, 31> atoms = {{ tuple(6, 2.9876f, -0.7593f), tuple(7, 3.2265f, 0.0303f), tuple(6, 2.5493f, 0.5015f), tuple(7, 1.8919f, 0.0031f), tuple(6, 2.1628f, -0.7762f), tuple(6, 1.0816f, 0.1581f), tuple(6, 0.8107f, 0.9374f), tuple(6, 1.3501f, 1.5616f), tuple(6, 1.0792f, 2.3409f), tuple(6, 0.2689f, 2.4959f), tuple(6, -0.2705f, 1.8716f), tuple(6, 0.0004f, 1.0924f), tuple(8, -1.0689f, 2.0308f), tuple(6, -1.6083f, 1.4066f), tuple(6, -1.3374f, 0.6273f), tuple(6, -1.8768f, 0.0031f), tuple(6, -2.6871f, 0.1581f), tuple(6, -2.958f, 0.9374f), tuple(6, -2.4186f, 1.5616f), tuple(6, -3.2265f, -0.4661f), tuple(6, -2.9556f, -1.2454f), tuple(6, -2.1453f, -1.4004f), tuple(6, -1.6059f, -0.7762f), tuple(7, -0.7956f, -0.9312f), tuple(6, -0.5247f, -1.7104f), tuple(6, 0.2856f, -1.8655f), tuple(6, 0.5591f, -1.0871f), tuple(6, -0.0651f, -0.5477f), tuple(7, 0.8178f, -2.4959f), tuple(6, 1.597f, -2.225f), tuple(6, 1.6234f, -1.4004f) }}; std::array, 36> bonds = {{ { 0, 1, 1 }, { 0, 4, 2 }, { 1, 2, 2 }, { 2, 3, 1 }, { 3, 4, 1 }, { 3, 5, 1 }, { 4, 30, 1 }, { 5, 6, 1 }, { 6, 7, 2 }, { 6, 11, 1 }, { 7, 8, 1 }, { 8, 9, 1 }, { 9, 10, 1 }, { 10, 11, 1 }, { 10, 12, 1 }, { 12, 13, 1 }, { 13, 14, 2 }, { 13, 18, 1 }, { 14, 15, 1 }, { 15, 16, 2 }, { 15, 22, 1 }, { 16, 17, 1 }, { 16, 19, 1 }, { 17, 18, 2 }, { 19, 20, 2 }, { 20, 21, 1 }, { 21, 22, 2 }, { 22, 23, 1 }, { 23, 24, 1 }, { 23, 27, 1 }, { 24, 25, 1 }, { 25, 26, 1 }, { 25, 28, 1 }, { 26, 27, 1 }, { 28, 29, 1 }, { 29, 30, 1 } }}; add_atoms(molecule, atoms); add_bonds(molecule, bonds); molecules[i] = molecule; ++i; } { auto molecule = new sketcherMinimizerMolecule(); std::array, 24> atoms = {{ tuple(6, -1.5713f, -2.1854f), tuple(6, -1.5713f, -1.3604f), tuple(6, -0.8568f, -2.5979f), tuple(6, -0.1424f, -2.1854f), tuple(6, -0.1424f, -1.3604f), tuple(6, -0.8568f, -0.9479f), tuple(6, 0.5721f, -2.5979f), tuple(6, 1.2866f, -2.1854f), tuple(6, 1.2866f, -1.3604f), tuple(6, 0.5721f, -0.9479f), tuple(6, 1.4548f, -0.4804f), tuple(6, 2.1692f, -0.8929f), tuple(6, 2.1692f, -1.7179f), tuple(6, -0.6433f, -1.801f), tuple(6, -0.4443f, -0.2334f), tuple(6, -0.4443f, 0.5916f), tuple(6, -1.1588f, 1.0041f), tuple(6, -1.5713f, 0.2896f), tuple(6, -1.5713f, -0.5354f), tuple(6, -0.5754f, 1.5875f), tuple(7, -0.789f, 2.3843f), tuple(6, -1.5859f, 2.5979f), tuple(6, -2.1692f, 2.0145f), tuple(6, -1.9557f, 1.2176f) }}; std::array, 28> bonds = {{ { 0, 1, 1 }, { 0, 2, 1 }, { 1, 5, 1 }, { 2, 3, 1 }, { 2, 13, 1 }, { 3, 4, 1 }, { 3, 6, 1 }, { 4, 5, 1 }, { 4, 9, 1 }, { 5, 14, 1 }, { 6, 7, 1 }, { 7, 8, 1 }, { 7, 12, 1 }, { 8, 9, 1 }, { 9, 10, 1 }, { 10, 11, 1 }, { 11, 12, 1 }, { 13, 18, 1 }, { 14, 15, 1 }, { 15, 16, 1 }, { 16, 17, 1 }, { 16, 19, 1 }, { 16, 23, 1 }, { 17, 18, 1 }, { 19, 20, 1 }, { 20, 21, 1 }, { 21, 22, 1 }, { 22, 23, 1 } }}; add_atoms(molecule, atoms); add_bonds(molecule, bonds); molecules[i] = molecule; ++i; } { auto molecule = new sketcherMinimizerMolecule(); std::array, 27> atoms = {{ tuple(6, -2.5006f, 1.8351f), tuple(6, -2.5006f, 1.0101f), tuple(6, -1.7862f, 0.5976f), tuple(6, -1.0717f, 1.0101f), tuple(6, -1.0717f, 1.8351f), tuple(6, -1.7862f, 2.2476f), tuple(6, -0.3572f, 0.5976f), tuple(6, 0.3572f, 1.0101f), tuple(6, 0.3572f, 1.8351f), tuple(6, -0.3572f, 2.2476f), tuple(6, 1.0717f, 0.5976f), tuple(6, 1.0717f, -0.2274f), tuple(6, 1.7862f, -0.6399f), tuple(6, 2.5006f, -0.2274f), tuple(6, 2.5006f, 0.5976f), tuple(6, 1.7862f, 1.0101f), tuple(6, 0.4586f, -0.7794f), tuple(6, 0.7942f, -1.5331f), tuple(6, 1.6147f, -1.4469f), tuple(6, 0.3817f, -2.2476f), tuple(6, -0.4708f, -2.2476f), tuple(6, -0.9883f, -1.678f), tuple(6, -1.0477f, -0.8552f), tuple(6, -1.8486f, -0.6573f), tuple(6, -2.2843f, -1.3579f), tuple(6, -1.7526f, -1.9888f), tuple(6, -2.3115f, 0.0256f) }}; std::array, 32> bonds = {{ { 0, 1, 1 }, { 0, 5, 1 }, { 1, 2, 1 }, { 2, 3, 1 }, { 2, 26, 1 }, { 3, 4, 1 }, { 3, 6, 1 }, { 4, 5, 1 }, { 4, 9, 1 }, { 6, 7, 1 }, { 7, 8, 1 }, { 7, 10, 1 }, { 8, 9, 1 }, { 10, 11, 1 }, { 10, 15, 1 }, { 11, 12, 1 }, { 11, 16, 1 }, { 12, 13, 1 }, { 12, 18, 1 }, { 13, 14, 1 }, { 14, 15, 1 }, { 16, 17, 1 }, { 17, 18, 1 }, { 17, 19, 1 }, { 19, 20, 1 }, { 20, 21, 1 }, { 21, 22, 1 }, { 21, 25, 1 }, { 22, 23, 1 }, { 23, 24, 1 }, { 23, 26, 1 }, { 24, 25, 1 } }}; add_atoms(molecule, atoms); add_bonds(molecule, bonds); molecules[i] = molecule; ++i; } { auto molecule = new sketcherMinimizerMolecule(); std::array, 22> atoms = {{ tuple(6, -1.7862f, -0.825f), tuple(6, -2.5006f, -0.4125f), tuple(6, -2.5006f, 0.4125f), tuple(6, -1.7862f, 0.825f), tuple(6, -1.0717f, 0.4125f), tuple(6, -1.0717f, -0.4125f), tuple(7, -0.3572f, 0.825f), tuple(6, -0.3572f, 1.65f), tuple(7, 0.3572f, 2.0625f), tuple(6, 1.0717f, 1.65f), tuple(7, 1.0717f, 0.825f), tuple(6, 1.7862f, 0.4125f), tuple(6, 2.5006f, 0.825f), tuple(7, 2.5006f, 1.65f), tuple(6, 1.7862f, 2.0625f), tuple(8, 1.7862f, -0.4125f), tuple(6, 2.3054f, -1.0536f), tuple(6, 1.8929f, -1.7681f), tuple(6, 1.0717f, -1.65f), tuple(6, 0.3572f, -2.0625f), tuple(6, -0.3572f, -1.65f), tuple(8, -0.3572f, -0.825f) }}; std::array, 24> bonds = {{ { 0, 1, 2 }, { 0, 5, 1 }, { 1, 2, 1 }, { 2, 3, 2 }, { 3, 4, 1 }, { 4, 5, 2 }, { 4, 6, 1 }, { 5, 21, 1 }, { 6, 7, 1 }, { 7, 8, 1 }, { 8, 9, 1 }, { 9, 10, 2 }, { 9, 14, 1 }, { 10, 11, 1 }, { 11, 12, 2 }, { 11, 15, 1 }, { 12, 13, 1 }, { 13, 14, 2 }, { 15, 16, 1 }, { 16, 17, 1 }, { 17, 18, 1 }, { 18, 19, 1 }, { 19, 20, 1 }, { 20, 21, 1 } }}; add_atoms(molecule, atoms); add_bonds(molecule, bonds); molecules[i] = molecule; ++i; } { auto molecule = new sketcherMinimizerMolecule(); std::array, 17> atoms = {{ tuple(6, -0.9687f, 0.294f), tuple(6, -1.7749f, 0.119f), tuple(6, -2.0264f, -0.6668f), tuple(6, -1.4717f, -1.2774f), tuple(6, -0.6655f, -1.1024f), tuple(6, -0.414f, -0.3166f), tuple(8, 0.0041f, -1.5844f), tuple(6, 0.6694f, -1.0965f), tuple(6, 0.411f, -0.313f), tuple(6, 0.9603f, 0.3025f), tuple(6, 1.768f, 0.1345f), tuple(6, 2.0264f, -0.649f), tuple(6, 1.4771f, -1.2645f), tuple(6, 0.9517f, 1.1274f), tuple(7, 0.3748f, 1.5844f), tuple(6, -0.4444f, 1.3835f), tuple(6, -0.6449f, 0.6594f) }}; std::array, 20> bonds = {{ { 0, 1, 2 }, { 0, 5, 1 }, { 1, 2, 1 }, { 2, 3, 1 }, { 3, 4, 1 }, { 4, 5, 1 }, { 4, 6, 1 }, { 5, 8, 1 }, { 5, 16, 1 }, { 6, 7, 1 }, { 7, 8, 2 }, { 7, 12, 1 }, { 8, 9, 1 }, { 9, 10, 2 }, { 9, 13, 1 }, { 10, 11, 1 }, { 11, 12, 2 }, { 13, 14, 2 }, { 14, 15, 1 }, { 15, 16, 1 } }}; add_atoms(molecule, atoms); add_bonds(molecule, bonds); molecules[i] = molecule; ++i; } { auto molecule = new sketcherMinimizerMolecule(); std::array, 36> atoms = {{ tuple(6, -1.5817f, 0.3446f), tuple(8, -1.1692f, -0.3699f), tuple(6, -1.5817f, -1.0843f), tuple(6, -2.3519f, -1.38f), tuple(7, -2.3519f, -2.205f), tuple(6, -1.5817f, -2.5006f), tuple(6, -1.1692f, -3.2151f), tuple(6, -3.0664f, -2.6175f), tuple(6, -3.7808f, -2.205f), tuple(6, -3.7808f, -1.38f), tuple(6, -3.0664f, -0.9675f), tuple(6, -1.1692f, 1.0591f), tuple(6, -1.5817f, 1.7862f), tuple(6, -1.1692f, 2.5006f), tuple(6, -0.3442f, 2.5006f), tuple(6, 0.0683f, 3.2151f), tuple(6, 0.8933f, 3.2151f), tuple(6, 1.3058f, 3.9296f), tuple(6, 2.1308f, 3.9296f), tuple(6, 2.5433f, 3.2151f), tuple(6, 3.3683f, 3.2151f), tuple(6, 3.7808f, 2.5006f), tuple(6, 3.3683f, 1.7862f), tuple(6, 3.7808f, 1.0717f), tuple(6, 3.3683f, 0.3572f), tuple(6, 3.7808f, -0.3572f), tuple(6, 3.3683f, -1.0717f), tuple(6, 2.5433f, -1.0717f), tuple(6, 2.1308f, -1.7862f), tuple(6, 1.3058f, -1.7862f), tuple(6, 0.8933f, -2.5006f), tuple(8, 0.0683f, -2.5006f), tuple(6, 1.3058f, -3.2151f), tuple(6, 0.8933f, -3.9296f), tuple(6, 0.0683f, -3.9296f), tuple(6, -0.3442f, -3.2151f) }}; std::array, 38> bonds = {{ { 0, 1, 1 }, { 0, 11, 1 }, { 1, 2, 1 }, { 2, 3, 1 }, { 3, 4, 1 }, { 3, 10, 1 }, { 4, 5, 1 }, { 4, 7, 1 }, { 5, 6, 1 }, { 6, 35, 1 }, { 7, 8, 1 }, { 8, 9, 1 }, { 9, 10, 1 }, { 11, 12, 1 }, { 12, 13, 1 }, { 13, 14, 1 }, { 14, 15, 2 }, { 15, 16, 1 }, { 16, 17, 1 }, { 17, 18, 1 }, { 18, 19, 1 }, { 19, 20, 1 }, { 20, 21, 1 }, { 21, 22, 1 }, { 22, 23, 2 }, { 23, 24, 1 }, { 24, 25, 2 }, { 25, 26, 1 }, { 26, 27, 2 }, { 27, 28, 1 }, { 28, 29, 1 }, { 29, 30, 1 }, { 30, 31, 1 }, { 30, 32, 1 }, { 31, 35, 1 }, { 32, 33, 1 }, { 33, 34, 1 }, { 34, 35, 1 } }}; add_atoms(molecule, atoms); add_bonds(molecule, bonds); molecules[i] = molecule; ++i; } { auto molecule = new sketcherMinimizerMolecule(); std::array, 8> atoms = {{ tuple(26, -5.7389f, 2.4841f), tuple(16, -4.5017f, 3.1984f), tuple(26, -4.5017f, 4.627f), tuple(16, -5.7389f, 5.3413f), tuple(26, -6.9761f, 4.627f), tuple(16, -6.9761f, 3.1984f), tuple(26, -6.2969f, 3.8639f), tuple(16, -4.8637f, 3.9143f) }}; std::array, 15> bonds = {{ { 0, 1, 1 }, { 0, 7, 1 }, { 0, 5, 1 }, { 0, 6, 1 }, { 1, 2, 1 }, { 1, 6, 1 }, { 2, 3, 1 }, { 2, 6, 1 }, { 2, 7, 1 }, { 3, 4, 1 }, { 3, 6, 1 }, { 4, 5, 1 }, { 4, 6, 1 }, { 4, 7, 1 }, { 5, 6, 1 } }}; add_atoms(molecule, atoms); add_bonds(molecule, bonds); molecules[i] = molecule; ++i; } { auto molecule = new sketcherMinimizerMolecule(); std::array, 16> atoms = {{ tuple(6, 0.054f, -2.4738f), tuple(6, 1.276f, -3.2135f), tuple(6, 0.7411f, -1.2213f), tuple(7, -1.3742f, -2.5049f), tuple(6, 2.6845f, -2.9747f), tuple(6, 3.5944f, -1.8734f), tuple(6, 3.5633f, -0.4452f), tuple(6, 2.6062f, 0.6154f), tuple(6, 1.1886f, 0.7924f), tuple(7, 0.0f, 0.0f), tuple(6, -1.4282f, -0.0312f), tuple(6, -2.1153f, -1.2836f), tuple(6, 3.4683f, 1.7546f), tuple(6, 2.9127f, 3.0707f), tuple(6, 1.4952f, 3.2477f), tuple(6, 0.6331f, 2.1085f) }}; std::array, 18> bonds = {{ { 0, 1, 1 }, { 0, 2, 1 }, { 0, 3, 1 }, { 1, 4, 1 }, { 2, 9, 1 }, { 3, 11, 1 }, { 4, 5, 1 }, { 5, 6, 1 }, { 6, 7, 1 }, { 7, 8, 1 }, { 7, 12, 1 }, { 8, 9, 1 }, { 8, 15, 1 }, { 9, 10, 1 }, { 10, 11, 1 }, { 12, 13, 1 }, { 13, 14, 1 }, { 14, 15, 1 } }}; add_atoms(molecule, atoms); add_bonds(molecule, bonds); molecules[i] = molecule; ++i; } { auto molecule = new sketcherMinimizerMolecule(); std::array, 12> atoms = {{ tuple(6, 0.3959f, -0.7295f), tuple(6, -0.3098f, -1.1567f), tuple(6, -1.1232f, -1.0188f), tuple(6, -1.6487f, -0.3828f), tuple(6, -1.6307f, 0.442f), tuple(6, -1.078f, 1.0545f), tuple(6, -0.2593f, 1.1567f), tuple(7, 0.4271f, 0.6991f), tuple(6, -0.0009f, -0.0062f), tuple(6, 1.2519f, 0.6811f), tuple(6, 1.6487f, -0.0422f), tuple(7, 1.2207f, -0.7475f) }}; std::array, 13> bonds = {{ { 0, 1, 1 }, { 0, 8, 1 }, { 0, 11, 1 }, { 1, 2, 1 }, { 2, 3, 1 }, { 3, 4, 1 }, { 4, 5, 1 }, { 5, 6, 1 }, { 6, 7, 1 }, { 7, 8, 1 }, { 7, 9, 1 }, { 9, 10, 1 }, { 10, 11, 1 } }}; add_atoms(molecule, atoms); add_bonds(molecule, bonds); molecules[i] = molecule; ++i; } { auto molecule = new sketcherMinimizerMolecule(); std::array, 26> atoms = {{ tuple(6, 0.1992f, 1.5479f), tuple(8, 0.7062f, 2.1987f), tuple(6, 1.5206f, 2.0665f), tuple(6, 1.7957f, 1.2887f), tuple(6, 1.3309f, 0.6071f), tuple(6, 0.5266f, 0.7907f), tuple(6, 2.6183f, 1.2271f), tuple(6, 2.9763f, 0.4838f), tuple(6, 2.5116f, -0.1979f), tuple(6, 1.6889f, -0.1362f), tuple(6, 1.3309f, -0.8795f), tuple(6, 0.5266f, -1.0631f), tuple(6, -0.0064f, -0.1362f), tuple(6, -0.1184f, -0.5487f), tuple(6, -0.1184f, 0.2763f), tuple(6, -0.8329f, 0.6888f), tuple(6, -1.5474f, 0.2763f), tuple(6, -1.5474f, -0.5487f), tuple(6, -0.8329f, -0.9612f), tuple(6, -0.8329f, -1.7862f), tuple(6, -1.5474f, -2.1987f), tuple(6, -2.2618f, -1.7862f), tuple(6, -2.2618f, -0.9612f), tuple(6, -2.9763f, -0.5487f), tuple(8, -2.9763f, 0.2763f), tuple(6, -2.2618f, 0.6888f) }}; std::array, 32> bonds = {{ { 0, 1, 1 }, { 0, 5, 1 }, { 1, 2, 1 }, { 2, 3, 1 }, { 3, 4, 2 }, { 3, 6, 1 }, { 4, 5, 1 }, { 4, 9, 1 }, { 5, 12, 1 }, { 5, 14, 1 }, { 6, 7, 2 }, { 7, 8, 1 }, { 8, 9, 2 }, { 9, 10, 1 }, { 10, 11, 1 }, { 11, 12, 1 }, { 11, 13, 1 }, { 13, 14, 1 }, { 13, 18, 1 }, { 14, 15, 1 }, { 15, 16, 1 }, { 16, 17, 1 }, { 16, 25, 1 }, { 17, 18, 2 }, { 17, 22, 1 }, { 18, 19, 1 }, { 19, 20, 2 }, { 20, 21, 1 }, { 21, 22, 2 }, { 22, 23, 1 }, { 23, 24, 1 }, { 24, 25, 1 } }}; add_atoms(molecule, atoms); add_bonds(molecule, bonds); molecules[i] = molecule; ++i; } { auto molecule = new sketcherMinimizerMolecule(); std::array, 19> atoms = {{ tuple(6, -1.1536f, -1.4947f), tuple(6, -1.9579f, -1.3111f), tuple(6, -2.3159f, -0.5678f), tuple(6, -1.2316f, -0.2195f), tuple(6, -1.9579f, 0.1755f), tuple(6, -1.1536f, 0.3591f), tuple(6, -0.5086f, -0.1553f), tuple(6, -0.5086f, -0.9803f), tuple(6, 0.2058f, 0.2572f), tuple(6, 0.9203f, -0.1553f), tuple(6, 1.6348f, 0.2572f), tuple(6, 2.3159f, -0.027f), tuple(6, 1.787601f, -0.327842f), tuple(6, 0.954927f, 0.36928f), tuple(6, 1.6348f, 1.0822f), tuple(8, 0.9203f, 1.4947f), tuple(6, 0.2058f, 1.0822f), tuple(6, 0.9203f, -0.9803f), tuple(6, 0.2058f, -1.3928f) }}; std::array, 23> bonds = {{ { 0, 1, 1 }, { 0, 7, 1 }, { 1, 2, 1 }, { 2, 3, 1 }, { 2, 4, 1 }, { 3, 7, 1 }, { 4, 5, 1 }, { 5, 6, 1 }, { 6, 7, 1 }, { 6, 8, 1 }, { 7, 18, 1 }, { 8, 9, 1 }, { 8, 13, 1 }, { 8, 16, 1 }, { 9, 10, 1 }, { 9, 17, 1 }, { 10, 11, 1 }, { 10, 14, 1 }, { 11, 12, 1 }, { 12, 13, 1 }, { 14, 15, 1 }, { 15, 16, 1 }, { 17, 18, 1 } }}; add_atoms(molecule, atoms); add_bonds(molecule, bonds); molecules[i] = molecule; ++i; } { auto molecule = new sketcherMinimizerMolecule(); std::array, 14> atoms = {{ tuple(7, 1.4289f, -0.4125f), tuple(8, 1.4289f, 0.4125f), tuple(6, 0.7145f, -0.825f), tuple(6, 0.0f, -0.4125f), tuple(6, 0.0f, 0.4125f), tuple(6, 0.7145f, 0.825f), tuple(6, 1.0565f, 0.3094f), tuple(6, 1.0565f, -0.3094f), tuple(6, -0.7145f, 0.825f), tuple(7, -1.4289f, 0.4125f), tuple(7, -1.4289f, -0.4125f), tuple(6, -0.7145f, -0.825f), tuple(6, -1.0565f, -0.3094f), tuple(6, -1.0565f, 0.3094f) }}; std::array, 17> bonds = {{ { 0, 1, 1 }, { 0, 2, 1 }, { 1, 5, 1 }, { 2, 3, 1 }, { 2, 7, 1 }, { 3, 4, 1 }, { 3, 11, 1 }, { 4, 5, 1 }, { 4, 8, 1 }, { 5, 6, 1 }, { 6, 7, 2 }, { 8, 9, 1 }, { 8, 13, 1 }, { 9, 10, 2 }, { 10, 11, 1 }, { 11, 12, 1 }, { 12, 13, 1 } }}; add_atoms(molecule, atoms); add_bonds(molecule, bonds); molecules[i] = molecule; ++i; } { auto molecule = new sketcherMinimizerMolecule(); std::array, 17> atoms = {{ tuple(6, 0.9645f, -1.0314f), tuple(6, 1.7715f, -0.8599f), tuple(6, 2.0264f, -0.0753f), tuple(6, 1.4744f, 0.5378f), tuple(6, 0.9081f, 1.0314f), tuple(8, 0.0831f, 0.3439f), tuple(6, 0.6674f, 0.3663f), tuple(6, -0.0f, 0.8512f), tuple(6, -0.6674f, 0.3663f), tuple(6, -0.4125f, -0.4183f), tuple(6, 0.4125f, -0.4183f), tuple(6, -1.4744f, 0.5378f), tuple(6, -2.0264f, -0.0753f), tuple(6, -1.5932f, -0.5171f), tuple(6, -0.988f, -0.6457f), tuple(6, -1.7715f, -0.8599f), tuple(6, -0.9645f, -1.0314f) }}; std::array, 21> bonds = {{ { 0, 1, 1 }, { 0, 10, 1 }, { 1, 2, 1 }, { 2, 3, 1 }, { 3, 4, 1 }, { 3, 6, 1 }, { 4, 5, 1 }, { 5, 10, 1 }, { 6, 7, 1 }, { 6, 10, 1 }, { 7, 8, 1 }, { 8, 9, 1 }, { 8, 11, 2 }, { 9, 10, 1 }, { 9, 14, 1 }, { 9, 16, 1 }, { 11, 12, 1 }, { 12, 13, 1 }, { 12, 15, 1 }, { 13, 14, 1 }, { 15, 16, 1 } }}; add_atoms(molecule, atoms); add_bonds(molecule, bonds); molecules[i] = molecule; ++i; } { auto molecule = new sketcherMinimizerMolecule(); std::array, 16> atoms = {{ tuple(7, -0.9959f, 1.5792f), tuple(6, -1.5792f, 0.9959f), tuple(6, -0.9959f, 0.4125f), tuple(6, -0.4125f, 0.9959f), tuple(6, -0.4125f, -0.1709f), tuple(6, 0.1709f, 0.4125f), tuple(6, -0.9959f, -0.4125f), tuple(6, -0.4125f, -0.9959f), tuple(6, 0.4125f, -0.9959f), tuple(6, 0.9959f, -0.4125f), tuple(6, 0.9959f, 0.4125f), tuple(6, 0.4125f, 0.9959f), tuple(6, 1.1026f, -0.8109f), tuple(6, 0.510524f, -1.402976f), tuple(7, 1.5792f, -0.9959f), tuple(7, 0.9959f, -1.5792f) }}; std::array, 20> bonds = {{ { 0, 1, 1 }, { 0, 3, 1 }, { 1, 2, 1 }, { 2, 3, 1 }, { 2, 4, 1 }, { 2, 6, 1 }, { 3, 5, 1 }, { 3, 11, 1 }, { 4, 5, 1 }, { 6, 7, 1 }, { 7, 8, 1 }, { 8, 9, 1 }, { 8, 13, 1 }, { 8, 15, 1 }, { 9, 10, 1 }, { 9, 12, 1 }, { 9, 14, 1 }, { 10, 11, 1 }, { 12, 13, 1 }, { 14, 15, 1 } }}; add_atoms(molecule, atoms); add_bonds(molecule, bonds); molecules[i] = molecule; ++i; } { auto molecule = new sketcherMinimizerMolecule(); std::array, 10> atoms = {{ tuple(6, 0.0f, 0.0f), tuple(6, 1.7143f, 0.8571f), tuple(7, -1.4286f, 0.4286f), tuple(7, 0.1429f, -1.4286f), tuple(6, 1.5714f, 2.2857f), tuple(6, 3.1429f, 0.4286f), tuple(6, 0.1429f, 2.2857f), tuple(6, 0.0f, 0.8571f), tuple(6, 1.7143f, 0.0f), tuple(6, 1.5714f, -1.4286f) }}; std::array, 12> bonds = {{ { 0, 1, 1 }, { 0, 2, 1 }, { 0, 3, 1 }, { 1, 4, 1 }, { 1, 5, 1 }, { 2, 7, 1 }, { 3, 9, 1 }, { 4, 6, 1 }, { 5, 8, 1 }, { 6, 7, 1 }, { 7, 8, 1 }, { 8, 9, 1 } }}; add_atoms(molecule, atoms); add_bonds(molecule, bonds); molecules[i] = molecule; ++i; } { auto molecule = new sketcherMinimizerMolecule(); std::array, 10> atoms = {{ tuple(7, -0.3709f, 2.6749f), tuple(7, 0.8663f, 3.1035f), tuple(8, -0.3709f, 1.2463f), tuple(7, 2.1035f, 2.6749f), tuple(6, 1.5806f, 2.152f), tuple(6, 2.1035f, 1.2463f), tuple(6, 0.8663f, 0.8178f), tuple(6, 2.8178f, 0.2949f), tuple(6, 0.3434f, 0.2949f), tuple(6, 1.5806f, 0.7234f) }}; std::array, 12> bonds = {{ { 0, 1, 1 }, { 0, 2, 1 }, { 1, 3, 1 }, { 1, 4, 1 }, { 2, 8, 1 }, { 2, 6, 1 }, { 3, 5, 1 }, { 4, 9, 1 }, { 5, 6, 1 }, { 5, 7, 1 }, { 7, 9, 1 }, { 8, 9, 1 } }}; add_atoms(molecule, atoms); add_bonds(molecule, bonds); molecules[i] = molecule; ++i; } { auto molecule = new sketcherMinimizerMolecule(); std::array, 11> atoms = {{ tuple(6, 2.2594f, -2.751f), tuple(6, 3.2304f, -1.7031f), tuple(6, 0.9479f, -2.3215f), tuple(6, 0.6005f, -1.1462f), tuple(6, -0.5154f, -2.8288f), tuple(6, -1.5255f, -1.8186f), tuple(6, 1.3803f, -0.3684f), tuple(6, 0.0f, 0.0f), tuple(6, 2.1571f, 0.8305f), tuple(6, 1.257f, 1.9398f), tuple(6, -0.0762f, 1.4265f) }}; std::array, 13> bonds = {{ { 0, 1, 2 }, { 0, 2, 1 }, { 1, 3, 1 }, { 2, 6, 1 }, { 2, 4, 1 }, { 3, 7, 1 }, { 3, 5, 1 }, { 4, 5, 1 }, { 6, 8, 1 }, { 6, 7, 2 }, { 7, 10, 1 }, { 8, 9, 1 }, { 9, 10, 1 } }}; add_atoms(molecule, atoms); add_bonds(molecule, bonds); molecules[i] = molecule; ++i; } { auto molecule = new sketcherMinimizerMolecule(); std::array, 30> atoms = {{ tuple(6, -6.8968f, -2.1736f), tuple(6, -7.7218f, -2.1736f), tuple(6, -7.7218f, -3.6026f), tuple(6, -6.8968f, -3.6026f), tuple(6, -6.4843f, -2.8881f), tuple(6, -8.2409f, -1.5325f), tuple(6, -9.0111f, -1.8281f), tuple(8, -8.968f, -2.652f), tuple(6, -8.1343f, -2.8881f), tuple(8, -9.8669f, -2.1006f), tuple(6, -5.6593f, -1.4591f), tuple(6, -6.4843f, -1.4591f), tuple(6, -5.6593f, -2.8881f), tuple(6, -5.2468f, -2.1736f), tuple(7, -4.4218f, -2.1736f), tuple(6, -3.8973f, -2.7275f), tuple(6, -9.808f, -2.8667f), tuple(6, -10.3457f, -3.3676f), tuple(6, -10.3163f, -4.2515f), tuple(6, -9.7624f, -4.8938f), tuple(6, -9.7624f, -5.7188f), tuple(6, -9.0317f, -6.1843f), tuple(6, -8.2348f, -5.8234f), tuple(6, -7.4376f, -6.1942f), tuple(6, -6.6585f, -5.8529f), tuple(6, -5.7773f, -6.1171f), tuple(6, -3.8447f, -3.6112f), tuple(6, -4.1476f, -4.4059f), tuple(6, -4.9341f, -4.7245f), tuple(6, -5.1329f, -5.5579f) }}; std::array, 33> bonds = {{ { 0, 1, 1 }, { 0, 4, 2 }, { 0, 11, 1 }, { 1, 5, 1 }, { 1, 8, 2 }, { 2, 8, 1 }, { 2, 3, 2 }, { 3, 4, 1 }, { 4, 12, 1 }, { 5, 6, 1 }, { 6, 7, 1 }, { 6, 9, 1 }, { 7, 8, 1 }, { 9, 16, 1 }, { 10, 11, 1 }, { 10, 13, 1 }, { 12, 13, 2 }, { 13, 14, 1 }, { 14, 15, 1 }, { 15, 26, 1 }, { 16, 17, 2 }, { 17, 18, 1 }, { 18, 19, 1 }, { 19, 20, 1 }, { 20, 21, 1 }, { 21, 22, 1 }, { 22, 23, 1 }, { 23, 24, 1 }, { 24, 25, 1 }, { 25, 29, 1 }, { 26, 27, 2 }, { 27, 28, 1 }, { 28, 29, 2 } }}; add_atoms(molecule, atoms); add_bonds(molecule, bonds); molecules[i] = molecule; ++i; } { auto molecule = new sketcherMinimizerMolecule(); std::array, 17> atoms = {{ tuple(6, -0.0447f, -0.7938f), tuple(6, -0.0447f, -1.6188f), tuple(6, 0.7399f, -1.8737f), tuple(6, 1.2248f, -1.2063f), tuple(6, 0.7399f, -0.5388f), tuple(6, -0.8293f, -0.5388f), tuple(6, -1.3143f, -1.2063f), tuple(6, -0.8293f, -1.8737f), tuple(6, -0.8093f, 0.2458f), tuple(6, -1.4289f, 1.4612f), tuple(6, -1.4289f, 0.6362f), tuple(6, 0.0f, 1.4612f), tuple(6, -0.7145f, 1.8737f), tuple(6, 0.7145f, 0.2237f), tuple(6, 1.4289f, 0.6362f), tuple(6, 1.4289f, 1.4612f), tuple(6, 0.7145f, 1.8737f) }}; std::array, 19> bonds = {{ { 0, 1, 1 }, { 0, 4, 1 }, { 0, 5, 1 }, { 1, 2, 1 }, { 1, 7, 1 }, { 2, 3, 1 }, { 3, 4, 1 }, { 4, 13, 1 }, { 5, 6, 1 }, { 5, 8, 1 }, { 6, 7, 1 }, { 8, 10, 1 }, { 9, 10, 1 }, { 9, 12, 1 }, { 11, 12, 1 }, { 11, 16, 1 }, { 13, 14, 1 }, { 14, 15, 1 }, { 15, 16, 1 } }}; add_atoms(molecule, atoms); add_bonds(molecule, bonds); molecules[i] = molecule; ++i; } { auto molecule = new sketcherMinimizerMolecule(); std::array, 42> atoms = {{ tuple(6, -2.1434f, 2.0625f), tuple(6, -1.4289f, 1.65f), tuple(6, -0.7145f, 2.0625f), tuple(6, -0.7145f, 2.8875f), tuple(7, -1.4289f, 3.3f), tuple(7, -2.1434f, 2.8875f), tuple(6, 0.7145f, 2.0625f), tuple(6, 0.7145f, 2.8875f), tuple(6, 0.0f, 3.3f), tuple(6, 1.4289f, 1.65f), tuple(6, 2.1434f, 2.0625f), tuple(7, 2.1434f, 2.8875f), tuple(7, 1.4289f, 3.3f), tuple(6, -2.8579f, 1.65f), tuple(6, -2.8579f, 0.825f), tuple(7, -3.5724f, 0.4125f), tuple(7, -3.5724f, -0.4125f), tuple(6, -2.1434f, 0.4125f), tuple(6, -2.1434f, -0.4125f), tuple(6, -2.8579f, -0.825f), tuple(7, 2.8579f, 1.65f), tuple(6, 2.8579f, 0.825f), tuple(6, -2.8579f, -1.65f), tuple(6, -2.1434f, -2.0625f), tuple(6, -1.4289f, -1.65f), tuple(6, -0.7145f, -2.0625f), tuple(6, -0.7145f, -2.8875f), tuple(7, -1.4289f, -3.3f), tuple(7, -2.1434f, -2.8875f), tuple(6, 2.1434f, 0.4125f), tuple(6, 2.1434f, -0.4125f), tuple(6, 2.8579f, -0.825f), tuple(7, 3.5724f, -0.4125f), tuple(7, 3.5724f, 0.4125f), tuple(6, 2.8579f, -1.65f), tuple(6, 2.1434f, -2.0625f), tuple(6, 0.0f, -3.3f), tuple(6, 0.7145f, -2.8875f), tuple(6, 0.7145f, -2.0625f), tuple(6, 1.4289f, -1.65f), tuple(7, 2.1434f, -2.8875f), tuple(7, 1.4289f, -3.3f) }}; std::array, 48> bonds = {{ { 0, 1, 1 }, { 0, 5, 1 }, { 0, 13, 1 }, { 1, 2, 1 }, { 2, 3, 1 }, { 3, 4, 1 }, { 3, 8, 1 }, { 4, 5, 1 }, { 6, 7, 1 }, { 6, 9, 1 }, { 7, 8, 1 }, { 7, 12, 1 }, { 9, 10, 1 }, { 10, 11, 1 }, { 10, 20, 1 }, { 11, 12, 1 }, { 13, 14, 1 }, { 14, 15, 1 }, { 14, 17, 1 }, { 15, 16, 1 }, { 16, 19, 1 }, { 17, 18, 1 }, { 18, 19, 1 }, { 19, 22, 1 }, { 20, 21, 1 }, { 21, 29, 1 }, { 21, 33, 1 }, { 22, 23, 1 }, { 23, 24, 1 }, { 23, 28, 1 }, { 24, 25, 1 }, { 25, 26, 1 }, { 26, 27, 1 }, { 26, 36, 1 }, { 27, 28, 1 }, { 29, 30, 1 }, { 30, 31, 1 }, { 31, 32, 1 }, { 31, 34, 1 }, { 32, 33, 1 }, { 34, 35, 1 }, { 35, 39, 1 }, { 35, 40, 1 }, { 36, 37, 1 }, { 37, 38, 1 }, { 37, 41, 1 }, { 38, 39, 1 }, { 40, 41, 1 } }}; add_atoms(molecule, atoms); add_bonds(molecule, bonds); molecules[i] = molecule; ++i; } { auto molecule = new sketcherMinimizerMolecule(); std::array, 20> atoms = {{ tuple(6, 2.0625f, -0.1207f), tuple(6, 1.6494f, 0.5935f), tuple(6, 1.6506f, -0.8355f), tuple(6, 1.6885f, -0.2179f), tuple(6, 1.3787f, 0.3177f), tuple(6, 0.8256f, -0.8361f), tuple(8, 0.001f, -1.384f), tuple(6, -0.8244f, -0.8374f), tuple(6, -1.6494f, -0.838f), tuple(6, -2.0625f, -0.1239f), tuple(6, -1.6506f, 0.5909f), tuple(6, -0.4125f, -0.1226f), tuple(6, -0.8256f, 0.5915f), tuple(6, -0.4136f, 1.3063f), tuple(6, 0.4114f, 1.307f), tuple(6, 0.8244f, 0.5928f), tuple(6, 0.4125f, -0.122f), tuple(7, 1.3363f, 1.384f), tuple(6, 1.8229f, 0.5936f), tuple(6, 1.3375f, -0.1975f) }}; std::array, 25> bonds = {{ { 0, 1, 1 }, { 0, 2, 1 }, { 1, 15, 1 }, { 2, 3, 1 }, { 2, 5, 1 }, { 3, 4, 1 }, { 4, 15, 1 }, { 5, 6, 1 }, { 5, 16, 1 }, { 6, 7, 1 }, { 7, 8, 2 }, { 7, 11, 1 }, { 8, 9, 1 }, { 9, 10, 2 }, { 10, 12, 1 }, { 11, 12, 2 }, { 11, 16, 1 }, { 12, 13, 1 }, { 13, 14, 1 }, { 14, 15, 1 }, { 14, 17, 1 }, { 15, 16, 1 }, { 16, 19, 1 }, { 17, 18, 1 }, { 18, 19, 1 } }}; add_atoms(molecule, atoms); add_bonds(molecule, bonds); molecules[i] = molecule; ++i; } { auto molecule = new sketcherMinimizerMolecule(); std::array, 18> atoms = {{ tuple(6, 2.0625f, -0.1207f), tuple(6, 1.6494f, 0.5935f), tuple(6, 1.6506f, -0.8355f), tuple(6, 0.8256f, -0.8361f), tuple(8, 0.001f, -1.384f), tuple(6, -0.8244f, -0.8374f), tuple(6, -1.6494f, -0.838f), tuple(6, -2.0625f, -0.1239f), tuple(6, -1.6506f, 0.5909f), tuple(6, -0.4125f, -0.1226f), tuple(6, -0.8256f, 0.5915f), tuple(6, -0.4136f, 1.3063f), tuple(6, 0.4114f, 1.307f), tuple(6, 0.8244f, 0.5928f), tuple(6, 0.4125f, -0.122f), tuple(7, 1.3363f, 1.384f), tuple(6, 1.8229f, 0.5936f), tuple(6, 1.3375f, -0.1975f) }}; std::array, 22> bonds = {{ { 0, 1, 1 }, { 0, 2, 1 }, { 1, 13, 1 }, { 2, 3, 1 }, { 3, 4, 1 }, { 3, 14, 1 }, { 4, 5, 1 }, { 5, 6, 2 }, { 5, 9, 1 }, { 6, 7, 1 }, { 7, 8, 2 }, { 8, 10, 1 }, { 9, 10, 2 }, { 9, 14, 1 }, { 10, 11, 1 }, { 11, 12, 1 }, { 12, 13, 1 }, { 12, 15, 1 }, { 13, 14, 1 }, { 14, 17, 1 }, { 15, 16, 1 }, { 16, 17, 1 } }}; add_atoms(molecule, atoms); add_bonds(molecule, bonds); molecules[i] = molecule; ++i; } { auto molecule = new sketcherMinimizerMolecule(); std::array, 21> atoms = {{ tuple(6, -1.4289f, -1.4438f), tuple(6, -1.4289f, -2.2687f), tuple(6, -0.7145f, -2.6812f), tuple(6, 0.0f, -2.2687f), tuple(6, 0.0f, -1.4438f), tuple(6, -0.7145f, -1.0312f), tuple(6, 0.7145f, -2.6812f), tuple(6, 1.4289f, -2.2687f), tuple(6, 1.4289f, -1.4438f), tuple(6, 0.7145f, -1.0312f), tuple(6, 0.7145f, -0.2062f), tuple(6, -0.7145f, -0.2062f), tuple(6, -0.7145f, 1.4438f), tuple(6, -1.4289f, 1.0312f), tuple(6, -1.4289f, 0.2062f), tuple(6, 1.4289f, 0.2062f), tuple(6, 1.4289f, 1.0312f), tuple(6, 0.7145f, 1.4438f), tuple(6, 0.7145f, 2.2687f), tuple(6, 0.0f, 2.6812f), tuple(6, -0.7145f, 2.2687f) }}; std::array, 22> bonds = {{ { 0, 1, 1 }, { 0, 5, 1 }, { 1, 2, 1 }, { 2, 3, 1 }, { 3, 6, 1 }, { 4, 5, 1 }, { 4, 9, 1 }, { 5, 11, 1 }, { 6, 7, 1 }, { 7, 8, 1 }, { 8, 9, 1 }, { 9, 10, 1 }, { 10, 15, 1 }, { 11, 14, 1 }, { 12, 13, 1 }, { 12, 20, 1 }, { 13, 14, 1 }, { 15, 16, 1 }, { 16, 17, 1 }, { 17, 18, 1 }, { 18, 19, 1 }, { 19, 20, 1 } }}; add_atoms(molecule, atoms); add_bonds(molecule, bonds); molecules[i] = molecule; ++i; } { auto molecule = new sketcherMinimizerMolecule(); std::array, 25> atoms = {{ tuple(6, 1.7862f, -0.825f), tuple(6, 1.7862f, -1.65f), tuple(6, 2.5006f, -2.0625f), tuple(6, 3.2151f, -1.65f), tuple(6, 3.2151f, -0.825f), tuple(6, 2.5006f, -0.4125f), tuple(6, 1.0717f, -2.0625f), tuple(6, 0.3572f, -1.65f), tuple(6, -0.3572f, -2.0625f), tuple(6, -1.0717f, -1.65f), tuple(6, -1.7862f, -2.0625f), tuple(6, -2.5006f, -1.65f), tuple(6, -2.5006f, -0.825f), tuple(6, -3.2151f, -1.2375f), tuple(6, -1.7862f, -0.4125f), tuple(6, -1.7862f, 0.4125f), tuple(6, -1.0717f, 0.825f), tuple(6, -1.0717f, 1.65f), tuple(6, -0.3572f, 2.0625f), tuple(6, 0.3572f, 1.65f), tuple(6, 1.1817f, -0.3025f), tuple(6, 0.3572f, 0.825f), tuple(6, 1.1419f, 0.5701f), tuple(6, 1.6268f, 1.2375f), tuple(6, 1.1419f, 1.9049f) }}; std::array, 28> bonds = {{ { 0, 1, 1 }, { 0, 5, 1 }, { 0, 20, 1 }, { 1, 2, 1 }, { 1, 6, 1 }, { 2, 3, 1 }, { 3, 4, 1 }, { 4, 5, 1 }, { 6, 7, 1 }, { 7, 8, 1 }, { 8, 9, 1 }, { 9, 10, 1 }, { 10, 11, 1 }, { 11, 12, 1 }, { 11, 13, 1 }, { 12, 13, 1 }, { 12, 14, 1 }, { 14, 15, 1 }, { 15, 16, 1 }, { 16, 17, 1 }, { 17, 18, 1 }, { 18, 19, 1 }, { 19, 21, 1 }, { 19, 24, 1 }, { 20, 22, 1 }, { 21, 22, 1 }, { 22, 23, 1 }, { 23, 24, 1 } }}; add_atoms(molecule, atoms); add_bonds(molecule, bonds); molecules[i] = molecule; ++i; } { auto molecule = new sketcherMinimizerMolecule(); std::array, 20> atoms = {{ tuple(6, -1.2612f, -1.5367f), tuple(6, -1.5967f, -0.783f), tuple(6, -0.9836f, -0.2309f), tuple(7, -0.4407f, -1.4504f), tuple(6, -0.2691f, -0.6434f), tuple(6, 0.4453f, -0.2309f), tuple(6, 0.4453f, 0.5941f), tuple(6, 1.089f, 1.1102f), tuple(6, -0.4245f, 1.9077f), tuple(7, -1.7682f, 0.849f), tuple(6, -0.9836f, 0.5941f), tuple(6, -0.2691f, 1.0066f), tuple(6, -2.2532f, 0.1816f), tuple(6, -1.7682f, -0.4859f), tuple(6, 1.8937f, 0.9285f), tuple(6, 2.2532f, 0.1859f), tuple(8, 1.8965f, -0.558f), tuple(6, 1.0924f, -0.7427f), tuple(6, 0.995f, -1.5619f), tuple(6, 0.246f, -1.9077f) }}; std::array, 25> bonds = {{ { 0, 1, 1 }, { 0, 3, 1 }, { 1, 2, 1 }, { 2, 4, 1 }, { 2, 10, 1 }, { 2, 13, 1 }, { 3, 4, 1 }, { 3, 19, 1 }, { 4, 5, 1 }, { 5, 6, 1 }, { 5, 17, 1 }, { 6, 7, 1 }, { 6, 11, 1 }, { 7, 8, 1 }, { 7, 14, 2 }, { 8, 9, 1 }, { 9, 10, 1 }, { 9, 12, 1 }, { 10, 11, 1 }, { 12, 13, 1 }, { 14, 15, 1 }, { 15, 16, 1 }, { 16, 17, 1 }, { 17, 18, 1 }, { 18, 19, 1 } }}; add_atoms(molecule, atoms); add_bonds(molecule, bonds); molecules[i] = molecule; ++i; } { auto molecule = new sketcherMinimizerMolecule(); std::array, 36> atoms = {{ tuple(6, -3.3413f, -1.4289f), tuple(6, -2.5162f, -1.4289f), tuple(6, -2.1038f, -0.7145f), tuple(6, -2.5162f, 0.0f), tuple(6, -3.3413f, 0.0f), tuple(6, -3.7538f, -0.7145f), tuple(6, -2.1038f, 0.7145f), tuple(6, -2.5162f, 1.4289f), tuple(6, -3.3413f, 1.4289f), tuple(6, -3.7538f, 0.7145f), tuple(6, -1.6912f, -1.4289f), tuple(6, -0.8662f, -1.4289f), tuple(6, -1.6912f, 1.4289f), tuple(6, -0.8662f, 1.4289f), tuple(6, -0.4537f, 0.7145f), tuple(6, 0.3713f, 0.7145f), tuple(6, 0.7838f, 1.4289f), tuple(6, 0.3713f, 2.1434f), tuple(6, -0.4537f, 2.1434f), tuple(6, -0.4537f, -2.1434f), tuple(6, 0.3713f, -2.1434f), tuple(6, 0.7838f, -1.4289f), tuple(6, 0.3713f, -0.7145f), tuple(6, -0.4537f, -0.7145f), tuple(6, 1.6912f, -1.4289f), tuple(6, 2.1038f, -0.7145f), tuple(6, 2.5162f, -1.4289f), tuple(6, 3.3413f, -1.4289f), tuple(6, 3.7538f, -0.7145f), tuple(6, 3.3413f, 0.0f), tuple(6, 2.5162f, 0.0f), tuple(6, 3.7538f, 0.7145f), tuple(6, 3.3413f, 1.4289f), tuple(6, 2.5162f, 1.4289f), tuple(6, 2.1038f, 0.7145f), tuple(6, 2.1038f, 2.1434f) }}; std::array, 42> bonds = {{ { 0, 1, 1 }, { 0, 5, 1 }, { 1, 2, 1 }, { 2, 3, 1 }, { 2, 10, 1 }, { 3, 4, 1 }, { 3, 6, 1 }, { 4, 5, 1 }, { 4, 9, 1 }, { 6, 7, 1 }, { 6, 12, 1 }, { 7, 8, 1 }, { 8, 9, 1 }, { 10, 11, 1 }, { 11, 19, 1 }, { 11, 23, 1 }, { 12, 13, 1 }, { 13, 14, 1 }, { 13, 18, 1 }, { 14, 15, 1 }, { 15, 16, 1 }, { 16, 17, 1 }, { 17, 18, 1 }, { 17, 35, 1 }, { 19, 20, 1 }, { 20, 21, 1 }, { 21, 22, 1 }, { 21, 24, 1 }, { 22, 23, 1 }, { 24, 25, 1 }, { 25, 26, 1 }, { 25, 30, 1 }, { 26, 27, 1 }, { 27, 28, 1 }, { 28, 29, 1 }, { 29, 30, 1 }, { 29, 31, 1 }, { 30, 34, 1 }, { 31, 32, 1 }, { 32, 33, 1 }, { 33, 34, 1 }, { 33, 35, 1 } }}; add_atoms(molecule, atoms); add_bonds(molecule, bonds); molecules[i] = molecule; ++i; } { auto molecule = new sketcherMinimizerMolecule(); std::array, 50> atoms = {{ tuple(6, -3.1562f, 1.7691f), tuple(6, -2.4417f, 2.1816f), tuple(6, -2.4417f, 3.0066f), tuple(8, -1.7272f, 3.4191f), tuple(6, -3.1562f, 3.4191f), tuple(6, -3.8707f, 3.0066f), tuple(6, -3.8707f, 2.1816f), tuple(6, -4.5851f, 1.7691f), tuple(6, -4.5851f, 0.9441f), tuple(6, -3.8707f, 0.5316f), tuple(7, -3.1562f, 0.9441f), tuple(6, -2.4417f, 0.5316f), tuple(6, -1.7272f, 0.9441f), tuple(7, -1.0128f, 0.5316f), tuple(6, -0.2983f, 0.9441f), tuple(6, 0.4162f, 0.5316f), tuple(7, 1.1306f, 0.9441f), tuple(6, 1.8451f, 0.5316f), tuple(6, 2.5596f, 0.9441f), tuple(7, 3.2741f, 0.5316f), tuple(6, 1.9073f, -0.2911f), tuple(6, 2.6508f, -0.6486f), tuple(6, 2.6139f, -1.4755f), tuple(6, 1.9166f, -1.9164f), tuple(6, 1.1929f, -1.5203f), tuple(6, 1.1881f, -0.6954f), tuple(6, -0.2983f, 1.7691f), tuple(6, 0.4162f, 2.1816f), tuple(6, -1.0128f, 2.1816f), tuple(6, -1.0128f, 3.0066f), tuple(6, -0.2983f, 3.4191f), tuple(6, 0.4162f, 3.0066f), tuple(8, 1.1306f, 3.4191f), tuple(6, 1.8451f, 3.0066f), tuple(6, 1.8451f, 2.1816f), tuple(6, 2.5596f, 1.7691f), tuple(6, 2.5596f, 3.4191f), tuple(6, 3.2741f, 3.0066f), tuple(6, 3.2741f, 2.1816f), tuple(6, 3.9885f, 1.7691f), tuple(6, 3.9885f, 0.9441f), tuple(6, 4.567f, 0.3237f), tuple(7, 4.1338f, -0.3784f), tuple(6, 4.4472f, -1.1416f), tuple(6, 4.0513f, -1.8654f), tuple(6, 3.2396f, -2.0133f), tuple(6, 4.5851f, -2.4944f), tuple(6, 4.3073f, -3.2712f), tuple(6, 3.4957f, -3.4191f), tuple(6, 2.9618f, -2.7901f) }}; std::array, 57> bonds = {{ { 0, 1, 2 }, { 0, 6, 1 }, { 1, 2, 1 }, { 2, 3, 1 }, { 2, 4, 2 }, { 3, 29, 1 }, { 4, 5, 1 }, { 5, 6, 2 }, { 6, 7, 1 }, { 7, 8, 1 }, { 8, 9, 1 }, { 9, 10, 1 }, { 10, 11, 1 }, { 11, 12, 1 }, { 12, 13, 1 }, { 13, 14, 1 }, { 14, 15, 1 }, { 14, 26, 1 }, { 15, 16, 1 }, { 16, 17, 1 }, { 17, 18, 1 }, { 17, 20, 1 }, { 18, 19, 1 }, { 19, 40, 1 }, { 20, 21, 2 }, { 20, 25, 1 }, { 21, 22, 1 }, { 22, 23, 2 }, { 22, 45, 1 }, { 23, 24, 1 }, { 24, 25, 2 }, { 26, 27, 2 }, { 26, 28, 1 }, { 27, 31, 1 }, { 28, 29, 2 }, { 29, 30, 1 }, { 30, 31, 2 }, { 31, 32, 1 }, { 32, 33, 1 }, { 33, 34, 2 }, { 33, 36, 1 }, { 34, 35, 1 }, { 35, 38, 2 }, { 36, 37, 2 }, { 37, 38, 1 }, { 38, 39, 1 }, { 39, 40, 1 }, { 40, 41, 1 }, { 41, 42, 1 }, { 42, 43, 1 }, { 43, 44, 1 }, { 44, 45, 2 }, { 44, 46, 1 }, { 45, 49, 1 }, { 46, 47, 2 }, { 47, 48, 1 }, { 48, 49, 2 } }}; add_atoms(molecule, atoms); add_bonds(molecule, bonds); molecules[i] = molecule; ++i; } { auto molecule = new sketcherMinimizerMolecule(); std::array, 23> atoms = {{ tuple(6, -0.442f, -1.5973f), tuple(6, 0.418f, -1.6008f), tuple(6, 1.1001f, -2.0649f), tuple(6, 1.7523f, -1.5596f), tuple(6, 1.4732f, -0.7832f), tuple(7, 0.6486f, -0.8087f), tuple(6, 1.9373f, -0.1011f), tuple(6, 1.6048f, 0.6539f), tuple(6, 2.0202f, 1.3667f), tuple(6, 1.4706f, 1.982f), tuple(6, 0.7156f, 1.6495f), tuple(7, 0.7985f, 0.8287f), tuple(6, 0.0028f, 2.0649f), tuple(6, -0.7133f, 1.6553f), tuple(6, -1.4657f, 1.9939f), tuple(6, -2.0202f, 1.383f), tuple(6, -1.6105f, 0.6669f), tuple(7, -0.8029f, 0.8351f), tuple(6, -1.9491f, -0.0855f), tuple(6, -1.4906f, -0.7713f), tuple(7, -0.6662f, -0.8034f), tuple(6, -1.7758f, -1.5454f), tuple(6, -1.1278f, -2.0559f) }}; std::array, 27> bonds = {{ { 0, 1, 1 }, { 0, 20, 1 }, { 0, 22, 1 }, { 1, 2, 1 }, { 1, 5, 1 }, { 2, 3, 1 }, { 3, 4, 1 }, { 4, 5, 2 }, { 4, 6, 1 }, { 6, 7, 2 }, { 7, 8, 1 }, { 7, 11, 1 }, { 8, 9, 1 }, { 9, 10, 1 }, { 10, 11, 2 }, { 10, 12, 1 }, { 12, 13, 2 }, { 13, 14, 1 }, { 13, 17, 1 }, { 14, 15, 1 }, { 15, 16, 1 }, { 16, 17, 2 }, { 16, 18, 1 }, { 18, 19, 2 }, { 19, 20, 1 }, { 19, 21, 1 }, { 21, 22, 1 } }}; add_atoms(molecule, atoms); add_bonds(molecule, bonds); molecules[i] = molecule; ++i; } { auto molecule = new sketcherMinimizerMolecule(); std::array, 17> atoms = {{ tuple(6, 0.0186f, -1.4569f), tuple(6, 0.0952f, -0.6355f), tuple(6, -0.5779f, -0.1584f), tuple(6, -1.3276f, -0.5028f), tuple(7, -1.4042f, -1.3242f), tuple(7, -0.7311f, -1.8013f), tuple(8, -1.8868f, 0.1038f), tuple(6, -1.6411f, 0.8914f), tuple(6, -0.8362f, 1.0723f), tuple(6, -0.4321f, 1.7916f), tuple(6, 0.3929f, 1.8013f), tuple(7, 0.8137f, 1.0917f), tuple(6, 1.6227f, 0.9296f), tuple(6, 1.8868f, 0.1481f), tuple(7, 1.342f, -0.4715f), tuple(6, 1.4378f, -1.2909f), tuple(6, 0.7761f, -1.7836f) }}; std::array, 18> bonds = {{ { 0, 1, 2 }, { 0, 5, 1 }, { 0, 16, 1 }, { 1, 2, 1 }, { 2, 3, 2 }, { 3, 4, 1 }, { 3, 6, 1 }, { 4, 5, 2 }, { 6, 7, 1 }, { 7, 8, 1 }, { 8, 9, 1 }, { 9, 10, 1 }, { 10, 11, 1 }, { 11, 12, 1 }, { 12, 13, 1 }, { 13, 14, 1 }, { 14, 15, 1 }, { 15, 16, 1 } }}; add_atoms(molecule, atoms); add_bonds(molecule, bonds); molecules[i] = molecule; ++i; } { auto molecule = new sketcherMinimizerMolecule(); std::array, 22> atoms = {{ tuple(6, 1.9567f, 1.6008f), tuple(7, 1.936f, 0.6674f), tuple(6, 1.1514f, 0.4125f), tuple(6, 1.1514f, -0.4125f), tuple(7, 2.421f, 0.0f), tuple(6, 1.936f, -0.6674f), tuple(7, 1.1867f, 2.0133f), tuple(6, 0.4369f, 1.65f), tuple(7, 0.4369f, 0.825f), tuple(7, -0.2775f, 2.0625f), tuple(6, -0.992f, 1.65f), tuple(6, -0.992f, 0.825f), tuple(6, -1.7065f, 0.4125f), tuple(6, -2.421f, 0.825f), tuple(6, -2.4209f, 1.65f), tuple(6, -1.7065f, 2.0625f), tuple(7, -1.7065f, -0.4125f), tuple(6, -0.992f, -0.825f), tuple(6, -0.992f, -1.65f), tuple(6, -0.2775f, -2.0625f), tuple(6, 0.4369f, -1.65f), tuple(6, 0.4369f, -0.825f) }}; std::array, 25> bonds = {{ { 0, 1, 1 }, { 0, 6, 2 }, { 1, 2, 1 }, { 1, 4, 1 }, { 2, 3, 2 }, { 2, 8, 1 }, { 3, 5, 1 }, { 3, 21, 1 }, { 4, 5, 2 }, { 6, 7, 1 }, { 7, 8, 2 }, { 7, 9, 1 }, { 9, 10, 1 }, { 10, 11, 2 }, { 10, 15, 1 }, { 11, 12, 1 }, { 12, 13, 2 }, { 12, 16, 1 }, { 13, 14, 1 }, { 14, 15, 2 }, { 16, 17, 1 }, { 17, 18, 1 }, { 18, 19, 1 }, { 19, 20, 1 }, { 20, 21, 1 } }}; add_atoms(molecule, atoms); add_bonds(molecule, bonds); molecules[i] = molecule; ++i; } { auto molecule = new sketcherMinimizerMolecule(); std::array, 18> atoms = {{ tuple(6, 0.3572f, 2.0625f), tuple(6, 1.0717f, 1.65f), tuple(7, -0.3572f, 1.65f), tuple(6, -1.0717f, 2.0625f), tuple(6, -1.7862f, 1.65f), tuple(7, -1.7862f, 0.825f), tuple(6, -1.0717f, 0.4125f), tuple(6, -1.0717f, -0.4125f), tuple(6, -0.3572f, -0.825f), tuple(6, -0.3572f, -1.65f), tuple(6, 0.3572f, -2.0625f), tuple(8, 1.0717f, -1.65f), tuple(6, 1.0717f, -0.825f), tuple(7, 1.7862f, -0.4125f), tuple(7, 1.7862f, 0.4125f), tuple(6, 1.0717f, 0.825f), tuple(6, 0.3572f, -0.4125f), tuple(6, 0.3572f, 0.4125f) }}; std::array, 19> bonds = {{ { 0, 1, 1 }, { 0, 2, 1 }, { 1, 15, 1 }, { 2, 3, 1 }, { 3, 4, 1 }, { 4, 5, 1 }, { 5, 6, 1 }, { 6, 7, 1 }, { 7, 8, 1 }, { 8, 9, 1 }, { 9, 10, 1 }, { 10, 11, 1 }, { 11, 12, 1 }, { 12, 13, 2 }, { 12, 16, 1 }, { 13, 14, 1 }, { 14, 15, 2 }, { 15, 17, 1 }, { 16, 17, 2 } }}; add_atoms(molecule, atoms); add_bonds(molecule, bonds); molecules[i] = molecule; ++i; } { auto molecule = new sketcherMinimizerMolecule(); std::array, 17> atoms = {{ tuple(6, 1.0807f, -0.8666f), tuple(6, 1.8877f, -0.6951f), tuple(6, 2.1426f, 0.0895f), tuple(6, 1.5906f, 0.7026f), tuple(6, 0.9321f, 0.8748f), tuple(8, 0.4263f, 0.4193f), tuple(6, 0.7836f, 0.5311f), tuple(6, 0.1162f, 1.016f), tuple(6, 0.5287f, -0.2535f), tuple(6, -0.2963f, -0.2535f), tuple(6, -0.5513f, 0.5311f), tuple(6, -0.7508f, -0.9421f), tuple(6, -1.5725f, -1.016f), tuple(6, -2.1426f, -0.4197f), tuple(6, -1.0736f, -0.4019f), tuple(6, -2.0319f, 0.3978f), tuple(6, -1.3237f, 0.821f) }}; std::array, 21> bonds = {{ { 0, 1, 1 }, { 0, 8, 1 }, { 1, 2, 1 }, { 2, 3, 1 }, { 3, 4, 1 }, { 3, 6, 1 }, { 4, 5, 1 }, { 5, 8, 1 }, { 6, 7, 1 }, { 6, 8, 1 }, { 7, 10, 1 }, { 8, 9, 1 }, { 9, 10, 1 }, { 9, 11, 1 }, { 10, 14, 1 }, { 10, 16, 1 }, { 11, 12, 1 }, { 12, 13, 1 }, { 13, 14, 1 }, { 13, 15, 1 }, { 15, 16, 1 } }}; add_atoms(molecule, atoms); add_bonds(molecule, bonds); molecules[i] = molecule; ++i; } { auto molecule = new sketcherMinimizerMolecule(); std::array, 15> atoms = {{ tuple(6, -2.0637f, 0.6406f), tuple(6, -1.3492f, 1.0531f), tuple(6, -2.0637f, -0.1844f), tuple(6, -0.8306f, 1.0366f), tuple(6, -1.3492f, -0.5969f), tuple(6, -0.15f, -1.0531f), tuple(6, -0.6348f, -0.1844f), tuple(6, 0.0797f, -0.5969f), tuple(7, -0.6348f, 0.6406f), tuple(6, 0.0797f, 1.0531f), tuple(6, 0.7942f, 0.6406f), tuple(7, 1.5788f, 0.8955f), tuple(6, 2.0637f, 0.2281f), tuple(6, 1.5788f, -0.4393f), tuple(6, 0.7942f, -0.1844f) }}; std::array, 19> bonds = {{ { 0, 1, 1 }, { 0, 2, 1 }, { 1, 8, 1 }, { 2, 3, 1 }, { 2, 4, 1 }, { 3, 9, 1 }, { 4, 5, 1 }, { 4, 6, 1 }, { 5, 14, 1 }, { 6, 7, 1 }, { 6, 8, 1 }, { 7, 14, 1 }, { 8, 9, 1 }, { 9, 10, 1 }, { 10, 11, 1 }, { 10, 14, 1 }, { 11, 12, 1 }, { 12, 13, 1 }, { 13, 14, 1 } }}; add_atoms(molecule, atoms); add_bonds(molecule, bonds); molecules[i] = molecule; ++i; } { auto molecule = new sketcherMinimizerMolecule(); std::array, 16> atoms = {{ tuple(6, 1.6245f, -0.1243f), tuple(6, 1.6245f, -0.9493f), tuple(6, 0.91f, -1.3618f), tuple(6, 0.1955f, -0.9493f), tuple(6, -0.3947f, -1.5257f), tuple(6, -1.212f, -1.4132f), tuple(6, -1.6245f, -0.6987f), tuple(8, -0.9301f, -0.9617f), tuple(8, -0.222f, -0.7382f), tuple(8, -1.3133f, 0.0653f), tuple(6, -0.5189f, 0.2882f), tuple(8, -0.5189f, 1.1132f), tuple(6, 0.1955f, 1.5257f), tuple(6, 0.91f, 1.1132f), tuple(6, 0.91f, 0.2882f), tuple(6, 0.1955f, -0.1243f) }}; std::array, 19> bonds = {{ { 0, 1, 1 }, { 0, 14, 1 }, { 1, 2, 1 }, { 2, 3, 1 }, { 3, 4, 1 }, { 3, 15, 1 }, { 4, 5, 1 }, { 5, 6, 1 }, { 6, 7, 1 }, { 6, 9, 1 }, { 7, 8, 1 }, { 8, 15, 1 }, { 9, 10, 1 }, { 10, 11, 1 }, { 10, 15, 1 }, { 11, 12, 1 }, { 12, 13, 1 }, { 13, 14, 1 }, { 14, 15, 1 } }}; add_atoms(molecule, atoms); add_bonds(molecule, bonds); molecules[i] = molecule; ++i; } { auto molecule = new sketcherMinimizerMolecule(); std::array, 11> atoms = {{ tuple(6, -0.4849f, 0.54f), tuple(6, 0.0f, 1.2074f), tuple(6, 0.7846f, 0.9525f), tuple(6, 0.7846f, 0.1275f), tuple(6, 0.0f, -0.1275f), tuple(6, 1.2695f, -0.54f), tuple(6, 0.7846f, -1.2074f), tuple(6, 0.0f, -0.9525f), tuple(6, -0.7846f, -1.2074f), tuple(6, -1.2695f, -0.54f), tuple(6, -0.7846f, 0.1275f) }}; std::array, 13> bonds = {{ { 0, 1, 1 }, { 0, 4, 1 }, { 1, 2, 1 }, { 2, 3, 1 }, { 3, 4, 1 }, { 3, 5, 1 }, { 4, 7, 1 }, { 4, 10, 1 }, { 5, 6, 2 }, { 6, 7, 1 }, { 7, 8, 1 }, { 8, 9, 1 }, { 9, 10, 1 } }}; add_atoms(molecule, atoms); add_bonds(molecule, bonds); molecules[i] = molecule; ++i; } { auto molecule = new sketcherMinimizerMolecule(); std::array, 20> atoms = {{ tuple(6, -2.1561f, 0.9057f), tuple(6, -1.9813f, 0.0995f), tuple(8, -1.2419f, -0.2665f), tuple(6, -1.6481f, -0.6327f), tuple(6, -1.6348f, 1.5451f), tuple(6, -0.8098f, 1.5361f), tuple(6, -0.3025f, 0.8856f), tuple(6, -0.4948f, 0.0833f), tuple(6, 0.2894f, 0.2623f), tuple(6, -0.8438f, -0.6414f), tuple(6, -0.4948f, -1.3661f), tuple(6, 0.2894f, -1.5451f), tuple(6, 0.9183f, -1.0436f), tuple(6, 0.9183f, -0.2392f), tuple(6, 1.6833f, -1.2922f), tuple(8, 2.1561f, -0.6414f), tuple(6, 1.6833f, 0.0093f), tuple(6, 1.8013f, 0.8259f), tuple(6, 1.0414f, 1.1469f), tuple(8, 0.5383f, 0.493f) }}; std::array, 24> bonds = {{ { 0, 1, 1 }, { 0, 4, 1 }, { 1, 2, 1 }, { 1, 3, 1 }, { 2, 7, 1 }, { 3, 9, 1 }, { 4, 5, 1 }, { 5, 6, 1 }, { 6, 7, 1 }, { 7, 8, 1 }, { 7, 9, 1 }, { 8, 13, 1 }, { 9, 10, 1 }, { 10, 11, 1 }, { 11, 12, 1 }, { 12, 13, 1 }, { 12, 14, 1 }, { 13, 16, 1 }, { 13, 19, 1 }, { 14, 15, 1 }, { 15, 16, 1 }, { 16, 17, 1 }, { 17, 18, 1 }, { 18, 19, 1 } }}; add_atoms(molecule, atoms); add_bonds(molecule, bonds); molecules[i] = molecule; ++i; } { auto molecule = new sketcherMinimizerMolecule(); std::array, 18> atoms = {{ tuple(6, -1.6174f, -1.3111f), tuple(6, -0.8131f, -1.4947f), tuple(6, -1.9753f, -0.5678f), tuple(6, -1.1903f, -1.2937f), tuple(6, -1.6174f, 0.1755f), tuple(6, -0.8131f, 0.3591f), tuple(6, -0.1681f, -0.1553f), tuple(6, 0.5464f, 0.2572f), tuple(6, 0.8884f, -0.2584f), tuple(8, 0.8884f, -0.8772f), tuple(6, 1.2609f, -0.1553f), tuple(6, 1.2609f, -0.9803f), tuple(6, 0.5464f, -1.3928f), tuple(6, -0.1681f, -0.9803f), tuple(6, 0.5464f, 1.0822f), tuple(6, 1.2609f, 1.4947f), tuple(6, 1.9753f, 1.0822f), tuple(6, 1.9753f, 0.2572f) }}; std::array, 22> bonds = {{ { 0, 1, 1 }, { 0, 2, 1 }, { 1, 13, 1 }, { 2, 3, 1 }, { 2, 4, 1 }, { 3, 13, 1 }, { 4, 5, 1 }, { 5, 6, 1 }, { 6, 7, 1 }, { 6, 13, 1 }, { 7, 8, 1 }, { 7, 10, 1 }, { 7, 14, 1 }, { 8, 9, 1 }, { 9, 12, 1 }, { 10, 11, 1 }, { 10, 17, 1 }, { 11, 12, 1 }, { 12, 13, 1 }, { 14, 15, 1 }, { 15, 16, 1 }, { 16, 17, 1 } }}; add_atoms(molecule, atoms); add_bonds(molecule, bonds); molecules[i] = molecule; ++i; } { auto molecule = new sketcherMinimizerMolecule(); std::array, 23> atoms = {{ tuple(6, -1.0717f, 2.2687f), tuple(6, -1.7862f, 1.8562f), tuple(6, -1.7862f, 1.0312f), tuple(6, -1.0717f, 0.6187f), tuple(6, -0.3572f, 1.0312f), tuple(6, -0.3572f, 1.8562f), tuple(8, 0.3572f, 1.4437f), tuple(6, 0.3572f, 0.6187f), tuple(6, 1.0717f, 1.0312f), tuple(6, 1.0717f, 1.8562f), tuple(6, 0.3572f, 2.2687f), tuple(8, -0.3572f, 0.2063f), tuple(6, -0.3572f, -0.6187f), tuple(6, 0.3572f, -1.0312f), tuple(6, 0.3572f, -1.8562f), tuple(6, -0.3572f, -2.2687f), tuple(6, -1.0717f, -1.8562f), tuple(6, -1.0717f, -1.0312f), tuple(6, 1.0717f, -2.2687f), tuple(6, 1.7862f, -1.8562f), tuple(6, 1.7862f, -1.0312f), tuple(6, 1.0717f, -0.6187f), tuple(8, 1.0717f, 0.2063f) }}; std::array, 28> bonds = {{ { 0, 1, 1 }, { 0, 5, 1 }, { 1, 2, 2 }, { 2, 3, 1 }, { 3, 4, 1 }, { 4, 5, 1 }, { 4, 6, 1 }, { 4, 7, 1 }, { 5, 6, 1 }, { 5, 10, 1 }, { 7, 8, 1 }, { 7, 11, 1 }, { 7, 22, 1 }, { 8, 9, 2 }, { 9, 10, 1 }, { 11, 12, 1 }, { 12, 13, 2 }, { 12, 17, 1 }, { 13, 14, 1 }, { 13, 21, 1 }, { 14, 15, 2 }, { 14, 18, 1 }, { 15, 16, 1 }, { 16, 17, 2 }, { 18, 19, 2 }, { 19, 20, 1 }, { 20, 21, 2 }, { 21, 22, 1 } }}; add_atoms(molecule, atoms); add_bonds(molecule, bonds); molecules[i] = molecule; ++i; } { auto molecule = new sketcherMinimizerMolecule(); std::array, 16> atoms = {{ tuple(6, -3.2502f, 0.0934f), tuple(6, -2.0131f, 0.8077f), tuple(6, -2.0131f, 2.2363f), tuple(6, -3.2502f, 2.9506f), tuple(8, -4.4874f, 2.2363f), tuple(7, -4.4874f, 0.8077f), tuple(6, -2.5429f, 4.18f), tuple(6, -2.5429f, -1.1515f), tuple(6, 1.5663f, 0.0934f), tuple(7, 2.8034f, 0.8077f), tuple(8, 2.8034f, 2.2363f), tuple(6, 1.5663f, 2.9506f), tuple(6, 0.3291f, 2.2363f), tuple(6, 0.3291f, 0.8077f), tuple(6, 0.8571f, 4.18f), tuple(6, 0.8571f, -1.1515f) }}; std::array, 18> bonds = {{ { 0, 1, 1 }, { 0, 7, 1 }, { 0, 5, 2 }, { 1, 2, 2 }, { 2, 3, 1 }, { 3, 4, 2 }, { 3, 6, 1 }, { 4, 5, 1 }, { 6, 14, 1 }, { 7, 15, 1 }, { 8, 9, 1 }, { 8, 15, 1 }, { 8, 13, 2 }, { 9, 10, 2 }, { 10, 11, 1 }, { 11, 12, 2 }, { 11, 14, 1 }, { 12, 13, 1 } }}; add_atoms(molecule, atoms); add_bonds(molecule, bonds); molecules[i] = molecule; ++i; } { auto molecule = new sketcherMinimizerMolecule(); std::array, 25> atoms = {{ tuple(6, 1.4521f, 1.4521f), tuple(6, 1.707f, 0.6674f), tuple(6, 0.6674f, 1.707f), tuple(7, -0.0f, 1.2221f), tuple(6, -0.6674f, 1.707f), tuple(6, -0.4125f, 2.4916f), tuple(6, 0.4125f, 2.4916f), tuple(6, -1.4521f, 1.4521f), tuple(6, -1.707f, 0.6674f), tuple(7, -1.2221f, 0.0f), tuple(6, -1.707f, -0.6674f), tuple(6, -2.4916f, -0.4125f), tuple(6, -2.4916f, 0.4125f), tuple(6, -1.4521f, -1.4521f), tuple(6, -0.6674f, -1.707f), tuple(7, -0.0f, -1.2221f), tuple(28, -0.0063f, 0.0208f), tuple(6, 0.6674f, -1.707f), tuple(6, 0.4125f, -2.4916f), tuple(6, -0.4125f, -2.4916f), tuple(6, 1.4521f, -1.4521f), tuple(6, 1.707f, -0.6674f), tuple(7, 1.2221f, 0.0f), tuple(6, 2.4916f, -0.4125f), tuple(6, 2.4916f, 0.4125f) }}; std::array, 32> bonds = {{ { 0, 1, 2 }, { 0, 2, 1 }, { 1, 22, 1 }, { 1, 24, 1 }, { 2, 3, 1 }, { 2, 6, 2 }, { 3, 4, 1 }, { 3, 16, 1 }, { 4, 5, 2 }, { 4, 7, 1 }, { 5, 6, 1 }, { 7, 8, 2 }, { 8, 9, 1 }, { 8, 12, 1 }, { 9, 10, 1 }, { 9, 16, 1 }, { 10, 11, 1 }, { 10, 13, 2 }, { 11, 12, 2 }, { 13, 14, 1 }, { 14, 15, 1 }, { 14, 19, 2 }, { 15, 16, 1 }, { 15, 17, 1 }, { 16, 22, 1 }, { 17, 18, 2 }, { 17, 20, 1 }, { 18, 19, 1 }, { 20, 21, 2 }, { 21, 22, 1 }, { 21, 23, 1 }, { 23, 24, 2 } }}; add_atoms(molecule, atoms); add_bonds(molecule, bonds); molecules[i] = molecule; ++i; } { auto molecule = new sketcherMinimizerMolecule(); std::array, 25> atoms = {{ tuple(6, 1.4521f, 1.4521f), tuple(6, 1.707f, 0.6674f), tuple(6, 0.6674f, 1.707f), tuple(7, -0.0f, 1.2221f), tuple(6, -0.6674f, 1.707f), tuple(6, -0.4125f, 2.4916f), tuple(6, 0.4125f, 2.4916f), tuple(6, -1.4521f, 1.4521f), tuple(6, -1.707f, 0.6674f), tuple(7, -1.2221f, 0.0f), tuple(6, -1.707f, -0.6674f), tuple(6, -2.4916f, -0.4125f), tuple(6, -2.4916f, 0.4125f), tuple(6, -1.4521f, -1.4521f), tuple(6, -0.6674f, -1.707f), tuple(7, -0.0f, -1.2221f), tuple(28, -0.0063f, 0.0208f), tuple(6, 0.6674f, -1.707f), tuple(6, 0.4125f, -2.4916f), tuple(6, -0.4125f, -2.4916f), tuple(6, 1.4521f, -1.4521f), tuple(6, 1.707f, -0.6674f), tuple(7, 1.2221f, 0.0f), tuple(6, 2.4916f, -0.4125f), tuple(6, 2.4916f, 0.4125f) }}; std::array, 30> bonds = {{ { 0, 1, 2 }, { 0, 2, 1 }, { 1, 22, 1 }, { 1, 24, 1 }, { 2, 3, 2 }, { 2, 6, 1 }, { 3, 4, 1 }, { 4, 5, 2 }, { 4, 7, 1 }, { 5, 6, 1 }, { 7, 8, 2 }, { 8, 9, 1 }, { 8, 12, 1 }, { 9, 10, 1 }, { 9, 16, 1 }, { 10, 11, 1 }, { 10, 13, 2 }, { 11, 12, 2 }, { 13, 14, 1 }, { 14, 15, 2 }, { 14, 19, 1 }, { 15, 17, 1 }, { 16, 22, 1 }, { 17, 18, 2 }, { 17, 20, 1 }, { 18, 19, 1 }, { 20, 21, 2 }, { 21, 22, 1 }, { 21, 23, 1 }, { 23, 24, 2 } }}; add_atoms(molecule, atoms); add_bonds(molecule, bonds); molecules[i] = molecule; ++i; } { auto molecule = new sketcherMinimizerMolecule(); std::array, 24> atoms = {{ tuple(6, 1.4521f, 1.4521f), tuple(6, 1.707f, 0.6674f), tuple(6, 0.6674f, 1.707f), tuple(7, -0.0f, 1.2221f), tuple(6, -0.6674f, 1.707f), tuple(6, -0.4125f, 2.4916f), tuple(6, 0.4125f, 2.4916f), tuple(6, -1.4521f, 1.4521f), tuple(6, -1.707f, 0.6674f), tuple(7, -1.2221f, 0.0f), tuple(6, -1.707f, -0.6674f), tuple(6, -2.4916f, -0.4125f), tuple(6, -2.4916f, 0.4125f), tuple(6, -1.4521f, -1.4521f), tuple(6, -0.6674f, -1.707f), tuple(7, -0.0f, -1.2221f), tuple(6, 0.6674f, -1.707f), tuple(6, 0.4125f, -2.4916f), tuple(6, -0.4125f, -2.4916f), tuple(6, 1.4521f, -1.4521f), tuple(6, 1.707f, -0.6674f), tuple(7, 1.2221f, 0.0f), tuple(6, 2.4916f, -0.4125f), tuple(6, 2.4916f, 0.4125f) }}; std::array, 28> bonds = {{ { 0, 1, 2 }, { 0, 2, 1 }, { 1, 21, 1 }, { 1, 23, 1 }, { 2, 3, 2 }, { 2, 6, 1 }, { 3, 4, 1 }, { 4, 5, 2 }, { 4, 7, 1 }, { 5, 6, 1 }, { 7, 8, 2 }, { 8, 9, 1 }, { 8, 12, 1 }, { 9, 10, 1 }, { 10, 11, 1 }, { 10, 13, 2 }, { 11, 12, 2 }, { 13, 14, 1 }, { 14, 15, 2 }, { 14, 18, 1 }, { 15, 16, 1 }, { 16, 17, 2 }, { 16, 19, 1 }, { 17, 18, 1 }, { 19, 20, 2 }, { 20, 21, 1 }, { 20, 22, 1 }, { 22, 23, 2 } }}; add_atoms(molecule, atoms); add_bonds(molecule, bonds); molecules[i] = molecule; ++i; } { auto molecule = new sketcherMinimizerMolecule(); std::array, 19> atoms = {{ tuple(7, 0.9191f, 1.4438f), tuple(7, 0.2046f, 1.0312f), tuple(7, 1.6336f, 1.0312f), tuple(6, 1.6336f, 0.2062f), tuple(6, 1.9388f, -0.4428f), tuple(6, 1.3888f, -0.9653f), tuple(6, 0.4813f, -0.5528f), tuple(6, 0.9191f, -0.2062f), tuple(6, 0.2046f, 0.2062f), tuple(6, 0.9191f, -1.0312f), tuple(6, 0.2046f, -1.4438f), tuple(6, -0.5098f, -1.0312f), tuple(6, -0.5098f, -0.2062f), tuple(6, -1.2243f, 0.2062f), tuple(6, -1.9388f, -0.2062f), tuple(6, -1.6632f, -0.7603f), tuple(6, -1.1274f, -1.0696f), tuple(7, -1.9388f, -1.0312f), tuple(7, -1.2243f, -1.4438f) }}; std::array, 23> bonds = {{ { 0, 1, 1 }, { 0, 2, 1 }, { 1, 8, 1 }, { 2, 3, 1 }, { 3, 4, 1 }, { 3, 7, 1 }, { 4, 5, 1 }, { 5, 6, 1 }, { 6, 8, 1 }, { 7, 8, 1 }, { 7, 9, 1 }, { 8, 12, 1 }, { 9, 10, 1 }, { 10, 11, 1 }, { 11, 12, 1 }, { 11, 16, 1 }, { 11, 18, 1 }, { 12, 13, 1 }, { 13, 14, 1 }, { 14, 15, 1 }, { 14, 17, 1 }, { 15, 16, 1 }, { 17, 18, 1 } }}; add_atoms(molecule, atoms); add_bonds(molecule, bonds); molecules[i] = molecule; ++i; } { auto molecule = new sketcherMinimizerMolecule(); std::array, 20> atoms = {{ tuple(6, 0.5773f, 0.9186f), tuple(8, 0.1357f, 0.2217f), tuple(6, -0.6743f, 0.3782f), tuple(6, -1.3016f, -0.1576f), tuple(6, -2.0296f, 0.2307f), tuple(6, -2.7298f, -0.2056f), tuple(8, -2.702f, -1.0302f), tuple(6, -1.9741f, -1.4184f), tuple(6, -1.2739f, -0.9821f), tuple(6, -0.612f, -1.4745f), tuple(6, 0.1857f, -1.264f), tuple(8, 0.5185f, -0.5091f), tuple(6, 1.3428f, -0.5431f), tuple(6, 2.0429f, -0.9794f), tuple(6, 2.7298f, -0.5224f), tuple(6, 2.5977f, 0.292f), tuple(7, 2.7176f, 1.1082f), tuple(7, 1.9784f, 1.4745f), tuple(6, 1.4016f, 0.8847f), tuple(6, 1.7843f, 0.1538f) }}; std::array, 22> bonds = {{ { 0, 1, 1 }, { 0, 18, 1 }, { 1, 2, 1 }, { 2, 3, 1 }, { 3, 4, 1 }, { 4, 5, 1 }, { 5, 6, 1 }, { 6, 7, 1 }, { 7, 8, 1 }, { 8, 9, 1 }, { 9, 10, 1 }, { 10, 11, 1 }, { 11, 12, 1 }, { 12, 13, 1 }, { 12, 19, 1 }, { 13, 14, 1 }, { 14, 15, 1 }, { 15, 16, 1 }, { 15, 19, 1 }, { 16, 17, 1 }, { 17, 18, 1 }, { 18, 19, 1 } }}; add_atoms(molecule, atoms); add_bonds(molecule, bonds); molecules[i] = molecule; ++i; } { auto molecule = new sketcherMinimizerMolecule(); std::array, 18> atoms = {{ tuple(6, 0.4011f, 1.0822f), tuple(6, 1.1156f, 1.4947f), tuple(6, 1.8301f, 1.0822f), tuple(6, 1.8301f, 0.2572f), tuple(6, 2.1206f, -0.3935f), tuple(8, 0.8556f, -0.476f), tuple(6, 1.1156f, -0.1553f), tuple(6, 1.1156f, -0.9803f), tuple(6, 0.4011f, -1.3928f), tuple(6, 0.4011f, 0.2572f), tuple(6, -0.3133f, -0.1553f), tuple(6, -0.3133f, -0.9803f), tuple(6, -0.9583f, 0.3591f), tuple(6, -1.7626f, 0.1755f), tuple(6, -2.1206f, -0.5678f), tuple(6, -1.0984f, -0.2544f), tuple(6, -1.7626f, -1.3111f), tuple(6, -0.9583f, -1.4947f) }}; std::array, 22> bonds = {{ { 0, 1, 1 }, { 0, 9, 1 }, { 1, 2, 1 }, { 2, 3, 1 }, { 3, 4, 1 }, { 3, 6, 1 }, { 4, 5, 1 }, { 5, 9, 1 }, { 6, 7, 1 }, { 6, 9, 1 }, { 7, 8, 1 }, { 8, 11, 1 }, { 9, 10, 1 }, { 10, 11, 1 }, { 10, 12, 1 }, { 11, 15, 1 }, { 11, 17, 1 }, { 12, 13, 1 }, { 13, 14, 1 }, { 14, 15, 1 }, { 14, 16, 1 }, { 16, 17, 1 } }}; add_atoms(molecule, atoms); add_bonds(molecule, bonds); molecules[i] = molecule; ++i; } { auto molecule = new sketcherMinimizerMolecule(); std::array, 18> atoms = {{ tuple(6, 0.5382f, 0.7033f), tuple(6, 1.1432f, 1.3633f), tuple(6, 1.7207f, 1.0608f), tuple(6, 1.5906f, 0.3553f), tuple(6, 2.1426f, -0.2578f), tuple(8, 1.8877f, -1.0424f), tuple(6, 1.0807f, -1.214f), tuple(6, 0.7836f, 0.1837f), tuple(6, 0.1162f, 0.6687f), tuple(6, 0.5287f, -0.6009f), tuple(6, -0.2963f, -0.6009f), tuple(6, -0.5513f, 0.1837f), tuple(6, -0.7508f, -1.2894f), tuple(6, -1.5725f, -1.3633f), tuple(6, -2.1426f, -0.767f), tuple(6, -1.0736f, -0.7492f), tuple(6, -2.0319f, 0.0505f), tuple(6, -1.3237f, 0.4736f) }}; std::array, 22> bonds = {{ { 0, 1, 1 }, { 0, 9, 1 }, { 1, 2, 1 }, { 2, 3, 1 }, { 3, 4, 1 }, { 3, 7, 1 }, { 4, 5, 1 }, { 5, 6, 1 }, { 6, 9, 1 }, { 7, 8, 1 }, { 7, 9, 1 }, { 8, 11, 1 }, { 9, 10, 1 }, { 10, 11, 1 }, { 10, 12, 1 }, { 11, 15, 1 }, { 11, 17, 1 }, { 12, 13, 1 }, { 13, 14, 1 }, { 14, 15, 1 }, { 14, 16, 1 }, { 16, 17, 1 } }}; add_atoms(molecule, atoms); add_bonds(molecule, bonds); molecules[i] = molecule; ++i; } { auto molecule = new sketcherMinimizerMolecule(); std::array, 18> atoms = {{ tuple(6, -0.825f, 2.0426f), tuple(7, -0.4125f, 1.3281f), tuple(6, 0.4125f, 1.3281f), tuple(6, 0.825f, 0.6137f), tuple(6, 0.4125f, -0.1008f), tuple(6, 0.825f, -0.8153f), tuple(6, 1.65f, 0.6137f), tuple(6, 2.0625f, -0.1008f), tuple(6, 1.65f, -0.8153f), tuple(6, -1.65f, 2.0426f), tuple(8, -2.0625f, 1.3281f), tuple(6, -1.65f, 0.6137f), tuple(6, -2.0625f, -0.1008f), tuple(6, -1.65f, -0.8153f), tuple(6, -1.7791f, -1.6301f), tuple(6, -1.0646f, -2.0426f), tuple(7, -0.4125f, -1.5297f), tuple(6, 0.4125f, -1.5297f) }}; std::array, 19> bonds = {{ { 0, 1, 1 }, { 0, 9, 1 }, { 1, 2, 1 }, { 2, 3, 1 }, { 3, 4, 2 }, { 3, 6, 1 }, { 4, 5, 1 }, { 5, 8, 2 }, { 5, 17, 1 }, { 6, 7, 2 }, { 7, 8, 1 }, { 9, 10, 1 }, { 10, 11, 1 }, { 11, 12, 1 }, { 12, 13, 2 }, { 13, 14, 1 }, { 14, 15, 1 }, { 15, 16, 1 }, { 16, 17, 1 } }}; add_atoms(molecule, atoms); add_bonds(molecule, bonds); molecules[i] = molecule; ++i; } { auto molecule = new sketcherMinimizerMolecule(); std::array, 18> atoms = {{ tuple(6, -1.1713f, 1.5474f), tuple(7, -0.7588f, 2.2618f), tuple(6, 0.0662f, 2.2618f), tuple(6, 0.4787f, 1.5474f), tuple(6, 0.0662f, 0.8329f), tuple(6, 0.5806f, 0.1879f), tuple(6, 1.2988f, 1.637f), tuple(6, 1.7713f, 0.9607f), tuple(6, 1.4049f, 0.2215f), tuple(6, -0.7588f, 0.8329f), tuple(8, -1.2732f, 0.1879f), tuple(6, -1.0896f, -0.6164f), tuple(6, -1.7713f, -1.0812f), tuple(6, -1.7096f, -1.9039f), tuple(6, -0.9663f, -2.2618f), tuple(6, -0.2847f, -1.7971f), tuple(7, -0.3463f, -0.9744f), tuple(6, 0.397f, -0.6164f) }}; std::array, 19> bonds = {{ { 0, 1, 1 }, { 0, 9, 1 }, { 1, 2, 1 }, { 2, 3, 1 }, { 3, 4, 2 }, { 3, 6, 1 }, { 4, 5, 1 }, { 5, 8, 2 }, { 5, 17, 1 }, { 6, 7, 2 }, { 7, 8, 1 }, { 9, 10, 1 }, { 10, 11, 1 }, { 11, 12, 1 }, { 12, 13, 2 }, { 13, 14, 1 }, { 14, 15, 1 }, { 15, 16, 1 }, { 16, 17, 1 } }}; add_atoms(molecule, atoms); add_bonds(molecule, bonds); molecules[i] = molecule; ++i; } { auto molecule = new sketcherMinimizerMolecule(); std::array, 23> atoms = {{ tuple(6, -0.3572f, -0.825f), tuple(6, -0.3572f, -1.65f), tuple(6, 0.3572f, -2.0625f), tuple(6, 1.0717f, -1.65f), tuple(6, 1.0717f, -0.825f), tuple(6, 0.3572f, -0.4125f), tuple(6, 0.3572f, 0.4125f), tuple(6, 1.0717f, 0.825f), tuple(6, 1.7862f, -0.4125f), tuple(6, 1.7862f, 0.4125f), tuple(6, 2.5006f, 0.825f), tuple(6, 2.5006f, 1.65f), tuple(6, 1.7862f, 2.0625f), tuple(6, 1.0717f, 1.65f), tuple(6, 0.3572f, 2.0625f), tuple(6, -0.3572f, 1.65f), tuple(6, -0.3572f, 0.825f), tuple(6, -1.0717f, 0.4125f), tuple(6, -1.0717f, -0.4125f), tuple(6, -1.7862f, 0.825f), tuple(6, -2.5006f, 0.4125f), tuple(6, -2.5006f, -0.4125f), tuple(6, -1.7862f, -0.825f) }}; std::array, 25> bonds = {{ { 0, 1, 1 }, { 0, 18, 1 }, { 1, 2, 1 }, { 2, 3, 1 }, { 3, 4, 1 }, { 4, 5, 1 }, { 4, 8, 1 }, { 5, 6, 1 }, { 6, 7, 1 }, { 7, 9, 1 }, { 8, 9, 1 }, { 9, 10, 1 }, { 10, 11, 1 }, { 11, 12, 1 }, { 12, 13, 1 }, { 13, 14, 1 }, { 14, 15, 1 }, { 15, 16, 1 }, { 16, 17, 1 }, { 17, 18, 1 }, { 17, 19, 1 }, { 18, 22, 1 }, { 19, 20, 1 }, { 20, 21, 1 }, { 21, 22, 1 } }}; add_atoms(molecule, atoms); add_bonds(molecule, bonds); molecules[i] = molecule; ++i; } { auto molecule = new sketcherMinimizerMolecule(); std::array, 25> atoms = {{ tuple(6, -0.825f, -0.2767f), tuple(6, -0.825f, -1.1017f), tuple(6, -0.0f, -1.1017f), tuple(6, 0.4125f, -1.8161f), tuple(6, 1.2375f, -1.8161f), tuple(6, 1.6078f, -2.5533f), tuple(6, 2.4308f, -2.6108f), tuple(6, 2.9001f, -1.9323f), tuple(6, 1.65f, -1.1017f), tuple(6, 2.5559f, -1.1826f), tuple(6, 2.9684f, -0.4681f), tuple(6, 2.5559f, 0.2464f), tuple(6, 1.7309f, 0.2464f), tuple(6, 1.3184f, 0.9608f), tuple(6, 0.6039f, 1.3733f), tuple(6, 0.6039f, 2.1983f), tuple(6, -0.1105f, 2.6108f), tuple(6, -0.825f, 2.1983f), tuple(6, -0.825f, 1.3733f), tuple(6, -1.5395f, 0.9608f), tuple(6, -1.5395f, 0.1358f), tuple(6, -2.2539f, 1.3733f), tuple(6, -2.9684f, 0.9608f), tuple(6, -2.9684f, 0.1358f), tuple(6, -2.2539f, -0.2767f) }}; std::array, 27> bonds = {{ { 0, 1, 1 }, { 0, 20, 1 }, { 1, 2, 1 }, { 2, 3, 1 }, { 3, 4, 1 }, { 4, 5, 1 }, { 4, 8, 1 }, { 5, 6, 1 }, { 6, 7, 1 }, { 7, 9, 1 }, { 8, 9, 1 }, { 9, 10, 1 }, { 10, 11, 1 }, { 11, 12, 1 }, { 12, 13, 1 }, { 13, 14, 1 }, { 14, 15, 1 }, { 15, 16, 1 }, { 16, 17, 1 }, { 17, 18, 1 }, { 18, 19, 1 }, { 19, 20, 1 }, { 19, 21, 1 }, { 20, 24, 1 }, { 21, 22, 1 }, { 22, 23, 1 }, { 23, 24, 1 } }}; add_atoms(molecule, atoms); add_bonds(molecule, bonds); molecules[i] = molecule; ++i; } { auto molecule = new sketcherMinimizerMolecule(); std::array, 27> atoms = {{ tuple(6, -1.0717f, -0.2063f), tuple(6, -1.0717f, -1.0313f), tuple(6, -0.3572f, -1.4438f), tuple(6, 0.3572f, -1.0313f), tuple(6, 1.0717f, -1.4438f), tuple(6, 1.0717f, -2.2688f), tuple(6, 1.7862f, -2.6812f), tuple(6, 2.5006f, -2.2688f), tuple(6, 1.7862f, -1.0313f), tuple(6, 2.5006f, -1.4438f), tuple(6, 3.2151f, -1.0313f), tuple(6, 3.2151f, -0.2063f), tuple(6, 2.5006f, 0.2062f), tuple(6, 2.5006f, 1.0312f), tuple(6, 1.7862f, 1.4437f), tuple(6, 1.7862f, 2.2687f), tuple(6, 1.0717f, 2.6812f), tuple(6, 0.3572f, 2.2687f), tuple(6, 0.3572f, 1.4437f), tuple(6, -0.3572f, 1.0312f), tuple(6, -1.0717f, 1.4437f), tuple(6, -1.7862f, 1.0312f), tuple(6, -1.7862f, 0.2062f), tuple(6, -2.5006f, 1.4437f), tuple(6, -3.2151f, 1.0312f), tuple(6, -3.2151f, 0.2062f), tuple(6, -2.5006f, -0.2063f) }}; std::array, 29> bonds = {{ { 0, 1, 1 }, { 0, 22, 1 }, { 1, 2, 1 }, { 2, 3, 1 }, { 3, 4, 1 }, { 4, 5, 1 }, { 4, 8, 1 }, { 5, 6, 1 }, { 6, 7, 1 }, { 7, 9, 1 }, { 8, 9, 1 }, { 9, 10, 1 }, { 10, 11, 1 }, { 11, 12, 1 }, { 12, 13, 1 }, { 13, 14, 1 }, { 14, 15, 1 }, { 15, 16, 1 }, { 16, 17, 1 }, { 17, 18, 2 }, { 18, 19, 1 }, { 19, 20, 1 }, { 20, 21, 1 }, { 21, 22, 1 }, { 21, 23, 1 }, { 22, 26, 1 }, { 23, 24, 1 }, { 24, 25, 1 }, { 25, 26, 1 } }}; add_atoms(molecule, atoms); add_bonds(molecule, bonds); molecules[i] = molecule; ++i; } { auto molecule = new sketcherMinimizerMolecule(); std::array, 24> atoms = {{ tuple(6, -0.9629f, 0.0063f), tuple(6, -0.5504f, -0.7082f), tuple(6, 0.2746f, -0.7082f), tuple(6, 0.6871f, -1.4226f), tuple(6, 1.5121f, -1.4226f), tuple(6, 1.9246f, -2.1371f), tuple(6, 2.7496f, -2.1371f), tuple(6, 3.1621f, -1.4226f), tuple(6, 1.9246f, -0.7082f), tuple(6, 2.7496f, -0.7082f), tuple(6, 3.1621f, 0.0063f), tuple(6, 2.7496f, 0.7082f), tuple(6, 1.9246f, 0.7082f), tuple(6, 1.5121f, 1.4226f), tuple(6, 0.6871f, 1.4226f), tuple(6, 0.2746f, 2.1371f), tuple(6, -0.5504f, 2.1371f), tuple(6, -0.9629f, 1.4226f), tuple(6, -1.7331f, 1.127f), tuple(6, -1.7331f, 0.302f), tuple(6, -2.4476f, 1.5395f), tuple(6, -3.1621f, 1.127f), tuple(6, -3.1621f, 0.302f), tuple(6, -2.4476f, -0.1105f) }}; std::array, 26> bonds = {{ { 0, 1, 1 }, { 0, 19, 1 }, { 1, 2, 1 }, { 2, 3, 1 }, { 3, 4, 1 }, { 4, 5, 1 }, { 4, 8, 1 }, { 5, 6, 1 }, { 6, 7, 1 }, { 7, 9, 1 }, { 8, 9, 1 }, { 9, 10, 1 }, { 10, 11, 1 }, { 11, 12, 1 }, { 12, 13, 1 }, { 13, 14, 1 }, { 14, 15, 1 }, { 15, 16, 1 }, { 16, 17, 1 }, { 17, 18, 1 }, { 18, 19, 1 }, { 18, 20, 1 }, { 19, 23, 1 }, { 20, 21, 1 }, { 21, 22, 1 }, { 22, 23, 1 } }}; add_atoms(molecule, atoms); add_bonds(molecule, bonds); molecules[i] = molecule; ++i; } { auto molecule = new sketcherMinimizerMolecule(); std::array, 8> atoms = {{ tuple(6, -1.7634f, 2.7232f), tuple(6, -1.7634f, 1.8982f), tuple(6, -0.9384f, 1.8982f), tuple(6, -0.9384f, 2.7232f), tuple(6, -2.1145f, 1.5083f), tuple(6, -1.2895f, 1.5083f), tuple(6, -2.1145f, 2.3333f), tuple(6, -1.2895f, 2.3333f) }}; std::array, 12> bonds = {{ { 0, 1, 1 }, { 0, 3, 1 }, { 0, 6, 1 }, { 1, 2, 1 }, { 1, 4, 1 }, { 2, 3, 1 }, { 2, 5, 1 }, { 3, 7, 1 }, { 4, 5, 1 }, { 4, 6, 1 }, { 5, 7, 1 }, { 6, 7, 1 } }}; add_atoms(molecule, atoms); add_bonds(molecule, bonds); molecules[i] = molecule; ++i; } { auto molecule = new sketcherMinimizerMolecule(); std::array, 8> atoms = {{ tuple(6, -1.808f, 0.4902f), tuple(7, -2.5225f, 0.0777f), tuple(6, -2.5225f, -0.7474f), tuple(6, -1.808f, -1.1598f), tuple(6, -1.0935f, -0.7474f), tuple(7, -1.0935f, 0.0777f), tuple(6, -1.5071f, -0.1127f), tuple(6, -2.042f, -0.5793f) }}; std::array, 9> bonds = {{ { 0, 1, 1 }, { 0, 5, 1 }, { 0, 6, 1 }, { 1, 2, 1 }, { 2, 3, 1 }, { 3, 4, 1 }, { 3, 7, 1 }, { 4, 5, 1 }, { 6, 7, 1 } }}; add_atoms(molecule, atoms); add_bonds(molecule, bonds); molecules[i] = molecule; ++i; } { auto molecule = new sketcherMinimizerMolecule(); std::array, 5> atoms = {{ tuple(6, -0.5833f, -0.0f), tuple(6, 0.0f, 0.5833f), tuple(6, 0.5833f, -0.0f), tuple(6, 0.0f, -0.5833f), tuple(6, 0.1458f, -0.0f) }}; std::array, 6> bonds = {{ { 0, 1, 1 }, { 0, 3, 1 }, { 1, 2, 1 }, { 1, 4, 1 }, { 2, 3, 1 }, { 3, 4, 1 } }}; add_atoms(molecule, atoms); add_bonds(molecule, bonds); molecules[i] = molecule; ++i; } { auto molecule = new sketcherMinimizerMolecule(); std::array, 9> atoms = {{ tuple(6, -6.0f, 7.8125f), tuple(6, -4.46f, 7.8125f), tuple(6, -3.69f, 6.4788f), tuple(6, -6.77f, 6.4788f), tuple(6, -6.0f, 5.1451f), tuple(6, -4.46f, 5.1451f), tuple(6, -2.9954f, 7.3366f), tuple(6, -2.9954f, 5.621f), tuple(6, -5.2637f, 6.1586f) }}; std::array, 11> bonds = {{ { 0, 1, 1 }, { 0, 3, 1 }, { 1, 2, 1 }, { 1, 6, 1 }, { 2, 5, 1 }, { 3, 4, 1 }, { 3, 8, 1 }, { 4, 5, 1 }, { 5, 7, 1 }, { 6, 7, 1 }, { 6, 8, 1 } }}; add_atoms(molecule, atoms); add_bonds(molecule, bonds); molecules[i] = molecule; ++i; } return molecules; } } coordgenlibs-3.0.2/CoordgenTemplates.h000066400000000000000000000007431436654770400200020ustar00rootroot00000000000000 #pragma once /// // Find the templates for coordinate generation // // Autogenerated, do not edit. // // $SCHRODINGER/run mol_generator.py templates.mae // // generated using templates.mae version ad51e1ccece0b7b5f872. // #include class sketcherMinimizerMolecule; namespace schrodinger { /// // Create a new vector of sketcherMinimizerMolecule*. Caller // owns the sketcherMinimizerMolecule objects. std::vector coordgen_templates(); } coordgenlibs-3.0.2/Info.plist000066400000000000000000000013151436654770400161560ustar00rootroot00000000000000 NSPrincipalClass NSApplication CFBundleIconFile CFBundlePackageType APPL CFBundleGetInfoString Created by Qt/QMake CFBundleSignature ???? CFBundleExecutable coordgen_standalone CFBundleIdentifier com.yourcompany.${PRODUCT_NAME:rfc1034identifier} NOTE This file was generated by Qt/QMake. coordgenlibs-3.0.2/LICENSE000066400000000000000000000027561436654770400152250ustar00rootroot00000000000000BSD 3-Clause License Copyright (c) 2017, Schrödinger, Inc. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. coordgenlibs-3.0.2/README.md000066400000000000000000000120731436654770400154700ustar00rootroot00000000000000# CoordgenLibs [![Azure_Build_Status](https://dev.azure.com/patlorton/coordgenlibs/_apis/build/status/schrodinger.coordgenlibs?branchName=master)](https://dev.azure.com/patlorton/coordgenlibs/_build/latest?definitionId=2&branchName=master) This is **Schrödinger, Inc's** 2D coordinate generation. It was formerly proprietary code, but is now released under the [BSD license](https://github.com/schrodinger/coordgenlibs/blob/master/LICENSE). The emphasis of these algorithms are on quality of 2D coordinates rather than speed of generation. The algorithm distinguishes itself from many others by doing well with both macrocycles and metal complexes. It also does extremely well on typical drug-like small molecules, and has been validated on millions of compounds. Schrodinger intends to continue to contribute to this code as it still uses it inside its products, but will also be happy if others contribute pull-requests when there are improvements they would like to make. We'll also be happy to hear bug reports or feature requests from use of this code, though make no guarantee on our ability to process these. ## Documentation Examples and documentation will be added/improved over time ## Templates Coordgen uses templates for some macrocycle systems. The source for the templates is `templates.mae`. If you're an end user of coordgen, you can add local templates in a file called `user_templates.mae` in a directory specified by `CoordgenTemplates::setTemplateDir()`. If you want to update the templates, add new templates to `templates.mae` and run `mol_generator.py` to generate the source files. ## Usage example Code for a sample executable is provided in the `example_dir` directory. Building the example executable is enabled by default, but can be disabled by means of the `COORDGEN_BUILD_EXAMPLE` option. ## Automated Testing Automated testing is still primarily taking place inside Schrodinger's internal build system, although tests are incrementally being added to the `testing` directory. Building the tests is enabled by default, but can be disabled by means of the `COORDGEN_BUILD_TESTS` option. Memory debugging is, by default, configured to use `valgrind`. It can be run on the tests by passing `-DCMAKE_BUILD_TYPE=Debug` to cmake, to enable building the debugging symbols, and then using `ctest -T memcheck` inside the build directory. ## Building from source ### Requirements To build coordgen, you will need to have the following installed in your system: - **CMake** version 3.2 or later. - The development files for the **Boost libraries**. At least the **iostreams** and **regex** components are required. In case of also building the unit tests, the **filesystems** and **unit_test_framework** components will also be required. - A **C++ compiler** supporting the C++11 standard. - A compiled instance of the **maeparser library** or its source code. In case **maeparser** is not available on your system, neither as a compiled library or as source code, if a working `git` executable and an internet connection are available, the builder can automatically download the source and build **maeparser** for you. ### Building 1. Create a build directory inside the the one that contains Coordgen, and move into it: ```bash mkdir build cd build ``` 1. Run `cmake` to configure the build, passing the path to the directory where the sources are located (just `..` if you created `build` inside the sources directory). At this point, you should add any required flags to the `cmake` command. Check the 'Options' section in CMakeLists.txt to see which options are available. ```bash cmake .. -Dmaeparser_DIR=/home/schrodinger/maeparser_install -DCMAKE_INSTALL_PREFIX=/home/schrodinger/coordgen_install` ``` A few notes on the maeparser dependency: - CMake will, by default, search your system's default library paths for the maeparser library. If a `CMAKE_INSTALL_PREFIX` was specified to Coordgen, CMake will also search for maeparser there. - If you already built and installed maeparser using the `CMAKE_INSTALL_PREFIX` to set the installation path, you should pass the exact same path to Coordgen with `maeparser_DIR`. - If CMake cannot find a compiled library for maeparser, it will attempt to download the source code from GitHub and build it. The release to be downloaded if the library is not found can be set using the `-DMAEPARSER_VERSION` flag. The sources will be stored in a directory named like `maeparser-{MAEPARSER_VERSION}` under the coordgen sources. - If `maeparser_DIR` was passed to CMake, and the library was not found, CMake will **NOT** download the sources from GitHub (since we expected to find a compiled library). - If a copy of maeparser's source is found under the proper path, it be used, instead of being downloaded again. - If you want to use Coordgen in a CMake project that also depends on maeparser, set up the maeparser first, as Coordgen will be able to find and use it, without searching for further libraries or compiling it again from the source code. 1. Build and install: ```bash make -j install ``` coordgenlibs-3.0.2/azure-pipelines.yml000066400000000000000000000037661436654770400200610ustar00rootroot00000000000000trigger: - master - dev/* jobs: - job: Ubuntu_20_04_x64 timeoutInMinutes: 90 pool: vmImage: ubuntu-20.04 variables: compiler: gxx_linux-64 boost_version: 1.67.0 number_of_cores: nproc python_name: python37 shared_lib: ON steps: - template: .azure-pipelines/linux_build.yml - job: Ubuntu_20_04_x64_static timeoutInMinutes: 90 pool: vmImage: ubuntu-20.04 variables: compiler: gxx_linux-64 boost_version: 1.67.0 number_of_cores: nproc python_name: python37 shared_lib: OFF steps: - template: .azure-pipelines/linux_build.yml - job: macOS_10_15_x64 timeoutInMinutes: 90 pool: vmImage: macos-10.15 variables: compiler: clangxx_osx-64 boost_version: 1.67.0 number_of_cores: sysctl -n hw.ncpu python_name: python37 target_platform: 10.9 shared_lib: ON steps: - template: .azure-pipelines/mac_build.yml - job: macOS_10_15_x64_static timeoutInMinutes: 90 pool: vmImage: macos-10.15 variables: compiler: clangxx_osx-64 boost_version: 1.67.0 number_of_cores: sysctl -n hw.ncpu python_name: python37 target_platform: 10.9 shared_lib: OFF steps: - template: .azure-pipelines/mac_build.yml - job: Windows_VS2019_x64 timeoutInMinutes: 90 pool: vmImage: windows-2019 variables: compiler: vs2019_win-64 boost_version: 1.67.0 number_of_cores: "%NUMBER_OF_PROCESSORS%" python_name: python37 shared_lib: ON boost_lib_prefix: "" steps: - template: .azure-pipelines/vs_build.yml - job: Windows_VS2019_x64_static timeoutInMinutes: 90 pool: vmImage: windows-2019 variables: compiler: vs2019_win-64 boost_version: 1.67.0 number_of_cores: "%NUMBER_OF_PROCESSORS%" python_name: python37 shared_lib: OFF boost_lib_prefix: "lib" steps: - template: .azure-pipelines/vs_build.yml coordgenlibs-3.0.2/cmake/000077500000000000000000000000001436654770400152665ustar00rootroot00000000000000coordgenlibs-3.0.2/cmake/CoordgenUtils.cmake000066400000000000000000000027531436654770400210600ustar00rootroot00000000000000 # Search for the maeparser library or clone the sources from GitHub macro(find_or_clone_maeparser) find_package(maeparser QUIET) if(maeparser_FOUND) message(STATUS "Found compiled maeparser library at ${maeparser_DIR}") elseif(NOT "${maeparser_DIR}" STREQUAL "") message(FATAL_ERROR "*** Failed to find a compiled instance of maeparser under " "'${maeparser_DIR}'.") else() set(maeparser_DIR "${CMAKE_CURRENT_SOURCE_DIR}/maeparser-${MAEPARSER_VERSION}") if(NOT EXISTS "${maeparser_DIR}/maeparser/CMakeLists.txt") file(DOWNLOAD "https://github.com/schrodinger/maeparser/archive/${MAEPARSER_VERSION}.tar.gz" "${maeparser_DIR}/maeparser-${MAEPARSER_VERSION}.tar.gz") execute_process(COMMAND ${CMAKE_COMMAND} -E tar zxf "maeparser-${MAEPARSER_VERSION}.tar.gz" WORKING_DIRECTORY "${maeparser_DIR}") file(RENAME "${maeparser_DIR}/maeparser-${MAEPARSER_VERSION}" "${maeparser_DIR}/maeparser") endif() if(EXISTS "${maeparser_DIR}/maeparser/CMakeLists.txt") message(STATUS "Downloaded MaeParser '${MAEPARSER_VERSION}' to ${maeparser_DIR}.") else() message(FATAL_ERROR "Failed getting or unpacking Maeparser '${MAEPARSER_VERSION}'.") endif() add_subdirectory("${maeparser_DIR}/maeparser") set(maeparser_INCLUDE_DIRS "${maeparser_DIR}") set(maeparser_LIBRARIES maeparser) endif() endmacro()coordgenlibs-3.0.2/cmake/Findmaeparser.cmake000066400000000000000000000017771436654770400210640ustar00rootroot00000000000000# Try to find Schrodinger's MAEParser libraries. # # Different version handling is not yet supported # # Once found, this will find and define the following variables: # # maeparser_INCLUDE_DIRS - maeparser's includes directory # maeparser_LIBRARIES - maeparser's shared libraries # # include(FindPackageHandleStandardArgs) find_path(maeparser_INCLUDE_DIRS NAMES "maeparser/Reader.hpp" HINTS ${maeparser_INCLUDE_DIRS} ${maeparser_DIR} PATH_SUFFIXES "include" DOC "include path for maeparser" ) message(STATUS "maeparser include dir set as '${maeparser_INCLUDE_DIRS}'") find_library(maeparser_LIBRARIES NAMES maeparser HINTS ${maeparser_LIBRARIES} ${maeparser_DIR} PATH_SUFFIXES "lib" DOC "libraries for maeparser" ) message(STATUS "maeparser libraries set as '${maeparser_LIBRARIES}'") find_package_handle_standard_args(maeparser FOUND_VAR maeparser_FOUND REQUIRED_VARS maeparser_INCLUDE_DIRS maeparser_LIBRARIES) coordgenlibs-3.0.2/example_dir/000077500000000000000000000000001436654770400164775ustar00rootroot00000000000000coordgenlibs-3.0.2/example_dir/CMakeLists.txt000066400000000000000000000011421436654770400212350ustar00rootroot00000000000000add_executable(example example.cpp) if(COORDGEN_BUILD_SHARED_LIBS) target_compile_definitions(example PRIVATE "BOOST_ALL_DYN_LINK") else(COORDGEN_BUILD_SHARED_LIBS) set(Boost_USE_STATIC_LIBS ON) target_compile_definitions(example PRIVATE "STATIC_MAEPARSER") target_compile_definitions(example PRIVATE "STATIC_COORDGEN") endif(COORDGEN_BUILD_SHARED_LIBS) # Workaround for CI: Boost regex seems to be missing icu symbols in # some conda builds. The filesystem lib seems to have them. find_package(Boost COMPONENTS filesystem REQUIRED) target_link_libraries(example coordgen Boost::filesystem) coordgenlibs-3.0.2/example_dir/example.cpp000066400000000000000000000014031436654770400206340ustar00rootroot00000000000000#include #include "../sketcherMinimizer.h" int main() { sketcherMinimizer minimizer; /* create a molecule */ auto* min_mol = new sketcherMinimizerMolecule(); /* add an atom and set its parameters */ auto a1 = min_mol->addNewAtom(); a1->setAtomicNumber(7); auto a2 = min_mol->addNewAtom(); a2->setAtomicNumber(6); /* add a bond and set its parameters */ auto b1 = min_mol->addNewBond(a1, a2); b1->setBondOrder(1); /* load minimizer */ minimizer.initialize(min_mol); /* generate coordinates */ minimizer.runGenerateCoordinates(); /* print coordinates */ auto c1 = a1->getCoordinates(); auto c2 = a2->getCoordinates(); std::cerr << c1 << " " << c2 << std::endl; return 0; } coordgenlibs-3.0.2/mol_generator.py000066400000000000000000000101261436654770400174150ustar00rootroot00000000000000""" Using the schrodinger Python modules, read a template .mae file to generate the coordgen template C++ files. """ import sys import os import textwrap import argparse import subprocess from schrodinger import structure NAME = 'CoordgenTemplates' # String that creates a molecule and adds it to a container # of sketcherMinimizerMolecule* at index i. # # C++ programmers: `{` and `}` are escaped by duplication, so # `{{` means `{`. _MOLECULE = """ {{ auto molecule = new sketcherMinimizerMolecule(); std::array, {atom_total}> atoms = {{{{ {atoms} }}}}; std::array, {bond_total}> bonds = {{{{ {bonds} }}}}; add_atoms(molecule, atoms); add_bonds(molecule, bonds); molecules[i] = molecule; ++i; }} """ _DOC = """ /// // Find the templates for coordinate generation // // Autogenerated, do not edit. // // $SCHRODINGER/run {script_name} {template_file} // // generated using {template_file} version {git_hash}. // """ _HEADER = """ #pragma once {doc} #include class sketcherMinimizerMolecule; namespace schrodinger {{ /// // Create a new vector of sketcherMinimizerMolecule*. Caller // owns the sketcherMinimizerMolecule objects. std::vector coordgen_templates(); }} """ _IMPLEMENTATION = """ {doc} #include "{name}.h" #include #include "sketcherMinimizerMolecule.h" #include "sketcherMinimizerAtom.h" #include "sketcherMinimizerBond.h" using std::array; using std::tuple; template void add_atoms(sketcherMinimizerMolecule* molecule, const T& atoms) {{ for (const auto& a: atoms) {{ auto atom = molecule->addNewAtom(); atom->setAtomicNumber(std::get<0>(a)); atom->setCoordinates(sketcherMinimizerPointF(std::get<1>(a), std::get<2>(a))); }} }} template void add_bonds(sketcherMinimizerMolecule* molecule, const T& bonds) {{ for (const auto& b: bonds) {{ auto* from_atom = molecule->getAtoms().at(b[0]); auto* to_atom = molecule->getAtoms().at(b[1]); auto bond = molecule->addNewBond(from_atom, to_atom); bond->setBondOrder(b[2]); }} }} namespace schrodinger {{ std::vector coordgen_templates() {{ std::vector molecules({total}); size_t i = 0; {body} return molecules; }} }} """ def get_mol_def(st): """ Use _MOLECULE to define `st` as a sketcherMinimizerMolecule """ atoms = ( f' tuple({a.atomic_number}, {a.x}f, {a.y}f)' for a in st.atom) atoms = ',\n'.join(atoms) bonds = ( f' {{ {b.atom1.index - 1}, {b.atom2.index - 1}, {b.order} }}' for b in st.bond) bonds = ',\n'.join(bonds) t = _MOLECULE.format( bonds=bonds, atoms=atoms, atom_total=st.atom_total, bond_total=len(st.bond)) return t def main(args=None): parser = argparse.ArgumentParser(args) parser.add_argument('template_file') opts = parser.parse_args() git_hash = subprocess.check_output( ['git', 'log', '-n', '1', '--pretty=format:%H', opts.template_file]) git_hash = git_hash.decode().strip()[:20] template_dir, template_base_name = os.path.split(opts.template_file) doc = _DOC.format( script_name=os.path.basename(__file__), template_file=template_base_name, git_hash=git_hash) header = _HEADER.format(doc=doc) total = structure.count_structures(opts.template_file) body = '' with structure.StructureReader(opts.template_file) as r: for st in r: mol_def = get_mol_def(st) body += mol_def body = textwrap.indent(body, ' ') implementation = _IMPLEMENTATION.format( doc=doc, name=NAME, body=body, total=total) header_path = os.path.join(template_dir, f'{NAME}.h') with open(header_path, 'w') as fh: fh.write(header) implementation_path = os.path.join(template_dir, f'{NAME}.cpp') with open(implementation_path, 'w') as fh: fh.write(implementation) if __name__ == '__main__': main() coordgenlibs-3.0.2/project.pbxproj000066400000000000000000000647071436654770400173000ustar00rootroot00000000000000// !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 46; objects = { 5E618435888B9D49F8540165 = { buildActionMask = 2147483647; files = ( ); isa = PBXShellScriptBuildPhase; runOnlyForDeploymentPostprocessing = 0; name = "Qt Qmake"; shellPath = "/bin/sh"; shellScript = "make -C /Users/nicola/schrodinger/coordgen_standalone -f qt_makeqmake.mak"; showEnvVarsInLog = "0"; }; 8004577376EAADC6013FC613 = { isa = PBXFileReference; path = "/Users/nicola/schrodinger/coordgen_standalone/CoordgenFragmentBuilder.cpp"; name = "CoordgenFragmentBuilder.cpp"; sourceTree = ""; lastKnownFileType = "sourcecode.cpp.cpp"; }; 7D4215C9EA2EC9364CA98978 = { fileRef = "8004577376EAADC6013FC613"; isa = PBXBuildFile; settings = { ATTRIBUTES = ( ); }; }; 173C592B5DE416DC9480A99B = { isa = PBXFileReference; path = "/Users/nicola/schrodinger/coordgen_standalone/CoordgenFragmenter.cpp"; name = "CoordgenFragmenter.cpp"; sourceTree = ""; lastKnownFileType = "sourcecode.cpp.cpp"; }; CAFAA6B8F70759539F10C91D = { fileRef = "173C592B5DE416DC9480A99B"; isa = PBXBuildFile; settings = { ATTRIBUTES = ( ); }; }; 5766855F16B739293DA54322 = { isa = PBXFileReference; path = "/Users/nicola/schrodinger/coordgen_standalone/CoordgenMacrocycleBuilder.cpp"; name = "CoordgenMacrocycleBuilder.cpp"; sourceTree = ""; lastKnownFileType = "sourcecode.cpp.cpp"; }; 39B762AAD667F69E832051E1 = { fileRef = "5766855F16B739293DA54322"; isa = PBXBuildFile; settings = { ATTRIBUTES = ( ); }; }; B7FE768C7B5A33CFA9F0B580 = { isa = PBXFileReference; path = "/Users/nicola/schrodinger/coordgen_standalone/CoordgenMinimizer.cpp"; name = "CoordgenMinimizer.cpp"; sourceTree = ""; lastKnownFileType = "sourcecode.cpp.cpp"; }; 4A154F31F9833DEC2C9FDE8B = { fileRef = "B7FE768C7B5A33CFA9F0B580"; isa = PBXBuildFile; settings = { ATTRIBUTES = ( ); }; }; 04D8752E70F26A5FDFCC5DEC = { isa = PBXFileReference; path = "/Users/nicola/schrodinger/coordgen_standalone/sketcherMinimizer.cpp"; name = "sketcherMinimizer.cpp"; sourceTree = ""; lastKnownFileType = "sourcecode.cpp.cpp"; }; B2447E4B9F37D75E66FAFF9A = { fileRef = "04D8752E70F26A5FDFCC5DEC"; isa = PBXBuildFile; settings = { ATTRIBUTES = ( ); }; }; AE5FAEF482ADC60A21B9FF16 = { isa = PBXFileReference; path = "/Users/nicola/schrodinger/coordgen_standalone/sketcherMinimizerAtom.cpp"; name = "sketcherMinimizerAtom.cpp"; sourceTree = ""; lastKnownFileType = "sourcecode.cpp.cpp"; }; C70BEA260E22888A93D4F7DA = { fileRef = "AE5FAEF482ADC60A21B9FF16"; isa = PBXBuildFile; settings = { ATTRIBUTES = ( ); }; }; C79B18A9B745420A1E5926B3 = { isa = PBXFileReference; path = "/Users/nicola/schrodinger/coordgen_standalone/sketcherMinimizerBond.cpp"; name = "sketcherMinimizerBond.cpp"; sourceTree = ""; lastKnownFileType = "sourcecode.cpp.cpp"; }; 950F3F66368EEBE6F92B4539 = { fileRef = "C79B18A9B745420A1E5926B3"; isa = PBXBuildFile; settings = { ATTRIBUTES = ( ); }; }; 1E2A012F341DF7D22FE0BC00 = { isa = PBXFileReference; path = "/Users/nicola/schrodinger/coordgen_standalone/sketcherMinimizerFragment.cpp"; name = "sketcherMinimizerFragment.cpp"; sourceTree = ""; lastKnownFileType = "sourcecode.cpp.cpp"; }; 862F31084B9F015E58421CFA = { fileRef = "1E2A012F341DF7D22FE0BC00"; isa = PBXBuildFile; settings = { ATTRIBUTES = ( ); }; }; 5AD44C613336B2E77BF759F4 = { isa = PBXFileReference; path = "/Users/nicola/schrodinger/coordgen_standalone/sketcherMinimizerMarchingSquares.cpp"; name = "sketcherMinimizerMarchingSquares.cpp"; sourceTree = ""; lastKnownFileType = "sourcecode.cpp.cpp"; }; EE472AA202FF0BFE595D63FD = { fileRef = "5AD44C613336B2E77BF759F4"; isa = PBXBuildFile; settings = { ATTRIBUTES = ( ); }; }; FD8ECBFCDBCD3BD5A8055F4E = { isa = PBXFileReference; path = "/Users/nicola/schrodinger/coordgen_standalone/sketcherMinimizerMolecule.cpp"; name = "sketcherMinimizerMolecule.cpp"; sourceTree = ""; lastKnownFileType = "sourcecode.cpp.cpp"; }; 6620117DDF8F05AB64EFBE1F = { fileRef = "FD8ECBFCDBCD3BD5A8055F4E"; isa = PBXBuildFile; settings = { ATTRIBUTES = ( ); }; }; 3EE6F2EE708843B41C133B74 = { isa = PBXFileReference; path = "/Users/nicola/schrodinger/coordgen_standalone/sketcherMinimizerResidue.cpp"; name = "sketcherMinimizerResidue.cpp"; sourceTree = ""; lastKnownFileType = "sourcecode.cpp.cpp"; }; 1DF3023C3083E2694FA3804B = { fileRef = "3EE6F2EE708843B41C133B74"; isa = PBXBuildFile; settings = { ATTRIBUTES = ( ); }; }; 6A14CE45BB98D0EC27648EC0 = { isa = PBXFileReference; path = "/Users/nicola/schrodinger/coordgen_standalone/sketcherMinimizerResidueInteraction.cpp"; name = "sketcherMinimizerResidueInteraction.cpp"; sourceTree = ""; lastKnownFileType = "sourcecode.cpp.cpp"; }; C4B190AA295F953BDA775236 = { fileRef = "6A14CE45BB98D0EC27648EC0"; isa = PBXBuildFile; settings = { ATTRIBUTES = ( ); }; }; 5D434D1D67D536B53F101159 = { isa = PBXFileReference; path = "/Users/nicola/schrodinger/coordgen_standalone/sketcherMinimizerRing.cpp"; name = "sketcherMinimizerRing.cpp"; sourceTree = ""; lastKnownFileType = "sourcecode.cpp.cpp"; }; AEDE0BA4DD2E3A2AA04FB8D7 = { fileRef = "5D434D1D67D536B53F101159"; isa = PBXBuildFile; settings = { ATTRIBUTES = ( ); }; }; 3E886F0588AE0F051D777B7D = { isa = PBXFileReference; path = "/Users/nicola/schrodinger/coordgen_standalone/build/CMakeFiles/feature_tests.c"; name = "feature_tests.c"; sourceTree = ""; lastKnownFileType = "sourcecode.c.c"; }; AF1DFB735B92FEE3E17E1C97 = { fileRef = "3E886F0588AE0F051D777B7D"; isa = PBXBuildFile; settings = { ATTRIBUTES = ( ); }; }; 9E64CDC96A64E09BF516FAE0 = { isa = PBXFileReference; path = "/Users/nicola/schrodinger/coordgen_standalone/build/CMakeFiles/feature_tests.cxx"; name = "feature_tests.cxx"; sourceTree = ""; lastKnownFileType = "sourcecode.cpp.cpp"; }; 3B5E470500CC7B0191B8314A = { fileRef = "9E64CDC96A64E09BF516FAE0"; isa = PBXBuildFile; settings = { ATTRIBUTES = ( ); }; }; 0F6211F821F705453DA9798C = { isa = PBXFileReference; path = "/Users/nicola/schrodinger/coordgen_standalone/build/CMakeFiles/3.8.1/CompilerIdC/CMakeCCompilerId.c"; name = "CMakeCCompilerId.c"; sourceTree = ""; lastKnownFileType = "sourcecode.c.c"; }; BB291AFE0696CE2C2DF8C4B3 = { fileRef = "0F6211F821F705453DA9798C"; isa = PBXBuildFile; settings = { ATTRIBUTES = ( ); }; }; E2A4C54D8E5E9ED6A29A622A = { isa = PBXFileReference; path = "/Users/nicola/schrodinger/coordgen_standalone/build/CMakeFiles/3.8.1/CompilerIdCXX/CMakeCXXCompilerId.cpp"; name = "CMakeCXXCompilerId.cpp"; sourceTree = ""; lastKnownFileType = "sourcecode.cpp.cpp"; }; 79AAF5A9076F8CED519F26B7 = { fileRef = "E2A4C54D8E5E9ED6A29A622A"; isa = PBXBuildFile; settings = { ATTRIBUTES = ( ); }; }; C5A41B5DC88FA998B130D215 = { isa = PBXFileReference; path = "/Users/nicola/schrodinger/coordgen_standalone/CoordgenFragmentBuilder.h"; name = "CoordgenFragmentBuilder.h"; sourceTree = ""; lastKnownFileType = "sourcecode.c.h"; }; 990339E54EDFE74727852176 = { isa = PBXFileReference; path = "/Users/nicola/schrodinger/coordgen_standalone/CoordgenFragmenter.h"; name = "CoordgenFragmenter.h"; sourceTree = ""; lastKnownFileType = "sourcecode.c.h"; }; C873EE2F6448477EB1E34183 = { isa = PBXFileReference; path = "/Users/nicola/schrodinger/coordgen_standalone/CoordgenMacrocycleBuilder.h"; name = "CoordgenMacrocycleBuilder.h"; sourceTree = ""; lastKnownFileType = "sourcecode.c.h"; }; D285417F08E4D43BD4C850D6 = { isa = PBXFileReference; path = "/Users/nicola/schrodinger/coordgen_standalone/CoordgenMinimizer.h"; name = "CoordgenMinimizer.h"; sourceTree = ""; lastKnownFileType = "sourcecode.c.h"; }; B486F4C6CB351A731DBB6107 = { isa = PBXFileReference; path = "/Users/nicola/schrodinger/coordgen_standalone/sketcherMinimizer.h"; name = "sketcherMinimizer.h"; sourceTree = ""; lastKnownFileType = "sourcecode.c.h"; }; 3C79670156C7DCCDEAC3B855 = { isa = PBXFileReference; path = "/Users/nicola/schrodinger/coordgen_standalone/sketcherMinimizerAtom.h"; name = "sketcherMinimizerAtom.h"; sourceTree = ""; lastKnownFileType = "sourcecode.c.h"; }; 3245A010B556E1B593A51AEB = { isa = PBXFileReference; path = "/Users/nicola/schrodinger/coordgen_standalone/sketcherMinimizerBendInteraction.h"; name = "sketcherMinimizerBendInteraction.h"; sourceTree = ""; lastKnownFileType = "sourcecode.c.h"; }; B444D4B05F146022E5CCCCDF = { isa = PBXFileReference; path = "/Users/nicola/schrodinger/coordgen_standalone/sketcherMinimizerBond.h"; name = "sketcherMinimizerBond.h"; sourceTree = ""; lastKnownFileType = "sourcecode.c.h"; }; 7BDA4ABD086570C0651F11E0 = { isa = PBXFileReference; path = "/Users/nicola/schrodinger/coordgen_standalone/sketcherMinimizerClashInteraction.h"; name = "sketcherMinimizerClashInteraction.h"; sourceTree = ""; lastKnownFileType = "sourcecode.c.h"; }; 874CC0D60824F39AAF8C23AC = { isa = PBXFileReference; path = "/Users/nicola/schrodinger/coordgen_standalone/sketcherMinimizerEZConstrainInteraction.h"; name = "sketcherMinimizerEZConstrainInteraction.h"; sourceTree = ""; lastKnownFileType = "sourcecode.c.h"; }; C259596AA8C7150A1621FEA8 = { isa = PBXFileReference; path = "/Users/nicola/schrodinger/coordgen_standalone/sketcherMinimizerFragment.h"; name = "sketcherMinimizerFragment.h"; sourceTree = ""; lastKnownFileType = "sourcecode.c.h"; }; 0080BE02FFCB4D154DC71D9E = { isa = PBXFileReference; path = "/Users/nicola/schrodinger/coordgen_standalone/sketcherMinimizerInteraction.h"; name = "sketcherMinimizerInteraction.h"; sourceTree = ""; lastKnownFileType = "sourcecode.c.h"; }; 68EA8359B3CB02AAD94496D2 = { isa = PBXFileReference; path = "/Users/nicola/schrodinger/coordgen_standalone/sketcherMinimizerMarchingSquares.h"; name = "sketcherMinimizerMarchingSquares.h"; sourceTree = ""; lastKnownFileType = "sourcecode.c.h"; }; C50AF0DD64093A7E2C16171C = { isa = PBXFileReference; path = "/Users/nicola/schrodinger/coordgen_standalone/sketcherMinimizerMaths.h"; name = "sketcherMinimizerMaths.h"; sourceTree = ""; lastKnownFileType = "sourcecode.c.h"; }; DEC415536345E4C69EA6A3EB = { isa = PBXFileReference; path = "/Users/nicola/schrodinger/coordgen_standalone/sketcherMinimizerMolecule.h"; name = "sketcherMinimizerMolecule.h"; sourceTree = ""; lastKnownFileType = "sourcecode.c.h"; }; E84C6AD4150D03186A26CF59 = { isa = PBXFileReference; path = "/Users/nicola/schrodinger/coordgen_standalone/sketcherMinimizerResidue.h"; name = "sketcherMinimizerResidue.h"; sourceTree = ""; lastKnownFileType = "sourcecode.c.h"; }; 5FE91F9B3B341718479FFE25 = { isa = PBXFileReference; path = "/Users/nicola/schrodinger/coordgen_standalone/sketcherMinimizerResidueInteraction.h"; name = "sketcherMinimizerResidueInteraction.h"; sourceTree = ""; lastKnownFileType = "sourcecode.c.h"; }; 872CCCE1C0F4AF2F51D6C416 = { isa = PBXFileReference; path = "/Users/nicola/schrodinger/coordgen_standalone/sketcherMinimizerRing.h"; name = "sketcherMinimizerRing.h"; sourceTree = ""; lastKnownFileType = "sourcecode.c.h"; }; B6E29780788B628DA3D99447 = { isa = PBXFileReference; path = "/Users/nicola/schrodinger/coordgen_standalone/sketcherMinimizerStretchInteraction.h"; name = "sketcherMinimizerStretchInteraction.h"; sourceTree = ""; lastKnownFileType = "sourcecode.c.h"; }; 6309AA0759FDD94399560B74 = { isa = PBXFileReference; path = "/Users/nicola/schrodinger/coordgen_standalone/coordgen_standalone.pro"; name = "coordgen_standalone.pro"; sourceTree = ""; lastKnownFileType = "text"; }; 4FBDFB67332963B7F32A4555 = { isa = PBXFileReference; path = "/Users/nicola/schrodinger/coordgen_standalone/.qmake.stash"; name = ".qmake.stash"; sourceTree = ""; }; 2B7C642DFBD36E05E2C8F2BB = { isa = PBXGroup; children = ( "7252AB33D1A2353F535C9B12"); name = "build"; sourceTree = ""; }; 7252AB33D1A2353F535C9B12 = { isa = PBXGroup; children = ( "3E886F0588AE0F051D777B7D", "9E64CDC96A64E09BF516FAE0", "77A9FFA278D086CB8C3799CE"); name = "CMakeFiles"; sourceTree = ""; }; 77A9FFA278D086CB8C3799CE = { isa = PBXGroup; children = ( "D6C0D30D4D7AC486EB994E54", "9A91502F2E020930C1952027"); name = "3.8.1"; sourceTree = ""; }; D6C0D30D4D7AC486EB994E54 = { isa = PBXGroup; children = ( "0F6211F821F705453DA9798C"); name = "CompilerIdC"; sourceTree = ""; }; 9A91502F2E020930C1952027 = { isa = PBXGroup; children = ( "E2A4C54D8E5E9ED6A29A622A"); name = "CompilerIdCXX"; sourceTree = ""; }; 2EB56BE3C2D93CDAB0C52E67 = { isa = PBXGroup; children = ( "8004577376EAADC6013FC613", "173C592B5DE416DC9480A99B", "5766855F16B739293DA54322", "B7FE768C7B5A33CFA9F0B580", "04D8752E70F26A5FDFCC5DEC", "AE5FAEF482ADC60A21B9FF16", "C79B18A9B745420A1E5926B3", "1E2A012F341DF7D22FE0BC00", "5AD44C613336B2E77BF759F4", "FD8ECBFCDBCD3BD5A8055F4E", "3EE6F2EE708843B41C133B74", "6A14CE45BB98D0EC27648EC0", "5D434D1D67D536B53F101159", "2B7C642DFBD36E05E2C8F2BB", "C5A41B5DC88FA998B130D215", "990339E54EDFE74727852176", "C873EE2F6448477EB1E34183", "D285417F08E4D43BD4C850D6", "B486F4C6CB351A731DBB6107", "3C79670156C7DCCDEAC3B855", "3245A010B556E1B593A51AEB", "B444D4B05F146022E5CCCCDF", "7BDA4ABD086570C0651F11E0", "874CC0D60824F39AAF8C23AC", "C259596AA8C7150A1621FEA8", "0080BE02FFCB4D154DC71D9E", "68EA8359B3CB02AAD94496D2", "C50AF0DD64093A7E2C16171C", "DEC415536345E4C69EA6A3EB", "E84C6AD4150D03186A26CF59", "5FE91F9B3B341718479FFE25", "872CCCE1C0F4AF2F51D6C416", "B6E29780788B628DA3D99447"); name = "Sources"; sourceTree = ""; }; 74B182DB50CB5611B5C1C297 = { isa = PBXGroup; children = ( "6309AA0759FDD94399560B74", "4FBDFB67332963B7F32A4555"); name = "Supporting Files"; sourceTree = ""; }; 7EF0942E79C014DCEC8976BC = { buildActionMask = 2147483647; files = ( ); isa = PBXShellScriptBuildPhase; runOnlyForDeploymentPostprocessing = 0; name = "Qt Preprocessors"; shellPath = "/bin/sh"; shellScript = "make -C /Users/nicola/schrodinger/coordgen_standalone -f qt_preprocess.mak"; showEnvVarsInLog = "0"; }; F7E50F631C51CD5B5DC0BC43 = { buildActionMask = 2147483647; files = ( "7D4215C9EA2EC9364CA98978", "CAFAA6B8F70759539F10C91D", "39B762AAD667F69E832051E1", "4A154F31F9833DEC2C9FDE8B", "B2447E4B9F37D75E66FAFF9A", "C70BEA260E22888A93D4F7DA", "950F3F66368EEBE6F92B4539", "862F31084B9F015E58421CFA", "EE472AA202FF0BFE595D63FD", "6620117DDF8F05AB64EFBE1F", "1DF3023C3083E2694FA3804B", "C4B190AA295F953BDA775236", "AEDE0BA4DD2E3A2AA04FB8D7", "AF1DFB735B92FEE3E17E1C97", "3B5E470500CC7B0191B8314A", "BB291AFE0696CE2C2DF8C4B3", "79AAF5A9076F8CED519F26B7"); isa = PBXSourcesBuildPhase; runOnlyForDeploymentPostprocessing = 0; name = "Compile Sources"; }; 663182AC9CDA580CE9972B5A = { isa = PBXFileReference; name = "QtGui.framework"; path = "/software/lib/Darwin-x86_64/qt-5.6.2/lib/QtGui.framework"; refType = 0; sourceTree = ""; lastKnownFileType = "wrapper.framework"; }; 20F25706901C934E7D5C93C1 = { fileRef = "663182AC9CDA580CE9972B5A"; isa = PBXBuildFile; settings = { }; }; 518742F9CFEB14920968C619 = { isa = PBXFileReference; name = "QtCore.framework"; path = "/software/lib/Darwin-x86_64/qt-5.6.2/lib/QtCore.framework"; refType = 0; sourceTree = ""; lastKnownFileType = "wrapper.framework"; }; BB2AC6B8E5E8273CD0F39663 = { fileRef = "518742F9CFEB14920968C619"; isa = PBXBuildFile; settings = { }; }; 2B774D8E4178765CE52EAAF5 = { isa = PBXFileReference; name = "DiskArbitration.framework"; path = "/System/Library/Frameworks/DiskArbitration.framework"; refType = 0; sourceTree = ""; lastKnownFileType = "wrapper.framework"; }; A99B2AA0F9CBBDD12BA126A4 = { fileRef = "2B774D8E4178765CE52EAAF5"; isa = PBXBuildFile; settings = { }; }; A1A67BEAA744704B29168D39 = { isa = PBXFileReference; name = "IOKit.framework"; path = "/System/Library/Frameworks/IOKit.framework"; refType = 0; sourceTree = ""; lastKnownFileType = "wrapper.framework"; }; 8D267F2E4776F0ECA2F49DC8 = { fileRef = "A1A67BEAA744704B29168D39"; isa = PBXBuildFile; settings = { }; }; D4B32C2222F82AC56BADEB21 = { isa = PBXFileReference; name = "OpenGL.framework"; path = "/System/Library/Frameworks/OpenGL.framework"; refType = 0; sourceTree = ""; lastKnownFileType = "wrapper.framework"; }; 8771A8C96E9C391044035D99 = { fileRef = "D4B32C2222F82AC56BADEB21"; isa = PBXBuildFile; settings = { }; }; 8D9815BDB5BD9F90D2BC05C5 = { isa = PBXFileReference; name = "AGL.framework"; path = "/System/Library/Frameworks/AGL.framework"; refType = 0; sourceTree = ""; lastKnownFileType = "wrapper.framework"; }; E45E51A644D5FC9F942ECE55 = { fileRef = "8D9815BDB5BD9F90D2BC05C5"; isa = PBXBuildFile; settings = { }; }; AF39DD055C3EF8226FBE929D = { children = ( "663182AC9CDA580CE9972B5A", "518742F9CFEB14920968C619", "2B774D8E4178765CE52EAAF5", "A1A67BEAA744704B29168D39", "D4B32C2222F82AC56BADEB21", "8D9815BDB5BD9F90D2BC05C5"); isa = PBXGroup; name = "Frameworks"; sourceTree = ""; }; D1C883685E82D5676953459A = { buildActionMask = 2147483647; files = ( "20F25706901C934E7D5C93C1", "BB2AC6B8E5E8273CD0F39663", "A99B2AA0F9CBBDD12BA126A4", "8D267F2E4776F0ECA2F49DC8", "8771A8C96E9C391044035D99", "E45E51A644D5FC9F942ECE55"); isa = PBXFrameworksBuildPhase; runOnlyForDeploymentPostprocessing = 0; name = "Link Binary With Libraries"; }; 30414803F31797EB689AE508 = { buildActionMask = 2147483647; files = ( ); isa = PBXResourcesBuildPhase; runOnlyForDeploymentPostprocessing = 0; name = "Copy Bundle Resources"; }; 92898B5D77F05593375C470B = { isa = PBXFileReference; includeInIndex = 0; explicitFileType = "wrapper.application"; path = "coordgen_standalone.app"; sourceTree = BUILT_PRODUCTS_DIR; }; FE0A091FDBFB3E9C31B7A1BD = { children = ( "92898B5D77F05593375C470B"); isa = PBXGroup; name = "Products"; sourceTree = ""; }; E8C543AB96796ECAA2E65C57 = { children = ( "2EB56BE3C2D93CDAB0C52E67", "74B182DB50CB5611B5C1C297", "AF39DD055C3EF8226FBE929D", "FE0A091FDBFB3E9C31B7A1BD"); isa = PBXGroup; name = "coordgen_standalone"; sourceTree = ""; }; A98AFEFB583EE4AC4CD0C956 = { buildPhases = ( "5E618435888B9D49F8540165", "7EF0942E79C014DCEC8976BC"); dependencies = ( ); buildConfigurationList = 6CC3B5D2136C7CD6A5CF5A59; isa = PBXAggregateTarget; buildRules = ( ); productName = "Qt Preprocess"; name = "Qt Preprocess"; }; B8740090383D6EF069E04F39 = { isa = PBXTargetDependency; target = "A98AFEFB583EE4AC4CD0C956"; }; 6D39AB9852D6B9F1C38B8B1B = { buildPhases = ( "F7E50F631C51CD5B5DC0BC43", "D1C883685E82D5676953459A", "30414803F31797EB689AE508"); dependencies = ( "B8740090383D6EF069E04F39"); productReference = "92898B5D77F05593375C470B"; buildConfigurationList = 6CC3B5D2136C7CD6A5CF5A59; isa = PBXNativeTarget; buildRules = ( ); productType = "com.apple.product-type.application"; name = "coordgen_standalone"; productName = "coordgen_standalone"; }; 3AA6C32AC930069E80220CF1 = { isa = XCBuildConfiguration; buildSettings = { COPY_PHASE_STRIP = "NO"; ENABLE_BITCODE = "NO"; GCC_GENERATE_DEBUGGING_SYMBOLS = "YES"; GCC_OPTIMIZATION_LEVEL = "0"; PRODUCT_NAME = "coordgen_standalone"; QT_LIBRARY_SUFFIX = "_debug"; SDKROOT = "macosx"; GCC_VERSION = com.apple.compilers.llvm.clang.1_0; CC = "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang"; LDPLUSPLUS = "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang++"; INFOPLIST_FILE = "Info.plist"; SYMROOT = "/Users/nicola/schrodinger/coordgen_standalone"; DYLIB_CURRENT_VERSION = "1.0.0"; DYLIB_COMPATIBILITY_VERSION = "1.0"; MACOSX_DEPLOYMENT_TARGET = "10.7"; HEADER_SEARCH_PATHS = ( ".", ".", "/software/lib/Darwin-x86_64/qt-5.6.2/lib/QtGui.framework/Headers", "/software/lib/Darwin-x86_64/qt-5.6.2/lib/QtCore.framework/Headers", ".", "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/System/Library/Frameworks/OpenGL.framework/Headers", "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/System/Library/Frameworks/AGL.framework/Headers", "/software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/macx-clang"); LIBRARY_SEARCH_PATHS = ( "/software/lib/Darwin-x86_64/qt-5.6.2/lib", "/System/Library/Frameworks/", "/software/lib/Darwin-x86_64/openssl-0.9.8x/lib"); FRAMEWORK_SEARCH_PATHS = ( "/software/lib/Darwin-x86_64/qt-5.6.2/lib", "/software/lib/Darwin-x86_64/qt-5.6.2/lib"); OTHER_CFLAGS = ( "-pipe", "-g", "-Wall", "-W", "-fPIC", "-DQT_GUI_LIB", "-DQT_CORE_LIB"); OTHER_CPLUSPLUSFLAGS = ( "-pipe", "-stdlib=libc++", "-g", "-std=gnu++11", "-Wall", "-W", "-fPIC", "-DQT_GUI_LIB", "-DQT_CORE_LIB"); OTHER_LDFLAGS = ( "-headerpad_max_install_names", "-stdlib=libc++", "-F/software/lib/Darwin-x86_64/qt-5.6.2/lib", "-L/software/lib/Darwin-x86_64/openssl-0.9.8x/lib"); ARCHS = "x86_64"; }; name = "Debug"; }; 77418F46922677BB04ED38DD = { isa = XCBuildConfiguration; buildSettings = { COPY_PHASE_STRIP = "NO"; ENABLE_BITCODE = "NO"; GCC_GENERATE_DEBUGGING_SYMBOLS = "YES"; GCC_OPTIMIZATION_LEVEL = "0"; PRODUCT_NAME = "coordgen_standalone"; QT_LIBRARY_SUFFIX = "_debug"; SDKROOT = "macosx"; PRODUCT_NAME = "coordgen_standalone"; }; name = "Debug"; }; 339EE1B2CC4FC24589A0EA95 = { isa = XCBuildConfiguration; buildSettings = { COPY_PHASE_STRIP = "YES"; ENABLE_BITCODE = "NO"; GCC_GENERATE_DEBUGGING_SYMBOLS = "NO"; PRODUCT_NAME = "coordgen_standalone"; QT_LIBRARY_SUFFIX = ""; SDKROOT = "macosx"; GCC_VERSION = com.apple.compilers.llvm.clang.1_0; CC = "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang"; LDPLUSPLUS = "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang++"; INFOPLIST_FILE = "Info.plist"; SYMROOT = "/Users/nicola/schrodinger/coordgen_standalone"; DYLIB_CURRENT_VERSION = "1.0.0"; DYLIB_COMPATIBILITY_VERSION = "1.0"; MACOSX_DEPLOYMENT_TARGET = "10.7"; HEADER_SEARCH_PATHS = ( ".", ".", "/software/lib/Darwin-x86_64/qt-5.6.2/lib/QtGui.framework/Headers", "/software/lib/Darwin-x86_64/qt-5.6.2/lib/QtCore.framework/Headers", ".", "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/System/Library/Frameworks/OpenGL.framework/Headers", "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/System/Library/Frameworks/AGL.framework/Headers", "/software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/macx-clang"); LIBRARY_SEARCH_PATHS = ( "/software/lib/Darwin-x86_64/qt-5.6.2/lib", "/System/Library/Frameworks/", "/software/lib/Darwin-x86_64/openssl-0.9.8x/lib"); FRAMEWORK_SEARCH_PATHS = ( "/software/lib/Darwin-x86_64/qt-5.6.2/lib", "/software/lib/Darwin-x86_64/qt-5.6.2/lib"); OTHER_CFLAGS = ( "-pipe", "-g", "-Wall", "-W", "-fPIC", "-DQT_GUI_LIB", "-DQT_CORE_LIB"); OTHER_CPLUSPLUSFLAGS = ( "-pipe", "-stdlib=libc++", "-g", "-std=gnu++11", "-Wall", "-W", "-fPIC", "-DQT_GUI_LIB", "-DQT_CORE_LIB"); OTHER_LDFLAGS = ( "-headerpad_max_install_names", "-stdlib=libc++", "-F/software/lib/Darwin-x86_64/qt-5.6.2/lib", "-L/software/lib/Darwin-x86_64/openssl-0.9.8x/lib"); ARCHS = "x86_64"; }; name = "Release"; }; 6666AA5E688052234F6758D8 = { isa = XCBuildConfiguration; buildSettings = { COPY_PHASE_STRIP = "YES"; ENABLE_BITCODE = "NO"; GCC_GENERATE_DEBUGGING_SYMBOLS = "NO"; PRODUCT_NAME = "coordgen_standalone"; QT_LIBRARY_SUFFIX = ""; SDKROOT = "macosx"; PRODUCT_NAME = "coordgen_standalone"; }; name = "Release"; }; DAC4C1AA5EDEA1C85E9CA5E6 = { isa = XCConfigurationList; buildConfigurations = ( "3AA6C32AC930069E80220CF1", "339EE1B2CC4FC24589A0EA95"); defaultConfigurationIsVisible = 0; defaultConfigurationName = "Debug"; }; 6CC3B5D2136C7CD6A5CF5A59 = { isa = XCConfigurationList; buildConfigurations = ( "77418F46922677BB04ED38DD", "6666AA5E688052234F6758D8"); defaultConfigurationIsVisible = 0; defaultConfigurationName = "Debug"; }; 6DB9C3763D02B1415CD9D565 = { hasScannedForEncodings = 1; compatibilityVersion = "Xcode 3.2"; isa = PBXProject; mainGroup = "E8C543AB96796ECAA2E65C57"; productRefGroup = "FE0A091FDBFB3E9C31B7A1BD"; buildConfigurationList = "DAC4C1AA5EDEA1C85E9CA5E6"; projectDirPath = ""; projectRoot = ""; targets = ( "6D39AB9852D6B9F1C38B8B1B", "A98AFEFB583EE4AC4CD0C956"); attributes = { TargetAttributes = { }; }; }; }; rootObject = "6DB9C3763D02B1415CD9D565"; } coordgenlibs-3.0.2/project.xcworkspace/000077500000000000000000000000001436654770400202045ustar00rootroot00000000000000coordgenlibs-3.0.2/project.xcworkspace/xcshareddata/000077500000000000000000000000001436654770400226375ustar00rootroot00000000000000coordgenlibs-3.0.2/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings000066400000000000000000000004101436654770400304260ustar00rootroot00000000000000 IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded coordgenlibs-3.0.2/qt_makeqmake.mak000066400000000000000000000510641436654770400173460ustar00rootroot00000000000000############################################################################# # Makefile for building: coordgen_standalone.app/Contents/MacOS/coordgen_standalone # Generated by qmake (3.0) (Qt 5.6.2) # Project: coordgen_standalone.pro # Template: app # Command: /software/lib/Darwin-x86_64/qt-5.6.2/bin/qmake -spec /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/macx-xcode -o project.pbxproj coordgen_standalone.pro ############################################################################# MAKEFILE = project.pbxproj QMAKE = /software/lib/Darwin-x86_64/qt-5.6.2/bin/qmake project.pbxproj: coordgen_standalone.pro /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/macx-clang/qmake.conf /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/features/spec_pre.prf \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/qdevice.pri \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/features/device_config.prf \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/common/unix.conf \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/common/mac.conf \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/common/macx.conf \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/common/sanitize.conf \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/common/gcc-base.conf \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/common/gcc-base-mac.conf \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/common/clang.conf \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/common/clang-mac.conf \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/qconfig.pri \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_3dcore.pri \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_3dcore_private.pri \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_3dinput.pri \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_3dinput_private.pri \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_3dlogic.pri \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_3dlogic_private.pri \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_3dquick.pri \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_3dquick_private.pri \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_3dquickinput.pri \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_3dquickinput_private.pri \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_3dquickrender.pri \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_3dquickrender_private.pri \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_3drender.pri \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_3drender_private.pri \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_bootstrap_private.pri \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_clucene_private.pri \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_concurrent.pri \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_concurrent_private.pri \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_core.pri \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_core_private.pri \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_dbus.pri \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_dbus_private.pri \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_designer.pri \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_designer_private.pri \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_designercomponents_private.pri \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_enginio.pri \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_enginio_private.pri \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_gui.pri \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_gui_private.pri \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_help.pri \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_help_private.pri \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_labscontrols_private.pri \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_labstemplates_private.pri \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_location.pri \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_location_private.pri \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_macextras.pri \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_macextras_private.pri \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_network.pri \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_network_private.pri \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_opengl.pri \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_opengl_private.pri \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_openglextensions.pri \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_openglextensions_private.pri \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_platformsupport_private.pri \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_positioning.pri \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_positioning_private.pri \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_printsupport.pri \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_printsupport_private.pri \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_qml.pri \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_qml_private.pri \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_qmldevtools_private.pri \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_qmltest.pri \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_qmltest_private.pri \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_quick.pri \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_quick_private.pri \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_quickparticles_private.pri \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_quickwidgets.pri \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_quickwidgets_private.pri \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_script.pri \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_script_private.pri \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_scripttools.pri \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_scripttools_private.pri \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_sensors.pri \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_sensors_private.pri \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_serialbus.pri \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_serialbus_private.pri \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_serialport.pri \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_serialport_private.pri \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_sql.pri \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_sql_private.pri \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_svg.pri \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_svg_private.pri \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_testlib.pri \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_testlib_private.pri \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_uiplugin.pri \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_uitools.pri \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_uitools_private.pri \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_webchannel.pri \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_webchannel_private.pri \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_webkit.pri \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_webkit_private.pri \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_webkitwidgets.pri \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_webkitwidgets_private.pri \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_websockets.pri \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_websockets_private.pri \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_widgets.pri \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_widgets_private.pri \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_xml.pri \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_xml_private.pri \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_xmlpatterns.pri \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_xmlpatterns_private.pri \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/features/qt_functions.prf \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/features/qt_config.prf \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/macx-clang/qmake.conf \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/macx-xcode/qmake.conf \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/features/spec_post.prf \ .qmake.stash \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/features/exclusive_builds.prf \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/features/default_pre.prf \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/features/mac/default_pre.prf \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/features/resolve_config.prf \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/features/default_post.prf \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/features/mac/sdk.prf \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/features/mac/default_post.prf \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/features/mac/objective_c.prf \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/features/warn_on.prf \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/features/qt.prf \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/features/resources.prf \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/features/moc.prf \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/features/unix/opengl.prf \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/features/unix/thread.prf \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/features/file_copies.prf \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/features/mac/rez.prf \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/features/testcase_targets.prf \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/features/exceptions.prf \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/features/yacc.prf \ /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/features/lex.prf \ coordgen_standalone.pro \ /software/lib/Darwin-x86_64/qt-5.6.2/lib/QtGui.framework/QtGui.prl \ /software/lib/Darwin-x86_64/qt-5.6.2/lib/QtCore.framework/QtCore.prl $(QMAKE) -spec /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/macx-xcode -o project.pbxproj coordgen_standalone.pro /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/features/spec_pre.prf: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/qdevice.pri: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/features/device_config.prf: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/common/unix.conf: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/common/mac.conf: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/common/macx.conf: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/common/sanitize.conf: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/common/gcc-base.conf: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/common/gcc-base-mac.conf: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/common/clang.conf: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/common/clang-mac.conf: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/qconfig.pri: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_3dcore.pri: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_3dcore_private.pri: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_3dinput.pri: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_3dinput_private.pri: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_3dlogic.pri: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_3dlogic_private.pri: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_3dquick.pri: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_3dquick_private.pri: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_3dquickinput.pri: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_3dquickinput_private.pri: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_3dquickrender.pri: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_3dquickrender_private.pri: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_3drender.pri: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_3drender_private.pri: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_bootstrap_private.pri: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_clucene_private.pri: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_concurrent.pri: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_concurrent_private.pri: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_core.pri: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_core_private.pri: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_dbus.pri: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_dbus_private.pri: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_designer.pri: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_designer_private.pri: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_designercomponents_private.pri: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_enginio.pri: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_enginio_private.pri: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_gui.pri: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_gui_private.pri: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_help.pri: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_help_private.pri: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_labscontrols_private.pri: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_labstemplates_private.pri: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_location.pri: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_location_private.pri: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_macextras.pri: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_macextras_private.pri: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_network.pri: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_network_private.pri: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_opengl.pri: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_opengl_private.pri: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_openglextensions.pri: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_openglextensions_private.pri: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_platformsupport_private.pri: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_positioning.pri: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_positioning_private.pri: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_printsupport.pri: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_printsupport_private.pri: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_qml.pri: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_qml_private.pri: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_qmldevtools_private.pri: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_qmltest.pri: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_qmltest_private.pri: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_quick.pri: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_quick_private.pri: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_quickparticles_private.pri: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_quickwidgets.pri: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_quickwidgets_private.pri: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_script.pri: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_script_private.pri: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_scripttools.pri: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_scripttools_private.pri: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_sensors.pri: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_sensors_private.pri: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_serialbus.pri: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_serialbus_private.pri: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_serialport.pri: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_serialport_private.pri: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_sql.pri: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_sql_private.pri: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_svg.pri: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_svg_private.pri: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_testlib.pri: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_testlib_private.pri: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_uiplugin.pri: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_uitools.pri: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_uitools_private.pri: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_webchannel.pri: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_webchannel_private.pri: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_webkit.pri: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_webkit_private.pri: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_webkitwidgets.pri: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_webkitwidgets_private.pri: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_websockets.pri: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_websockets_private.pri: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_widgets.pri: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_widgets_private.pri: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_xml.pri: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_xml_private.pri: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_xmlpatterns.pri: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/modules/qt_lib_xmlpatterns_private.pri: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/features/qt_functions.prf: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/features/qt_config.prf: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/macx-clang/qmake.conf: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/macx-xcode/qmake.conf: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/features/spec_post.prf: .qmake.stash: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/features/exclusive_builds.prf: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/features/default_pre.prf: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/features/mac/default_pre.prf: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/features/resolve_config.prf: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/features/default_post.prf: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/features/mac/sdk.prf: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/features/mac/default_post.prf: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/features/mac/objective_c.prf: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/features/warn_on.prf: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/features/qt.prf: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/features/resources.prf: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/features/moc.prf: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/features/unix/opengl.prf: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/features/unix/thread.prf: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/features/file_copies.prf: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/features/mac/rez.prf: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/features/testcase_targets.prf: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/features/exceptions.prf: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/features/yacc.prf: /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/features/lex.prf: coordgen_standalone.pro: /software/lib/Darwin-x86_64/qt-5.6.2/lib/QtGui.framework/QtGui.prl: /software/lib/Darwin-x86_64/qt-5.6.2/lib/QtCore.framework/QtCore.prl: qmake: FORCE @$(QMAKE) -spec /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/macx-xcode -o project.pbxproj coordgen_standalone.pro qmake_all: FORCE coordgenlibs-3.0.2/qt_preprocess.mak000066400000000000000000000036101436654770400175710ustar00rootroot00000000000000############################################################################# # Makefile for building: coordgen_standalone.app/Contents/MacOS/coordgen_standalone # Generated by qmake (3.0) (Qt 5.6.2) # Project: coordgen_standalone.pro # Template: app # Command: /software/lib/Darwin-x86_64/qt-5.6.2/bin/qmake -spec /software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/macx-xcode -o project.pbxproj coordgen_standalone.pro ############################################################################# MAKEFILE = project.pbxproj MOC = /software/lib/Darwin-x86_64/qt-5.6.2/bin/moc UIC = LEX = flex LEXFLAGS = YACC = yacc YACCFLAGS = -d DEFINES = -DQT_GUI_LIB -DQT_CORE_LIB INCPATH = -I. -I. -I/software/lib/Darwin-x86_64/qt-5.6.2/lib/QtGui.framework/Headers -I/software/lib/Darwin-x86_64/qt-5.6.2/lib/QtCore.framework/Headers -I. -I/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/System/Library/Frameworks/OpenGL.framework/Headers -I/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/System/Library/Frameworks/AGL.framework/Headers -I/software/lib/Darwin-x86_64/qt-5.6.2/mkspecs/macx-clang -F/software/lib/Darwin-x86_64/qt-5.6.2/lib DEL_FILE = rm -f MOVE = mv -f preprocess: compilers clean preprocess_clean: compiler_clean mocclean: compiler_moc_header_clean compiler_moc_source_clean mocables: compiler_moc_header_make_all compiler_moc_source_make_all check: first benchmark: first compilers: compiler_rcc_make_all: compiler_rcc_clean: compiler_moc_header_make_all: compiler_moc_header_clean: compiler_moc_source_make_all: compiler_moc_source_clean: compiler_rez_source_make_all: compiler_rez_source_clean: compiler_yacc_decl_make_all: compiler_yacc_decl_clean: compiler_yacc_impl_make_all: compiler_yacc_impl_clean: compiler_lex_make_all: compiler_lex_clean: compiler_clean: coordgenlibs-3.0.2/sketcherMaeReading.h000066400000000000000000000046721436654770400201150ustar00rootroot00000000000000#pragma once /// // Shim for creating sketcherMolecules from .mae files. #include "sketcherMinimizerMolecule.h" #include "maeparser/MaeConstants.hpp" #include "maeparser/Reader.hpp" /// // A very simple utility function to parse a mae::Block into a 2D // sketcherMinimizerMolecule. Anything beyond atomic number, x and y coordinates // and bond orders will be ignored (i.e. no chiralities or stereo bonds will be // parsed). // sketcherMinimizerMolecule* mol_from_mae_block(schrodinger::mae::Block& block) { auto molecule = new sketcherMinimizerMolecule(); // Atom data is in the m_atom indexed block { const auto atom_data = block.getIndexedBlock(schrodinger::mae::ATOM_BLOCK); // All atoms are gauranteed to have these three field names: const auto atomic_numbers = atom_data->getIntProperty(schrodinger::mae::ATOM_ATOMIC_NUM); const auto xs = atom_data->getRealProperty(schrodinger::mae::ATOM_X_COORD); const auto ys = atom_data->getRealProperty(schrodinger::mae::ATOM_Y_COORD); const auto size = atomic_numbers->size(); // atomic numbers, and x, y, and z coordinates for (size_t i = 0; i < size; ++i) { auto atom = molecule->addNewAtom(); atom->setAtomicNumber(atomic_numbers->at(i)); atom->setCoordinates(sketcherMinimizerPointF( static_cast(xs->at(i)), static_cast(ys->at(i)))); } } // Bond data is in the m_bond indexed block try { const auto bond_data = block.getIndexedBlock(schrodinger::mae::BOND_BLOCK); // All bonds are gauranteed to have these three field names: auto from_atoms = bond_data->getIntProperty(schrodinger::mae::BOND_ATOM_1); auto to_atoms = bond_data->getIntProperty(schrodinger::mae::BOND_ATOM_2); auto orders = bond_data->getIntProperty(schrodinger::mae::BOND_ORDER); const auto size = from_atoms->size(); for (size_t i = 0; i < size; ++i) { // Maestro atoms are 1 indexed! auto* from_atom = molecule->getAtoms().at(from_atoms->at(i) - 1); auto* to_atom = molecule->getAtoms().at(to_atoms->at(i) - 1); auto bond = molecule->addNewBond(from_atom, to_atom); bond->setBondOrder(orders->at(i)); } } catch (const std::out_of_range&) { // no bonds. } return molecule; } coordgenlibs-3.0.2/sketcherMinimizer.cpp000066400000000000000000004027171436654770400204210ustar00rootroot00000000000000/* * sketcherMinimizer.cpp * 2d_sketcher * * Created by Nicola Zonta on 13/04/2010. * Copyright Schrodinger, LLC. All rights reserved * */ #include "sketcherMinimizer.h" #include #include #include #include #include #include "CoordgenTemplates.h" #ifdef USE_MAEPARSER #include "sketcherMaeReading.h" #endif #include "CoordgenFragmenter.h" #include "CoordgenMacrocycleBuilder.h" #include "sketcherMinimizerBendInteraction.h" #include "sketcherMinimizerClashInteraction.h" #include "sketcherMinimizerMaths.h" #include "sketcherMinimizerRing.h" #include "sketcherMinimizerStretchInteraction.h" using namespace std; using namespace schrodinger; #define RESIDUE_CLASH_DISTANCE_SQUARED 2.0 * 2.0 #ifndef M_PI #define M_PI 3.1415926535897931 #endif const int bondLength = BONDLENGTH; static const unsigned int MINIMUM_LIGAND_ATOMS = 8; static const float SCORE_MULTIPLIER_FOR_DOUBLE_BONDS = 0.82f; static const float SCORE_MULTIPLIER_FOR_SINGLE_BONDED_HETEROATOMS = 0.9f; static const float SCORE_MULTIPLIER_FOR_FRAGMENTS = 0.1f; const int MAX_NUMBER_OF_RINGS = 40; sketcherMinimizer::sketcherMinimizer(float precision) { setEvenAngles(false); m_minimizer.setPrecision(precision); m_fragmentBuilder.setPrecision(precision); } sketcherMinimizer::~sketcherMinimizer() { clear(); } void sketcherMinimizer::setScoreResidueInteractions(bool b) { m_minimizer.m_scoreResidueInteractions = b; } void sketcherMinimizer::canonicalOrdering(sketcherMinimizerMolecule* minMol) { vector scores; for (unsigned int i = 0; i < minMol->_atoms.size(); i++) { minMol->_atoms[i]->_generalUseN = i; } sketcherMinimizer::morganScores(minMol->_atoms, minMol->_bonds, scores); if (scores.size() == minMol->_atoms.size()) { for (unsigned int i = 0; i < scores.size(); i++) { scores[i] *= 100; scores[i] += minMol->_atoms[i]->atomicNumber; } for (sketcherMinimizerAtom* at : minMol->_atoms) { at->neighbors.clear(); at->bonds.clear(); } for (sketcherMinimizerBond* bo : minMol->_bonds) { bo->startAtom->neighbors.push_back(bo->endAtom); bo->endAtom->neighbors.push_back(bo->startAtom); bo->startAtom->bonds.push_back(bo); bo->endAtom->bonds.push_back(bo); } vector newAtoms; vector newBonds; for (unsigned int i = 0; i < minMol->_atoms.size(); i++) { minMol->_atoms[i]->_generalUseN = i; minMol->_atoms[i]->_generalUseVisited = false; } for (auto& _bond : minMol->_bonds) { _bond->_SSSRVisited = false; } bool found = true; do { int scoreMaxI = -1; for (unsigned int i = 0; i < scores.size(); i++) { if (minMol->_atoms[i]->_generalUseVisited) { continue; } if (scoreMaxI == -1) { scoreMaxI = i; } else if (scores[i] > scores[scoreMaxI]) { scoreMaxI = i; } } if (scoreMaxI > -1) { queue q; q.push(minMol->_atoms[scoreMaxI]); minMol->_atoms[scoreMaxI]->_generalUseVisited = true; while (!q.empty()) { sketcherMinimizerAtom* at = q.front(); newAtoms.push_back(at); q.pop(); int neighI = -1; do { neighI = -1; for (unsigned int i = 0; i < at->neighbors.size(); i++) { if (at->bonds[i]->_SSSRVisited) { continue; } else { if (neighI == -1) { neighI = i; } else { if (scores[at->neighbors[neighI] ->_generalUseN] < scores[at->neighbors[i] ->_generalUseN]) { neighI = i; } } } } if (neighI > -1) { if (!at->neighbors[neighI]->_generalUseVisited) { at->neighbors[neighI]->_generalUseVisited = true; q.push(at->neighbors[neighI]); } at->bonds[neighI]->_SSSRVisited = true; newBonds.push_back(at->bonds[neighI]); } } while (neighI > -1); } } else { found = false; } } while (found); minMol->_atoms = newAtoms; minMol->_bonds = newBonds; } } void sketcherMinimizer::initialize( sketcherMinimizerMolecule* minMol) // min mol is split into molecules if // needed and then added to the minimizer { clear(); m_referenceAtoms = minMol->_atoms; m_referenceBonds = minMol->_bonds; std::map bondsToAtom; for (auto& _bond : minMol->_bonds) { bondsToAtom[_bond->startAtom]++; bondsToAtom[_bond->endAtom]++; } for (auto& _bond : minMol->_bonds) { if (_bond->skip) { continue; } if (getTreatNonterminalBondsToMetalAsZOBs()) { if (_bond->bondOrder == 1 || _bond->bondOrder == 2) { bool terminalBond = bondsToAtom[_bond->startAtom] == 1 || bondsToAtom[_bond->endAtom] == 1; if (!terminalBond && (sketcherMinimizerAtom::isMetal( _bond->startAtom->atomicNumber) || sketcherMinimizerAtom::isMetal( _bond->endAtom->atomicNumber))) { _bond->bondOrder = 0; } } } } for (auto& _bond : minMol->_bonds) { if (_bond->skip) { continue; } if (_bond->bondOrder == 0) { m_proximityRelations.push_back(_bond); } else if (_bond->isResidueInteraction()) { if (!_bond->startAtom->isResidue() && !_bond->endAtom->isResidue()) { m_proximityRelations.push_back(_bond); } } } for (auto& m_extraBond : m_extraBonds) { if (m_extraBond->skip) { continue; } if (m_extraBond->bondOrder == 0) { m_proximityRelations.push_back(m_extraBond); } else if (m_extraBond->isResidueInteraction()) { if (!m_extraBond->startAtom->isResidue() && !m_extraBond->endAtom->isResidue()) { m_proximityRelations.push_back(m_extraBond); } } } { // remove skipped and hidden bonds auto new_end = std::remove_if( minMol->_bonds.begin(), minMol->_bonds.end(), [](sketcherMinimizerBond* b) { return (b->skip || b->bondOrder == 0 || b->startAtom->hidden || b->endAtom->hidden); }); minMol->_bonds.erase(new_end, minMol->_bonds.end()); } { // remove hidden atoms atoms auto new_end = std::remove_if( minMol->_atoms.begin(), minMol->_atoms.end(), [](sketcherMinimizerAtom* a) { return (a->hidden); }); minMol->_atoms.erase(new_end, minMol->_atoms.end()); } // order atoms and bonds using morgan indices to make the result input // order independent canonicalOrdering(minMol); for (auto a : minMol->_atoms) { if (!a->hidden) { m_atoms.push_back(a); } if (a->isResidue()) { m_residues.push_back(static_cast(a)); } } for (auto b : minMol->_bonds) { if (!b->startAtom->hidden && !b->endAtom->hidden) { m_bonds.push_back(b); } if (b->isResidueInteraction()) { m_residueInteractions.push_back( static_cast(b)); } } minMol->forceUpdateStruct(minMol->_atoms, minMol->_bonds, minMol->_rings); splitIntoMolecules(minMol, m_molecules); for (auto& b : m_proximityRelations) { b->startAtom->molecule->m_proximityRelations.push_back(b); if (b->endAtom != b->startAtom) { b->endAtom->molecule->m_proximityRelations.push_back(b); } } flagCrossAtoms(); m_minimizer.m_atoms = m_atoms; m_minimizer.m_bonds = m_bonds; m_minimizer.m_molecules = m_molecules; m_minimizer.m_residues = m_residues; m_minimizer.m_residueInteractions = m_residueInteractions; } bool sketcherMinimizer::structurePassSanityCheck() const { if (m_atoms.empty()) { return false; } for (auto molecule : m_molecules) { if (molecule->_rings.size() > MAX_NUMBER_OF_RINGS) { return false; } } return true; } bool sketcherMinimizer::runGenerateCoordinates() { bool cleanPose = true; if (structurePassSanityCheck()) { findFragments(); buildFromFragments(true); cleanPose = m_minimizer.avoidClashes(); bestRotation(); maybeFlip(); arrangeMultipleMolecules(); writeStereoChemistry(); #ifdef DEBUG_MINIMIZATION_COORDINATES // write minimization data and atom mapping to file writeMinimizationData(); #endif } return cleanPose; } void sketcherMinimizer::flagCrossAtoms() { for (auto at : m_atoms) { if (at->atomicNumber == 16 || at->atomicNumber == 15) { at->crossLayout = true; } } for (auto at : m_atoms) { if (at->crossLayout) { continue; } int cross = 0; for (auto n : at->neighbors) { if (n->neighbors.size() > 3) { cross++; } } if (cross > 2) { at->crossLayout = true; } } } void sketcherMinimizer::clear() { for (auto& _referenceAtom : m_referenceAtoms) { delete _referenceAtom; } m_referenceAtoms.clear(); m_residues.clear(); for (auto& _referenceBond : m_referenceBonds) { delete _referenceBond; } m_referenceBonds.clear(); for (auto& m_extraBond : m_extraBonds) { delete m_extraBond; } m_extraBonds.clear(); for (auto& _fragment : _fragments) { delete _fragment; } _fragments.clear(); for (auto& _molecule : m_molecules) { delete _molecule; } m_molecules.clear(); } void sketcherMinimizer::splitIntoMolecules( sketcherMinimizerMolecule* mol, vector& mols) { if (mol->_atoms.empty()) { mols.push_back(mol); return; } for (sketcherMinimizerAtom* a : mol->_atoms) { a->_generalUseVisited = false; } queue q; q.push(mol->_atoms[0]); for (sketcherMinimizerAtom* a : mol->_atoms) { if (!a->hidden) { q.push(a); break; } } while (!q.empty()) { sketcherMinimizerAtom* a = q.front(); q.pop(); a->_generalUseVisited = true; for (sketcherMinimizerAtom* n : a->neighbors) { if (!n->_generalUseVisited && !n->hidden) { q.push(n); } } } vector newAtoms; for (sketcherMinimizerAtom* a : mol->_atoms) { if (!a->_generalUseVisited && !a->hidden) { newAtoms.push_back(a); } } if (newAtoms.empty()) { mols.push_back(mol); for (sketcherMinimizerMolecule* m : mols) { for (sketcherMinimizerAtom* a : m->_atoms) { a->_generalUseVisited = false; } } } else { auto* newMol = new sketcherMinimizerMolecule; for (unsigned int i = 0; i < mol->_rings.size(); i++) { if (!mol->_rings[i]->_atoms[0]->_generalUseVisited) { newMol->_rings.push_back(mol->_rings[i]); mol->_rings.erase(mol->_rings.begin() + i); i--; } } for (unsigned int i = 0; i < mol->_bonds.size(); i++) { if (!mol->_bonds[i]->startAtom->_generalUseVisited) { newMol->_bonds.push_back(mol->_bonds[i]); mol->_bonds.erase(mol->_bonds.begin() + i); i--; } } for (unsigned int i = 0; i < mol->_atoms.size(); i++) { if (!mol->_atoms[i]->_generalUseVisited) { mol->_atoms[i]->molecule = newMol; newMol->_atoms.push_back(mol->_atoms[i]); mol->_atoms.erase(mol->_atoms.begin() + i); i--; } } mols.push_back(mol); splitIntoMolecules(newMol, mols); } } sketcherMinimizerRing* sketcherMinimizer::sameRing(const sketcherMinimizerAtom* at1, const sketcherMinimizerAtom* at2) { return sketcherMinimizerAtom::shareARing(at1, at2); } sketcherMinimizerRing* sketcherMinimizer::sameRing(const sketcherMinimizerAtom* at1, const sketcherMinimizerAtom* at2, const sketcherMinimizerAtom* at3) { if (at1->rings.empty()) { return nullptr; } if (at2->rings.empty()) { return nullptr; } if (at3->rings.empty()) { return nullptr; } sketcherMinimizerRing* r = nullptr; for (sketcherMinimizerRing* ring : at1->rings) { if (ring->isMacrocycle()) { continue; } for (sketcherMinimizerRing* ring2 : at2->rings) { if (ring != ring2) { continue; } for (sketcherMinimizerRing* ring3 : at3->rings) { if (ring3 == ring2) { if (!r) { r = ring2; } else if (ring2->_atoms.size() < r->_atoms.size()) { r = ring2; } } } } } for (sketcherMinimizerRing* ring : at1->rings) { for (sketcherMinimizerRing* ring2 : at2->rings) { if (ring != ring2) { continue; } for (sketcherMinimizerRing* ring3 : at3->rings) { if (ring3 == ring2) { if (!r) { r = ring2; } else if (ring2->_atoms.size() < r->_atoms.size()) { r = ring2; } } } } } return r; } void sketcherMinimizer::writeStereoChemistry() { for (sketcherMinimizerAtom* a : m_atoms) { if (a->hasStereochemistrySet) { a->writeStereoChemistry(); } } assignPseudoZ(); } void sketcherMinimizer::assignPseudoZ() { for (sketcherMinimizerMolecule* mol : m_molecules) { for (sketcherMinimizerAtom* a : mol->_atoms) { a->_generalUseVisited = false; } sketcherMinimizerAtom* lastAtom = nullptr; bool finished = false; while (!finished) { lastAtom = nullptr; for (sketcherMinimizerAtom* a : mol->_atoms) { if (!a->_generalUseVisited) { lastAtom = a; break; } } if (lastAtom) { queue q; q.push(lastAtom); while (!q.empty()) { lastAtom = q.front(); q.pop(); lastAtom->_generalUseVisited = true; for (unsigned int i = 0; i < lastAtom->neighbors.size(); i++) { if (lastAtom->neighbors[i]->_generalUseVisited) { continue; } float Z = lastAtom->m_pseudoZ; sketcherMinimizerBond* b = lastAtom->bonds[i]; if (b->hasStereochemistryDisplay) { if (b->isWedge) { if ((b->startAtom == lastAtom && !b->isReversed) || (b->endAtom == lastAtom && b->isReversed)) { Z += 1.f; } else if ((b->startAtom == lastAtom && b->isReversed) || (b->endAtom == lastAtom && !b->isReversed)) { Z -= 1.f; } } else { if ((b->startAtom == lastAtom && !b->isReversed) || (b->endAtom == lastAtom && b->isReversed)) { Z -= 1.f; } else if ((b->startAtom == lastAtom && b->isReversed) || (b->endAtom == lastAtom && !b->isReversed)) { Z += 1.f; } } } lastAtom->neighbors[i]->m_pseudoZ = Z; q.push(lastAtom->neighbors[i]); } } } else { finished = true; } } } } void sketcherMinimizer::maybeFlipPeptides( const std::vector& atoms, float& scoreX) { auto chetoCs = m_minimizer.getChetoCs(atoms); auto aminoNs = m_minimizer.getAminoNs(atoms); auto alphaCs = m_minimizer.getAlphaCs(atoms, chetoCs, aminoNs); for (auto alphaC : alphaCs) { sketcherMinimizerAtom* aminoN = nullptr; sketcherMinimizerAtom* chetoC = nullptr; for (auto neighbor : alphaC->neighbors) { if (aminoNs.find(neighbor) != aminoNs.end()) { aminoN = neighbor; } else if (chetoCs.find(neighbor) != chetoCs.end()) { chetoC = neighbor; } } if (aminoN && chetoC) { auto direction = aminoN->coordinates - chetoC->coordinates; const float PEPTIDE_SCORE = 100.f; if (direction.x() > 0) { scoreX -= PEPTIDE_SCORE; } else { scoreX += PEPTIDE_SCORE; } } } } void sketcherMinimizer::maybeFlip() { for (sketcherMinimizerMolecule* mol : m_molecules) { if (mol->hasFixedFragments) { continue; } if (mol->hasConstrainedFragments) { continue; } if (mol->_atoms.size() < 2) { continue; } float scoreY = 0.f, scoreX = 0.f; maybeFlipPeptides(mol->getAtoms(), scoreX); sketcherMinimizerPointF cent(0.f, 0.f); for (sketcherMinimizerAtom* a : mol->_atoms) cent += a->coordinates; if (!mol->_atoms.empty()) { cent /= mol->_atoms.size(); } for (sketcherMinimizerFragment* f : mol->_fragments) { vector rings = f->getRings(); if (rings.size() == 2) { sketcherMinimizerRing* r1 = rings[0]; sketcherMinimizerRing* r2 = rings[1]; sketcherMinimizerPointF c1 = r1->findCenter(); sketcherMinimizerPointF c2 = r2->findCenter(); if (c1.x() - c2.x() > SKETCHER_EPSILON) { sketcherMinimizerPointF swapP = c2; c2 = c1; c1 = swapP; sketcherMinimizerRing* swapR; swapR = r2; r2 = r1; r1 = swapR; } if (r2->isBenzene() && !r1->isBenzene()) { scoreX -= 20; } else if (r1->isBenzene() && !r2->isBenzene()) { scoreX += 20; } } if (rings.size() > 3) { sketcherMinimizerPointF center(0.f, 0.f); sketcherMinimizerPointF weightedCenter(0.f, 0.f); size_t totalN = 0; int totalRings = 0; for (sketcherMinimizerRing* r : rings) { if (r->_atoms.size() < 4) { continue; } sketcherMinimizerPointF c = r->findCenter(); center += c; weightedCenter += c * r->_atoms.size(); totalN += r->_atoms.size(); totalRings++; } if (totalRings && totalN) { center /= totalRings; weightedCenter /= totalN; } if (weightedCenter.y() - center.y() < -SKETCHER_EPSILON) { scoreY += 50.f; } else if (weightedCenter.y() - center.y() > SKETCHER_EPSILON) { scoreY -= 50.f; } if (weightedCenter.x() - center.x() < -SKETCHER_EPSILON) { scoreX += 50.f; } else if (weightedCenter.x() - center.x() > SKETCHER_EPSILON) { scoreX -= 50.f; } } } float minx = 9999.f, miny = 9999.f, maxx = -9999.f, maxy = -9999.f; for (sketcherMinimizerAtom* a : mol->_atoms) { float x = a->coordinates.x(); float y = a->coordinates.y(); if (x < minx) { minx = x; } else if (x > maxx) { maxx = x; } if (y < miny) { miny = y; } else if (y > maxy) { maxy = y; } } float meanx = (maxx + minx) * 0.5f; float meany = (maxy + miny) * 0.5f; if (meanx - cent.x() > SKETCHER_EPSILON) { scoreX -= 0.5f; } else if (meanx - cent.x() < -SKETCHER_EPSILON) { scoreX += 0.5f; } if (meany - cent.y() > SKETCHER_EPSILON) { scoreY += 0.5f; } else if (meany - cent.y() < -SKETCHER_EPSILON) { scoreY -= 0.5f; } for (sketcherMinimizerBond* b : mol->_bonds) { if (b->bondOrder == 2) { if (b->startAtom->neighbors.size() == 1 && b->endAtom->neighbors.size() > 1) { float diff = b->startAtom->coordinates.y() - b->endAtom->coordinates.y(); if (diff > SKETCHER_EPSILON) { scoreY += 1; } else if (diff < -SKETCHER_EPSILON) { scoreY -= 1; } } else if (b->endAtom->neighbors.size() == 1 && b->startAtom->neighbors.size() > 1) { float diff = b->endAtom->coordinates.y() - b->startAtom->coordinates.y(); if (diff > SKETCHER_EPSILON) { scoreY += 1; } else if (diff < -SKETCHER_EPSILON) { scoreY -= 1; } } } } if (0.f > scoreY) { flipY = -1; for (sketcherMinimizerAtom* a : mol->_atoms) { a->coordinates.setY(-a->coordinates.y()); } } if (0.f > scoreX) { flipX = -1; for (sketcherMinimizerAtom* a : mol->_atoms) { a->coordinates.setX(-a->coordinates.x()); } } } } void sketcherMinimizer::addToVector(float weight, float angle, vector>& angles) { angle = roundToTwoDecimalDigits(angle); while (angle <= 0) { angle += static_cast(M_PI); } for (unsigned int i = 0; i < angles.size(); i++) { if (angles[i].second < angle - SKETCHER_EPSILON) { if (i == angles.size() - 1) { angles.emplace_back(weight, angle); break; } } else if (angles[i].second - angle < SKETCHER_EPSILON && angles[i].second - angle > -SKETCHER_EPSILON) { angles[i].first += weight; break; } else { angles.insert(angles.begin() + i, pair(weight, angle)); break; } } if (angles.empty()) { angles.emplace_back(weight, angle); } } /* if a peptide chain is present rotate the molecule so it's horizontal */ void sketcherMinimizer::addBestRotationInfoForPeptides( vector>& angles, const std::vector& atoms) { auto chetoCs = m_minimizer.getChetoCs(atoms); auto aminoNs = m_minimizer.getAminoNs(atoms); auto alphaCs = m_minimizer.getAlphaCs(atoms, chetoCs, aminoNs); for (auto alphaC : alphaCs) { sketcherMinimizerAtom* aminoN = nullptr; sketcherMinimizerAtom* chetoC = nullptr; for (auto neighbor : alphaC->neighbors) { if (aminoNs.find(neighbor) != aminoNs.end()) { aminoN = neighbor; } else if (chetoCs.find(neighbor) != chetoCs.end()) { chetoC = neighbor; } } if (aminoN && chetoC) { auto direction = aminoN->coordinates - chetoC->coordinates; float weight = 1000.f; float angle = atan2(-direction.y(), direction.x()); addToVector(weight, angle, angles); } } } void sketcherMinimizer::bestRotation() { for (sketcherMinimizerMolecule* mol : m_molecules) { vector> angles; if (mol->hasFixedFragments || mol->hasConstrainedFragments) { continue; } addBestRotationInfoForPeptides(angles, mol->getAtoms()); float angle = 0.f; float lastAngle; unsigned int i = 0, j = 0; float weight = 1.f; auto increment = static_cast(M_PI / 6); for (sketcherMinimizerAtom* a : mol->_atoms) { if (!a->rings.empty()) { continue; } if (a->neighbors.size() > 1) { for (i = 0; i < a->neighbors.size() - 1; i++) { for (j = i + 1; j < a->neighbors.size(); j++) { weight = 6; if (a->neighbors[i]->neighbors.size() != 1) { weight += 2; } if (a->neighbors[j]->neighbors.size() != 1) { weight += 2; } if (a->neighbors[j]->atomicNumber == 6) { weight += 1; } if (a->neighbors[j]->atomicNumber == 6) { weight += 1; } if (a->neighbors[i]->charge == 0) { weight += 1; } if (a->neighbors[j]->charge == 0) { weight += 1; } sketcherMinimizerPointF p = a->neighbors[i]->coordinates - a->neighbors[j]->coordinates; angle = atan2(-p.y(), p.x()); addToVector(weight, angle, angles); } } } } for (sketcherMinimizerBond* b : mol->_bonds) { sketcherMinimizerPointF p = b->endAtom->coordinates - b->startAtom->coordinates; weight = 1; angle = atan2(-p.y(), p.x()); angle = roundToTwoDecimalDigits(angle); while (angle <= 0) { angle += static_cast(M_PI); } lastAngle = angle; for (unsigned int i = 0; i < 6; i++) { if (i == 1 || i == 5) { weight = 5.f; } else if (i == 0 || i == 3) { weight = 1.5f; } else { weight = 1.f; } if (b->bondOrder == 2 && i == 3 && (b->startAtom->neighbors.size() == 1 || b->endAtom->neighbors.size() == 1)) { weight += 1.5; } if (b->startAtom->neighbors.size() == 1 && b->endAtom->neighbors.size() == 1 && i == 0) { weight += 10; } addToVector(weight, lastAngle, angles); lastAngle += increment; if (lastAngle > M_PI) { lastAngle -= static_cast(M_PI); } } } for (sketcherMinimizerFragment* f : mol->_fragments) { vector rings = f->getRings(); vector inPlaneRings = rings; size_t ringsN = inPlaneRings.size(); if (ringsN == 2) { sketcherMinimizerRing* r1 = inPlaneRings[0]; sketcherMinimizerRing* r2 = inPlaneRings[1]; sketcherMinimizerPointF p = r2->findCenter() - r1->findCenter(); p.normalize(); angle = atan2(-p.y(), p.x()); weight = 25.f; addToVector(weight, angle, angles); } else if (ringsN == 3) { sketcherMinimizerPointF r1 = inPlaneRings[0]->findCenter(); sketcherMinimizerPointF r2 = inPlaneRings[1]->findCenter(); for (sketcherMinimizerRing* r : inPlaneRings) { vector fusedWith; vector> fusionAtoms; for (unsigned int fw = 0; fw < r->fusedWith.size(); fw++) { fusedWith.push_back(r->fusedWith[fw]); fusionAtoms.push_back(r->fusionAtoms[fw]); } if (fusedWith.size() == 2) { if (fusionAtoms[0].size() == 2 && fusionAtoms[1].size() == 2) { r1 = (fusionAtoms[0][0]->coordinates + fusionAtoms[0][1]->coordinates) * 0.5; r2 = (fusionAtoms[1][0]->coordinates + fusionAtoms[1][1]->coordinates) * 0.5; break; } } } sketcherMinimizerPointF p = r2 - r1; angle = atan2(-p.y(), p.x()); weight = 50.f; addToVector(weight, angle, angles); } else { vector rings; for (sketcherMinimizerRing* r : inPlaneRings) { if (r->_atoms.size() == 6) { rings.push_back(r); } } for (sketcherMinimizerRing* r : rings) { for (auto fusionAts : r->fusionAtoms) { if (fusionAts.size() == 2) { sketcherMinimizerPointF p = fusionAts[0]->coordinates - fusionAts[1]->coordinates; // if (p.x () != p.x () || p.y () != p.y ()) p = // sketcherMinimizerPointF (50.f, 0.f); sketcherMinimizerPointF rotatedP(p.y(), p.x()); angle = static_cast(atan2(-p.y(), p.x()) - M_PI * 0.5); weight = 25.f; addToVector(weight, angle, angles); } } } } } if (angles.size() > 1) { if (angles[angles.size() - 1].second - angles[0].second >= M_PI - 2 * SKETCHER_EPSILON) { angles[0].first += angles[angles.size() - 1].first; angles.erase(angles.begin() + angles.size() - 1); } } if (!angles.empty()) { int bestI = 0; for (i = 0; i < angles.size(); i++) { if (angles[i].first > angles[bestI].first) { bestI = i; } } float s = -sin(angles[bestI].second); float c = cos(angles[bestI].second); sketcherMinimizerPointF center(0.f, 0.f); for (sketcherMinimizerAtom* at : mol->_atoms) center += at->coordinates; if (!mol->_atoms.empty()) { center /= mol->_atoms.size(); } for (sketcherMinimizerAtom* at : mol->_atoms) { sketcherMinimizerPointF v = at->coordinates - center; v.rotate(s, c); at->setCoordinates(center + v); } sin_flip = s; cos_flip = c; centerX = center.x(); centerY = center.y(); } } } void sketcherMinimizer::writeMinimizationData() { // print all coordinates to output file sketcherMinimizerPointF center(centerX, centerY); std::ofstream energy_file("minimization_data.txt"); for (size_t i = 0; i < m_minimizer.energy_list.size(); ++i) { energy_file << m_minimizer.energy_list[i] << ";"; for (auto coord : m_minimizer.all_coordinates[i]) { sketcherMinimizerPointF v = coord - center; v.rotate(sin_flip, cos_flip); sketcherMinimizerPointF new_coord = center + v; energy_file << new_coord.x() * flipX << "," << new_coord.y() * flipY << ";"; } energy_file << "\n"; } energy_file.close(); // print atom mapping to output file std::ofstream atom_mapping_file("atom_mapping.txt"); for (size_t i = 0; i < m_referenceAtoms.size(); ++i) { size_t actual_idx = -1; for (size_t j = 0; j < m_atoms.size(); ++j) { if (m_referenceAtoms[i] == m_atoms[j]) { actual_idx = j; break; } } atom_mapping_file << i << "," << actual_idx << ";"; } atom_mapping_file.close(); } void sketcherMinimizer::findFragments() { assert(!m_molecules.empty()); for (sketcherMinimizerMolecule* mol : m_molecules) { CoordgenFragmenter::splitIntoFragments(mol); if (mol->_fragments.empty()) { continue; } vector fragments = mol->_fragments; _fragments.reserve(_fragments.size() + fragments.size()); _fragments.insert(_fragments.end(), fragments.begin(), fragments.end()); m_independentFragments.push_back(mol->getMainFragment()); } m_minimizer.m_fragments = _fragments; initializeFragments(); } void sketcherMinimizer::placeResiduesProteinOnlyModeCircleStyle( const std::map>& chains) { size_t totalResiduesNumber = m_residues.size() + chains.size(); auto angle = static_cast(2.f * M_PI / totalResiduesNumber); const float residueRadius = 30.f; const auto circumference = static_cast(totalResiduesNumber * residueRadius * 2); const auto radius = static_cast(circumference * 0.5 / M_PI); int i = 0; for (const auto& chain : chains) { ++i; // gap between chains auto residues = chain.second; sort(residues.begin(), residues.end(), [](const sketcherMinimizerResidue* firstRes, const sketcherMinimizerResidue* secondRes) { int firstN = firstRes->resnum; int secondN = secondRes->resnum; return firstN < secondN; }); for (auto res : residues) { sketcherMinimizerPointF p(radius, 0); // place residues in a circle p.rotate(sin(angle * i), cos(angle * i)); res->coordinates = p; res->coordinatesSet = true; res->molecule->isPlaced = true; ++i; } } } std::map sketcherMinimizer::computeChainsStartingPositionsMetaMol( const std::map>& chains) { map molMap; auto* metaMol = new sketcherMinimizerMolecule; for (const auto& chainPair : chains) { auto* a = new sketcherMinimizerAtom; a->molecule = metaMol; metaMol->_atoms.push_back(a); molMap[chainPair.first] = a; } for (const auto& chainPair : chains) { for (auto residue : chainPair.second) { for (auto interaction : residue->residueInteractions) { if (interaction->startAtom->isResidue() && interaction->endAtom->isResidue()) { auto* r1 = static_cast( interaction->startAtom); auto* r2 = static_cast( interaction->endAtom); if (r1->chain != r2->chain) { // add a bond to the metaMol if it doesn't exist already sketcherMinimizerAtom* at1 = molMap[r1->chain]; sketcherMinimizerAtom* at2 = molMap[r2->chain]; bool found = false; for (sketcherMinimizerBond* b : metaMol->_bonds) { if ((b->startAtom == at1 && b->endAtom == at2) || (b->startAtom == at2 && b->endAtom == at1)) { found = true; break; } } if (!found) { auto* newBond = new sketcherMinimizerBond; newBond->startAtom = at1; newBond->endAtom = at2; metaMol->_bonds.push_back(newBond); } } } } } } sketcherMinimizer min; if (!metaMol->_atoms.empty()) { min.setEvenAngles(true); min.initialize(metaMol); findFragments(); min.buildFromFragments(true); min.m_minimizer.avoidClashes(); min.bestRotation(); min.maybeFlip(); min.arrangeMultipleMolecules(); } std::map positions; for (const auto& iter : molMap) { positions[iter.first] = iter.second->coordinates * 10.; } return positions; } void sketcherMinimizer::shortenInteractions( const std::map>& chains) { for (const auto& chain : chains) { for (auto res : chain.second) { for (auto interaction : res->residueInteractions) { sketcherMinimizerPointF midPoint = 0.5 * (interaction->startAtom->coordinates + interaction->endAtom->coordinates); res->coordinates += (midPoint - res->coordinates) * 0.1; } } } } std::vector sketcherMinimizer::orderResiduesOfChains( const std::map>& chains) { std::vector vec; for (const auto& chain : chains) { for (auto res : chain.second) { vec.push_back(res); } } sort(vec.begin(), vec.end(), [](const sketcherMinimizerResidue* firstRes, const sketcherMinimizerResidue* secondRes) { return firstRes->residueInteractions.size() > secondRes->residueInteractions.size(); }); std::set visitedResidues; std::queue residueQueue; std::vector finalVec; for (auto residue : vec) { if (visitedResidues.find(residue) != visitedResidues.end()) { continue; } residueQueue.push(residue); visitedResidues.insert(residue); while (!residueQueue.empty()) { auto topResidue = residueQueue.front(); finalVec.push_back(topResidue); residueQueue.pop(); for (auto partner : topResidue->residueInteractionPartners) { auto* partnerRes = static_cast(partner); if (visitedResidues.find(partnerRes) == visitedResidues.end()) { residueQueue.push(partnerRes); visitedResidues.insert(partnerRes); } } } } return finalVec; } void sketcherMinimizer::placeResiduesProteinOnlyModeLIDStyle( const std::map>& chains) { auto positions = computeChainsStartingPositionsMetaMol(chains); sketcherMinimizerPointF p; for (const auto& chain : chains) { p = positions[chain.first]; for (auto res : chain.second) { res->coordinates = p; } } shortenInteractions(chains); auto residues = orderResiduesOfChains(chains); for (auto res : residues) { sketcherMinimizerResidue* firstPartner = nullptr; for (auto partner : res->residueInteractionPartners) { if (partner->coordinatesSet) { auto partnerResidue = static_cast(partner); if (!firstPartner && partnerResidue->chain != res->chain) { firstPartner = partnerResidue; } } } /* when searching for a position for res prefer a direction * perpendicular to the direction of interactions to optimize use of * space */ sketcherMinimizerPointF direction(0, 1); if (firstPartner) { sketcherMinimizerPointF chainCenterDirections = positions[firstPartner->chain] - positions[res->chain]; direction = sketcherMinimizerPointF(-chainCenterDirections.y(), chainCenterDirections.x()); direction.normalize(); direction *= 4.; } res->coordinates = exploreGridAround(res->coordinates, 10, 5, 0, 0, -1.f, false, res, direction); res->coordinatesSet = true; res->molecule->isPlaced = true; } } void sketcherMinimizer::placeResiduesProteinOnlyMode() { std::map> chains; for (auto residue : m_residues) { string chainOfResidue = residue->chain; chains[chainOfResidue].push_back(residue); } placeResiduesProteinOnlyModeLIDStyle(chains); m_minimizer.minimizeProteinOnlyLID(chains); } void sketcherMinimizer::placeResiduesInCrowns() { auto SSEs = groupResiduesInSSEs(m_residues); /* sort secondary structure elements so that the most importants are placed * first. prefer longer SSEs and ones that make more interactions */ sort(SSEs.begin(), SSEs.end(), [](const vector& firstSSE, const vector& secondSSE) { float interactionsOfFirst = 0, interactionsOfSecond = 0; for (auto res : firstSSE) { interactionsOfFirst += res->residueInteractions.size(); } for (auto res : secondSSE) { interactionsOfSecond += res->residueInteractions.size(); } float interactionScaling = 3.f; float score1 = firstSSE.size() + interactionScaling * interactionsOfFirst / firstSSE.size(); float score2 = secondSSE.size() + interactionScaling * interactionsOfSecond / secondSSE.size(); return score1 > score2; }); bool needOtherShape = true; int shapeCounter = 0; // place residues in a crowns around the ligand. Keep expanding to further // away crowns until all residues are placed while (needOtherShape) { vector shape = shapeAroundLigand(shapeCounter++); needOtherShape = fillShape(SSEs, shape, shapeCounter); } } /* place residues in SSEs in the current shape. Return false if all residues are * place, true otherwise */ bool sketcherMinimizer::fillShape( vector>& SSEs, const vector& shape, int shapeN) { vector penalties(shape.size(), false); std::set outliers; for (const auto& SSE : SSEs) { placeSSE(SSE, shape, shapeN, penalties, outliers); } return !outliers.empty(); } /* assign a penalty for the stretching of bonds between residues in the same * SSE */ float sketcherMinimizer::scoreSSEBondStretch( const sketcherMinimizerPointF& coordinates1, const sketcherMinimizerPointF& coordinates2) { const float stretchPenalty = 400.f; auto squaredLength = (coordinates2 - coordinates1).squareLength(); return squaredLength * stretchPenalty; } float sketcherMinimizer::getResidueDistance( float startF, float increment, sketcherMinimizerResidue* resToConsider, const vector& SSE) const { float totalF = startF; sketcherMinimizerResidue* lastRes = nullptr; for (auto res : SSE) { if (lastRes) { auto result = static_cast(res->resnum - lastRes->resnum); /* if the gap is more than 1, make the distance a bit smaller for * aesthetic reasons */ result = static_cast(1 + (result - 1) * 0.8); if (result < 1.f) { result = 1.f; } totalF += increment * result; } if (res == resToConsider) { break; } lastRes = res; } return totalF; } /* return a score for the placing on the SSE starting at startingPosition and * separated by increment */ float sketcherMinimizer::scoreSSEPosition( const vector& SSE, const vector& shape, int shapeN, vector& penalties, float startingPosition, float increment) { float score = 0.f; sketcherMinimizerResidue* lastResidue = nullptr; int lastResiduePosition = 0; sketcherMinimizerPointF lastResidueCoordinates; for (auto res : SSE) { int index = getShapeIndex( shape, getResidueDistance(startingPosition, increment, res, SSE)); auto residueCoordinates = shape.at(index); int residuePosition = 0; if (res->coordinatesSet) { residuePosition = -1; residueCoordinates = res->coordinates; } else { if (!penalties[index]) { residuePosition = 0; } else { residuePosition = 1; } } if (residuePosition != -1) { score += scoreResiduePosition(index, shape, shapeN, penalties, res); } if (lastResidue && (residuePosition != lastResiduePosition)) { score += scoreSSEBondStretch(residueCoordinates, lastResidueCoordinates); } lastResiduePosition = residuePosition; lastResidueCoordinates = residueCoordinates; lastResidue = res; } return score; } void sketcherMinimizer::placeSSE(const vector& SSE, const vector& shape, int shapeN, vector& penalties, set& outliers, bool placeOnlyInteracting) { int residuesToPlace = 0; for (auto res : SSE) { if (!res->coordinatesSet) { residuesToPlace++; } } if (residuesToPlace == 0) { return; } typedef pair Solution; vector> scoredSolutions; /* move around the crown scoring possible solutions, varying the starting * position and the separation between consecutive residues */ for (float f = 0.f; f < 1.f; f += 0.004f) { float distance = 5.f / shape.size(); for (float increment = -1 * distance; increment <= 1 * distance; increment += distance) { if (increment == 0) { continue; } float score = scoreSSEPosition(SSE, shape, shapeN, penalties, f, increment); scoredSolutions.emplace_back(score, Solution(f, increment)); } } auto bestResult = min_element(scoredSolutions.begin(), scoredSolutions.end()); set alreadyPlaced; for (auto residue : SSE) { if (residue->coordinatesSet) { continue; // placed in a previous crown } float f = getResidueDistance(bestResult->second.first, bestResult->second.second, residue, SSE); int index = getShapeIndex(shape, f); bool alreadyAResidueHere = penalties.at(index); sketcherMinimizerPointF position = shape.at(index); if (alreadyAResidueHere || (placeOnlyInteracting && residue->residueInteractionPartners.empty())) { outliers.insert(residue); } else { residue->coordinates = position; alreadyPlaced.insert(residue); } } // mark the current solution to prevent other residues from being placed on // top of these markSolution(bestResult->second, SSE, shape, penalties, outliers); for (auto res : alreadyPlaced) { res->coordinatesSet = true; } for (auto res : SSE) { if (res->m_isWaterMap && res->m_isClashing && res->coordinatesSet && res->m_closestLigandAtom != nullptr) { sketcherMinimizerPointF directionToLigand = res->m_closestLigandAtom->coordinates - res->coordinates; directionToLigand.normalize(); float displacement = BONDLENGTH * 0.3; res->coordinates = res->m_closestLigandAtom->coordinates - directionToLigand * displacement; } } } void sketcherMinimizer::markSolution( const pair& solution, const vector& SSE, const vector& shape, vector& penalties, set& outliers) { float padding = abs(solution.second) * 0.5f; sketcherMinimizerResidue* lastRes = nullptr; float lastF = 0.f; for (auto res : SSE) { if (res->coordinatesSet || (res->m_isWaterMap && res->m_isClashing) || outliers.find(res) != outliers.end()) { lastRes = nullptr; lastF = 0.f; continue; } float f = getResidueDistance(solution.first, solution.second, res, SSE); int startIndex = getShapeIndex(shape, f - padding); int endIndex = getShapeIndex(shape, f + padding); for (int index = startIndex; index != endIndex; index = (index + 1) % shape.size()) { penalties.at(index) = true; } if (lastRes) { if (solution.second < 0) { std::swap(lastF, f); } int startIndex = getShapeIndex(shape, lastF); int endIndex = getShapeIndex(shape, f); for (int index = startIndex; index != endIndex; index = (index + 1) % shape.size()) { penalties.at(index) = true; } } lastRes = res; lastF = f; } } int sketcherMinimizer::getShapeIndex( const vector& shape, float floatPosition) const { float normalizedF = floatPosition; while (normalizedF < 0) { normalizedF += 1.f; } while (normalizedF >= 1.f) { normalizedF -= 1.f; } int counter = static_cast(shape.size() * normalizedF); return counter; } vector> sketcherMinimizer::groupResiduesInSSEs( const vector& residues) { // divide residues by chain map> chainsMap; for (auto res : residues) { chainsMap[res->chain].push_back(res); } // order each chain by residue number for (auto& pair : chainsMap) { sort(pair.second.begin(), pair.second.end(), [](const sketcherMinimizerResidue* firstRes, const sketcherMinimizerResidue* secondRes) { return firstRes->resnum < secondRes->resnum; }); } int gap = 3; // split chains in smaller chunks whenever more than gap consecutive // residues are missing vector> returnValue; for (auto& pair : chainsMap) { vector growingChain; for (auto res : pair.second) { if (!growingChain.empty() && (res->resnum - growingChain.back()->resnum > gap || res->chain == " " || res->chain.empty())) { returnValue.push_back(growingChain); growingChain.clear(); } growingChain.push_back(res); } if (!growingChain.empty()) { returnValue.push_back(growingChain); } } return returnValue; } vector sketcherMinimizer::shapeAroundLigand(int crownN) { // return crownN-th crown around ligand float distanceOfFirstCrown = 60; float distanceBetweenCrowns = 60; // find limits const auto& atoms = m_atoms; const auto& bonds = m_bonds; float border = distanceBetweenCrowns * crownN + distanceOfFirstCrown; float minX = atoms[0]->coordinates.x(); float maxX = atoms[0]->coordinates.x(); float minY = atoms[0]->coordinates.y(); float maxY = atoms[0]->coordinates.y(); float maxPocketD = 0; for (auto atom : atoms) { float distance = atom->m_pocketDistance; if (distance > maxPocketD) { maxPocketD = distance; } float newX = atom->coordinates.x(); float newY = atom->coordinates.y(); if (minX > newX) { minX = newX; } if (maxX < newX) { maxX = newX; } if (minY > newY) { minY = newY; } if (maxY < newY) { maxY = newY; } } maxPocketD += 10; // to account for cutoffs at borders minX -= border + maxPocketD; maxX += border + maxPocketD; minY -= border + maxPocketD; maxY += border + maxPocketD; /* run a marching square algorithm on a grid of x_interval spacing */ sketcherMinimizerMarchingSquares ms; float x_interval = 20.f; ms.initialize(minX, maxX, minY, maxY, x_interval); for (unsigned int j = 0; j < ms.getYN(); j++) { for (unsigned int i = 0; i < ms.getXN(); i++) { float pointX = ms.toRealx(static_cast(i)); float pointY = ms.toRealy(static_cast(j)); sketcherMinimizerPointF p(pointX, pointY); float shortestD = -1; for (auto a : atoms) { float dist = a->m_pocketDistance; auto vect = a->coordinates - p; float D = vect.length(); D -= dist + border; if (D < shortestD || shortestD < 0) { shortestD = D; } } for (auto b : bonds) { sketcherMinimizerPointF sp1(b->startAtom->coordinates); sketcherMinimizerPointF sp2(b->endAtom->coordinates); float distancePercentage = 1.f; float D2 = sketcherMinimizerMaths::squaredDistancePointSegment( p, sp1, sp2, &distancePercentage); float D = sqrt(D2); float distance2 = b->startAtom->m_pocketDistance; float distance1 = b->endAtom->m_pocketDistance; float dist = distance1 * distancePercentage + distance2 * (1 - distancePercentage); D -= dist + border; if (D < shortestD) { shortestD = D; } } ms.setValue(shortestD, i, j); } } ms.setThreshold(0); ms.run(); auto result = ms.getOrderedCoordinatesPoints(); sort(result.begin(), result.end(), [](const vector& firstContour, const vector& secondContour) { return firstContour.size() > secondContour.size(); }); vector returnValue; if (!result.empty()) { for (unsigned int i = 0; i < result.at(0).size(); i += 2) { returnValue.emplace_back(result.at(0).at(i), result.at(0).at(i + 1)); } } return returnValue; } float sketcherMinimizer::scoreResiduePosition( int index, const vector& shape, int shapeN, vector&, sketcherMinimizerResidue* residue) { auto position = shape.at(index); float distancePenalty = 0.01f; float clashingLigandAtomsPenalty = 100.f; vector targets; for (auto interactionPartner : residue->residueInteractionPartners) { if (interactionPartner->coordinatesSet) { targets.push_back(interactionPartner); } } float interactionsF = 1.f; if (targets.empty() && residue->m_closestLigandAtom != nullptr) { interactionsF = 0.2f; targets.push_back(residue->m_closestLigandAtom); } float score = 0.f; for (auto target : targets) { int clashingLigandAtoms = 0; for (auto ligandAtom : m_atoms) { if (ligandAtom == target) { continue; } auto ligandAtomPos = ligandAtom->coordinates; float squareDist = sketcherMinimizerMaths::squaredDistancePointSegment( ligandAtomPos, position, target->coordinates); if (squareDist < 40 * 40) { clashingLigandAtoms++; } } auto distance = sketcherMinimizerMaths::squaredDistance( target->coordinates, position) - (shapeN * 50) * (shapeN * 50); score += interactionsF * (distancePenalty * distance + clashingLigandAtoms * clashingLigandAtomsPenalty); } return score; } void sketcherMinimizer::placeResidues( const vector& atoms) { if (m_residues.empty()) { return; } if (atoms.empty()) { placeResiduesProteinOnlyMode(); return; } findClosestAtomToResidues(atoms); placeResiduesInCrowns(); m_minimizer.minimizeResidues(); } /* move mol around to avoid clashes with other already placed molecules. Explore a grid of @levels concentric levels, with #gridD resolution. @distanceFromAtoms is the minimum clash distance to reject a position. */ sketcherMinimizerPointF sketcherMinimizer::exploreMolPosition(sketcherMinimizerMolecule* mol, unsigned int levels, float gridD, float distanceFromAtoms) { sketcherMinimizerPointF v(0, 0), centerOfGrid(0, 0); for (unsigned int i = 0; i < levels; i++) { vector pointstoTest; sketcherMinimizerPointF top = centerOfGrid + sketcherMinimizerPointF(0.f, (1 + i) * gridD); sketcherMinimizerPointF bottom = centerOfGrid + sketcherMinimizerPointF(0.f, -((1 + i) * gridD)); sketcherMinimizerPointF right = centerOfGrid + sketcherMinimizerPointF((1 + i) * gridD, 0.f); sketcherMinimizerPointF left = centerOfGrid + sketcherMinimizerPointF(-((1 + i) * gridD), 0.f); pointstoTest.push_back(centerOfGrid); pointstoTest.push_back(right); pointstoTest.push_back(left); pointstoTest.push_back(bottom); pointstoTest.push_back(top); for (unsigned int j = 0; j < i; j++) { pointstoTest.push_back( right + sketcherMinimizerPointF(0.f, gridD * (j + 1))); pointstoTest.push_back( right - sketcherMinimizerPointF(0.f, gridD * (j + 1))); pointstoTest.push_back( left + sketcherMinimizerPointF(0.f, gridD * (j + 1))); pointstoTest.push_back( left - sketcherMinimizerPointF(0.f, gridD * (j + 1))); pointstoTest.push_back( bottom + sketcherMinimizerPointF(gridD * (j + 1), 0.f)); pointstoTest.push_back( bottom - sketcherMinimizerPointF(gridD * (j + 1), 0.f)); pointstoTest.push_back( top + sketcherMinimizerPointF(gridD * (j + 1), 0.f)); pointstoTest.push_back( top - sketcherMinimizerPointF(gridD * (j + 1), 0.f)); } pointstoTest.push_back( centerOfGrid + sketcherMinimizerPointF((1 + i) * gridD, (1 + i) * gridD)); pointstoTest.push_back( centerOfGrid + sketcherMinimizerPointF((1 + i) * gridD, -((1 + i) * gridD))); pointstoTest.push_back( centerOfGrid + sketcherMinimizerPointF(-((1 + i) * gridD), (1 + i) * gridD)); pointstoTest.push_back( centerOfGrid + sketcherMinimizerPointF(-((1 + i) * gridD), -((1 + i) * gridD))); bool noClash = true; if (distanceFromAtoms < 0) { distanceFromAtoms = bondLength * 1.8; } float dist = distanceFromAtoms; for (const auto& pc : pointstoTest) { noClash = true; v = pc; for (sketcherMinimizerAtom* at : mol->_atoms) { sketcherMinimizerPointF placeNextTo = at->coordinates + v; for (sketcherMinimizerMolecule* m : m_molecules) { if (!m->isPlaced) { continue; } if (m == mol) { continue; } for (sketcherMinimizerAtom* a : m->_atoms) { dist = distanceFromAtoms; if (((a->coordinates.x() < placeNextTo.x() + dist) && (a->coordinates.x() > placeNextTo.x() - dist)) && ((a->coordinates.y() < placeNextTo.y() + dist) && (a->coordinates.y() > placeNextTo.y() - dist))) { noClash = false; break; } } if (!noClash) { break; } } if (!noClash) { break; } } if (noClash) { break; } } if (noClash) { break; } } return v; } sketcherMinimizerPointF sketcherMinimizer::exploreGridAround( const sketcherMinimizerPointF& centerOfGrid, unsigned int levels, float gridD, float dx, float dy, float distanceFromAtoms, bool watermap, sketcherMinimizerResidue* residueForInteractions, const sketcherMinimizerPointF& direction) { sketcherMinimizerPointF placeNextTo = centerOfGrid; for (unsigned int i = 0; i < levels; i++) { vector pointstoTest; sketcherMinimizerPointF top = centerOfGrid + sketcherMinimizerPointF(0.f, (1 + i) * gridD); sketcherMinimizerPointF bottom = centerOfGrid + sketcherMinimizerPointF(0.f, -((1 + i) * gridD)); sketcherMinimizerPointF right = centerOfGrid + sketcherMinimizerPointF((1 + i) * gridD, 0.f); sketcherMinimizerPointF left = centerOfGrid + sketcherMinimizerPointF(-((1 + i) * gridD), 0.f); pointstoTest.push_back(centerOfGrid); pointstoTest.push_back(right); pointstoTest.push_back(left); pointstoTest.push_back(bottom); pointstoTest.push_back(top); for (unsigned int j = 0; j < i; j++) { pointstoTest.push_back( right + sketcherMinimizerPointF(0.f, gridD * (j + 1))); pointstoTest.push_back( right - sketcherMinimizerPointF(0.f, gridD * (j + 1))); pointstoTest.push_back( left + sketcherMinimizerPointF(0.f, gridD * (j + 1))); pointstoTest.push_back( left - sketcherMinimizerPointF(0.f, gridD * (j + 1))); pointstoTest.push_back( bottom + sketcherMinimizerPointF(gridD * (j + 1), 0.f)); pointstoTest.push_back( bottom - sketcherMinimizerPointF(gridD * (j + 1), 0.f)); pointstoTest.push_back( top + sketcherMinimizerPointF(gridD * (j + 1), 0.f)); pointstoTest.push_back( top - sketcherMinimizerPointF(gridD * (j + 1), 0.f)); } pointstoTest.push_back( centerOfGrid + sketcherMinimizerPointF((1 + i) * gridD, (1 + i) * gridD)); pointstoTest.push_back( centerOfGrid + sketcherMinimizerPointF((1 + i) * gridD, -((1 + i) * gridD))); pointstoTest.push_back( centerOfGrid + sketcherMinimizerPointF(-((1 + i) * gridD), (1 + i) * gridD)); pointstoTest.push_back( centerOfGrid + sketcherMinimizerPointF(-((1 + i) * gridD), -((1 + i) * gridD))); bool noClash = true; if (distanceFromAtoms < 0) { distanceFromAtoms = bondLength * 1.8; } float distanceFromResidues = bondLength * 1.3; float watermapDistance = 10; float dist = distanceFromAtoms; sketcherMinimizerPointF directionNormal(-direction.y(), direction.x()); directionNormal.normalize(); for (const auto& pc : pointstoTest) { noClash = true; sketcherMinimizerPointF point = pc - centerOfGrid; placeNextTo = point.y() * direction + point.x() * directionNormal + centerOfGrid; for (sketcherMinimizerMolecule* m : m_molecules) { if (!m->isPlaced) { continue; } for (sketcherMinimizerAtom* a : m->_atoms) { if (a->isResidue()) { dist = distanceFromResidues; } else { dist = distanceFromAtoms; } if (watermap) { if (!a->isResidue()) { continue; } dist = watermapDistance; } if (((a->coordinates.x() < placeNextTo.x() + dist + dx) && (a->coordinates.x() > placeNextTo.x() - dist - dx)) && ((a->coordinates.y() < placeNextTo.y() + dist + dy) && (a->coordinates.y() > placeNextTo.y() - dist - dy))) { noClash = false; break; } if (residueForInteractions) { for (auto partnerOfA : a->residueInteractionPartners) { if (a == residueForInteractions || partnerOfA == residueForInteractions || !a->coordinatesSet || !partnerOfA->coordinatesSet) { continue; } float squareD = sketcherMinimizerMaths:: squaredDistancePointSegment( placeNextTo, a->coordinates, partnerOfA->coordinates); if (squareD < distanceFromResidues * distanceFromResidues) { noClash = false; break; } for (auto partner : residueForInteractions ->residueInteractionPartners) { if (!partner->coordinatesSet) { continue; } if (sketcherMinimizerMaths:: intersectionOfSegments( placeNextTo, partner->coordinates, a->coordinates, partnerOfA->coordinates)) { noClash = false; break; } } } } } if (!noClash) { break; } } if (noClash) { break; } } if (noClash) { break; } } return placeNextTo; } vector sketcherMinimizer::buildProximityDataVector( vector& proximityMols, map& molMap) { vector proximityDataVector; for (sketcherMinimizerMolecule* mol : proximityMols) { proximityData data; sketcherMinimizerAtom* metaAtom = molMap[mol]; vector additionVectors( metaAtom->neighbors.size(), sketcherMinimizerPointF(0.f, 0.f)); vector centers( metaAtom->neighbors.size(), sketcherMinimizerPointF(0.f, 0.f)); vector counters(metaAtom->neighbors.size(), 0); for (sketcherMinimizerBond* pr : mol->m_proximityRelations) { sketcherMinimizerAtom* otherMetaAtom = nullptr; sketcherMinimizerAtom* targetAtom = nullptr; if (pr->startAtom->molecule == mol && !(pr->endAtom->molecule == mol)) { otherMetaAtom = molMap[pr->endAtom->molecule]; targetAtom = pr->startAtom; } else if (pr->endAtom->molecule == mol && !(pr->startAtom->molecule == mol)) { otherMetaAtom = molMap[pr->startAtom->molecule]; targetAtom = pr->endAtom; } if (otherMetaAtom) { for (unsigned int i = 0; i < metaAtom->neighbors.size(); i++) { if (metaAtom->neighbors[i] == otherMetaAtom) { additionVectors[i] += targetAtom->getSingleAdditionVector(); centers[i] += targetAtom->coordinates; counters[i]++; } } } } for (unsigned int i = 0; i < centers.size(); i++) { if (counters[i] > 0) { centers[i] /= counters[i]; } additionVectors[i].normalize(); } data.additionVectors = additionVectors; data.centers = centers; data.counters = counters; proximityDataVector.push_back(data); } return proximityDataVector; } void sketcherMinimizer::rotateMoleculesWithProximityRelations( vector& proximityMols, map& molMap, vector& proximityDataVector) { for (unsigned int m = 0; m < proximityMols.size(); m++) { sketcherMinimizerMolecule* mol = proximityMols[m]; sketcherMinimizerAtom* metaAtom = molMap[mol]; vector additionVectors = proximityDataVector[m].additionVectors; vector centers = proximityDataVector[m].centers; if (mol->_atoms.size() < 2) { continue; } sketcherMinimizerPointF direction(1, 0); if (metaAtom->bonds.size() == 1) { direction = metaAtom->coordinates - metaAtom->neighbors[0]->coordinates; sketcherMinimizerPointF p1 = additionVectors[0]; p1 *= -1; sketcherMinimizerPointF p3 = direction; float rotationAngle = sketcherMinimizerMaths::signedAngle( p1, sketcherMinimizerPointF(0, 0), p3); rotationAngle *= static_cast(-M_PI / 180.f); float s = sin(rotationAngle); float c = cos(rotationAngle); for (sketcherMinimizerAtom* a : mol->_atoms) { sketcherMinimizerPointF coords = a->coordinates - centers[0]; coords.rotate(s, c); a->coordinates = coords + centers[0]; } } else if (metaAtom->bonds.size() > 1) { vector v1, v2; for (sketcherMinimizerAtom* n : metaAtom->neighbors) { v1.push_back(n->coordinates - metaAtom->coordinates); } v2 = additionVectors; float rotMat[4]; alignmentMatrix(v1, v2, rotMat); sketcherMinimizerPointF center = mol->center(); for (sketcherMinimizerAtom* a : mol->_atoms) { sketcherMinimizerPointF coords = a->coordinates - center; float x = coords.x(); float y = coords.y(); sketcherMinimizerPointF newCoords(x * rotMat[0] + y * rotMat[1], x * rotMat[2] + y * rotMat[3]); a->coordinates = center + newCoords; } } } } void sketcherMinimizer::translateMoleculesWithProximityRelations( vector& proximityMols, map& molMap, map& templateCenters, vector&) { // placing int counterN = 1; bool cleverPlacing = false; do { cleverPlacing = !cleverPlacing; // alternatively try to be smart aboout // single atom mols if (!cleverPlacing) { counterN++; } for (auto mol : proximityMols) { bool residue = false; if (mol->_atoms.size() == 1) { if (mol->_atoms[0]->isResidue()) { residue = true; } } if (!residue) { if (mol->hasConstrainedFragments) { mol->isPlaced = true; continue; } } if (mol->hasFixedFragments) { mol->isPlaced = true; continue; } if (!mol->m_proximityRelations.empty()) { sketcherMinimizerPointF atomsCenter = sketcherMinimizerPointF(0, 0); int atomsN = 0; for (sketcherMinimizerBond* pr : mol->m_proximityRelations) { if (pr->startAtom->molecule == mol && pr->endAtom->molecule != mol) { atomsCenter += pr->startAtom->coordinates; atomsN++; } else if (pr->endAtom->molecule == mol && pr->startAtom->molecule != mol) { atomsCenter += pr->endAtom->coordinates; atomsN++; } } if (atomsN > 0) { atomsCenter /= atomsN; } /* positioning */ sketcherMinimizerPointF placeNextTo = templateCenters[mol]; placeNextTo *= counterN; for (sketcherMinimizerAtom* a : mol->_atoms) { a->coordinates += placeNextTo - atomsCenter; } mol->isPlaced = true; } } if (cleverPlacing) { // replace single terminal atoms for (auto mol : proximityMols) { if (mol->_atoms.size() == 1) { sketcherMinimizerAtom* metaAtom = molMap[mol]; if (metaAtom->neighbors.size() == 1) { int bondsN = 0; sketcherMinimizerPointF coords(0, 0); for (sketcherMinimizerBond* pr : mol->m_proximityRelations) { if (pr->startAtom->molecule == mol && pr->endAtom->molecule != mol) { sketcherMinimizerPointF addV = pr->endAtom->getSingleAdditionVector(); if (addV.length() < SKETCHER_EPSILON) { continue; } addV.normalize(); addV *= bondLength * counterN; coords += pr->endAtom->coordinates + addV; bondsN++; } else if (pr->endAtom->molecule == mol && pr->startAtom->molecule != mol) { sketcherMinimizerPointF addV = pr->startAtom->getSingleAdditionVector(); if (addV.length() < SKETCHER_EPSILON) { continue; } addV.normalize(); addV *= bondLength * counterN; coords += pr->startAtom->coordinates + addV; bondsN++; } } if (bondsN > 0) { coords /= bondsN; mol->_atoms[0]->coordinates = coords; } else { // a suitable addition Vector could not be // found, try positionings a bondlength to the // right of a proximity partner for (sketcherMinimizerBond* pr : mol->m_proximityRelations) { if (pr->startAtom->molecule == mol && pr->endAtom->molecule != mol) { mol->_atoms[0]->coordinates = pr->endAtom->coordinates; break; } else if (pr->endAtom->molecule == mol && pr->startAtom->molecule != mol) { mol->_atoms[0]->coordinates = pr->startAtom->coordinates; break; } } } } } } } } while (m_minimizer.findIntermolecularClashes(proximityMols, bondLength * 0.5) && counterN < 10); } void sketcherMinimizer::placeMoleculesWithProximityRelations( vector proximityMols) { map molMap; auto* metaMol = new sketcherMinimizerMolecule; for (sketcherMinimizerMolecule* mol : m_molecules) { if (!mol->m_proximityRelations.empty()) { auto* a = new sketcherMinimizerAtom; a->molecule = metaMol; metaMol->_atoms.push_back(a); molMap[mol] = a; } } for (sketcherMinimizerBond* b : m_proximityRelations) { if (b->startAtom->molecule == b->endAtom->molecule) { continue; } sketcherMinimizerAtom* at1 = molMap[b->startAtom->molecule]; sketcherMinimizerAtom* at2 = molMap[b->endAtom->molecule]; bool found = false; for (sketcherMinimizerBond* b : metaMol->_bonds) { if ((b->startAtom == at1 && b->endAtom == at2) || (b->startAtom == at2 && b->endAtom == at1)) { found = true; } } if (!found) { auto* newBond = new sketcherMinimizerBond; newBond->startAtom = at1; newBond->endAtom = at2; metaMol->_bonds.push_back(newBond); } } sketcherMinimizer min(m_minimizer.getPrecision()); if (!metaMol->_atoms.empty()) { min.setEvenAngles(true); min.initialize(metaMol); min.findFragments(); min.buildFromFragments(true); min.m_minimizer.avoidClashes(); min.bestRotation(); min.maybeFlip(); min.arrangeMultipleMolecules(); } bool ligandResidueStyle = true; // positions of molecules are determined // more by a bigger central molecule than by // a bonding pattern for (auto molecule : min.m_molecules) { if (!molecule->_rings.empty()) { // if at least three molecules are connected to each other // (i.e. two residues are connected to each other and both to // the ligand) abort the ligandResidue display style) ligandResidueStyle = false; } } sketcherMinimizerMolecule* centralMol = proximityMols[0]; for (sketcherMinimizerMolecule* mol : proximityMols) { if (mol->m_proximityRelations.size() > centralMol->m_proximityRelations.size()) { centralMol = mol; } else if (mol->m_proximityRelations.size() == centralMol->m_proximityRelations.size() && mol->_atoms.size() > centralMol->_atoms.size()) { centralMol = mol; } } if (centralMol->_atoms.size() < MINIMUM_LIGAND_ATOMS) { ligandResidueStyle = false; } map templateCenters; for (sketcherMinimizerMolecule* mol : proximityMols) { sketcherMinimizerPointF point(0, 0); sketcherMinimizerAtom* at = molMap[mol]; if (at) { point = at->coordinates; } templateCenters[mol] = point; } if (ligandResidueStyle) { queue q; map getParent; q.push(centralMol); while (!q.empty()) { sketcherMinimizerMolecule* mol = q.front(); q.pop(); if (mol->isPlaced) { continue; } if (mol == centralMol) { mol->isPlaced = true; } else { sketcherMinimizerMolecule* parent = getParent[mol]; if (parent != nullptr) { placeMolResidueLigandStyle(mol, parent); } } for (sketcherMinimizerBond* b : mol->m_proximityRelations) { if (!b->startAtom->molecule ->isPlaced) { // will place a molecule twice if it has // two relations with mol. This is safe // cause of the continue for mol->isPlace // when looping the second time q.push(b->startAtom->molecule); getParent[b->startAtom->molecule] = mol; } if (!b->endAtom->molecule->isPlaced) { q.push(b->endAtom->molecule); getParent[b->endAtom->molecule] = mol; } } } } else { vector proximityDataVector = buildProximityDataVector(proximityMols, molMap); rotateMoleculesWithProximityRelations(proximityMols, molMap, proximityDataVector); translateMoleculesWithProximityRelations( proximityMols, molMap, templateCenters, proximityDataVector); } } void sketcherMinimizer::placeMolResidueLigandStyle( sketcherMinimizerMolecule* mol, sketcherMinimizerMolecule* parent) { int n = 0; sketcherMinimizerPointF parentV(0, 0); sketcherMinimizerPointF parentAdditionV(0, 0); sketcherMinimizerPointF v(0, 0); sketcherMinimizerPointF additionV(0, 0); // actually using line to centroid, to // orient the molecule away from the // ligand sketcherMinimizerPointF cent = mol->center(); for (sketcherMinimizerBond* b : mol->m_proximityRelations) { sketcherMinimizerAtom *at = nullptr, *parentAt = nullptr; if (b->startAtom->molecule == parent) { parentAt = b->startAtom; at = b->endAtom; } else if (b->endAtom->molecule == parent) { at = b->startAtom; parentAt = b->endAtom; } if (at == nullptr || parentAt == nullptr) { continue; } n++; sketcherMinimizerPointF paddV = parentAt->getSingleAdditionVector(); if (b->isResidueInteraction()) { auto* ri = static_cast(b); if (ri->startAtom->molecule == parent && !ri->m_otherStartAtoms.empty()) { paddV = sketcherMinimizerAtom::getSingleAdditionVector( ri->getAllStartAtoms()); } else if (ri->endAtom->molecule == parent && !ri->m_otherEndAtoms.empty()) { paddV = sketcherMinimizerAtom::getSingleAdditionVector( ri->getAllEndAtoms()); } } paddV.normalize(); paddV *= bondLength * 3; parentV += parentAt->coordinates; parentAdditionV += paddV; additionV += at->coordinates - cent; v += at->coordinates; } if (n > 0) { v /= n; parentV /= n; parentAdditionV /= n; additionV /= n; sketcherMinimizerPointF startingPos = parentV + parentAdditionV; startingPos = exploreGridAround(startingPos, 15, 10); auto signedAngle = sketcherMinimizerMaths::signedAngle( startingPos - parentV, sketcherMinimizerPointF(0, 0), -additionV); auto angle = static_cast(signedAngle / 180 * M_PI); float s = sin(angle); float c = cos(angle); for (sketcherMinimizerAtom* a : mol->_atoms) { a->coordinates -= v; a->coordinates.rotate(s, c); a->coordinates += startingPos; a->coordinates.round(); } flipIfCrossingInteractions(mol); sketcherMinimizerPointF avoidClashV = exploreMolPosition( mol, 15, bondLength * 0.5); // explore positions on a grid of points to solve clashes for (sketcherMinimizerAtom* a : mol->_atoms) { a->coordinates += avoidClashV; } } mol->isPlaced = true; } void sketcherMinimizer::flipIfCrossingInteractions( sketcherMinimizerMolecule* mol) { for (unsigned int bb = 0; bb < mol->m_proximityRelations.size() - 1; bb++) { bool out = false; sketcherMinimizerBond* pr1 = mol->m_proximityRelations[bb]; if (pr1->startAtom->molecule == pr1->endAtom->molecule) { continue; } if (!(pr1->startAtom->molecule->isPlaced || pr1->startAtom->molecule == mol)) { continue; } if (!(pr1->endAtom->molecule->isPlaced || pr1->endAtom->molecule == mol)) { continue; } for (unsigned int bb2 = bb + 1; bb2 < mol->m_proximityRelations.size(); bb2++) { sketcherMinimizerBond* pr2 = mol->m_proximityRelations[bb2]; if (pr2->startAtom->molecule == pr2->endAtom->molecule) { continue; } if (!(pr2->startAtom->molecule->isPlaced || pr2->startAtom->molecule == mol)) { continue; } if (!(pr2->endAtom->molecule->isPlaced || pr2->endAtom->molecule == mol)) { continue; } if (sketcherMinimizerMaths::intersectionOfSegments( pr1->startAtom->coordinates, pr1->endAtom->coordinates, pr2->startAtom->coordinates, pr2->endAtom->coordinates)) { /* mirror the coordinates */ sketcherMinimizerAtom* p1 = nullptr; sketcherMinimizerAtom* p2 = nullptr; if (pr1->startAtom->molecule == mol) { p1 = pr1->startAtom; } else if (pr1->endAtom->molecule == mol) { p1 = pr1->endAtom; } if (pr2->startAtom->molecule == mol) { p2 = pr2->startAtom; } else if (pr2->endAtom->molecule == mol) { p2 = pr2->endAtom; } if (p1 && p2) { sketcherMinimizerPointF middleP = p1->coordinates + p2->coordinates; middleP *= 0.5; sketcherMinimizerPointF p1p2V = p1->coordinates - p2->coordinates; p1p2V.normalize(); for (sketcherMinimizerAtom* a : mol->_atoms) { sketcherMinimizerPointF v2 = a->coordinates - middleP; float dot = sketcherMinimizerMaths::dotProduct(p1p2V, v2); sketcherMinimizerPointF parallel = p1p2V; parallel *= dot; // parallel component of v2 a->coordinates -= 2 * parallel; a->coordinates.round(); } out = true; break; } } } if (out) { break; } } } void sketcherMinimizer::arrangeMultipleMolecules() { for (auto& _residue : m_residues) { // replace residues _residue->coordinatesSet = false; } if (m_molecules.size() > 1) { // find centers for molecules bound by proximity relations vector proximityMols; for (sketcherMinimizerMolecule* mol : m_molecules) { if (!mol->m_proximityRelations.empty()) { proximityMols.push_back(mol); } } sketcherMinimizerPointF center(0.f, 0.f); if (!proximityMols.empty()) { placeMoleculesWithProximityRelations(proximityMols); } else { int maxI = 0; size_t maxSize = m_molecules[0]->_atoms.size(); for (unsigned int i = 0; i < m_molecules.size(); i++) { sketcherMinimizerMolecule* m = m_molecules[i]; size_t size = m->_atoms.size(); if (size > maxSize) { maxI = i; maxSize = size; } } sketcherMinimizerMolecule* centralMol = m_molecules[maxI]; centralMol->isPlaced = true; for (sketcherMinimizerAtom* a : m_atoms) a->_generalUseVisited = false; // using _generalUseVisited to keep track of charged // atoms that have already been used for counterions center = centralMol->center(); } // placing non counterions bool foundCounterion = true; while (foundCounterion) { foundCounterion = false; for (sketcherMinimizerMolecule* mol : m_molecules) { bool residue = false; if (mol->_atoms.size() == 1) { if (mol->_atoms[0]->isResidue()) { residue = true; } } if (!residue) { if (mol->hasConstrainedFragments) { mol->isPlaced = true; } } if (mol->hasFixedFragments) { mol->isPlaced = true; } if (mol->isPlaced) { continue; } if (residue) { continue; } int charge = mol->totalCharge(); if (charge == 0) { sketcherMinimizerPointF counterionMin, counterionMax; sketcherMinimizerPointF placeNextTo = center; mol->boundingBox(counterionMin, counterionMax); float counteriondx = (counterionMax.x() - counterionMin.x()) * .5f; float counteriondy = (counterionMax.y() - counterionMin.y()) * .5f; sketcherMinimizerPointF counterionCenter = (counterionMax + counterionMin) * .5f; foundCounterion = true; // explore a grid around placeNextTo to find a suitable // place sketcherMinimizerPointF centerOfGrid = placeNextTo; float gridD = bondLength; placeNextTo = exploreGridAround(centerOfGrid, 10, gridD, counteriondx, counteriondy); for (sketcherMinimizerAtom* a : mol->_atoms) { a->coordinates += placeNextTo - counterionCenter; } mol->isPlaced = true; } } } // placing counterions foundCounterion = true; while (foundCounterion) { foundCounterion = false; for (sketcherMinimizerMolecule* mol : m_molecules) { if (mol->isPlaced) { continue; } int charge = mol->totalCharge(); if (charge != 0) { sketcherMinimizerPointF counterionMin, counterionMax; sketcherMinimizerPointF placeNextTo = center; mol->boundingBox(counterionMin, counterionMax); float counteriondx = (counterionMax.x() - counterionMin.x()) * .5f; float counteriondy = (counterionMax.y() - counterionMin.y()) * .5f; sketcherMinimizerPointF counterionCenter = (counterionMax + counterionMin) * .5f; foundCounterion = true; // find an already placed charged atom to place the // counterion next to for (sketcherMinimizerMolecule* m : m_molecules) { bool found = false; if (!m->isPlaced) { continue; } for (sketcherMinimizerAtom* a : m->_atoms) { if (a->charge == 0) { continue; } if (a->_generalUseVisited) { continue; } if (a->charge * charge < 0) { a->_generalUseVisited = true; placeNextTo = a->coordinates; found = true; break; } } if (found) { break; } } // explore a grid around placeNextTo to find a suitable // place sketcherMinimizerPointF centerOfGrid = placeNextTo; float gridD = bondLength; placeNextTo = exploreGridAround(centerOfGrid, 10, gridD, counteriondx, counteriondy, bondLength * 0.8); for (sketcherMinimizerAtom* a : mol->_atoms) { a->coordinates += placeNextTo - counterionCenter; } mol->isPlaced = true; } } } vector ligandAtoms; for (sketcherMinimizerAtom* a : m_atoms) if (a->m_isLigand) { ligandAtoms.push_back(a); } placeResidues(ligandAtoms); } } void sketcherMinimizer::initializeFragments() { if (_fragments.empty()) { cerr << "Sketcherlibs warning: no fragments to initialize" << endl; return; } for (sketcherMinimizerFragment* indf : m_independentFragments) { // recursively assign it to children assignNumberOfChildrenAtomsFromHere(indf); } for (sketcherMinimizerFragment* f : _fragments) { m_fragmentBuilder.initializeCoordinates(f); } for (sketcherMinimizerFragment* indf : m_independentFragments) { // recursively assign it to children assignLongestChainFromHere(indf); } } bool sketcherMinimizer::alignWithParentDirectionConstrained( sketcherMinimizerFragment* fragment, const sketcherMinimizerPointF& position, float angle) { vector templates, plainCoordinates, flippedCoordinates; float sine = sin(angle); float cosine = cos(angle); for (const auto& atom : fragment->_coordinates) { if (atom.first->constrained) { sketcherMinimizerPointF plainCoordinatesAtom = atom.second; sketcherMinimizerPointF flippedCoordinatesAtom( plainCoordinatesAtom.x(), -plainCoordinatesAtom.y()); plainCoordinatesAtom.rotate(sine, cosine); flippedCoordinatesAtom.rotate(sine, cosine); templates.push_back(atom.first->templateCoordinates); plainCoordinates.push_back(plainCoordinatesAtom + position); flippedCoordinates.push_back(flippedCoordinatesAtom + position); } } float scorePlain = roundToTwoDecimalDigits(RMSD(templates, plainCoordinates)); float scoreFlipped = roundToTwoDecimalDigits(RMSD(templates, flippedCoordinates)); return (scoreFlipped < scorePlain); } vector sketcherMinimizer::getAllTerminalBonds(sketcherMinimizerFragment* fragment) { vector bonds; for (auto bond : fragment->getBonds()) { if (bond->isResidueInteraction()) { continue; } if (bond->startAtom->neighbors.size() == 1 || bond->endAtom->neighbors.size() == 1) { bonds.push_back(bond); } } for (auto child : fragment->_children) { bonds.push_back(child->_bondToParent); } if (fragment->getParent()) { bonds.push_back(fragment->_bondToParent); } return bonds; } vector> sketcherMinimizer::findDirectionsToAlignWith( sketcherMinimizerFragment* fragment) { vector> chainDirs; sketcherMinimizerPointF origin = (fragment->_bondToParent->startAtom->coordinates + fragment->_bondToParent->endAtom->coordinates) * 0.5; vector parentEndBonds = getAllTerminalBonds(fragment->getParent()); for (auto bond : parentEndBonds) { if (bond->endAtom->fragment == fragment) { continue; } sketcherMinimizerPointF direction = origin - (bond->startAtom->coordinates + bond->endAtom->coordinates) * 0.5; direction.normalize(); float score = 1.f; if (bond->bondOrder == 2) { score *= SCORE_MULTIPLIER_FOR_DOUBLE_BONDS; } if ((bond->startAtom->neighbors.size() == 1 && bond->startAtom->atomicNumber != 6) || (bond->endAtom->neighbors.size() == 1 && bond->endAtom->atomicNumber != 6)) { score *= SCORE_MULTIPLIER_FOR_SINGLE_BONDED_HETEROATOMS; } if (bond->endAtom->fragment != fragment->getParent() || bond->startAtom->fragment != fragment->getParent()) { score = bond->endAtom->fragment->longestChainFromHere * SCORE_MULTIPLIER_FOR_FRAGMENTS; if (fragment->getParent()->getParent() && bond->startAtom->fragment == fragment->getParent()->getParent()) { score *= 100; } } chainDirs.emplace_back(direction, score); } return chainDirs; } float sketcherMinimizer::testAlignment( const sketcherMinimizerPointF& direction, const std::pair& templat) { float dot = sketcherMinimizerMaths::dotProduct(direction, templat.first); if (dot < 0) { dot = 0; } float score = dot * dot; if (dot > 1 - SKETCHER_EPSILON) { score += 1000; } score *= templat.second; return score; } sketcherMinimizerPointF sketcherMinimizer::scoreDirections( sketcherMinimizerFragment* fragment, float angle, const vector>& directions, bool& invert) { float sine = sin(angle); float cosine = cos(angle); float bestScore = 0.f; sketcherMinimizerPointF bestDirection(1.f, 0.f); vector terminalBonds = getAllTerminalBonds(fragment); for (auto bond : terminalBonds) { if (bond->startAtom->fragment != fragment) { continue; } sketcherMinimizerPointF bondDirectionPlain = (fragment->_coordinates[bond->startAtom] + fragment->_coordinates[bond->endAtom]) * 0.5 - sketcherMinimizerPointF(-bondLength * 0.5, 0); bondDirectionPlain.normalize(); sketcherMinimizerPointF bondDirectionInverted(bondDirectionPlain.x(), -bondDirectionPlain.y()); bondDirectionPlain.rotate(sine, cosine); bondDirectionInverted.rotate(sine, cosine); float scoreModifier = 1.f; if (bond->bondOrder == 2) { scoreModifier *= SCORE_MULTIPLIER_FOR_DOUBLE_BONDS; } if ((bond->startAtom->neighbors.size() == 1 && bond->startAtom->atomicNumber != 6) || (bond->endAtom->neighbors.size() == 1 && bond->endAtom->atomicNumber != 6)) { scoreModifier *= SCORE_MULTIPLIER_FOR_SINGLE_BONDED_HETEROATOMS; } if (bond->endAtom->fragment != fragment) { scoreModifier = bond->endAtom->fragment->longestChainFromHere * SCORE_MULTIPLIER_FOR_FRAGMENTS; } for (const auto& direction : directions) { float scorePlain = testAlignment(bondDirectionPlain, direction) * scoreModifier; if (scorePlain > bestScore) { bestScore = scorePlain; bestDirection = direction.first; invert = false; } float scoreInverted = testAlignment(bondDirectionInverted, direction) * scoreModifier; if (scoreInverted > bestScore) { bestScore = scoreInverted; bestDirection = direction.first; invert = true; } } } return bestDirection; } bool sketcherMinimizer::alignWithParentDirectionUnconstrained( sketcherMinimizerFragment* fragment, float angle) { vector> directions = findDirectionsToAlignWith(fragment); bool invert = false; scoreDirections(fragment, angle, directions, invert); return invert; } void sketcherMinimizer::alignWithParentDirection( sketcherMinimizerFragment* f, const sketcherMinimizerPointF& position, float angle) { // deciding which "side" the fragment will be drawn, rotating 180° around // the axis of its bond to parent if (f->fixed) { return; } bool invert = (f->constrained ? alignWithParentDirectionConstrained(f, position, angle) : alignWithParentDirectionUnconstrained(f, angle)); if (invert) { for (auto& atom : f->_coordinates) { atom.second.setY(-atom.second.y()); } for (auto atom : f->getAtoms()) { if (atom->hasStereochemistrySet) { for (auto bond : atom->bonds) { bond->isWedge = !bond->isWedge; } } } } } void sketcherMinimizer::assignNumberOfChildrenAtomsFromHere( sketcherMinimizerFragment* f) { size_t cumulatedNumberOfAtoms = 0; float cumulatedNumberOfAtomsRanks = 0; size_t childrenAtoms = 0; for (sketcherMinimizerFragment* child : f->_children) { assignNumberOfChildrenAtomsFromHere(child); cumulatedNumberOfAtoms += child->numberOfChildrenAtoms; cumulatedNumberOfAtomsRanks += child->numberOfChildrenAtomsRank; childrenAtoms += child->getAtoms().size(); } f->numberOfChildrenAtoms = cumulatedNumberOfAtoms + childrenAtoms; f->numberOfChildrenAtomsRank = static_cast(0.01f * cumulatedNumberOfAtomsRanks + childrenAtoms); } void sketcherMinimizer::assignLongestChainFromHere(sketcherMinimizerFragment* f) { float longestDist = 0; for (sketcherMinimizerFragment* child : f->_children) { assignLongestChainFromHere(child); if (child->longestChainFromHere > longestDist) { longestDist = child->longestChainFromHere; } } sketcherMinimizerPointF positionFromParent(0.f, 0.f); if (f->getParent()) { positionFromParent = f->getParent()->_coordinates[f->_bondToParent->endAtom]; } f->longestChainFromHere = longestDist + positionFromParent.length(); } sketcherMinimizerBond* sketcherMinimizer::getBond(const sketcherMinimizerAtom* a1, const sketcherMinimizerAtom* a2) { for (unsigned int i = 0; i < a1->neighbors.size(); i++) { if (a1->neighbors[i] == a2) { return a1->bonds[i]; } } return nullptr; } sketcherMinimizerAtom* sketcherMinimizer::pickBestAtom(vector& atoms) { vector candidates, oldCandidates; { size_t biggestSize = atoms[0]->fragment->numberOfChildrenAtoms; for (sketcherMinimizerAtom* a : atoms) { size_t size = a->fragment->numberOfChildrenAtoms; if (size == biggestSize) { candidates.push_back(a); } else if (size > biggestSize) { biggestSize = size; candidates.clear(); candidates.push_back(a); } } if (candidates.size() == 1) { return candidates[0]; } oldCandidates = candidates; candidates.clear(); } { float biggestSize = oldCandidates[0]->fragment->numberOfChildrenAtomsRank; for (sketcherMinimizerAtom* a : oldCandidates) { float size = a->fragment->numberOfChildrenAtomsRank; if (size == biggestSize) { candidates.push_back(a); } else if (size > biggestSize) { biggestSize = size; candidates.clear(); candidates.push_back(a); } } if (candidates.size() == 1) { return candidates[0]; } oldCandidates = candidates; candidates.clear(); } { int biggestSize = oldCandidates[0]->atomicNumber; for (sketcherMinimizerAtom* a : oldCandidates) { int size = a->atomicNumber; if (size == biggestSize) { candidates.push_back(a); } else if (size > biggestSize) { biggestSize = size; candidates.clear(); candidates.push_back(a); } } if (candidates.size() == 1) { return candidates[0]; } oldCandidates = candidates; candidates.clear(); } // give up return oldCandidates[0]; } void sketcherMinimizer::constrainAllAtoms() { // cerr << "sketcherMinimizer::constrainAllAtoms ()"<constrained = true; } void sketcherMinimizer::constrainAtoms(const vector& constrained) { if (constrained.size() == m_referenceAtoms.size()) { for (unsigned int i = 0; i < constrained.size(); i++) { if (constrained[i]) { m_referenceAtoms[i]->constrained = true; } } } else { cerr << "warning, wrong size of vector for constrained atoms. Ignoring" << endl; } } void sketcherMinimizer::fixAtoms(const vector& fixed) { if (fixed.size() == m_referenceAtoms.size()) { for (unsigned int i = 0; i < fixed.size(); i++) { if (fixed[i]) { m_referenceAtoms[i]->fixed = true; } } } else { cerr << "warning, wrong size of vector for fixed atoms. Ignoring" << endl; } } void sketcherMinimizer::findClosestAtomToResidues( const vector& catoms) { const vector& atoms = catoms.empty() ? m_atoms : catoms; for (sketcherMinimizerAtom* r : m_residues) { float squareD = 9999999.f; sketcherMinimizerAtom* closestA = nullptr; for (sketcherMinimizerAtom* a : atoms) { if (!a->isResidue()) { float diffx = a->m_x3D - r->m_x3D; float diffy = a->m_y3D - r->m_y3D; float diffz = a->m_z3D - r->m_z3D; float newSquareD = diffx * diffx + diffy * diffy + diffz * diffz; if (newSquareD < squareD) { squareD = newSquareD; closestA = a; } } } static_cast(r)->m_closestLigandAtom = closestA; if (!r->m_isClashing) { r->m_isClashing = (squareD < RESIDUE_CLASH_DISTANCE_SQUARED); } } for (sketcherMinimizerBond* b : m_bonds) { if (b->startAtom->isResidue()) { static_cast(b->startAtom) ->m_closestLigandAtom = b->endAtom; } if (b->endAtom->isResidue()) { static_cast(b->endAtom) ->m_closestLigandAtom = b->startAtom; } } } float sketcherMinimizer::RMSD(const vector& templates, const vector& points) { assert(templates.size() == points.size()); size_t counter = templates.size(); float total = 0.f; for (unsigned int i = 0; i < templates.size(); i++) { // cerr << templates[i].x () << ", "<< templates[i].y () << " // " << points[i].x()<<", "< 0) { total /= counter; } return sqrt(total); } void sketcherMinimizer::alignmentMatrix( const vector& ref, const vector& points, float* m) { float U[4]; float Sig[4]; float V[4]; float a[4]; a[0] = 0.f; a[1] = 0.f; a[2] = 0.f; a[3] = 0.f; assert(ref.size() == points.size()); for (unsigned int i = 0; i < ref.size(); i++) { a[0] += ref[i].x() * points[i].x(); a[1] += ref[i].y() * points[i].x(); a[2] += ref[i].x() * points[i].y(); a[3] += ref[i].y() * points[i].y(); } svd(a, U, Sig, V); m[0] = V[0] * U[0] + V[1] * U[1]; m[1] = V[0] * U[2] + V[1] * U[3]; m[2] = V[2] * U[0] + V[3] * U[1]; m[3] = V[2] * U[2] + V[3] * U[3]; } void sketcherMinimizer::svd(float* a, float* U, float* Sig, float* V) { float a1[4]; a1[0] = a[0]; a1[1] = a[2]; a1[2] = a[1]; a1[3] = a[3]; float Su[4]; Su[0] = a[0] * a1[0] + a[1] * a1[2]; Su[1] = a[0] * a1[1] + a[1] * a1[3]; Su[2] = a[2] * a1[0] + a[3] * a1[2]; Su[3] = a[2] * a1[1] + a[3] * a1[3]; auto phi = static_cast(0.5 * atan2(Su[1] + Su[2], Su[0] - Su[3])); float cphi = cos(phi); cphi = roundToTwoDecimalDigits(cphi); float sphi = sin(phi); sphi = roundToTwoDecimalDigits(sphi); U[0] = cphi * (-1); U[1] = -sphi; U[2] = sphi * (-1); U[3] = cphi; float Sw[4]; Sw[0] = a1[0] * a[0] + a1[1] * a[2]; Sw[1] = a1[0] * a[1] + a1[1] * a[3]; Sw[2] = a1[2] * a[0] + a1[3] * a[2]; Sw[3] = a1[2] * a[1] + a1[3] * a[3]; auto theta = static_cast(0.5 * atan2(Sw[1] + Sw[2], Sw[0] - Sw[3])); float ctheta = cos(theta); float stheta = sin(theta); float W[4]; W[0] = ctheta; W[1] = -stheta; W[2] = stheta; W[3] = ctheta; float SUsum = Su[0] + Su[3]; float SUdif = sqrt((Su[0] - Su[3]) * (Su[0] - Su[3]) + 4.f * Su[1] * Su[2]); Sig[0] = sqrt((SUsum + SUdif) * 0.5f); Sig[1] = 0.f; Sig[2] = 0.f; Sig[3] = sqrt((SUsum - SUdif) * 0.5f); float U1[4]; U1[0] = U[0]; U1[1] = U[2]; U1[2] = U[1]; U1[3] = U[3]; float U1A[4]; U1A[0] = U1[0] * a[0] + U1[1] * a[2]; U1A[1] = U1[0] * a[1] + U1[1] * a[3]; U1A[2] = U1[2] * a[0] + U1[3] * a[2]; U1A[3] = U1[2] * a[1] + U1[3] * a[3]; float S[4]; S[0] = U1A[0] * W[0] + U1A[1] * W[2]; S[1] = U1A[0] * W[1] + U1A[1] * W[3]; S[2] = U1A[2] * W[0] + U1A[3] * W[2]; S[3] = U1A[2] * W[1] + U1A[3] * W[3]; S[0] = roundToTwoDecimalDigits(S[0]); S[1] = roundToTwoDecimalDigits(S[1]); S[2] = roundToTwoDecimalDigits(S[2]); S[3] = roundToTwoDecimalDigits(S[3]); float sign1 = 1.f, sign2 = 1.f; if (S[0] < 0.f) { sign1 = -1.f; } if (S[3] < 0.f) { sign2 = -1.f; } float C[4]; C[0] = sign1; C[1] = 0.f; C[2] = 0.f; C[3] = sign2; V[0] = W[0] * C[0] + W[1] * C[2]; V[1] = W[0] * C[1] + W[1] * C[3]; V[2] = W[2] * C[0] + W[3] * C[2]; V[3] = W[2] * C[1] + W[3] * C[3]; V[0] = roundToTwoDecimalDigits(V[0]); V[1] = roundToTwoDecimalDigits(V[1]); V[2] = roundToTwoDecimalDigits(V[2]); V[3] = roundToTwoDecimalDigits(V[3]); } bool sketcherMinimizer::compare(const vector& atoms, const vector& bonds, sketcherMinimizerMolecule* templ, vector& mapping) { if (atoms.size() != templ->_atoms.size()) { return false; } vector molScores, tempScores; int molIter = morganScores(atoms, bonds, molScores); int templateIter = morganScores(templ->_atoms, templ->_bonds, tempScores); if (molIter != templateIter) { return false; } size_t size = atoms.size(); vector matrix(size * size, false); vector templateCoordinates; vector> molBonds; vector> templateBonds; // for double bond chirality // vector < vector < int > > templateAllowedZChains; vector> molCisTransChains; vector molIsCis; for (unsigned int ma = 0; ma < size; ma++) { vector vec; molBonds.push_back(vec); } for (unsigned int ta = 0; ta < size; ta++) { vector vec; templateBonds.push_back(vec); } for (unsigned int ta = 0; ta < size; ta++) { templateCoordinates.push_back(templ->_atoms[ta]->coordinates); } for (auto bond : bonds) { if (bond->bondOrder == 2) { sketcherMinimizerBond* b = bond; if (b->m_ignoreZE) { continue; } bool ok = false; if (b->rings.empty()) { ok = true; } else { ok = true; for (auto& ring : b->rings) { if (ring->_atoms.size() < MACROCYCLE) { ok = false; } } } if (!ok) { continue; } sketcherMinimizerAtom* startA = b->startAtomCIPFirstNeighbor(); sketcherMinimizerAtom* endA = b->endAtomCIPFirstNeighbor(); sketcherMinimizerAtom* startN = nullptr; sketcherMinimizerAtom* endN = nullptr; for (unsigned int i = 0; i < b->startAtom->neighbors.size(); i++) { if (b->startAtom->neighbors[i] == b->endAtom) { continue; } bool found = false; for (auto atom : atoms) { if (atom == b->startAtom->neighbors[i]) { startN = b->startAtom->neighbors[i]; found = true; break; } } if (found) { break; } } for (unsigned int i = 0; i < b->endAtom->neighbors.size(); i++) { if (b->endAtom->neighbors[i] == b->startAtom) { continue; } bool found = false; for (auto atom : atoms) { if (atom == b->endAtom->neighbors[i]) { endN = b->endAtom->neighbors[i]; found = true; break; } } if (found) { break; } } if (startN && endN && startA && endA) { bool isCis = b->isZ; if (startN != startA) { isCis = !isCis; } if (endN != endA) { isCis = !isCis; } vector chain; chain.push_back(startN->_generalUseN); chain.push_back(b->startAtom->_generalUseN); chain.push_back(b->endAtom->_generalUseN); chain.push_back(endN->_generalUseN); molCisTransChains.push_back(chain); molIsCis.push_back(isCis); // cerr << "chiral double bond" <isZ<startAtom->_generalUseN; size_t in2 = bond->endAtom->_generalUseN; if (in1 < in2) { molBonds[in2].push_back(in1); } else { molBonds[in1].push_back(in2); } } for (auto& _bond : templ->_bonds) { size_t in1 = _bond->startAtom->_generalUseN; size_t in2 = _bond->endAtom->_generalUseN; if (in1 < in2) { templateBonds[in2].push_back(in1); } else { templateBonds[in1].push_back(in2); } } for (unsigned int ma = 0; ma < atoms.size(); ma++) { for (unsigned int ta = 0; ta < templ->_atoms.size(); ta++) { if (molScores[ma] == tempScores[ta]) { matrix[ma * size + ta] = true; } } } bool found = false; vector solution; for (unsigned int i = 0; i < size; i++) { if (!matrix[i]) { continue; } checkIdentity(solution, i, matrix, templateCoordinates, molBonds, templateBonds, molCisTransChains, molIsCis, size, found, mapping); if (found) { break; } } return found; } void sketcherMinimizer::checkIdentity( vector solution, int newSol, vector& matrix, vector& templateCoordinates, vector>& molBonds, vector>& templateBonds, vector>& molCisTransChains, vector& molIsCis, size_t size, bool& found, vector& mapping) { solution.push_back(newSol); if (solution.size() == size) { // check double bonds stereo bool doubleBondsStereoOk = true; for (size_t i = 0; i < molCisTransChains.size(); i++) { sketcherMinimizerPointF p1 = templateCoordinates[solution[molCisTransChains[i][0]]]; sketcherMinimizerPointF p2 = templateCoordinates[solution[molCisTransChains[i][1]]]; sketcherMinimizerPointF p3 = templateCoordinates[solution[molCisTransChains[i][2]]]; sketcherMinimizerPointF p4 = templateCoordinates[solution[molCisTransChains[i][3]]]; if (molIsCis[i] != sketcherMinimizerMaths::sameSide(p1, p4, p2, p3)) { doubleBondsStereoOk = false; break; } } if (doubleBondsStereoOk) { found = true; mapping = solution; } } else { for (unsigned int i = 0; i < size; i++) { if (found) { break; } if (!(matrix[solution.size() * size + i])) { continue; } bool check = true; for (unsigned int ss : solution) { if (ss == i) { check = false; break; } } if (check) { for (const auto& molBond : molBonds[solution.size()]) { check = false; unsigned int high = i; unsigned int low = solution[molBond]; if (low > high) { std::swap(low, high); } for (auto ch : templateBonds[high]) { if (ch == low) { check = true; break; } } if (!check) { break; } } } if (check) { checkIdentity(solution, i, matrix, templateCoordinates, molBonds, templateBonds, molCisTransChains, molIsCis, size, found, mapping); } } } } void sketcherMinimizer::setTemplateFileDir(string dir) { sketcherMinimizer::m_templates.setTemplateDir(std::move(dir)); } static void normalizeTemplate(sketcherMinimizerMolecule* mol) { // normalize bond length and set _generalUseN on atoms. vector dds; vector ns; for (auto& _bond : mol->_bonds) { sketcherMinimizerPointF v = _bond->startAtom->coordinates - _bond->endAtom->coordinates; float dd = v.x() * v.x() + v.y() * v.y(); bool found = false; for (unsigned int j = 0; j < dds.size(); ++j) { if (dd * 0.9 < dds[j] && dd * 1.1 > dds[j]) { ++ns[j]; found = true; break; } } if (!found) { dds.push_back(dd); ns.push_back(1); } } if (!dds.empty()) { int maxI = 0; for (unsigned int i = 0; i < ns.size(); ++i) { if (ns[i] > ns[maxI]) { maxI = i; } } float f = sqrt(dds[maxI]); for (unsigned int i = 0; i < mol->_atoms.size(); ++i) { mol->_atoms[i]->coordinates /= f; mol->_atoms[i]->_generalUseN = i; } } } #ifdef USE_MAEPARSER static string getTempFileProjDir() { return sketcherMinimizer::m_templates.getTemplateDir(); } static string getUserTemplateFileName() { const string suffix = "user_templates.mae"; // whatever you wish return getTempFileProjDir() + suffix; } static void loadTemplate(const string& filename, vector& templates) { auto pFile = fopen(filename.c_str(), "r"); if (pFile == nullptr) { return; } schrodinger::mae::Reader r(pFile); std::shared_ptr b; while ((b = r.next(mae::CT_BLOCK)) != nullptr) { auto mol = mol_from_mae_block(*b); normalizeTemplate(mol); templates.push_back(mol); } fclose(pFile); } #endif void sketcherMinimizer::loadTemplates() { static bool loaded = false; if (loaded || !m_templates.getTemplates().empty()) { return; } m_templates.getTemplates() = coordgen_templates(); for (auto* m : m_templates.getTemplates()) { normalizeTemplate(m); } #ifdef USE_MAEPARSER string filename = getUserTemplateFileName(); loadTemplate(filename, m_templates.getTemplates()); #endif loaded = true; } int sketcherMinimizer::morganScores(const vector& atoms, const vector& bonds, vector& oldScores) { // assumes that atom[i]->_generalUseN = i if (atoms.size() < 2) { return 0; } oldScores = vector(atoms.size(), 1); vector newScores(atoms.size(), 0); vector orderedScores; bool goOn = false; int n = 0; size_t idx1, idx2; size_t oldTies = atoms.size(); unsigned int i = 0, j = 0; do { ++n; for (i = 0; i < bonds.size(); ++i) { idx1 = bonds[i]->startAtom->_generalUseN; idx2 = bonds[i]->endAtom->_generalUseN; newScores[idx1] += oldScores[idx2]; newScores[idx2] += oldScores[idx1]; } orderedScores = newScores; stable_sort(orderedScores.begin(), orderedScores.end()); size_t newTies = 0; for (j = 1; j < orderedScores.size(); j++) { if (orderedScores[j] == orderedScores[j - 1]) { newTies++; } } if (newTies < oldTies) { goOn = true; oldTies = newTies; oldScores = newScores; } else { goOn = false; } } while (goOn); return n; } // interactions with m_minimizer and m_fragmentBuilder const std::vector& sketcherMinimizer::getBendInteractions() const { return m_minimizer.getBendInteractions(); } const std::vector& sketcherMinimizer::getStretchInteractions() const { return m_minimizer.getStretchInteractions(); } const std::vector& sketcherMinimizer::getInteractions() const { return m_minimizer.getInteractions(); } std::set sketcherMinimizer::getChetoCs( const std::vector& allAtoms) const { return m_minimizer.getChetoCs(allAtoms); } std::set sketcherMinimizer::getAminoNs( const std::vector& allAtoms) const { return m_minimizer.getAminoNs(allAtoms); } std::set sketcherMinimizer::getAlphaCs( const std::vector& allAtoms, const std::set& chetoCs, const std::set& aminoNs) const { return m_minimizer.getAlphaCs(allAtoms, chetoCs, aminoNs); } void sketcherMinimizer::clearInteractions() { m_minimizer.clearInteractions(); } void sketcherMinimizer::addInteractionsOfMolecule( sketcherMinimizerMolecule* molecule, bool intrafragmentClashes) { m_minimizer.addInteractionsOfMolecule(molecule, intrafragmentClashes); } void sketcherMinimizer::minimizeMolecule(sketcherMinimizerMolecule* molecule) { CoordgenFragmenter::splitIntoFragments(molecule); m_minimizer.minimizeMolecule(molecule); }; void sketcherMinimizer::forceFieldMinimize() { m_minimizer.run(); } void sketcherMinimizer::addExtraInteraction( sketcherMinimizerMolecule* molecule, sketcherMinimizerInteraction* interaction) { m_minimizer.addExtraInteraction(molecule, interaction); } void sketcherMinimizer::setEvenAngles(bool b) { m_fragmentBuilder.m_evenAngles = b; m_minimizer.m_evenAngles = b; } void sketcherMinimizer::setSkipMinimization(bool b) { m_minimizer.skipMinimization = b; } void sketcherMinimizer::setForceOpenMacrocycles(bool b) { m_fragmentBuilder.setForceOpenMacrocycles(b); } void sketcherMinimizer::buildFromFragments(bool b) { m_minimizer.buildFromFragments(b); } bool sketcherMinimizer::avoidClashesOfMolecule( sketcherMinimizerMolecule* molecule, const std::vector& extraInteractions) { return m_minimizer.avoidClashesOfMolecule(molecule, extraInteractions); } void sketcherMinimizer::addExtraBond(sketcherMinimizerBond* bond) { m_extraBonds.push_back(bond); } CoordgenTemplates sketcherMinimizer::m_templates; coordgenlibs-3.0.2/sketcherMinimizer.h000066400000000000000000000524531436654770400200640ustar00rootroot00000000000000#pragma once /* * sketcherMinimizer.h * * Created by Nicola Zonta on 13/04/2010. * Copyright Schrodinger, LLC. All rights reserved. * */ #include #include #include #include "CoordgenConfig.hpp" #include "CoordgenFragmentBuilder.h" #include "CoordgenMinimizer.h" #include "sketcherMinimizerFragment.h" #include "sketcherMinimizerMarchingSquares.h" #include "sketcherMinimizerMolecule.h" #include "sketcherMinimizerResidue.h" #include "sketcherMinimizerResidueInteraction.h" #include "sketcherMinimizerRing.h" static const float SKETCHER_STANDARD_PRECISION = 1.f; static const float SKETCHER_QUICK_PRECISION = 0.2f; static const float SKETCHER_BEST_PRECISION = 3.f; class sketcherMinimimizerInteraction; namespace schrodinger { namespace mae { class Block; } } // namespace schrodinger typedef struct { std::vector additionVectors; std::vector centers; std::vector counters; } proximityData; /* class to handle templates of common difficult ring structures */ class CoordgenTemplates { public: CoordgenTemplates() = default; ~CoordgenTemplates() { for (auto molecule : m_templates) { for (auto atom : molecule->_atoms) { delete atom; } for (auto bond : molecule->_bonds) { delete bond; } delete molecule; } m_templates.clear(); } std::vector& getTemplates() { return m_templates; } void setTemplateDir(std::string&& dir) { m_templateDir = std::move(dir); if (m_templateDir.back() != '/') { m_templateDir += "/"; } } std::string getTemplateDir() { return m_templateDir; } private: std::vector m_templates; std::string m_templateDir = ""; }; /* main class. Creates 2d coordinates for molecular inputs */ class EXPORT_COORDGEN sketcherMinimizer { public: sketcherMinimizer(float precision = SKETCHER_STANDARD_PRECISION); ~sketcherMinimizer(); /* fields used in rdkit */ std::vector _fragments; CoordgenMinimizer m_minimizer; /* run coordinates generation and return true if the pose is considered * optimal */ bool runGenerateCoordinates(); /* initialize data from given molecule */ void initialize(sketcherMinimizerMolecule* minMol); /* run a force-field based minimization on the given molecule */ void minimizeMolecule(sketcherMinimizerMolecule* molecule); // void initializeFromMolecule(ChmMol& mol); void writeMinimizationData(); /* run a force-field based minimization */ void forceFieldMinimize(); /* if mol contains separate molecules, split them into a vector */ void splitIntoMolecules(sketcherMinimizerMolecule* mol, std::vector& mols); /* split molecules into rigid fragments */ void findFragments(); /* constrain coordinates on all atoms */ void constrainAllAtoms(); /* constrain coordinates on atoms corresponding to true */ void constrainAtoms(const std::vector& constrained); /* fix cooordinates (i.e. guarantee they will not change) on atoms marked as * true */ void fixAtoms(const std::vector& fixed); /* set a flag to enable/disable the scoring of interactions with residues */ void setScoreResidueInteractions(bool b); /* add bond to m_extrabonds */ void addExtraBond(sketcherMinimizerBond* bond); /* getters */ const std::vector& getAtoms() const { return m_atoms; } const std::vector& getMolecules() const { return m_molecules; } const std::vector& getReferenceAtoms() const { return m_referenceAtoms; } const std::vector& getReferenceBonds() const { return m_referenceBonds; } const std::vector& getIndependentFragments() const { return m_independentFragments; } bool getTreatNonterminalBondsToMetalAsZOBs() const {return m_treatNonterminalBondsToMetalAsZOBs;} const std::vector& getBendInteractions() const; const std::vector& getStretchInteractions() const; const std::vector& getInteractions() const; /* setters */ void setFragments(std::vector fragments) { _fragments = fragments; } void setTreatNonterminalBondsToMetalAsZOBs(bool b) {m_treatNonterminalBondsToMetalAsZOBs = b;} void setEvenAngles(bool b); void setSkipMinimization(bool b); void setForceOpenMacrocycles(bool b); /// Interactions with CoordgenMinimizer and CoordgenFragmentBuilder /* find a list of carbons from the backbone C=O of a peptide */ std::set getChetoCs(const std::vector& allAtoms) const; /* find a list of nitrogens from the backbon NH of a peptide */ std::set getAminoNs(const std::vector& allAtoms) const; /* find a list of alpha carbons of a peptide */ std::set getAlphaCs(const std::vector& allAtoms, const std::set& chetoCs, const std::set& aminoNs) const; /* clear all the interactions loaded in the minimizer and free memory */ void clearInteractions(); /* setup all constraints of given molecule */ void addInteractionsOfMolecule(sketcherMinimizerMolecule* molecule, bool intrafragmentClashes = false); void addExtraInteraction(sketcherMinimizerMolecule* molecule, sketcherMinimizerInteraction* interaction); void buildFromFragments(bool b); bool avoidClashesOfMolecule( sketcherMinimizerMolecule* molecule, const std::vector& extraInteractions = std::vector()); /// static members /* put atoms in a canonical order to reduce dependency from order in the * input vector */ static void canonicalOrdering(sketcherMinimizerMolecule* minMol); /* pick one atom out of the vector. Arbitrary criteria such as atomic number * and connectivity are used */ static sketcherMinimizerAtom* pickBestAtom(std::vector& atoms); /* return a score of the alignment between direction and templat.first, * weight on the angle between the two and templat.second */ static float testAlignment(const sketcherMinimizerPointF& direction, const std::pair& templat); /* find the best alignment of a fragment to its parent and set invert in * case the fragment needs to be flipped */ static sketcherMinimizerPointF scoreDirections( sketcherMinimizerFragment* fragment, float angle, const std::vector>& directions, bool& invert); /* align the fragment to its parent */ static void alignWithParentDirection(sketcherMinimizerFragment* f, const sketcherMinimizerPointF& position, float angle); /* align the fragment to its parent in the case of constrained coordinates */ static bool alignWithParentDirectionConstrained(sketcherMinimizerFragment* fragment, const sketcherMinimizerPointF& position, float angle); /* align the fragment to its parent in the case of unconstrained coordinates */ static bool alignWithParentDirectionUnconstrained(sketcherMinimizerFragment* fragment, float angle); /* get all bonds to a terminal atom */ static std::vector getAllTerminalBonds(sketcherMinimizerFragment* fragment); /* return a list of vectors the given fragment can be aligned with and a * score of the importance of each */ static std::vector> findDirectionsToAlignWith(sketcherMinimizerFragment* fragment); /* if the three atoms share a ring, return it */ static sketcherMinimizerRing* sameRing(const sketcherMinimizerAtom* at1, const sketcherMinimizerAtom* at2, const sketcherMinimizerAtom* at3); /* if the two atoms share a ring, return it */ static sketcherMinimizerRing* sameRing(const sketcherMinimizerAtom* at1, const sketcherMinimizerAtom* at2); /* if the two atoms share a bond, return it */ static sketcherMinimizerBond* getBond(const sketcherMinimizerAtom* a1, const sketcherMinimizerAtom* a2); /* calculate root mean square deviation between templates and points */ static float RMSD(const std::vector& templates, const std::vector& points); /* singular value decomposition for 2x2 matrices. used for 2D alignment. */ static void svd(float* a, float* U, float* Sig, float* V); /* set m to a rotation matrix to align ref to points */ static void alignmentMatrix(const std::vector& ref, const std::vector& points, float* m); static void checkIdentity(std::vector solution, int newSol, std::vector& matrix, std::vector& templateCoordinates, std::vector>& molBonds, std::vector>& templateBonds, std::vector>& molCisTransChains, std::vector& molIsCis, size_t size, bool& found, std::vector& mapping); /* compare atoms and bonds to template and map which atom is which in case * of a positive match */ static bool compare(const std::vector& atoms, const std::vector& bonds, sketcherMinimizerMolecule* templ, std::vector& mapping); /* calculate morgan scores for the given input */ static int morganScores(const std::vector& atoms, const std::vector& bonds, std::vector& scores); /* load the templates from the template file */ static void setTemplateFileDir(std::string dir); static void loadTemplates(); static CoordgenTemplates m_templates; private: /*all non-terminal bonds to a metal atom are treated as if they were zero order bonds (this usually results in a longer bond*/ bool m_treatNonterminalBondsToMetalAsZOBs = true; CoordgenFragmentBuilder m_fragmentBuilder; std::vector m_atoms; std::vector m_referenceAtoms; std::vector m_residues; std::vector m_residueInteractions; std::vector m_independentFragments; std::vector m_bonds; std::vector m_referenceBonds; std::vector m_proximityRelations; std::vector m_extraBonds; std::vector m_molecules; /* return the position of res, which is part of SSE, given that the first * residue of SSE is placed at startF and consecutive residues are placed * increment away from each other. All distances are expressed in floats, * where 0.f is an arbitrary starting point, 0.5 is the opposite side of the * curve and 1.0 is again the starting point */ float getResidueDistance(float startF, float increment, sketcherMinimizerResidue* res, const std::vector& SSE) const; /* return the vector index corresponding to floatPosition */ int getShapeIndex(const std::vector& shape, float floatPosition) const; /* return true if the molecules structure is reasonable (e.g. reasonable * amount of fused rings) */ bool structurePassSanityCheck() const; /* clear data and free memory */ void clear(); /* flag atoms that will be drawn with 90° angles (e.g. phosphate P) */ void flagCrossAtoms(); /* assign coordinates to all molecules and residues */ void minimizeAll(); /* find the best angle to rotate each molecule */ void bestRotation(); /* add info to choose the best angle so that, if present, peptide chains are * horizontal */ void addBestRotationInfoForPeptides( std::vector>& angles, const std::vector& atoms); /* if a peptide chain is present make sure that the N term is on the left */ void maybeFlipPeptides(const std::vector& atoms, float& scoreX); /* consider flipping the molecule horizontally and/or vertically */ void maybeFlip(); /* mark atoms with wedges as above or below the plane to correctly draw * crossing bonds */ void assignPseudoZ(); /* write wedges and dashed bonds to mark stereochemistry */ void writeStereoChemistry(); /* arrange multiple molecules next to each other */ void arrangeMultipleMolecules(); /* arrange molecules that have parts that interact with each other so that * they are close */ void placeMoleculesWithProximityRelations( std::vector proximityMols); /* place molecules so that one is in the middle and other are around */ void placeMolResidueLigandStyle(sketcherMinimizerMolecule* mol, sketcherMinimizerMolecule* parent); /* if the molecule has more than one interaction and they cross mirror its coordinates so they don't cross anymore */ void flipIfCrossingInteractions(sketcherMinimizerMolecule* mol); /* build data vectors to place molecules with proximity relations */ std::vector buildProximityDataVector( std::vector& proximityMols, std::map& molMap); /* translate molecules with proximity relations */ void translateMoleculesWithProximityRelations( std::vector& proximityMols, std::map& molMap, std::map& templateCenters, std::vector& proximityDataVecto); /* rotate molecules with proximity relations */ void rotateMoleculesWithProximityRelations( std::vector& proximityMols, std::map& molMap, std::vector& proximityDataVector); /* place residues in concentric contours around the ligand */ void placeResiduesInCrowns(); /* place residues from the given strands of consecutive residues to fill the given path */ bool fillShape(std::vector>& SSEs, const std::vector& shape, int shapeN); /* place a single strand of consecutive residues */ void placeSSE(const std::vector& SSE, const std::vector& shape, int shapeN, std::vector& penalties, std::set& outliers, bool placeOnlyInteracting = false); /* score the position of the given strands */ float scoreSSEPosition(const std::vector& SSE, const std::vector& shape, int shapeN, std::vector& penalties, float startingPosition, float increment); /* score the distance between the two given points of connected residues */ float scoreSSEBondStretch(const sketcherMinimizerPointF& coordinates1, const sketcherMinimizerPointF& coordinates2); /* solution represent the placement chosen for residues in SSE. Mark the * corresponding sections of the crown to prevent other residues to be * placed * there */ void markSolution(const std::pair& solution, const std::vector& SSE, const std::vector& shape, std::vector& penalties, std::set& outliers); /* return a concentric shape around the ligand. CrownN controls how far away from the ligand the shape is */ std::vector shapeAroundLigand(int crownN); /* group residues in strands of consecutive residues */ std::vector> groupResiduesInSSEs(const std::vector& residues); /* score the position of given residues */ float scoreResiduePosition(int index, const std::vector& shape, int shapeN, std::vector& penalties, sketcherMinimizerResidue* residue); /* assign coordinates to residues */ void placeResidues(const std::vector& atoms = std::vector(0)); /* assign coordinates to residues in the context of a protein-protein interaction diagram */ void placeResiduesProteinOnlyMode(); /* assign coordinates to residues in a protein-protein interaction diagram shaped as a circle */ void placeResiduesProteinOnlyModeCircleStyle( const std::map>& chains); /* assign coordinates to residues in a protein-protein interaction diagram shaped as a LID */ void placeResiduesProteinOnlyModeLIDStyle( const std::map>& chains); /* order residues for drawing, so that residues interacting together are * drawn one after the other and residues with more interactions are drawn * first */ std::vector orderResiduesOfChains( const std::map>& chains); /* find center position for each chain of residues using a meta-molecule * approach, building a molecule where each atom represents a chain and each * bond connects two interacting chains */ std::map computeChainsStartingPositionsMetaMol( const std::map>& chains); /* place interacting residues closer to each other, so they end up at the * periphery of the chain */ void shortenInteractions( const std::map>& chains); /* explore positions in a grid around the current one to ease clashes */ sketcherMinimizerPointF exploreGridAround( const sketcherMinimizerPointF& centerOfGrid, unsigned int levels, float gridD, float dx = 0.f, float dy = 0.f, float distanceFromAtoms = -1.f, bool watermap = false, sketcherMinimizerResidue* residueForInteractions = nullptr, const sketcherMinimizerPointF& direction = sketcherMinimizerPointF(0, 1)); sketcherMinimizerPointF exploreMolPosition(sketcherMinimizerMolecule* mol, unsigned int levels, float gridD, float distanceFromAtoms = -1.f); /* add given angle to a vector of angles, clustering them if a close angle * is already in the vector */ void addToVector(float weight, float angle, std::vector>& angles); void assignLongestChainFromHere(sketcherMinimizerFragment* f); void assignNumberOfChildrenAtomsFromHere(sketcherMinimizerFragment* f); /* for each residue, find the closest atom among atoms, or all atoms if none are given */ void findClosestAtomToResidues(const std::vector& atoms = std::vector(0)); /* initialize data and coordinates for each fragment */ void initializeFragments(); /* for tracking coordinates */ float sin_flip = 0.f; float cos_flip = 0.f; float centerX = 0.f; float centerY = 0.f; int flipX = 1; int flipY = 1; }; coordgenlibs-3.0.2/sketcherMinimizerAtom.cpp000066400000000000000000001460721436654770400212410ustar00rootroot00000000000000/* * sketcherMinimizerAtom.h * * Created by Nicola Zonta on 19/10/2010. * Copyright Schrodinger, LLC. All rights reserved. * */ #include #include #include #include "sketcherMinimizer.h" #include "sketcherMinimizerAtom.h" #include "sketcherMinimizerBond.h" #include "sketcherMinimizerMaths.h" #include "sketcherMinimizerRing.h" using namespace std; bool CIPAtom::operator<(const CIPAtom& rhs) const { /* check if this has priority over rhs. An atom is better than another if it has a parent in the chain that gets priority. Parents are evaluated starting from the furthest to the closest. Priority is assigned to the atom with highest atomic number, or has been found to have priority due to its children in previous iterations of the algorithm (scores) or in the present iteration (medals) */ assert(allParents.size() == rhs.allParents.size()); for (size_t i = 0; i < allParents.size(); i++) { if (allParents[i]->atomicNumber > rhs.allParents[i]->atomicNumber) { return true; } if (allParents[i]->atomicNumber < rhs.allParents[i]->atomicNumber) { return false; } if ((*scores)[allParents[i]] < (*rhs.scores)[rhs.allParents[i]]) { return true; } if ((*scores)[allParents[i]] > (*rhs.scores)[rhs.allParents[i]]) { return false; } vector meds = (*medals)[allParents[i]]; vector meds2 = (*rhs.medals)[rhs.allParents[i]]; size_t s = (meds.size() < meds2.size()) ? meds.size() : meds2.size(); for (size_t mm = 0; mm < s; mm++) { if (meds[mm] > meds2[mm]) { return true; } if (meds[mm] < meds2[mm]) { return false; } } if (meds.size() > meds2.size()) { return true; } if (meds2.size() > meds.size()) { return false; } } size_t siz = theseAtoms.size(); if (rhs.theseAtoms.size() < siz) { siz = rhs.theseAtoms.size(); } for (size_t i = 0; i < siz; i++) { if (theseAtoms[i].first > rhs.theseAtoms[i].first) { return true; } if (theseAtoms[i].first < rhs.theseAtoms[i].first) { return false; } } if (theseAtoms.size() > rhs.theseAtoms.size()) { return true; } if (theseAtoms.size() < rhs.theseAtoms.size()) { return false; } return false; } bool CIPAtom::operator==(const CIPAtom& rhs) const { assert(allParents.size() == rhs.allParents.size()); for (size_t i = 0; i < allParents.size(); i++) { if (allParents[i]->atomicNumber != rhs.allParents[i]->atomicNumber) { return false; } if ((*scores)[allParents[i]] != (*rhs.scores)[rhs.allParents[i]]) { return false; } } if (theseAtoms.size() != rhs.theseAtoms.size()) { return false; } for (size_t i = 0; i < theseAtoms.size(); i++) { if (theseAtoms[i].first != rhs.theseAtoms[i].first) { return false; } } return true; } std::ostream& operator<<(std::ostream& os, const CIPAtom& a) { for (size_t i = 0; i < a.allParents.size(); i++) { os << a.allParents[i]->atomicNumber << "(" << (*a.scores)[a.allParents[i]] << ")"; if (!(*a.medals)[a.allParents[i]].empty()) { cerr << "<"; for (int ii : (*a.medals)[a.allParents[i]]) { cerr << ii << "|"; } cerr << ">"; } cerr << " "; } os << "-"; for (const auto& theseAtom : a.theseAtoms) { os << " " << theseAtom.first; } return os; } bool CIPAtom::isBetter(CIPAtom& rhs, map* m) const { /* Similar to the < operator, but in estabilishing priorities also considers scores stored in m */ assert(allParents.size() == rhs.allParents.size()); for (size_t i = 0; i < allParents.size(); i++) { if ((*m)[allParents[i]] > (*m)[rhs.allParents[i]]) { return true; } if ((*m)[allParents[i]] < (*m)[rhs.allParents[i]]) { return false; } if (allParents[i]->atomicNumber > rhs.allParents[i]->atomicNumber) { return true; } if (allParents[i]->atomicNumber < rhs.allParents[i]->atomicNumber) { return false; } if ((*scores)[allParents[i]] < (*rhs.scores)[rhs.allParents[i]]) { return true; } if ((*scores)[allParents[i]] > (*rhs.scores)[rhs.allParents[i]]) { return false; } vector meds = (*medals)[allParents[i]]; vector meds2 = (*rhs.medals)[rhs.allParents[i]]; size_t s = (meds.size() < meds2.size()) ? meds.size() : meds2.size(); for (size_t mm = 0; mm < s; mm++) { if (meds[mm] > meds2[mm]) { return true; } if (meds[mm] < meds2[mm]) { return false; } } if (meds.size() > meds2.size()) { return true; } if (meds2.size() > meds.size()) { return false; } } size_t siz = theseAtoms.size(); if (rhs.theseAtoms.size() < siz) { siz = rhs.theseAtoms.size(); } for (size_t i = 0; i < siz; i++) { if (theseAtoms[i].first > rhs.theseAtoms[i].first) { return true; } if (theseAtoms[i].first < rhs.theseAtoms[i].first) { return false; } } if (theseAtoms.size() > rhs.theseAtoms.size()) { return true; } if (theseAtoms.size() < rhs.theseAtoms.size()) { return false; } return false; } sketcherMinimizerAtom::~sketcherMinimizerAtom() = default; sketcherMinimizerAtom::sketcherMinimizerAtom() : crossLayout(false), fixed(false), constrained(false), rigid(false), isSharedAndInner(false), atomicNumber(6), charge(0), _valence(-10), _generalUseN(-1), _generalUseN2(-1), m_chmN(-1), _generalUseVisited(false), _generalUseVisited2(false), fragment(nullptr), needsCheckForClashes(false), visited(false), coordinatesSet(false), isR(true), hasStereochemistrySet(false), _hasRingChirality(false) { hidden = false; m_pseudoZ = 0.f; m_pocketDistance = 0.f; m_x3D = INVALID_COORDINATES; m_y3D = INVALID_COORDINATES; m_z3D = INVALID_COORDINATES; m_isClashing = false; m_isLigand = false; m_isWaterMap = false; m_clockwiseInvert = false; m_isStereogenic = false; m_ignoreRingChirality = false; } sketcherMinimizerRing* sketcherMinimizerAtom::shareARing(const sketcherMinimizerAtom* atom1, const sketcherMinimizerAtom* atom2) { /* return a ring shared by the two atoms. return a non-macrocycle if * possible */ if (atom1->rings.empty()) { return nullptr; } if (atom2->rings.empty()) { return nullptr; } for (sketcherMinimizerRing* ring : atom1->rings) { if (ring->isMacrocycle()) { continue; } for (sketcherMinimizerRing* ring2 : atom2->rings) { if (ring == ring2) { return ring; } } } for (sketcherMinimizerRing* ring : atom1->rings) { for (sketcherMinimizerRing* ring2 : atom2->rings) { if (ring == ring2) { return ring; } } } return nullptr; } int sketcherMinimizerAtom::findHsNumber() const { int valence = _valence; if (valence == -10) { valence = expectedValence(atomicNumber); // valence is not yet set } int nBondOrders = 0; for (auto bond : bonds) { nBondOrders += bond->bondOrder; } if (atomicNumber == 16) { // sulfite & sulfate int nOs = 0; for (size_t i = 0; i < neighbors.size(); ++i) { if (neighbors[i]->atomicNumber == 8 && bonds[i]->bondOrder == 2) { ++nOs; } } if ((nOs) < 3) { valence += nOs * 2; } } if (atomicNumber == 15) { // P int nOs = 0; for (size_t i = 0; i < neighbors.size(); ++i) { if (neighbors[i]->atomicNumber == 8 && bonds[i]->bondOrder == 2) { ++nOs; } } if (nOs < 2) { valence += nOs * 2; } } int out = valence - nBondOrders + charge; if (out < 0) { out = 0; } else if (out > 4) { out = 4; } return out; } unsigned int sketcherMinimizerAtom::expectedValence(unsigned int atomicNumber) const { switch (atomicNumber) { case 1: return 1; case 5: return 3; case 6: return 4; case 7: return 3; case 8: return 2; case 9: return 1; case 14: return 4; case 15: return 3; case 16: return 2; case 17: return 1; case 34: return 2; case 35: return 1; case 53: return 1; default: return 4; } return 4; } vector sketcherMinimizerAtom::clockwiseOrderedNeighbors() const { vector> rankedNeighbors; rankedNeighbors.reserve(neighbors.size()); for (auto&& neighbor : neighbors) { float newAngle = sketcherMinimizerMaths::signedAngle( neighbors[0]->coordinates, coordinates, neighbor->coordinates); if (std::isnan(newAngle)) { newAngle = 361; } else if (newAngle < 0) { newAngle += 360; } rankedNeighbors.emplace_back(newAngle, neighbor); } std::sort(rankedNeighbors.begin(), rankedNeighbors.end()); vector orderedNeighs; orderedNeighs.reserve(neighbors.size()); for (const auto& rankedNeighbor : rankedNeighbors) { orderedNeighs.push_back(rankedNeighbor.second); } return orderedNeighs; } void sketcherMinimizerAtom::writeStereoChemistry() // sets stereochemistry for // this atom and from // hasStereochemistrySet and // isR { assert(neighbors.size() == bonds.size()); if (!hasStereochemistrySet) { return; } if (!canBeChiral()) { hasStereochemistrySet = false; return; } else { sketcherMinimizerAtom dummyH; dummyH.atomicNumber = 1; dummyH.molecule = molecule; sketcherMinimizerAtom dummyLP; dummyLP.atomicNumber = 0; dummyLP.molecule = molecule; sketcherMinimizerAtom* dummy = &dummyH; vector neighs = neighbors; vector orderedNeighs; vector bbonds = bonds; vector orderedBonds; vector angles; int lastPoppedIndex = 0; sketcherMinimizerAtom* lastPoppedAtom = neighs[lastPoppedIndex]; orderedNeighs.push_back(lastPoppedAtom); neighs.erase(neighs.begin() + lastPoppedIndex); orderedBonds.push_back(bbonds[lastPoppedIndex]); bbonds.erase(bbonds.begin() + lastPoppedIndex); // TODO: consider using sketcherMinimizerAtom::clockwiseOrderedNeighbors while (!neighs.empty()) { // order atoms float smallestAngle = 361; for (unsigned int i = 0; i < neighs.size(); i++) { float newAngle = sketcherMinimizerMaths::signedAngle( sketcherMinimizerPointF(lastPoppedAtom->coordinates.x(), lastPoppedAtom->coordinates.y()), sketcherMinimizerPointF(coordinates.x(), coordinates.y()), sketcherMinimizerPointF(neighs[i]->coordinates.x(), neighs[i]->coordinates.y())); if (newAngle < 0) { newAngle += 360; } if (newAngle < smallestAngle) { smallestAngle = newAngle; lastPoppedIndex = i; } } angles.push_back(smallestAngle); lastPoppedAtom = neighs[lastPoppedIndex]; orderedNeighs.push_back(lastPoppedAtom); neighs.erase(neighs.begin() + lastPoppedIndex); orderedBonds.push_back(bbonds[lastPoppedIndex]); bbonds.erase(bbonds.begin() + lastPoppedIndex); } if ((atomicNumber == 7 || atomicNumber == 16) && _implicitHs == 0 && orderedBonds.size() == 3) { dummy = &dummyLP; } bool four = true; float totalAngle = std::accumulate(angles.begin(), angles.end(), 0.f); angles.push_back(360.f - totalAngle); vector atomPriorities, orderedAtomPriorities; for (auto& orderedNeigh : orderedNeighs) { sketcherMinimizerAtomPriority p; p.a = orderedNeigh; atomPriorities.push_back(p); } if (atomPriorities.size() == 3) { four = false; sketcherMinimizerAtomPriority p; p.a = dummy; atomPriorities.push_back(p); } bool isStereocenter = setCIPPriorities(atomPriorities, this); if (!isStereocenter) { if (!m_ignoreRingChirality) { _hasRingChirality = true; isStereocenter = setCIPPriorities(atomPriorities, this); } } if (!isStereocenter) { _hasRingChirality = false; } orderedAtomPriorities = atomPriorities; orderAtomPriorities(orderedAtomPriorities, this); if (isStereocenter) { if (!four) { if (orderedAtomPriorities[0].a == dummy) { orderedAtomPriorities.push_back(orderedAtomPriorities[0]); orderedAtomPriorities.insert(orderedAtomPriorities.begin(), orderedAtomPriorities[3]); orderedAtomPriorities.erase(orderedAtomPriorities.begin() + 1); orderedAtomPriorities.erase(orderedAtomPriorities.begin() + 3); } } unsigned int startIndex = 0; for (unsigned int i = 0; i < atomPriorities.size(); i++) { if (atomPriorities[i].a == orderedAtomPriorities[0].a) { startIndex = i; break; } } for (unsigned int i = 0; i < startIndex; i++) { atomPriorities.push_back(atomPriorities[0]); atomPriorities.erase(atomPriorities.begin()); } if (four) { if (atomPriorities[1].a == orderedAtomPriorities[3].a) { atomPriorities.push_back(atomPriorities[0]); atomPriorities.erase(atomPriorities.begin()); } } sketcherMinimizerAtom* mainAtom = nullptr; if (four) { if (atomPriorities[0].a == orderedAtomPriorities[0].a) { mainAtom = atomPriorities[0].a; } if (atomPriorities[3].a == orderedAtomPriorities[0].a) { mainAtom = atomPriorities[3].a; } } bool invert = false; sketcherMinimizerBond* b1 = bondTo(atomPriorities[0].a); if (b1) { if (!four || mainAtom == atomPriorities[0].a || (!sketcherMinimizer::sameRing(this, atomPriorities[0].a) && !atomPriorities[0].a->hasStereochemistrySet)) { bool reverse = false; if (b1->startAtom != this) { reverse = true; } b1->isWedge = !invert; b1->hasStereochemistryDisplay = true; b1->isReversed = reverse; } else { b1->hasStereochemistryDisplay = false; } } if (four) { sketcherMinimizerBond* b2 = bondTo(atomPriorities[3].a); if (b2) { if (mainAtom == atomPriorities[3].a || (!sketcherMinimizer::sameRing(this, atomPriorities[3].a) && !atomPriorities[3].a->hasStereochemistrySet)) { bool reverse = false; if (b2->startAtom != this) { reverse = true; } b2->isWedge = invert; b2->hasStereochemistryDisplay = true; b2->isReversed = reverse; } else { b2->hasStereochemistryDisplay = false; } } } sketcherMinimizerBond* b3 = bondTo(atomPriorities[1].a); if (b3) { b3->hasStereochemistryDisplay = false; } sketcherMinimizerBond* b4 = bondTo(atomPriorities[2].a); if (b4) { b4->hasStereochemistryDisplay = false; } int readS = readStereochemistry(true); readS = -readS; // inverting stereochemistry cause isR is in // sketcher coords and readStereo in coordgen coords // (flipped y) if ((readS == -1 && isR) || (readS == 1 && !isR)) { // inverting invert = true; if (b1) { if (!four || mainAtom == atomPriorities[0].a || (!sketcherMinimizer::sameRing(this, atomPriorities[0].a) && !atomPriorities[0].a->hasStereochemistrySet)) { // cerr << "and setting it "<startAtom != this) { reverse = true; } b1->isWedge = !invert; b1->hasStereochemistryDisplay = true; b1->isReversed = reverse; } else { b1->hasStereochemistryDisplay = false; } } if (four) { sketcherMinimizerBond* b2 = bondTo(atomPriorities[3].a); if (b2) { if (mainAtom == atomPriorities[3].a || (!sketcherMinimizer::sameRing( this, atomPriorities[3].a) && !atomPriorities[3].a->hasStereochemistrySet)) { bool reverse = false; if (b2->startAtom != this) { reverse = true; } b2->isWedge = invert; b2->hasStereochemistryDisplay = true; b2->isReversed = reverse; } else { b2->hasStereochemistryDisplay = false; } } } } } else { for (auto b : bonds) { b->hasStereochemistryDisplay = false; } } } } sketcherMinimizerAtomChiralityInfo::sketcherMinimizerChirality sketcherMinimizerAtom::getRelativeStereo(sketcherMinimizerAtom* lookingFrom, sketcherMinimizerAtom* atom1, sketcherMinimizerAtom* atom2) { readStereochemistry(); // to set m_RSPriorities auto RSpriorities = m_RSPriorities; if (RSpriorities.size() < 3) { return sketcherMinimizerAtomChiralityInfo::unspecified; } vector priorities(4, 3); /* order the CIP priority of the atoms in the following order atom1 - atom2 - atom3 - atomLookingFrom */ for (unsigned int nn = 0; nn < neighbors.size(); nn++) { sketcherMinimizerAtom* n = neighbors[nn]; if (n == atom1) { priorities[0] = RSpriorities[nn]; } else if (n == atom2) { priorities[1] = RSpriorities[nn]; } else if (n == lookingFrom) { priorities[3] = RSpriorities[nn]; } else { priorities[2] = RSpriorities[nn]; } } vector can(4); for (unsigned int i = 0; i < 4; i++) { can[i] = i; } /* this represents a molecule with atom1 (priority 0 - highest) atom2 (priority 1) atom3 (priority 2) atomLookingFrom (priority 3 -lowest) which is the opposite of the CIP rules, where the the lowest priority atom is AWAY from the observer. This is the reason why we return CCW for R and CW for S. */ bool match = sketcherMinimizerAtom::matchCIPSequence(priorities, can); bool isClockWise = (match ? !isR : isR); if (isClockWise) { return sketcherMinimizerAtomChiralityInfo::clockwise; } return sketcherMinimizerAtomChiralityInfo::counterClockwise; } bool sketcherMinimizerAtom::setAbsoluteStereoFromChiralityInfo() { auto info = m_chiralityInfo; if (info.direction == sketcherMinimizerAtomChiralityInfo::unspecified) { return true; } readStereochemistry(); // to set m_RSPriorities auto RSpriorities = m_RSPriorities; if (RSpriorities.size() < 3) { cerr << "CHMMol-> sketcher stereo error: wrong number for RSpriorities" << endl; return false; } vector priorities(4, 5); bool at3 = false; for (unsigned int nn = 0; nn < neighbors.size(); nn++) { sketcherMinimizerAtom* n = neighbors[nn]; if (n == info.atom1) { priorities[0] = RSpriorities[nn]; } else if (n == info.atom2) { priorities[1] = RSpriorities[nn]; } else if (n == info.lookingFrom) { priorities[3] = RSpriorities[nn]; } else { if (at3) { cerr << "CHMMol-> sketcher stereo error: more than 1 atom not " "matching" << endl; return false; } else { at3 = true; priorities[2] = RSpriorities[nn]; } } } int addingHN = 0; if (priorities[0] == 5) { priorities[0] = 3; addingHN++; } if (priorities[1] == 5) { priorities[1] = 3; addingHN++; } if (priorities[2] == 5) { priorities[2] = 3; addingHN++; } if (priorities[3] == 5) { priorities[3] = 3; addingHN++; } if (addingHN > 1) { cerr << "CHMMol-> sketcher stereo error: more than 1 H on chiral center" << endl; return false; } bool invert = false; vector can(4); for (unsigned int i = 0; i < 4; i++) { can[i] = i; } if (!sketcherMinimizerAtom::matchCIPSequence(priorities, can)) { invert = !invert; } bool isRBool = true; if (info.direction == sketcherMinimizerAtomChiralityInfo::clockwise) { isRBool = false; } if (invert) { isRBool = !isRBool; } isR = isRBool; hasStereochemistrySet = true; return true; } bool sketcherMinimizerAtom::matchCIPSequence(vector& v1, vector& v2) { if (v1.size() < v2.size()) { v1.push_back(3); } else if (v2.size() < v1.size()) { v2.push_back(3); } int outofPlaceNs = 0; for (unsigned int i = 0; i < v1.size(); i++) { if (v1[i] != v2[i]) { outofPlaceNs++; } } if (outofPlaceNs == 2) { return false; } else if (outofPlaceNs == 4) { int n1 = v1[0]; int index2 = 0; for (unsigned int j = 0; j < v2.size(); j++) { if (v2[j] == n1) { index2 = j; break; } } if (v1[index2] != v2[0]) { return false; } } return true; } void sketcherMinimizerAtom::setCoordinates(sketcherMinimizerPointF coords) { coordinates = std::move(coords); coordinates.round(); coordinatesSet = true; } bool sketcherMinimizerAtom::hasNoStereoActiveBonds() const { for (auto bond : bonds) { if (bond->isStereo()) { return false; } } return true; } void sketcherMinimizerAtom::orderAtomPriorities( vector& atomPriorities, sketcherMinimizerAtom* center) // orders trying to keep long chains in // position 2 and 3 and side substituents in // 1 and 4 { assert(atomPriorities.size() == 4); vector weights(4); for (unsigned int i = 0; i < 4; i++) { queue q; for (auto& _atom : center->molecule->_atoms) { _atom->_generalUseVisited = false; } q.push(atomPriorities[i].a); center->_generalUseVisited = true; atomPriorities[i].a->_generalUseVisited = true; int counter = 0; while (!q.empty()) { counter++; sketcherMinimizerAtom* at = q.front(); q.pop(); for (auto n : at->neighbors) { if (!n->_generalUseVisited) { q.push(n); n->_generalUseVisited = true; } } } weights[i] = static_cast(counter); sketcherMinimizerBond* b = center->bondTo(atomPriorities[i].a); if (b) { if (b->bondOrder == 2) { weights[i] -= 0.25; // so that =O get lower priority than -OH in phosphate } if (center->atomicNumber == 16 && b->bondOrder == 2) { weights[i] += 2000; // forcing the wedge away from double bond } // in sulphoxide if (sketcherMinimizer::sameRing(b->startAtom, b->endAtom)) { weights[i] += 500; // force same ring atoms to be in position 3 and 4 } } if (atomPriorities[i].a->atomicNumber == 6) { weights[i] += 0.5; // carbons get priority over other heavy atoms } if (atomPriorities[i].a->atomicNumber == 1) { weights[i] -= 0.5; } if (atomPriorities[i].a->isSharedAndInner && !center->isSharedAndInner) { weights[i] -= 2000; // forced bond to shared and inner } if (center->crossLayout) { if (atomPriorities[i].a->neighbors.size() > 1) { weights[i] += 200; } } if (/* atomPriorities[i].a->isStereogenic && */ atomPriorities[i] .a->hasStereochemistrySet) { weights[i] += 10000; // to avoid problems with wedges when 2 } // stereocenters are near for (unsigned int j = 0; j < atomPriorities[i].a->bonds.size(); j++) { if (atomPriorities[i].a->bonds[j]->bondOrder == 2) { weights[i] += 100; break; } } } float lowestWeight = weights[0]; int index = 0; sketcherMinimizerAtomPriority firstAtom = atomPriorities[0]; for (unsigned int i = 1; i < 4; i++) { if (weights[i] < lowestWeight) { lowestWeight = weights[i]; index = i; } } firstAtom = atomPriorities[index]; atomPriorities.erase(atomPriorities.begin() + index); weights.erase(weights.begin() + index); index = 0; lowestWeight = weights[0]; sketcherMinimizerAtomPriority secondAtom = atomPriorities[0]; for (unsigned int i = 1; i < 3; i++) { if (weights[i] < lowestWeight) { lowestWeight = weights[i]; index = i; } } secondAtom = atomPriorities[index]; atomPriorities.erase(atomPriorities.begin() + index); if ((center->atomicNumber != 16 && center->atomicNumber != 15) || center->neighbors.size() != 4) { atomPriorities.push_back(secondAtom); atomPriorities.insert(atomPriorities.begin(), firstAtom); } else { atomPriorities.insert(atomPriorities.begin() + 1, secondAtom); atomPriorities.insert(atomPriorities.begin(), firstAtom); } } bool sketcherMinimizerAtom::setCIPPriorities( vector& atomPriorities, sketcherMinimizerAtom* center) { for (auto& atomPrioritie : atomPriorities) { atomPrioritie.priority = 3; } if (atomPriorities.size() != 4) { // cerr << "coordgen: stereo error. (wrong number of atom priorities: // "<< atomPriorities.size () << ")"< found(4, false); for (auto& atomPrioritie : atomPriorities) { if (found[atomPrioritie.priority]) { return false; // two atoms have the same priority } found[atomPrioritie.priority] = true; } return true; } sketcherMinimizerAtom* sketcherMinimizerAtom::CIPPriority(sketcherMinimizerAtom* at1, sketcherMinimizerAtom* at2, sketcherMinimizerAtom* center) { assert(center->molecule); assert(at1->molecule == center->molecule); assert(at2->molecule == center->molecule); assert(!center->molecule->_atoms.empty()); assert(at1); assert(at2); if (at1->atomicNumber > at2->atomicNumber) { return at1; } else if (at2->atomicNumber > at1->atomicNumber) { return at2; } if (center->_hasRingChirality && !center->m_ignoreRingChirality) { if (sketcherMinimizer::sameRing(center, at1, at2)) { if (at1->_generalUseN > at2->_generalUseN) { return at1; } else { return at2; } } } vector AN1, AN2; map score1, score2; // used to keep track if a parent atom has been found to have // priority over another map> medals1, medals2; // marks if an atom is a parent of the atoms being evaluated in // the current iteration map visited1, visited2; // marks at which iteration this atom was evaluated visited1[center] = 1; visited2[center] = 1; visited1[at1] = 2; visited2[at2] = 2; vector> v1, v2; v1.emplace_back(at1->atomicNumber, at1); v2.emplace_back(at2->atomicNumber, at2); vector parents1, parents2; parents1.push_back(center); parents1.push_back(at1); parents2.push_back(center); parents2.push_back(at2); AN1.emplace_back(v1, center, parents1, &score1, &medals1, &visited1); AN2.emplace_back(v2, center, parents2, &score2, &medals2, &visited2); while (!AN1.empty() || !AN2.empty()) { stable_sort(AN1.begin(), AN1.end()); stable_sort(AN2.begin(), AN2.end()); sketcherMinimizerAtom::assignMedals(AN1); sketcherMinimizerAtom::assignMedals(AN2); sketcherMinimizerAtom::chooseFirstAndSortAccordingly(AN1); sketcherMinimizerAtom::chooseFirstAndSortAccordingly(AN2); sketcherMinimizerAtom::finalizeScores(AN1); sketcherMinimizerAtom::finalizeScores(AN2); size_t nn = AN1.size(); if (AN2.size() < nn) { nn = AN2.size(); } for (size_t i = 0; i < nn; ++i) { if (AN1[i] < AN2[i]) { return at1; } if (AN2[i] < AN1[i]) { return at2; } } if (AN1.size() > AN2.size()) { return at1; } if (AN2.size() > AN1.size()) { return at2; } AN1 = sketcherMinimizerAtom::expandOneLevel(AN1); AN2 = sketcherMinimizerAtom::expandOneLevel(AN2); } return nullptr; } void sketcherMinimizerAtom::chooseFirstAndSortAccordingly(vector& V) { if (V.size() < 2) { return; } vector copyV = V; V.clear(); map friendsMask; while (!copyV.empty()) { int bestI = 0; for (unsigned int i = 1; i < copyV.size(); i++) { if (copyV[i].isBetter(copyV[bestI], &friendsMask)) { bestI = i; } } CIPAtom newBest = copyV[bestI]; copyV.erase(copyV.begin() + bestI); V.push_back(newBest); for (auto allParent : newBest.allParents) { friendsMask[allParent] |= (1 << copyV.size()); } } } vector sketcherMinimizerAtom::expandOneLevel(vector& oldV) { // we need to keep the bound atoms together, one by one will not work. map visitedThisRound; vector newV; for (auto& an : oldV) { for (unsigned int aa = 0; aa < an.theseAtoms.size(); aa++) { sketcherMinimizerAtom* a = an.theseAtoms[aa].second; if (a == nullptr) { continue; // dummy atom } // if (visitedThisRound[a]) continue; // a is present twice // because closing a ring and has already been dealt with visitedThisRound[a] = true; map* visited = an.visited; map>* medals = an.medals; map* scores = an.scores; vector allParents = an.allParents; allParents.push_back(a); vector> theseAts; for (unsigned int n = 0; n < a->bonds.size(); n++) { sketcherMinimizerAtom* neigh = a->neighbors[n]; if (neigh != an.parent) { // if n is not the direct parent of a bool ghost = (neigh->atomicNumber == 1 || ((*visited)[neigh] && (*visited)[neigh] != (*visited)[a] + 1) // closing a ring to an atom // already visited in a // previous cycle ); theseAts.emplace_back( neigh->atomicNumber, ghost ? ((sketcherMinimizerAtom*) nullptr) : neigh); // put a ghost for hydrogens and atoms // closing a ring if (!ghost) { (*visited)[neigh] = (*visited)[a] + 1; } } if (a->bonds[n]->bondOrder == 2) { // put ghosts for multiple // order bonds, even to the // parent theseAts.emplace_back(neigh->atomicNumber, (sketcherMinimizerAtom*) nullptr); } else if (a->bonds[n]->bondOrder == 3) { theseAts.emplace_back(neigh->atomicNumber, (sketcherMinimizerAtom*) nullptr); theseAts.emplace_back(neigh->atomicNumber, (sketcherMinimizerAtom*) nullptr); } } for (int counter = 0; counter < a->_implicitHs; counter++) { // put ghosts for implicit Hs theseAts.emplace_back(1, (sketcherMinimizerAtom*) nullptr); } stable_sort(theseAts.begin(), theseAts.end()); reverse(theseAts.begin(), theseAts.end()); newV.emplace_back(theseAts, a, allParents, scores, medals, visited); } } return newV; } void sketcherMinimizerAtom::assignMedals(vector& v) { if (v.empty()) { return; } map>* medals = v[0].medals; vector isEqualToPrevious(v.size()); for (unsigned int i = 1; i < v.size(); i++) { // need to be done before assigning the medals because they are // considered in the == operator isEqualToPrevious[i] = (v[i] == v[i - 1]); } unsigned int medalLvl = 0; for (unsigned int i = 0; i < v.size(); i++) { if (i > 0) { if (isEqualToPrevious[i]) { assert(medalLvl > 0); medalLvl--; } } for (auto allParent : v[i].allParents) { vector medalsV = (*medals)[allParent]; while (medalsV.size() < medalLvl) { medalsV.push_back(0); } if (medalsV.size() > medalLvl) { medalsV[medalLvl] = medalsV[medalLvl] + 1; } else { medalsV.push_back(1); } (*medals)[allParent] = medalsV; } medalLvl++; } } void sketcherMinimizerAtom::finalizeScores(vector& v) { if (v.empty()) { return; } vector isEqualToPrevious(v.size()); for (unsigned int i = 1; i < v.size(); i++) { // need to be done before assigning the scores because they are // considered in the == operator isEqualToPrevious[i] = (v[i] == v[i - 1]); } map>* medals = v[0].medals; map* scores = v[0].scores; scores->clear(); int score = 1; for (unsigned int i = 0; i < v.size(); i++) { if (i > 0) { if (isEqualToPrevious[i]) { score--; } } /* write the score */ for (auto allParent : v[i].allParents) { if ((*scores)[allParent] == 0) { (*scores)[allParent] = score; } } score++; } medals->clear(); } sketcherMinimizerBond* sketcherMinimizerAtom::bondTo(sketcherMinimizerAtom* at) const { for (unsigned int i = 0; i < neighbors.size(); i++) { if (neighbors[i] == at) { return bonds[i]; } } return nullptr; } bool sketcherMinimizerAtom::isResidue() const { return false; } int sketcherMinimizerAtom::readStereochemistry( bool readOnly) // 0 if not assigned, 1 if R, -1 if S { if (!readOnly) { _hasRingChirality = false; m_isStereogenic = false; } if (!canBeChiral()) { return 0; } // if (neighbors.size () != 4 && neighbors.size () != 3) return 0; sketcherMinimizerAtom dummyH; dummyH.atomicNumber = 1; dummyH.molecule = molecule; sketcherMinimizerAtom dummyLP; dummyLP.atomicNumber = 0; dummyLP.molecule = molecule; vector neighs = neighbors; vector orderedNeighs; vector bnds = bonds; vector orderedBonds; vector angles; int lastPoppedIndex = 0; sketcherMinimizerAtom* lastPoppedAtom = neighs[lastPoppedIndex]; orderedNeighs.push_back(lastPoppedAtom); neighs.erase(neighs.begin() + lastPoppedIndex); orderedBonds.push_back(bnds[lastPoppedIndex]); bnds.erase(bnds.begin() + lastPoppedIndex); // TODO: consider using sketcherMinimizerAtom::clockwiseOrderedNeighbors while (!neighs.empty()) { // order atoms float smallestAngle = 361; for (unsigned int i = 0; i < neighs.size(); i++) { float newAngle = sketcherMinimizerMaths::signedAngle( lastPoppedAtom->coordinates, coordinates, neighs[i]->coordinates); if (newAngle < 0) { newAngle += 360; } if (newAngle < smallestAngle) { smallestAngle = newAngle; lastPoppedIndex = i; } } angles.push_back(smallestAngle); lastPoppedAtom = neighs[lastPoppedIndex]; orderedNeighs.push_back(lastPoppedAtom); neighs.erase(neighs.begin() + lastPoppedIndex); orderedBonds.push_back(bnds[lastPoppedIndex]); bnds.erase(bnds.begin() + lastPoppedIndex); } float totalAngle = 0; for (float angle : angles) { totalAngle += angle; } angles.push_back(360.f - totalAngle); bool semiplane = false; sketcherMinimizerAtom* centralAtom = nullptr; if (angles.size() == 3) { for (unsigned int i = 0; i < angles.size(); i++) { if (angles[i] > 180.f) { semiplane = true; size_t precI; if (i == 0) { precI = angles.size() - 1; } else { precI = i - 1; } centralAtom = orderedNeighs[precI]; } } } int wedgeN = -1; int dashedN = -1; bool giveUp = false; assert(orderedBonds.size() == 4 || orderedBonds.size() == 3); for (unsigned int i = 0; i < orderedBonds.size(); i++) { if (orderedBonds[i]->hasStereochemistryDisplay) { if (!orderedBonds[i]->isReversed && orderedBonds[i]->startAtom != this) { continue; } if (orderedBonds[i]->isReversed && orderedBonds[i]->endAtom != this) { continue; } bool wedge = orderedBonds[i]->isWedge; if (orderedBonds[i]->isReversed) { wedge = !wedge; } if (orderedBonds[i]->startAtom != this) { wedge = !wedge; } if (wedge) { if (wedgeN == -1) { wedgeN = i; } else { giveUp = true; } } else { if (dashedN == -1) { dashedN = i; } else { giveUp = true; } } } } int startIndex = 0; bool invert = false; if (dashedN == -1 && wedgeN == -1) { giveUp = true; } else if (dashedN == -1) { startIndex = wedgeN; } else if (wedgeN == -1) { startIndex = dashedN; invert = true; } else { if (orderedBonds.size() == 3) { return 0; } if (wedgeN - dashedN == 1 || wedgeN - dashedN == -3) { startIndex = wedgeN; } else if (wedgeN - dashedN == -1 || wedgeN - dashedN == 3) { startIndex = dashedN; invert = true; } else { giveUp = true; } } int nOfHs = _implicitHs; size_t totalSubstituentsN = neighbors.size() + nOfHs; if (orderedNeighs.size() == 3 && nOfHs == 1) { if (semiplane) { if (centralAtom == orderedNeighs[startIndex]) { invert = !invert; } } orderedNeighs.insert(orderedNeighs.begin() + startIndex, &dummyH); invert = !invert; } if (orderedNeighs.size() == 3 && (atomicNumber == 7 || atomicNumber == 16)) { // nitrogen or sulphoxide // should we check for // the =O on the sulphoxide? orderedNeighs.insert(orderedNeighs.begin() + startIndex, &dummyLP); invert = !invert; } vector atomPriorities; for (auto& orderedNeigh : orderedNeighs) { sketcherMinimizerAtomPriority p; p.a = orderedNeigh; atomPriorities.push_back(p); } if (atomPriorities.size() != 4) { return 0; } vector canonical; canonical.push_back(0); canonical.push_back(1); canonical.push_back(2); canonical.push_back(3); m_RSPriorities.clear(); bool isStereocenter = setCIPPriorities(atomPriorities, this); if (!isStereocenter) { if (!readOnly) { if (!m_ignoreRingChirality) { _hasRingChirality = true; isStereocenter = setCIPPriorities(atomPriorities, this); } } } if (!isStereocenter) { if (!readOnly) { _hasRingChirality = false; } } if (!isStereocenter) { giveUp = true; } else { if (!readOnly) { m_isStereogenic = true; } } if (totalSubstituentsN < 4 && (atomicNumber != 7 && atomicNumber != 16)) { if (!readOnly) { m_isStereogenic = false; } } if (!m_isStereogenic) { if (!readOnly) { _hasRingChirality = false; } } for (auto n : neighbors) { for (auto& atomPrioritie : atomPriorities) { if (atomPrioritie.a == n) { m_RSPriorities.push_back(atomPrioritie.priority); break; } } } if (!matchCIPSequence(canonical, m_RSPriorities)) { m_clockwiseInvert = true; } else { m_clockwiseInvert = false; } if (!giveUp) { int outofPlaceAtoms = 0; for (unsigned int i = 0; i < atomPriorities.size(); i++) { // cerr <atomicNumber< 3) { n -= 4; } if (atomPriorities[n].priority != i) { outofPlaceAtoms++; } } if (outofPlaceAtoms == 2) { invert = !invert; } else if (outofPlaceAtoms == 4) { int n2 = atomPriorities[startIndex].priority + startIndex; if (n2 > 3) { n2 -= 4; } if (atomPriorities[n2].priority != 0) { invert = !invert; // if I swapped position 0 with another will } // that settle both atoms? } if (invert) { return -1; } else { return 1; } } return 0; } bool sketcherMinimizerAtom::canBeChiral() const { if (atomicNumber == 16) { if (neighbors.size() == 3) { return true; } } if (atomicNumber == 7) { if (neighbors.size() == 3 || neighbors.size() == 4) { return true; } } if (neighbors.size() != 3 && neighbors.size() != 4) { return false; } if ((neighbors.size() + _implicitHs != 4)) { return false; } return true; } /* get a vector that points out towards the most free region of space around the * atom. Used to determined where an arrow to the atom will point from */ sketcherMinimizerPointF sketcherMinimizerAtom::getSingleAdditionVector( const vector& ats) { sketcherMinimizerPointF out(0.f, 0.f); int n = 0; for (unsigned int i = 0; i < ats.size(); i++) { sketcherMinimizerAtom* at = ats[i]; for (unsigned int j = 0; j < at->neighbors.size(); j++) { sketcherMinimizerAtom* ne = at->neighbors[j]; if (ne->neighbors.size() > 1 && find(ats.begin(), ats.end(), ne) == ats.end()) { out += ne->coordinates - at->coordinates; n++; } } } if (n > 0) { out /= n; } else { return sketcherMinimizerPointF(50, 0); } out *= -1; return out; } sketcherMinimizerPointF sketcherMinimizerAtom::getSingleAdditionVector() const { sketcherMinimizerPointF out(0.f, 0.f); float totalf = 0.f; if (!neighbors.empty()) { for (auto neighbor : neighbors) { float f = 1.f; if (sketcherMinimizer::sameRing(this, neighbor)) { f = 4.f; } out += f * (neighbor->coordinates - coordinates); totalf += f; } out /= totalf; } out *= -1; return out; } bool sketcherMinimizerAtom::isMetal(const unsigned int atomicNumber) { if (atomicNumber >= 3 && atomicNumber <= 4) { return true; } if (atomicNumber >= 11 && atomicNumber <= 12) { return true; } if (atomicNumber >= 19 && atomicNumber <= 20) { return true; } if (atomicNumber >= 37 && atomicNumber <= 38) { return true; } if (atomicNumber >= 55 && atomicNumber <= 56) { return true; } if (atomicNumber >= 87 && atomicNumber <= 88) { return true; } if (atomicNumber >= 21 && atomicNumber <= 30) { return true; } if (atomicNumber >= 39 && atomicNumber <= 48) { return true; } if (atomicNumber >= 72 && atomicNumber <= 80) { return true; } if (atomicNumber >= 104 && atomicNumber <= 112) { return true; } if (atomicNumber >= 57 && atomicNumber <= 71) { return true; // lanthanoids } if (atomicNumber >= 89 && atomicNumber <= 103) { return true; // actinoids } if (atomicNumber == 13) { return true; } if (atomicNumber == 31) { return true; } if (atomicNumber == 49) { return true; } if (atomicNumber == 81) { return true; } if (atomicNumber == 32) { return true; } if (atomicNumber == 50) { return true; } if (atomicNumber == 82) { return true; } if (atomicNumber == 51) { return true; } if (atomicNumber == 83) { return true; } if (atomicNumber == 84) { return true; } return false; } void sketcherMinimizerAtom::mirrorCoordinates(sketcherMinimizerAtom* at, const sketcherMinimizerBond* bond) { at->setCoordinates(sketcherMinimizerMaths::mirrorPoint( at->getCoordinates(), bond->getStartAtom()->getCoordinates(), bond->getEndAtom()->getCoordinates())); } bool sketcherMinimizerAtom::hasValid3DCoordinates() const { return (m_x3D < INVALID_COORDINATES && m_y3D < INVALID_COORDINATES && m_z3D < INVALID_COORDINATES); } vector sketcherMinimizerAtom::getSubmolecule(sketcherMinimizerAtom* excludedAtom) { vector subMolecule; queue q; map isVisited; isVisited[excludedAtom] = true; q.push(this); isVisited[this] = true; while (!q.empty()) { sketcherMinimizerAtom* atom = q.front(); subMolecule.push_back(atom); q.pop(); for (sketcherMinimizerAtom* neighbor : atom->neighbors) { if (!isVisited[neighbor]) { q.push(neighbor); isVisited[neighbor] = true; } } } return subMolecule; } coordgenlibs-3.0.2/sketcherMinimizerAtom.h000066400000000000000000000234101436654770400206740ustar00rootroot00000000000000/* * sketcherMinimizerAtom.h * * Created by Nicola Zonta on 13/04/2010. * Copyright Schrodinger, LLC. All rights reserved. * */ #ifndef sketcherMINIMIZERATOM_H #define sketcherMINIMIZERATOM_H // #include #include "CoordgenConfig.hpp" #include "sketcherMinimizerMaths.h" #include #include #include static const int COORDINATES_LIMIT = 10000000; static const int INVALID_COORDINATES = COORDINATES_LIMIT + 1; class sketcherMinimizerBond; class sketcherMinimizerFragment; class sketcherMinimizerRing; class sketcherMinimizerMolecule; class sketcherMinimizerAtom; typedef struct { sketcherMinimizerAtom* a; unsigned int priority; } sketcherMinimizerAtomPriority; struct sketcherMinimizerAtomChiralityInfo { enum sketcherMinimizerChirality { clockwise, counterClockwise, unspecified }; sketcherMinimizerAtom* lookingFrom = nullptr; sketcherMinimizerAtom* atom1 = nullptr; sketcherMinimizerAtom* atom2 = nullptr; sketcherMinimizerChirality direction = unspecified; }; /* structure to represent an atom in Cahn–Ingold–Prelog priorities assignment */ struct CIPAtom { CIPAtom(std::vector> us, sketcherMinimizerAtom* dad, std::vector allPars, std::map* scors, std::map>* meds, std::map* visits ) : theseAtoms(std::move(us)), parent(dad), allParents(std::move(allPars)), scores(scors), visited(visits), medals(meds) { } bool operator<(const CIPAtom& rhs) const; bool operator==(const CIPAtom& rhs) const; bool isBetter(CIPAtom& rhs, std::map* m) const; std::vector> theseAtoms; // NULL if dummy sketcherMinimizerAtom* parent; std::vector allParents; std::map* scores; std::map* visited; std::map>* medals; private: friend std::ostream& operator<<(std::ostream& os, const CIPAtom& a); }; /* class to represent an atom */ class EXPORT_COORDGEN sketcherMinimizerAtom { public: sketcherMinimizerAtom(); virtual ~sketcherMinimizerAtom(); bool crossLayout; // atoms with 4 substituents displayed in a cross style // (such as S in sulphate) bool fixed, constrained, rigid; bool isSharedAndInner; // shared by two rings and needs to be drawn inside a // ring bool hidden; int atomicNumber, charge, _valence, _generalUseN, _generalUseN2; int m_chmN; // idx of the corresponding ChmAtom if molecule comes from 3d bool _generalUseVisited, _generalUseVisited2; bool m_clockwiseInvert; bool m_ignoreRingChirality; std::vector m_RSPriorities; int _implicitHs = -1; sketcherMinimizerMolecule* molecule; sketcherMinimizerFragment* fragment; void setFragment(sketcherMinimizerFragment* fragmentToSet) { fragment = fragmentToSet; } sketcherMinimizerFragment* getFragment() const { return fragment; } const std::vector& getBonds() const { return bonds; } const std::vector& getRings() const { return rings; } sketcherMinimizerMolecule* getMolecule() const { return molecule; } /* Find all connected atoms, pruning the search at the excludedAtom." This function assumes that the bond between this atom and excludedAtom is not part of a ring. */ std::vector getSubmolecule(sketcherMinimizerAtom* excludedAtom); std::vector neighbors; std::vector bonds; std::vector residueInteractionPartners; std::vector residueInteractions; std::vector rings; float m_pseudoZ; float m_x3D; float m_y3D; float m_z3D; bool m_isClashing, m_isWaterMap; float m_pocketDistance; bool needsCheckForClashes; bool m_isLigand; bool visited, coordinatesSet; bool isR; // stereochemistry bool hasStereochemistrySet, m_isStereogenic; bool _hasRingChirality; // used to keep track of cyclohexane cis/trans // chirality /* write coordinates to atom */ void setCoordinates(sketcherMinimizerPointF coords); /* check that the atom has no double bonds possibly involved in E/Z * stereochemistry */ bool hasNoStereoActiveBonds() const; const sketcherMinimizerPointF& getCoordinates() const { return coordinates; } int getAtomicNumber() const { return atomicNumber; } void setAtomicNumber(int number) { atomicNumber = number; } void setStereoChemistry(sketcherMinimizerAtomChiralityInfo info) { m_chiralityInfo = info; } /* write template coordinates to atom */ void setCoordinatesToTemplate() { setCoordinates(templateCoordinates); } sketcherMinimizerPointF coordinates; sketcherMinimizerPointF templateCoordinates; sketcherMinimizerPointF force; /* return the expected valence for the atom */ unsigned int expectedValence(unsigned int atomicNumber) const; bool canBeChiral() const; // checks if the atom can have 4 substituents (one // can be implicit H). Doesn't actually check if // two of them are the same, so can return true // for achiral centers /* return true if this and at2 share a bond */ bool isNeighborOf(sketcherMinimizerAtom* at2) const { for (auto& neighbor : at2->neighbors) { if (neighbor == this) { return true; } } return false; } sketcherMinimizerAtomChiralityInfo::sketcherMinimizerChirality getRelativeStereo(sketcherMinimizerAtom* lookingFrom, sketcherMinimizerAtom* atom1, sketcherMinimizerAtom* atom2); bool setAbsoluteStereoFromChiralityInfo(); /* if this atom and the given one share a bond, return it */ sketcherMinimizerBond* bondTo(sketcherMinimizerAtom* at) const; /* return all bonded atoms, ordered as they appear clockwise around this */ std::vector clockwiseOrderedNeighbors() const; int findHsNumber() const; void writeStereoChemistry(); // assigns up-down bond flags based on isR and // hasStereochemistrySet /* return true if the two sequences represent the same isomer */ static bool matchCIPSequence(std::vector& v1, std::vector& v2); /* calculate CIP priorities and assign them */ static bool setCIPPriorities(std::vector& atomPriorities, sketcherMinimizerAtom* center); static void orderAtomPriorities( std::vector& atomPriorities, sketcherMinimizerAtom* center); // orders trying to keep long chains in // position 2 and 3 and side // substituents in 1 and 4 /* return which between at1 and at2 has higher CIP priority. Returns NULL if * they have the same */ static sketcherMinimizerAtom* CIPPriority(sketcherMinimizerAtom* at1, sketcherMinimizerAtom* at2, sketcherMinimizerAtom* center); /* consider one additional level of bound atoms in the CIP algorithm to * break a tie */ static std::vector expandOneLevel(std::vector& oldV); /* if any ties between parent atoms was solved, assign two different scores to them. Also clear the medals for the next iteration */ static void finalizeScores(std::vector& v); /* medals are used to mark parent atoms according to the priorities of their children and also their numbers. */ static void assignMedals(std::vector& v); /* first atom will be the highest priority, subsequent will be based on * atoms that have already been picked, giving priorities to branches that * have been already been visited. friendsMask keeps track of parents that * have a child that has been already selected */ static void chooseFirstAndSortAccordingly(std::vector& V); /* if the two atoms share a ring, return it */ static sketcherMinimizerRing* shareARing(const sketcherMinimizerAtom* atom1, const sketcherMinimizerAtom* atom2); /* mirror the coordinates of at wrt bond */ static void mirrorCoordinates(sketcherMinimizerAtom* at, const sketcherMinimizerBond* bond); /* return the stereochemistry set in the wedges around the atom. 0 if not * assigned, 1 if R, -1 if S */ int readStereochemistry(bool readOnly = false); /* return a direction perpendicular to the atom's bonds average */ sketcherMinimizerPointF getSingleAdditionVector() const; static sketcherMinimizerPointF getSingleAdditionVector(const std::vector& ats); /* return true if the atom has valid 3d coordinates */ bool hasValid3DCoordinates() const; /* return true if the atom is a residue */ virtual bool isResidue() const; /* return true if atomicNumber represents a metal */ static bool isMetal(const unsigned int atomicNumber); sketcherMinimizerAtomChiralityInfo m_chiralityInfo; }; #endif // sketcherMINIMIZERATOM_H coordgenlibs-3.0.2/sketcherMinimizerBendInteraction.h000066400000000000000000000113331436654770400230450ustar00rootroot00000000000000/* * sketcherMinimizerBendInteraction.h * * Created by Nicola Zonta on 13/04/2010. * Copyright Schrodinger, LLC. All rights reserved. * */ #ifndef sketcherMINIMIZERBENDMINIMIZERINTERACTION #define sketcherMINIMIZERBENDMINIMIZERINTERACTION #include "sketcherMinimizerInteraction.h" #ifndef M_PI #define M_PI 3.1415926535897931 #endif /* forcefield class to represent angle bends */ class sketcherMinimizerBendInteraction : public sketcherMinimizerInteraction { public: sketcherMinimizerBendInteraction(sketcherMinimizerAtom* at1, sketcherMinimizerAtom* at2, sketcherMinimizerAtom* at3) : sketcherMinimizerInteraction(at1, at2) { atom3 = at3; restV = 120; k2 = 0.05f; // multipleSnap = false; isRing = false; } ~sketcherMinimizerBendInteraction() override = default; /* calculate energy associated with the current state */ void energy(float& e) override { float dA = angle() - restV; e += 0.5f * k * k2 * dA * dA * 10; // qDebug () << restV << " " << angle ()< 180) { target = 360 - target; // this is needed when the angle function is } // based on cos and only works in [0, 180[ . // not needed if using atan2 /* if (multipleSnap) { vector targets; targets .push_back(60); targets .push_back(90); targets .push_back(120); // targets .push_back(150); target = targets [0]; float distance = target - a; if (distance < 0) distance = -distance; for (unsigned int i =1; i < targets.size (); i++) { float newtarget = targets [i]; float newdistance = newtarget - a; if (newdistance < 0) newdistance = - newdistance; if (newdistance < distance) { target = newtarget; distance = newdistance; } } } */ float dA = target - a; energy(totalE); float x1 = atom1->coordinates.x(); float y1 = atom1->coordinates.y(); float x2 = atom2->coordinates.x(); float y2 = atom2->coordinates.y(); float x3 = atom3->coordinates.x(); float y3 = atom3->coordinates.y(); float v1x = x1 - x2; float v1y = y1 - y2; float v2x = x3 - x2; float v2y = y3 - y2; float v3x = x3 - x1; float v3y = y3 - y1; float newk2 = k2; // if (minimizationPhase < 1) newk2 *= 5; sketcherMinimizerPointF n1(v1y, -v1x); sketcherMinimizerPointF n2(v2y, -v2x); if ((n1.x() * v3x + n1.y() * v3y) > 0) { n1 *= -1; // dot product n1 v3 } if ((n2.x() * v3x + n2.y() * v3y) < 0) { n2 *= -1; // dot product n2 v3 } float q1 = sqrt(n1.x() * n1.x() + n1.y() * n1.y()); if (q1 < SKETCHER_EPSILON) { q1 = SKETCHER_EPSILON; } float q2 = sqrt(n2.x() * n2.x() + n2.y() * n2.y()); if (q2 < SKETCHER_EPSILON) { q2 = SKETCHER_EPSILON; } n1 /= q1; n2 /= q2; n1 *= k * newk2 * dA; n2 *= k * newk2 * dA; atom1->force += n1; atom3->force += n2; atom2->force -= n1 + n2; }; /* calculate angle between the three atoms */ float angle() { float x1 = atom1->coordinates.x(); float y1 = atom1->coordinates.y(); float x2 = atom2->coordinates.x(); float y2 = atom2->coordinates.y(); float x3 = atom3->coordinates.x(); float y3 = atom3->coordinates.y(); float v1x = x1 - x2; float v1y = y1 - y2; float v2x = x3 - x2; float v2y = y3 - y2; float d = sqrt(v1x * v1x + v1y * v1y) * sqrt(v2x * v2x + v2y * v2y); if (d < SKETCHER_EPSILON) { d = SKETCHER_EPSILON; } float cosine = (v1x * v2x + v1y * v2y) / d; if (cosine < -1) { cosine = -1; } else if (cosine > 1) { cosine = 1; } return float((acos(cosine)) * 180 / M_PI); } sketcherMinimizerAtom* atom3; float k2; // bool multipleSnap; // used in tetracoordinated centers to get 120 - 90 // -90 -60 angles bool isRing; }; #endif // sketcherMINIMIZERBENDINTERACTION coordgenlibs-3.0.2/sketcherMinimizerBond.cpp000066400000000000000000000142331436654770400212140ustar00rootroot00000000000000/* Contributors: Nicola Zonta Copyright Schrodinger, LLC. All rights reserved */ #include "sketcherMinimizerBond.h" #include "sketcherMinimizerAtom.h" #include "sketcherMinimizerMaths.h" #include "sketcherMinimizerMolecule.h" #include "sketcherMinimizerRing.h" #include using namespace std; sketcherMinimizerAtom* sketcherMinimizerBond::startAtomCIPFirstNeighbor() const { if (bondOrder != 2) { return nullptr; } sketcherMinimizerAtom* a = startAtom; if (a->neighbors.size() == 2) { if (a->neighbors[0] == endAtom) { return a->neighbors[1]; } else { return a->neighbors[0]; } } else if (a->neighbors.size() == 3) { std::vector ats; for (sketcherMinimizerAtom* n : a->neighbors) { if (n != endAtom) { ats.push_back(n); } } if (ats.size() == 2) { return sketcherMinimizerAtom::CIPPriority(ats[0], ats[1], startAtom); } return nullptr; } else { return nullptr; } } sketcherMinimizerAtom* sketcherMinimizerBond::endAtomCIPFirstNeighbor() const { if (bondOrder != 2) { return nullptr; } sketcherMinimizerAtom* a = endAtom; if (a->neighbors.size() == 2) { if (a->neighbors[0] == startAtom) { return a->neighbors[1]; } else { return a->neighbors[0]; } } else if (a->neighbors.size() == 3) { std::vector ats; for (sketcherMinimizerAtom* n : a->neighbors) { if (n != startAtom) { ats.push_back(n); } } if (ats.size() == 2) { return sketcherMinimizerAtom::CIPPriority(ats[0], ats[1], endAtom); } return nullptr; } else { return nullptr; } } void sketcherMinimizerBond::setAbsoluteStereoFromStereoInfo() { if (isStereo() && m_stereo.atom1 != nullptr && m_stereo.atom2 != nullptr) { auto firstCIPNeighborStart = startAtomCIPFirstNeighbor(); auto firstCIPNeighborEnd = endAtomCIPFirstNeighbor(); if (firstCIPNeighborStart != nullptr && firstCIPNeighborEnd) { bool invert = false; if (m_stereo.atom1 != firstCIPNeighborStart && m_stereo.atom1 != firstCIPNeighborEnd) { invert = !invert; } if (m_stereo.atom2 != firstCIPNeighborStart && m_stereo.atom2 != firstCIPNeighborEnd) { invert = !invert; } bool settingIsZ = (m_stereo.stereo == sketcherMinimizerBondStereoInfo::cis); if (invert) { settingIsZ = !settingIsZ; } isZ = settingIsZ; } } if (m_stereo.stereo == sketcherMinimizerBondStereoInfo::unspecified) { m_ignoreZE = true; } } bool sketcherMinimizerBond::checkStereoChemistry() const { if (!isStereo()) { return true; } if (isInSmallRing()) { return true; } sketcherMinimizerAtom* firstCIPNeighborStart = startAtomCIPFirstNeighbor(); if (firstCIPNeighborStart == nullptr) { return true; } sketcherMinimizerAtom* firstCIPNeighborEnd = endAtomCIPFirstNeighbor(); if (firstCIPNeighborEnd == nullptr) { return true; } return (sketcherMinimizerMaths::sameSide( firstCIPNeighborStart->getCoordinates(), firstCIPNeighborEnd->getCoordinates(), getStartAtom()->getCoordinates(), getEndAtom()->getCoordinates()) == isZ); } bool sketcherMinimizerBond::isInSmallRing() const { for (auto ring : rings) { if (!ring->isMacrocycle()) { return true; } } return false; } bool sketcherMinimizerBond::isInMacrocycle() const { for (auto ring : rings) { if (ring->isMacrocycle()) { return true; } } return false; } bool sketcherMinimizerBond::isTerminal() const { return (getStartAtom()->getBonds().size() == 1 || getEndAtom()->getBonds().size() == 1); } bool sketcherMinimizerBond::isInterFragment() const { if (getStartAtom()->getBonds().size() == 1) { return false; } if (getEndAtom()->getBonds().size() == 1) { return false; } if (sketcherMinimizerAtom::shareARing(getStartAtom(), getEndAtom())) { return false; } if (isStereo()) { return false; } return true; } bool sketcherMinimizerBond::markedAsCis(sketcherMinimizerAtom* atom1, sketcherMinimizerAtom* atom2) const { sketcherMinimizerAtom* firstCIPNeighbor1 = startAtomCIPFirstNeighbor(); sketcherMinimizerAtom* firstCIPNeighbor2 = endAtomCIPFirstNeighbor(); bool cis = isZ; if (atom1 != firstCIPNeighbor1 && atom1 != firstCIPNeighbor2) { cis = !cis; } if (atom2 != firstCIPNeighbor1 && atom2 != firstCIPNeighbor2) { cis = !cis; } return cis; } bool sketcherMinimizerBond::isStereo() const { if (bondOrder != 2) { return false; } if (m_ignoreZE) { return false; } sketcherMinimizerRing* ring = sketcherMinimizerAtom::shareARing(getStartAtom(), getEndAtom()); return !(ring && !ring->isMacrocycle()); } void sketcherMinimizerBond::flip() { size_t totalAtomsNumber = getStartAtom()->getMolecule()->getAtoms().size(); vector atoms = getStartAtom()->getSubmolecule(getEndAtom()); if (atoms.size() > totalAtomsNumber / 2) { atoms = getEndAtom()->getSubmolecule(getStartAtom()); } vector allBonds = getStartAtom()->getMolecule()->getBonds(); for (sketcherMinimizerAtom* atom : atoms) { sketcherMinimizerAtom::mirrorCoordinates(atom, this); } for (sketcherMinimizerBond* bond : allBonds) { if (find(atoms.begin(), atoms.end(), bond->getStartAtom()) != atoms.end() && find(atoms.begin(), atoms.end(), bond->getEndAtom()) != atoms.end()) { bond->isWedge = !bond->isWedge; } } } coordgenlibs-3.0.2/sketcherMinimizerBond.h000066400000000000000000000072651436654770400206700ustar00rootroot00000000000000/* * sketcherMinimizerBond.h * * Created by Nicola Zonta on 03/05/2010. * Copyright Schrodinger, LLC. All rights reserved. * */ #ifndef sketcherMINIMIZERBOND_H #define sketcherMINIMIZERBOND_H #include "CoordgenConfig.hpp" #include #include class sketcherMinimizerRing; class sketcherMinimizerAtom; struct sketcherMinimizerBondStereoInfo { enum sketcherMinimizerBondStereo { cis, trans, unspecified }; sketcherMinimizerAtom* atom1 = nullptr; sketcherMinimizerAtom* atom2 = nullptr; sketcherMinimizerBondStereo stereo = unspecified; }; /* class to represent a covalent bond */ class EXPORT_COORDGEN sketcherMinimizerBond { public: sketcherMinimizerBond() : rings() {} sketcherMinimizerBond(sketcherMinimizerAtom* at1, sketcherMinimizerAtom* at2) : sketcherMinimizerBond() { startAtom = at1; endAtom = at2; } virtual ~sketcherMinimizerBond() = default; virtual bool isResidueInteraction() { return false; } sketcherMinimizerAtom* startAtom = nullptr; sketcherMinimizerAtom* endAtom = nullptr; sketcherMinimizerAtom* getStartAtom() const { return startAtom; } sketcherMinimizerAtom* getEndAtom() const { return endAtom; } /* return bond order */ int getBondOrder() const { return bondOrder; } void setBondOrder(int order) { bondOrder = order; } void setStereoChemistry(sketcherMinimizerBondStereoInfo stereo) { m_stereo = stereo; } void setAbsoluteStereoFromStereoInfo(); /* return true if the bond is part of a small ring (i.e. 8 members or less) */ bool isInSmallRing() const; /* return true if the bond is part of a macrocycle */ bool isInMacrocycle() const; /* return true if the bond is to a terminal atom */ bool isTerminal() const; /* does this bond separate two rigid fragments? i.e. is bond a single rotatable bond to a non-terminal atom? */ bool isInterFragment() const; bool isStereo() const; /* given atom1 and atom2 as substituents on the two sides of a double bond, should they be put in cis? */ bool markedAsCis(sketcherMinimizerAtom* atom1, sketcherMinimizerAtom* atom2) const; /* flip the current bond, mirroring the coordinates of all the atoms on one * side of it */ void flip(); /* get the atom bound to the start atom of the bond with the highest CIP * priority */ sketcherMinimizerAtom* startAtomCIPFirstNeighbor() const; /* get the atom bound to the end atom of the bond with the highest CIP * priority */ sketcherMinimizerAtom* endAtomCIPFirstNeighbor() const; /* return true if the E/Z stereochemistry as read from the atoms coordinates * matches the label */ bool checkStereoChemistry() const; int bondOrder{1}; bool skip{false}; bool isZEActive{false}; // does it have a Z and E form? bool isZ{false}; // used for double bonds to distinguish Z from E form. // bonds default to E int m_chmN = -1; // idx of the corresponding ChmAtom if molecule comes from 3d sketcherMinimizerBondStereoInfo m_stereo; bool isWedge{false}; bool isReversed{false}; bool hasStereochemistryDisplay{false}; bool _SSSRVisited{false}; bool _SSSRParentAtStart{true}; bool m_ignoreZE{false}; sketcherMinimizerBond* _SSSRParent{nullptr}; /*this modifies the penalty for crossing this bond. scores < 1 indicate bonds that can be crossed without compromising aesthetics too much (e.g. residue interactions) */ float crossingBondPenaltyMultiplier{1.f}; std::vector rings; }; #endif // sketcherMINIMIZERBOND_H coordgenlibs-3.0.2/sketcherMinimizerClashInteraction.h000066400000000000000000000043361436654770400232340ustar00rootroot00000000000000/* * sketcherMinimizerClashInteraction.h * * Created by Nicola Zonta on 19/04/2010. * Copyright Schrodinger, LLC. All rights reserved. * */ #ifndef sketcherMINIMIZERCLASHMINIMIZERINTERACTION #define sketcherMINIMIZERCLASHMINIMIZERINTERACTION #include "sketcherMinimizerInteraction.h" #include "sketcherMinimizerMaths.h" #include /* forcefield clash */ class sketcherMinimizerClashInteraction : public sketcherMinimizerInteraction { public: sketcherMinimizerClashInteraction(sketcherMinimizerAtom* at1, sketcherMinimizerAtom* at2, sketcherMinimizerAtom* at3) : sketcherMinimizerInteraction(at1, at2) { atom3 = at3; restV = 900; k2 = 0.1f; } ~sketcherMinimizerClashInteraction() override = default; /* calculate the energy of the clash */ void energy(float& e) override { squaredDistance = sketcherMinimizerMaths::squaredDistancePointSegment( atom2->coordinates, atom1->coordinates, atom3->coordinates); if (squaredDistance > restV) { return; } float dr = restV - squaredDistance; if (dr > 0) { e += 0.5f * k * k2 * dr; } }; /* calculate the forces of the clash and apply them */ void score(float& totalE, bool skipForce = false) override { energy(totalE); if (skipForce) { return; } if (squaredDistance > restV) { return; } sketcherMinimizerPointF atomP = atom2->coordinates; sketcherMinimizerPointF bondP1 = atom1->coordinates; sketcherMinimizerPointF bondP2 = atom3->coordinates; sketcherMinimizerPointF projection = sketcherMinimizerMaths::projectPointOnLine(atomP, bondP1, bondP2); sketcherMinimizerPointF f = atomP - projection; f.normalize(); f *= (restV - squaredDistance) * k * k2; atom2->force += f; atom1->force -= f * 0.5; atom3->force -= f * 0.5; } bool isClash() override { return true; }; float k2; sketcherMinimizerAtom* atom3; private: float squaredDistance; }; #endif // sketcherMINIMIZERCLASHINTERACTION coordgenlibs-3.0.2/sketcherMinimizerConstraintInteraction.h000066400000000000000000000023121436654770400243160ustar00rootroot00000000000000/* * sketcherMinimizerConstraintInteraction.h * * Created by Nicola Zonta on 7/02/2019. * Copyright Schrodinger, LLC. All rights reserved. * */ #ifndef sketcherMINIMIZERCONSTRAINTINTERACTION #define sketcherMINIMIZERCONSTRAINTINTERACTION #include "sketcherMinimizerInteraction.h" static const float CONSTRAINT_SCALE = .5f; /* force field bond stretches */ class sketcherMinimizerConstraintInteraction : public sketcherMinimizerInteraction { public: sketcherMinimizerConstraintInteraction( sketcherMinimizerAtom* at1, const sketcherMinimizerPointF& position) : sketcherMinimizerInteraction(at1, at1), origin(position) { k = CONSTRAINT_SCALE; } ~sketcherMinimizerConstraintInteraction() override = default; /* calculate the energy of the interaction */ void energy(float& e) override { e += k * sketcherMinimizerMaths::squaredDistance(atom1->coordinates, origin); } /* calculate the forces and apply them */ void score(float& totalE, bool = false) override { energy(totalE); } private: sketcherMinimizerPointF origin; }; #endif // sketcherMINIMIZERCONSTRAINTINTERACTION coordgenlibs-3.0.2/sketcherMinimizerEZConstrainInteraction.h000066400000000000000000000062011436654770400243720ustar00rootroot00000000000000/* * sketcherMinimizerEZConstrainInteraction.h * * Created by Nicola Zonta * Copyright Schrodinger, LLC. All rights reserved. * */ #ifndef sketcherMINIMIZEREZCONSTRAININTERACTION #define sketcherMINIMIZEREZCONSTRAININTERACTION #include "sketcherMinimizerInteraction.h" /* forcefield constrain to avoid EZ inversion */ class sketcherMinimizerEZConstrainInteraction : public sketcherMinimizerInteraction { public: sketcherMinimizerEZConstrainInteraction(sketcherMinimizerAtom* at1, sketcherMinimizerAtom* at2, sketcherMinimizerAtom* at3, sketcherMinimizerAtom* at4, bool isZ) : sketcherMinimizerInteraction(at1, at2) { atom3 = at3; atom4 = at4; m_isZ = isZ; m_forceMovement = false; }; ~sketcherMinimizerEZConstrainInteraction() override = default; /* calculate the energy of the interaction */ void energy(float& e) override { if (inversion()) { e += 5000; } }; /* calculate the forces and apply them */ void score(float& totalE, bool = false) override { if (!inversion()) { return; } energy(totalE); sketcherMinimizerPointF projection1 = sketcherMinimizerMaths::projectPointOnLine( atom1->coordinates, atom2->coordinates, atom3->coordinates); sketcherMinimizerPointF projection2 = sketcherMinimizerMaths::projectPointOnLine( atom4->coordinates, atom2->coordinates, atom3->coordinates); sketcherMinimizerAtom* sideAtom = atom1; sketcherMinimizerAtom* doubleBondAtom = atom2; sketcherMinimizerPointF projection = projection1; if (sketcherMinimizerMaths::squaredDistance(atom1->coordinates, projection1) > sketcherMinimizerMaths::squaredDistance(atom4->coordinates, projection2)) { sideAtom = atom4; doubleBondAtom = atom3; projection = projection2; } sketcherMinimizerPointF force = projection - sideAtom->coordinates; if (m_forceMovement) { sideAtom->coordinates += force; doubleBondAtom->coordinates -= force; sideAtom->force = sketcherMinimizerPointF(0, 0); doubleBondAtom->force = sketcherMinimizerPointF(0, 0); } else { force.normalize(); force *= 10; sideAtom->force += force; doubleBondAtom->force -= force; } }; /* check if the E/Z configuration is inverted */ bool inversion() { return sketcherMinimizerMaths::sameSide( atom1->coordinates, atom4->coordinates, atom2->coordinates, atom3->coordinates) != m_isZ; } sketcherMinimizerAtom* atom3; sketcherMinimizerAtom* atom4; float k2; bool m_isZ; bool m_forceMovement; }; #endif // sketcherMINIMIZEREZCONSTRAININTERACTION coordgenlibs-3.0.2/sketcherMinimizerFragment.cpp000066400000000000000000000324161436654770400221000ustar00rootroot00000000000000/* Contributors: Nicola Zonta Copyright Schrodinger, LLC. All rights reserved */ #include "sketcherMinimizerFragment.h" #include "sketcherMinimizerAtom.h" #include "sketcherMinimizerBond.h" #include "sketcherMinimizerMaths.h" #include "sketcherMinimizerRing.h" static const float INVERTED_MACROCYCLE_BOND_PENALTY = 100.f; static const float SCALE_FRAGMENT_PENALTY = 500.f; static const float SCALE_ATOMS_PENALTY = 50.f; static const float ROTATE_FRAGMENT_PENALTY = 400.f; static const float BREAK_CHAIN_PENALTY = 10.f; static const float CHANGE_PARENT_BOND_PENALTY = 200.f; static const float FLIP_RING_PENALTY = 200.f; static const float FLIP_CONSTRAINED_FRAGMENT_PENALTY = 1000.f; static const int FLIP_FRAGMENT_TIER = 0; static const int INVERT_BOND_TIER = 1; static const int ROTATE_FRAGMENT_TIER = 3; static const int ELONGATE_PARENT_BOND_TIER = 2; static const int SCALE_ATOMS_TIER = 4; static const int FLIP_RING_TIER = 1; static const int SCALE_FRAGMENT_TIER = 5; CoordgenFragmentDOF::CoordgenFragmentDOF(sketcherMinimizerFragment* fragment) : m_currentState(0), m_optimalState(0), m_fragment(fragment) { } CoordgenFragmentDOF::~CoordgenFragmentDOF() = default; short unsigned int CoordgenFragmentDOF::getCurrentState() { return m_currentState; } void CoordgenFragmentDOF::setState(short unsigned int state) { m_currentState = state; } void CoordgenFragmentDOF::storeCurrentValueAsOptimal() { m_optimalState = m_currentState; } void CoordgenFragmentDOF::setToOptimalValue() { m_currentState = m_optimalState; } void CoordgenFragmentDOF::changeState() { m_currentState++; m_currentState = m_currentState % numberOfStates(); } void CoordgenFragmentDOF::addAtom(sketcherMinimizerAtom* atom) { m_atoms.push_back(atom); atom->fragment->addDofToAtom(atom, this); } float CoordgenFragmentDOF::getCurrentPenalty() const { return 0.f; } sketcherMinimizerFragment* CoordgenFragmentDOF::getFragment() const { return m_fragment; } CoordgenFlipFragmentDOF::CoordgenFlipFragmentDOF( sketcherMinimizerFragment* fragment) : CoordgenFragmentDOF(fragment) { } float CoordgenFlipFragmentDOF::getCurrentPenalty() const { float penalty = 0.f; if (m_currentState != 0 && m_fragment->constrainedFlip) { penalty += FLIP_CONSTRAINED_FRAGMENT_PENALTY; } if (m_fragment->isChain && m_fragment->getParent() && m_fragment->getParent()->isChain) { penalty += BREAK_CHAIN_PENALTY; } return penalty; } int CoordgenFlipFragmentDOF::numberOfStates() const { if (m_fragment->getParent() == nullptr) { return 1; } return 2; } int CoordgenFlipFragmentDOF::tier() const { return FLIP_FRAGMENT_TIER; } void CoordgenFlipFragmentDOF::apply() const { if (m_currentState != 0) { for (auto& atom : m_fragment->_coordinates) { atom.first->coordinates.setY(-atom.first->coordinates.y()); } } } CoordgenScaleFragmentDOF::CoordgenScaleFragmentDOF( sketcherMinimizerFragment* fragment) : CoordgenFragmentDOF(fragment) { } int CoordgenScaleFragmentDOF::numberOfStates() const { if (m_fragment->getRings().empty()) { return 1; } return 5; } int CoordgenScaleFragmentDOF::tier() const { return SCALE_FRAGMENT_TIER; } void CoordgenScaleFragmentDOF::apply() const { if (m_currentState != 0) { auto scale = static_cast(pow(1.4, (m_currentState + 1) / 2)); if (m_currentState % 2 == 0) { scale = 1 / scale; } for (auto& atom : m_fragment->_coordinates) { atom.first->setCoordinates(atom.first->getCoordinates() * scale); } } } float CoordgenScaleFragmentDOF::getCurrentPenalty() const { if (m_currentState != 0) { return SCALE_FRAGMENT_PENALTY * ((m_currentState + 1) / 2); } return 0.f; } CoordgenScaleAtomsDOF::CoordgenScaleAtomsDOF(sketcherMinimizerAtom* pivotAtom) : CoordgenFragmentDOF(pivotAtom->getFragment()), m_pivotAtom(pivotAtom) { } int CoordgenScaleAtomsDOF::numberOfStates() const { return 2; } int CoordgenScaleAtomsDOF::tier() const { return SCALE_ATOMS_TIER; } void CoordgenScaleAtomsDOF::apply() const { if (m_currentState != 0) { float scale = 0.4f; for (auto atom : m_atoms) { auto distance = atom->getCoordinates() - m_pivotAtom->getCoordinates(); atom->setCoordinates(distance * scale + m_pivotAtom->getCoordinates()); } } } float CoordgenScaleAtomsDOF::getCurrentPenalty() const { if (m_currentState != 0) { return SCALE_ATOMS_PENALTY * m_atoms.size(); } return 0.f; } CoordgenChangeParentBondLengthFragmentDOF:: CoordgenChangeParentBondLengthFragmentDOF( sketcherMinimizerFragment* fragment) : CoordgenFragmentDOF(fragment) { } int CoordgenChangeParentBondLengthFragmentDOF::numberOfStates() const { return 7; } int CoordgenChangeParentBondLengthFragmentDOF::tier() const { return ELONGATE_PARENT_BOND_TIER; } void CoordgenChangeParentBondLengthFragmentDOF::apply() const { if (m_currentState != 0) { auto scale = static_cast(pow(1.6, (m_currentState + 1) / 2)); if (m_currentState % 2 == 0) { scale = 1 / scale; } float MoveBy = BONDLENGTH * (scale - 1); for (auto& atom : m_fragment->_coordinates) { atom.first->coordinates.setX(atom.first->coordinates.x() + MoveBy); } } } float CoordgenChangeParentBondLengthFragmentDOF::getCurrentPenalty() const { if (m_currentState != 0) { return CHANGE_PARENT_BOND_PENALTY * ((m_currentState + 1) / 2); } return 0.f; } CoordgenRotateFragmentDOF::CoordgenRotateFragmentDOF( sketcherMinimizerFragment* fragment) : CoordgenFragmentDOF(fragment) { } int CoordgenRotateFragmentDOF::numberOfStates() const { if (m_fragment->getParent() == nullptr) { return 1; } return 5; } int CoordgenRotateFragmentDOF::tier() const { return ROTATE_FRAGMENT_TIER; } void CoordgenRotateFragmentDOF::apply() const { if (m_currentState != 0) { auto angle = static_cast(M_PI / 180 * 15 * ((m_currentState + 1) / 2)); if (m_currentState % 2 == 0) { angle = -angle; } float sine = sin(angle); float cosine = cos(angle); for (auto& atom : m_fragment->_coordinates) { sketcherMinimizerPointF origin(-BONDLENGTH, 0); sketcherMinimizerPointF coords = atom.first->getCoordinates() - origin; coords.rotate(sine, cosine); atom.first->setCoordinates(coords + origin); } } } float CoordgenRotateFragmentDOF::getCurrentPenalty() const { if (m_currentState != 0) { return ROTATE_FRAGMENT_PENALTY * ((m_currentState + 1) / 2); } return 0.f; } CoordgenInvertBondDOF::CoordgenInvertBondDOF(sketcherMinimizerAtom* pivotAtom, sketcherMinimizerAtom* boundAtom) : CoordgenFragmentDOF(pivotAtom->getFragment()), m_pivotAtom(pivotAtom), m_boundAtom(boundAtom) { assert(pivotAtom->bondTo(boundAtom) != nullptr); addAtom(boundAtom); } int CoordgenInvertBondDOF::numberOfStates() const { return 2; } int CoordgenInvertBondDOF::tier() const { return INVERT_BOND_TIER; } void CoordgenInvertBondDOF::apply() const { if (m_currentState != 0) { sketcherMinimizerPointF pivot = m_pivotAtom->getCoordinates(); sketcherMinimizerPointF bondDir = m_boundAtom->getCoordinates() - pivot; sketcherMinimizerPointF normal(bondDir.y(), -bondDir.x()); sketcherMinimizerPointF point1 = pivot + normal; sketcherMinimizerPointF point2 = pivot - normal; for (auto& atom : m_atoms) { atom->setCoordinates(sketcherMinimizerMaths::mirrorPoint( atom->getCoordinates(), point1, point2)); } } } float CoordgenInvertBondDOF::getCurrentPenalty() const { if (m_currentState != 0) { return INVERTED_MACROCYCLE_BOND_PENALTY; } return 0.f; } CoordgenFlipRingDOF::CoordgenFlipRingDOF( sketcherMinimizerRing* ring, const std::vector& fusionAtoms) : CoordgenFragmentDOF((*fusionAtoms.begin())->getFragment()), m_pivotAtom1(*(fusionAtoms.begin())), m_pivotAtom2(*(fusionAtoms.rbegin())), m_penalty(std::abs(int(ring->size() - 2 * fusionAtoms.size() + 2))) { for (auto atom : ring->getAtoms()) { addAtom(atom); } } int CoordgenFlipRingDOF::numberOfStates() const { return 2; } int CoordgenFlipRingDOF::tier() const { return FLIP_RING_TIER; } void CoordgenFlipRingDOF::apply() const { if (m_currentState != 0) { for (auto& atom : m_atoms) { atom->setCoordinates(sketcherMinimizerMaths::mirrorPoint( atom->getCoordinates(), m_pivotAtom1->getCoordinates(), m_pivotAtom2->getCoordinates())); } } } float CoordgenFlipRingDOF::getCurrentPenalty() const { if (m_currentState != 0) { return FLIP_RING_PENALTY * m_penalty; } return 0.f; } sketcherMinimizerFragment::sketcherMinimizerFragment() : fixed(false), isTemplated(false), constrained(false), isChain(false), _bondToParent(nullptr), longestChainFromHere(0.f), numberOfChildrenAtoms(0), numberOfChildrenAtomsRank(0.f), m_parent(nullptr) { m_dofs.push_back(new CoordgenFlipFragmentDOF(this)); // m_dofs.push_back(new CoordgenScaleFragmentDOF(this)); m_dofs.push_back(new CoordgenChangeParentBondLengthFragmentDOF(this)); m_dofs.push_back(new CoordgenRotateFragmentDOF(this)); } sketcherMinimizerFragment::~sketcherMinimizerFragment() { for (auto dof : m_dofs) { delete dof; } } void sketcherMinimizerFragment::addDof(CoordgenFragmentDOF* dof) { m_dofs.push_back(dof); } const std::vector& sketcherMinimizerFragment::getDofs() { return m_dofs; } unsigned int sketcherMinimizerFragment::totalWeight() const { int n = 0; for (auto m_atom : m_atoms) { n += m_atom->atomicNumber + m_atom->_implicitHs; } return n; } unsigned int sketcherMinimizerFragment::countDoubleBonds() const { int n = 0; for (auto m_bond : m_bonds) { if (m_bond->bondOrder == 2) { ++n; } } return n; } unsigned int sketcherMinimizerFragment::countHeavyAtoms() const { int n = 0; for (auto m_atom : m_atoms) { if (m_atom->atomicNumber != 6) { ++n; } } return n; } unsigned int sketcherMinimizerFragment::countConstrainedAtoms() const { int n = 0; for (auto atom : m_atoms) { if (atom->constrained) { ++n; } } return n; } unsigned int sketcherMinimizerFragment::countFixedAtoms() const { int n = 0; for (auto atom : m_atoms) { if (atom->fixed) { ++n; } } return n; } void sketcherMinimizerFragment::addAtom(sketcherMinimizerAtom* atom) { m_atoms.push_back(atom); atom->setFragment(this); } void sketcherMinimizerFragment::addBond(sketcherMinimizerBond* bond) { m_bonds.push_back(bond); } void sketcherMinimizerFragment::addRing(sketcherMinimizerRing* ring) { m_rings.push_back(ring); } void sketcherMinimizerFragment::setAllCoordinatesToTemplate() { for (sketcherMinimizerAtom* atom : m_atoms) { atom->setCoordinatesToTemplate(); } if (_bondToParent) { _bondToParent->startAtom->setCoordinatesToTemplate(); _bondToParent->endAtom->setCoordinatesToTemplate(); } for (sketcherMinimizerFragment* child : _children) { child->_bondToParent->startAtom->setCoordinatesToTemplate(); child->_bondToParent->endAtom->setCoordinatesToTemplate(); } } void sketcherMinimizerFragment::storeCoordinateInformation() { _coordinates.clear(); sketcherMinimizerPointF origin(0.f, 0.f); float angle = 0.f; if (_bondToParent) { origin = _bondToParent->endAtom->getCoordinates(); angle = atan2(_bondToParent->startAtom->coordinates.y() - origin.y(), -_bondToParent->startAtom->coordinates.x() + origin.x()); } else { if (!constrained && !fixed) { origin = m_atoms[0]->getCoordinates(); } } float cosine = cos(-angle); float sine = sin(-angle); for (auto at : m_atoms) { sketcherMinimizerPointF c = at->coordinates - origin; c.rotate(sine, cosine); _coordinates[at] = c; } for (auto child : _children) { sketcherMinimizerAtom* at = child->_bondToParent->endAtom; sketcherMinimizerPointF c = at->coordinates - origin; c.rotate(sine, cosine); _coordinates[at] = c; } } void sketcherMinimizerFragment::setCoordinates( const sketcherMinimizerPointF& position, float angle) { float sine = sin(angle); float cosine = cos(angle); assert(_coordinates.size() == m_atoms.size() + _children.size()); for (auto& atom : _coordinates) { atom.first->setCoordinates(atom.second); } for (auto dof : m_dofs) { dof->apply(); } for (auto& coords : _coordinates) { sketcherMinimizerAtom* atom = coords.first; sketcherMinimizerPointF initialCoordinates = atom->getCoordinates(); initialCoordinates.rotate(sine, cosine); atom->setCoordinates(initialCoordinates + position); } } coordgenlibs-3.0.2/sketcherMinimizerFragment.h000066400000000000000000000206611436654770400215440ustar00rootroot00000000000000/* * * * Created by Nicola Zonta on 03/05/2010. * Copyright Schrodinger, LLC. All rights reserved. * */ #ifndef sketcherMINIMIZERFRAGMENT #define sketcherMINIMIZERFRAGMENT #include "sketcherMinimizerMaths.h" #include #include #include #include #include "CoordgenConfig.hpp" class sketcherMinimizerAtom; class sketcherMinimizerBond; class sketcherMinimizerRing; class sketcherMinimizerFragment; /* abstract class for fragment degree of freedom */ class CoordgenFragmentDOF { public: CoordgenFragmentDOF(sketcherMinimizerFragment* fragment); virtual ~CoordgenFragmentDOF(); /* set the current value as the optimal value for this DOF */ void storeCurrentValueAsOptimal(); /* load the optimal value */ void setToOptimalValue(); /* cycle through the various possible values of this DOF */ void changeState(); /* add the given atom to the DoF */ void addAtom(sketcherMinimizerAtom* atom); /* get the penalty associated with the current state */ virtual float getCurrentPenalty() const; /* return the number of states */ virtual int numberOfStates() const = 0; /* return the tier of this DoF. Lower tier DoFs are considered first in the * minimization */ virtual int tier() const = 0; /* apply the current DoF value to the atoms coordinates */ virtual void apply() const = 0; /* return the fragment this DoF refers to */ sketcherMinimizerFragment* getFragment() const; /* return the current state */ short unsigned int getCurrentState(); /* set the given state as current */ void setState(short unsigned int state); short unsigned int m_currentState, m_optimalState; protected: std::vector m_atoms; sketcherMinimizerFragment* m_fragment; }; /* change the angle of the fragment wrt its parent */ class CoordgenRotateFragmentDOF : public CoordgenFragmentDOF { public: CoordgenRotateFragmentDOF(sketcherMinimizerFragment* fragment); int numberOfStates() const override; int tier() const override; void apply() const override; float getCurrentPenalty() const override; }; /* flip the fragment along the bond to its parent */ class CoordgenFlipFragmentDOF : public CoordgenFragmentDOF { public: CoordgenFlipFragmentDOF(sketcherMinimizerFragment* fragment); int numberOfStates() const override; int tier() const override; void apply() const override; float getCurrentPenalty() const override; }; /* scale the coordinates of the given atoms */ class CoordgenScaleAtomsDOF : public CoordgenFragmentDOF { public: CoordgenScaleAtomsDOF(sketcherMinimizerAtom* pivotAtom); int numberOfStates() const override; int tier() const override; void apply() const override; float getCurrentPenalty() const override; private: sketcherMinimizerAtom* m_pivotAtom; }; /* scale the coordinates of the whole fragment */ class CoordgenScaleFragmentDOF : public CoordgenFragmentDOF { public: CoordgenScaleFragmentDOF(sketcherMinimizerFragment* fragment); int numberOfStates() const override; int tier() const override; void apply() const override; float getCurrentPenalty() const override; }; /* extend or shorten the bond to the parent fragment */ class CoordgenChangeParentBondLengthFragmentDOF : public CoordgenFragmentDOF { public: CoordgenChangeParentBondLengthFragmentDOF( sketcherMinimizerFragment* fragment); int numberOfStates() const override; int tier() const override; void apply() const override; float getCurrentPenalty() const override; }; /* Invert the direction of a bond (e.g. a substituent to a macrocycle can be placed towards the inside of the ring) */ class CoordgenInvertBondDOF : public CoordgenFragmentDOF { public: CoordgenInvertBondDOF(sketcherMinimizerAtom* pivotAtom, sketcherMinimizerAtom* boundAtom); int numberOfStates() const override; int tier() const override; void apply() const override; float getCurrentPenalty() const override; private: sketcherMinimizerAtom* m_pivotAtom; sketcherMinimizerAtom* m_boundAtom; }; /* flip a ring fused with another with more than 2 bonds (e.g. ring in a * macrocycle) */ class CoordgenFlipRingDOF : public CoordgenFragmentDOF { public: CoordgenFlipRingDOF(sketcherMinimizerRing* ring, const std::vector& fusionAtoms); int numberOfStates() const override; int tier() const override; void apply() const override; float getCurrentPenalty() const override; private: sketcherMinimizerAtom* m_pivotAtom1; sketcherMinimizerAtom* m_pivotAtom2; int m_penalty; }; /* class that represents a rigid molecular fragment */ class EXPORT_COORDGEN sketcherMinimizerFragment { public: sketcherMinimizerFragment(); ~sketcherMinimizerFragment(); /* return the total weight of the fragment */ unsigned int totalWeight() const; /* return the number of double bonds in the fragment */ unsigned int countDoubleBonds() const; /* return the number of heavy atoms in the fragment */ unsigned int countHeavyAtoms() const; /* return the number of constrained atoms in the fragment */ unsigned int countConstrainedAtoms() const; /* return the number of fixed atoms in the fragment */ unsigned int countFixedAtoms() const; /* add an atom to this fragment */ void addAtom(sketcherMinimizerAtom* atom); /* add a bond to this fragment */ void addBond(sketcherMinimizerBond* bond); /* add a ring to this fragment */ void addRing(sketcherMinimizerRing* ring); /* add a degree of freedom to this fragment */ void addDof(CoordgenFragmentDOF* dof); /* get all degrees of freedom of this fragment */ const std::vector& getDofs(); /* mark the given bond as interfragment */ void addInterFragmentBond(sketcherMinimizerBond* bond) { _interFragmentBonds.push_back(bond); } std::vector getAtoms() const { return m_atoms; } std::vector getBonds() const { return m_bonds; } std::vector getRings() const { return m_rings; } std::vector& atoms() { return m_atoms; } std::vector& bonds() { return m_bonds; } std::vector& rings() { return m_rings; } /* return the parent fragment */ sketcherMinimizerFragment* getParent() const { return m_parent; } /* set the given fragment as parent */ void setParent(sketcherMinimizerFragment* parent) { m_parent = parent; } /* add the given degree of freedom to the given atom which will be modified * by it */ void addDofToAtom(sketcherMinimizerAtom* atom, CoordgenFragmentDOF* dof) { m_dofsForAtom[atom].push_back(dof); } /* return the degrees of freedom that would modify the given atom */ std::vector& getDofsOfAtom(sketcherMinimizerAtom* atom) { return m_dofsForAtom[atom]; } /* set the coordinates of each atom to the template coordinates */ void setAllCoordinatesToTemplate(); /* save coordinates information */ void storeCoordinateInformation(); std::vector _interFragmentBonds; std::vector _children; std::map _coordinates; sketcherMinimizerPointF _bondToParentCoordinatesStart; sketcherMinimizerPointF _bondToParentCoordinatesEnd; bool fixed, isTemplated, constrained, constrainedFlip; bool isChain; sketcherMinimizerBond* _bondToParent; float longestChainFromHere; size_t numberOfChildrenAtoms; float numberOfChildrenAtomsRank; /* translate and rotate the fragment and set the resulting coordinates to * every atom */ void setCoordinates(const sketcherMinimizerPointF& position, float angle); /* get the dof that refers to flipping this fragment */ CoordgenFragmentDOF* getFlipDof() const { return m_dofs[0]; } private: sketcherMinimizerFragment* m_parent; std::vector m_atoms; std::vector m_bonds; std::vector m_rings; std::vector m_dofs; std::map> m_dofsForAtom; }; #endif // sketcherMINIMIZERFRAGMENT coordgenlibs-3.0.2/sketcherMinimizerInteraction.h000066400000000000000000000037511436654770400222610ustar00rootroot00000000000000/* * sketcherMinimizerInteraction.h * * Created by Nicola Zonta on 13/04/2010. * Copyright Schrodinger, LLC. All rights reserved. * */ #ifndef sketcherMINIMIZERINTERACTION #define sketcherMINIMIZERINTERACTION #include "sketcherMinimizerAtom.h" /* abstract class for force field interactions */ class sketcherMinimizerInteraction { public: sketcherMinimizerInteraction(sketcherMinimizerAtom* at1, sketcherMinimizerAtom* at2) { atom1 = at1; atom2 = at2; k = 1.f; restV = 50; // minimizationPhase = 0; }; virtual ~sketcherMinimizerInteraction() = default; /* return energy associated with it */ virtual void energy(float& e) { sketcherMinimizerPointF l = atom1->coordinates - atom2->coordinates; float dr = sqrt(l.x() * l.x() + l.y() * l.y()) - restV; e += 0.5f * k * dr * dr; }; /* calculate and apply forces */ virtual void score(float& totalE, bool = false) { sketcherMinimizerPointF l = atom1->coordinates - atom2->coordinates; if (l.x() > 0 && l.x() < SKETCHER_EPSILON) { l.setX(SKETCHER_EPSILON); } else if (l.x() < 0 && l.x() > -SKETCHER_EPSILON) { l.setX(-SKETCHER_EPSILON); } float delta = 0.05f; float e1 = 0.f; float e2 = 0.f; float dx, dy; atom1->coordinates.rx() += delta; energy(e1); atom1->coordinates.rx() -= 2 * delta; energy(e2); dx = (e2 - e1) / (2 * delta); atom1->coordinates.rx() += delta; dy = dx * l.y() / l.x(); totalE += (e2 + e1) * .5f; sketcherMinimizerPointF dForce(dx, dy); atom1->force += dForce; atom2->force -= dForce; }; virtual bool isClash() { return false; }; float k; float restV; // rest value sketcherMinimizerAtom* atom1; sketcherMinimizerAtom* atom2; // int minimizationPhase; }; #endif // sketcherMINIMIZERINTERACTION coordgenlibs-3.0.2/sketcherMinimizerMarchingSquares.cpp000066400000000000000000000205061436654770400234260ustar00rootroot00000000000000/* * sketcherMarchingSquares.h * * * Created by Nicola Zonta on 13/3/2011. * Copyright Schrodinger, LLC. All rights reserved * */ #include "sketcherMinimizerMarchingSquares.h" #include "sketcherMinimizer.h" #include #include using namespace std; sketcherMinimizerMarchingSquares::sketcherMinimizerMarchingSquares() = default; sketcherMinimizerMarchingSquares::~sketcherMinimizerMarchingSquares() { clear(); } void sketcherMinimizerMarchingSquares::initialize(float minx, float maxx, float miny, float maxy, float x_interval, float y_interval) { if (y_interval == 0.f) { y_interval = x_interval; } m_xinterval = x_interval; m_yinterval = y_interval; m_left = minx; m_bottom = miny; float dx = maxx - minx; float dy = maxy - miny; assert(dx > 0); assert(dy > 0); m_XN = static_cast((dx / x_interval) + 2); m_YN = static_cast((dy / y_interval) + 2); m_grid.clear(); m_grid.resize(m_XN * m_YN, 0.f); m_lastRowPoints.resize(m_XN, nullptr); } float sketcherMinimizerMarchingSquares::getNodeValue(unsigned int x, unsigned int y) const { if (x + y * m_XN < m_grid.size()) { return m_grid[x + y * m_XN]; } else { cerr << "violating grid limits" << endl; } return 0.f; } void sketcherMinimizerMarchingSquares::setValue(float v, unsigned int x, unsigned int y) { if (x + y * m_XN < m_grid.size()) { m_grid[x + y * m_XN] = v; } else { cerr << "violating grid limits" << endl; } } void sketcherMinimizerMarchingSquares::clear() { for (auto& m_point : m_points) { delete m_point; } m_points.clear(); for (auto& m_side : m_sides) { delete m_side; } m_sides.clear(); m_grid.clear(); m_lastRowPoints.clear(); } void sketcherMinimizerMarchingSquares::setThreshold(float t) { m_threshold = t; } float sketcherMinimizerMarchingSquares::getThreshold() const { return m_threshold; } float sketcherMinimizerMarchingSquares::toRealx(float x) const { return m_left + x * m_xinterval; } float sketcherMinimizerMarchingSquares::toRealy(float y) const { return m_bottom + y * m_yinterval; } float sketcherMinimizerMarchingSquares::interpolate(float v1, float v2) const { float diff = v2 - v1; if (diff < SKETCHER_EPSILON && diff > -SKETCHER_EPSILON) { return 0.5; } return ((m_threshold - v1) / (v2 - v1)); } void sketcherMinimizerMarchingSquares::addSide( sketcherMinimizerMarchingSquaresPoint* p1, sketcherMinimizerMarchingSquaresPoint* p2) { auto* side = new sketcherMinimizerMarchingSquaresSide; side->p1 = p1; side->p2 = p2; if (p1->side1) { p1->side2 = side; } else { p1->side1 = side; } if (p2->side1) { p2->side2 = side; } else { p2->side1 = side; } m_sides.push_back(side); } std::vector sketcherMinimizerMarchingSquares::getCoordinatesPoints() const { std::vector out; for (auto m_point : m_points) { out.push_back(m_point->x); out.push_back(m_point->y); } return out; } std::vector> sketcherMinimizerMarchingSquares::getOrderedCoordinatesPoints() const { std::vector> out; bool newShape = true; sketcherMinimizerMarchingSquaresPoint* nextPoint = nullptr; while (newShape) { newShape = false; nextPoint = nullptr; for (auto m_point : m_points) { if (!m_point->visited) { newShape = true; nextPoint = m_point; break; } } if (nextPoint) { std::vector newVec; while (nextPoint) { nextPoint->visited = true; newVec.push_back(nextPoint->x); newVec.push_back(nextPoint->y); sketcherMinimizerMarchingSquaresPoint* followingPoint1 = nullptr; if (nextPoint->side1) { followingPoint1 = nextPoint->side1->p1; } if (followingPoint1 == nextPoint) { followingPoint1 = nextPoint->side1->p2; } sketcherMinimizerMarchingSquaresPoint* followingPoint2 = nullptr; if (nextPoint->side2) { followingPoint2 = nextPoint->side2->p1; } if (followingPoint2 == nextPoint) { followingPoint2 = nextPoint->side2->p2; } bool found = false; if (followingPoint1) { if (!followingPoint1->visited) { nextPoint = followingPoint1; found = true; } } if (!found) { if (followingPoint2) { if (!followingPoint2->visited) { nextPoint = followingPoint2; found = true; } } } if (!found) { nextPoint = nullptr; } } out.push_back(newVec); } } return out; } void sketcherMinimizerMarchingSquares::run() { for (unsigned int j = 0; j < m_YN - 1; j++) { m_lastCellRightPoint = nullptr; for (unsigned int i = 0; i < m_XN - 1; i++) { assert((i + 1 + j * m_XN) < m_grid.size()); assert((i + (j + 1) * m_XN) < m_grid.size()); assert((i + 1 + (j + 1) * m_XN) < m_grid.size()); // float BL = m_grid [i + j*m_XN]; float BR = m_grid[i + 1 + j * m_XN]; float TL = m_grid[i + (j + 1) * m_XN]; float TR = m_grid[i + 1 + (j + 1) * m_XN]; assert(i < m_lastRowPoints.size()); sketcherMinimizerMarchingSquaresPoint* rp = nullptr; sketcherMinimizerMarchingSquaresPoint* tp = nullptr; sketcherMinimizerMarchingSquaresPoint* lp = m_lastCellRightPoint; sketcherMinimizerMarchingSquaresPoint* bp = m_lastRowPoints[i]; if (((BR - m_threshold) * (TR - m_threshold)) < 0) { float inter = interpolate(BR, TR); float newY = toRealy(inter + j); rp = new sketcherMinimizerMarchingSquaresPoint( toRealx(static_cast(i + 1)), newY); m_points.push_back(rp); } if (((TL - m_threshold) * (TR - m_threshold)) < 0) { float inter = interpolate(TL, TR); float newX = toRealx(inter + i); tp = new sketcherMinimizerMarchingSquaresPoint( newX, toRealy(static_cast(j + 1))); m_points.push_back(tp); } if (rp && tp && lp && bp) { if (TL > m_threshold) { addSide(tp, rp); addSide(bp, lp); } else { addSide(tp, lp); addSide(bp, rp); } } else { sketcherMinimizerMarchingSquaresPoint *p1 = nullptr, *p2 = nullptr; if (tp) { p1 = tp; } if (rp) { if (p1) { p2 = rp; } else { p1 = rp; } } if (bp) { if (p1) { p2 = bp; } else { p1 = bp; } } if (lp) { if (p1) { p2 = lp; } else { p1 = lp; } } if (p1 && p2) { addSide(p1, p2); } } m_lastCellRightPoint = rp; m_lastRowPoints[i] = tp; } m_lastCellRightPoint = nullptr; } } coordgenlibs-3.0.2/sketcherMinimizerMarchingSquares.h000066400000000000000000000055351436654770400231000ustar00rootroot00000000000000/* * sketcherMarchingSquares.h * * * Created by Nicola Zonta on 19/11/2010. * Copyright Schrodinger, LLC. All rights reserved * */ #ifndef sketcherMINIMIZERMARCHINGSQUARES_H #define sketcherMINIMIZERMARCHINGSQUARES_H #include "CoordgenConfig.hpp" #include #include class sketcherMinimizerPointF; struct sketcherMinimizerMarchingSquaresPoint; struct sketcherMinimizerMarchingSquaresSide { sketcherMinimizerMarchingSquaresPoint* p1; sketcherMinimizerMarchingSquaresPoint* p2; }; struct sketcherMinimizerMarchingSquaresPoint { public: sketcherMinimizerMarchingSquaresPoint(float ix, float iy) { x = ix; y = iy; side1 = nullptr; side2 = nullptr; visited = false; } float x, y; sketcherMinimizerMarchingSquaresSide *side1, *side2; bool visited; }; /* implementation of a marching squares algorithm */ class EXPORT_COORDGEN sketcherMinimizerMarchingSquares { public: sketcherMinimizerMarchingSquares(); ~sketcherMinimizerMarchingSquares(); // inline void clearGrid (); void setValue(float v, unsigned int x, unsigned int y); void initialize(float minx, float maxx, float miny, float maxy, float x_interval, float y_interval = 0.f); void clear(); void setThreshold(float t); float getThreshold() const; float toRealx(float x) const; float toRealy(float y) const; unsigned int getXN() const { return m_XN; }; unsigned int getYN() const { return m_YN; }; void run(); // computes the isovalue points and segments /* call after run () is executed, returns the coordinates of all the isovalue line points [x1, y1, x2, y2 .. xn, yn] in the order they were created */ std::vector getCoordinatesPoints() const; /* call after run () is executed. Returns a vector of isovalue closed lines [x1, y1, x2, y2 .. xn, yn]. The points are ordered as they appear along the line. */ std::vector> getOrderedCoordinatesPoints() const; inline std::vector getRawData() const { return m_grid; }; // returns a vector of all the data set with setValue. float getNodeValue(unsigned int x, unsigned int y) const; private: void addSide(sketcherMinimizerMarchingSquaresPoint* p1, sketcherMinimizerMarchingSquaresPoint* p2); float m_xinterval, m_yinterval, m_left, m_bottom; std::vector m_grid; unsigned int m_XN, m_YN; float m_threshold; std::vector m_lastRowPoints; sketcherMinimizerMarchingSquaresPoint* m_lastCellRightPoint; float interpolate(float v1, float v2) const; std::vector m_points; std::vector m_sides; }; #endif // sketcherMINIMIZERMARCHINGSQUARES_H coordgenlibs-3.0.2/sketcherMinimizerMaths.h000066400000000000000000000570561436654770400210650ustar00rootroot00000000000000/* * sketcherMinimizerMaths.h * * * Created by Nicola Zonta on 15/3/2011. * Copyright Schrodinger, LLC. All rights reserved * */ #ifndef sketcherMINIMIZERMATHS_H #define sketcherMINIMIZERMATHS_H #include #include #include #include #include #define MACROCYCLE 9 // smallest MACROCYCLE #define BONDLENGTH 50 #define FRACTION_OF_BONDLENGTH_FOR_CLASH 0.25 #define SKETCHER_EPSILON 0.0001f #ifndef M_PI #define M_PI 3.1415926535897931 #endif inline float roundToTwoDecimalDigits(float f) { return static_cast(floor(f * 100 + 0.5) * 0.01); } inline float roundToPrecision(float f, int precision) { return static_cast(floor(f * pow(10.f, precision) + 0.5) * pow(0.1, precision)); } /* class to represent a point or vector in 2d */ class sketcherMinimizerPointF { public: sketcherMinimizerPointF() = default; sketcherMinimizerPointF(const sketcherMinimizerPointF& p) : xp(p.x()), yp(p.y()) { } sketcherMinimizerPointF(float xpos, float ypos) : xp(xpos), yp(ypos) {} sketcherMinimizerPointF& operator=(const sketcherMinimizerPointF& p) { if (this != &p) { xp = p.x(); yp = p.y(); } return *this; } inline float x() const { return xp; } inline float y() const { return yp; } inline float& rx() { return xp; } inline float& ry() { return yp; } void setX(float x) { xp = x; } void setY(float y) { yp = y; } float squareLength() const { float dd = x() * x() + y() * y(); return dd; } /* return the length of the vector */ float length() const { float dd = squareLength(); if (dd > SKETCHER_EPSILON) { return sqrt(dd); } else { return 0; } } /* normalize the vector */ void normalize() { float q = length(); if (q > SKETCHER_EPSILON) { xp /= q; yp /= q; } } /* rotate the vector by the angle with given sine and cosine */ void rotate(float s, float c) { float x = xp; float y = yp; xp = x * c + y * s; yp = -x * s + y * c; } /* parallel component of this along the give axis */ sketcherMinimizerPointF parallelComponent(const sketcherMinimizerPointF& axis) { float dotProduct = x() * axis.x() + y() * axis.y(); return axis * dotProduct / axis.squareLength(); } /* round the coordinates to the given number of decimal figures */ void round(int precision = 2) { if (precision == 2) { xp = roundToTwoDecimalDigits(xp); yp = roundToTwoDecimalDigits(yp); } else { xp = roundToPrecision(xp, precision); yp = roundToPrecision(yp, precision); } } sketcherMinimizerPointF& operator+=(const sketcherMinimizerPointF& p) { xp += p.xp; yp += p.yp; return *this; } sketcherMinimizerPointF& operator-=(const sketcherMinimizerPointF& p) { xp -= p.xp; yp -= p.yp; return *this; } template sketcherMinimizerPointF& operator*=(T c) { xp *= static_cast(c); yp *= static_cast(c); return *this; } template sketcherMinimizerPointF& operator/=(T c) { xp /= static_cast(c); yp /= static_cast(c); return *this; } // friend inline bool operator==(const sketcherMinimizerPointF &p1, const // sketcherMinimizerPointF &p2) ; // friend inline bool operator!=(const sketcherMinimizerPointF &, const // sketcherMinimizerPointF &); inline friend std::ostream& operator<<(std::ostream& out, sketcherMinimizerPointF& point) { out << "(" << point.xp << ", " << point.yp << ")"; return out; } friend inline const sketcherMinimizerPointF operator+(const sketcherMinimizerPointF& p1, const sketcherMinimizerPointF& p2) { return sketcherMinimizerPointF(p1.xp + p2.xp, p1.yp + p2.yp); } friend inline const sketcherMinimizerPointF operator-(const sketcherMinimizerPointF& p1, const sketcherMinimizerPointF& p2) { return sketcherMinimizerPointF(p1.xp - p2.xp, p1.yp - p2.yp); } friend inline const sketcherMinimizerPointF operator*(float c, const sketcherMinimizerPointF& p1) { return sketcherMinimizerPointF(p1.xp * c, p1.yp * c); } template friend inline const sketcherMinimizerPointF operator*(const sketcherMinimizerPointF& p1, T c) { auto cf = static_cast(c); return sketcherMinimizerPointF(p1.xp * cf, p1.yp * cf); } template friend inline const sketcherMinimizerPointF operator/(const sketcherMinimizerPointF& p1, T c) { auto cf = static_cast(c); return sketcherMinimizerPointF(p1.xp / cf, p1.yp / cf); } friend inline const sketcherMinimizerPointF operator-(const sketcherMinimizerPointF& p1) { return sketcherMinimizerPointF(-p1.xp, -p1.yp); } // friend inline const sketcherMinimizerPointF operator/(const // sketcherMinimizerPointF &, float); private: float xp{0.f}; float yp{0.f}; }; /* return true if the two segments intersect and if a result pointer was given, * set it to the intersection point */ struct sketcherMinimizerMaths { static bool intersectionOfSegments(const sketcherMinimizerPointF& s1p1, const sketcherMinimizerPointF& s1p2, const sketcherMinimizerPointF& s2p1, const sketcherMinimizerPointF& s2p2, sketcherMinimizerPointF* result = nullptr) { /* Suppose the two line segments run from p to p + r and from q to q + s. Then any point on the first line is representable as p + t r (for a scalar parameter t) and any point on the second line as q + u s (for a scalar parameter u). The two lines intersect if we can find t and u such that: p + t r = q + u s Cross both sides with s, getting (p + t r) × s = (q + u s) × s And since s × s = 0, this means t (r × s) = (q − p) × s And therefore, solving for t: t = (q − p) × s / (r × s) In the same way, we can solve for u: (p + t r) × r = (q + u s) × r u (s × r) = (p − q) × r u = (p − q) × r / (s × r) To reduce the number of computation steps, it's convenient to rewrite this as follows (remembering that s × r = − r × s): u = (q − p) × r / (r × s) Now there are five cases: If r × s = 0 and (q − p) × r = 0, then the two lines are collinear. If in addition, either 0 ≤ (q − p) · r ≤ r · r or 0 ≤ (p − q) · s ≤ s · s, then the two lines are overlapping. If r × s = 0 and (q − p) × r = 0, but neither 0 ≤ (q − p) · r ≤ r · r nor 0 ≤ (p − q) · s ≤ s · s, then the two lines are collinear but disjoint. If r × s = 0 and (q − p) × r ≠ 0, then the two lines are parallel and non-intersecting. If r × s ≠ 0 and 0 ≤ t ≤ 1 and 0 ≤ u ≤ 1, the two line segments meet at the point p + t r = q + u s. Otherwise, the two line segments are not parallel but do not intersect. */ const sketcherMinimizerPointF& p = s1p1; sketcherMinimizerPointF r = s1p2 - s1p1; const sketcherMinimizerPointF& q = s2p1; sketcherMinimizerPointF s = s2p2 - s2p1; float rxs = crossProduct(r, s); if (rxs > -SKETCHER_EPSILON && rxs < SKETCHER_EPSILON) { // parallel lines return false; } sketcherMinimizerPointF qminusp = q - p; float t = crossProduct(qminusp, s) / rxs; if (t < 0 || t > 1) { return false; } float u = crossProduct(qminusp, r) / rxs; if (u < 0 || u > 1) { return false; } if (result) { *result = p + t * r; } return true; } /* signed angle between p1p2 and p2p3 */ static float signedAngle(const sketcherMinimizerPointF& p1, const sketcherMinimizerPointF& p2, const sketcherMinimizerPointF& p3) { sketcherMinimizerPointF v1 = p1 - p2; sketcherMinimizerPointF v2 = p3 - p2; return float(atan2(v1.x() * v2.y() - v1.y() * v2.x(), v1.x() * v2.x() + v1.y() * v2.y()) * 180 / M_PI); } /* unsigned angle between p1p2 and p2p3 */ static float unsignedAngle(const sketcherMinimizerPointF& p1, const sketcherMinimizerPointF& p2, const sketcherMinimizerPointF& p3) { float x1 = p1.x(); float y1 = p1.y(); float x2 = p2.x(); float y2 = p2.y(); float x3 = p3.x(); float y3 = p3.y(); float v1x = x1 - x2; float v1y = y1 - y2; float v2x = x3 - x2; float v2y = y3 - y2; float d = sqrt(v1x * v1x + v1y * v1y) * sqrt(v2x * v2x + v2y * v2y); if (d < SKETCHER_EPSILON) { d = SKETCHER_EPSILON; } float cosine = (v1x * v2x + v1y * v2y) / d; if (cosine < -1) { cosine = -1; } else if (cosine > 1) { cosine = 1; } return float((acos(cosine)) * 180 / M_PI); } /* return true if the two points are very close in space */ static bool pointsCoincide(const sketcherMinimizerPointF& p1, const sketcherMinimizerPointF& p2) { return ((p1 - p2).squareLength() < SKETCHER_EPSILON * SKETCHER_EPSILON); } /* return true if p1 and p2 are in the same semiplane defined by the given * segment */ static bool sameSide(const sketcherMinimizerPointF& p1, const sketcherMinimizerPointF& p2, const sketcherMinimizerPointF& lineP1, const sketcherMinimizerPointF& lineP2) { float x = lineP2.x() - lineP1.x(); float y = lineP2.y() - lineP1.y(); // ///cerr << "("< fabs((y))) { // what about q? float m = y / x; float d1 = p1.y() - lineP1.y() - m * (p1.x() - lineP1.x()); float d2 = p2.y() - lineP1.y() - m * (p2.x() - lineP1.x()); return (d2 * d1 > 0); } else { float m = x / y; float d1 = p1.x() - lineP1.x() - m * (p1.y() - lineP1.y()); float d2 = p2.x() - lineP1.x() - m * (p2.y() - lineP1.y()); return (d2 * d1 > 0); } } /* return the projection of p on the line defined by the given segment */ static sketcherMinimizerPointF projectPointOnLine(const sketcherMinimizerPointF& p, const sketcherMinimizerPointF& sp1, const sketcherMinimizerPointF& sp2) { sketcherMinimizerPointF l1 = p - sp1; sketcherMinimizerPointF l3 = sp2 - sp1; float segmentl2 = l3.squareLength(); if (segmentl2 < SKETCHER_EPSILON) { segmentl2 = SKETCHER_EPSILON; } float t = sketcherMinimizerMaths::dotProduct(l1, l3) / segmentl2; return sp1 + t * l3; } /* squared distance of the given point from the given segment */ static float squaredDistancePointSegment(const sketcherMinimizerPointF& p, const sketcherMinimizerPointF& sp1, const sketcherMinimizerPointF& sp2, float* returnT = nullptr) { sketcherMinimizerPointF l1 = p - sp1; sketcherMinimizerPointF l2 = sp2 - p; sketcherMinimizerPointF l3 = sp2 - sp1; float segmentl2 = l3.x() * l3.x() + l3.y() * l3.y(); // float l1l = sqrt ( l1.x () * l1.x () + l1.y() * l1.y() ); if (segmentl2 < SKETCHER_EPSILON) { segmentl2 = SKETCHER_EPSILON; } float t = (l1.x() * l3.x() + l1.y() * l3.y()) / segmentl2; if (returnT != nullptr) { if (t < 0) { *returnT = 0; } else if (t > 1) { *returnT = 1; } else { *returnT = t; } } float squaredistance = 0.f; if (t < 0.f) { squaredistance = l1.x() * l1.x() + l1.y() * l1.y(); } else if (t > 1.f) { squaredistance = l2.x() * l2.x() + l2.y() * l2.y(); } else { sketcherMinimizerPointF proj = sp1 + t * l3; sketcherMinimizerPointF l5 = p - proj; squaredistance = l5.x() * l5.x() + l5.y() * l5.y(); } if (squaredistance < SKETCHER_EPSILON) { squaredistance = SKETCHER_EPSILON; } return squaredistance; } static float squaredDistance(const sketcherMinimizerPointF& p1, const sketcherMinimizerPointF& p2) { return (p1.x() - p2.x()) * (p1.x() - p2.x()) + (p1.y() - p2.y()) * (p1.y() - p2.y()); } static std::vector tridiagonalSolve(const std::vector& a, const std::vector& b, const std::vector& c, const std::vector& rhs) { assert(a.size() == b.size() && a.size() == c.size() && a.size() == rhs.size()); assert(b[0] != 0.f); auto n = static_cast(rhs.size()); std::vector u(n); std::vector gam(n); float bet = b[0]; u[0] = rhs[0] / bet; for (unsigned int j = 1; j < n; j++) { gam[j] = c[j - 1] / bet; bet = b[j] - a[j] * gam[j]; assert(bet != 0.f); u[j] = (rhs[j] - a[j] * u[j - 1]) / bet; } for (unsigned int j = 1; j < n; j++) { u[n - j - 1] -= gam[n - j] * u[n - j]; } return u; } /* used by ClosedBezierControlPoints */ static std::vector cyclicSolve(const std::vector& a, const std::vector& b, const std::vector& c, float alpha, float beta, const std::vector& rhs) { assert(a.size() == b.size() && a.size() == c.size()); auto n = static_cast(b.size()); assert(n > 2); float gamma = -b[0]; // Avoid subtraction error in forming bb[0]. // Set up the diagonal of the modified tridiagonal system. std::vector bb(n); bb[0] = b[0] - gamma; bb[n - 1] = b[n - 1] - alpha * beta / gamma; for (unsigned int i = 1; i < n - 1; i++) { bb[i] = b[i]; } // Solve A · x = rhs. std::vector solution = tridiagonalSolve(a, bb, c, rhs); std::vector x = solution; // Set up the vector u. std::vector u(n); u[0] = gamma; u[n - 1] = alpha; for (unsigned int i = 1; i < n - 1; i++) { u[i] = 0.f; } // Solve A · z = u. solution = tridiagonalSolve(a, bb, c, u); std::vector z = solution; // Form v · x/(1 + v · z). double fact = (x[0] + beta * x[n - 1] / gamma) / (1.f + z[0] + beta * z[n - 1] / gamma); // Now get the solution vector x. for (unsigned int i = 0; i < n; i++) { x[i] -= float(fact * z[i]); } return x; } static sketcherMinimizerPointF pointOnCubicBezier(const sketcherMinimizerPointF& p1, const sketcherMinimizerPointF& cp1, const sketcherMinimizerPointF& cp2, const sketcherMinimizerPointF& p2, float t) { // using Casteljiau's algorithm auto v1 = (1 - t) * p1 + t * cp1; auto v2 = (1 - t) * cp1 + t * cp2; auto v3 = (1 - t) * cp2 + t * p2; auto v4 = (1 - t) * v1 + t * v2; auto v5 = (1 - t) * v2 + t * v3; return (1 - t) * v4 + t * v5; } /* find control points to a closed Bezier curve that passes through the * given points */ static void ClosedBezierControlPoints( const std::vector& knots, std::vector& firstControlPoints, std::vector& secondControlPoints) { auto n = static_cast(knots.size()); if (n <= 2) { return; } // Calculate first Bezier control points std::vector a(n), b(n), c(n); for (unsigned int i = 0; i < n; i++) { a[i] = 1; b[i] = 4; c[i] = 1; } std::vector rhs(n); for (unsigned int i = 0; i < n; i++) { int j = i + 1; if (j > int(n - 1)) { j = 0; } rhs[i] = 4 * knots[i].x() + 2 * knots[j].x(); } // Solve the system for X. std::vector x = cyclicSolve(a, b, c, 1, 1, rhs); for (unsigned int i = 0; i < n; i++) { int j = i + 1; if (j > int(n - 1)) { j = 0; } rhs[i] = 4 * knots[i].y() + 2 * knots[j].y(); } // Solve the system for Y. std::vector y = cyclicSolve(a, b, c, 1, 1, rhs); // Fill output arrays. firstControlPoints.resize(n); secondControlPoints.resize(n); for (unsigned int i = 0; i < n; i++) { firstControlPoints[i] = sketcherMinimizerPointF(x[i], y[i]); secondControlPoints[i] = sketcherMinimizerPointF( 2 * knots[i].x() - x[i], 2 * knots[i].y() - y[i]); } } /* return the mirror image of the given point wrt the given segment */ static sketcherMinimizerPointF mirrorPoint(const sketcherMinimizerPointF& point, const sketcherMinimizerPointF& segmentPoint1, const sketcherMinimizerPointF& segmentPoint2) { sketcherMinimizerPointF segmentV = segmentPoint2 - segmentPoint1; sketcherMinimizerPointF v2 = point - segmentPoint1; sketcherMinimizerPointF parallelComponent = v2.parallelComponent(segmentV); sketcherMinimizerPointF normalComponent = v2 - parallelComponent; return segmentPoint1 + parallelComponent - normalComponent; } /* dot product of two vectors */ static float dotProduct(const sketcherMinimizerPointF& a, const sketcherMinimizerPointF& b) { return (a.x() * b.x() + a.y() * b.y()); } /* cross product of two vectors */ static float crossProduct(const sketcherMinimizerPointF& a, const sketcherMinimizerPointF& b) { return (a.x() * b.y() - a.y() * b.x()); } static float cannonBallDistance(float originX, float originY, float originZ, float directionX, float directionY, float directionZ, float targetX, float targetY, float targetZ, float ballR, float targetR, float cutOff = 4.f) // how far can a cannonball of radius ballR shot from origin travel befor // hitting a target ball of targetR radius { // assume that direction is normalized float targetdX = targetX - originX; float targetdY = targetY - originY; float targetdZ = targetZ - originZ; float rR = ballR + targetR; float d2 = (targetdX * targetdX) + (targetdY * targetdY) + (targetdZ * targetdZ); if (d2 > (cutOff + rR) * (cutOff + rR)) { return cutOff; } if (d2 < rR * rR) { return 0; } float d = sqrt(d2); if (d > SKETCHER_EPSILON) { targetdX /= d; targetdY /= d; targetdZ /= d; } float cos = targetdX * directionX + targetdY * directionY + targetdZ * directionZ; if (cos < 0) { return cutOff; } float sin = sqrt(1 - (cos * cos)); float f = d * sin; if (f > rR) { return cutOff; } float result = sqrt(d2 - (f * f)) - sqrt((rR * rR) - (f * f)); if (result > cutOff) { return cutOff; } return result; } /* length of a 3d vector */ static float length3D(float x, float y, float z) { float m = x * x + y * y + z * z; if (m > SKETCHER_EPSILON) { m = sqrt(m); } return m; } /* dot product of two 3d vectors */ static float dotProduct3D(float x1, float y1, float z1, float x2, float y2, float z2) { return x1 * x2 + y1 * y2 + z1 * z2; } /* cross product of two 3d vectors */ static void crossProduct3D(float x1, float y1, float z1, float x2, float y2, float z2, float& xr, float& yr, float& zr) { xr = y1 * z2 - z1 * y2; yr = z1 * x2 - x1 * z2; zr = x1 * y2 - y1 * x2; } static float distance3D(float x1, float y1, float z1, float x2, float y2, float z2) { return length3D(x2 - x1, y2 - y1, z2 - z1); } /* angle between two 3d vectors */ static float angle3D(float x1, float y1, float z1, float x2, float y2, float z2, float x3, float y3, float z3) { float xa = x1 - x2; float ya = y1 - y2; float za = z1 - z2; float xb = x3 - x2; float yb = y3 - y2; float zb = z3 - z2; float l1 = length3D(xa, ya, za); float l2 = length3D(xb, yb, zb); float dp = dotProduct3D(xa, ya, za, xb, yb, zb); return static_cast(acos(dp / (l1 * l2)) * 180.f / M_PI); } /* dihedral angle defined by 4 3d points */ static float dihedral3D(float x1, float y1, float z1, float x2, float y2, float z2, float x3, float y3, float z3, float x4, float y4, float z4) { float xa, ya, za; crossProduct3D(x1 - x2, y1 - y2, z1 - z2, x3 - x2, y3 - y2, z3 - z2, xa, ya, za); float xb, yb, zb; crossProduct3D(x2 - x3, y2 - y3, z2 - z3, x4 - x3, y4 - y3, z4 - z3, xb, yb, zb); return angle3D(xa, ya, za, 0, 0, 0, xb, yb, zb); } }; // struct sketcherMinimizerMaths #endif // sketcherMINIMIZERMATHS_H coordgenlibs-3.0.2/sketcherMinimizerMolecule.cpp000066400000000000000000000173351436654770400221050ustar00rootroot00000000000000/* * sketcherMinimizerMolecule.cpp * * Created by Nicola Zonta on 24/05/2011. * Copyright Schrodinger, LLC. All rights reserved. * */ #include "sketcherMinimizerMolecule.h" #include "sketcherMinimizerAtom.h" #include "sketcherMinimizerMaths.h" #include "sketcherMinimizerRing.h" #include "sketcherMinimizerBond.h" #include using namespace std; sketcherMinimizerMolecule::sketcherMinimizerMolecule() : fixed(false), hasFixedFragments(false), hasConstrainedFragments(false), needToAlignNonRingAtoms(false), needToAlignWholeMolecule(false), isPlaced(false), m_mainFragment(nullptr), m_requireMinimization(false){}; sketcherMinimizerMolecule::~sketcherMinimizerMolecule() { for (auto& ring : _rings) { delete ring; ring = nullptr; } } sketcherMinimizerAtom* sketcherMinimizerMolecule::addNewAtom() { auto atom = new sketcherMinimizerAtom(); _atoms.push_back(atom); atom->molecule = this; return atom; } sketcherMinimizerBond* sketcherMinimizerMolecule::addNewBond(sketcherMinimizerAtom* at1, sketcherMinimizerAtom* at2) { auto bond = new sketcherMinimizerBond(at1, at2); _bonds.push_back(bond); return bond; } int sketcherMinimizerMolecule::totalCharge() { int charge = 0; for (auto& _atom : _atoms) { charge += _atom->charge; } return charge; } void sketcherMinimizerMolecule::boundingBox(sketcherMinimizerPointF& min, sketcherMinimizerPointF& max) { min.setX(0.f); min.setY(0.f); max.setX(0.f); max.setY(0.f); if (!_atoms.empty()) { min = _atoms[0]->coordinates; max = _atoms[0]->coordinates; for (auto a : _atoms) { if (a->coordinates.x() < min.x()) { min.setX(a->coordinates.x()); } if (a->coordinates.y() < min.y()) { min.setY(a->coordinates.y()); } if (a->coordinates.x() > max.x()) { max.setX(a->coordinates.x()); } if (a->coordinates.y() > max.y()) { max.setY(a->coordinates.y()); } } } } void sketcherMinimizerMolecule::requireMinimization() { m_requireMinimization = true; } bool sketcherMinimizerMolecule::minimizationIsRequired() { return m_requireMinimization; } sketcherMinimizerPointF sketcherMinimizerMolecule::center() { if (_atoms.empty()) { return sketcherMinimizerPointF(0.f, 0.f); } sketcherMinimizerPointF c(.0f, .0f); for (auto& _atom : _atoms) { c += _atom->coordinates; } return c / _atoms.size(); } void sketcherMinimizerMolecule::assignBondsAndNeighbors( std::vector& atoms, std::vector& bonds) { for (auto atom : atoms) { atom->bonds.clear(); atom->neighbors.clear(); atom->residueInteractionPartners.clear(); atom->residueInteractions.clear(); atom->rings.clear(); } for (auto bond : bonds) { bond->rings.clear(); if (!bond->isResidueInteraction()) { // bond->_rings.clear (); bond->startAtom->bonds.push_back(bond); bond->endAtom->neighbors.push_back(bond->startAtom); bond->endAtom->bonds.push_back(bond); bond->startAtom->neighbors.push_back(bond->endAtom); } else { bond->startAtom->residueInteractions.push_back(bond); bond->endAtom->residueInteractionPartners.push_back( bond->startAtom); bond->endAtom->residueInteractions.push_back(bond); bond->startAtom->residueInteractionPartners.push_back( bond->endAtom); } } for (auto& atom : atoms) { if (atom->_implicitHs == -1) { atom->_implicitHs = atom->findHsNumber(); } } } void sketcherMinimizerMolecule::forceUpdateStruct( std::vector& atoms, std::vector& bonds, std::vector& rings) { sketcherMinimizerMolecule::assignBondsAndNeighbors(atoms, bonds); findRings(bonds, rings); for (auto& bond : bonds) { for (unsigned int j = 0; j < bond->rings.size(); j++) { sketcherMinimizerRing* ring = bond->rings[j]; bool found = false; for (auto& k : bond->startAtom->rings) { if (k == ring) { found = true; break; } } if (!found) { bond->startAtom->rings.push_back(ring); } found = false; for (auto& k : bond->endAtom->rings) { if (k == ring) { found = true; break; } } if (!found) { bond->endAtom->rings.push_back(ring); } } } for (auto& atom : atoms) { for (unsigned int j = 0; j < atom->rings.size(); j++) { atom->rings[j]->_atoms.push_back(atom); } } } void sketcherMinimizerMolecule::findRings( std::vector& bonds, std::vector& rings) { for (auto& ring : rings) { delete ring; } rings.clear(); for (unsigned int i = 0; i < bonds.size(); i++) { for (auto& bond : bonds) { bond->_SSSRVisited = false; bond->_SSSRParent = nullptr; bond->_SSSRParentAtStart = true; } sketcherMinimizerBond* bond = bonds[i]; std::queue q; bond->_SSSRVisited = true; q.push(bond); bool closedRing = false; while (!q.empty() && !closedRing) { sketcherMinimizerBond* lastBond = q.front(); q.pop(); sketcherMinimizerAtom* pivotAtom = lastBond->endAtom; if (!lastBond->_SSSRParentAtStart) { pivotAtom = lastBond->startAtom; } for (unsigned int j = 0; j < pivotAtom->bonds.size(); j++) { sketcherMinimizerBond* nextBond = pivotAtom->bonds[j]; // sketcherMinimizerAtom *nextAtom = pivotAtom->neighbors[j]; if (nextBond == lastBond) { continue; } if (nextBond->_SSSRVisited) { if (nextBond == bond) { addRing(closeRing(lastBond), rings); closedRing = true; } } else { if (nextBond->endAtom == pivotAtom) { nextBond->_SSSRParentAtStart = false; } nextBond->_SSSRParent = lastBond; nextBond->_SSSRVisited = true; q.push(nextBond); } } } } for (auto ring : rings) { for (unsigned int j = 0; j < ring->_bonds.size(); j++) { sketcherMinimizerBond* bond = ring->_bonds[j]; bond->rings.push_back(ring); } } } sketcherMinimizerRing* sketcherMinimizerMolecule::closeRing(sketcherMinimizerBond* bond) { auto* ring = new sketcherMinimizerRing(); sketcherMinimizerBond* lastBond = bond; while (lastBond) { ring->_bonds.push_back(lastBond); lastBond = lastBond->_SSSRParent; } return ring; } void sketcherMinimizerMolecule::addRing( sketcherMinimizerRing* ring, std::vector& rings) { bool found = false; for (auto& i : rings) { if (i->sameAs(ring)) { found = true; break; } } if (!found) { rings.push_back(ring); } else { delete ring; } } coordgenlibs-3.0.2/sketcherMinimizerMolecule.h000066400000000000000000000074161436654770400215510ustar00rootroot00000000000000/* * sketcherMinimizerMolecule.h * * Created by Nicola Zonta on 03/05/2010. * Copyright Schrodinger, LLC. All rights reserved. * */ #include "CoordgenConfig.hpp" #include #include #include #ifndef sketcherMINIMIZERMOLECULE_H #define sketcherMINIMIZERMOLECULE_H class sketcherMinimizerAtom; class sketcherMinimizerBond; class sketcherMinimizerRing; class sketcherMinimizerPointF; class sketcherMinimizerFragment; /* class to define a molecule */ class EXPORT_COORDGEN sketcherMinimizerMolecule { public: sketcherMinimizerMolecule(); ~sketcherMinimizerMolecule(); // create a new atom and add it to the molecule sketcherMinimizerAtom* addNewAtom(); // create a new bond and add it to the molecule sketcherMinimizerBond* addNewBond(sketcherMinimizerAtom* at1, sketcherMinimizerAtom* at2); // void fromChmMol(ChmMol& mol); std::vector& getAtoms() { return _atoms; } std::vector& getBonds() { return _bonds; } std::vector& getRings() { return _rings; } std::vector& getFragments() { return _fragments; } void setFragments(std::vector fragments) { _fragments = std::move(fragments); } /* set this molecule to require force-field minimization */ void requireMinimization(); /* return true if this molecule requires a force field-based minimization (i.e. has clashes that cannot be solved otherwise) */ bool minimizationIsRequired(); std::vector _atoms; std::vector _bonds; std::vector _rings; std::vector m_proximityRelations; std::vector _fragments; /* set the given fragment as the main fragment of the kinematic chain */ void setMainFragment(sketcherMinimizerFragment* fragment) { m_mainFragment = fragment; } sketcherMinimizerFragment* getMainFragment() { return m_mainFragment; } bool fixed; bool hasFixedFragments, hasConstrainedFragments; bool needToAlignNonRingAtoms; bool needToAlignWholeMolecule; bool isPlaced; // used by arrangeMultipleMolecules /* return the total charge of the molecule */ int totalCharge(); /* set the top left and bottom right points of the molecule's bounding * rectangle */ void boundingBox(sketcherMinimizerPointF& min, sketcherMinimizerPointF& max); /* return the coordinates of the center of the molecule */ sketcherMinimizerPointF center(); /* recalculate structure elements (e.g. rings) */ static void forceUpdateStruct(std::vector& atoms, std::vector& bonds, std::vector& rings); /* calculate neighbor info of each atom */ static void assignBondsAndNeighbors(std::vector& atoms, std::vector& bonds); /* run a SSSR algorithm */ static void findRings(std::vector& bonds, std::vector& rings); /* convenience function for the SSSR algorithm */ static sketcherMinimizerRing* closeRing(sketcherMinimizerBond* bond); /* convenience function for the SSSR algorithm */ static void addRing(sketcherMinimizerRing* ring, std::vector& rings); private: sketcherMinimizerFragment* m_mainFragment; bool m_requireMinimization; }; #endif // sketcherMINIMIZERMOLECULE_H coordgenlibs-3.0.2/sketcherMinimizerResidue.cpp000066400000000000000000000006621436654770400217330ustar00rootroot00000000000000/* * sketcherMinimizerResidue.cpp * * Created by Nicola Zonta on 13/05/2011. * Copyright Schrodinger, LLC. All rights reserved. * */ #include "sketcherMinimizerResidue.h" using namespace std; sketcherMinimizerResidue::sketcherMinimizerResidue() { m_closestLigandAtom = nullptr; } sketcherMinimizerResidue::~sketcherMinimizerResidue() = default; bool sketcherMinimizerResidue::isResidue() const { return true; } coordgenlibs-3.0.2/sketcherMinimizerResidue.h000066400000000000000000000034611436654770400214000ustar00rootroot00000000000000/* * sketcherMinimizerResidue.h * * Created by Nicola Zonta on 13/05/2011. * Copyright Schrodinger, LLC. All rights reserved. * */ #ifndef sketcherMINIMIZERRESIDUE_H #define sketcherMINIMIZERRESIDUE_H #include "sketcherMinimizerAtom.h" #include "sketcherMinimizerBond.h" /* class to represent protein residues */ class EXPORT_COORDGEN sketcherMinimizerResidue : public sketcherMinimizerAtom { public: sketcherMinimizerResidue(); ~sketcherMinimizerResidue() override; bool isResidue() const override; /* compute coordinates based on the position of the closest ligand atom */ sketcherMinimizerPointF computeStartingCoordinates(float d = 2.f) { sketcherMinimizerPointF out = templateCoordinates; if (m_closestLigandAtom) { out = m_closestLigandAtom->getSingleAdditionVector() * d + m_closestLigandAtom->coordinates; } if (residueInteractions.size()) { int nn = 0; sketcherMinimizerPointF coords(0.f, 0.f); for (auto& residueInteraction : residueInteractions) { sketcherMinimizerAtom* n = residueInteraction->endAtom; if (n == this) { n = residueInteraction->startAtom; } if (!n->isResidue()) { coords += n->getSingleAdditionVector() * d + n->coordinates; nn++; } else if (n->coordinatesSet) { coords += n->coordinates; nn++; } } if (nn > 0) { coords /= float(nn); } out = coords; } return out; } std::string chain; int resnum; sketcherMinimizerAtom* m_closestLigandAtom; }; #endif // sketcherMINIMIZERRESIDUE_H coordgenlibs-3.0.2/sketcherMinimizerResidueInteraction.cpp000066400000000000000000000016341436654770400241330ustar00rootroot00000000000000/* * sketcherMinimizerResidueInteraction.cpp * * Created by Nicola Zonta on 13/05/2011. * Copyright Schrodinger, LLC. All rights reserved. * */ #include "sketcherMinimizerResidueInteraction.h" using namespace std; sketcherMinimizerResidueInteraction::sketcherMinimizerResidueInteraction() : sketcherMinimizerBond() { } sketcherMinimizerResidueInteraction::~sketcherMinimizerResidueInteraction() = default; bool sketcherMinimizerResidueInteraction::isResidueInteraction() { return true; } vector sketcherMinimizerResidueInteraction::getAllEndAtoms() { vector out = m_otherEndAtoms; out.insert(out.begin(), endAtom); return out; } vector sketcherMinimizerResidueInteraction::getAllStartAtoms() { vector out = m_otherStartAtoms; out.insert(out.begin(), startAtom); return out; }coordgenlibs-3.0.2/sketcherMinimizerResidueInteraction.h000066400000000000000000000020351436654770400235740ustar00rootroot00000000000000/* * sketcherMinimizerResidueInteraction.h * * Created by Nicola Zonta on 13/05/2011. * Copyright Schrodinger, LLC. All rights reserved. * */ #ifndef sketcherMINIMIZERRESIDUEINTERACTION_H #define sketcherMINIMIZERRESIDUEINTERACTION_H #include "sketcherMinimizerBond.h" /* class to represent an interaction with protein residues (e.g. h-bond or pi-pi stacking */ class EXPORT_COORDGEN sketcherMinimizerResidueInteraction : public sketcherMinimizerBond { public: sketcherMinimizerResidueInteraction(); ~sketcherMinimizerResidueInteraction() override; bool isResidueInteraction() override; /* get all the atoms involved at the end side of the interaction */ std::vector getAllEndAtoms(); std::vector getAllStartAtoms(); /* get all the atoms involved at the start side of the interaction */ std::vector m_otherEndAtoms; std::vector m_otherStartAtoms; }; #endif // sketcherMINIMIZERRESIDUEINTERACTION_H coordgenlibs-3.0.2/sketcherMinimizerRing.cpp000066400000000000000000000100721436654770400212260ustar00rootroot00000000000000/* * sketcherMinimizerRing.cpp * * Created by Nicola Zonta on 24/05/2011. * Copyright Schrodinger, LLC. All rights reserved. * */ #include "sketcherMinimizerRing.h" #include "sketcherMinimizerAtom.h" #include "sketcherMinimizerBond.h" #include "sketcherMinimizerMaths.h" using namespace std; sketcherMinimizerRing::sketcherMinimizerRing() : visited(false), coordinatesGenerated(false) { // assert (0); side = false; } sketcherMinimizerRing::~sketcherMinimizerRing() = default; sketcherMinimizerPointF sketcherMinimizerRing::findCenter() { sketcherMinimizerPointF o(0.f, 0.f); for (auto& _atom : _atoms) { o += _atom->coordinates; } o /= _atoms.size(); return o; } bool sketcherMinimizerRing::isBenzene() { if (_atoms.size() != 6) { return false; } for (auto& _atom : _atoms) { if (_atom->atomicNumber != 6) { return false; } } for (auto a : _atoms) { bool found = false; for (auto& bond : a->bonds) { if (bond->bondOrder == 2) { found = true; break; } } if (!found) { return false; } } return true; } bool sketcherMinimizerRing::isAromatic() // not chemically accurate, but good // enough for minimizer { size_t bonds = _bonds.size(); int doubleBonds = 0; int NSOCount = 0; for (auto& _bond : _bonds) { if (_bond->bondOrder == 2) { doubleBonds++; } } for (auto& _atom : _atoms) { int an = _atom->atomicNumber; bool doubleBound = false; for (auto& bond : _atom->bonds) { if (bond->bondOrder == 2) { doubleBound = true; } } if (!doubleBound) { if (an == 8 || an == 7 || an == 16) { NSOCount++; } } } if (bonds == 6 && doubleBonds == 3) { return true; } if (bonds == 5 && doubleBonds == 2 && NSOCount == 1) { return true; } return false; } bool sketcherMinimizerRing::containsAtom(const sketcherMinimizerAtom* a) const { for (auto _atom : _atoms) { if (_atom == a) { return true; } } return false; } bool sketcherMinimizerRing::containsBond(sketcherMinimizerBond* b) { for (auto& _bond : _bonds) { if (_bond == b) { return true; } } return false; } bool sketcherMinimizerRing::isFusedWith(sketcherMinimizerRing* ring) { for (auto& i : fusedWith) { if (i == ring) { return true; } } return false; } std::vector sketcherMinimizerRing::getFusionAtomsWith( const sketcherMinimizerRing* ring) const { for (unsigned int i = 0; i < fusedWith.size(); i++) { if (fusedWith[i] == ring) { return fusionAtoms[i]; } } std::vector empty; return empty; } bool sketcherMinimizerRing::sameAs(sketcherMinimizerRing* ring) { if (!(_bonds.size() == ring->_bonds.size())) { return false; } for (auto& _bond : _bonds) { if (!ring->containsBond(_bond)) { return false; } } return true; } bool sketcherMinimizerRing::contains(const sketcherMinimizerPointF& p) { int n = 0; for (auto b : _bonds) { if ((p.y() < b->startAtom->coordinates.y() && p.y() > b->endAtom->coordinates.y()) || (p.y() > b->startAtom->coordinates.y() && p.y() < b->endAtom->coordinates.y())) { sketcherMinimizerPointF v = b->endAtom->coordinates - b->startAtom->coordinates; if (v.y() > SKETCHER_EPSILON || v.y() < -SKETCHER_EPSILON) { v *= (p.y() - b->startAtom->coordinates.y()) / v.y(); v += b->startAtom->coordinates; if (p.x() > v.x()) { n++; } } } } return (n % 2) != 0; } // std::vector _bonds; coordgenlibs-3.0.2/sketcherMinimizerRing.h000066400000000000000000000043461436654770400207020ustar00rootroot00000000000000/* * sketcherMinimizerRing.h * * Created by Nicola Zonta on 03/05/2010. * Copyright Schrodinger, LLC. All rights reserved. * */ #include "CoordgenConfig.hpp" #include "sketcherMinimizerMaths.h" #include #include #ifndef sketcherMINIMIZERRING_H #define sketcherMINIMIZERRING_H class sketcherMinimizerAtom; class sketcherMinimizerPointF; class sketcherMinimizerBond; /* class to represent a ring */ class EXPORT_COORDGEN sketcherMinimizerRing { public: sketcherMinimizerRing(); ~sketcherMinimizerRing(); /* rings that share atoms with this */ std::vector fusedWith; /* list of atoms that are shared with each other ring in fusedWith */ std::vector> fusionAtoms; /* list of bonds in the case of two rings attached by a double bond */ std::vector fusionBonds; bool visited, coordinatesGenerated, side /* not central */; std::vector getAtoms() const { return _atoms; } int size() const { return static_cast(_atoms.size()); } bool isMacrocycle() const { return size() >= MACROCYCLE; } std::vector _atoms; std::vector _bonds; /* return the coordinates of the center of the ring */ sketcherMinimizerPointF findCenter(); /* return true if the ring is benzene */ bool isBenzene(); /* return true if the given point is inside the ring */ bool contains(const sketcherMinimizerPointF& p); /* return true if the given atom is part of the ring */ bool containsAtom(const sketcherMinimizerAtom* a) const; /* return true if the given bond is part of the ring */ bool containsBond(sketcherMinimizerBond* b); /* return true if this is fused with ring */ bool isFusedWith(sketcherMinimizerRing* ring); /* return the common atoms between this and ring */ std::vector getFusionAtomsWith(const sketcherMinimizerRing* ring) const; /* convenience function used by the SSSR algorithm */ bool sameAs(sketcherMinimizerRing* ring); bool isAromatic(); // not chemically accurate, but good enough for minimizer }; #endif // sketcherMINIMIZERRING_H coordgenlibs-3.0.2/sketcherMinimizerStretchInteraction.h000066400000000000000000000030361436654770400236120ustar00rootroot00000000000000/* * sketcherMinimizerStretchInteraction.h * * Created by Nicola Zonta on 13/04/2010. * Copyright Schrodinger, LLC. All rights reserved. * */ #ifndef sketcherMINIMIZERSTRETCHMINIMIZERINTERACTION #define sketcherMINIMIZERSTRETCHMINIMIZERINTERACTION #include "sketcherMinimizerInteraction.h" /* force field bond stretches */ class sketcherMinimizerStretchInteraction : public sketcherMinimizerInteraction { public: sketcherMinimizerStretchInteraction(sketcherMinimizerAtom* at1, sketcherMinimizerAtom* at2) : sketcherMinimizerInteraction(at1, at2) { } ~sketcherMinimizerStretchInteraction() override = default; /* calculate forces and apply them */ void score(float& totalE, bool = false) override { energy(totalE); sketcherMinimizerPointF l = atom1->coordinates - atom2->coordinates; float m = l.length(); float dr = 0; if (m < restV - tolerance) dr = restV - tolerance - m; else if (m > restV + tolerance) dr = restV + tolerance - m; else return; float shortBondThreshold = restV * 0.4f; float penaltyForVeryShortBonds = (shortBondThreshold - m); if (penaltyForVeryShortBonds < 0) { penaltyForVeryShortBonds = 0; } if (m > SKETCHER_EPSILON) { l /= m; } l *= (k * dr + penaltyForVeryShortBonds * 10); atom1->force += l; atom2->force -= l; } float tolerance = 0; }; #endif // sketcherMINIMIZERSTRETCHINTERACTION coordgenlibs-3.0.2/templates.mae000066400000000000000000004651261436654770400167060ustar00rootroot00000000000000{ s_m_m2io_version ::: 2.0.0 } f_m_ct { s_m_title s_m_entry_id s_m_entry_name s_m_Source_Path s_m_Source_File i_m_Source_File_Index s_m_subgroup_title s_m_subgroupid b_m_subgroup_collapsed i_m_ct_format ::: CRDGEN-172_2D_template 2 templates.1 /Users/nicola/schrodinger/coordgenlibs templates.mae 1 templates templates1 0 2 m_atom[36] { # First column is atom index # i_m_mmod_type r_m_x_coord r_m_y_coord r_m_z_coord i_m_residue_number i_m_color i_m_atomic_number s_m_color_rgb ::: 1 2 5.433100 -5.999800 0.000000 9 2 6 A0A0A0 2 7 4.195900 -5.285600 0.000000 9 2 6 A0A0A0 3 7 4.195900 -3.857000 0.000000 9 2 6 A0A0A0 4 2 5.433100 -3.142700 0.000000 9 2 6 A0A0A0 5 7 6.670300 -3.857000 0.000000 9 2 6 A0A0A0 6 7 6.670300 -5.285600 0.000000 9 2 6 A0A0A0 7 7 3.208400 -6.993000 0.000000 9 2 6 A0A0A0 8 7 1.970400 -7.705800 0.000000 9 2 6 A0A0A0 9 2 1.968600 -9.134300 0.000000 9 2 6 A0A0A0 10 7 3.205000 -9.850100 0.000000 9 2 6 A0A0A0 11 7 4.443000 -9.137300 0.000000 9 2 6 A0A0A0 12 2 4.444700 -7.708700 0.000000 9 2 6 A0A0A0 13 7 -0.007200 -7.705600 0.000000 9 2 6 A0A0A0 14 7 -1.245100 -6.992600 0.000000 9 2 6 A0A0A0 15 2 -2.481500 -7.708100 0.000000 9 2 6 A0A0A0 16 7 -2.480000 -9.136700 0.000000 9 2 6 A0A0A0 17 7 -1.242100 -9.849700 0.000000 9 2 6 A0A0A0 18 2 -0.005700 -9.134100 0.000000 9 2 6 A0A0A0 19 2 -3.469800 -5.999100 0.000000 9 2 6 A0A0A0 20 7 -2.232600 -5.284900 0.000000 9 2 6 A0A0A0 21 7 -2.232500 -3.856300 0.000000 9 2 6 A0A0A0 22 2 -3.469700 -3.142000 0.000000 9 2 6 A0A0A0 23 7 -4.706900 -3.856200 0.000000 9 2 6 A0A0A0 24 7 -4.706900 -5.284800 0.000000 9 2 6 A0A0A0 25 7 -2.479600 -0.004500 0.000000 9 2 6 A0A0A0 26 2 -2.481300 -1.433100 0.000000 9 2 6 A0A0A0 27 7 -1.244900 -2.148800 0.000000 9 2 6 A0A0A0 28 7 -0.006900 -1.436000 0.000000 9 2 6 A0A0A0 29 2 -0.005200 -0.007400 0.000000 9 2 6 A0A0A0 30 7 -1.241600 0.708300 0.000000 9 2 6 A0A0A0 31 7 3.208400 -2.149200 0.000000 9 2 6 A0A0A0 32 7 1.970500 -1.436200 0.000000 9 2 6 A0A0A0 33 2 1.969100 -0.007600 0.000000 9 2 6 A0A0A0 34 7 3.205500 0.707900 0.000000 9 2 6 A0A0A0 35 7 4.443400 -0.005100 0.000000 9 2 6 A0A0A0 36 2 4.444900 -1.433700 0.000000 9 2 6 A0A0A0 ::: } m_bond[42] { # First column is bond index # i_m_from i_m_to i_m_order ::: 1 1 2 1 2 1 6 2 3 1 12 1 4 2 3 2 5 3 4 1 6 4 5 2 7 4 36 1 8 5 6 1 9 7 8 1 10 7 12 2 11 8 9 2 12 9 10 1 13 9 18 1 14 10 11 2 15 11 12 1 16 13 14 1 17 13 18 2 18 14 15 2 19 15 16 1 20 15 19 1 21 16 17 2 22 17 18 1 23 19 20 1 24 19 24 2 25 20 21 2 26 21 22 1 27 22 23 2 28 22 26 1 29 23 24 1 30 25 26 1 31 25 30 2 32 26 27 2 33 27 28 1 34 28 29 2 35 29 30 1 36 29 33 1 37 31 32 1 38 31 36 2 39 32 33 2 40 33 34 1 41 34 35 2 42 35 36 1 ::: } } f_m_ct { s_m_title s_m_entry_id s_m_entry_name s_m_Source_Path s_m_Source_File i_m_Source_File_Index s_m_subgroup_title s_m_subgroupid b_m_subgroup_collapsed i_m_ct_format ::: CRDGEN-118_template 3 templates.2 /Users/nicola/schrodinger/coordgenlibs templates.mae 2 templates templates1 0 2 m_atom[20] { # First column is atom index # i_m_mmod_type r_m_x_coord r_m_y_coord r_m_z_coord i_m_residue_number i_m_color i_m_atomic_number s_m_color_rgb s_m_atom_name ::: 1 2 -6.178200 2.189800 0.000000 9 2 6 A0A0A0 C1 2 7 -6.772600 1.617700 0.000000 9 2 6 A0A0A0 C2 3 7 -6.574500 0.816900 0.000000 9 2 6 A0A0A0 C3 4 7 -5.781800 0.588100 0.000000 9 2 6 A0A0A0 C4 5 2 -5.187400 1.160100 0.000000 9 2 6 A0A0A0 C5 6 2 -5.385500 1.960900 0.000000 9 2 6 A0A0A0 C6 7 29 -6.205500 3.014300 0.000000 9 43 7 5757FF N7 8 5 -5.429700 3.295100 0.000000 9 2 6 A0A0A0 C8 9 4 -4.791000 2.533000 0.000000 9 2 6 A0A0A0 C9 10 7 -3.880500 2.628300 0.000000 9 2 6 A0A0A0 C10 11 29 -4.247400 0.695600 0.000000 9 43 7 5757FF N11 12 5 -3.813500 -0.134700 0.000000 9 2 6 A0A0A0 C12 13 5 -2.696800 -0.068900 0.000000 9 2 6 A0A0A0 C14 14 7 -3.113100 2.296900 0.000000 9 2 6 A0A0A0 C15 15 7 -2.899600 1.500000 0.000000 9 2 6 A0A0A0 C16 16 7 -2.102700 1.286500 0.000000 9 2 6 A0A0A0 C17 17 7 -1.889200 0.489600 0.000000 9 2 6 A0A0A0 C18 18 7 -1.092300 0.276100 0.000000 9 2 6 A0A0A0 C19 19 5 -1.400400 -0.510900 0.000000 9 2 6 A0A0A0 C20 20 5 0.103700 0.542600 0.000000 9 2 6 A0A0A0 C21 ::: } m_bond[22] { # First column is bond index # i_m_from i_m_to i_m_order ::: 1 1 2 2 2 1 6 1 3 1 7 1 4 2 3 1 5 3 4 2 6 4 5 1 7 5 6 2 8 5 11 1 9 6 9 1 10 7 8 1 11 8 9 1 12 9 10 1 13 10 14 2 14 11 12 1 15 12 13 1 16 13 19 1 17 14 15 1 18 15 16 2 19 16 17 1 20 17 18 2 21 18 20 1 22 19 20 1 ::: } } f_m_ct { s_m_title s_m_entry_id s_m_entry_name s_m_Source_Path s_m_Source_File i_m_Source_File_Index s_m_subgroup_title s_m_subgroupid b_m_subgroup_collapsed i_m_ct_format ::: "template 2" 4 templates.3 /Users/nicola/schrodinger/coordgenlibs templates.mae 3 templates templates1 0 2 m_atom[23] { # First column is atom index # i_m_mmod_type r_m_x_coord r_m_y_coord r_m_z_coord i_m_residue_number i_m_color i_m_atomic_number s_m_color_rgb ::: 1 5 -0.561400 2.224200 0.000000 9 2 6 A0A0A0 2 5 -0.561400 1.399200 0.000000 9 2 6 A0A0A0 3 5 0.153000 0.986700 0.000000 9 2 6 A0A0A0 4 5 0.867500 1.399200 0.000000 9 2 6 A0A0A0 5 4 0.867500 2.224200 0.000000 9 2 6 A0A0A0 6 5 0.153000 2.636700 0.000000 9 2 6 A0A0A0 7 5 0.153000 3.461700 0.000000 9 2 6 A0A0A0 8 5 0.867500 3.874200 0.000000 9 2 6 A0A0A0 9 5 1.582000 2.636700 0.000000 9 2 6 A0A0A0 10 4 1.582000 3.461700 0.000000 9 2 6 A0A0A0 11 5 2.296400 3.874200 0.000000 9 2 6 A0A0A0 12 5 2.296400 4.699200 0.000000 9 2 6 A0A0A0 13 5 1.582000 5.111700 0.000000 9 2 6 A0A0A0 14 5 0.867500 4.699200 0.000000 9 2 6 A0A0A0 15 5 0.153000 5.111700 0.000000 9 2 6 A0A0A0 16 5 -0.561400 4.699200 0.000000 9 2 6 A0A0A0 17 5 -0.561400 3.874200 0.000000 9 2 6 A0A0A0 18 4 -1.275900 3.461700 0.000000 9 2 6 A0A0A0 19 4 -1.275900 2.636700 0.000000 9 2 6 A0A0A0 20 5 -1.990400 3.874200 0.000000 9 2 6 A0A0A0 21 5 -2.704900 3.461700 0.000000 9 2 6 A0A0A0 22 5 -2.704900 2.636700 0.000000 9 2 6 A0A0A0 23 5 -1.990400 2.224200 0.000000 9 2 6 A0A0A0 ::: } m_bond[25] { # First column is bond index # i_m_from i_m_to i_m_order ::: 1 1 2 1 2 1 19 1 3 2 3 1 4 3 4 1 5 4 5 1 6 5 6 1 7 5 9 1 8 6 7 1 9 7 8 1 10 8 10 1 11 9 10 1 12 10 11 1 13 11 12 1 14 12 13 1 15 13 14 1 16 14 15 1 17 15 16 1 18 16 17 1 19 17 18 1 20 18 19 1 21 18 20 1 22 19 23 1 23 20 21 1 24 21 22 1 25 22 23 1 ::: } } f_m_ct { s_m_title s_m_entry_id s_m_entry_name s_m_Source_Path s_m_Source_File i_m_Source_File_Index s_m_subgroup_title s_m_subgroupid b_m_subgroup_collapsed i_m_ct_format ::: "template 3" 5 templates.4 /Users/nicola/schrodinger/coordgenlibs templates.mae 4 templates templates1 0 2 m_atom[25] { # First column is atom index # i_m_mmod_type r_m_x_coord r_m_y_coord r_m_z_coord i_m_residue_number i_m_color i_m_atomic_number s_m_color_rgb ::: 1 5 -1.663800 -1.746700 0.000000 9 2 6 A0A0A0 2 5 -1.663800 -2.571700 0.000000 9 2 6 A0A0A0 3 5 -0.838800 -2.571700 0.000000 9 2 6 A0A0A0 4 5 -0.426300 -3.286200 0.000000 9 2 6 A0A0A0 5 4 0.398700 -3.286200 0.000000 9 2 6 A0A0A0 6 5 0.769000 -4.023400 0.000000 9 2 6 A0A0A0 7 5 1.592000 -4.080900 0.000000 9 2 6 A0A0A0 8 5 2.061300 -3.402400 0.000000 9 2 6 A0A0A0 9 5 0.811200 -2.571700 0.000000 9 2 6 A0A0A0 10 4 1.717100 -2.652600 0.000000 9 2 6 A0A0A0 11 5 2.129600 -1.938100 0.000000 9 2 6 A0A0A0 12 5 1.717100 -1.223700 0.000000 9 2 6 A0A0A0 13 5 0.892100 -1.223700 0.000000 9 2 6 A0A0A0 14 5 0.479600 -0.509200 0.000000 9 2 6 A0A0A0 15 5 -0.234900 -0.096700 0.000000 9 2 6 A0A0A0 16 5 -0.234900 0.728300 0.000000 9 2 6 A0A0A0 17 5 -0.949400 1.140800 0.000000 9 2 6 A0A0A0 18 5 -1.663800 0.728300 0.000000 9 2 6 A0A0A0 19 5 -1.663800 -0.096700 0.000000 9 2 6 A0A0A0 20 4 -2.378300 -0.509200 0.000000 9 2 6 A0A0A0 21 4 -2.378300 -1.334200 0.000000 9 2 6 A0A0A0 22 5 -3.092800 -0.096700 0.000000 9 2 6 A0A0A0 23 5 -3.807200 -0.509200 0.000000 9 2 6 A0A0A0 24 5 -3.807200 -1.334200 0.000000 9 2 6 A0A0A0 25 5 -3.092800 -1.746700 0.000000 9 2 6 A0A0A0 ::: } m_bond[27] { # First column is bond index # i_m_from i_m_to i_m_order ::: 1 1 2 1 2 1 21 1 3 2 3 1 4 3 4 1 5 4 5 1 6 5 6 1 7 5 9 1 8 6 7 1 9 7 8 1 10 8 10 1 11 9 10 1 12 10 11 1 13 11 12 1 14 12 13 1 15 13 14 1 16 14 15 1 17 15 16 1 18 16 17 1 19 17 18 1 20 18 19 1 21 19 20 1 22 20 21 1 23 20 22 1 24 21 25 1 25 22 23 1 26 23 24 1 27 24 25 1 ::: } } f_m_ct { s_m_title s_m_entry_id s_m_entry_name s_m_Source_Path s_m_Source_File i_m_Source_File_Index s_m_subgroup_title s_m_subgroupid b_m_subgroup_collapsed i_m_ct_format ::: "template 4" 6 templates.5 /Users/nicola/schrodinger/coordgenlibs templates.mae 5 templates templates1 0 2 m_atom[27] { # First column is atom index # i_m_mmod_type r_m_x_coord r_m_y_coord r_m_z_coord i_m_residue_number i_m_color i_m_atomic_number s_m_color_rgb ::: 1 5 0.071600 -7.562500 0.000000 9 2 6 A0A0A0 2 5 0.071600 -8.387500 0.000000 9 2 6 A0A0A0 3 5 0.786100 -8.800000 0.000000 9 2 6 A0A0A0 4 5 1.500500 -8.387500 0.000000 9 2 6 A0A0A0 5 4 2.215000 -8.800000 0.000000 9 2 6 A0A0A0 6 5 2.215000 -9.625000 0.000000 9 2 6 A0A0A0 7 5 2.929500 -10.037500 0.000000 9 2 6 A0A0A0 8 5 3.643900 -9.625000 0.000000 9 2 6 A0A0A0 9 5 2.929500 -8.387500 0.000000 9 2 6 A0A0A0 10 4 3.643900 -8.800000 0.000000 9 2 6 A0A0A0 11 5 4.358400 -8.387500 0.000000 9 2 6 A0A0A0 12 5 4.358400 -7.562500 0.000000 9 2 6 A0A0A0 13 5 3.643900 -7.150000 0.000000 9 2 6 A0A0A0 14 5 3.643900 -6.325000 0.000000 9 2 6 A0A0A0 15 5 2.929500 -5.912500 0.000000 9 2 6 A0A0A0 16 5 2.929500 -5.087500 0.000000 9 2 6 A0A0A0 17 5 2.215000 -4.675000 0.000000 9 2 6 A0A0A0 18 7 1.500500 -5.087500 0.000000 9 2 6 A0A0A0 19 7 1.500500 -5.912500 0.000000 9 2 6 A0A0A0 20 5 0.786100 -6.325000 0.000000 9 2 6 A0A0A0 21 5 0.071600 -5.912500 0.000000 9 2 6 A0A0A0 22 4 -0.642900 -6.325000 0.000000 9 2 6 A0A0A0 23 4 -0.642900 -7.150000 0.000000 9 2 6 A0A0A0 24 5 -1.357400 -5.912500 0.000000 9 2 6 A0A0A0 25 5 -2.071800 -6.325000 0.000000 9 2 6 A0A0A0 26 5 -2.071800 -7.150000 0.000000 9 2 6 A0A0A0 27 5 -1.357400 -7.562500 0.000000 9 2 6 A0A0A0 ::: } m_bond[29] { # First column is bond index # i_m_from i_m_to i_m_order ::: 1 1 2 1 2 1 23 1 3 2 3 1 4 3 4 1 5 4 5 1 6 5 6 1 7 5 9 1 8 6 7 1 9 7 8 1 10 8 10 1 11 9 10 1 12 10 11 1 13 11 12 1 14 12 13 1 15 13 14 1 16 14 15 1 17 15 16 1 18 16 17 1 19 17 18 1 20 18 19 2 21 19 20 1 22 20 21 1 23 21 22 1 24 22 23 1 25 22 24 1 26 23 27 1 27 24 25 1 28 25 26 1 29 26 27 1 ::: } } f_m_ct { s_m_title s_m_entry_id s_m_entry_name s_m_Source_Path s_m_Source_File i_m_Source_File_Index s_m_subgroup_title s_m_subgroupid b_m_subgroup_collapsed i_m_ct_format ::: "template 5" 7 templates.6 /Users/nicola/schrodinger/coordgenlibs templates.mae 6 templates templates1 0 2 m_atom[24] { # First column is atom index # i_m_mmod_type r_m_x_coord r_m_y_coord r_m_z_coord i_m_residue_number i_m_color i_m_atomic_number s_m_color_rgb ::: 1 5 -2.159300 7.906800 0.000000 9 2 6 A0A0A0 2 5 -1.746800 7.192300 0.000000 9 2 6 A0A0A0 3 5 -0.921800 7.192300 0.000000 9 2 6 A0A0A0 4 5 -0.509300 6.477800 0.000000 9 2 6 A0A0A0 5 4 0.315700 6.477800 0.000000 9 2 6 A0A0A0 6 5 0.728200 5.763300 0.000000 9 2 6 A0A0A0 7 5 1.553200 5.763300 0.000000 9 2 6 A0A0A0 8 5 1.965700 6.477800 0.000000 9 2 6 A0A0A0 9 5 0.728200 7.192300 0.000000 9 2 6 A0A0A0 10 4 1.553200 7.192300 0.000000 9 2 6 A0A0A0 11 5 1.965700 7.906800 0.000000 9 2 6 A0A0A0 12 5 1.553200 8.608600 0.000000 9 2 6 A0A0A0 13 5 0.728200 8.608600 0.000000 9 2 6 A0A0A0 14 5 0.315700 9.323100 0.000000 9 2 6 A0A0A0 15 5 -0.509300 9.323100 0.000000 9 2 6 A0A0A0 16 5 -0.921800 10.037500 0.000000 9 2 6 A0A0A0 17 5 -1.746800 10.037500 0.000000 9 2 6 A0A0A0 18 5 -2.159300 9.323100 0.000000 9 2 6 A0A0A0 19 4 -2.929500 9.027400 0.000000 9 2 6 A0A0A0 20 4 -2.929500 8.202400 0.000000 9 2 6 A0A0A0 21 5 -3.643900 9.439900 0.000000 9 2 6 A0A0A0 22 5 -4.358400 9.027400 0.000000 9 2 6 A0A0A0 23 5 -4.358400 8.202400 0.000000 9 2 6 A0A0A0 24 5 -3.643900 7.789900 0.000000 9 2 6 A0A0A0 ::: } m_bond[26] { # First column is bond index # i_m_from i_m_to i_m_order ::: 1 1 2 1 2 1 20 1 3 2 3 1 4 3 4 1 5 4 5 1 6 5 6 1 7 5 9 1 8 6 7 1 9 7 8 1 10 8 10 1 11 9 10 1 12 10 11 1 13 11 12 1 14 12 13 1 15 13 14 1 16 14 15 1 17 15 16 1 18 16 17 1 19 17 18 1 20 18 19 1 21 19 20 1 22 19 21 1 23 20 24 1 24 21 22 1 25 22 23 1 26 23 24 1 ::: } } f_m_ct { s_m_title s_m_entry_id s_m_entry_name s_m_Source_Path s_m_Source_File i_m_Source_File_Index s_m_subgroup_title s_m_subgroupid b_m_subgroup_collapsed i_m_ct_format ::: "template 6" 8 templates.7 /Users/nicola/schrodinger/coordgenlibs templates.mae 7 templates templates1 0 2 m_atom[27] { # First column is atom index # i_m_mmod_type r_m_x_coord r_m_y_coord r_m_z_coord i_m_residue_number i_m_color i_m_atomic_number s_m_color_rgb ::: 1 5 -0.714500 1.031200 0.000000 9 2 6 A0A0A0 2 5 -0.714500 0.206200 0.000000 9 2 6 A0A0A0 3 5 -1.428900 -0.206300 0.000000 9 2 6 A0A0A0 4 5 -1.428900 -1.031300 0.000000 9 2 6 A0A0A0 5 4 -0.714500 -1.443800 0.000000 9 2 6 A0A0A0 6 5 -0.714500 -2.268800 0.000000 9 2 6 A0A0A0 7 5 -0.000000 -2.681200 0.000000 9 2 6 A0A0A0 8 5 0.714500 -2.268800 0.000000 9 2 6 A0A0A0 9 5 0.000000 -1.031300 0.000000 9 2 6 A0A0A0 10 4 0.714500 -1.443800 0.000000 9 2 6 A0A0A0 11 5 1.428900 -1.031300 0.000000 9 2 6 A0A0A0 12 5 2.143400 -1.443800 0.000000 9 2 6 A0A0A0 13 5 2.857900 -1.031300 0.000000 9 2 6 A0A0A0 14 5 2.857900 -0.206300 0.000000 9 2 6 A0A0A0 15 5 2.143400 0.206200 0.000000 9 2 6 A0A0A0 16 5 2.143400 1.031200 0.000000 9 2 6 A0A0A0 17 5 1.428900 1.443700 0.000000 9 2 6 A0A0A0 18 5 1.428900 2.268700 0.000000 9 2 6 A0A0A0 19 5 0.714500 2.681200 0.000000 9 2 6 A0A0A0 20 5 0.000000 2.268700 0.000000 9 2 6 A0A0A0 21 5 -0.714500 2.681200 0.000000 9 2 6 A0A0A0 22 4 -1.428900 2.268700 0.000000 9 2 6 A0A0A0 23 4 -1.428900 1.443700 0.000000 9 2 6 A0A0A0 24 5 -2.143400 2.681200 0.000000 9 2 6 A0A0A0 25 5 -2.857900 2.268700 0.000000 9 2 6 A0A0A0 26 5 -2.857900 1.443700 0.000000 9 2 6 A0A0A0 27 5 -2.143400 1.031200 0.000000 9 2 6 A0A0A0 ::: } m_bond[29] { # First column is bond index # i_m_from i_m_to i_m_order ::: 1 1 2 1 2 1 23 1 3 2 3 1 4 3 4 1 5 4 5 1 6 5 6 1 7 5 9 1 8 6 7 1 9 7 8 1 10 8 10 1 11 9 10 1 12 10 11 1 13 11 12 1 14 12 13 1 15 13 14 1 16 14 15 1 17 15 16 1 18 16 17 1 19 17 18 1 20 18 19 1 21 19 20 1 22 20 21 1 23 21 22 1 24 22 23 1 25 22 24 1 26 23 27 1 27 24 25 1 28 25 26 1 29 26 27 1 ::: } } f_m_ct { s_m_title s_m_entry_id s_m_entry_name s_m_Source_Path s_m_Source_File i_m_Source_File_Index s_m_subgroup_title s_m_subgroupid b_m_subgroup_collapsed i_m_ct_format ::: "template 7" 9 templates.8 /Users/nicola/schrodinger/coordgenlibs templates.mae 8 templates templates1 0 2 m_atom[26] { # First column is atom index # i_m_mmod_type r_m_x_coord r_m_y_coord r_m_z_coord i_m_residue_number i_m_color i_m_atomic_number s_m_color_rgb ::: 1 5 -1.428900 -0.591400 0.000000 9 2 6 A0A0A0 2 5 -0.714400 -0.178900 0.000000 9 2 6 A0A0A0 3 5 -0.000000 -0.591400 0.000000 9 2 6 A0A0A0 4 5 0.714400 -0.178900 0.000000 9 2 6 A0A0A0 5 4 1.428900 -0.591400 0.000000 9 2 6 A0A0A0 6 5 1.428900 -1.416400 0.000000 9 2 6 A0A0A0 7 5 2.143300 -1.828800 0.000000 9 2 6 A0A0A0 8 5 2.857800 -1.416400 0.000000 9 2 6 A0A0A0 9 5 2.143300 -0.178900 0.000000 9 2 6 A0A0A0 10 4 2.857800 -0.591400 0.000000 9 2 6 A0A0A0 11 5 3.572300 -0.178900 0.000000 9 2 6 A0A0A0 12 5 3.572300 0.646100 0.000000 9 2 6 A0A0A0 13 5 2.845200 1.058600 0.000000 9 2 6 A0A0A0 14 5 2.549500 1.828800 0.000000 9 2 6 A0A0A0 15 5 1.724500 1.828800 0.000000 9 2 6 A0A0A0 16 5 1.428900 1.058600 0.000000 9 2 6 A0A0A0 17 5 0.714400 0.646100 0.000000 9 2 6 A0A0A0 18 5 -0.000000 1.058600 0.000000 9 2 6 A0A0A0 19 5 -0.714400 0.646100 0.000000 9 2 6 A0A0A0 20 5 -1.428900 1.058600 0.000000 9 2 6 A0A0A0 21 4 -2.143400 0.646100 0.000000 9 2 6 A0A0A0 22 4 -2.143400 -0.178900 0.000000 9 2 6 A0A0A0 23 5 -2.857800 1.058600 0.000000 9 2 6 A0A0A0 24 5 -3.572300 0.646100 0.000000 9 2 6 A0A0A0 25 5 -3.572300 -0.178900 0.000000 9 2 6 A0A0A0 26 5 -2.857800 -0.591400 0.000000 9 2 6 A0A0A0 ::: } m_bond[28] { # First column is bond index # i_m_from i_m_to i_m_order ::: 1 1 2 1 2 1 22 1 3 2 3 1 4 3 4 1 5 4 5 1 6 5 6 1 7 5 9 1 8 6 7 1 9 7 8 1 10 8 10 1 11 9 10 1 12 10 11 1 13 11 12 1 14 12 13 1 15 13 14 1 16 14 15 1 17 15 16 1 18 16 17 1 19 17 18 1 20 18 19 1 21 19 20 1 22 20 21 1 23 21 22 1 24 21 23 1 25 22 26 1 26 23 24 1 27 24 25 1 28 25 26 1 ::: } } f_m_ct { s_m_title s_m_entry_id s_m_entry_name s_m_Source_Path s_m_Source_File i_m_Source_File_Index s_m_subgroup_title s_m_subgroupid b_m_subgroup_collapsed i_m_ct_format ::: "template 8" 10 templates.9 /Users/nicola/schrodinger/coordgenlibs templates.mae 9 templates templates1 0 2 m_atom[34] { # First column is atom index # i_m_mmod_type r_m_x_coord r_m_y_coord r_m_z_coord i_m_residue_number i_m_color i_m_atomic_number i_m_formal_charge s_m_color_rgb ::: 1 7 -0.749600 -1.308200 0.000000 9 2 6 0 A0A0A0 2 7 -1.464000 -1.720700 0.000000 9 2 6 0 A0A0A0 3 7 -2.178500 -1.308200 0.000000 9 2 6 0 A0A0A0 4 2 -2.178500 -0.483200 0.000000 9 2 6 0 A0A0A0 5 7 -2.893000 -0.070700 0.000000 9 2 6 0 A0A0A0 6 7 -2.893000 0.754300 0.000000 9 2 6 0 A0A0A0 7 7 -2.178500 1.166800 0.000000 9 2 6 0 A0A0A0 8 2 -1.464000 0.754300 0.000000 9 2 6 0 A0A0A0 9 18 -0.648200 0.876700 0.000000 9 70 8 -1 FF2F2F 10 2 -1.464000 -0.070700 0.000000 9 2 6 0 A0A0A0 11 31 -0.749600 -0.483200 0.000000 9 43 7 1 5757FF 12 163 0.587100 0.100900 0.000000 9 4 13 3 1E1EE1 13 31 0.749600 1.550400 0.000000 9 43 7 1 5757FF 14 2 1.464000 1.962900 0.000000 9 2 6 0 A0A0A0 15 2 1.464000 2.787900 0.000000 9 2 6 0 A0A0A0 16 7 0.749600 3.200400 0.000000 9 2 6 0 A0A0A0 17 7 0.035100 2.787900 0.000000 9 2 6 0 A0A0A0 18 7 0.035100 1.962900 0.000000 9 2 6 0 A0A0A0 19 7 2.178500 3.200400 0.000000 9 2 6 0 A0A0A0 20 7 2.893000 2.787900 0.000000 9 2 6 0 A0A0A0 21 7 2.893000 1.962900 0.000000 9 2 6 0 A0A0A0 22 2 2.178500 1.550400 0.000000 9 2 6 0 A0A0A0 23 18 1.876500 0.782700 0.000000 9 70 8 -1 FF2F2F 24 31 0.532800 -1.356800 0.000000 9 43 7 1 5757FF 25 2 1.178200 -1.870700 0.000000 9 2 6 0 A0A0A0 26 2 1.945900 -1.568700 0.000000 9 2 6 0 A0A0A0 27 18 1.761200 -0.764600 0.000000 9 70 8 -1 FF2F2F 28 7 2.591300 -2.082600 0.000000 9 2 6 0 A0A0A0 29 7 2.468900 -2.898500 0.000000 9 2 6 0 A0A0A0 30 7 1.701200 -3.200400 0.000000 9 2 6 0 A0A0A0 31 2 1.055800 -2.686500 0.000000 9 2 6 0 A0A0A0 32 7 0.288100 -2.988500 0.000000 9 2 6 0 A0A0A0 33 7 -0.357300 -2.474600 0.000000 9 2 6 0 A0A0A0 34 7 -0.235000 -1.658700 0.000000 9 2 6 0 A0A0A0 ::: } m_bond[42] { # First column is bond index # i_m_from i_m_to i_m_order ::: 1 1 2 2 2 1 11 1 3 2 3 1 4 3 4 2 5 4 5 1 6 4 10 1 7 5 6 2 8 6 7 1 9 7 8 2 10 8 9 1 11 8 10 1 12 9 12 1 13 10 11 2 14 11 12 1 15 12 13 1 16 12 23 1 17 12 24 1 18 12 27 1 19 13 14 2 20 13 18 1 21 14 15 1 22 14 22 1 23 15 16 2 24 15 19 1 25 16 17 1 26 17 18 2 27 19 20 2 28 20 21 1 29 21 22 2 30 22 23 1 31 24 25 2 32 24 34 1 33 25 26 1 34 25 31 1 35 26 27 1 36 26 28 2 37 28 29 1 38 29 30 2 39 30 31 1 40 31 32 2 41 32 33 1 42 33 34 2 ::: } } f_m_ct { s_m_title s_m_entry_id s_m_entry_name s_m_Source_Path s_m_Source_File i_m_Source_File_Index s_m_subgroup_title s_m_subgroupid b_m_subgroup_collapsed i_m_ct_format ::: "template 9" 11 templates.10 /Users/nicola/schrodinger/coordgenlibs templates.mae 10 templates templates1 0 2 m_atom[22] { # First column is atom index # i_m_mmod_type r_m_x_coord r_m_y_coord r_m_z_coord i_m_residue_number i_m_color i_m_atomic_number s_m_color_rgb s_m_atom_name ::: 1 7 0.159300 3.056900 0.000000 9 2 6 A0A0A0 C1 2 7 0.859700 2.621000 0.000000 9 2 6 A0A0A0 C2 3 2 0.859700 1.796000 0.000000 9 2 6 A0A0A0 C3 4 7 -0.581000 2.692600 0.000000 9 2 6 A0A0A0 C4 5 2 -0.662800 1.871700 0.000000 9 2 6 A0A0A0 C5 6 7 0.082700 1.518500 0.000000 9 2 6 A0A0A0 C6 7 5 -1.341500 1.402600 0.000000 9 2 6 A0A0A0 C7 8 5 -1.274600 0.580400 0.000000 9 2 6 A0A0A0 C8 9 27 -1.809300 -0.048800 0.000000 9 43 7 5757FF N9 10 5 -1.531900 -0.825800 0.000000 9 2 6 A0A0A0 C10 11 5 -0.720300 -0.973900 0.000000 9 2 6 A0A0A0 C11 12 2 -0.251200 -1.652600 0.000000 9 2 6 A0A0A0 C12 13 7 0.559600 -1.500100 0.000000 9 2 6 A0A0A0 C13 14 2 1.097000 -2.126000 0.000000 9 2 6 A0A0A0 C14 15 7 0.823700 -2.904400 0.000000 9 2 6 A0A0A0 C15 16 7 0.012900 -3.056900 0.000000 9 2 6 A0A0A0 C16 17 7 -0.524500 -2.431000 0.000000 9 2 6 A0A0A0 C17 18 5 1.775700 -1.656900 0.000000 9 2 6 A0A0A0 C18 19 5 1.380100 -0.933000 0.000000 9 2 6 A0A0A0 C19 20 5 1.809300 -0.228400 0.000000 9 2 6 A0A0A0 C20 21 5 1.340200 0.450300 0.000000 9 2 6 A0A0A0 C21 22 5 1.488400 1.261900 0.000000 9 2 6 A0A0A0 C22 ::: } m_bond[24] { # First column is bond index # i_m_from i_m_to i_m_order ::: 1 1 2 2 2 1 4 1 3 2 3 1 4 3 6 2 5 3 22 1 6 4 5 2 7 5 6 1 8 5 7 1 9 7 8 1 10 8 9 1 11 9 10 1 12 10 11 1 13 11 12 1 14 12 13 2 15 12 17 1 16 13 14 1 17 14 15 2 18 14 18 1 19 15 16 1 20 16 17 2 21 18 19 1 22 19 20 1 23 20 21 1 24 21 22 1 ::: } } f_m_ct { s_m_title s_m_entry_id s_m_entry_name s_m_Source_Path s_m_Source_File i_m_Source_File_Index s_m_subgroup_title s_m_subgroupid b_m_subgroup_collapsed i_m_ct_format ::: "template 10" 12 templates.11 /Users/nicola/schrodinger/coordgenlibs templates.mae 11 templates templates1 0 2 m_atom[22] { # First column is atom index # i_m_mmod_type r_m_x_coord r_m_y_coord r_m_z_coord i_m_residue_number i_m_color i_m_atomic_number s_m_color_rgb ::: 1 5 0.714500 1.650000 0.000000 9 2 6 A0A0A0 2 27 0.714500 0.825000 0.000000 9 43 7 5757FF 3 5 1.428900 0.412500 0.000000 9 2 6 A0A0A0 4 5 0.000000 2.062500 0.000000 9 2 6 A0A0A0 5 4 -0.714500 1.650000 0.000000 9 2 6 A0A0A0 6 5 -1.428900 2.062500 0.000000 9 2 6 A0A0A0 7 5 -2.143400 1.650000 0.000000 9 2 6 A0A0A0 8 5 -2.143400 0.825000 0.000000 9 2 6 A0A0A0 9 5 -0.714500 0.825000 0.000000 9 2 6 A0A0A0 10 4 -1.428900 0.412500 0.000000 9 2 6 A0A0A0 11 16 -1.428900 -0.412500 0.000000 9 70 8 FF2F2F 12 5 -2.143400 -0.825000 0.000000 9 2 6 A0A0A0 13 5 -2.143400 -1.650000 0.000000 9 2 6 A0A0A0 14 5 -1.428900 -2.062500 0.000000 9 2 6 A0A0A0 15 5 -0.714500 -1.650000 0.000000 9 2 6 A0A0A0 16 27 0.000000 -2.062500 0.000000 9 43 7 5757FF 17 4 0.714500 -1.650000 0.000000 9 2 6 A0A0A0 18 5 0.714500 -0.825000 0.000000 9 2 6 A0A0A0 19 5 1.428900 -2.062500 0.000000 9 2 6 A0A0A0 20 5 2.143400 -1.650000 0.000000 9 2 6 A0A0A0 21 5 2.143400 -0.825000 0.000000 9 2 6 A0A0A0 22 4 1.428900 -0.412500 0.000000 9 2 6 A0A0A0 ::: } m_bond[24] { # First column is bond index # i_m_from i_m_to i_m_order ::: 1 1 2 1 2 1 4 1 3 2 3 1 4 3 22 1 5 4 5 1 6 5 6 1 7 5 9 1 8 6 7 1 9 7 8 1 10 8 10 1 11 9 10 1 12 10 11 1 13 11 12 1 14 12 13 1 15 13 14 1 16 14 15 1 17 15 16 1 18 16 17 1 19 17 18 1 20 17 19 1 21 18 22 1 22 19 20 1 23 20 21 1 24 21 22 1 ::: } } f_m_ct { s_m_title s_m_entry_id s_m_entry_name s_m_Source_Path s_m_Source_File i_m_Source_File_Index s_m_subgroup_title s_m_subgroupid b_m_subgroup_collapsed i_m_ct_format ::: "template 11" 13 templates.12 /Users/nicola/schrodinger/coordgenlibs templates.mae 12 templates templates1 0 2 m_atom[19] { # First column is atom index # i_m_mmod_type r_m_x_coord r_m_y_coord r_m_z_coord i_m_residue_number i_m_color i_m_atomic_number s_m_color_rgb s_m_atom_name ::: 1 5 -0.206200 1.786200 0.000000 9 2 6 A0A0A0 C1 2 5 0.206300 1.071700 0.000000 9 2 6 A0A0A0 C2 3 29 1.031300 1.071700 0.000000 9 43 7 5757FF N3 4 5 -1.031200 1.786200 0.000000 9 2 6 A0A0A0 C4 5 5 -1.443700 1.071700 0.000000 9 2 6 A0A0A0 C5 6 5 -2.268700 1.071700 0.000000 9 2 6 A0A0A0 C6 7 5 -2.681200 0.357200 0.000000 9 2 6 A0A0A0 C7 8 5 -2.268700 -0.357200 0.000000 9 2 6 A0A0A0 C8 9 5 -1.443700 -0.357200 0.000000 9 2 6 A0A0A0 C9 10 5 -1.031200 -1.071700 0.000000 9 2 6 A0A0A0 C10 11 27 -0.206200 -1.071700 0.000000 9 43 7 5757FF N11 12 5 0.206300 -1.786200 0.000000 9 2 6 A0A0A0 C12 13 5 1.031300 -1.786200 0.000000 9 2 6 A0A0A0 C13 14 2 1.443800 -1.071700 0.000000 9 2 6 A0A0A0 C14 15 7 1.031300 -0.357200 0.000000 9 2 6 A0A0A0 C15 16 2 1.443800 0.357200 0.000000 9 2 6 A0A0A0 C16 17 7 2.268800 -1.071700 0.000000 9 2 6 A0A0A0 C17 18 7 2.681200 -0.357200 0.000000 9 2 6 A0A0A0 C18 19 7 2.268800 0.357200 0.000000 9 2 6 A0A0A0 C19 ::: } m_bond[20] { # First column is bond index # i_m_from i_m_to i_m_order ::: 1 1 2 1 2 1 4 1 3 2 3 1 4 3 16 1 5 4 5 1 6 5 6 1 7 6 7 1 8 7 8 1 9 8 9 1 10 9 10 1 11 10 11 1 12 11 12 1 13 12 13 1 14 13 14 1 15 14 15 2 16 14 17 1 17 15 16 1 18 16 19 2 19 17 18 2 20 18 19 1 ::: } } f_m_ct { s_m_title s_m_entry_id s_m_entry_name s_m_Source_Path s_m_Source_File i_m_Source_File_Index s_m_subgroup_title s_m_subgroupid b_m_subgroup_collapsed i_m_ct_format ::: "template 12" 14 templates.13 /Users/nicola/schrodinger/coordgenlibs templates.mae 13 templates templates1 0 2 m_atom[12] { # First column is atom index # i_m_mmod_type r_m_x_coord r_m_y_coord r_m_z_coord i_m_residue_number i_m_color i_m_atomic_number s_m_color_rgb ::: 1 27 2.259400 -2.751000 0.000000 9 43 7 5757FF 2 27 3.230400 -1.703100 0.000000 9 43 7 5757FF 3 26 0.947900 -2.321500 0.000000 9 43 7 5757FF 4 4 0.600500 -1.146200 0.000000 9 2 6 A0A0A0 5 4 -0.515400 -2.828800 0.000000 9 2 6 A0A0A0 6 4 -1.525500 -1.818600 0.000000 9 2 6 A0A0A0 7 5 1.380300 -0.368400 0.000000 9 2 6 A0A0A0 8 5 0.000000 0.000000 0.000000 9 2 6 A0A0A0 9 5 -2.905400 -2.188300 0.000000 9 2 6 A0A0A0 10 5 -3.275200 -3.568200 0.000000 9 2 6 A0A0A0 11 5 -2.265100 -4.578400 0.000000 9 2 6 A0A0A0 12 5 -0.885200 -4.208700 0.000000 9 2 6 A0A0A0 ::: } m_bond[14] { # First column is bond index # i_m_from i_m_to i_m_order ::: 1 1 2 1 2 1 3 1 3 2 4 1 4 3 7 1 5 3 5 1 6 4 8 1 7 4 6 1 8 5 6 1 9 5 12 1 10 6 9 1 11 7 8 1 12 9 10 1 13 10 11 1 14 11 12 1 ::: } } f_m_ct { s_m_title s_m_entry_id s_m_entry_name s_m_Source_Path s_m_Source_File i_m_Source_File_Index s_m_subgroup_title s_m_subgroupid b_m_subgroup_collapsed i_m_ct_format ::: CRDGEN-85_template_2 15 templates.14 /Users/nicola/schrodinger/coordgenlibs templates.mae 14 templates templates1 0 2 m_atom[22] { # First column is atom index # i_m_mmod_type r_m_x_coord r_m_y_coord r_m_z_coord i_m_residue_number i_m_color i_m_atomic_number s_m_color_rgb ::: 1 5 -17.652800 -2.580900 0.000000 9 2 6 A0A0A0 2 4 -16.863400 -2.422000 0.000000 9 2 6 A0A0A0 3 4 -16.256600 -0.995200 0.000000 9 2 6 A0A0A0 4 5 -16.664200 -0.306500 0.000000 9 2 6 A0A0A0 5 5 -13.305800 -3.061000 0.000000 9 2 6 A0A0A0 6 4 -13.370000 -1.860200 0.000000 9 2 6 A0A0A0 7 5 -14.160600 -1.624400 0.000000 9 2 6 A0A0A0 8 4 -13.924800 -0.833800 0.000000 9 2 6 A0A0A0 9 5 -14.684000 -0.510900 0.000000 9 2 6 A0A0A0 10 5 -13.789500 -3.729300 0.000000 9 2 6 A0A0A0 11 5 -14.515300 -4.121600 0.000000 9 2 6 A0A0A0 12 5 -15.339400 -4.160100 0.000000 9 2 6 A0A0A0 13 5 -16.098600 -3.837200 0.000000 9 2 6 A0A0A0 14 5 -16.642500 -3.216900 0.000000 9 2 6 A0A0A0 15 5 -16.300300 -1.819000 0.000000 9 2 6 A0A0A0 16 5 -15.508100 -0.549400 0.000000 9 2 6 A0A0A0 17 5 -13.134200 -1.069700 0.000000 9 2 6 A0A0A0 18 5 -18.479200 -2.308500 0.000000 9 2 6 A0A0A0 19 5 -17.336000 0.070600 0.000000 9 2 6 A0A0A0 20 5 -18.944700 -1.666200 0.000000 9 2 6 A0A0A0 21 5 -18.863600 -0.722000 0.000000 9 2 6 A0A0A0 22 5 -18.219900 -0.017800 0.000000 9 2 6 A0A0A0 ::: } m_bond[24] { # First column is bond index # i_m_from i_m_to i_m_order ::: 1 1 2 1 2 1 18 1 3 2 14 1 4 2 15 1 5 3 4 1 6 3 16 1 7 3 15 1 8 4 19 1 9 5 10 1 10 5 6 1 11 6 7 1 12 6 17 1 13 7 8 1 14 8 9 1 15 8 17 1 16 9 16 1 17 10 11 1 18 11 12 1 19 12 13 1 20 13 14 1 21 18 20 1 22 19 22 1 23 20 21 1 24 21 22 1 ::: } } f_m_ct { s_m_title s_m_entry_id s_m_entry_name s_m_Source_Path s_m_Source_File i_m_Source_File_Index s_m_subgroup_title s_m_subgroupid b_m_subgroup_collapsed i_m_ct_format ::: CRDGEN-85_template 16 templates.15 /Users/nicola/schrodinger/coordgenlibs templates.mae 15 templates templates1 0 2 m_atom[21] { # First column is atom index # i_m_mmod_type r_m_x_coord r_m_y_coord r_m_z_coord i_m_residue_number i_m_color i_m_atomic_number s_m_color_rgb ::: 1 5 -18.373900 -2.072200 0.000000 9 2 6 A0A0A0 2 5 -17.682300 -2.522000 0.000000 9 2 6 A0A0A0 3 4 -16.863400 -2.422000 0.000000 9 2 6 A0A0A0 4 4 -16.256600 -0.995200 0.000000 9 2 6 A0A0A0 5 5 -16.752600 -0.336000 0.000000 9 2 6 A0A0A0 6 5 -17.556400 -0.149800 0.000000 9 2 6 A0A0A0 7 5 -18.291700 -0.523900 0.000000 9 2 6 A0A0A0 8 5 -18.614600 -1.283100 0.000000 9 2 6 A0A0A0 9 5 -13.305800 -3.061000 0.000000 9 2 6 A0A0A0 10 4 -13.370000 -1.860200 0.000000 9 2 6 A0A0A0 11 5 -14.160600 -1.624400 0.000000 9 2 6 A0A0A0 12 4 -13.924800 -0.833800 0.000000 9 2 6 A0A0A0 13 5 -14.684000 -0.510900 0.000000 9 2 6 A0A0A0 14 5 -13.789500 -3.729300 0.000000 9 2 6 A0A0A0 15 5 -14.515300 -4.121600 0.000000 9 2 6 A0A0A0 16 5 -15.339400 -4.160100 0.000000 9 2 6 A0A0A0 17 5 -16.098600 -3.837200 0.000000 9 2 6 A0A0A0 18 5 -16.642500 -3.216900 0.000000 9 2 6 A0A0A0 19 5 -16.300300 -1.819000 0.000000 9 2 6 A0A0A0 20 5 -15.508100 -0.549400 0.000000 9 2 6 A0A0A0 21 5 -13.134200 -1.069700 0.000000 9 2 6 A0A0A0 ::: } m_bond[23] { # First column is bond index # i_m_from i_m_to i_m_order ::: 1 1 2 1 2 1 8 1 3 2 3 1 4 3 18 1 5 3 19 1 6 4 5 1 7 4 20 1 8 4 19 1 9 5 6 1 10 6 7 1 11 7 8 1 12 9 14 1 13 9 10 1 14 10 11 1 15 10 21 1 16 11 12 1 17 12 13 1 18 12 21 1 19 13 20 1 20 14 15 1 21 15 16 1 22 16 17 1 23 17 18 1 ::: } } f_m_ct { s_m_title s_m_entry_id s_m_entry_name s_m_Source_Path s_m_Source_File i_m_Source_File_Index s_m_subgroup_title s_m_subgroupid b_m_subgroup_collapsed i_m_ct_format ::: "template 15" 17 templates.16 /Users/nicola/schrodinger/coordgenlibs templates.mae 16 templates templates1 0 2 m_atom[17] { # First column is atom index # i_m_mmod_type r_m_x_coord r_m_y_coord r_m_z_coord i_m_residue_number i_m_color i_m_atomic_number s_m_color_rgb ::: 1 5 -2.021800 0.783500 0.000000 9 2 6 A0A0A0 2 5 -1.820500 -0.016500 0.000000 9 2 6 A0A0A0 3 4 -1.027000 -0.242200 0.000000 9 2 6 A0A0A0 4 4 -0.434800 0.332100 0.000000 9 2 6 A0A0A0 5 4 -0.636100 1.132200 0.000000 9 2 6 A0A0A0 6 5 -1.429600 1.357900 0.000000 9 2 6 A0A0A0 7 3 0.388400 0.276300 0.000000 9 2 6 A0A0A0 8 4 0.695800 1.041900 0.000000 9 2 6 A0A0A0 9 5 0.062600 1.570900 0.000000 9 2 6 A0A0A0 10 5 0.897700 -0.372700 0.000000 9 2 6 A0A0A0 11 5 1.714400 -0.256100 0.000000 9 2 6 A0A0A0 12 5 2.021800 0.509500 0.000000 9 2 6 A0A0A0 13 5 1.512500 1.158500 0.000000 9 2 6 A0A0A0 14 5 -1.077700 -1.065700 0.000000 9 2 6 A0A0A0 15 5 0.589700 -0.523700 0.000000 9 2 6 A0A0A0 16 5 0.359100 -1.315900 0.000000 9 2 6 A0A0A0 17 5 -0.425500 -1.570900 0.000000 9 2 6 A0A0A0 ::: } m_bond[20] { # First column is bond index # i_m_from i_m_to i_m_order ::: 1 1 2 1 2 1 6 1 3 2 3 1 4 3 4 1 5 3 14 1 6 4 5 1 7 4 7 1 8 5 6 1 9 5 9 1 10 7 8 1 11 7 10 1 12 7 15 1 13 8 9 1 14 8 13 1 15 10 11 1 16 11 12 1 17 12 13 1 18 14 17 1 19 15 16 1 20 16 17 1 ::: } } f_m_ct { s_m_title s_m_entry_id s_m_entry_name s_m_Source_Path s_m_Source_File i_m_Source_File_Index s_m_subgroup_title s_m_subgroupid b_m_subgroup_collapsed i_m_ct_format ::: "template 16" 18 templates.17 /Users/nicola/schrodinger/coordgenlibs templates.mae 17 templates templates1 0 2 m_atom[15] { # First column is atom index # i_m_mmod_type r_m_x_coord r_m_y_coord r_m_z_coord i_m_residue_number i_m_color i_m_atomic_number s_m_color_rgb s_m_atom_name ::: 1 5 1.186400 1.035900 0.000000 9 2 6 A0A0A0 C1 2 5 0.370300 1.157000 0.000000 9 2 6 A0A0A0 C2 3 4 -0.326500 0.715300 0.000000 9 2 6 A0A0A0 C3 4 5 0.085100 0.000400 0.000000 9 2 6 A0A0A0 C4 5 26 -0.328300 -0.713600 0.000000 9 43 7 5757FF N5 6 5 -1.151500 0.716400 0.000000 9 2 6 A0A0A0 C6 7 5 -1.564900 0.002400 0.000000 9 2 6 A0A0A0 C7 8 5 -1.153300 -0.712600 0.000000 9 2 6 A0A0A0 C9 9 2 1.724800 0.410800 0.000000 9 2 6 A0A0A0 C12 10 2 1.723800 -0.414200 0.000000 9 2 6 A0A0A0 C13 11 5 1.183800 -1.037900 0.000000 9 2 6 A0A0A0 C14 12 5 0.367400 -1.157000 0.000000 9 2 6 A0A0A0 C15 13 7 2.508100 -0.670100 0.000000 9 2 6 A0A0A0 C16 14 7 2.993800 -0.003300 0.000000 9 2 6 A0A0A0 C17 15 29 2.509700 0.664800 0.000000 9 43 7 5757FF N18 ::: } m_bond[17] { # First column is bond index # i_m_from i_m_to i_m_order ::: 1 1 2 1 2 1 9 1 3 2 3 1 4 3 4 1 5 3 6 1 6 4 5 1 7 5 8 1 8 5 12 1 9 6 7 1 10 7 8 1 11 9 10 2 12 9 15 1 13 10 11 1 14 10 13 1 15 11 12 1 16 13 14 2 17 14 15 1 ::: } } f_m_ct { s_m_title s_m_entry_id s_m_entry_name s_m_Source_Path s_m_Source_File i_m_Source_File_Index s_m_subgroup_title s_m_subgroupid b_m_subgroup_collapsed i_m_ct_format ::: "template 17" 19 templates.18 /Users/nicola/schrodinger/coordgenlibs templates.mae 18 templates templates1 0 2 m_atom[21] { # First column is atom index # i_m_mmod_type r_m_x_coord r_m_y_coord r_m_z_coord i_m_residue_number i_m_color i_m_atomic_number s_m_color_rgb ::: 1 4 -1.155700 -2.185300 0.000000 9 2 6 A0A0A0 2 4 -1.155700 -1.360400 0.000000 9 2 6 A0A0A0 3 4 -0.441300 -2.597800 0.000000 9 2 6 A0A0A0 4 5 0.273100 -2.185300 0.000000 9 2 6 A0A0A0 5 5 0.273100 -1.360400 0.000000 9 2 6 A0A0A0 6 4 -0.441300 -0.947900 0.000000 9 2 6 A0A0A0 7 5 -0.227800 -1.800900 0.000000 9 2 6 A0A0A0 8 5 -0.028800 -0.233400 0.000000 9 2 6 A0A0A0 9 5 -0.028800 0.591600 0.000000 9 2 6 A0A0A0 10 3 -0.743300 1.004100 0.000000 9 2 6 A0A0A0 11 5 -1.155700 0.289600 0.000000 9 2 6 A0A0A0 12 5 -1.155700 -0.535400 0.000000 9 2 6 A0A0A0 13 5 -0.159900 1.587500 0.000000 9 2 6 A0A0A0 14 27 -0.373500 2.384200 0.000000 9 43 7 5757FF 15 5 -1.170300 2.597800 0.000000 9 2 6 A0A0A0 16 5 -1.753600 2.014400 0.000000 9 2 6 A0A0A0 17 5 -1.540100 1.217600 0.000000 9 2 6 A0A0A0 18 5 -1.870200 -0.947900 0.000000 9 2 6 A0A0A0 19 5 -2.584600 -1.360400 0.000000 9 2 6 A0A0A0 20 5 -2.584600 -2.185300 0.000000 9 2 6 A0A0A0 21 5 -1.870200 -2.597800 0.000000 9 2 6 A0A0A0 ::: } m_bond[24] { # First column is bond index # i_m_from i_m_to i_m_order ::: 1 1 2 1 2 1 3 1 3 1 21 1 4 2 6 1 5 2 18 1 6 3 4 1 7 3 7 1 8 4 5 1 9 5 6 1 10 6 8 1 11 7 12 1 12 8 9 1 13 9 10 1 14 10 11 1 15 10 13 1 16 10 17 1 17 11 12 1 18 13 14 1 19 14 15 1 20 15 16 1 21 16 17 1 22 18 19 1 23 19 20 1 24 20 21 1 ::: } } f_m_ct { s_m_title s_m_entry_id s_m_entry_name s_m_Source_Path s_m_Source_File i_m_Source_File_Index s_m_subgroup_title s_m_subgroupid b_m_subgroup_collapsed i_m_ct_format ::: "template 18" 20 templates.19 /Users/nicola/schrodinger/coordgenlibs templates.mae 19 templates templates1 0 2 m_atom[28] { # First column is atom index # i_m_mmod_type r_m_x_coord r_m_y_coord r_m_z_coord i_m_residue_number i_m_color i_m_atomic_number s_m_color_rgb ::: 1 4 -1.155700 -2.185300 0.000000 9 2 6 A0A0A0 2 4 -1.155700 -1.360400 0.000000 9 2 6 A0A0A0 3 4 -0.441300 -2.597800 0.000000 9 2 6 A0A0A0 4 4 0.273100 -2.185300 0.000000 9 2 6 A0A0A0 5 4 0.273100 -1.360400 0.000000 9 2 6 A0A0A0 6 4 -0.441300 -0.947900 0.000000 9 2 6 A0A0A0 7 5 0.987600 -2.597800 0.000000 9 2 6 A0A0A0 8 4 1.702100 -2.185300 0.000000 9 2 6 A0A0A0 9 5 1.702100 -1.360400 0.000000 9 2 6 A0A0A0 10 4 0.987600 -0.947900 0.000000 9 2 6 A0A0A0 11 5 1.870300 -0.480400 0.000000 9 2 6 A0A0A0 12 5 2.584600 -0.892900 0.000000 9 2 6 A0A0A0 13 5 2.584600 -1.717800 0.000000 9 2 6 A0A0A0 14 5 -0.227800 -1.800900 0.000000 9 2 6 A0A0A0 15 5 -0.028800 -0.233400 0.000000 9 2 6 A0A0A0 16 5 -0.028800 0.591600 0.000000 9 2 6 A0A0A0 17 3 -0.743300 1.004100 0.000000 9 2 6 A0A0A0 18 5 -1.155700 0.289600 0.000000 9 2 6 A0A0A0 19 5 -1.155700 -0.535400 0.000000 9 2 6 A0A0A0 20 5 -0.159900 1.587500 0.000000 9 2 6 A0A0A0 21 27 -0.373500 2.384200 0.000000 9 43 7 5757FF 22 5 -1.170300 2.597800 0.000000 9 2 6 A0A0A0 23 5 -1.753600 2.014400 0.000000 9 2 6 A0A0A0 24 5 -1.540100 1.217600 0.000000 9 2 6 A0A0A0 25 5 -1.870200 -0.947900 0.000000 9 2 6 A0A0A0 26 5 -2.584600 -1.360400 0.000000 9 2 6 A0A0A0 27 5 -2.584600 -2.185300 0.000000 9 2 6 A0A0A0 28 5 -1.870200 -2.597800 0.000000 9 2 6 A0A0A0 ::: } m_bond[33] { # First column is bond index # i_m_from i_m_to i_m_order ::: 1 1 2 1 2 1 3 1 3 1 28 1 4 2 6 1 5 2 25 1 6 3 4 1 7 3 14 1 8 4 5 1 9 4 7 1 10 5 6 1 11 5 10 1 12 6 15 1 13 7 8 1 14 8 9 1 15 8 13 1 16 9 10 1 17 10 11 1 18 11 12 1 19 12 13 1 20 14 19 1 21 15 16 1 22 16 17 1 23 17 18 1 24 17 20 1 25 17 24 1 26 18 19 1 27 20 21 1 28 21 22 1 29 22 23 1 30 23 24 1 31 25 26 1 32 26 27 1 33 27 28 1 ::: } } f_m_ct { s_m_title s_m_entry_id s_m_entry_name s_m_Source_Path s_m_Source_File i_m_Source_File_Index s_m_subgroup_title s_m_subgroupid b_m_subgroup_collapsed i_m_ct_format ::: "template 19" 21 templates.20 /Users/nicola/schrodinger/coordgenlibs templates.mae 20 templates templates1 0 2 m_atom[23] { # First column is atom index # i_m_mmod_type r_m_x_coord r_m_y_coord r_m_z_coord i_m_residue_number i_m_color i_m_atomic_number s_m_color_rgb ::: 1 4 -1.155700 -2.185300 0.000000 9 2 6 A0A0A0 2 4 -1.155700 -1.360400 0.000000 9 2 6 A0A0A0 3 4 -0.441300 -2.597800 0.000000 9 2 6 A0A0A0 4 4 0.273100 -2.185300 0.000000 9 2 6 A0A0A0 5 4 0.273100 -1.360400 0.000000 9 2 6 A0A0A0 6 4 -0.441300 -0.947900 0.000000 9 2 6 A0A0A0 7 5 0.987600 -2.597800 0.000000 9 2 6 A0A0A0 8 4 1.702100 -2.185300 0.000000 9 2 6 A0A0A0 9 5 1.702100 -1.360400 0.000000 9 2 6 A0A0A0 10 4 0.987600 -0.947900 0.000000 9 2 6 A0A0A0 11 5 1.870300 -0.480400 0.000000 9 2 6 A0A0A0 12 5 2.584600 -0.892900 0.000000 9 2 6 A0A0A0 13 5 2.584600 -1.717800 0.000000 9 2 6 A0A0A0 14 5 -0.227800 -1.800900 0.000000 9 2 6 A0A0A0 15 5 -0.028800 -0.233400 0.000000 9 2 6 A0A0A0 16 5 -0.028800 0.591600 0.000000 9 2 6 A0A0A0 17 5 -0.743300 1.004100 0.000000 9 2 6 A0A0A0 18 5 -1.155700 0.289600 0.000000 9 2 6 A0A0A0 19 5 -1.155700 -0.535400 0.000000 9 2 6 A0A0A0 20 5 -1.870200 -0.947900 0.000000 9 2 6 A0A0A0 21 5 -2.584600 -1.360400 0.000000 9 2 6 A0A0A0 22 5 -2.584600 -2.185300 0.000000 9 2 6 A0A0A0 23 5 -1.870200 -2.597800 0.000000 9 2 6 A0A0A0 ::: } m_bond[27] { # First column is bond index # i_m_from i_m_to i_m_order ::: 1 1 2 1 2 1 3 1 3 1 23 1 4 2 6 1 5 2 20 1 6 3 4 1 7 3 14 1 8 4 5 1 9 4 7 1 10 5 6 1 11 5 10 1 12 6 15 1 13 7 8 1 14 8 9 1 15 8 13 1 16 9 10 1 17 10 11 1 18 11 12 1 19 12 13 1 20 14 19 1 21 15 16 1 22 16 17 1 23 17 18 1 24 18 19 1 25 20 21 1 26 21 22 1 27 22 23 1 ::: } } f_m_ct { s_m_title s_m_entry_id s_m_entry_name s_m_Source_Path s_m_Source_File i_m_Source_File_Index s_m_subgroup_title s_m_subgroupid b_m_subgroup_collapsed i_m_ct_format ::: "template 20" 22 templates.21 /Users/nicola/schrodinger/coordgenlibs templates.mae 21 templates templates1 0 2 m_atom[19] { # First column is atom index # i_m_mmod_type r_m_x_coord r_m_y_coord r_m_z_coord i_m_residue_number i_m_color i_m_atomic_number s_m_color_rgb ::: 1 5 -1.155700 -2.185300 0.000000 9 2 6 A0A0A0 2 5 -1.155700 -1.360400 0.000000 9 2 6 A0A0A0 3 4 -0.441300 -2.597800 0.000000 9 2 6 A0A0A0 4 4 0.273100 -2.185300 0.000000 9 2 6 A0A0A0 5 4 0.273100 -1.360400 0.000000 9 2 6 A0A0A0 6 4 -0.441300 -0.947900 0.000000 9 2 6 A0A0A0 7 5 0.987600 -2.597800 0.000000 9 2 6 A0A0A0 8 4 1.702100 -2.185300 0.000000 9 2 6 A0A0A0 9 5 1.702100 -1.360400 0.000000 9 2 6 A0A0A0 10 4 0.987600 -0.947900 0.000000 9 2 6 A0A0A0 11 5 1.870300 -0.480400 0.000000 9 2 6 A0A0A0 12 5 2.584600 -0.892900 0.000000 9 2 6 A0A0A0 13 5 2.584600 -1.717800 0.000000 9 2 6 A0A0A0 14 5 -0.227800 -1.800900 0.000000 9 2 6 A0A0A0 15 5 -0.028800 -0.233400 0.000000 9 2 6 A0A0A0 16 5 -0.028800 0.591600 0.000000 9 2 6 A0A0A0 17 5 -0.743300 1.004100 0.000000 9 2 6 A0A0A0 18 5 -1.155700 0.289600 0.000000 9 2 6 A0A0A0 19 5 -1.155700 -0.535400 0.000000 9 2 6 A0A0A0 ::: } m_bond[22] { # First column is bond index # i_m_from i_m_to i_m_order ::: 1 1 2 1 2 1 3 1 3 2 6 1 4 3 4 1 5 3 14 1 6 4 5 1 7 4 7 1 8 5 6 1 9 5 10 1 10 6 15 1 11 7 8 1 12 8 9 1 13 8 13 1 14 9 10 1 15 10 11 1 16 11 12 1 17 12 13 1 18 14 19 1 19 15 16 1 20 16 17 1 21 17 18 1 22 18 19 1 ::: } } f_m_ct { s_m_title s_m_entry_id s_m_entry_name s_m_Source_Path s_m_Source_File i_m_Source_File_Index s_m_subgroup_title s_m_subgroupid b_m_subgroup_collapsed i_m_ct_format ::: "template 21" 23 templates.22 /Users/nicola/schrodinger/coordgenlibs templates.mae 22 templates templates1 0 2 m_atom[16] { # First column is atom index # i_m_mmod_type r_m_x_coord r_m_y_coord r_m_z_coord i_m_residue_number i_m_color i_m_atomic_number s_m_color_rgb ::: 1 5 -1.661900 0.540000 0.000000 9 2 6 A0A0A0 2 5 -1.661900 -0.285000 0.000000 9 2 6 A0A0A0 3 3 -0.877200 -0.540000 0.000000 9 2 6 A0A0A0 4 3 -0.392300 0.127500 0.000000 9 2 6 A0A0A0 5 5 -0.877200 0.794900 0.000000 9 2 6 A0A0A0 6 5 -0.392300 -1.207400 0.000000 9 2 6 A0A0A0 7 4 0.392300 -0.952500 0.000000 9 2 6 A0A0A0 8 3 0.392300 -0.127500 0.000000 9 2 6 A0A0A0 9 5 1.176900 -1.207400 0.000000 9 2 6 A0A0A0 10 5 1.661900 -0.540000 0.000000 9 2 6 A0A0A0 11 5 1.176900 0.127500 0.000000 9 2 6 A0A0A0 12 5 0.877200 0.540000 0.000000 9 2 6 A0A0A0 13 5 0.392300 1.207400 0.000000 9 2 6 A0A0A0 14 4 -0.392300 0.952500 0.000000 9 2 6 A0A0A0 15 5 0.191100 0.369100 0.000000 9 2 6 A0A0A0 16 5 -0.080300 -0.326400 0.000000 9 2 6 A0A0A0 ::: } m_bond[20] { # First column is bond index # i_m_from i_m_to i_m_order ::: 1 1 2 1 2 1 5 1 3 2 3 1 4 3 4 1 5 3 6 1 6 3 16 1 7 4 5 1 8 4 8 1 9 4 14 1 10 6 7 1 11 7 8 1 12 7 9 1 13 8 11 1 14 8 12 1 15 9 10 1 16 10 11 1 17 12 13 1 18 13 14 1 19 14 15 1 20 15 16 1 ::: } } f_m_ct { s_m_title s_m_entry_id s_m_entry_name s_m_Source_Path s_m_Source_File i_m_Source_File_Index s_m_subgroup_title s_m_subgroupid b_m_subgroup_collapsed i_m_ct_format ::: "template 22" 24 templates.23 /Users/nicola/schrodinger/coordgenlibs templates.mae 23 templates templates1 0 2 m_atom[33] { # First column is atom index # i_m_mmod_type r_m_x_coord r_m_y_coord r_m_z_coord i_m_residue_number i_m_color i_m_atomic_number s_m_color_rgb ::: 1 5 4.962100 -4.710300 0.000000 9 2 6 A0A0A0 2 5 4.962100 -6.138900 0.000000 9 2 6 A0A0A0 3 5 5.921200 -3.598100 0.000000 9 2 6 A0A0A0 4 5 3.696800 -6.944900 0.000000 9 2 6 A0A0A0 5 5 2.316900 -6.320000 0.000000 9 2 6 A0A0A0 6 5 0.936500 -6.962100 0.000000 9 2 6 A0A0A0 7 5 -0.412600 -6.371100 0.000000 9 2 6 A0A0A0 8 5 -1.938500 -6.828600 0.000000 9 2 6 A0A0A0 9 7 -3.054400 -5.860300 0.000000 9 2 6 A0A0A0 10 7 -3.398600 -4.417100 0.000000 9 2 6 A0A0A0 11 7 -5.285000 -2.489400 0.000000 9 2 6 A0A0A0 12 5 -5.193900 -0.959100 0.000000 9 2 6 A0A0A0 13 7 -4.760500 -3.865500 0.000000 9 2 6 A0A0A0 14 29 -4.285700 0.000000 0.000000 9 43 7 5757FF 15 2 -0.714300 -1.237200 0.000000 9 2 6 A0A0A0 16 7 0.000000 -2.474500 0.000000 9 2 6 A0A0A0 17 2 0.000000 0.000000 0.000000 9 2 6 A0A0A0 18 5 -2.142900 -1.237200 0.000000 9 2 6 A0A0A0 19 2 1.428600 0.000000 0.000000 9 2 6 A0A0A0 20 4 -0.714300 1.237200 0.000000 9 2 6 A0A0A0 21 2 2.142900 -1.237200 0.000000 9 2 6 A0A0A0 22 5 2.327400 1.110100 0.000000 9 2 6 A0A0A0 23 4 3.661100 0.598300 0.000000 9 2 6 A0A0A0 24 16 3.586500 -0.828400 0.000000 9 70 8 FF2F2F 25 7 1.428600 -2.474500 0.000000 9 2 6 A0A0A0 26 2 -2.857100 0.000000 0.000000 9 2 6 A0A0A0 27 2 -2.142900 1.237200 0.000000 9 2 6 A0A0A0 28 7 5.972100 -2.067500 0.000000 9 2 6 A0A0A0 29 7 5.041000 -1.200200 0.000000 9 2 6 A0A0A0 30 16 5.143000 0.126400 0.000000 9 70 8 FF2F2F 31 5 -0.272800 2.595900 0.000000 9 2 6 A0A0A0 32 5 -1.428600 3.435600 0.000000 9 2 6 A0A0A0 33 5 -2.584300 2.595900 0.000000 9 2 6 A0A0A0 ::: } m_bond[37] { # First column is bond index # i_m_from i_m_to i_m_order ::: 1 1 2 1 2 1 3 1 3 2 4 1 4 3 28 1 5 4 5 1 6 5 6 1 7 6 7 1 8 7 8 1 9 8 9 1 10 9 10 2 11 10 13 1 12 11 12 1 13 11 13 2 14 12 14 1 15 14 26 1 16 15 16 1 17 15 17 2 18 15 18 1 19 16 25 2 20 17 19 1 21 17 20 1 22 18 26 1 23 19 21 2 24 19 22 1 25 20 31 1 26 20 27 1 27 21 24 1 28 21 25 1 29 22 23 1 30 23 24 1 31 23 30 1 32 26 27 2 33 27 33 1 34 28 29 2 35 29 30 1 36 31 32 1 37 32 33 1 ::: } } f_m_ct { s_m_title s_m_entry_id s_m_entry_name s_m_Source_Path s_m_Source_File i_m_Source_File_Index s_m_subgroup_title s_m_subgroupid b_m_subgroup_collapsed i_m_ct_format ::: "template 23" 25 templates.24 /Users/nicola/schrodinger/coordgenlibs templates.mae 24 templates templates1 0 2 m_atom[22] { # First column is atom index # i_m_mmod_type r_m_x_coord r_m_y_coord r_m_z_coord i_m_residue_number i_m_color i_m_atomic_number s_m_color_rgb ::: 1 5 -0.595400 2.036900 0.000000 9 2 6 A0A0A0 2 2 0.106700 1.603600 0.000000 9 2 6 A0A0A0 3 7 0.909500 1.793700 0.000000 9 2 6 A0A0A0 4 7 -0.130100 0.813400 0.000000 9 2 6 A0A0A0 5 7 0.435900 0.213100 0.000000 9 2 6 A0A0A0 6 5 -1.276800 1.571800 0.000000 9 2 6 A0A0A0 7 16 -2.066700 1.771000 0.000000 9 70 8 FF2F2F 8 5 -2.573200 0.900600 0.000000 9 2 6 A0A0A0 9 5 -1.843400 0.201500 0.000000 9 2 6 A0A0A0 10 5 -2.041000 -0.778600 0.000000 9 2 6 A0A0A0 11 2 -1.052300 -1.065400 0.000000 9 2 6 A0A0A0 12 7 -0.491600 -0.460300 0.000000 9 2 6 A0A0A0 13 7 0.312900 -0.643200 0.000000 9 2 6 A0A0A0 14 7 -0.808800 -1.853700 0.000000 9 2 6 A0A0A0 15 7 -0.004400 -2.036900 0.000000 9 2 6 A0A0A0 16 2 0.556800 -1.431300 0.000000 9 2 6 A0A0A0 17 16 1.509000 -1.201000 0.000000 9 70 8 FF2F2F 18 2 1.238700 0.403200 0.000000 9 2 6 A0A0A0 19 2 1.475500 1.193500 0.000000 9 2 6 A0A0A0 20 4 1.917100 -0.066200 0.000000 9 2 6 A0A0A0 21 5 2.573200 0.433900 0.000000 9 2 6 A0A0A0 22 5 2.292800 1.214600 0.000000 9 2 6 A0A0A0 ::: } m_bond[25] { # First column is bond index # i_m_from i_m_to i_m_order ::: 1 1 2 1 2 1 6 1 3 2 3 2 4 2 4 1 5 3 19 1 6 4 5 2 7 5 18 1 8 6 7 1 9 7 8 1 10 8 9 1 11 9 10 1 12 10 11 1 13 11 12 2 14 11 14 1 15 12 13 1 16 13 16 2 17 14 15 2 18 15 16 1 19 16 17 1 20 17 20 1 21 18 19 2 22 18 20 1 23 19 22 1 24 20 21 1 25 21 22 1 ::: } } f_m_ct { s_m_title s_m_entry_id s_m_entry_name s_m_Source_Path s_m_Source_File i_m_Source_File_Index s_m_subgroup_title s_m_subgroupid b_m_subgroup_collapsed i_m_ct_format ::: "template 24" 26 templates.25 /Users/nicola/schrodinger/coordgenlibs templates.mae 25 templates templates1 0 2 m_atom[12] { # First column is atom index # i_m_mmod_type r_m_x_coord r_m_y_coord r_m_z_coord i_m_residue_number i_m_color i_m_atomic_number s_m_color_rgb ::: 1 5 0.667100 1.194000 0.000000 9 2 6 A0A0A0 2 5 1.372900 0.766800 0.000000 9 2 6 A0A0A0 3 5 1.627800 -0.017800 0.000000 9 2 6 A0A0A0 4 5 -0.146300 1.056000 0.000000 9 2 6 A0A0A0 5 4 -0.671700 0.420000 0.000000 9 2 6 A0A0A0 6 5 -1.456300 0.165000 0.000000 9 2 6 A0A0A0 7 5 -1.627800 -0.641900 0.000000 9 2 6 A0A0A0 8 5 -1.014700 -1.194000 0.000000 9 2 6 A0A0A0 9 26 -0.230100 -0.939000 0.000000 9 43 7 5757FF 10 5 -0.058600 -0.132100 0.000000 9 2 6 A0A0A0 11 5 0.568800 -1.144800 0.000000 9 2 6 A0A0A0 12 5 1.308000 -0.778300 0.000000 9 2 6 A0A0A0 ::: } m_bond[13] { # First column is bond index # i_m_from i_m_to i_m_order ::: 1 1 2 1 2 1 4 1 3 2 3 1 4 3 12 1 5 4 5 1 6 5 6 1 7 5 10 1 8 6 7 1 9 7 8 1 10 8 9 1 11 9 10 1 12 9 11 1 13 11 12 1 ::: } } f_m_ct { s_m_title s_m_entry_id s_m_entry_name s_m_Source_Path s_m_Source_File i_m_Source_File_Index s_m_subgroup_title s_m_subgroupid b_m_subgroup_collapsed i_m_ct_format ::: "template 25" 27 templates.26 /Users/nicola/schrodinger/coordgenlibs templates.mae 26 templates templates1 0 2 m_atom[13] { # First column is atom index # i_m_mmod_type r_m_x_coord r_m_y_coord r_m_z_coord i_m_residue_number i_m_color i_m_atomic_number s_m_color_rgb ::: 1 5 0.720600 1.025900 0.000000 9 2 6 A0A0A0 2 4 0.004100 0.617000 0.000000 9 2 6 A0A0A0 3 3 -0.000000 -0.208000 0.000000 9 2 6 A0A0A0 4 5 0.712400 -0.624100 0.000000 9 2 6 A0A0A0 5 5 1.428900 -0.215200 0.000000 9 2 6 A0A0A0 6 5 1.433000 0.609800 0.000000 9 2 6 A0A0A0 7 4 -0.708300 1.033000 0.000000 9 2 6 A0A0A0 8 5 -1.424800 0.624100 0.000000 9 2 6 A0A0A0 9 4 -1.428900 -0.200900 0.000000 9 2 6 A0A0A0 10 5 -0.716500 -0.617000 0.000000 9 2 6 A0A0A0 11 5 -0.712400 0.208000 0.000000 9 2 6 A0A0A0 12 5 -0.004100 -1.033000 0.000000 9 2 6 A0A0A0 13 4 -1.433000 -1.025900 0.000000 9 2 6 A0A0A0 ::: } m_bond[16] { # First column is bond index # i_m_from i_m_to i_m_order ::: 1 1 2 1 2 1 6 1 3 2 3 1 4 2 7 1 5 3 4 1 6 3 10 1 7 3 12 1 8 4 5 1 9 5 6 1 10 7 8 1 11 7 11 1 12 8 9 1 13 9 10 1 14 9 13 1 15 11 13 1 16 12 13 1 ::: } } f_m_ct { s_m_title s_m_entry_id s_m_entry_name s_m_Source_Path s_m_Source_File i_m_Source_File_Index s_m_subgroup_title s_m_subgroupid b_m_subgroup_collapsed i_m_ct_format ::: "template 26" 28 templates.27 /Users/nicola/schrodinger/coordgenlibs templates.mae 27 templates templates1 0 2 m_atom[31] { # First column is atom index # i_m_mmod_type r_m_x_coord r_m_y_coord r_m_z_coord i_m_residue_number i_m_color i_m_atomic_number s_m_color_rgb ::: 1 7 2.987600 -0.759300 0.000000 9 2 6 A0A0A0 2 25 3.226500 0.030300 0.000000 9 43 7 5757FF 3 7 2.549300 0.501500 0.000000 9 2 6 A0A0A0 4 25 1.891900 0.003100 0.000000 9 43 7 5757FF 5 2 2.162800 -0.776200 0.000000 9 2 6 A0A0A0 6 5 1.081600 0.158100 0.000000 9 2 6 A0A0A0 7 2 0.810700 0.937400 0.000000 9 2 6 A0A0A0 8 7 1.350100 1.561600 0.000000 9 2 6 A0A0A0 9 5 1.079200 2.340900 0.000000 9 2 6 A0A0A0 10 5 0.268900 2.495900 0.000000 9 2 6 A0A0A0 11 4 -0.270500 1.871600 0.000000 9 2 6 A0A0A0 12 5 0.000400 1.092400 0.000000 9 2 6 A0A0A0 13 16 -1.068900 2.030800 0.000000 9 70 8 FF2F2F 14 2 -1.608300 1.406600 0.000000 9 2 6 A0A0A0 15 7 -1.337400 0.627300 0.000000 9 2 6 A0A0A0 16 2 -1.876800 0.003100 0.000000 9 2 6 A0A0A0 17 2 -2.687100 0.158100 0.000000 9 2 6 A0A0A0 18 7 -2.958000 0.937400 0.000000 9 2 6 A0A0A0 19 7 -2.418600 1.561600 0.000000 9 2 6 A0A0A0 20 7 -3.226500 -0.466100 0.000000 9 2 6 A0A0A0 21 7 -2.955600 -1.245400 0.000000 9 2 6 A0A0A0 22 7 -2.145300 -1.400400 0.000000 9 2 6 A0A0A0 23 2 -1.605900 -0.776200 0.000000 9 2 6 A0A0A0 24 25 -0.795600 -0.931200 0.000000 9 43 7 5757FF 25 5 -0.524700 -1.710400 0.000000 9 2 6 A0A0A0 26 4 0.285600 -1.865500 0.000000 9 2 6 A0A0A0 27 5 0.559100 -1.087100 0.000000 9 2 6 A0A0A0 28 5 -0.065100 -0.547700 0.000000 9 2 6 A0A0A0 29 27 0.817800 -2.495900 0.000000 9 43 7 5757FF 30 5 1.597000 -2.225000 0.000000 9 2 6 A0A0A0 31 5 1.623400 -1.400400 0.000000 9 2 6 A0A0A0 ::: } m_bond[36] { # First column is bond index # i_m_from i_m_to i_m_order ::: 1 1 2 1 2 1 5 2 3 2 3 2 4 3 4 1 5 4 5 1 6 4 6 1 7 5 31 1 8 6 7 1 9 7 8 2 10 7 12 1 11 8 9 1 12 9 10 1 13 10 11 1 14 11 12 1 15 11 13 1 16 13 14 1 17 14 15 2 18 14 19 1 19 15 16 1 20 16 17 2 21 16 23 1 22 17 18 1 23 17 20 1 24 18 19 2 25 20 21 2 26 21 22 1 27 22 23 2 28 23 24 1 29 24 25 1 30 24 28 1 31 25 26 1 32 26 27 1 33 26 29 1 34 27 28 1 35 29 30 1 36 30 31 1 ::: } } f_m_ct { s_m_title s_m_entry_id s_m_entry_name s_m_Source_Path s_m_Source_File i_m_Source_File_Index s_m_subgroup_title s_m_subgroupid b_m_subgroup_collapsed i_m_ct_format ::: "template 27" 29 templates.28 /Users/nicola/schrodinger/coordgenlibs templates.mae 28 templates templates1 0 2 m_atom[24] { # First column is atom index # i_m_mmod_type r_m_x_coord r_m_y_coord r_m_z_coord i_m_residue_number i_m_color i_m_atomic_number s_m_color_rgb ::: 1 5 -1.571300 -2.185400 0.000000 9 2 6 A0A0A0 2 5 -1.571300 -1.360400 0.000000 9 2 6 A0A0A0 3 4 -0.856800 -2.597900 0.000000 9 2 6 A0A0A0 4 4 -0.142400 -2.185400 0.000000 9 2 6 A0A0A0 5 4 -0.142400 -1.360400 0.000000 9 2 6 A0A0A0 6 4 -0.856800 -0.947900 0.000000 9 2 6 A0A0A0 7 5 0.572100 -2.597900 0.000000 9 2 6 A0A0A0 8 4 1.286600 -2.185400 0.000000 9 2 6 A0A0A0 9 5 1.286600 -1.360400 0.000000 9 2 6 A0A0A0 10 4 0.572100 -0.947900 0.000000 9 2 6 A0A0A0 11 5 1.454800 -0.480400 0.000000 9 2 6 A0A0A0 12 5 2.169200 -0.892900 0.000000 9 2 6 A0A0A0 13 5 2.169200 -1.717900 0.000000 9 2 6 A0A0A0 14 5 -0.643300 -1.801000 0.000000 9 2 6 A0A0A0 15 5 -0.444300 -0.233400 0.000000 9 2 6 A0A0A0 16 5 -0.444300 0.591600 0.000000 9 2 6 A0A0A0 17 3 -1.158800 1.004100 0.000000 9 2 6 A0A0A0 18 5 -1.571300 0.289600 0.000000 9 2 6 A0A0A0 19 5 -1.571300 -0.535400 0.000000 9 2 6 A0A0A0 20 5 -0.575400 1.587500 0.000000 9 2 6 A0A0A0 21 27 -0.789000 2.384300 0.000000 9 43 7 5757FF 22 5 -1.585900 2.597900 0.000000 9 2 6 A0A0A0 23 5 -2.169200 2.014500 0.000000 9 2 6 A0A0A0 24 5 -1.955700 1.217600 0.000000 9 2 6 A0A0A0 ::: } m_bond[28] { # First column is bond index # i_m_from i_m_to i_m_order ::: 1 1 2 1 2 1 3 1 3 2 6 1 4 3 4 1 5 3 14 1 6 4 5 1 7 4 7 1 8 5 6 1 9 5 10 1 10 6 15 1 11 7 8 1 12 8 9 1 13 8 13 1 14 9 10 1 15 10 11 1 16 11 12 1 17 12 13 1 18 14 19 1 19 15 16 1 20 16 17 1 21 17 18 1 22 17 20 1 23 17 24 1 24 18 19 1 25 20 21 1 26 21 22 1 27 22 23 1 28 23 24 1 ::: } } f_m_ct { s_m_title s_m_entry_id s_m_entry_name s_m_Source_Path s_m_Source_File i_m_Source_File_Index s_m_subgroup_title s_m_subgroupid b_m_subgroup_collapsed i_m_ct_format ::: "template 28" 30 templates.29 /Users/nicola/schrodinger/coordgenlibs templates.mae 29 templates templates1 0 2 m_atom[27] { # First column is atom index # i_m_mmod_type r_m_x_coord r_m_y_coord r_m_z_coord i_m_residue_number i_m_color i_m_atomic_number s_m_color_rgb ::: 1 5 -2.500600 1.835100 0.000000 9 2 6 A0A0A0 2 5 -2.500600 1.010100 0.000000 9 2 6 A0A0A0 3 4 -1.786200 0.597600 0.000000 9 2 6 A0A0A0 4 4 -1.071700 1.010100 0.000000 9 2 6 A0A0A0 5 4 -1.071700 1.835100 0.000000 9 2 6 A0A0A0 6 5 -1.786200 2.247600 0.000000 9 2 6 A0A0A0 7 5 -0.357200 0.597600 0.000000 9 2 6 A0A0A0 8 4 0.357200 1.010100 0.000000 9 2 6 A0A0A0 9 5 0.357200 1.835100 0.000000 9 2 6 A0A0A0 10 5 -0.357200 2.247600 0.000000 9 2 6 A0A0A0 11 4 1.071700 0.597600 0.000000 9 2 6 A0A0A0 12 4 1.071700 -0.227400 0.000000 9 2 6 A0A0A0 13 4 1.786200 -0.639900 0.000000 9 2 6 A0A0A0 14 5 2.500600 -0.227400 0.000000 9 2 6 A0A0A0 15 5 2.500600 0.597600 0.000000 9 2 6 A0A0A0 16 5 1.786200 1.010100 0.000000 9 2 6 A0A0A0 17 5 0.458600 -0.779400 0.000000 9 2 6 A0A0A0 18 4 0.794200 -1.533100 0.000000 9 2 6 A0A0A0 19 5 1.614700 -1.446900 0.000000 9 2 6 A0A0A0 20 5 0.381700 -2.247600 0.000000 9 2 6 A0A0A0 21 5 -0.470800 -2.247600 0.000000 9 2 6 A0A0A0 22 4 -0.988300 -1.678000 0.000000 9 2 6 A0A0A0 23 5 -1.047700 -0.855200 0.000000 9 2 6 A0A0A0 24 4 -1.848600 -0.657300 0.000000 9 2 6 A0A0A0 25 5 -2.284300 -1.357900 0.000000 9 2 6 A0A0A0 26 5 -1.752600 -1.988800 0.000000 9 2 6 A0A0A0 27 5 -2.311500 0.025600 0.000000 9 2 6 A0A0A0 ::: } m_bond[32] { # First column is bond index # i_m_from i_m_to i_m_order ::: 1 1 2 1 2 1 6 1 3 2 3 1 4 3 4 1 5 3 27 1 6 4 5 1 7 4 7 1 8 5 6 1 9 5 10 1 10 7 8 1 11 8 9 1 12 8 11 1 13 9 10 1 14 11 12 1 15 11 16 1 16 12 13 1 17 12 17 1 18 13 14 1 19 13 19 1 20 14 15 1 21 15 16 1 22 17 18 1 23 18 19 1 24 18 20 1 25 20 21 1 26 21 22 1 27 22 23 1 28 22 26 1 29 23 24 1 30 24 25 1 31 24 27 1 32 25 26 1 ::: } } f_m_ct { s_m_title s_m_entry_id s_m_entry_name s_m_Source_Path s_m_Source_File i_m_Source_File_Index s_m_subgroup_title s_m_subgroupid b_m_subgroup_collapsed i_m_ct_format ::: "template 29" 31 templates.30 /Users/nicola/schrodinger/coordgenlibs templates.mae 30 templates templates1 0 2 m_atom[22] { # First column is atom index # i_m_mmod_type r_m_x_coord r_m_y_coord r_m_z_coord i_m_residue_number i_m_color i_m_atomic_number s_m_color_rgb ::: 1 7 -1.786200 -0.825000 0.000000 9 2 6 A0A0A0 2 7 -2.500600 -0.412500 0.000000 9 2 6 A0A0A0 3 7 -2.500600 0.412500 0.000000 9 2 6 A0A0A0 4 7 -1.786200 0.825000 0.000000 9 2 6 A0A0A0 5 2 -1.071700 0.412500 0.000000 9 2 6 A0A0A0 6 2 -1.071700 -0.412500 0.000000 9 2 6 A0A0A0 7 29 -0.357200 0.825000 0.000000 9 43 7 5757FF 8 5 -0.357200 1.650000 0.000000 9 2 6 A0A0A0 9 29 0.357200 2.062500 0.000000 9 43 7 5757FF 10 2 1.071700 1.650000 0.000000 9 2 6 A0A0A0 11 25 1.071700 0.825000 0.000000 9 43 7 5757FF 12 2 1.786200 0.412500 0.000000 9 2 6 A0A0A0 13 7 2.500600 0.825000 0.000000 9 2 6 A0A0A0 14 25 2.500600 1.650000 0.000000 9 43 7 5757FF 15 7 1.786200 2.062500 0.000000 9 2 6 A0A0A0 16 16 1.786200 -0.412500 0.000000 9 70 8 FF2F2F 17 5 2.305400 -1.053600 0.000000 9 2 6 A0A0A0 18 5 1.892900 -1.768100 0.000000 9 2 6 A0A0A0 19 5 1.071700 -1.650000 0.000000 9 2 6 A0A0A0 20 5 0.357200 -2.062500 0.000000 9 2 6 A0A0A0 21 5 -0.357200 -1.650000 0.000000 9 2 6 A0A0A0 22 16 -0.357200 -0.825000 0.000000 9 70 8 FF2F2F ::: } m_bond[24] { # First column is bond index # i_m_from i_m_to i_m_order ::: 1 1 2 2 2 1 6 1 3 2 3 1 4 3 4 2 5 4 5 1 6 5 6 2 7 5 7 1 8 6 22 1 9 7 8 1 10 8 9 1 11 9 10 1 12 10 11 2 13 10 15 1 14 11 12 1 15 12 13 2 16 12 16 1 17 13 14 1 18 14 15 2 19 16 17 1 20 17 18 1 21 18 19 1 22 19 20 1 23 20 21 1 24 21 22 1 ::: } } f_m_ct { s_m_title s_m_entry_id s_m_entry_name s_m_Source_Path s_m_Source_File i_m_Source_File_Index s_m_subgroup_title s_m_subgroupid b_m_subgroup_collapsed i_m_ct_format ::: "template 30" 32 templates.31 /Users/nicola/schrodinger/coordgenlibs templates.mae 31 templates templates1 0 2 m_atom[17] { # First column is atom index # i_m_mmod_type r_m_x_coord r_m_y_coord r_m_z_coord i_m_residue_number i_m_color i_m_atomic_number i_m_formal_charge s_m_color_rgb ::: 1 7 -0.968700 0.294000 0.000000 9 2 6 0 A0A0A0 2 7 -1.774900 0.119000 0.000000 9 2 6 0 A0A0A0 3 5 -2.026400 -0.666800 0.000000 9 2 6 0 A0A0A0 4 5 -1.471700 -1.277400 0.000000 9 2 6 0 A0A0A0 5 4 -0.665500 -1.102400 0.000000 9 2 6 0 A0A0A0 6 3 -0.414000 -0.316600 0.000000 9 2 6 0 A0A0A0 7 16 0.004100 -1.584400 0.000000 9 70 8 0 FF2F2F 8 2 0.669400 -1.096500 0.000000 9 2 6 0 A0A0A0 9 2 0.411000 -0.313000 0.000000 9 2 6 0 A0A0A0 10 2 0.960300 0.302500 0.000000 9 2 6 0 A0A0A0 11 7 1.768000 0.134500 0.000000 9 2 6 0 A0A0A0 12 7 2.026400 -0.649000 0.000000 9 2 6 0 A0A0A0 13 7 1.477100 -1.264500 0.000000 9 2 6 0 A0A0A0 14 7 0.951700 1.127400 0.000000 9 2 6 0 A0A0A0 15 36 0.374800 1.584400 0.000000 9 43 7 1 5757FF 16 5 -0.444400 1.383500 0.000000 9 2 6 0 A0A0A0 17 5 -0.644900 0.659400 0.000000 9 2 6 0 A0A0A0 ::: } m_bond[20] { # First column is bond index # i_m_from i_m_to i_m_order ::: 1 1 2 2 2 1 6 1 3 2 3 1 4 3 4 1 5 4 5 1 6 5 6 1 7 5 7 1 8 6 9 1 9 6 17 1 10 7 8 1 11 8 9 2 12 8 13 1 13 9 10 1 14 10 11 2 15 10 14 1 16 11 12 1 17 12 13 2 18 14 15 2 19 15 16 1 20 16 17 1 ::: } } f_m_ct { s_m_title s_m_entry_id s_m_entry_name s_m_Source_Path s_m_Source_File i_m_Source_File_Index s_m_subgroup_title s_m_subgroupid b_m_subgroup_collapsed i_m_ct_format ::: "template 31" 33 templates.32 /Users/nicola/schrodinger/coordgenlibs templates.mae 32 templates templates1 0 2 m_atom[36] { # First column is atom index # i_m_mmod_type r_m_x_coord r_m_y_coord r_m_z_coord i_m_residue_number i_m_color i_m_atomic_number s_m_color_rgb ::: 1 5 -1.581700 0.344600 0.000000 9 2 6 A0A0A0 2 16 -1.169200 -0.369900 0.000000 9 70 8 FF2F2F 3 5 -1.581700 -1.084300 0.000000 9 2 6 A0A0A0 4 4 -2.351900 -1.380000 0.000000 9 2 6 A0A0A0 5 26 -2.351900 -2.205000 0.000000 9 43 7 5757FF 6 5 -1.581700 -2.500600 0.000000 9 2 6 A0A0A0 7 5 -1.169200 -3.215100 0.000000 9 2 6 A0A0A0 8 5 -3.066400 -2.617500 0.000000 9 2 6 A0A0A0 9 5 -3.780800 -2.205000 0.000000 9 2 6 A0A0A0 10 5 -3.780800 -1.380000 0.000000 9 2 6 A0A0A0 11 5 -3.066400 -0.967500 0.000000 9 2 6 A0A0A0 12 5 -1.169200 1.059100 0.000000 9 2 6 A0A0A0 13 5 -1.581700 1.786200 0.000000 9 2 6 A0A0A0 14 5 -1.169200 2.500600 0.000000 9 2 6 A0A0A0 15 7 -0.344200 2.500600 0.000000 9 2 6 A0A0A0 16 7 0.068300 3.215100 0.000000 9 2 6 A0A0A0 17 5 0.893300 3.215100 0.000000 9 2 6 A0A0A0 18 5 1.305800 3.929600 0.000000 9 2 6 A0A0A0 19 5 2.130800 3.929600 0.000000 9 2 6 A0A0A0 20 5 2.543300 3.215100 0.000000 9 2 6 A0A0A0 21 5 3.368300 3.215100 0.000000 9 2 6 A0A0A0 22 5 3.780800 2.500600 0.000000 9 2 6 A0A0A0 23 7 3.368300 1.786200 0.000000 9 2 6 A0A0A0 24 7 3.780800 1.071700 0.000000 9 2 6 A0A0A0 25 7 3.368300 0.357200 0.000000 9 2 6 A0A0A0 26 7 3.780800 -0.357200 0.000000 9 2 6 A0A0A0 27 7 3.368300 -1.071700 0.000000 9 2 6 A0A0A0 28 7 2.543300 -1.071700 0.000000 9 2 6 A0A0A0 29 5 2.130800 -1.786200 0.000000 9 2 6 A0A0A0 30 5 1.305800 -1.786200 0.000000 9 2 6 A0A0A0 31 4 0.893300 -2.500600 0.000000 9 2 6 A0A0A0 32 16 0.068300 -2.500600 0.000000 9 70 8 FF2F2F 33 5 1.305800 -3.215100 0.000000 9 2 6 A0A0A0 34 5 0.893300 -3.929600 0.000000 9 2 6 A0A0A0 35 5 0.068300 -3.929600 0.000000 9 2 6 A0A0A0 36 4 -0.344200 -3.215100 0.000000 9 2 6 A0A0A0 ::: } m_bond[38] { # First column is bond index # i_m_from i_m_to i_m_order ::: 1 1 2 1 2 1 12 1 3 2 3 1 4 3 4 1 5 4 5 1 6 4 11 1 7 5 6 1 8 5 8 1 9 6 7 1 10 7 36 1 11 8 9 1 12 9 10 1 13 10 11 1 14 12 13 1 15 13 14 1 16 14 15 1 17 15 16 2 18 16 17 1 19 17 18 1 20 18 19 1 21 19 20 1 22 20 21 1 23 21 22 1 24 22 23 1 25 23 24 2 26 24 25 1 27 25 26 2 28 26 27 1 29 27 28 2 30 28 29 1 31 29 30 1 32 30 31 1 33 31 32 1 34 31 33 1 35 32 36 1 36 33 34 1 37 34 35 1 38 35 36 1 ::: } } f_m_ct { s_m_title s_m_entry_id s_m_entry_name s_m_Source_Path s_m_Source_File i_m_Source_File_Index s_m_subgroup_title s_m_subgroupid b_m_subgroup_collapsed i_m_ct_format ::: "template 32" 34 templates.33 /Users/nicola/schrodinger/coordgenlibs templates.mae 33 templates templates1 0 2 m_atom[8] { # First column is atom index # i_m_mmod_type r_m_x_coord r_m_y_coord r_m_z_coord i_m_residue_number i_m_color i_m_atomic_number s_m_color_rgb ::: 1 159 -5.738900 2.484100 0.000000 9 4 26 1E1EE1 2 49 -4.501700 3.198400 0.000000 9 13 16 E1E11E 3 159 -4.501700 4.627000 0.000000 9 4 26 1E1EE1 4 49 -5.738900 5.341300 0.000000 9 13 16 E1E11E 5 159 -6.976100 4.627000 0.000000 9 4 26 1E1EE1 6 49 -6.976100 3.198400 0.000000 9 13 16 E1E11E 7 163 -6.296900 3.863900 0.000000 9 4 26 1E1EE1 8 49 -4.863700 3.914300 0.000000 9 13 16 E1E11E ::: } m_bond[15] { # First column is bond index # i_m_from i_m_to i_m_order ::: 1 1 2 1 2 1 8 1 3 1 6 1 4 1 7 1 5 2 3 1 6 2 7 1 7 3 4 1 8 3 7 1 9 3 8 1 10 4 5 1 11 4 7 1 12 5 6 1 13 5 7 1 14 5 8 1 15 6 7 1 ::: } } f_m_ct { s_m_title s_m_entry_id s_m_entry_name s_m_Source_Path s_m_Source_File i_m_Source_File_Index s_m_subgroup_title s_m_subgroupid b_m_subgroup_collapsed i_m_ct_format ::: "template 33" 35 templates.34 /Users/nicola/schrodinger/coordgenlibs templates.mae 34 templates templates1 0 2 m_atom[16] { # First column is atom index # i_m_mmod_type r_m_x_coord r_m_y_coord r_m_z_coord i_m_residue_number i_m_color i_m_atomic_number s_m_color_rgb ::: 1 4 0.054000 -2.473800 0.000000 9 2 6 A0A0A0 2 5 1.276000 -3.213500 0.000000 9 2 6 A0A0A0 3 5 0.741100 -1.221300 0.000000 9 2 6 A0A0A0 4 27 -1.374200 -2.504900 0.000000 9 43 7 5757FF 5 5 2.684500 -2.974700 0.000000 9 2 6 A0A0A0 6 5 3.594400 -1.873400 0.000000 9 2 6 A0A0A0 7 5 3.563300 -0.445200 0.000000 9 2 6 A0A0A0 8 4 2.606200 0.615400 0.000000 9 2 6 A0A0A0 9 4 1.188600 0.792400 0.000000 9 2 6 A0A0A0 10 26 0.000000 0.000000 0.000000 9 43 7 5757FF 11 5 -1.428200 -0.031200 0.000000 9 2 6 A0A0A0 12 5 -2.115300 -1.283600 0.000000 9 2 6 A0A0A0 13 5 3.468300 1.754600 0.000000 9 2 6 A0A0A0 14 5 2.912700 3.070700 0.000000 9 2 6 A0A0A0 15 5 1.495200 3.247700 0.000000 9 2 6 A0A0A0 16 5 0.633100 2.108500 0.000000 9 2 6 A0A0A0 ::: } m_bond[18] { # First column is bond index # i_m_from i_m_to i_m_order ::: 1 1 2 1 2 1 3 1 3 1 4 1 4 2 5 1 5 3 10 1 6 4 12 1 7 5 6 1 8 6 7 1 9 7 8 1 10 8 9 1 11 8 13 1 12 9 10 1 13 9 16 1 14 10 11 1 15 11 12 1 16 13 14 1 17 14 15 1 18 15 16 1 ::: } } f_m_ct { s_m_title s_m_entry_id s_m_entry_name s_m_Source_Path s_m_Source_File i_m_Source_File_Index s_m_subgroup_title s_m_subgroupid b_m_subgroup_collapsed i_m_ct_format ::: "template 34" 36 templates.35 /Users/nicola/schrodinger/coordgenlibs templates.mae 35 templates templates1 0 2 m_atom[12] { # First column is atom index # i_m_mmod_type r_m_x_coord r_m_y_coord r_m_z_coord i_m_residue_number i_m_color i_m_atomic_number s_m_color_rgb ::: 1 4 0.395900 -0.729500 0.000000 9 2 6 A0A0A0 2 5 -0.309800 -1.156700 0.000000 9 2 6 A0A0A0 3 5 -1.123200 -1.018800 0.000000 9 2 6 A0A0A0 4 5 -1.648700 -0.382800 0.000000 9 2 6 A0A0A0 5 5 -1.630700 0.442000 0.000000 9 2 6 A0A0A0 6 5 -1.078000 1.054500 0.000000 9 2 6 A0A0A0 7 5 -0.259300 1.156700 0.000000 9 2 6 A0A0A0 8 26 0.427100 0.699100 0.000000 9 43 7 5757FF 9 5 -0.000900 -0.006200 0.000000 9 2 6 A0A0A0 10 5 1.251900 0.681100 0.000000 9 2 6 A0A0A0 11 5 1.648700 -0.042200 0.000000 9 2 6 A0A0A0 12 27 1.220700 -0.747500 0.000000 9 43 7 5757FF ::: } m_bond[13] { # First column is bond index # i_m_from i_m_to i_m_order ::: 1 1 2 1 2 1 9 1 3 1 12 1 4 2 3 1 5 3 4 1 6 4 5 1 7 5 6 1 8 6 7 1 9 7 8 1 10 8 9 1 11 8 10 1 12 10 11 1 13 11 12 1 ::: } } f_m_ct { s_m_title s_m_entry_id s_m_entry_name s_m_Source_Path s_m_Source_File i_m_Source_File_Index s_m_subgroup_title s_m_subgroupid b_m_subgroup_collapsed i_m_ct_format ::: "template 35" 37 templates.36 /Users/nicola/schrodinger/coordgenlibs templates.mae 36 templates templates1 0 2 m_atom[26] { # First column is atom index # i_m_mmod_type r_m_x_coord r_m_y_coord r_m_z_coord i_m_residue_number i_m_color i_m_atomic_number s_m_color_rgb ::: 1 5 0.199200 1.547900 0.000000 9 2 6 A0A0A0 2 16 0.706200 2.198700 0.000000 9 70 8 FF2F2F 3 5 1.520600 2.066500 0.000000 9 2 6 A0A0A0 4 2 1.795700 1.288700 0.000000 9 2 6 A0A0A0 5 2 1.330900 0.607100 0.000000 9 2 6 A0A0A0 6 3 0.526600 0.790700 0.000000 9 2 6 A0A0A0 7 7 2.618300 1.227100 0.000000 9 2 6 A0A0A0 8 7 2.976300 0.483800 0.000000 9 2 6 A0A0A0 9 7 2.511600 -0.197900 0.000000 9 2 6 A0A0A0 10 2 1.688900 -0.136200 0.000000 9 2 6 A0A0A0 11 5 1.330900 -0.879500 0.000000 9 2 6 A0A0A0 12 4 0.526600 -1.063100 0.000000 9 2 6 A0A0A0 13 5 -0.006400 -0.136200 0.000000 9 2 6 A0A0A0 14 4 -0.118400 -0.548700 0.000000 9 2 6 A0A0A0 15 4 -0.118400 0.276300 0.000000 9 2 6 A0A0A0 16 5 -0.832900 0.688800 0.000000 9 2 6 A0A0A0 17 4 -1.547400 0.276300 0.000000 9 2 6 A0A0A0 18 2 -1.547400 -0.548700 0.000000 9 2 6 A0A0A0 19 2 -0.832900 -0.961200 0.000000 9 2 6 A0A0A0 20 7 -0.832900 -1.786200 0.000000 9 2 6 A0A0A0 21 7 -1.547400 -2.198700 0.000000 9 2 6 A0A0A0 22 7 -2.261800 -1.786200 0.000000 9 2 6 A0A0A0 23 2 -2.261800 -0.961200 0.000000 9 2 6 A0A0A0 24 5 -2.976300 -0.548700 0.000000 9 2 6 A0A0A0 25 16 -2.976300 0.276300 0.000000 9 70 8 FF2F2F 26 5 -2.261800 0.688800 0.000000 9 2 6 A0A0A0 ::: } m_bond[32] { # First column is bond index # i_m_from i_m_to i_m_order ::: 1 1 2 1 2 1 6 1 3 2 3 1 4 3 4 1 5 4 5 2 6 4 7 1 7 5 6 1 8 5 10 1 9 6 13 1 10 6 15 1 11 7 8 2 12 8 9 1 13 9 10 2 14 10 11 1 15 11 12 1 16 12 13 1 17 12 14 1 18 14 15 1 19 14 19 1 20 15 16 1 21 16 17 1 22 17 18 1 23 17 26 1 24 18 19 2 25 18 23 1 26 19 20 1 27 20 21 2 28 21 22 1 29 22 23 2 30 23 24 1 31 24 25 1 32 25 26 1 ::: } } f_m_ct { s_m_title s_m_entry_id s_m_entry_name s_m_Source_Path s_m_Source_File i_m_Source_File_Index s_m_subgroup_title s_m_subgroupid b_m_subgroup_collapsed i_m_ct_format ::: "template 36" 38 templates.37 /Users/nicola/schrodinger/coordgenlibs templates.mae 37 templates templates1 0 2 m_atom[19] { # First column is atom index # i_m_mmod_type r_m_x_coord r_m_y_coord r_m_z_coord i_m_residue_number i_m_color i_m_atomic_number s_m_color_rgb ::: 1 5 -1.153600 -1.494700 0.000000 9 2 6 A0A0A0 2 5 -1.957900 -1.311100 0.000000 9 2 6 A0A0A0 3 4 -2.315900 -0.567800 0.000000 9 2 6 A0A0A0 4 5 -1.231600 -0.219500 0.000000 9 2 6 A0A0A0 5 5 -1.957900 0.175500 0.000000 9 2 6 A0A0A0 6 5 -1.153600 0.359100 0.000000 9 2 6 A0A0A0 7 4 -0.508600 -0.155300 0.000000 9 2 6 A0A0A0 8 3 -0.508600 -0.980300 0.000000 9 2 6 A0A0A0 9 3 0.205800 0.257200 0.000000 9 2 6 A0A0A0 10 4 0.920300 -0.155300 0.000000 9 2 6 A0A0A0 11 4 1.634800 0.257200 0.000000 9 2 6 A0A0A0 12 5 2.315900 -0.027000 0.000000 9 2 6 A0A0A0 13 5 1.787601 -0.327842 0.000000 9 2 6 A0A0A0 14 5 0.954927 0.369280 0.000000 9 2 6 A0A0A0 15 5 1.634800 1.082200 0.000000 9 2 6 A0A0A0 16 16 0.920300 1.494700 0.000000 9 70 8 FF2F2F 17 5 0.205800 1.082200 0.000000 9 2 6 A0A0A0 18 5 0.920300 -0.980300 0.000000 9 2 6 A0A0A0 19 5 0.205800 -1.392800 0.000000 9 2 6 A0A0A0 ::: } m_bond[23] { # First column is bond index # i_m_from i_m_to i_m_order ::: 1 1 2 1 2 1 8 1 3 2 3 1 4 3 4 1 5 3 5 1 6 4 8 1 7 5 6 1 8 6 7 1 9 7 8 1 10 7 9 1 11 8 19 1 12 9 10 1 13 9 14 1 14 9 17 1 15 10 11 1 16 10 18 1 17 11 12 1 18 11 15 1 19 12 13 1 20 13 14 1 21 15 16 1 22 16 17 1 23 18 19 1 ::: } } f_m_ct { s_m_title s_m_entry_id s_m_entry_name s_m_Source_Path s_m_Source_File i_m_Source_File_Index s_m_subgroup_title s_m_subgroupid b_m_subgroup_collapsed i_m_ct_format ::: "template 37" 39 templates.38 /Users/nicola/schrodinger/coordgenlibs templates.mae 38 templates templates1 0 2 m_atom[14] { # First column is atom index # i_m_mmod_type r_m_x_coord r_m_y_coord r_m_z_coord i_m_residue_number i_m_color i_m_atomic_number s_m_color_rgb s_m_atom_name ::: 1 27 1.428900 -0.412500 0.000000 9 43 7 5757FF "N1" 2 16 1.428900 0.412500 0.000000 9 70 8 FF2F2F "O2" 3 4 0.714500 -0.825000 0.000000 9 2 6 A0A0A0 "" 4 4 0.000000 -0.412500 0.000000 9 2 6 A0A0A0 "" 5 4 0.000000 0.412500 0.000000 9 2 6 A0A0A0 "" 6 4 0.714500 0.825000 0.000000 9 2 6 A0A0A0 "" 7 7 1.056500 0.309400 0.000000 9 2 6 A0A0A0 "C7" 8 7 1.056500 -0.309400 0.000000 9 2 6 A0A0A0 "C8" 9 4 -0.714500 0.825000 0.000000 9 2 6 A0A0A0 "" 10 25 -1.428900 0.412500 0.000000 9 43 7 5757FF "N10" 11 25 -1.428900 -0.412500 0.000000 9 43 7 5757FF "N11" 12 4 -0.714500 -0.825000 0.000000 9 2 6 A0A0A0 "" 13 5 -1.056500 -0.309400 0.000000 9 2 6 A0A0A0 "" 14 5 -1.056500 0.309400 0.000000 9 2 6 A0A0A0 "" ::: } m_bond[17] { # First column is bond index # i_m_from i_m_to i_m_order ::: 1 1 2 1 2 1 3 1 3 2 6 1 4 3 4 1 5 3 8 1 6 4 5 1 7 4 12 1 8 5 6 1 9 5 9 1 10 6 7 1 11 7 8 2 12 9 10 1 13 9 14 1 14 10 11 2 15 11 12 1 16 12 13 1 17 13 14 1 ::: } } f_m_ct { s_m_title s_m_entry_id s_m_entry_name s_m_Source_Path s_m_Source_File i_m_Source_File_Index s_m_subgroup_title s_m_subgroupid b_m_subgroup_collapsed i_m_ct_format ::: "template 38" 40 templates.39 /Users/nicola/schrodinger/coordgenlibs templates.mae 39 templates templates1 0 2 m_atom[17] { # First column is atom index # i_m_mmod_type r_m_x_coord r_m_y_coord r_m_z_coord i_m_residue_number i_m_color i_m_atomic_number s_m_color_rgb ::: 1 5 0.964500 -1.031400 0.000000 9 2 6 A0A0A0 2 5 1.771500 -0.859900 0.000000 9 2 6 A0A0A0 3 5 2.026400 -0.075300 0.000000 9 2 6 A0A0A0 4 4 1.474400 0.537800 0.000000 9 2 6 A0A0A0 5 5 0.908100 1.031400 0.000000 9 2 6 A0A0A0 6 16 0.083100 0.343900 0.000000 9 70 8 FF2F2F 7 4 0.667400 0.366300 0.000000 9 2 6 A0A0A0 8 5 -0.000000 0.851200 0.000000 9 2 6 A0A0A0 9 2 -0.667400 0.366300 0.000000 9 2 6 A0A0A0 10 3 -0.412500 -0.418300 0.000000 9 2 6 A0A0A0 11 3 0.412500 -0.418300 0.000000 9 2 6 A0A0A0 12 7 -1.474400 0.537800 0.000000 9 2 6 A0A0A0 13 4 -2.026400 -0.075300 0.000000 9 2 6 A0A0A0 14 5 -1.593200 -0.517100 0.000000 9 2 6 A0A0A0 15 5 -0.988000 -0.645700 0.000000 9 2 6 A0A0A0 16 5 -1.771500 -0.859900 0.000000 9 2 6 A0A0A0 17 5 -0.964500 -1.031400 0.000000 9 2 6 A0A0A0 ::: } m_bond[21] { # First column is bond index # i_m_from i_m_to i_m_order ::: 1 1 2 1 2 1 11 1 3 2 3 1 4 3 4 1 5 4 5 1 6 4 7 1 7 5 6 1 8 6 11 1 9 7 8 1 10 7 11 1 11 8 9 1 12 9 10 1 13 9 12 2 14 10 11 1 15 10 15 1 16 10 17 1 17 12 13 1 18 13 14 1 19 13 16 1 20 14 15 1 21 16 17 1 ::: } } f_m_ct { s_m_title s_m_entry_id s_m_entry_name s_m_Source_Path s_m_Source_File i_m_Source_File_Index s_m_subgroup_title s_m_subgroupid b_m_subgroup_collapsed i_m_ct_format ::: "template 39" 41 templates.40 /Users/nicola/schrodinger/coordgenlibs templates.mae 40 templates templates1 0 2 m_atom[16] { # First column is atom index # i_m_mmod_type r_m_x_coord r_m_y_coord r_m_z_coord i_m_residue_number i_m_color i_m_atomic_number s_m_color_rgb s_m_atom_name ::: 1 27 -0.995900 1.579200 0.000000 9 43 7 5757FF "N1" 2 5 -1.579200 0.995900 0.000000 9 2 6 A0A0A0 "" 3 3 -0.995900 0.412500 0.000000 9 2 6 A0A0A0 "" 4 3 -0.412500 0.995900 0.000000 9 2 6 A0A0A0 "" 5 5 -0.412500 -0.170900 0.000000 9 2 6 A0A0A0 "" 6 5 0.170900 0.412500 0.000000 9 2 6 A0A0A0 "" 7 5 -0.995900 -0.412500 0.000000 9 2 6 A0A0A0 "" 8 5 -0.412500 -0.995900 0.000000 9 2 6 A0A0A0 "" 9 3 0.412500 -0.995900 0.000000 9 2 6 A0A0A0 "" 10 3 0.995900 -0.412500 0.000000 9 2 6 A0A0A0 "" 11 5 0.995900 0.412500 0.000000 9 2 6 A0A0A0 "" 12 5 0.412500 0.995900 0.000000 9 2 6 A0A0A0 "" 13 5 1.102600 -0.810900 0.000000 9 2 6 A0A0A0 "" 14 5 0.510524 -1.402976 0.000000 9 2 6 A0A0A0 "" 15 27 1.579200 -0.995900 0.000000 9 43 7 5757FF "N15" 16 27 0.995900 -1.579200 0.000000 9 43 7 5757FF "N16" ::: } m_bond[20] { # First column is bond index # i_m_from i_m_to i_m_order ::: 1 1 2 1 2 1 4 1 3 2 3 1 4 3 4 1 5 3 5 1 6 3 7 1 7 4 6 1 8 4 12 1 9 5 6 1 10 7 8 1 11 8 9 1 12 9 10 1 13 9 14 1 14 9 16 1 15 10 11 1 16 10 13 1 17 10 15 1 18 11 12 1 19 13 14 1 20 15 16 1 ::: } } f_m_ct { s_m_title s_m_entry_id s_m_entry_name s_m_Source_Path s_m_Source_File i_m_Source_File_Index s_m_subgroup_title s_m_subgroupid b_m_subgroup_collapsed i_m_ct_format ::: twistane 42 templates.41 /Users/nicola/schrodinger/coordgenlibs templates.mae 41 templates templates1 0 2 m_atom[10] { # First column is atom index # i_m_mmod_type r_m_x_coord r_m_y_coord r_m_z_coord i_m_residue_number i_m_color i_m_atomic_number s_m_color_rgb ::: 1 4 0.000000 0.000000 0.000000 9 2 6 A0A0A0 2 4 1.714300 0.857100 0.000000 9 2 6 A0A0A0 3 27 -1.428600 0.428600 0.000000 9 43 7 5757FF 4 27 0.142900 -1.428600 0.000000 9 43 7 5757FF 5 5 1.571400 2.285700 0.000000 9 2 6 A0A0A0 6 5 3.142900 0.428600 0.000000 9 2 6 A0A0A0 7 5 0.142900 2.285700 0.000000 9 2 6 A0A0A0 8 4 0.000000 0.857100 0.000000 9 2 6 A0A0A0 9 4 1.714300 0.000000 0.000000 9 2 6 A0A0A0 10 5 1.571400 -1.428600 0.000000 9 2 6 A0A0A0 ::: } m_bond[12] { # First column is bond index # i_m_from i_m_to i_m_order ::: 1 1 2 1 2 1 3 1 3 1 4 1 4 2 5 1 5 2 6 1 6 3 8 1 7 4 10 1 8 5 7 1 9 6 9 1 10 7 8 1 11 8 9 1 12 9 10 1 ::: } } f_m_ct { s_m_title s_m_entry_id s_m_entry_name s_m_Source_Path s_m_Source_File i_m_Source_File_Index s_m_subgroup_title s_m_subgroupid b_m_subgroup_collapsed i_m_ct_format ::: "template 41" 43 templates.42 /Users/nicola/schrodinger/coordgenlibs templates.mae 42 templates templates1 0 2 m_atom[10] { # First column is atom index # i_m_mmod_type r_m_x_coord r_m_y_coord r_m_z_coord i_m_residue_number i_m_color i_m_atomic_number s_m_color_rgb s_m_atom_name ::: 1 27 -0.370900 2.674900 0.000000 9 43 7 5757FF "N1" 2 26 0.866300 3.103500 0.000000 9 43 7 5757FF "N2" 3 158 -0.370900 1.246300 0.000000 9 20 8 9F5F9F "3" 4 27 2.103500 2.674900 0.000000 9 43 7 5757FF "N4" 5 5 1.580600 2.152000 0.000000 9 2 6 A0A0A0 "" 6 4 2.103500 1.246300 0.000000 9 2 6 A0A0A0 "" 7 5 0.866300 0.817800 0.000000 9 2 6 A0A0A0 "" 8 5 2.817800 0.294900 0.000000 9 2 6 A0A0A0 "" 9 5 0.343400 0.294900 0.000000 9 2 6 A0A0A0 "" 10 4 1.580600 0.723400 0.000000 9 2 6 A0A0A0 "" ::: } m_bond[12] { # First column is bond index # i_m_from i_m_to i_m_order ::: 1 1 2 1 2 1 3 1 3 2 4 1 4 2 5 1 5 3 9 1 6 3 7 1 7 4 6 1 8 5 10 1 9 6 7 1 10 6 8 1 11 8 10 1 12 9 10 1 ::: } } f_m_ct { s_m_title s_m_entry_id s_m_entry_name s_m_Source_Path s_m_Source_File i_m_Source_File_Index s_m_subgroup_title s_m_subgroupid b_m_subgroup_collapsed i_m_ct_format ::: "template 42" 44 templates.43 /Users/nicola/schrodinger/coordgenlibs templates.mae 43 templates templates1 0 2 m_atom[11] { # First column is atom index # i_m_mmod_type r_m_x_coord r_m_y_coord r_m_z_coord i_m_residue_number i_m_color i_m_atomic_number s_m_color_rgb ::: 1 7 2.259400 -2.751000 0.000000 9 2 6 A0A0A0 2 7 3.230400 -1.703100 0.000000 9 2 6 A0A0A0 3 4 0.947900 -2.321500 0.000000 9 2 6 A0A0A0 4 4 0.600500 -1.146200 0.000000 9 2 6 A0A0A0 5 5 -0.515400 -2.828800 0.000000 9 2 6 A0A0A0 6 5 -1.525500 -1.818600 0.000000 9 2 6 A0A0A0 7 2 1.380300 -0.368400 0.000000 9 2 6 A0A0A0 8 2 0.000000 0.000000 0.000000 9 2 6 A0A0A0 9 5 2.157100 0.830500 0.000000 9 2 6 A0A0A0 10 5 1.257000 1.939800 0.000000 9 2 6 A0A0A0 11 5 -0.076200 1.426500 0.000000 9 2 6 A0A0A0 ::: } m_bond[13] { # First column is bond index # i_m_from i_m_to i_m_order ::: 1 1 2 2 2 1 3 1 3 2 4 1 4 3 7 1 5 3 5 1 6 4 8 1 7 4 6 1 8 5 6 1 9 7 9 1 10 7 8 2 11 8 11 1 12 9 10 1 13 10 11 1 ::: } } f_m_ct { s_m_title s_m_entry_id s_m_entry_name s_m_Source_Path s_m_Source_File i_m_Source_File_Index s_m_subgroup_title s_m_subgroupid b_m_subgroup_collapsed i_m_ct_format ::: "template 43" 45 templates.44 /Users/nicola/schrodinger/coordgenlibs templates.mae 44 templates templates1 0 2 m_atom[30] { # First column is atom index # i_m_mmod_type r_m_x_coord r_m_y_coord r_m_z_coord i_m_residue_number i_m_color i_m_atomic_number s_m_color_rgb ::: 1 2 -6.896800 -2.173600 0.000000 9 2 6 A0A0A0 2 2 -7.721800 -2.173600 0.000000 9 2 6 A0A0A0 3 7 -7.721800 -3.602600 0.000000 9 2 6 A0A0A0 4 7 -6.896800 -3.602600 0.000000 9 2 6 A0A0A0 5 2 -6.484300 -2.888100 0.000000 9 2 6 A0A0A0 6 5 -8.240900 -1.532500 0.000000 9 2 6 A0A0A0 7 4 -9.011100 -1.828100 0.000000 9 2 6 A0A0A0 8 16 -8.968000 -2.652000 0.000000 9 70 8 FF2F2F 9 2 -8.134300 -2.888100 0.000000 9 2 6 A0A0A0 10 16 -9.866900 -2.100600 0.000000 9 70 8 FF2F2F 11 5 -5.659300 -1.459100 0.000000 9 2 6 A0A0A0 12 5 -6.484300 -1.459100 0.000000 9 2 6 A0A0A0 13 7 -5.659300 -2.888100 0.000000 9 2 6 A0A0A0 14 2 -5.246800 -2.173600 0.000000 9 2 6 A0A0A0 15 29 -4.421800 -2.173600 0.000000 9 43 7 5757FF 16 5 -3.897300 -2.727500 0.000000 9 2 6 A0A0A0 17 7 -9.808000 -2.866700 0.000000 9 2 6 A0A0A0 18 7 -10.345700 -3.367600 0.000000 9 2 6 A0A0A0 19 5 -10.316300 -4.251500 0.000000 9 2 6 A0A0A0 20 5 -9.762400 -4.893800 0.000000 9 2 6 A0A0A0 21 5 -9.762400 -5.718800 0.000000 9 2 6 A0A0A0 22 5 -9.031700 -6.184300 0.000000 9 2 6 A0A0A0 23 5 -8.234800 -5.823400 0.000000 9 2 6 A0A0A0 24 5 -7.437600 -6.194200 0.000000 9 2 6 A0A0A0 25 5 -6.658500 -5.852900 0.000000 9 2 6 A0A0A0 26 5 -5.777300 -6.117100 0.000000 9 2 6 A0A0A0 27 7 -3.844700 -3.611200 0.000000 9 2 6 A0A0A0 28 7 -4.147600 -4.405900 0.000000 9 2 6 A0A0A0 29 7 -4.934100 -4.724500 0.000000 9 2 6 A0A0A0 30 7 -5.132900 -5.557900 0.000000 9 2 6 A0A0A0 ::: } m_bond[33] { # First column is bond index # i_m_from i_m_to i_m_order ::: 1 1 2 1 2 1 5 2 3 1 12 1 4 2 6 1 5 2 9 2 6 3 9 1 7 3 4 2 8 4 5 1 9 5 13 1 10 6 7 1 11 7 8 1 12 7 10 1 13 8 9 1 14 10 17 1 15 11 12 1 16 11 14 1 17 13 14 2 18 14 15 1 19 15 16 1 20 16 27 1 21 17 18 2 22 18 19 1 23 19 20 1 24 20 21 1 25 21 22 1 26 22 23 1 27 23 24 1 28 24 25 1 29 25 26 1 30 26 30 1 31 27 28 2 32 28 29 1 33 29 30 2 ::: } } f_m_ct { s_m_title s_m_entry_id s_m_entry_name s_m_Source_Path s_m_Source_File i_m_Source_File_Index s_m_subgroup_title s_m_subgroupid b_m_subgroup_collapsed i_m_ct_format ::: "template 44" 46 templates.45 /Users/nicola/schrodinger/coordgenlibs templates.mae 45 templates templates1 0 2 m_atom[17] { # First column is atom index # i_m_mmod_type r_m_x_coord r_m_y_coord r_m_z_coord i_m_residue_number i_m_color i_m_atomic_number s_m_color_rgb ::: 1 4 -0.044700 -0.793800 0.000000 9 2 6 A0A0A0 2 4 -0.044700 -1.618800 0.000000 9 2 6 A0A0A0 3 5 0.739900 -1.873700 0.000000 9 2 6 A0A0A0 4 5 1.224800 -1.206300 0.000000 9 2 6 A0A0A0 5 4 0.739900 -0.538800 0.000000 9 2 6 A0A0A0 6 4 -0.829300 -0.538800 0.000000 9 2 6 A0A0A0 7 5 -1.314300 -1.206300 0.000000 9 2 6 A0A0A0 8 5 -0.829300 -1.873700 0.000000 9 2 6 A0A0A0 9 5 -0.809300 0.245800 0.000000 9 2 6 A0A0A0 10 5 -1.428900 1.461200 0.000000 9 2 6 A0A0A0 11 5 -1.428900 0.636200 0.000000 9 2 6 A0A0A0 12 5 0.000000 1.461200 0.000000 9 2 6 A0A0A0 13 5 -0.714500 1.873700 0.000000 9 2 6 A0A0A0 14 5 0.714500 0.223700 0.000000 9 2 6 A0A0A0 15 5 1.428900 0.636200 0.000000 9 2 6 A0A0A0 16 5 1.428900 1.461200 0.000000 9 2 6 A0A0A0 17 5 0.714500 1.873700 0.000000 9 2 6 A0A0A0 ::: } m_bond[19] { # First column is bond index # i_m_from i_m_to i_m_order ::: 1 1 2 1 2 1 5 1 3 1 6 1 4 2 3 1 5 2 8 1 6 3 4 1 7 4 5 1 8 5 14 1 9 6 7 1 10 6 9 1 11 7 8 1 12 9 11 1 13 10 11 1 14 10 13 1 15 12 13 1 16 12 17 1 17 14 15 1 18 15 16 1 19 16 17 1 ::: } } f_m_ct { s_m_title s_m_entry_id s_m_entry_name s_m_Source_Path s_m_Source_File i_m_Source_File_Index s_m_subgroup_title s_m_subgroupid b_m_subgroup_collapsed i_m_ct_format ::: "template 45" 47 templates.46 /Users/nicola/schrodinger/coordgenlibs templates.mae 46 templates templates1 0 2 m_atom[42] { # First column is atom index # i_m_mmod_type r_m_x_coord r_m_y_coord r_m_z_coord i_m_residue_number i_m_color i_m_atomic_number s_m_color_rgb s_m_atom_name ::: 1 4 -2.143400 2.062500 0.000000 9 2 6 A0A0A0 "" 2 5 -1.428900 1.650000 0.000000 9 2 6 A0A0A0 "" 3 5 -0.714500 2.062500 0.000000 9 2 6 A0A0A0 "" 4 4 -0.714500 2.887500 0.000000 9 2 6 A0A0A0 "" 5 27 -1.428900 3.300000 0.000000 9 43 7 5757FF "N5" 6 27 -2.143400 2.887500 0.000000 9 43 7 5757FF "N6" 7 5 0.714500 2.062500 0.000000 9 2 6 A0A0A0 "" 8 4 0.714500 2.887500 0.000000 9 2 6 A0A0A0 "" 9 5 0.000000 3.300000 0.000000 9 2 6 A0A0A0 "" 10 5 1.428900 1.650000 0.000000 9 2 6 A0A0A0 "" 11 4 2.143400 2.062500 0.000000 9 2 6 A0A0A0 "" 12 27 2.143400 2.887500 0.000000 9 43 7 5757FF "N12" 13 27 1.428900 3.300000 0.000000 9 43 7 5757FF "N13" 14 5 -2.857900 1.650000 0.000000 9 2 6 A0A0A0 "" 15 4 -2.857900 0.825000 0.000000 9 2 6 A0A0A0 "" 16 27 -3.572400 0.412500 0.000000 9 43 7 5757FF "N16" 17 27 -3.572400 -0.412500 0.000000 9 43 7 5757FF "N17" 18 5 -2.143400 0.412500 0.000000 9 2 6 A0A0A0 "" 19 5 -2.143400 -0.412500 0.000000 9 2 6 A0A0A0 "" 20 4 -2.857900 -0.825000 0.000000 9 2 6 A0A0A0 "" 21 27 2.857900 1.650000 0.000000 9 43 7 5757FF "N21" 22 4 2.857900 0.825000 0.000000 9 2 6 A0A0A0 "" 23 5 -2.857900 -1.650000 0.000000 9 2 6 A0A0A0 "" 24 4 -2.143400 -2.062500 0.000000 9 2 6 A0A0A0 "" 25 5 -1.428900 -1.650000 0.000000 9 2 6 A0A0A0 "" 26 5 -0.714500 -2.062500 0.000000 9 2 6 A0A0A0 "" 27 4 -0.714500 -2.887500 0.000000 9 2 6 A0A0A0 "" 28 27 -1.428900 -3.300000 0.000000 9 43 7 5757FF "N28" 29 27 -2.143400 -2.887500 0.000000 9 43 7 5757FF "N29" 30 5 2.143400 0.412500 0.000000 9 2 6 A0A0A0 "" 31 5 2.143400 -0.412500 0.000000 9 2 6 A0A0A0 "" 32 4 2.857900 -0.825000 0.000000 9 2 6 A0A0A0 "" 33 27 3.572400 -0.412500 0.000000 9 43 7 5757FF "N33" 34 27 3.572400 0.412500 0.000000 9 43 7 5757FF "N34" 35 5 2.857900 -1.650000 0.000000 9 2 6 A0A0A0 "" 36 4 2.143400 -2.062500 0.000000 9 2 6 A0A0A0 "" 37 5 0.000000 -3.300000 0.000000 9 2 6 A0A0A0 "" 38 4 0.714500 -2.887500 0.000000 9 2 6 A0A0A0 "" 39 5 0.714500 -2.062500 0.000000 9 2 6 A0A0A0 "" 40 5 1.428900 -1.650000 0.000000 9 2 6 A0A0A0 "" 41 27 2.143400 -2.887500 0.000000 9 43 7 5757FF "N41" 42 27 1.428900 -3.300000 0.000000 9 43 7 5757FF "N42" ::: } m_bond[48] { # First column is bond index # i_m_from i_m_to i_m_order ::: 1 1 2 1 2 1 6 1 3 1 14 1 4 2 3 1 5 3 4 1 6 4 5 1 7 4 9 1 8 5 6 1 9 7 8 1 10 7 10 1 11 8 9 1 12 8 13 1 13 10 11 1 14 11 12 1 15 11 21 1 16 12 13 1 17 14 15 1 18 15 16 1 19 15 18 1 20 16 17 1 21 17 20 1 22 18 19 1 23 19 20 1 24 20 23 1 25 21 22 1 26 22 30 1 27 22 34 1 28 23 24 1 29 24 25 1 30 24 29 1 31 25 26 1 32 26 27 1 33 27 28 1 34 27 37 1 35 28 29 1 36 30 31 1 37 31 32 1 38 32 33 1 39 32 35 1 40 33 34 1 41 35 36 1 42 36 40 1 43 36 41 1 44 37 38 1 45 38 39 1 46 38 42 1 47 39 40 1 48 41 42 1 ::: } } f_m_ct { s_m_title s_m_entry_id s_m_entry_name s_m_Source_Path s_m_Source_File i_m_Source_File_Index s_m_subgroup_title s_m_subgroupid b_m_subgroup_collapsed i_m_ct_format ::: "template 46" 48 templates.47 /Users/nicola/schrodinger/coordgenlibs templates.mae 47 templates templates1 0 2 m_atom[20] { # First column is atom index # i_m_mmod_type r_m_x_coord r_m_y_coord r_m_z_coord i_m_residue_number i_m_color i_m_atomic_number s_m_color_rgb ::: 1 5 2.062500 -0.120700 0.000000 9 2 6 A0A0A0 2 5 1.649400 0.593500 0.000000 9 2 6 A0A0A0 3 4 1.650600 -0.835500 0.000000 9 2 6 A0A0A0 4 5 1.688500 -0.217900 0.000000 9 2 6 A0A0A0 5 5 1.378700 0.317700 0.000000 9 2 6 A0A0A0 6 4 0.825600 -0.836100 0.000000 9 2 6 A0A0A0 7 16 0.001000 -1.384000 0.000000 9 70 8 FF2F2F 8 2 -0.824400 -0.837400 0.000000 9 2 6 A0A0A0 9 7 -1.649400 -0.838000 0.000000 9 2 6 A0A0A0 10 7 -2.062500 -0.123900 0.000000 9 2 6 A0A0A0 11 7 -1.650600 0.590900 0.000000 9 2 6 A0A0A0 12 2 -0.412500 -0.122600 0.000000 9 2 6 A0A0A0 13 2 -0.825600 0.591500 0.000000 9 2 6 A0A0A0 14 5 -0.413600 1.306300 0.000000 9 2 6 A0A0A0 15 4 0.411400 1.307000 0.000000 9 2 6 A0A0A0 16 3 0.824400 0.592800 0.000000 9 2 6 A0A0A0 17 3 0.412500 -0.122000 0.000000 9 2 6 A0A0A0 18 27 1.336300 1.384000 0.000000 9 43 7 5757FF 19 5 1.822900 0.593600 0.000000 9 2 6 A0A0A0 20 5 1.337500 -0.197500 0.000000 9 2 6 A0A0A0 ::: } m_bond[25] { # First column is bond index # i_m_from i_m_to i_m_order ::: 1 1 2 1 2 1 3 1 3 2 16 1 4 3 4 1 5 3 6 1 6 4 5 1 7 5 16 1 8 6 7 1 9 6 17 1 10 7 8 1 11 8 9 2 12 8 12 1 13 9 10 1 14 10 11 2 15 11 13 1 16 12 13 2 17 12 17 1 18 13 14 1 19 14 15 1 20 15 16 1 21 15 18 1 22 16 17 1 23 17 20 1 24 18 19 1 25 19 20 1 ::: } } f_m_ct { s_m_title s_m_entry_id s_m_entry_name s_m_Source_Path s_m_Source_File i_m_Source_File_Index s_m_subgroup_title s_m_subgroupid b_m_subgroup_collapsed i_m_ct_format ::: "template 47" 49 templates.48 /Users/nicola/schrodinger/coordgenlibs templates.mae 48 templates templates1 0 2 m_atom[18] { # First column is atom index # i_m_mmod_type r_m_x_coord r_m_y_coord r_m_z_coord i_m_residue_number i_m_color i_m_atomic_number s_m_color_rgb ::: 1 5 2.062500 -0.120700 0.000000 9 2 6 A0A0A0 2 5 1.649400 0.593500 0.000000 9 2 6 A0A0A0 3 5 1.650600 -0.835500 0.000000 9 2 6 A0A0A0 4 4 0.825600 -0.836100 0.000000 9 2 6 A0A0A0 5 16 0.001000 -1.384000 0.000000 9 70 8 FF2F2F 6 2 -0.824400 -0.837400 0.000000 9 2 6 A0A0A0 7 7 -1.649400 -0.838000 0.000000 9 2 6 A0A0A0 8 7 -2.062500 -0.123900 0.000000 9 2 6 A0A0A0 9 7 -1.650600 0.590900 0.000000 9 2 6 A0A0A0 10 2 -0.412500 -0.122600 0.000000 9 2 6 A0A0A0 11 2 -0.825600 0.591500 0.000000 9 2 6 A0A0A0 12 5 -0.413600 1.306300 0.000000 9 2 6 A0A0A0 13 4 0.411400 1.307000 0.000000 9 2 6 A0A0A0 14 4 0.824400 0.592800 0.000000 9 2 6 A0A0A0 15 3 0.412500 -0.122000 0.000000 9 2 6 A0A0A0 16 27 1.336300 1.384000 0.000000 9 43 7 5757FF 17 5 1.822900 0.593600 0.000000 9 2 6 A0A0A0 18 5 1.337500 -0.197500 0.000000 9 2 6 A0A0A0 ::: } m_bond[22] { # First column is bond index # i_m_from i_m_to i_m_order ::: 1 1 2 1 2 1 3 1 3 2 14 1 4 3 4 1 5 4 5 1 6 4 15 1 7 5 6 1 8 6 7 2 9 6 10 1 10 7 8 1 11 8 9 2 12 9 11 1 13 10 11 2 14 10 15 1 15 11 12 1 16 12 13 1 17 13 14 1 18 13 16 1 19 14 15 1 20 15 18 1 21 16 17 1 22 17 18 1 ::: } } f_m_ct { s_m_title s_m_entry_id s_m_entry_name s_m_Source_Path s_m_Source_File i_m_Source_File_Index s_m_subgroup_title s_m_subgroupid b_m_subgroup_collapsed i_m_ct_format ::: "template 48" 50 templates.49 /Users/nicola/schrodinger/coordgenlibs templates.mae 49 templates templates1 0 2 m_atom[21] { # First column is atom index # i_m_mmod_type r_m_x_coord r_m_y_coord r_m_z_coord i_m_residue_number i_m_color i_m_atomic_number s_m_color_rgb ::: 1 5 -1.428900 -1.443800 0.000000 9 2 6 A0A0A0 2 5 -1.428900 -2.268700 0.000000 9 2 6 A0A0A0 3 5 -0.714500 -2.681200 0.000000 9 2 6 A0A0A0 4 5 0.000000 -2.268700 0.000000 9 2 6 A0A0A0 5 5 0.000000 -1.443800 0.000000 9 2 6 A0A0A0 6 4 -0.714500 -1.031200 0.000000 9 2 6 A0A0A0 7 5 0.714500 -2.681200 0.000000 9 2 6 A0A0A0 8 5 1.428900 -2.268700 0.000000 9 2 6 A0A0A0 9 5 1.428900 -1.443800 0.000000 9 2 6 A0A0A0 10 4 0.714500 -1.031200 0.000000 9 2 6 A0A0A0 11 5 0.714500 -0.206200 0.000000 9 2 6 A0A0A0 12 5 -0.714500 -0.206200 0.000000 9 2 6 A0A0A0 13 5 -0.714500 1.443800 0.000000 9 2 6 A0A0A0 14 5 -1.428900 1.031200 0.000000 9 2 6 A0A0A0 15 5 -1.428900 0.206200 0.000000 9 2 6 A0A0A0 16 5 1.428900 0.206200 0.000000 9 2 6 A0A0A0 17 5 1.428900 1.031200 0.000000 9 2 6 A0A0A0 18 5 0.714500 1.443800 0.000000 9 2 6 A0A0A0 19 5 0.714500 2.268700 0.000000 9 2 6 A0A0A0 20 5 0.000000 2.681200 0.000000 9 2 6 A0A0A0 21 5 -0.714500 2.268700 0.000000 9 2 6 A0A0A0 ::: } m_bond[22] { # First column is bond index # i_m_from i_m_to i_m_order ::: 1 1 2 1 2 1 6 1 3 2 3 1 4 3 4 1 5 4 7 1 6 5 6 1 7 5 10 1 8 6 12 1 9 7 8 1 10 8 9 1 11 9 10 1 12 10 11 1 13 11 16 1 14 12 15 1 15 13 14 1 16 13 21 1 17 14 15 1 18 16 17 1 19 17 18 1 20 18 19 1 21 19 20 1 22 20 21 1 ::: } } f_m_ct { s_m_title s_m_entry_id s_m_entry_name s_m_Source_Path s_m_Source_File i_m_Source_File_Index s_m_subgroup_title s_m_subgroupid b_m_subgroup_collapsed i_m_ct_format ::: "template 49" 51 templates.50 /Users/nicola/schrodinger/coordgenlibs templates.mae 50 templates templates1 0 2 m_atom[25] { # First column is atom index # i_m_mmod_type r_m_x_coord r_m_y_coord r_m_z_coord i_m_residue_number i_m_color i_m_atomic_number s_m_color_rgb ::: 1 4 1.786200 -0.825000 0.000000 9 2 6 A0A0A0 2 4 1.786200 -1.650000 0.000000 9 2 6 A0A0A0 3 5 2.500600 -2.062500 0.000000 9 2 6 A0A0A0 4 5 3.215100 -1.650000 0.000000 9 2 6 A0A0A0 5 5 3.215100 -0.825000 0.000000 9 2 6 A0A0A0 6 5 2.500600 -0.412500 0.000000 9 2 6 A0A0A0 7 5 1.071700 -2.062500 0.000000 9 2 6 A0A0A0 8 5 0.357200 -1.650000 0.000000 9 2 6 A0A0A0 9 5 -0.357200 -2.062500 0.000000 9 2 6 A0A0A0 10 5 -1.071700 -1.650000 0.000000 9 2 6 A0A0A0 11 5 -1.786200 -2.062500 0.000000 9 2 6 A0A0A0 12 4 -2.500600 -1.650000 0.000000 9 2 6 A0A0A0 13 4 -2.500600 -0.825000 0.000000 9 2 6 A0A0A0 14 5 -3.215100 -1.237500 0.000000 9 2 6 A0A0A0 15 5 -1.786200 -0.412500 0.000000 9 2 6 A0A0A0 16 5 -1.786200 0.412500 0.000000 9 2 6 A0A0A0 17 5 -1.071700 0.825000 0.000000 9 2 6 A0A0A0 18 5 -1.071700 1.650000 0.000000 9 2 6 A0A0A0 19 5 -0.357200 2.062500 0.000000 9 2 6 A0A0A0 20 4 0.357200 1.650000 0.000000 9 2 6 A0A0A0 21 5 1.181700 -0.302500 0.000000 9 2 6 A0A0A0 22 5 0.357200 0.825000 0.000000 9 2 6 A0A0A0 23 4 1.141900 0.570100 0.000000 9 2 6 A0A0A0 24 5 1.626800 1.237500 0.000000 9 2 6 A0A0A0 25 5 1.141900 1.904900 0.000000 9 2 6 A0A0A0 ::: } m_bond[28] { # First column is bond index # i_m_from i_m_to i_m_order ::: 1 1 2 1 2 1 6 1 3 1 21 1 4 2 3 1 5 2 7 1 6 3 4 1 7 4 5 1 8 5 6 1 9 7 8 1 10 8 9 1 11 9 10 1 12 10 11 1 13 11 12 1 14 12 13 1 15 12 14 1 16 13 14 1 17 13 15 1 18 15 16 1 19 16 17 1 20 17 18 1 21 18 19 1 22 19 20 1 23 20 22 1 24 20 25 1 25 21 23 1 26 22 23 1 27 23 24 1 28 24 25 1 ::: } } f_m_ct { s_m_title s_m_entry_id s_m_entry_name s_m_Source_Path s_m_Source_File i_m_Source_File_Index s_m_subgroup_title s_m_subgroupid b_m_subgroup_collapsed i_m_ct_format ::: "template 50" 52 templates.51 /Users/nicola/schrodinger/coordgenlibs templates.mae 51 templates templates1 0 2 m_atom[20] { # First column is atom index # i_m_mmod_type r_m_x_coord r_m_y_coord r_m_z_coord i_m_residue_number i_m_color i_m_atomic_number s_m_color_rgb ::: 1 5 -1.261200 -1.536700 0.000000 9 2 6 A0A0A0 2 5 -1.596700 -0.783000 0.000000 9 2 6 A0A0A0 3 3 -0.983600 -0.230900 0.000000 9 2 6 A0A0A0 4 26 -0.440700 -1.450400 0.000000 9 43 7 5757FF 5 4 -0.269100 -0.643400 0.000000 9 2 6 A0A0A0 6 4 0.445300 -0.230900 0.000000 9 2 6 A0A0A0 7 4 0.445300 0.594100 0.000000 9 2 6 A0A0A0 8 2 1.089000 1.110200 0.000000 9 2 6 A0A0A0 9 5 -0.424500 1.907700 0.000000 9 2 6 A0A0A0 10 26 -1.768200 0.849000 0.000000 9 43 7 5757FF 11 4 -0.983600 0.594100 0.000000 9 2 6 A0A0A0 12 5 -0.269100 1.006600 0.000000 9 2 6 A0A0A0 13 5 -2.253200 0.181600 0.000000 9 2 6 A0A0A0 14 5 -1.768200 -0.485900 0.000000 9 2 6 A0A0A0 15 7 1.893700 0.928500 0.000000 9 2 6 A0A0A0 16 5 2.253200 0.185900 0.000000 9 2 6 A0A0A0 17 16 1.896500 -0.558000 0.000000 9 70 8 FF2F2F 18 4 1.092400 -0.742700 0.000000 9 2 6 A0A0A0 19 5 0.995000 -1.561900 0.000000 9 2 6 A0A0A0 20 5 0.246000 -1.907700 0.000000 9 2 6 A0A0A0 ::: } m_bond[25] { # First column is bond index # i_m_from i_m_to i_m_order ::: 1 1 2 1 2 1 4 1 3 2 3 1 4 3 5 1 5 3 11 1 6 3 14 1 7 4 5 1 8 4 20 1 9 5 6 1 10 6 7 1 11 6 18 1 12 7 8 1 13 7 12 1 14 8 9 1 15 8 15 2 16 9 10 1 17 10 11 1 18 10 13 1 19 11 12 1 20 13 14 1 21 15 16 1 22 16 17 1 23 17 18 1 24 18 19 1 25 19 20 1 ::: } } f_m_ct { s_m_title s_m_entry_id s_m_entry_name s_m_Source_Path s_m_Source_File i_m_Source_File_Index s_m_subgroup_title s_m_subgroupid b_m_subgroup_collapsed i_m_ct_format ::: "template 51" 53 templates.52 /Users/nicola/schrodinger/coordgenlibs templates.mae 52 templates templates1 0 2 m_atom[36] { # First column is atom index # i_m_mmod_type r_m_x_coord r_m_y_coord r_m_z_coord i_m_residue_number i_m_color i_m_atomic_number s_m_color_rgb ::: 1 5 -3.341300 -1.428900 0.000000 9 2 6 A0A0A0 2 5 -2.516200 -1.428900 0.000000 9 2 6 A0A0A0 3 4 -2.103800 -0.714500 0.000000 9 2 6 A0A0A0 4 4 -2.516200 0.000000 0.000000 9 2 6 A0A0A0 5 4 -3.341300 0.000000 0.000000 9 2 6 A0A0A0 6 5 -3.753800 -0.714500 0.000000 9 2 6 A0A0A0 7 4 -2.103800 0.714500 0.000000 9 2 6 A0A0A0 8 5 -2.516200 1.428900 0.000000 9 2 6 A0A0A0 9 5 -3.341300 1.428900 0.000000 9 2 6 A0A0A0 10 5 -3.753800 0.714500 0.000000 9 2 6 A0A0A0 11 5 -1.691200 -1.428900 0.000000 9 2 6 A0A0A0 12 4 -0.866200 -1.428900 0.000000 9 2 6 A0A0A0 13 5 -1.691200 1.428900 0.000000 9 2 6 A0A0A0 14 4 -0.866200 1.428900 0.000000 9 2 6 A0A0A0 15 5 -0.453700 0.714500 0.000000 9 2 6 A0A0A0 16 5 0.371300 0.714500 0.000000 9 2 6 A0A0A0 17 5 0.783800 1.428900 0.000000 9 2 6 A0A0A0 18 4 0.371300 2.143400 0.000000 9 2 6 A0A0A0 19 5 -0.453700 2.143400 0.000000 9 2 6 A0A0A0 20 5 -0.453700 -2.143400 0.000000 9 2 6 A0A0A0 21 5 0.371300 -2.143400 0.000000 9 2 6 A0A0A0 22 4 0.783800 -1.428900 0.000000 9 2 6 A0A0A0 23 5 0.371300 -0.714500 0.000000 9 2 6 A0A0A0 24 5 -0.453700 -0.714500 0.000000 9 2 6 A0A0A0 25 5 1.691200 -1.428900 0.000000 9 2 6 A0A0A0 26 4 2.103800 -0.714500 0.000000 9 2 6 A0A0A0 27 5 2.516200 -1.428900 0.000000 9 2 6 A0A0A0 28 5 3.341300 -1.428900 0.000000 9 2 6 A0A0A0 29 5 3.753800 -0.714500 0.000000 9 2 6 A0A0A0 30 4 3.341300 0.000000 0.000000 9 2 6 A0A0A0 31 4 2.516200 0.000000 0.000000 9 2 6 A0A0A0 32 5 3.753800 0.714500 0.000000 9 2 6 A0A0A0 33 5 3.341300 1.428900 0.000000 9 2 6 A0A0A0 34 4 2.516200 1.428900 0.000000 9 2 6 A0A0A0 35 5 2.103800 0.714500 0.000000 9 2 6 A0A0A0 36 5 2.103800 2.143400 0.000000 9 2 6 A0A0A0 ::: } m_bond[42] { # First column is bond index # i_m_from i_m_to i_m_order ::: 1 1 2 1 2 1 6 1 3 2 3 1 4 3 4 1 5 3 11 1 6 4 5 1 7 4 7 1 8 5 6 1 9 5 10 1 10 7 8 1 11 7 13 1 12 8 9 1 13 9 10 1 14 11 12 1 15 12 20 1 16 12 24 1 17 13 14 1 18 14 15 1 19 14 19 1 20 15 16 1 21 16 17 1 22 17 18 1 23 18 19 1 24 18 36 1 25 20 21 1 26 21 22 1 27 22 23 1 28 22 25 1 29 23 24 1 30 25 26 1 31 26 27 1 32 26 31 1 33 27 28 1 34 28 29 1 35 29 30 1 36 30 31 1 37 30 32 1 38 31 35 1 39 32 33 1 40 33 34 1 41 34 35 1 42 34 36 1 ::: } } f_m_ct { s_m_title s_m_entry_id s_m_entry_name s_m_Source_Path s_m_Source_File i_m_Source_File_Index s_m_subgroup_title s_m_subgroupid b_m_subgroup_collapsed i_m_ct_format ::: "template 52" 54 templates.53 /Users/nicola/schrodinger/coordgenlibs templates.mae 53 templates templates1 0 2 m_atom[50] { # First column is atom index # i_m_mmod_type r_m_x_coord r_m_y_coord r_m_z_coord i_m_residue_number i_m_color i_m_atomic_number s_m_color_rgb ::: 1 7 -3.156200 1.769100 0.000000 9 2 6 A0A0A0 2 7 -2.441700 2.181600 0.000000 9 2 6 A0A0A0 3 2 -2.441700 3.006600 0.000000 9 2 6 A0A0A0 4 16 -1.727200 3.419100 0.000000 9 70 8 FF2F2F 5 7 -3.156200 3.419100 0.000000 9 2 6 A0A0A0 6 7 -3.870700 3.006600 0.000000 9 2 6 A0A0A0 7 2 -3.870700 2.181600 0.000000 9 2 6 A0A0A0 8 5 -4.585100 1.769100 0.000000 9 2 6 A0A0A0 9 5 -4.585100 0.944100 0.000000 9 2 6 A0A0A0 10 5 -3.870700 0.531600 0.000000 9 2 6 A0A0A0 11 27 -3.156200 0.944100 0.000000 9 43 7 5757FF 12 5 -2.441700 0.531600 0.000000 9 2 6 A0A0A0 13 5 -1.727200 0.944100 0.000000 9 2 6 A0A0A0 14 27 -1.012800 0.531600 0.000000 9 43 7 5757FF 15 4 -0.298300 0.944100 0.000000 9 2 6 A0A0A0 16 5 0.416200 0.531600 0.000000 9 2 6 A0A0A0 17 27 1.130600 0.944100 0.000000 9 43 7 5757FF 18 4 1.845100 0.531600 0.000000 9 2 6 A0A0A0 19 5 2.559600 0.944100 0.000000 9 2 6 A0A0A0 20 27 3.274100 0.531600 0.000000 9 43 7 5757FF 21 2 1.907300 -0.291100 0.000000 9 2 6 A0A0A0 22 7 2.650800 -0.648600 0.000000 9 2 6 A0A0A0 23 2 2.613900 -1.475500 0.000000 9 2 6 A0A0A0 24 7 1.916600 -1.916400 0.000000 9 2 6 A0A0A0 25 7 1.192900 -1.520300 0.000000 9 2 6 A0A0A0 26 7 1.188100 -0.695400 0.000000 9 2 6 A0A0A0 27 2 -0.298300 1.769100 0.000000 9 2 6 A0A0A0 28 7 0.416200 2.181600 0.000000 9 2 6 A0A0A0 29 7 -1.012800 2.181600 0.000000 9 2 6 A0A0A0 30 2 -1.012800 3.006600 0.000000 9 2 6 A0A0A0 31 7 -0.298300 3.419100 0.000000 9 2 6 A0A0A0 32 2 0.416200 3.006600 0.000000 9 2 6 A0A0A0 33 16 1.130600 3.419100 0.000000 9 70 8 FF2F2F 34 2 1.845100 3.006600 0.000000 9 2 6 A0A0A0 35 7 1.845100 2.181600 0.000000 9 2 6 A0A0A0 36 7 2.559600 1.769100 0.000000 9 2 6 A0A0A0 37 7 2.559600 3.419100 0.000000 9 2 6 A0A0A0 38 7 3.274100 3.006600 0.000000 9 2 6 A0A0A0 39 2 3.274100 2.181600 0.000000 9 2 6 A0A0A0 40 5 3.988500 1.769100 0.000000 9 2 6 A0A0A0 41 4 3.988500 0.944100 0.000000 9 2 6 A0A0A0 42 5 4.567000 0.323700 0.000000 9 2 6 A0A0A0 43 27 4.133800 -0.378400 0.000000 9 43 7 5757FF 44 5 4.447200 -1.141600 0.000000 9 2 6 A0A0A0 45 2 4.051300 -1.865400 0.000000 9 2 6 A0A0A0 46 2 3.239600 -2.013300 0.000000 9 2 6 A0A0A0 47 7 4.585100 -2.494400 0.000000 9 2 6 A0A0A0 48 7 4.307300 -3.271200 0.000000 9 2 6 A0A0A0 49 7 3.495700 -3.419100 0.000000 9 2 6 A0A0A0 50 7 2.961800 -2.790100 0.000000 9 2 6 A0A0A0 ::: } m_bond[57] { # First column is bond index # i_m_from i_m_to i_m_order ::: 1 1 2 2 2 1 7 1 3 2 3 1 4 3 4 1 5 3 5 2 6 4 30 1 7 5 6 1 8 6 7 2 9 7 8 1 10 8 9 1 11 9 10 1 12 10 11 1 13 11 12 1 14 12 13 1 15 13 14 1 16 14 15 1 17 15 16 1 18 15 27 1 19 16 17 1 20 17 18 1 21 18 19 1 22 18 21 1 23 19 20 1 24 20 41 1 25 21 22 2 26 21 26 1 27 22 23 1 28 23 24 2 29 23 46 1 30 24 25 1 31 25 26 2 32 27 28 2 33 27 29 1 34 28 32 1 35 29 30 2 36 30 31 1 37 31 32 2 38 32 33 1 39 33 34 1 40 34 35 2 41 34 37 1 42 35 36 1 43 36 39 2 44 37 38 2 45 38 39 1 46 39 40 1 47 40 41 1 48 41 42 1 49 42 43 1 50 43 44 1 51 44 45 1 52 45 46 2 53 45 47 1 54 46 50 1 55 47 48 2 56 48 49 1 57 49 50 2 ::: } } f_m_ct { s_m_title s_m_entry_id s_m_entry_name s_m_Source_Path s_m_Source_File i_m_Source_File_Index s_m_subgroup_title s_m_subgroupid b_m_subgroup_collapsed i_m_ct_format ::: "template 53" 55 templates.54 /Users/nicola/schrodinger/coordgenlibs templates.mae 54 templates templates1 0 2 m_atom[23] { # First column is atom index # i_m_mmod_type r_m_x_coord r_m_y_coord r_m_z_coord i_m_residue_number i_m_color i_m_atomic_number s_m_color_rgb ::: 1 4 -0.442000 -1.597300 0.000000 9 2 6 A0A0A0 2 4 0.418000 -1.600800 0.000000 9 2 6 A0A0A0 3 5 1.100100 -2.064900 0.000000 9 2 6 A0A0A0 4 5 1.752300 -1.559600 0.000000 9 2 6 A0A0A0 5 2 1.473200 -0.783200 0.000000 9 2 6 A0A0A0 6 25 0.648600 -0.808700 0.000000 9 43 7 5757FF 7 7 1.937300 -0.101100 0.000000 9 2 6 A0A0A0 8 2 1.604800 0.653900 0.000000 9 2 6 A0A0A0 9 5 2.020200 1.366700 0.000000 9 2 6 A0A0A0 10 5 1.470600 1.982000 0.000000 9 2 6 A0A0A0 11 2 0.715600 1.649500 0.000000 9 2 6 A0A0A0 12 25 0.798500 0.828700 0.000000 9 43 7 5757FF 13 7 0.002800 2.064900 0.000000 9 2 6 A0A0A0 14 2 -0.713300 1.655300 0.000000 9 2 6 A0A0A0 15 5 -1.465700 1.993900 0.000000 9 2 6 A0A0A0 16 5 -2.020200 1.383000 0.000000 9 2 6 A0A0A0 17 2 -1.610500 0.666900 0.000000 9 2 6 A0A0A0 18 25 -0.802900 0.835100 0.000000 9 43 7 5757FF 19 7 -1.949100 -0.085500 0.000000 9 2 6 A0A0A0 20 2 -1.490600 -0.771300 0.000000 9 2 6 A0A0A0 21 29 -0.666200 -0.803400 0.000000 9 43 7 5757FF 22 5 -1.775800 -1.545400 0.000000 9 2 6 A0A0A0 23 5 -1.127800 -2.055900 0.000000 9 2 6 A0A0A0 ::: } m_bond[27] { # First column is bond index # i_m_from i_m_to i_m_order ::: 1 1 2 1 2 1 21 1 3 1 23 1 4 2 3 1 5 2 6 1 6 3 4 1 7 4 5 1 8 5 6 2 9 5 7 1 10 7 8 2 11 8 9 1 12 8 12 1 13 9 10 1 14 10 11 1 15 11 12 2 16 11 13 1 17 13 14 2 18 14 15 1 19 14 18 1 20 15 16 1 21 16 17 1 22 17 18 2 23 17 19 1 24 19 20 2 25 20 21 1 26 20 22 1 27 22 23 1 ::: } } f_m_ct { s_m_title s_m_entry_id s_m_entry_name s_m_Source_Path s_m_Source_File i_m_Source_File_Index s_m_subgroup_title s_m_subgroupid b_m_subgroup_collapsed i_m_ct_format ::: "template 54" 56 templates.55 /Users/nicola/schrodinger/coordgenlibs templates.mae 55 templates templates1 0 2 m_atom[17] { # First column is atom index # i_m_mmod_type r_m_x_coord r_m_y_coord r_m_z_coord i_m_residue_number i_m_color i_m_atomic_number s_m_color_rgb s_m_atom_name ::: 1 2 0.018600 -1.456900 0.000000 9 2 6 A0A0A0 "" 2 7 0.095200 -0.635500 0.000000 9 2 6 A0A0A0 "" 3 7 -0.577900 -0.158400 0.000000 9 2 6 A0A0A0 "" 4 2 -1.327600 -0.502800 0.000000 9 2 6 A0A0A0 "" 5 25 -1.404200 -1.324200 0.000000 9 43 7 5757FF "N5" 6 25 -0.731100 -1.801300 0.000000 9 43 7 5757FF "N6" 7 16 -1.886800 0.103800 0.000000 9 70 8 FF2F2F "" 8 5 -1.641100 0.891400 0.000000 9 2 6 A0A0A0 "" 9 5 -0.836200 1.072300 0.000000 9 2 6 A0A0A0 "" 10 5 -0.432100 1.791600 0.000000 9 2 6 A0A0A0 "" 11 5 0.392900 1.801300 0.000000 9 2 6 A0A0A0 "" 12 27 0.813700 1.091700 0.000000 9 43 7 5757FF "" 13 5 1.622700 0.929600 0.000000 9 2 6 A0A0A0 "" 14 5 1.886800 0.148100 0.000000 9 2 6 A0A0A0 "" 15 27 1.342000 -0.471500 0.000000 9 43 7 5757FF "" 16 5 1.437800 -1.290900 0.000000 9 2 6 A0A0A0 "" 17 5 0.776100 -1.783600 0.000000 9 2 6 A0A0A0 "" ::: } m_bond[18] { # First column is bond index # i_m_from i_m_to i_m_order ::: 1 1 2 2 2 1 6 1 3 1 17 1 4 2 3 1 5 3 4 2 6 4 5 1 7 4 7 1 8 5 6 2 9 7 8 1 10 8 9 1 11 9 10 1 12 10 11 1 13 11 12 1 14 12 13 1 15 13 14 1 16 14 15 1 17 15 16 1 18 16 17 1 ::: } } f_m_ct { s_m_title s_m_entry_id s_m_entry_name s_m_Source_Path s_m_Source_File i_m_Source_File_Index s_m_subgroup_title s_m_subgroupid b_m_subgroup_collapsed i_m_ct_format ::: "template 55" 57 templates.56 /Users/nicola/schrodinger/coordgenlibs templates.mae 56 templates templates1 0 2 m_atom[22] { # First column is atom index # i_m_mmod_type r_m_x_coord r_m_y_coord r_m_z_coord i_m_residue_number i_m_color i_m_atomic_number s_m_color_rgb ::: 1 7 1.956700 1.600800 0.000000 9 2 6 A0A0A0 2 25 1.936000 0.667400 0.000000 9 43 7 5757FF 3 2 1.151400 0.412500 0.000000 9 2 6 A0A0A0 4 2 1.151400 -0.412500 0.000000 9 2 6 A0A0A0 5 25 2.421000 0.000000 0.000000 9 43 7 5757FF 6 7 1.936000 -0.667400 0.000000 9 2 6 A0A0A0 7 25 1.186700 2.013300 0.000000 9 43 7 5757FF 8 2 0.436900 1.650000 0.000000 9 2 6 A0A0A0 9 25 0.436900 0.825000 0.000000 9 43 7 5757FF 10 29 -0.277500 2.062500 0.000000 9 43 7 5757FF 11 2 -0.992000 1.650000 0.000000 9 2 6 A0A0A0 12 7 -0.992000 0.825000 0.000000 9 2 6 A0A0A0 13 2 -1.706500 0.412500 0.000000 9 2 6 A0A0A0 14 7 -2.421000 0.825000 0.000000 9 2 6 A0A0A0 15 7 -2.420900 1.650000 0.000000 9 2 6 A0A0A0 16 7 -1.706500 2.062500 0.000000 9 2 6 A0A0A0 17 29 -1.706500 -0.412500 0.000000 9 43 7 5757FF 18 5 -0.992000 -0.825000 0.000000 9 2 6 A0A0A0 19 5 -0.992000 -1.650000 0.000000 9 2 6 A0A0A0 20 5 -0.277500 -2.062500 0.000000 9 2 6 A0A0A0 21 5 0.436900 -1.650000 0.000000 9 2 6 A0A0A0 22 5 0.436900 -0.825000 0.000000 9 2 6 A0A0A0 ::: } m_bond[25] { # First column is bond index # i_m_from i_m_to i_m_order ::: 1 1 2 1 2 1 7 2 3 2 3 1 4 2 5 1 5 3 4 2 6 3 9 1 7 4 6 1 8 4 22 1 9 5 6 2 10 7 8 1 11 8 9 2 12 8 10 1 13 10 11 1 14 11 12 2 15 11 16 1 16 12 13 1 17 13 14 2 18 13 17 1 19 14 15 1 20 15 16 2 21 17 18 1 22 18 19 1 23 19 20 1 24 20 21 1 25 21 22 1 ::: } } f_m_ct { s_m_title s_m_entry_id s_m_entry_name s_m_Source_Path s_m_Source_File i_m_Source_File_Index s_m_subgroup_title s_m_subgroupid b_m_subgroup_collapsed i_m_ct_format ::: "template 56" 58 templates.57 /Users/nicola/schrodinger/coordgenlibs templates.mae 57 templates templates1 0 2 m_atom[18] { # First column is atom index # i_m_mmod_type r_m_x_coord r_m_y_coord r_m_z_coord i_m_residue_number i_m_color i_m_atomic_number s_m_color_rgb s_m_atom_name ::: 1 5 0.357200 2.062500 0.000000 9 2 6 A0A0A0 "" 2 5 1.071700 1.650000 0.000000 9 2 6 A0A0A0 "" 3 27 -0.357200 1.650000 0.000000 9 43 7 5757FF "" 4 5 -1.071700 2.062500 0.000000 9 2 6 A0A0A0 "" 5 5 -1.786200 1.650000 0.000000 9 2 6 A0A0A0 "" 6 27 -1.786200 0.825000 0.000000 9 43 7 5757FF "" 7 5 -1.071700 0.412500 0.000000 9 2 6 A0A0A0 "" 8 5 -1.071700 -0.412500 0.000000 9 2 6 A0A0A0 "" 9 5 -0.357200 -0.825000 0.000000 9 2 6 A0A0A0 "" 10 5 -0.357200 -1.650000 0.000000 9 2 6 A0A0A0 "" 11 5 0.357200 -2.062500 0.000000 9 2 6 A0A0A0 "" 12 16 1.071700 -1.650000 0.000000 9 70 8 FF2F2F "" 13 2 1.071700 -0.825000 0.000000 9 2 6 A0A0A0 "" 14 25 1.786200 -0.412500 0.000000 9 43 7 5757FF "N14" 15 25 1.786200 0.412500 0.000000 9 43 7 5757FF "N15" 16 2 1.071700 0.825000 0.000000 9 2 6 A0A0A0 "" 17 7 0.357200 -0.412500 0.000000 9 2 6 A0A0A0 "" 18 7 0.357200 0.412500 0.000000 9 2 6 A0A0A0 "" ::: } m_bond[19] { # First column is bond index # i_m_from i_m_to i_m_order ::: 1 1 2 1 2 1 3 1 3 2 16 1 4 3 4 1 5 4 5 1 6 5 6 1 7 6 7 1 8 7 8 1 9 8 9 1 10 9 10 1 11 10 11 1 12 11 12 1 13 12 13 1 14 13 14 2 15 13 17 1 16 14 15 1 17 15 16 2 18 16 18 1 19 17 18 2 ::: } } f_m_ct { s_m_title s_m_entry_id s_m_entry_name s_m_Source_Path s_m_Source_File i_m_Source_File_Index s_m_subgroup_title s_m_subgroupid b_m_subgroup_collapsed i_m_ct_format ::: "template 57" 59 templates.58 /Users/nicola/schrodinger/coordgenlibs templates.mae 58 templates templates1 0 2 m_atom[17] { # First column is atom index # i_m_mmod_type r_m_x_coord r_m_y_coord r_m_z_coord i_m_residue_number i_m_color i_m_atomic_number s_m_color_rgb ::: 1 5 1.080700 -0.866600 0.000000 9 2 6 A0A0A0 2 5 1.887700 -0.695100 0.000000 9 2 6 A0A0A0 3 5 2.142600 0.089500 0.000000 9 2 6 A0A0A0 4 4 1.590600 0.702600 0.000000 9 2 6 A0A0A0 5 5 0.932100 0.874800 0.000000 9 2 6 A0A0A0 6 16 0.426300 0.419300 0.000000 9 70 8 FF2F2F 7 4 0.783600 0.531100 0.000000 9 2 6 A0A0A0 8 5 0.116200 1.016000 0.000000 9 2 6 A0A0A0 9 3 0.528700 -0.253500 0.000000 9 2 6 A0A0A0 10 4 -0.296300 -0.253500 0.000000 9 2 6 A0A0A0 11 3 -0.551300 0.531100 0.000000 9 2 6 A0A0A0 12 5 -0.750800 -0.942100 0.000000 9 2 6 A0A0A0 13 5 -1.572500 -1.016000 0.000000 9 2 6 A0A0A0 14 4 -2.142600 -0.419700 0.000000 9 2 6 A0A0A0 15 5 -1.073600 -0.401900 0.000000 9 2 6 A0A0A0 16 5 -2.031900 0.397800 0.000000 9 2 6 A0A0A0 17 5 -1.323700 0.821000 0.000000 9 2 6 A0A0A0 ::: } m_bond[21] { # First column is bond index # i_m_from i_m_to i_m_order ::: 1 1 2 1 2 1 9 1 3 2 3 1 4 3 4 1 5 4 5 1 6 4 7 1 7 5 6 1 8 6 9 1 9 7 8 1 10 7 9 1 11 8 11 1 12 9 10 1 13 10 11 1 14 10 12 1 15 11 15 1 16 11 17 1 17 12 13 1 18 13 14 1 19 14 15 1 20 14 16 1 21 16 17 1 ::: } } f_m_ct { s_m_title s_m_entry_id s_m_entry_name s_m_Source_Path s_m_Source_File i_m_Source_File_Index s_m_subgroup_title s_m_subgroupid b_m_subgroup_collapsed i_m_ct_format ::: "template 58" 60 templates.59 /Users/nicola/schrodinger/coordgenlibs templates.mae 59 templates templates1 0 2 m_atom[15] { # First column is atom index # i_m_mmod_type r_m_x_coord r_m_y_coord r_m_z_coord i_m_residue_number i_m_color i_m_atomic_number s_m_color_rgb ::: 1 5 -2.063700 0.640600 0.000000 9 2 6 A0A0A0 2 5 -1.349200 1.053100 0.000000 9 2 6 A0A0A0 3 4 -2.063700 -0.184400 0.000000 9 2 6 A0A0A0 4 5 -0.830600 1.036600 0.000000 9 2 6 A0A0A0 5 4 -1.349200 -0.596900 0.000000 9 2 6 A0A0A0 6 5 -0.150000 -1.053100 0.000000 9 2 6 A0A0A0 7 4 -0.634800 -0.184400 0.000000 9 2 6 A0A0A0 8 5 0.079700 -0.596900 0.000000 9 2 6 A0A0A0 9 26 -0.634800 0.640600 0.000000 9 43 7 5757FF 10 4 0.079700 1.053100 0.000000 9 2 6 A0A0A0 11 4 0.794200 0.640600 0.000000 9 2 6 A0A0A0 12 27 1.578800 0.895500 0.000000 9 43 7 5757FF 13 5 2.063700 0.228100 0.000000 9 2 6 A0A0A0 14 5 1.578800 -0.439300 0.000000 9 2 6 A0A0A0 15 3 0.794200 -0.184400 0.000000 9 2 6 A0A0A0 ::: } m_bond[19] { # First column is bond index # i_m_from i_m_to i_m_order ::: 1 1 2 1 2 1 3 1 3 2 9 1 4 3 4 1 5 3 5 1 6 4 10 1 7 5 6 1 8 5 7 1 9 6 15 1 10 7 8 1 11 7 9 1 12 8 15 1 13 9 10 1 14 10 11 1 15 11 12 1 16 11 15 1 17 12 13 1 18 13 14 1 19 14 15 1 ::: } } f_m_ct { s_m_title s_m_entry_id s_m_entry_name s_m_Source_Path s_m_Source_File i_m_Source_File_Index s_m_subgroup_title s_m_subgroupid b_m_subgroup_collapsed i_m_ct_format ::: "template 59" 61 templates.60 /Users/nicola/schrodinger/coordgenlibs templates.mae 60 templates templates1 0 2 m_atom[16] { # First column is atom index # i_m_mmod_type r_m_x_coord r_m_y_coord r_m_z_coord i_m_residue_number i_m_color i_m_atomic_number s_m_color_rgb ::: 1 5 1.624500 -0.124300 0.000000 9 2 6 A0A0A0 2 5 1.624500 -0.949300 0.000000 9 2 6 A0A0A0 3 5 0.910000 -1.361800 0.000000 9 2 6 A0A0A0 4 4 0.195500 -0.949300 0.000000 9 2 6 A0A0A0 5 5 -0.394700 -1.525700 0.000000 9 2 6 A0A0A0 6 5 -1.212000 -1.413200 0.000000 9 2 6 A0A0A0 7 4 -1.624500 -0.698700 0.000000 9 2 6 A0A0A0 8 16 -0.930100 -0.961700 0.000000 9 70 8 FF2F2F 9 16 -0.222000 -0.738200 0.000000 9 70 8 FF2F2F 10 16 -1.313300 0.065300 0.000000 9 70 8 FF2F2F 11 4 -0.518900 0.288200 0.000000 9 2 6 A0A0A0 12 16 -0.518900 1.113200 0.000000 9 70 8 FF2F2F 13 5 0.195500 1.525700 0.000000 9 2 6 A0A0A0 14 5 0.910000 1.113200 0.000000 9 2 6 A0A0A0 15 4 0.910000 0.288200 0.000000 9 2 6 A0A0A0 16 3 0.195500 -0.124300 0.000000 9 2 6 A0A0A0 ::: } m_bond[19] { # First column is bond index # i_m_from i_m_to i_m_order ::: 1 1 2 1 2 1 15 1 3 2 3 1 4 3 4 1 5 4 5 1 6 4 16 1 7 5 6 1 8 6 7 1 9 7 8 1 10 7 10 1 11 8 9 1 12 9 16 1 13 10 11 1 14 11 12 1 15 11 16 1 16 12 13 1 17 13 14 1 18 14 15 1 19 15 16 1 ::: } } f_m_ct { s_m_title s_m_entry_id s_m_entry_name s_m_Source_Path s_m_Source_File i_m_Source_File_Index s_m_subgroup_title s_m_subgroupid b_m_subgroup_collapsed i_m_ct_format ::: "template 60" 62 templates.61 /Users/nicola/schrodinger/coordgenlibs templates.mae 61 templates templates1 0 2 m_atom[11] { # First column is atom index # i_m_mmod_type r_m_x_coord r_m_y_coord r_m_z_coord i_m_residue_number i_m_color i_m_atomic_number s_m_color_rgb ::: 1 5 -0.484900 0.540000 0.000000 9 2 6 A0A0A0 2 5 0.000000 1.207400 0.000000 9 2 6 A0A0A0 3 5 0.784600 0.952500 0.000000 9 2 6 A0A0A0 4 4 0.784600 0.127500 0.000000 9 2 6 A0A0A0 5 3 0.000000 -0.127500 0.000000 9 2 6 A0A0A0 6 7 1.269500 -0.540000 0.000000 9 2 6 A0A0A0 7 7 0.784600 -1.207400 0.000000 9 2 6 A0A0A0 8 4 0.000000 -0.952500 0.000000 9 2 6 A0A0A0 9 5 -0.784600 -1.207400 0.000000 9 2 6 A0A0A0 10 5 -1.269500 -0.540000 0.000000 9 2 6 A0A0A0 11 5 -0.784600 0.127500 0.000000 9 2 6 A0A0A0 ::: } m_bond[13] { # First column is bond index # i_m_from i_m_to i_m_order ::: 1 1 2 1 2 1 5 1 3 2 3 1 4 3 4 1 5 4 5 1 6 4 6 1 7 5 8 1 8 5 11 1 9 6 7 2 10 7 8 1 11 8 9 1 12 9 10 1 13 10 11 1 ::: } } f_m_ct { s_m_title s_m_entry_id s_m_entry_name s_m_Source_Path s_m_Source_File i_m_Source_File_Index s_m_subgroup_title s_m_subgroupid b_m_subgroup_collapsed i_m_ct_format ::: "template 61" 63 templates.62 /Users/nicola/schrodinger/coordgenlibs templates.mae 62 templates templates1 0 2 m_atom[20] { # First column is atom index # i_m_mmod_type r_m_x_coord r_m_y_coord r_m_z_coord i_m_residue_number i_m_color i_m_atomic_number s_m_color_rgb ::: 1 5 -2.156100 0.905700 0.000000 9 2 6 A0A0A0 2 4 -1.981300 0.099500 0.000000 9 2 6 A0A0A0 3 16 -1.241900 -0.266500 0.000000 9 70 8 FF2F2F 4 5 -1.648100 -0.632700 0.000000 9 2 6 A0A0A0 5 5 -1.634800 1.545100 0.000000 9 2 6 A0A0A0 6 5 -0.809800 1.536100 0.000000 9 2 6 A0A0A0 7 5 -0.302500 0.885600 0.000000 9 2 6 A0A0A0 8 3 -0.494800 0.083300 0.000000 9 2 6 A0A0A0 9 5 0.289400 0.262300 0.000000 9 2 6 A0A0A0 10 4 -0.843800 -0.641400 0.000000 9 2 6 A0A0A0 11 5 -0.494800 -1.366100 0.000000 9 2 6 A0A0A0 12 5 0.289400 -1.545100 0.000000 9 2 6 A0A0A0 13 4 0.918300 -1.043600 0.000000 9 2 6 A0A0A0 14 3 0.918300 -0.239200 0.000000 9 2 6 A0A0A0 15 5 1.683300 -1.292200 0.000000 9 2 6 A0A0A0 16 16 2.156100 -0.641400 0.000000 9 70 8 FF2F2F 17 4 1.683300 0.009300 0.000000 9 2 6 A0A0A0 18 5 1.801300 0.825900 0.000000 9 2 6 A0A0A0 19 5 1.041400 1.146900 0.000000 9 2 6 A0A0A0 20 16 0.538300 0.493000 0.000000 9 70 8 FF2F2F ::: } m_bond[24] { # First column is bond index # i_m_from i_m_to i_m_order ::: 1 1 2 1 2 1 5 1 3 2 3 1 4 2 4 1 5 3 8 1 6 4 10 1 7 5 6 1 8 6 7 1 9 7 8 1 10 8 9 1 11 8 10 1 12 9 14 1 13 10 11 1 14 11 12 1 15 12 13 1 16 13 14 1 17 13 15 1 18 14 17 1 19 14 20 1 20 15 16 1 21 16 17 1 22 17 18 1 23 18 19 1 24 19 20 1 ::: } } f_m_ct { s_m_title s_m_entry_id s_m_entry_name s_m_Source_Path s_m_Source_File i_m_Source_File_Index s_m_subgroup_title s_m_subgroupid b_m_subgroup_collapsed i_m_ct_format ::: "template 62" 64 templates.63 /Users/nicola/schrodinger/coordgenlibs templates.mae 63 templates templates1 0 2 m_atom[18] { # First column is atom index # i_m_mmod_type r_m_x_coord r_m_y_coord r_m_z_coord i_m_residue_number i_m_color i_m_atomic_number s_m_color_rgb ::: 1 5 -1.617400 -1.311100 0.000000 9 2 6 A0A0A0 2 5 -0.813100 -1.494700 0.000000 9 2 6 A0A0A0 3 4 -1.975300 -0.567800 0.000000 9 2 6 A0A0A0 4 5 -1.190300 -1.293700 0.000000 9 2 6 A0A0A0 5 5 -1.617400 0.175500 0.000000 9 2 6 A0A0A0 6 5 -0.813100 0.359100 0.000000 9 2 6 A0A0A0 7 4 -0.168100 -0.155300 0.000000 9 2 6 A0A0A0 8 3 0.546400 0.257200 0.000000 9 2 6 A0A0A0 9 5 0.888400 -0.258400 0.000000 9 2 6 A0A0A0 10 16 0.888400 -0.877200 0.000000 9 70 8 FF2F2F 11 4 1.260900 -0.155300 0.000000 9 2 6 A0A0A0 12 5 1.260900 -0.980300 0.000000 9 2 6 A0A0A0 13 4 0.546400 -1.392800 0.000000 9 2 6 A0A0A0 14 3 -0.168100 -0.980300 0.000000 9 2 6 A0A0A0 15 5 0.546400 1.082200 0.000000 9 2 6 A0A0A0 16 5 1.260900 1.494700 0.000000 9 2 6 A0A0A0 17 5 1.975300 1.082200 0.000000 9 2 6 A0A0A0 18 5 1.975300 0.257200 0.000000 9 2 6 A0A0A0 ::: } m_bond[22] { # First column is bond index # i_m_from i_m_to i_m_order ::: 1 1 2 1 2 1 3 1 3 2 14 1 4 3 4 1 5 3 5 1 6 4 14 1 7 5 6 1 8 6 7 1 9 7 8 1 10 7 14 1 11 8 9 1 12 8 11 1 13 8 15 1 14 9 10 1 15 10 13 1 16 11 12 1 17 11 18 1 18 12 13 1 19 13 14 1 20 15 16 1 21 16 17 1 22 17 18 1 ::: } } f_m_ct { s_m_title s_m_entry_id s_m_entry_name s_m_Source_Path s_m_Source_File i_m_Source_File_Index s_m_subgroup_title s_m_subgroupid b_m_subgroup_collapsed i_m_ct_format ::: "template 63" 65 templates.64 /Users/nicola/schrodinger/coordgenlibs templates.mae 64 templates templates1 0 2 m_atom[23] { # First column is atom index # i_m_mmod_type r_m_x_coord r_m_y_coord r_m_z_coord i_m_residue_number i_m_color i_m_atomic_number s_m_color_rgb ::: 1 5 -1.071700 2.268700 0.000000 9 2 6 A0A0A0 2 7 -1.786200 1.856200 0.000000 9 2 6 A0A0A0 3 7 -1.786200 1.031200 0.000000 9 2 6 A0A0A0 4 5 -1.071700 0.618700 0.000000 9 2 6 A0A0A0 5 3 -0.357200 1.031200 0.000000 9 2 6 A0A0A0 6 3 -0.357200 1.856200 0.000000 9 2 6 A0A0A0 7 16 0.357200 1.443700 0.000000 9 70 8 FF2F2F 8 3 0.357200 0.618700 0.000000 9 2 6 A0A0A0 9 7 1.071700 1.031200 0.000000 9 2 6 A0A0A0 10 7 1.071700 1.856200 0.000000 9 2 6 A0A0A0 11 5 0.357200 2.268700 0.000000 9 2 6 A0A0A0 12 16 -0.357200 0.206300 0.000000 9 70 8 FF2F2F 13 2 -0.357200 -0.618700 0.000000 9 2 6 A0A0A0 14 2 0.357200 -1.031200 0.000000 9 2 6 A0A0A0 15 2 0.357200 -1.856200 0.000000 9 2 6 A0A0A0 16 7 -0.357200 -2.268700 0.000000 9 2 6 A0A0A0 17 7 -1.071700 -1.856200 0.000000 9 2 6 A0A0A0 18 7 -1.071700 -1.031200 0.000000 9 2 6 A0A0A0 19 7 1.071700 -2.268700 0.000000 9 2 6 A0A0A0 20 7 1.786200 -1.856200 0.000000 9 2 6 A0A0A0 21 7 1.786200 -1.031200 0.000000 9 2 6 A0A0A0 22 2 1.071700 -0.618700 0.000000 9 2 6 A0A0A0 23 16 1.071700 0.206300 0.000000 9 70 8 FF2F2F ::: } m_bond[28] { # First column is bond index # i_m_from i_m_to i_m_order ::: 1 1 2 1 2 1 6 1 3 2 3 2 4 3 4 1 5 4 5 1 6 5 6 1 7 5 7 1 8 5 8 1 9 6 7 1 10 6 11 1 11 8 9 1 12 8 12 1 13 8 23 1 14 9 10 2 15 10 11 1 16 12 13 1 17 13 14 2 18 13 18 1 19 14 15 1 20 14 22 1 21 15 16 2 22 15 19 1 23 16 17 1 24 17 18 2 25 19 20 2 26 20 21 1 27 21 22 2 28 22 23 1 ::: } } f_m_ct { s_m_title s_m_entry_id s_m_entry_name s_m_Source_Path s_m_Source_File i_m_Source_File_Index s_m_subgroup_title s_m_subgroupid b_m_subgroup_collapsed i_m_ct_format ::: 2D_paracyclophane 66 templates.65 /Users/nicola/schrodinger/coordgenlibs templates.mae 65 templates templates1 0 2 m_atom[16] { # First column is atom index # i_m_mmod_type r_m_x_coord r_m_y_coord r_m_z_coord i_m_residue_number i_m_color i_m_atomic_number s_m_color_rgb s_m_atom_name ::: 1 2 -3.250200 0.093400 0.000000 9 2 6 A0A0A0 C1 2 7 -2.013100 0.807700 0.000000 9 2 6 A0A0A0 C2 3 7 -2.013100 2.236300 0.000000 9 2 6 A0A0A0 C3 4 2 -3.250200 2.950600 0.000000 9 2 6 A0A0A0 C4 5 154 -4.487400 2.236300 0.000000 9 20 8 9F5F9F 5 6 25 -4.487400 0.807700 0.000000 9 43 7 5757FF N6 7 5 -2.542900 4.180000 0.000000 9 2 6 A0A0A0 C7 8 5 -2.542900 -1.151500 0.000000 9 2 6 A0A0A0 C8 9 2 1.566300 0.093400 0.000000 9 2 6 A0A0A0 C9 10 25 2.803400 0.807700 0.000000 9 43 7 5757FF N10 11 154 2.803400 2.236300 0.000000 9 20 8 9F5F9F 11 12 2 1.566300 2.950600 0.000000 9 2 6 A0A0A0 C12 13 7 0.329100 2.236300 0.000000 9 2 6 A0A0A0 C13 14 7 0.329100 0.807700 0.000000 9 2 6 A0A0A0 C14 15 5 0.857100 4.180000 0.000000 9 2 6 A0A0A0 C15 16 5 0.857100 -1.151500 0.000000 9 2 6 A0A0A0 C16 ::: } m_bond[18] { # First column is bond index # i_m_from i_m_to i_m_order ::: 1 1 2 1 2 1 8 1 3 1 6 2 4 2 3 2 5 3 4 1 6 4 5 2 7 4 7 1 8 5 6 1 9 7 15 1 10 8 16 1 11 9 10 1 12 9 16 1 13 9 14 2 14 10 11 2 15 11 12 1 16 12 13 2 17 12 15 1 18 13 14 1 ::: } } f_m_ct { s_m_title s_m_entry_id s_m_entry_name s_m_Source_Path s_m_Source_File i_m_Source_File_Index s_m_subgroup_title s_m_subgroupid b_m_subgroup_collapsed i_m_ct_format ::: "template 65" 67 templates.66 /Users/nicola/schrodinger/coordgenlibs templates.mae 66 templates templates1 0 2 m_atom[25] { # First column is atom index # i_m_mmod_type r_m_x_coord r_m_y_coord r_m_z_coord i_m_residue_number i_m_color i_m_atomic_number s_m_color_rgb ::: 1 7 1.452100 1.452100 0.000000 9 2 6 A0A0A0 2 2 1.707000 0.667400 0.000000 9 2 6 A0A0A0 3 2 0.667400 1.707000 0.000000 9 2 6 A0A0A0 4 25 -0.000000 1.222100 0.000000 9 43 7 5757FF 5 2 -0.667400 1.707000 0.000000 9 2 6 A0A0A0 6 7 -0.412500 2.491600 0.000000 9 2 6 A0A0A0 7 7 0.412500 2.491600 0.000000 9 2 6 A0A0A0 8 7 -1.452100 1.452100 0.000000 9 2 6 A0A0A0 9 2 -1.707000 0.667400 0.000000 9 2 6 A0A0A0 10 25 -1.222100 0.000000 0.000000 9 43 7 5757FF 11 2 -1.707000 -0.667400 0.000000 9 2 6 A0A0A0 12 7 -2.491600 -0.412500 0.000000 9 2 6 A0A0A0 13 7 -2.491600 0.412500 0.000000 9 2 6 A0A0A0 14 7 -1.452100 -1.452100 0.000000 9 2 6 A0A0A0 15 2 -0.667400 -1.707000 0.000000 9 2 6 A0A0A0 16 25 -0.000000 -1.222100 0.000000 9 43 7 5757FF 17 161 -0.006300 0.020800 0.000000 9 4 28 1E1EE1 18 2 0.667400 -1.707000 0.000000 9 2 6 A0A0A0 19 7 0.412500 -2.491600 0.000000 9 2 6 A0A0A0 20 7 -0.412500 -2.491600 0.000000 9 2 6 A0A0A0 21 7 1.452100 -1.452100 0.000000 9 2 6 A0A0A0 22 2 1.707000 -0.667400 0.000000 9 2 6 A0A0A0 23 25 1.222100 0.000000 0.000000 9 43 7 5757FF 24 7 2.491600 -0.412500 0.000000 9 2 6 A0A0A0 25 7 2.491600 0.412500 0.000000 9 2 6 A0A0A0 ::: } m_bond[32] { # First column is bond index # i_m_from i_m_to i_m_order ::: 1 1 2 2 2 1 3 1 3 2 23 1 4 2 25 1 5 3 4 1 6 3 7 2 7 4 5 1 8 4 17 1 9 5 6 2 10 5 8 1 11 6 7 1 12 8 9 2 13 9 10 1 14 9 13 1 15 10 11 1 16 10 17 1 17 11 12 1 18 11 14 2 19 12 13 2 20 14 15 1 21 15 16 1 22 15 20 2 23 16 17 1 24 16 18 1 25 17 23 1 26 18 19 2 27 18 21 1 28 19 20 1 29 21 22 2 30 22 23 1 31 22 24 1 32 24 25 2 ::: } } f_m_ct { s_m_title s_m_entry_id s_m_entry_name s_m_Source_Path s_m_Source_File i_m_Source_File_Index s_m_subgroup_title s_m_subgroupid b_m_subgroup_collapsed i_m_ct_format ::: "template 66" 68 templates.67 /Users/nicola/schrodinger/coordgenlibs templates.mae 67 templates templates1 0 2 m_atom[25] { # First column is atom index # i_m_mmod_type r_m_x_coord r_m_y_coord r_m_z_coord i_m_residue_number i_m_color i_m_atomic_number s_m_color_rgb ::: 1 7 1.452100 1.452100 0.000000 9 2 6 A0A0A0 2 2 1.707000 0.667400 0.000000 9 2 6 A0A0A0 3 2 0.667400 1.707000 0.000000 9 2 6 A0A0A0 4 25 -0.000000 1.222100 0.000000 9 43 7 5757FF 5 2 -0.667400 1.707000 0.000000 9 2 6 A0A0A0 6 7 -0.412500 2.491600 0.000000 9 2 6 A0A0A0 7 5 0.412500 2.491600 0.000000 9 2 6 A0A0A0 8 7 -1.452100 1.452100 0.000000 9 2 6 A0A0A0 9 2 -1.707000 0.667400 0.000000 9 2 6 A0A0A0 10 25 -1.222100 0.000000 0.000000 9 43 7 5757FF 11 2 -1.707000 -0.667400 0.000000 9 2 6 A0A0A0 12 7 -2.491600 -0.412500 0.000000 9 2 6 A0A0A0 13 7 -2.491600 0.412500 0.000000 9 2 6 A0A0A0 14 7 -1.452100 -1.452100 0.000000 9 2 6 A0A0A0 15 2 -0.667400 -1.707000 0.000000 9 2 6 A0A0A0 16 25 -0.000000 -1.222100 0.000000 9 43 7 5757FF 17 153 -0.006300 0.020800 0.000000 9 4 28 1E1EE1 18 2 0.667400 -1.707000 0.000000 9 2 6 A0A0A0 19 7 0.412500 -2.491600 0.000000 9 2 6 A0A0A0 20 5 -0.412500 -2.491600 0.000000 9 2 6 A0A0A0 21 7 1.452100 -1.452100 0.000000 9 2 6 A0A0A0 22 2 1.707000 -0.667400 0.000000 9 2 6 A0A0A0 23 25 1.222100 0.000000 0.000000 9 43 7 5757FF 24 7 2.491600 -0.412500 0.000000 9 2 6 A0A0A0 25 7 2.491600 0.412500 0.000000 9 2 6 A0A0A0 ::: } m_bond[30] { # First column is bond index # i_m_from i_m_to i_m_order ::: 1 1 2 2 2 1 3 1 3 2 23 1 4 2 25 1 5 3 4 2 6 3 7 1 7 4 5 1 8 5 6 2 9 5 8 1 10 6 7 1 11 8 9 2 12 9 10 1 13 9 13 1 14 10 11 1 15 10 17 1 16 11 12 1 17 11 14 2 18 12 13 2 19 14 15 1 20 15 16 2 21 15 20 1 22 16 18 1 23 17 23 1 24 18 19 2 25 18 21 1 26 19 20 1 27 21 22 2 28 22 23 1 29 22 24 1 30 24 25 2 ::: } } f_m_ct { s_m_title s_m_entry_id s_m_entry_name s_m_Source_Path s_m_Source_File i_m_Source_File_Index s_m_subgroup_title s_m_subgroupid b_m_subgroup_collapsed i_m_ct_format ::: "template 67" 69 templates.68 /Users/nicola/schrodinger/coordgenlibs templates.mae 68 templates templates1 0 2 m_atom[24] { # First column is atom index # i_m_mmod_type r_m_x_coord r_m_y_coord r_m_z_coord i_m_residue_number i_m_color i_m_atomic_number s_m_color_rgb ::: 1 7 1.452100 1.452100 0.000000 9 2 6 A0A0A0 2 2 1.707000 0.667400 0.000000 9 2 6 A0A0A0 3 2 0.667400 1.707000 0.000000 9 2 6 A0A0A0 4 25 -0.000000 1.222100 0.000000 9 43 7 5757FF 5 2 -0.667400 1.707000 0.000000 9 2 6 A0A0A0 6 7 -0.412500 2.491600 0.000000 9 2 6 A0A0A0 7 5 0.412500 2.491600 0.000000 9 2 6 A0A0A0 8 7 -1.452100 1.452100 0.000000 9 2 6 A0A0A0 9 2 -1.707000 0.667400 0.000000 9 2 6 A0A0A0 10 29 -1.222100 0.000000 0.000000 9 43 7 5757FF 11 2 -1.707000 -0.667400 0.000000 9 2 6 A0A0A0 12 7 -2.491600 -0.412500 0.000000 9 2 6 A0A0A0 13 7 -2.491600 0.412500 0.000000 9 2 6 A0A0A0 14 7 -1.452100 -1.452100 0.000000 9 2 6 A0A0A0 15 2 -0.667400 -1.707000 0.000000 9 2 6 A0A0A0 16 25 -0.000000 -1.222100 0.000000 9 43 7 5757FF 17 2 0.667400 -1.707000 0.000000 9 2 6 A0A0A0 18 7 0.412500 -2.491600 0.000000 9 2 6 A0A0A0 19 5 -0.412500 -2.491600 0.000000 9 2 6 A0A0A0 20 7 1.452100 -1.452100 0.000000 9 2 6 A0A0A0 21 2 1.707000 -0.667400 0.000000 9 2 6 A0A0A0 22 29 1.222100 0.000000 0.000000 9 43 7 5757FF 23 7 2.491600 -0.412500 0.000000 9 2 6 A0A0A0 24 7 2.491600 0.412500 0.000000 9 2 6 A0A0A0 ::: } m_bond[28] { # First column is bond index # i_m_from i_m_to i_m_order ::: 1 1 2 2 2 1 3 1 3 2 22 1 4 2 24 1 5 3 4 2 6 3 7 1 7 4 5 1 8 5 6 2 9 5 8 1 10 6 7 1 11 8 9 2 12 9 10 1 13 9 13 1 14 10 11 1 15 11 12 1 16 11 14 2 17 12 13 2 18 14 15 1 19 15 16 2 20 15 19 1 21 16 17 1 22 17 18 2 23 17 20 1 24 18 19 1 25 20 21 2 26 21 22 1 27 21 23 1 28 23 24 2 ::: } } f_m_ct { s_m_title s_m_entry_id s_m_entry_name s_m_Source_Path s_m_Source_File i_m_Source_File_Index s_m_subgroup_title s_m_subgroupid b_m_subgroup_collapsed i_m_ct_format ::: "template 68" 70 templates.69 /Users/nicola/schrodinger/coordgenlibs templates.mae 69 templates templates1 0 2 m_atom[19] { # First column is atom index # i_m_mmod_type r_m_x_coord r_m_y_coord r_m_z_coord i_m_residue_number i_m_color i_m_atomic_number s_m_color_rgb ::: 1 27 0.919100 1.443800 0.000000 9 43 7 5757FF 2 27 0.204600 1.031200 0.000000 9 43 7 5757FF 3 27 1.633600 1.031200 0.000000 9 43 7 5757FF 4 4 1.633600 0.206200 0.000000 9 2 6 A0A0A0 5 5 1.938800 -0.442800 0.000000 9 2 6 A0A0A0 6 5 1.388800 -0.965300 0.000000 9 2 6 A0A0A0 7 5 0.481300 -0.552800 0.000000 9 2 6 A0A0A0 8 4 0.919100 -0.206200 0.000000 9 2 6 A0A0A0 9 3 0.204600 0.206200 0.000000 9 2 6 A0A0A0 10 5 0.919100 -1.031200 0.000000 9 2 6 A0A0A0 11 5 0.204600 -1.443800 0.000000 9 2 6 A0A0A0 12 3 -0.509800 -1.031200 0.000000 9 2 6 A0A0A0 13 4 -0.509800 -0.206200 0.000000 9 2 6 A0A0A0 14 5 -1.224300 0.206200 0.000000 9 2 6 A0A0A0 15 4 -1.938800 -0.206200 0.000000 9 2 6 A0A0A0 16 5 -1.663200 -0.760300 0.000000 9 2 6 A0A0A0 17 5 -1.127400 -1.069600 0.000000 9 2 6 A0A0A0 18 27 -1.938800 -1.031200 0.000000 9 43 7 5757FF 19 27 -1.224300 -1.443800 0.000000 9 43 7 5757FF ::: } m_bond[23] { # First column is bond index # i_m_from i_m_to i_m_order ::: 1 1 2 1 2 1 3 1 3 2 9 1 4 3 4 1 5 4 5 1 6 4 8 1 7 5 6 1 8 6 7 1 9 7 9 1 10 8 9 1 11 8 10 1 12 9 13 1 13 10 11 1 14 11 12 1 15 12 13 1 16 12 17 1 17 12 19 1 18 13 14 1 19 14 15 1 20 15 16 1 21 15 18 1 22 16 17 1 23 18 19 1 ::: } } f_m_ct { s_m_title s_m_entry_id s_m_entry_name s_m_Source_Path s_m_Source_File i_m_Source_File_Index s_m_subgroup_title s_m_subgroupid b_m_subgroup_collapsed i_m_ct_format ::: "template 69" 71 templates.70 /Users/nicola/schrodinger/coordgenlibs templates.mae 70 templates templates1 0 2 m_atom[20] { # First column is atom index # i_m_mmod_type r_m_x_coord r_m_y_coord r_m_z_coord i_m_residue_number i_m_color i_m_atomic_number s_m_color_rgb ::: 1 5 0.577300 0.918600 0.000000 9 2 6 A0A0A0 2 16 0.135700 0.221700 0.000000 9 70 8 FF2F2F 3 5 -0.674300 0.378200 0.000000 9 2 6 A0A0A0 4 5 -1.301600 -0.157600 0.000000 9 2 6 A0A0A0 5 5 -2.029600 0.230700 0.000000 9 2 6 A0A0A0 6 5 -2.729800 -0.205600 0.000000 9 2 6 A0A0A0 7 16 -2.702000 -1.030200 0.000000 9 70 8 FF2F2F 8 5 -1.974100 -1.418400 0.000000 9 2 6 A0A0A0 9 5 -1.273900 -0.982100 0.000000 9 2 6 A0A0A0 10 5 -0.612000 -1.474500 0.000000 9 2 6 A0A0A0 11 5 0.185700 -1.264000 0.000000 9 2 6 A0A0A0 12 16 0.518500 -0.509100 0.000000 9 70 8 FF2F2F 13 4 1.342800 -0.543100 0.000000 9 2 6 A0A0A0 14 5 2.042900 -0.979400 0.000000 9 2 6 A0A0A0 15 5 2.729800 -0.522400 0.000000 9 2 6 A0A0A0 16 4 2.597700 0.292000 0.000000 9 2 6 A0A0A0 17 27 2.717600 1.108200 0.000000 9 43 7 5757FF 18 27 1.978400 1.474500 0.000000 9 43 7 5757FF 19 4 1.401600 0.884700 0.000000 9 2 6 A0A0A0 20 4 1.784300 0.153800 0.000000 9 2 6 A0A0A0 ::: } m_bond[22] { # First column is bond index # i_m_from i_m_to i_m_order ::: 1 1 2 1 2 1 19 1 3 2 3 1 4 3 4 1 5 4 5 1 6 5 6 1 7 6 7 1 8 7 8 1 9 8 9 1 10 9 10 1 11 10 11 1 12 11 12 1 13 12 13 1 14 13 14 1 15 13 20 1 16 14 15 1 17 15 16 1 18 16 17 1 19 16 20 1 20 17 18 1 21 18 19 1 22 19 20 1 ::: } } f_m_ct { s_m_title s_m_entry_id s_m_entry_name s_m_Source_Path s_m_Source_File i_m_Source_File_Index s_m_subgroup_title s_m_subgroupid b_m_subgroup_collapsed i_m_ct_format ::: "template 70" 72 templates.71 /Users/nicola/schrodinger/coordgenlibs templates.mae 71 templates templates1 0 2 m_atom[18] { # First column is atom index # i_m_mmod_type r_m_x_coord r_m_y_coord r_m_z_coord i_m_residue_number i_m_color i_m_atomic_number s_m_color_rgb ::: 1 5 0.401100 1.082200 0.000000 9 2 6 A0A0A0 2 5 1.115600 1.494700 0.000000 9 2 6 A0A0A0 3 5 1.830100 1.082200 0.000000 9 2 6 A0A0A0 4 4 1.830100 0.257200 0.000000 9 2 6 A0A0A0 5 5 2.120600 -0.393500 0.000000 9 2 6 A0A0A0 6 16 0.855600 -0.476000 0.000000 9 70 8 FF2F2F 7 4 1.115600 -0.155300 0.000000 9 2 6 A0A0A0 8 5 1.115600 -0.980300 0.000000 9 2 6 A0A0A0 9 5 0.401100 -1.392800 0.000000 9 2 6 A0A0A0 10 3 0.401100 0.257200 0.000000 9 2 6 A0A0A0 11 4 -0.313300 -0.155300 0.000000 9 2 6 A0A0A0 12 3 -0.313300 -0.980300 0.000000 9 2 6 A0A0A0 13 5 -0.958300 0.359100 0.000000 9 2 6 A0A0A0 14 5 -1.762600 0.175500 0.000000 9 2 6 A0A0A0 15 4 -2.120600 -0.567800 0.000000 9 2 6 A0A0A0 16 5 -1.098400 -0.254400 0.000000 9 2 6 A0A0A0 17 5 -1.762600 -1.311100 0.000000 9 2 6 A0A0A0 18 5 -0.958300 -1.494700 0.000000 9 2 6 A0A0A0 ::: } m_bond[22] { # First column is bond index # i_m_from i_m_to i_m_order ::: 1 1 2 1 2 1 10 1 3 2 3 1 4 3 4 1 5 4 5 1 6 4 7 1 7 5 6 1 8 6 10 1 9 7 8 1 10 7 10 1 11 8 9 1 12 9 12 1 13 10 11 1 14 11 12 1 15 11 13 1 16 12 16 1 17 12 18 1 18 13 14 1 19 14 15 1 20 15 16 1 21 15 17 1 22 17 18 1 ::: } } f_m_ct { s_m_title s_m_entry_id s_m_entry_name s_m_Source_Path s_m_Source_File i_m_Source_File_Index s_m_subgroup_title s_m_subgroupid b_m_subgroup_collapsed i_m_ct_format ::: "template 71" 73 templates.72 /Users/nicola/schrodinger/coordgenlibs templates.mae 72 templates templates1 0 2 m_atom[18] { # First column is atom index # i_m_mmod_type r_m_x_coord r_m_y_coord r_m_z_coord i_m_residue_number i_m_color i_m_atomic_number s_m_color_rgb ::: 1 5 0.538200 0.703300 0.000000 9 2 6 A0A0A0 2 5 1.143200 1.363300 0.000000 9 2 6 A0A0A0 3 5 1.720700 1.060800 0.000000 9 2 6 A0A0A0 4 4 1.590600 0.355300 0.000000 9 2 6 A0A0A0 5 5 2.142600 -0.257800 0.000000 9 2 6 A0A0A0 6 16 1.887700 -1.042400 0.000000 9 70 8 FF2F2F 7 5 1.080700 -1.214000 0.000000 9 2 6 A0A0A0 8 4 0.783600 0.183700 0.000000 9 2 6 A0A0A0 9 5 0.116200 0.668700 0.000000 9 2 6 A0A0A0 10 3 0.528700 -0.600900 0.000000 9 2 6 A0A0A0 11 4 -0.296300 -0.600900 0.000000 9 2 6 A0A0A0 12 3 -0.551300 0.183700 0.000000 9 2 6 A0A0A0 13 5 -0.750800 -1.289400 0.000000 9 2 6 A0A0A0 14 5 -1.572500 -1.363300 0.000000 9 2 6 A0A0A0 15 4 -2.142600 -0.767000 0.000000 9 2 6 A0A0A0 16 5 -1.073600 -0.749200 0.000000 9 2 6 A0A0A0 17 5 -2.031900 0.050500 0.000000 9 2 6 A0A0A0 18 5 -1.323700 0.473600 0.000000 9 2 6 A0A0A0 ::: } m_bond[22] { # First column is bond index # i_m_from i_m_to i_m_order ::: 1 1 2 1 2 1 10 1 3 2 3 1 4 3 4 1 5 4 5 1 6 4 8 1 7 5 6 1 8 6 7 1 9 7 10 1 10 8 9 1 11 8 10 1 12 9 12 1 13 10 11 1 14 11 12 1 15 11 13 1 16 12 16 1 17 12 18 1 18 13 14 1 19 14 15 1 20 15 16 1 21 15 17 1 22 17 18 1 ::: } } f_m_ct { s_m_title s_m_entry_id s_m_entry_name s_m_Source_Path s_m_Source_File i_m_Source_File_Index s_m_subgroup_title s_m_subgroupid b_m_subgroup_collapsed i_m_ct_format ::: "template 72" 74 templates.73 /Users/nicola/schrodinger/coordgenlibs templates.mae 73 templates templates1 0 2 m_atom[18] { # First column is atom index # i_m_mmod_type r_m_x_coord r_m_y_coord r_m_z_coord i_m_residue_number i_m_color i_m_atomic_number s_m_color_rgb ::: 1 5 -0.825000 2.042600 0.000000 9 2 6 A0A0A0 2 27 -0.412500 1.328100 0.000000 9 43 7 5757FF 3 5 0.412500 1.328100 0.000000 9 2 6 A0A0A0 4 2 0.825000 0.613700 0.000000 9 2 6 A0A0A0 5 7 0.412500 -0.100800 0.000000 9 2 6 A0A0A0 6 2 0.825000 -0.815300 0.000000 9 2 6 A0A0A0 7 7 1.650000 0.613700 0.000000 9 2 6 A0A0A0 8 7 2.062500 -0.100800 0.000000 9 2 6 A0A0A0 9 7 1.650000 -0.815300 0.000000 9 2 6 A0A0A0 10 5 -1.650000 2.042600 0.000000 9 2 6 A0A0A0 11 16 -2.062500 1.328100 0.000000 9 70 8 FF2F2F 12 5 -1.650000 0.613700 0.000000 9 2 6 A0A0A0 13 7 -2.062500 -0.100800 0.000000 9 2 6 A0A0A0 14 7 -1.650000 -0.815300 0.000000 9 2 6 A0A0A0 15 5 -1.779100 -1.630100 0.000000 9 2 6 A0A0A0 16 5 -1.064600 -2.042600 0.000000 9 2 6 A0A0A0 17 27 -0.412500 -1.529700 0.000000 9 43 7 5757FF 18 5 0.412500 -1.529700 0.000000 9 2 6 A0A0A0 ::: } m_bond[19] { # First column is bond index # i_m_from i_m_to i_m_order ::: 1 1 2 1 2 1 10 1 3 2 3 1 4 3 4 1 5 4 5 2 6 4 7 1 7 5 6 1 8 6 9 2 9 6 18 1 10 7 8 2 11 8 9 1 12 10 11 1 13 11 12 1 14 12 13 1 15 13 14 2 16 14 15 1 17 15 16 1 18 16 17 1 19 17 18 1 ::: } } f_m_ct { s_m_title s_m_entry_id s_m_entry_name s_m_Source_Path s_m_Source_File i_m_Source_File_Index s_m_subgroup_title s_m_subgroupid b_m_subgroup_collapsed i_m_ct_format ::: "template 73" 75 templates.74 /Users/nicola/schrodinger/coordgenlibs templates.mae 74 templates templates1 0 2 m_atom[18] { # First column is atom index # i_m_mmod_type r_m_x_coord r_m_y_coord r_m_z_coord i_m_residue_number i_m_color i_m_atomic_number s_m_color_rgb ::: 1 5 -1.171300 1.547400 0.000000 9 2 6 A0A0A0 2 27 -0.758800 2.261800 0.000000 9 43 7 5757FF 3 5 0.066200 2.261800 0.000000 9 2 6 A0A0A0 4 2 0.478700 1.547400 0.000000 9 2 6 A0A0A0 5 7 0.066200 0.832900 0.000000 9 2 6 A0A0A0 6 2 0.580600 0.187900 0.000000 9 2 6 A0A0A0 7 7 1.298800 1.637000 0.000000 9 2 6 A0A0A0 8 7 1.771300 0.960700 0.000000 9 2 6 A0A0A0 9 7 1.404900 0.221500 0.000000 9 2 6 A0A0A0 10 5 -0.758800 0.832900 0.000000 9 2 6 A0A0A0 11 16 -1.273200 0.187900 0.000000 9 70 8 FF2F2F 12 5 -1.089600 -0.616400 0.000000 9 2 6 A0A0A0 13 7 -1.771300 -1.081200 0.000000 9 2 6 A0A0A0 14 7 -1.709600 -1.903900 0.000000 9 2 6 A0A0A0 15 5 -0.966300 -2.261800 0.000000 9 2 6 A0A0A0 16 5 -0.284700 -1.797100 0.000000 9 2 6 A0A0A0 17 27 -0.346300 -0.974400 0.000000 9 43 7 5757FF 18 5 0.397000 -0.616400 0.000000 9 2 6 A0A0A0 ::: } m_bond[19] { # First column is bond index # i_m_from i_m_to i_m_order ::: 1 1 2 1 2 1 10 1 3 2 3 1 4 3 4 1 5 4 5 2 6 4 7 1 7 5 6 1 8 6 9 2 9 6 18 1 10 7 8 2 11 8 9 1 12 10 11 1 13 11 12 1 14 12 13 1 15 13 14 2 16 14 15 1 17 15 16 1 18 16 17 1 19 17 18 1 ::: } } f_m_ct { s_m_title s_m_entry_id s_m_entry_name s_m_Source_Path s_m_Source_File i_m_Source_File_Index s_m_subgroup_title s_m_subgroupid b_m_subgroup_collapsed i_m_ct_format ::: "template 74" 76 templates.75 /Users/nicola/schrodinger/coordgenlibs templates.mae 75 templates templates1 0 2 m_atom[23] { # First column is atom index # i_m_mmod_type r_m_x_coord r_m_y_coord r_m_z_coord i_m_residue_number i_m_color i_m_atomic_number s_m_color_rgb ::: 1 5 -0.357200 -0.825000 0.000000 9 2 6 A0A0A0 2 5 -0.357200 -1.650000 0.000000 9 2 6 A0A0A0 3 5 0.357200 -2.062500 0.000000 9 2 6 A0A0A0 4 5 1.071700 -1.650000 0.000000 9 2 6 A0A0A0 5 4 1.071700 -0.825000 0.000000 9 2 6 A0A0A0 6 5 0.357200 -0.412500 0.000000 9 2 6 A0A0A0 7 5 0.357200 0.412500 0.000000 9 2 6 A0A0A0 8 5 1.071700 0.825000 0.000000 9 2 6 A0A0A0 9 5 1.786200 -0.412500 0.000000 9 2 6 A0A0A0 10 4 1.786200 0.412500 0.000000 9 2 6 A0A0A0 11 5 2.500600 0.825000 0.000000 9 2 6 A0A0A0 12 5 2.500600 1.650000 0.000000 9 2 6 A0A0A0 13 5 1.786200 2.062500 0.000000 9 2 6 A0A0A0 14 5 1.071700 1.650000 0.000000 9 2 6 A0A0A0 15 5 0.357200 2.062500 0.000000 9 2 6 A0A0A0 16 5 -0.357200 1.650000 0.000000 9 2 6 A0A0A0 17 5 -0.357200 0.825000 0.000000 9 2 6 A0A0A0 18 4 -1.071700 0.412500 0.000000 9 2 6 A0A0A0 19 4 -1.071700 -0.412500 0.000000 9 2 6 A0A0A0 20 5 -1.786200 0.825000 0.000000 9 2 6 A0A0A0 21 5 -2.500600 0.412500 0.000000 9 2 6 A0A0A0 22 5 -2.500600 -0.412500 0.000000 9 2 6 A0A0A0 23 5 -1.786200 -0.825000 0.000000 9 2 6 A0A0A0 ::: } m_bond[25] { # First column is bond index # i_m_from i_m_to i_m_order ::: 1 1 2 1 2 1 19 1 3 2 3 1 4 3 4 1 5 4 5 1 6 5 6 1 7 5 9 1 8 6 7 1 9 7 8 1 10 8 10 1 11 9 10 1 12 10 11 1 13 11 12 1 14 12 13 1 15 13 14 1 16 14 15 1 17 15 16 1 18 16 17 1 19 17 18 1 20 18 19 1 21 18 20 1 22 19 23 1 23 20 21 1 24 21 22 1 25 22 23 1 ::: } } f_m_ct { s_m_title s_m_entry_id s_m_entry_name s_m_Source_Path s_m_Source_File i_m_Source_File_Index s_m_subgroup_title s_m_subgroupid b_m_subgroup_collapsed i_m_ct_format ::: "template 75" 77 templates.76 /Users/nicola/schrodinger/coordgenlibs templates.mae 76 templates templates1 0 2 m_atom[25] { # First column is atom index # i_m_mmod_type r_m_x_coord r_m_y_coord r_m_z_coord i_m_residue_number i_m_color i_m_atomic_number s_m_color_rgb ::: 1 5 -0.825000 -0.276700 0.000000 9 2 6 A0A0A0 2 5 -0.825000 -1.101700 0.000000 9 2 6 A0A0A0 3 5 -0.000000 -1.101700 0.000000 9 2 6 A0A0A0 4 5 0.412500 -1.816100 0.000000 9 2 6 A0A0A0 5 4 1.237500 -1.816100 0.000000 9 2 6 A0A0A0 6 5 1.607800 -2.553300 0.000000 9 2 6 A0A0A0 7 5 2.430800 -2.610800 0.000000 9 2 6 A0A0A0 8 5 2.900100 -1.932300 0.000000 9 2 6 A0A0A0 9 5 1.650000 -1.101700 0.000000 9 2 6 A0A0A0 10 4 2.555900 -1.182600 0.000000 9 2 6 A0A0A0 11 5 2.968400 -0.468100 0.000000 9 2 6 A0A0A0 12 5 2.555900 0.246400 0.000000 9 2 6 A0A0A0 13 5 1.730900 0.246400 0.000000 9 2 6 A0A0A0 14 5 1.318400 0.960800 0.000000 9 2 6 A0A0A0 15 5 0.603900 1.373300 0.000000 9 2 6 A0A0A0 16 5 0.603900 2.198300 0.000000 9 2 6 A0A0A0 17 5 -0.110500 2.610800 0.000000 9 2 6 A0A0A0 18 5 -0.825000 2.198300 0.000000 9 2 6 A0A0A0 19 5 -0.825000 1.373300 0.000000 9 2 6 A0A0A0 20 4 -1.539500 0.960800 0.000000 9 2 6 A0A0A0 21 4 -1.539500 0.135800 0.000000 9 2 6 A0A0A0 22 5 -2.253900 1.373300 0.000000 9 2 6 A0A0A0 23 5 -2.968400 0.960800 0.000000 9 2 6 A0A0A0 24 5 -2.968400 0.135800 0.000000 9 2 6 A0A0A0 25 5 -2.253900 -0.276700 0.000000 9 2 6 A0A0A0 ::: } m_bond[27] { # First column is bond index # i_m_from i_m_to i_m_order ::: 1 1 2 1 2 1 21 1 3 2 3 1 4 3 4 1 5 4 5 1 6 5 6 1 7 5 9 1 8 6 7 1 9 7 8 1 10 8 10 1 11 9 10 1 12 10 11 1 13 11 12 1 14 12 13 1 15 13 14 1 16 14 15 1 17 15 16 1 18 16 17 1 19 17 18 1 20 18 19 1 21 19 20 1 22 20 21 1 23 20 22 1 24 21 25 1 25 22 23 1 26 23 24 1 27 24 25 1 ::: } } f_m_ct { s_m_title s_m_entry_id s_m_entry_name s_m_Source_Path s_m_Source_File i_m_Source_File_Index s_m_subgroup_title s_m_subgroupid b_m_subgroup_collapsed i_m_ct_format ::: "template 76" 78 templates.77 /Users/nicola/schrodinger/coordgenlibs templates.mae 77 templates templates1 0 2 m_atom[27] { # First column is atom index # i_m_mmod_type r_m_x_coord r_m_y_coord r_m_z_coord i_m_residue_number i_m_color i_m_atomic_number s_m_color_rgb ::: 1 5 -1.071700 -0.206300 0.000000 9 2 6 A0A0A0 2 5 -1.071700 -1.031300 0.000000 9 2 6 A0A0A0 3 5 -0.357200 -1.443800 0.000000 9 2 6 A0A0A0 4 5 0.357200 -1.031300 0.000000 9 2 6 A0A0A0 5 4 1.071700 -1.443800 0.000000 9 2 6 A0A0A0 6 5 1.071700 -2.268800 0.000000 9 2 6 A0A0A0 7 5 1.786200 -2.681200 0.000000 9 2 6 A0A0A0 8 5 2.500600 -2.268800 0.000000 9 2 6 A0A0A0 9 5 1.786200 -1.031300 0.000000 9 2 6 A0A0A0 10 4 2.500600 -1.443800 0.000000 9 2 6 A0A0A0 11 5 3.215100 -1.031300 0.000000 9 2 6 A0A0A0 12 5 3.215100 -0.206300 0.000000 9 2 6 A0A0A0 13 5 2.500600 0.206200 0.000000 9 2 6 A0A0A0 14 5 2.500600 1.031200 0.000000 9 2 6 A0A0A0 15 5 1.786200 1.443700 0.000000 9 2 6 A0A0A0 16 5 1.786200 2.268700 0.000000 9 2 6 A0A0A0 17 5 1.071700 2.681200 0.000000 9 2 6 A0A0A0 18 7 0.357200 2.268700 0.000000 9 2 6 A0A0A0 19 7 0.357200 1.443700 0.000000 9 2 6 A0A0A0 20 5 -0.357200 1.031200 0.000000 9 2 6 A0A0A0 21 5 -1.071700 1.443700 0.000000 9 2 6 A0A0A0 22 4 -1.786200 1.031200 0.000000 9 2 6 A0A0A0 23 4 -1.786200 0.206200 0.000000 9 2 6 A0A0A0 24 5 -2.500600 1.443700 0.000000 9 2 6 A0A0A0 25 5 -3.215100 1.031200 0.000000 9 2 6 A0A0A0 26 5 -3.215100 0.206200 0.000000 9 2 6 A0A0A0 27 5 -2.500600 -0.206300 0.000000 9 2 6 A0A0A0 ::: } m_bond[29] { # First column is bond index # i_m_from i_m_to i_m_order ::: 1 1 2 1 2 1 23 1 3 2 3 1 4 3 4 1 5 4 5 1 6 5 6 1 7 5 9 1 8 6 7 1 9 7 8 1 10 8 10 1 11 9 10 1 12 10 11 1 13 11 12 1 14 12 13 1 15 13 14 1 16 14 15 1 17 15 16 1 18 16 17 1 19 17 18 1 20 18 19 2 21 19 20 1 22 20 21 1 23 21 22 1 24 22 23 1 25 22 24 1 26 23 27 1 27 24 25 1 28 25 26 1 29 26 27 1 ::: } } f_m_ct { s_m_title s_m_entry_id s_m_entry_name s_m_Source_Path s_m_Source_File i_m_Source_File_Index s_m_subgroup_title s_m_subgroupid b_m_subgroup_collapsed i_m_ct_format ::: "template 77" 79 templates.78 /Users/nicola/schrodinger/coordgenlibs templates.mae 78 templates templates1 0 2 m_atom[24] { # First column is atom index # i_m_mmod_type r_m_x_coord r_m_y_coord r_m_z_coord i_m_residue_number i_m_color i_m_atomic_number s_m_color_rgb ::: 1 5 -0.962900 0.006300 0.000000 9 2 6 A0A0A0 2 5 -0.550400 -0.708200 0.000000 9 2 6 A0A0A0 3 5 0.274600 -0.708200 0.000000 9 2 6 A0A0A0 4 5 0.687100 -1.422600 0.000000 9 2 6 A0A0A0 5 4 1.512100 -1.422600 0.000000 9 2 6 A0A0A0 6 5 1.924600 -2.137100 0.000000 9 2 6 A0A0A0 7 5 2.749600 -2.137100 0.000000 9 2 6 A0A0A0 8 5 3.162100 -1.422600 0.000000 9 2 6 A0A0A0 9 5 1.924600 -0.708200 0.000000 9 2 6 A0A0A0 10 4 2.749600 -0.708200 0.000000 9 2 6 A0A0A0 11 5 3.162100 0.006300 0.000000 9 2 6 A0A0A0 12 5 2.749600 0.708200 0.000000 9 2 6 A0A0A0 13 5 1.924600 0.708200 0.000000 9 2 6 A0A0A0 14 5 1.512100 1.422600 0.000000 9 2 6 A0A0A0 15 5 0.687100 1.422600 0.000000 9 2 6 A0A0A0 16 5 0.274600 2.137100 0.000000 9 2 6 A0A0A0 17 5 -0.550400 2.137100 0.000000 9 2 6 A0A0A0 18 5 -0.962900 1.422600 0.000000 9 2 6 A0A0A0 19 4 -1.733100 1.127000 0.000000 9 2 6 A0A0A0 20 4 -1.733100 0.302000 0.000000 9 2 6 A0A0A0 21 5 -2.447600 1.539500 0.000000 9 2 6 A0A0A0 22 5 -3.162100 1.127000 0.000000 9 2 6 A0A0A0 23 5 -3.162100 0.302000 0.000000 9 2 6 A0A0A0 24 5 -2.447600 -0.110500 0.000000 9 2 6 A0A0A0 ::: } m_bond[26] { # First column is bond index # i_m_from i_m_to i_m_order ::: 1 1 2 1 2 1 20 1 3 2 3 1 4 3 4 1 5 4 5 1 6 5 6 1 7 5 9 1 8 6 7 1 9 7 8 1 10 8 10 1 11 9 10 1 12 10 11 1 13 11 12 1 14 12 13 1 15 13 14 1 16 14 15 1 17 15 16 1 18 16 17 1 19 17 18 1 20 18 19 1 21 19 20 1 22 19 21 1 23 20 24 1 24 21 22 1 25 22 23 1 26 23 24 1 ::: } } f_m_ct { s_m_title s_m_entry_id s_m_entry_name s_m_Source_Path s_m_Source_File i_m_Source_File_Index s_m_subgroup_title s_m_subgroupid b_m_subgroup_collapsed i_m_ct_format ::: cubane 80 templates.79 /Users/nicola/schrodinger/coordgenlibs templates.mae 79 templates templates1 0 2 m_atom[8] { # First column is atom index # i_m_mmod_type r_m_x_coord r_m_y_coord r_m_z_coord i_m_residue_number i_m_color i_m_atomic_number s_m_color_rgb ::: 1 4 -1.763400 2.723200 0.000000 9 2 6 A0A0A0 2 4 -1.763400 1.898200 0.000000 9 2 6 A0A0A0 3 4 -0.938400 1.898200 0.000000 9 2 6 A0A0A0 4 4 -0.938400 2.723200 0.000000 9 2 6 A0A0A0 5 4 -2.114500 1.508300 0.000000 9 2 6 A0A0A0 6 4 -1.289500 1.508300 0.000000 9 2 6 A0A0A0 7 4 -2.114500 2.333300 0.000000 9 2 6 A0A0A0 8 4 -1.289500 2.333300 0.000000 9 2 6 A0A0A0 ::: } m_bond[12] { # First column is bond index # i_m_from i_m_to i_m_order ::: 1 1 2 1 2 1 4 1 3 1 7 1 4 2 3 1 5 2 5 1 6 3 4 1 7 3 6 1 8 4 8 1 9 5 6 1 10 5 7 1 11 6 8 1 12 7 8 1 ::: } } f_m_ct { s_m_title s_m_entry_id s_m_entry_name s_m_Source_Path s_m_Source_File i_m_Source_File_Index s_m_subgroup_title s_m_subgroupid b_m_subgroup_collapsed i_m_ct_format ::: "template 79" 81 templates.80 /Users/nicola/schrodinger/coordgenlibs templates.mae 80 templates templates1 0 2 m_atom[8] { # First column is atom index # i_m_mmod_type r_m_x_coord r_m_y_coord r_m_z_coord i_m_residue_number i_m_color i_m_atomic_number s_m_color_rgb s_m_atom_name ::: 1 4 -1.808000 0.490200 0.000000 9 2 6 A0A0A0 "" 2 27 -2.522500 0.077700 0.000000 9 43 7 5757FF "N2" 3 5 -2.522500 -0.747400 0.000000 9 2 6 A0A0A0 "" 4 4 -1.808000 -1.159800 0.000000 9 2 6 A0A0A0 "" 5 5 -1.093500 -0.747400 0.000000 9 2 6 A0A0A0 "" 6 27 -1.093500 0.077700 0.000000 9 43 7 5757FF "N6" 7 5 -1.507100 -0.112700 0.000000 9 2 6 A0A0A0 "" 8 5 -2.042000 -0.579300 0.000000 9 2 6 A0A0A0 "" ::: } m_bond[9] { # First column is bond index # i_m_from i_m_to i_m_order ::: 1 1 2 1 2 1 6 1 3 1 7 1 4 2 3 1 5 3 4 1 6 4 5 1 7 4 8 1 8 5 6 1 9 7 8 1 ::: } } f_m_ct { s_m_title i_m_ct_enhanced_stereo_status s_m_entry_id s_m_entry_name s_m_Source_Path s_m_Source_File i_m_Source_File_Index s_m_subgroup_title s_m_subgroupid b_m_subgroup_collapsed i_m_ct_format ::: biciclo(1,1,1)pentane 0 82 templates.81 /Users/nicola/schrodinger/coordgenlibs templates.mae 81 templates templates1 0 2 m_atom[5] { # First column is atom index # i_m_mmod_type r_m_x_coord r_m_y_coord r_m_z_coord i_m_residue_number i_m_color i_m_atomic_number s_m_color_rgb ::: 1 5 -0.583300 -0.000000 0.000000 900 2 6 A0A0A0 2 4 0.000000 0.583300 0.000000 900 2 6 A0A0A0 3 5 0.583300 -0.000000 0.000000 900 2 6 A0A0A0 4 4 0.000000 -0.583300 0.000000 900 2 6 A0A0A0 5 5 0.145800 -0.000000 0.000000 900 2 6 A0A0A0 ::: } m_bond[6] { # First column is bond index # i_m_from i_m_to i_m_order ::: 1 1 2 1 2 1 4 1 3 2 3 1 4 2 5 1 5 3 4 1 6 4 5 1 ::: } } f_m_ct { s_m_title i_m_ct_enhanced_stereo_status s_m_entry_id s_m_entry_name b_sd_chiral_flag i_sd_version s_m_Source_Path s_m_Source_File i_m_Source_File_Index s_m_subgroup_title s_m_subgroupid b_m_subgroup_collapsed i_m_ct_format ::: template 0 1 template.1 0 1 /Users/nicola/Desktop template.mol 1 templates templates1 0 2 m_atom[9] { # First column is atom index # i_m_mmod_type r_m_x_coord r_m_y_coord r_m_z_coord i_m_residue_number i_m_color i_m_atomic_number s_m_color_rgb ::: 1 5 -6.000000 7.812500 0.000000 900 2 6 A0A0A0 2 4 -4.460000 7.812500 0.000000 900 2 6 A0A0A0 3 5 -3.690000 6.478800 0.000000 900 2 6 A0A0A0 4 4 -6.770000 6.478800 0.000000 900 2 6 A0A0A0 5 5 -6.000000 5.145100 0.000000 900 2 6 A0A0A0 6 4 -4.460000 5.145100 0.000000 900 2 6 A0A0A0 7 4 -2.995400 7.336600 0.000000 900 2 6 A0A0A0 8 5 -2.995400 5.621000 0.000000 900 2 6 A0A0A0 9 5 -5.263700 6.158600 0.000000 900 2 6 A0A0A0 ::: } m_bond[11] { # First column is bond index # i_m_from i_m_to i_m_order ::: 1 1 2 1 2 1 4 1 3 2 3 1 4 2 7 1 5 3 6 1 6 4 5 1 7 4 9 1 8 5 6 1 9 6 8 1 10 7 8 1 11 7 9 1 ::: } } coordgenlibs-3.0.2/test/000077500000000000000000000000001436654770400151655ustar00rootroot00000000000000coordgenlibs-3.0.2/test/CMakeLists.txt000066400000000000000000000033041436654770400177250ustar00rootroot00000000000000# Use the example executable as a test add_test(example ${CMAKE_BINARY_DIR}/example_dir/example) add_executable(test_coordgen test_coordgen.cpp) if(COORDGEN_BUILD_SHARED_LIBS) target_compile_definitions(test_coordgen PRIVATE "BOOST_ALL_DYN_LINK") else(COORDGEN_BUILD_SHARED_LIBS) set(Boost_USE_STATIC_LIBS ON) target_compile_definitions(test_coordgen PRIVATE "STATIC_MAEPARSER") target_compile_definitions(test_coordgen PRIVATE "STATIC_COORDGEN") endif(COORDGEN_BUILD_SHARED_LIBS) find_package(Boost COMPONENTS filesystem unit_test_framework REQUIRED) target_link_libraries(test_coordgen coordgen ${maeparser_LIBRARIES} ${boost_link_options} Boost::unit_test_framework Boost::filesystem) # Set the path for the input files get_filename_component(TEST_SAMPLES_PATH ${CMAKE_CURRENT_SOURCE_DIR} ABSOLUTE) target_compile_definitions(test_coordgen PRIVATE "TEST_SAMPLES_PATH=\"${TEST_SAMPLES_PATH}\"") target_compile_definitions(test_coordgen PRIVATE "SOURCE_DIR=\"${PROJECT_SOURCE_DIR}\"") add_test(NAME test_coordgen COMMAND ${CMAKE_BINARY_DIR}/test/test_coordgen WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/test) add_executable(test_smilesparser test_smilesparser.cpp) if(COORDGEN_BUILD_SHARED_LIBS) target_compile_definitions(test_smilesparser PRIVATE "BOOST_ALL_DYN_LINK") else(COORDGEN_BUILD_SHARED_LIBS) set(Boost_USE_STATIC_LIBS ON) target_compile_definitions(test_smilesparser PRIVATE "STATIC_COORDGEN") endif(COORDGEN_BUILD_SHARED_LIBS) target_link_libraries(test_smilesparser coordgen ${boost_link_options} Boost::unit_test_framework Boost::filesystem) add_test(NAME test_smilesparser COMMAND ${CMAKE_BINARY_DIR}/test/test_coordgen WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/test)coordgenlibs-3.0.2/test/coordgenBasicSMILES.h000066400000000000000000000046311436654770400210210ustar00rootroot00000000000000/* * A very, very basic SMILES-like parser. No aromaticity, * or zero-order bonds. No chirality/stereochemistry * * Do not use this as a basis for real SMILES parsers. It just lets * us sidestep using a full chemistry toolkit when writing tests. */ #include #include #include #include #include #include #include "../sketcherMinimizerMolecule.h" namespace schrodinger { sketcherMinimizerMolecule* approxSmilesParse(const std::string& smiles) { const std::unordered_map elements{ {'H', 1}, {'C', 6}, {'N', 7}, {'S', 16}, {'O', 8}}; auto mol = new sketcherMinimizerMolecule(); std::stack> tree; tree.emplace(); auto* prev = &tree.top(); std::unordered_map cycles; int bond_order = 1; size_t idx = 0; for (auto c : smiles) { auto atomic_number = elements.find(c); if (atomic_number != elements.end()) { auto atom = mol->addNewAtom(); atom->setAtomicNumber(atomic_number->second); if (!prev->empty()) { auto bond = mol->addNewBond(atom, prev->top()); bond->setBondOrder(bond_order); bond_order = 1; } prev->push(atom); } else if (c == '=') { bond_order = 2; } else if (c == '1' || c == '2' || c == '3' || c == '4') { auto other = cycles.find(c); if (other == cycles.end()) { cycles[c] = prev->top(); } else { auto bond = mol->addNewBond(prev->top(), other->second); bond->setBondOrder(bond_order); bond_order = 1; cycles.erase(other); } } else if (c == '(') { auto old = prev->top(); tree.emplace(); prev = &tree.top(); prev->push(old); } else if (c == ')') { tree.pop(); prev = &tree.top(); } else { std::string msg = "unrecognized symbol: "; msg += c; msg += " in SMILES: " + smiles; throw std::runtime_error(msg); } ++idx; } sketcherMinimizerMolecule::assignBondsAndNeighbors(mol->getAtoms(), mol->getBonds()); return mol; } } // namespace schrodinger coordgenlibs-3.0.2/test/macrocycle.mae000066400000000000000000000235751436654770400200060ustar00rootroot00000000000000{ s_m_m2io_version ::: 2.0.0 } f_m_ct { s_m_title i_m_ct_stereo_status i_m_ct_enhanced_stereo_status s_st_Chirality_1 s_m_entry_id s_m_entry_name s_sd_ID s_sd_All_IDs s_sd_Rationale s_sd_Lot_Scientist s_sd_Approved_Drug r_sd_Quick_Properties_(MW) s_sd_PUBCHEM\_CACTVS\_SUBSKEYS_(undefined) s_sd_PUBCHEM\_IUPAC\_OPENEYE\_NAME_(undefined) s_sd_PUBCHEM\_IUPAC\_CAS\_NAME_(undefined) s_sd_PUBCHEM\_IUPAC\_NAME\_MARKUP_(undefined) s_sd_PUBCHEM\_IUPAC\_NAME_(undefined) s_sd_PUBCHEM\_IUPAC\_SYSTEMATIC\_NAME_(undefined) s_sd_PUBCHEM\_IUPAC\_TRADITIONAL\_NAME_(undefined) s_sd_PUBCHEM\_IUPAC\_INCHI_(undefined) s_sd_PUBCHEM\_IUPAC\_INCHIKEY_(undefined) s_sd_PUBCHEM\_MOLECULAR\_FORMULA_(undefined) s_sd_PUBCHEM\_OPENEYE\_CAN\_SMILES_(undefined) s_sd_PUBCHEM\_OPENEYE\_ISO\_SMILES_(undefined) s_sd_PUBCHEM\_NONSTANDARDBOND_(undefined) s_sd_PUBCHEM\_BONDANNOTATIONS_(undefined) s_sd_PUBCHEM\_CONFORMER\_RMSD_(undefined) s_sd_PUBCHEM\_CONFORMER\_DIVERSEORDER_(undefined) s_sd_PUBCHEM\_MMFF94\_PARTIAL\_CHARGES_(undefined) s_sd_PUBCHEM\_EFFECTIVE\_ROTOR\_COUNT_(undefined) s_sd_PUBCHEM\_PHARMACOPHORE\_FEATURES_(undefined) s_sd_PUBCHEM\_CONFORMER\_ID_(undefined) s_sd_PUBCHEM\_MMFF94\_ENERGY_(undefined) s_sd_PUBCHEM\_FEATURE\_SELFOVERLAP_(undefined) s_sd_PUBCHEM\_SHAPE\_FINGERPRINT_(undefined) s_sd_PUBCHEM\_SHAPE\_MULTIPOLES_(undefined) s_sd_PUBCHEM\_SHAPE\_SELFOVERLAP_(undefined) s_sd_PUBCHEM\_SHAPE\_VOLUME_(undefined) b_sd_chiral_flag i_sd_version s_m_Source_Path s_m_Source_File i_m_Source_File_Index i_sd_PUBCHEM\_COMPOUND\_CID_(undefined) i_sd_PUBCHEM\_COMPOUND\_CANONICALIZED_(undefined) r_sd_PUBCHEM\_CACTVS\_COMPLEXITY_(undefined) r_sd_PUBCHEM\_CACTVS\_HBOND\_ACCEPTOR_(undefined) i_sd_PUBCHEM\_CACTVS\_HBOND\_DONOR_(undefined) r_sd_PUBCHEM\_CACTVS\_ROTATABLE\_BOND_(undefined) r_sd_PUBCHEM\_EXACT\_MASS_(undefined) r_sd_PUBCHEM\_MOLECULAR\_WEIGHT_(undefined) r_sd_PUBCHEM\_CACTVS\_TPSA_(undefined) r_sd_PUBCHEM\_MONOISOTOPIC\_WEIGHT_(undefined) i_sd_PUBCHEM\_TOTAL\_CHARGE_(undefined) i_sd_PUBCHEM\_HEAVY\_ATOM\_COUNT_(undefined) i_sd_PUBCHEM\_ATOM\_DEF\_STEREO\_COUNT_(undefined) r_sd_PUBCHEM\_ATOM\_UDEF\_STEREO\_COUNT_(undefined) i_sd_PUBCHEM\_BOND\_DEF\_STEREO\_COUNT_(undefined) i_sd_PUBCHEM\_BOND\_UDEF\_STEREO\_COUNT_(undefined) i_sd_PUBCHEM\_ISOTOPIC\_ATOM\_COUNT_(undefined) r_sd_PUBCHEM\_COMPONENT\_COUNT_(undefined) i_sd_PUBCHEM\_CACTVS\_TAUTO\_COUNT_(undefined) r_sd_PUBCHEM\_COORDINATE\_TYPE_(undefined) r_sd_PUBCHEM\_XLOGP3\_AA_(undefined) s_m_subgroup_title s_m_subgroupid b_m_subgroup_collapsed i_m_ct_format ::: V226050 1 0 41_S_9_8_49_54 6 macrocycles.6 V226050 V226050 "" demo "" 822.8939 AAADcfB/PAAAAAAAAAAAAAAAGAAAASAAAAA0QIAAAAAAAEiBAAAAHgAQCAAADTzxmAcCDoLABgCoA6XyXAKCCAAkIgAIiAH0CNgeNzaGtT+neWCl5BWMuYf67vzu4AADCAAYAADAAAYQADAAAAAAAAAAAA== "[(7S)-2,15,17-trihydroxy-28-(6-hydroxy-2-methyl-tetrahydropyran-3-yl)imino-11-methoxy-3,7,12,14,16,23-hexamethyl-6,21,24,30-tetraoxo-8,31-dioxa-25-azapentacyclo[24.3.1.14,7.05,29.018,20]hentriaconta-1(29),2,4,9,22,26-hexaen-13-yl] acetate" "acetic acid [(7S)-2,15,17-trihydroxy-28-[(6-hydroxy-2-methyl-3-oxanyl)imino]-11-methoxy-3,7,12,14,16,23-hexamethyl-6,21,24,30-tetraoxo-8,31-dioxa-25-azapentacyclo[24.3.1.14,7.05,29.018,20]hentriaconta-1(29),2,4,9,22,26-hexaen-13-yl] ester" "[(7S)-2,15,17-trihydroxy-28-(6-hydroxy-2-methyloxan-3-yl)imino-11-methoxy-3,7,12,14,16,23-hexamethyl-6,21,24,30-tetraoxo-8,31-dioxa-25-azapentacyclo[24.3.1.14,7.05,29.018,20]hentriaconta-1(29),2,4,9,22,26-hexaen-13-yl] acetate" "[(7S)-2,15,17-trihydroxy-28-(6-hydroxy-2-methyloxan-3-yl)imino-11-methoxy-3,7,12,14,16,23-hexamethyl-6,21,24,30-tetraoxo-8,31-dioxa-25-azapentacyclo[24.3.1.14,7.05,29.018,20]hentriaconta-1(29),2,4,9,22,26-hexaen-13-yl] acetate" "[(7S)-11-methoxy-3,7,12,14,16,23-hexamethyl-28-(2-methyl-6-oxidanyl-oxan-3-yl)imino-2,15,17-tris(oxidanyl)-6,21,24,30-tetrakis(oxidanylidene)-8,31-dioxa-25-azapentacyclo[24.3.1.14,7.05,29.018,20]hentriaconta-1(29),2,4,9,22,26-hexaen-13-yl] ethanoate" "acetic acid [(7S)-2,15,17-trihydroxy-28-(6-hydroxy-2-methyl-tetrahydropyran-3-yl)imino-6,21,24,30-tetraketo-11-methoxy-3,7,12,14,16,23-hexamethyl-8,31-dioxa-25-azapentacyclo[24.3.1.14,7.05,29.018,20]hentriaconta-1(29),2,4,9,22,26-hexaen-13-yl] ester" InChI=1S/C43H54N2O14/c1-17-14-29(47)24-15-25(24)36(50)19(3)35(49)20(4)39(58-23(7)46)18(2)30(55-9)12-13-56-43(8)41(53)34-32-27(44-26-10-11-31(48)57-22(26)6)16-28(45-42(17)54)38(52)33(32)37(51)21(5)40(34)59-43/h12-14,16,18-20,22,24-26,30-31,35-36,39,48-51H,10-11,15H2,1-9H3,(H,45,54)/t18?,19?,20?,22?,24?,25?,26?,30?,31?,35?,36?,39?,43-/m0/s1 RYCBEGMWBUYSAD-XGUWRKLTSA-N C43H54N2O14 CC1C(C=COC2(C(=O)C3=C(O2)C(=C(C4=C3C(=NC5CCC(OC5C)O)C=C(C4=O)NC(=O)C(=CC(=O)C6CC6C(C(C(C(C1OC(=O)C)C)O)C)O)C)O)C)C)OC CC1C(C=CO[C@@]2(C(=O)C3=C(O2)C(=C(C4=C3C(=NC5CCC(OC5C)O)C=C(C4=O)NC(=O)C(=CC(=O)C6CC6C(C(C(C(C1OC(=O)C)C)O)C)O)C)O)C)C)OC "" "18 19 3 42 48 8 24 28 3 29 32 3 21 25 3 42 43 8 43 50 8 20 1 3 26 4 3 50 55 8 35 37 1 55 56 8 44 16 3 31 5 3 23 2 3 57 14 3 41 54 6 17 19 3 51 58 3 27 30 1 48 56 8" "" "" "" "" "" "" "" "" "" "" "" "" 1 0 /Users/nicola/Downloads macrocycles.sdf 6 146158297 1 1810 15 5 4 822.36 822.9 237 822.36 0 59 1 12 0 2 0 1 -1 87 3.5 macrocycles macrocycles 0 2 m_atom[59] { # First column is atom index # i_m_mmod_type r_m_x_coord r_m_y_coord r_m_z_coord i_m_residue_number i_m_color i_m_atomic_number s_m_color_rgb i_sd_original_parity ::: 1 17 -2.940200 -1.811800 0.000000 900 70 8 FF2F2F <> 2 17 -1.486900 -3.171100 0.000000 900 70 8 FF2F2F <> 3 15 -3.673500 0.438400 0.000000 900 70 8 FF2F2F <> 4 16 -0.110900 -3.929000 0.000000 900 70 8 FF2F2F <> 5 16 2.343400 -2.474700 0.000000 900 70 8 FF2F2F <> 6 15 -2.780600 3.255800 0.000000 900 70 8 FF2F2F <> 7 15 -0.053500 -5.353400 0.000000 900 70 8 FF2F2F <> 8 16 1.426800 -0.192600 0.000000 900 70 8 FF2F2F <> 9 16 2.483600 1.065700 0.000000 900 70 8 FF2F2F <> 10 16 -0.848100 -0.515500 0.000000 900 70 8 FF2F2F <> 11 15 0.554600 4.313600 0.000000 900 70 8 FF2F2F <> 12 15 0.602200 0.750900 0.000000 900 70 8 FF2F2F <> 13 17 2.097800 3.889500 0.000000 900 70 8 FF2F2F <> 14 17 -0.292000 -1.646400 0.000000 900 70 8 FF2F2F <> 15 29 -1.389100 3.520600 0.000000 900 43 7 5757FF <> 16 25 -0.447900 1.301900 0.000000 900 43 7 5757FF <> 17 4 -2.033000 -0.625100 0.000000 900 2 6 A0A0A0 <> 18 4 -2.265900 0.176300 0.000000 900 2 6 A0A0A0 <> 19 5 -1.485900 -0.034200 0.000000 900 2 6 A0A0A0 <> 20 4 -2.217600 -1.422200 0.000000 900 2 6 A0A0A0 <> 21 4 -1.429200 -1.733400 0.000000 900 2 6 A0A0A0 <> 22 2 -2.895500 0.712100 0.000000 900 2 6 A0A0A0 <> 23 4 -1.050000 -2.477400 0.000000 900 2 6 A0A0A0 <> 24 4 -0.205700 -2.505800 0.000000 900 2 6 A0A0A0 <> 25 6 -0.896000 -1.159400 0.000000 900 2 6 A0A0A0 <> 26 4 0.252600 -3.186700 0.000000 900 2 6 A0A0A0 <> 27 7 -2.731800 1.564100 0.000000 900 2 6 A0A0A0 <> 28 6 0.271700 -1.833300 0.000000 900 2 6 A0A0A0 <> 29 4 1.079400 -3.115200 0.000000 900 2 6 A0A0A0 <> 30 2 -2.028200 2.065300 0.000000 900 2 6 A0A0A0 <> 31 4 1.514200 -2.403900 0.000000 900 2 6 A0A0A0 <> 32 6 1.515900 -3.815300 0.000000 900 2 6 A0A0A0 <> 33 6 -1.302300 1.683100 0.000000 900 2 6 A0A0A0 <> 34 2 -2.026300 2.929700 0.000000 900 2 6 A0A0A0 <> 35 7 1.201600 -1.635400 0.000000 900 2 6 A0A0A0 <> 36 2 0.332500 -4.626700 0.000000 900 2 6 A0A0A0 <> 37 7 1.706500 -0.973400 0.000000 900 2 6 A0A0A0 <> 38 6 1.154400 -4.599100 0.000000 900 2 6 A0A0A0 <> 39 6 2.821100 -1.802400 0.000000 900 2 6 A0A0A0 <> 40 2 -0.599200 3.288500 0.000000 900 2 6 A0A0A0 <> 41 3 1.898200 0.502100 0.000000 900 2 6 A0A0A0 1 42 2 0.748700 2.207500 0.000000 900 2 6 A0A0A0 <> 43 2 1.313200 1.603100 0.000000 900 2 6 A0A0A0 <> 44 4 -0.211500 0.550100 0.000000 900 2 6 A0A0A0 <> 45 7 -0.788900 2.560300 0.000000 900 2 6 A0A0A0 <> 46 2 0.336400 3.512400 0.000000 900 2 6 A0A0A0 <> 47 2 -0.186300 1.961300 0.000000 900 2 6 A0A0A0 <> 48 2 0.973400 2.896100 0.000000 900 2 6 A0A0A0 <> 49 2 1.189700 0.843500 0.000000 900 2 6 A0A0A0 <> 50 2 2.137700 1.726700 0.000000 900 2 6 A0A0A0 <> 51 4 -0.871000 0.190600 0.000000 900 2 6 A0A0A0 <> 52 5 0.510700 0.162800 0.000000 900 2 6 A0A0A0 <> 53 5 0.503900 -0.541800 0.000000 900 2 6 A0A0A0 <> 54 6 2.531100 -0.032300 0.000000 900 2 6 A0A0A0 <> 55 2 2.400600 2.496300 0.000000 900 2 6 A0A0A0 <> 56 2 1.856300 3.112600 0.000000 900 2 6 A0A0A0 <> 57 4 -0.153100 -0.927100 0.000000 900 2 6 A0A0A0 <> 58 6 -1.572200 0.603000 0.000000 900 2 6 A0A0A0 <> 59 6 3.214400 2.660400 0.000000 900 2 6 A0A0A0 <> ::: } m_bond[67] { # First column is bond index # i_m_from i_m_to i_m_order i_sd_original_parity ::: 1 1 20 1 <> 2 2 23 1 <> 3 3 22 2 <> 4 4 26 1 <> 5 4 36 1 <> 6 5 31 1 <> 7 5 39 1 <> 8 6 34 2 <> 9 7 36 2 <> 10 8 37 1 <> 11 8 41 1 <> 12 9 41 1 <> 13 9 50 1 <> 14 10 51 1 <> 15 10 57 1 <> 16 11 46 2 <> 17 12 49 2 <> 18 13 56 1 <> 19 14 57 1 <> 20 15 34 1 <> 21 15 40 1 <> 22 16 44 1 <> 23 16 47 2 <> 24 17 18 1 <> 25 17 19 1 <> 26 17 20 1 <> 27 18 19 1 <> 28 18 22 1 <> 29 20 21 1 <> 30 21 23 1 <> 31 21 25 1 <> 32 22 27 1 <> 33 23 24 1 <> 34 24 26 1 <> 35 24 28 1 <> 36 26 29 1 <> 37 27 30 2 2 38 29 31 1 <> 39 29 32 1 <> 40 30 27 2 2 41 30 33 1 <> 42 30 34 1 <> 43 31 35 1 <> 44 35 37 2 2 45 36 38 1 <> 46 37 35 2 2 47 40 45 2 <> 48 40 46 1 <> 49 41 49 1 <> 50 41 54 1 1 51 42 43 2 <> 52 42 47 1 <> 53 42 48 1 <> 54 43 49 1 <> 55 43 50 1 <> 56 44 51 1 <> 57 44 52 1 <> 58 45 47 1 <> 59 46 48 1 <> 60 48 56 2 <> 61 50 55 2 <> 62 51 58 1 <> 63 52 53 1 <> 64 53 57 1 <> 65 54 41 1 1 66 55 56 1 <> 67 55 59 1 <> ::: } } coordgenlibs-3.0.2/test/metalZobs.mae000066400000000000000000000014141436654770400176110ustar00rootroot00000000000000{ s_m_m2io_version ::: 2.0.0 } f_m_ct { s_m_title s_m_entry_id s_m_entry_name i_m_ct_format ::: Structure1 1 entry 2 m_atom[6] { # First column is atom index # i_m_mmod_type r_m_x_coord r_m_y_coord r_m_z_coord i_m_color i_m_atomic_number s_m_color_rgb i_rdk_index ::: 1 158 0.000000 0.000000 0.000000 19 13 E11EE1 0 2 26 1.970000 0.000000 0.000000 43 7 5757FF 1 3 41 -0.801858 1.375985 -0.000000 21 1 FFFFFF <> 4 41 -0.801888 -1.375976 -0.000019 21 1 FFFFFF <> 5 43 2.307145 -0.952068 -0.000000 21 1 FFFFFF <> 6 43 2.307145 0.477048 -0.823929 21 1 FFFFFF <> ::: } m_bond[5] { # First column is bond index # i_m_from i_m_to i_m_order ::: 1 1 2 1 2 1 3 1 3 1 4 1 4 2 5 1 5 2 6 1 ::: } } coordgenlibs-3.0.2/test/nonterminalMetalZobs.mae000066400000000000000000000016111436654770400220170ustar00rootroot00000000000000{ s_m_m2io_version ::: 2.0.0 } f_m_ct { s_m_title s_m_entry_id s_m_entry_name s_m_Source_Path s_m_Source_File i_m_Source_File_Index i_m_ct_format ::: Structure1 1 entry /Users/nicola/schrodinger/coordgenlibs/test metalZobs.mae 1 2 m_atom[6] { # First column is atom index # i_m_mmod_type r_m_x_coord r_m_y_coord r_m_z_coord i_m_color i_m_atomic_number s_m_color_rgb i_rdk_index ::: 1 158 0.000000 0.000000 0.000000 19 13 E11EE1 0 2 26 1.970000 0.000000 0.000000 43 7 5757FF 1 3 41 -0.801858 1.375985 -0.000000 21 1 FFFFFF <> 4 41 -0.801888 -1.375976 -0.000019 21 1 FFFFFF <> 5 43 2.307145 -0.952068 -0.000000 21 1 FFFFFF <> 6 43 2.307145 0.477048 -0.823929 21 1 FFFFFF <> ::: } m_bond[5] { # First column is bond index # i_m_from i_m_to i_m_order ::: 1 1 2 1 2 1 3 1 3 1 4 1 4 2 5 1 5 2 6 1 ::: } } coordgenlibs-3.0.2/test/test.mae000066400000000000000000000032001436654770400166230ustar00rootroot00000000000000{ s_m_m2io_version ::: 2.0.0 } f_m_ct { s_m_title i_m_ct_format ::: "" 2 m_atom[26] { # First column is atom index # i_m_mmod_type r_m_x_coord r_m_y_coord r_m_z_coord i_m_color i_m_atomic_number ::: 1 16 0.000000 0.000000 0.000000 70 8 2 107 0.000000 0.000000 0.000000 15 15 3 15 0.000000 0.000000 0.000000 70 8 4 16 0.000000 0.000000 0.000000 70 8 5 16 0.000000 0.000000 0.000000 70 8 6 3 0.000000 0.000000 0.000000 2 6 7 2 0.000000 0.000000 0.000000 2 6 8 2 0.000000 0.000000 0.000000 2 6 9 2 0.000000 0.000000 0.000000 2 6 10 15 0.000000 0.000000 0.000000 70 8 11 2 0.000000 0.000000 0.000000 2 6 12 16 0.000000 0.000000 0.000000 70 8 13 2 0.000000 0.000000 0.000000 2 6 14 3 0.000000 0.000000 0.000000 2 6 15 25 0.000000 0.000000 0.000000 43 7 16 2 0.000000 0.000000 0.000000 2 6 17 42 0.000000 0.000000 0.000000 21 1 18 42 0.000000 0.000000 0.000000 21 1 19 41 0.000000 0.000000 0.000000 21 1 20 41 0.000000 0.000000 0.000000 21 1 21 41 0.000000 0.000000 0.000000 21 1 22 42 0.000000 0.000000 0.000000 21 1 23 41 0.000000 0.000000 0.000000 21 1 24 41 0.000000 0.000000 0.000000 21 1 25 41 0.000000 0.000000 0.000000 21 1 26 41 0.000000 0.000000 0.000000 21 1 ::: } m_bond[26] { # First column is bond index # i_m_from i_m_to i_m_order ::: 1 1 2 1 2 1 17 1 3 2 3 2 4 2 4 1 5 2 5 1 6 4 18 1 7 5 6 1 8 6 7 1 9 6 19 1 10 6 20 1 11 7 8 2 12 7 16 1 13 8 9 1 14 8 11 1 15 9 10 2 16 9 21 1 17 11 12 1 18 11 13 2 19 12 22 1 20 13 14 1 21 13 15 1 22 14 23 1 23 14 24 1 24 14 25 1 25 15 16 2 26 16 26 1 ::: } } coordgenlibs-3.0.2/test/testChirality.mae000066400000000000000000000016761436654770400205130ustar00rootroot00000000000000{ s_m_m2io_version ::: 2.0.0 } f_m_ct { s_m_title s_m_entry_id s_m_entry_name i_m_ct_format ::: Structure1 1 entry 2 m_atom[9] { # First column is atom index # i_m_mmod_type r_m_x_coord r_m_y_coord r_m_z_coord i_m_color i_m_atomic_number s_m_color_rgb i_rdk_index ::: 1 3 0.000000 0.000000 0.000000 2 6 A0A0A0 0 2 26 1.460000 0.000000 0.000000 43 7 5757FF 1 3 56 -0.430248 -0.615488 1.100130 8 9 00FF7F 2 4 16 -0.474027 -0.678116 -1.104471 70 8 FF2F2F 3 5 49 -0.611428 1.671693 0.000000 13 16 E1E11E 4 6 43 1.797145 0.476034 0.824515 21 1 FFFFFF <> 7 43 1.797145 -0.952068 -0.001171 21 1 FFFFFF <> 8 42 -0.173846 -1.629206 -1.177409 21 1 FFFFFF <> 9 41 -0.015792 1.940932 -1.165171 21 1 FFFFFF <> ::: } m_bond[8] { # First column is bond index # i_m_from i_m_to i_m_order ::: 1 1 2 1 2 1 3 1 3 1 4 1 4 1 5 1 5 2 6 1 6 2 7 1 7 4 8 1 8 5 9 1 ::: } } coordgenlibs-3.0.2/test/test_coordgen.cpp000066400000000000000000000552121436654770400205350ustar00rootroot00000000000000#define BOOST_TEST_MODULE Test_Coordgen #include #include #include #include "../CoordgenFragmenter.h" #include "../sketcherMinimizer.h" #include "../sketcherMinimizerMaths.h" #include "../sketcherMinimizerStretchInteraction.h" #include "../sketcherMinimizerBendInteraction.h" #include "../sketcherMaeReading.h" #include "coordgenBasicSMILES.h" #include "maeparser/MaeConstants.hpp" #include "maeparser/Reader.hpp" using std::unordered_set; using namespace schrodinger; const boost::filesystem::path test_samples_path(TEST_SAMPLES_PATH); namespace { std::map getReportingIndices(sketcherMinimizerMolecule& mol) { std::map fakeIndices; int index = 0; for (auto& atom : mol.getAtoms()) { fakeIndices.emplace(atom, ++index); } return fakeIndices; } bool areBondsNearIdeal(sketcherMinimizerMolecule& mol, std::map& indices, std::set > skip = std::set > ()) { const float targetBondLength = BONDLENGTH * BONDLENGTH; const auto tolerance = static_cast(targetBondLength * 0.1); bool passed = true; for (auto& bond : mol.getBonds()) { auto bondPair = std::pair (indices[bond->getStartAtom()], indices[bond->getEndAtom()]); if (skip.find(bondPair) != skip.end()) { continue; } auto& startCoordinates = bond->getStartAtom()->getCoordinates(); auto& endCoordinates = bond->getEndAtom()->getCoordinates(); const auto sq_distance = sketcherMinimizerMaths::squaredDistance( startCoordinates, endCoordinates); const auto deviation = sq_distance - targetBondLength; if (deviation < -tolerance || deviation > tolerance) { std::cerr << "Bond" << indices[bond->getStartAtom()] << '-' << indices[bond->getEndAtom()] << " has length " << sq_distance << " (" << targetBondLength << ")\n"; passed = false; } } return passed; } bool noCrossingBonds(sketcherMinimizerMolecule& mol, std::map& indices) { bool passed = true; for (auto& bond : mol.getBonds()) { for (auto& bond2 : mol.getBonds()) { if (bond == bond2) continue; if (bond->getStartAtom() == bond2->getStartAtom()) continue; if (bond->getStartAtom() == bond2->getEndAtom()) continue; if (bond->getEndAtom() == bond2->getStartAtom()) continue; if (bond->getEndAtom() == bond2->getEndAtom()) continue; auto& startCoordinates1 = bond->getStartAtom()->getCoordinates(); auto& endCoordinates1 = bond->getEndAtom()->getCoordinates(); auto& startCoordinates2 = bond2->getStartAtom()->getCoordinates(); auto& endCoordinates2 = bond2->getEndAtom()->getCoordinates(); if (sketcherMinimizerMaths::intersectionOfSegments(startCoordinates1, endCoordinates1, startCoordinates2, endCoordinates2)) { std::cerr << "Bond" << indices[bond->getStartAtom()] << '-' << indices[bond->getEndAtom()] << " intersects bond " << indices[bond2->getStartAtom()]<< '-' << indices[bond2->getEndAtom()]<<")\n"; passed = false; } } } return passed; } } // namespace static sketcherMinimizerMolecule* operator"" _smiles(const char * smiles, size_t len) { return approxSmilesParse({smiles, len}); } BOOST_AUTO_TEST_CASE(SampleTest) { // A small sample test showing how to import a molecule from a .mae file and // initialize the minimizer with it. const std::string testfile = (test_samples_path / "test.mae").string(); mae::Reader r(testfile); auto block = r.next(mae::CT_BLOCK); BOOST_REQUIRE(block != nullptr); auto* mol = mol_from_mae_block(*block); BOOST_REQUIRE(mol != nullptr); BOOST_REQUIRE_EQUAL(mol->getAtoms().size(), 26); BOOST_REQUIRE_EQUAL(mol->getBonds().size(), 26); sketcherMinimizer minimizer; minimizer.initialize(mol); // minimizer takes ownership of mol minimizer.runGenerateCoordinates(); for (auto& atom : mol->getAtoms()) { auto c = atom->getCoordinates(); // This is best we can do with checking: there are precision and // rounding issues depending on platform and environment. BOOST_CHECK(c.x() != 0 || c.y() != 0); } auto indices = getReportingIndices(*mol); BOOST_CHECK(areBondsNearIdeal(*mol, indices)); } BOOST_AUTO_TEST_CASE(TemplateTest) { /// // Do the structures in the templates file get the same coordinates that // were supplied in the templates file? const boost::filesystem::path source_dir(SOURCE_DIR); const std::string templates_file = (source_dir / "templates.mae").string(); // Known issues. See issue #52 const unordered_set no_match = {1, 8, 19, 20, 22, 32, 43, 53, 65, 66, 67}; // 32 is odd. minimization removes atoms?? But it matches?? const unordered_set match_incorrectly = {18, 27}; mae::Reader r(templates_file); std::shared_ptr b; size_t template_index = 0; while ((b = r.next(mae::CT_BLOCK)) != nullptr) { if (no_match.count(template_index) > 0) { ++template_index; continue; } auto* mol = mol_from_mae_block(*b); BOOST_REQUIRE(mol != nullptr); const auto original_atom_count = mol->getAtoms().size(); sketcherMinimizer minimizer; minimizer.setTemplateFileDir(source_dir.string()); minimizer.initialize(mol); // minimizer takes ownership of mol minimizer.runGenerateCoordinates(); BOOST_CHECK_EQUAL(original_atom_count, mol->getAtoms().size()); bool any_rigid = false; bool all_rigid = true; for (auto a: mol->getAtoms()) { if (a->rigid) { any_rigid = true; } else { all_rigid = false; } } const bool matches_incorrectly = match_incorrectly.count(template_index) > 0; if (!any_rigid) { BOOST_CHECK_MESSAGE(any_rigid, "No template found for " << template_index); } else if (!matches_incorrectly) { BOOST_CHECK_MESSAGE(all_rigid, "Not all atoms templated for " << template_index); } ++template_index; } } BOOST_AUTO_TEST_CASE(ClearWedgesTest) { // test that when writing stereochemistry we first clear the existing one const std::string testfile = (test_samples_path / "testChirality.mae").string(); mae::Reader r(testfile); auto block = r.next(mae::CT_BLOCK); BOOST_REQUIRE(block != nullptr); auto* mol = mol_from_mae_block(*block); BOOST_REQUIRE(mol != nullptr); /*set wedges on all bonds*/ mol->getBonds().at(0)->hasStereochemistryDisplay = true; mol->getBonds().at(1)->hasStereochemistryDisplay = true; mol->getBonds().at(2)->hasStereochemistryDisplay = true; mol->getBonds().at(3)->hasStereochemistryDisplay = true; /*set chirality on the atom*/ auto carbon = mol->getAtoms().at(0); BOOST_REQUIRE_EQUAL(carbon->atomicNumber, 6); carbon->hasStereochemistrySet = true; carbon->isR = true; /*run minimization*/ sketcherMinimizer minimizer; minimizer.initialize(mol); // minimizer takes ownership of mol minimizer.runGenerateCoordinates(); /*make sure that previous wedges are reset and only 2 are now used*/ BOOST_REQUIRE_EQUAL(mol->getBonds().at(0)->hasStereochemistryDisplay, false); BOOST_REQUIRE_EQUAL(mol->getBonds().at(1)->hasStereochemistryDisplay, true); BOOST_REQUIRE_EQUAL(mol->getBonds().at(2)->hasStereochemistryDisplay, false); BOOST_REQUIRE_EQUAL(mol->getBonds().at(3)->hasStereochemistryDisplay, true); } BOOST_AUTO_TEST_CASE(DisableMetalZOBs) { // Load a molecule with a single bond to a metal. Make sure that disabling the automatic conversion // to zob behaves as expected const std::string testfile = (test_samples_path / "nonterminalMetalZobs.mae").string(); mae::Reader r(testfile); auto block = r.next(mae::CT_BLOCK); BOOST_REQUIRE(block != nullptr); auto* mol = mol_from_mae_block(*block); BOOST_REQUIRE(mol != nullptr); sketcherMinimizer minimizer; minimizer.setTreatNonterminalBondsToMetalAsZOBs(false); auto Al = mol->getAtoms().at(0); auto N = mol->getAtoms().at(1); //make sure we got the right atoms BOOST_REQUIRE_EQUAL(Al->atomicNumber, 13); BOOST_REQUIRE_EQUAL(N->atomicNumber, 7); minimizer.initialize(mol); // minimizer takes ownership of mol minimizer.runGenerateCoordinates(); auto bondLength = (Al->coordinates - N->coordinates).length(); auto expectedLength = 50.f; auto tolerance = 2.f; BOOST_REQUIRE ((bondLength > expectedLength-tolerance) && (bondLength < expectedLength+tolerance)); auto indices = getReportingIndices(*mol); BOOST_CHECK(areBondsNearIdeal(*mol, indices)); } BOOST_AUTO_TEST_CASE(terminalMetalZOBs) { // Load a molecule with a single bond to a terminal metal. Make sure the bondlength is consistant with a terminal bond const std::string testfile = (test_samples_path / "metalZobs.mae").string(); mae::Reader r(testfile); auto block = r.next(mae::CT_BLOCK); BOOST_REQUIRE(block != nullptr); auto* mol = mol_from_mae_block(*block); BOOST_REQUIRE(mol != nullptr); sketcherMinimizer minimizer; auto Al = mol->getAtoms().at(0); auto N = mol->getAtoms().at(1); //make sure we got the right atoms BOOST_REQUIRE_EQUAL(Al->atomicNumber, 13); BOOST_REQUIRE_EQUAL(N->atomicNumber, 7); minimizer.initialize(mol); // minimizer takes ownership of mol minimizer.runGenerateCoordinates(); auto bondLength = (Al->coordinates - N->coordinates).length(); auto expectedLength = 50.f; auto tolerance = 2.f; BOOST_REQUIRE ((bondLength > expectedLength-tolerance) && (bondLength < expectedLength+tolerance)); auto indices = getReportingIndices(*mol); BOOST_CHECK(areBondsNearIdeal(*mol, indices)); } BOOST_AUTO_TEST_CASE(testMinimizedRingsShape) { // minimize a complex macrocycle. Make sure rings have the shape of regular polygons const std::string testfile = (test_samples_path / "macrocycle.mae").string(); mae::Reader r(testfile); auto block = r.next(mae::CT_BLOCK); BOOST_REQUIRE(block != nullptr); auto* mol = mol_from_mae_block(*block); BOOST_REQUIRE(mol != nullptr); sketcherMinimizer minimizer; minimizer.initialize(mol); // minimizer takes ownership of mol minimizer.runGenerateCoordinates(); //check the length of every non macrocycle-ring bond int bondsN = 0; for (auto interaction : minimizer.getStretchInteractions()) { auto ring = sketcherMinimizer::sameRing(interaction->atom1, interaction->atom2); if (ring && !ring->isMacrocycle()) { auto expectedLength = 50.f; auto tolerance = 2.f; auto bondLength = (interaction->atom1->coordinates - interaction->atom2->coordinates).length(); BOOST_REQUIRE ((bondLength > expectedLength-tolerance) && (bondLength < expectedLength+tolerance)); bondsN++; } } // check the angles int anglesN = 0; for (auto interaction : minimizer.getBendInteractions()) { if (interaction->isRing) { auto ring = sketcherMinimizer::sameRing(interaction->atom1, interaction->atom2, interaction->atom3); BOOST_REQUIRE (ring != nullptr); BOOST_REQUIRE (!ring->isMacrocycle()); auto expectedValue = interaction->restV; auto tolerance = 2.f; auto angle = interaction->angle(); BOOST_REQUIRE ((angle > expectedValue-tolerance) && (angle < expectedValue+tolerance)); anglesN++; } } BOOST_REQUIRE (anglesN == 32); } BOOST_AUTO_TEST_CASE(testPolyominoCoordinatesOfSubstituent) { Polyomino p; p.addHex(hexCoords(0, 0)); auto substCoords = p.coordinatesOfSubstituent(vertexCoords(1, 0, 0)); BOOST_REQUIRE(substCoords == vertexCoords(1, -1, -1)); p.addHex(hexCoords(1, 0)); substCoords = p.coordinatesOfSubstituent(vertexCoords(1, 0, 0)); BOOST_REQUIRE(substCoords == vertexCoords(0, 0, -1)); } BOOST_AUTO_TEST_CASE(testPolyominoSameAs) { // identity Polyomino p1; p1.addHex(hexCoords(0, 0)); p1.addHex(hexCoords(1, 0)); p1.addHex(hexCoords(2, 0)); p1.addHex(hexCoords(0, 1)); BOOST_REQUIRE(p1.isTheSameAs(p1)); // order-independence Polyomino p2; p2.addHex(hexCoords(2, 0)); p2.addHex(hexCoords(0, 0)); p2.addHex(hexCoords(0, 1)); p2.addHex(hexCoords(1, 0)); BOOST_REQUIRE(p1.isTheSameAs(p2)); BOOST_REQUIRE(p2.isTheSameAs(p1)); // translation Polyomino p3; p3.addHex(hexCoords(4, 2)); p3.addHex(hexCoords(5, 2)); p3.addHex(hexCoords(6, 2)); p3.addHex(hexCoords(4, 3)); BOOST_REQUIRE(p1.isTheSameAs(p3)); BOOST_REQUIRE(p3.isTheSameAs(p1)); // rotation Polyomino p4; p4.addHex(hexCoords(0, 0)); p4.addHex(hexCoords(-1, 0)); p4.addHex(hexCoords(-2, 0)); p4.addHex(hexCoords(0, -1)); BOOST_REQUIRE(p1.isTheSameAs(p4)); BOOST_REQUIRE(p4.isTheSameAs(p1)); // symmetry Polyomino p5; p5.addHex(hexCoords(0, 0)); p5.addHex(hexCoords(0, 1)); p5.addHex(hexCoords(0, 2)); p5.addHex(hexCoords(1, 0)); BOOST_REQUIRE(!p1.isTheSameAs(p5)); BOOST_REQUIRE(!p5.isTheSameAs(p1)); // different number of points Polyomino p6; p6.addHex(hexCoords(1, 0)); p6.addHex(hexCoords(2, 0)); p6.addHex(hexCoords(0, 1)); BOOST_REQUIRE(!p1.isTheSameAs(p6)); BOOST_REQUIRE(!p6.isTheSameAs(p1)); } BOOST_AUTO_TEST_CASE(testGetDoubleBondConstraints) { /* test that getDoubleBondConstraints behaves as expected: notably don't set up interactions for double bonds that are also part of a small ring. CRDGEN-160 */ sketcherMinimizer min; CoordgenFragmentBuilder fragmentBuilder; CoordgenMacrocycleBuilder macrocycleBuilder; const std::string testfile = (test_samples_path / "test_mol.mae").string(); mae::Reader r(testfile); auto block = r.next(mae::CT_BLOCK); BOOST_REQUIRE(block != nullptr); auto* mol = mol_from_mae_block(*block); BOOST_REQUIRE(mol != nullptr); min.initialize(mol); // minimizer takes ownership of mol for (auto molecule : min.getMolecules()) { for (auto ring : molecule->getRings()) { std::vector atoms = fragmentBuilder.orderRingAtoms(ring); std::vector constraints = macrocycleBuilder.getDoubleBondConstraints(atoms); BOOST_REQUIRE(constraints.empty()); } } } BOOST_AUTO_TEST_CASE(testClockwiseOrderedSubstituents) { auto mol = "CN(C)C"_smiles; sketcherMinimizer minimizer; minimizer.initialize(mol); // minimizer takes ownership of mol minimizer.runGenerateCoordinates(); const auto& atoms = minimizer.getAtoms(); sketcherMinimizerAtom* center = atoms.at(0); sketcherMinimizerAtom* neigh1 = atoms.at(1); sketcherMinimizerAtom* neigh2 = atoms.at(2); sketcherMinimizerAtom* neigh3 = atoms.at(3); BOOST_REQUIRE_EQUAL(center->getAtomicNumber(), 7); sketcherMinimizerPointF origin(0, 0); sketcherMinimizerPointF above(0, 50); sketcherMinimizerPointF left(-50, 0); sketcherMinimizerPointF right(50, 0); center->coordinates = origin; neigh1->coordinates = above; neigh2->coordinates = left; neigh3->coordinates = right; auto orderedNeighbors = center->clockwiseOrderedNeighbors(); BOOST_REQUIRE((orderedNeighbors[0]->coordinates - above).length() == 0); BOOST_REQUIRE((orderedNeighbors[1]->coordinates - left).length() == 0); BOOST_REQUIRE((orderedNeighbors[2]->coordinates - right).length() == 0); BOOST_REQUIRE_EQUAL(orderedNeighbors[0], neigh1); BOOST_REQUIRE_EQUAL(orderedNeighbors[1], neigh2); BOOST_REQUIRE_EQUAL(orderedNeighbors[2], neigh3); neigh1->coordinates = above; neigh3->coordinates = left; neigh2->coordinates = right; orderedNeighbors = center->clockwiseOrderedNeighbors(); BOOST_REQUIRE((orderedNeighbors[0]->coordinates - above).length() == 0); BOOST_REQUIRE((orderedNeighbors[1]->coordinates - left).length() == 0); BOOST_REQUIRE((orderedNeighbors[2]->coordinates - right).length() == 0); BOOST_REQUIRE_EQUAL(orderedNeighbors[0], neigh1); BOOST_REQUIRE_EQUAL(orderedNeighbors[1], neigh3); BOOST_REQUIRE_EQUAL(orderedNeighbors[2], neigh2); } BOOST_AUTO_TEST_CASE(testClockwiseOrderedNaN) { std::unique_ptr mol("CN(C)C"_smiles); auto& atoms = mol->getAtoms(); sketcherMinimizerAtom* center = atoms.at(0); sketcherMinimizerAtom* neigh1 = atoms.at(1); neigh1->coordinates = sketcherMinimizerPointF(std::nanf("name"), std::nanf("name")); const auto orderedNeighbors = center->clockwiseOrderedNeighbors(); // We usually allow the sketcher minimizer to clean up bonds & atoms, // but we don't have a minimizer here for (auto& bond : mol->getBonds()) { delete bond; } for (auto& atom : atoms) { delete atom; } } BOOST_AUTO_TEST_CASE(testbicyclopentane) { /* test that bicyclo(1,1,1)pentane is rendered without clashes between the bridge carbons CRDGEN-270 */ auto mol = "C1C2CC1C2"_smiles; sketcherMinimizer minimizer; minimizer.initialize(mol); // minimizer takes ownership of mol minimizer.runGenerateCoordinates(); const auto& atoms = minimizer.getAtoms(); auto bridgeAtom1 = atoms.at(1); auto bridgeAtom2 = atoms.at(2); auto bridgeAtom3 = atoms.at(3); BOOST_TEST(bridgeAtom1->neighbors.size() == 2); BOOST_TEST(bridgeAtom2->neighbors.size() == 2); BOOST_TEST(bridgeAtom3->neighbors.size() == 2); auto distance1 = (bridgeAtom1->getCoordinates() - bridgeAtom2->getCoordinates()).length(); auto distance2 = (bridgeAtom1->getCoordinates() - bridgeAtom3->getCoordinates()).length(); auto distance3 = (bridgeAtom2->getCoordinates() - bridgeAtom3->getCoordinates()).length(); auto minimumDistance = 15.f; BOOST_TEST(distance1 > minimumDistance); BOOST_TEST(distance2 > minimumDistance); BOOST_TEST(distance3 > minimumDistance); } BOOST_AUTO_TEST_CASE(testFusedRings) { /* CRDGEN271, CRDGEN-272 */ std::vector smiles {"C1CCC23CCCCC2CC3C1", "C1=CC2C3CC4C(CC3NC3CCCC(C32)N1)NC1CCCC2C1C4CCN2"}; for (auto smile : smiles) { auto mol = approxSmilesParse(smile); sketcherMinimizer minimizer; minimizer.initialize(mol); // minimizer takes ownership of mol minimizer.runGenerateCoordinates(); auto indices = getReportingIndices(*mol); BOOST_CHECK(areBondsNearIdeal(*mol, indices)); BOOST_CHECK(noCrossingBonds(*mol, indices)); } } BOOST_AUTO_TEST_CASE(testTemplates) { auto mol = "C12CC3CC(CC3C1)C2"_smiles; sketcherMinimizer minimizer; minimizer.initialize(mol); // minimizer takes ownership of mol minimizer.runGenerateCoordinates(); auto indices = getReportingIndices(*mol); //template has two stretched bonds std::set > skip; skip.insert(std::pair (2, 5)); skip.insert(std::pair (6, 2)); BOOST_CHECK(areBondsNearIdeal(*mol, indices, skip)); } BOOST_AUTO_TEST_CASE(testRingComplex) { auto mol = "CC1CC2CCCC(C3CC4CCC(C3)C4C)C2O1"_smiles; sketcherMinimizer minimizer; minimizer.initialize(mol); // minimizer takes ownership of mol minimizer.runGenerateCoordinates(); auto indices = getReportingIndices(*mol); BOOST_CHECK(noCrossingBonds(*mol, indices)); } BOOST_AUTO_TEST_CASE(testCoordgenFragmenter) { /* Test that a molecule is fragmented as expected and fragments are given the correct flags. Atoms 3-8 and 11 are constrained. 6 / \ 1 -- 2 -- 3 -- 4 -- 5 7 -- 8 -- 9 -- 10 \ / 11 */ auto mol = "CCCCC1CC(CCC)C1"_smiles; auto atoms = mol->getAtoms(); for (int i = 3; i <= 8; ++i) { atoms[i-1]->constrained = true; } atoms[10]->constrained = true; auto atom_map = getReportingIndices(*mol); sketcherMinimizer minimizer; minimizer.initialize(mol); CoordgenFragmenter::splitIntoFragments(mol); std::vector> expected_fragments = {{1, 2}, {3}, {4}, {5, 6, 7, 11}, {8}, {9, 10}}; std::vector> actual_fragments; for (auto fragment : mol->_fragments) { std::set fragment_idices; for (auto at : fragment->getAtoms()) { fragment_idices.insert(atom_map[at]); } actual_fragments.push_back(fragment_idices); } std::sort(actual_fragments.begin(), actual_fragments.end()); // Check that the fragmenting is correct BOOST_REQUIRE_EQUAL(actual_fragments.size(), expected_fragments.size()); for (size_t i = 0; i < actual_fragments.size(); ++i) { BOOST_CHECK_EQUAL_COLLECTIONS(expected_fragments[i].begin(), expected_fragments[i].end(), actual_fragments[i].begin(), actual_fragments[i].end()); } // Fragment containing atoms (1, 2) BOOST_TEST(atoms[0]->fragment->constrained == false); BOOST_TEST(atoms[0]->fragment->constrainedFlip == false); // Fragment containing atom 3. Flip should not be constrained since // the fragment does not have any constrained child fragments BOOST_TEST(atoms[2]->fragment->constrained == true); BOOST_TEST(atoms[2]->fragment->constrainedFlip == false); // Fragment containing atom 4. Flip should be constrained since fragment // has a child fragment that is constrained BOOST_TEST(atoms[3]->fragment->constrained == true); BOOST_TEST(atoms[3]->fragment->constrainedFlip == true); // Fragment containing atoms (5, 6, 7, 11) BOOST_TEST(atoms[4]->fragment->constrained == true); BOOST_TEST(atoms[4]->fragment->constrainedFlip == true); // Fragment containing atom 8 BOOST_TEST(atoms[7]->fragment->constrained == true); BOOST_TEST(atoms[7]->fragment->constrainedFlip == false); // Fragment containing atoms (9, 10) BOOST_TEST(atoms[8]->fragment->constrained == false); BOOST_TEST(atoms[8]->fragment->constrainedFlip == false); for (auto& fragment : mol->_fragments) { delete fragment; } } coordgenlibs-3.0.2/test/test_mol.mae000066400000000000000000000045351436654770400175060ustar00rootroot00000000000000{ s_m_m2io_version ::: 2.0.0 } f_m_ct { s_m_title i_m_ct_stereo_status s_st_Chirality_1 s_st_Chirality_2 i_m_ct_format ::: Untitled_Molecule_000001 1 5_R_4_7_6 10_R_9_11_13 2 m_depend[2] { # First column is dependency index # i_m_depend_dependency s_m_depend_property ::: 1 10 s_st_Chirality_1 2 10 s_st_Chirality_2 ::: } m_atom[27] { # First column is atom index # i_m_mmod_type r_m_x_coord r_m_y_coord r_m_z_coord i_m_residue_number i_m_color i_m_atomic_number i_sd_original_parity ::: 1 5 -2.791812 1.972102 0.000000 900 2 6 <> 2 2 -1.665230 2.611009 0.000000 900 2 6 <> 3 15 -1.657448 3.908277 0.000000 900 70 8 <> 4 29 -0.545392 1.956279 0.000000 900 43 7 <> 5 4 0.581190 2.599076 0.000000 900 2 6 2 6 6 0.587415 3.895826 0.000000 900 2 6 <> 7 2 1.701806 1.945643 0.000000 900 2 6 <> 8 15 2.827350 2.589997 0.000000 900 70 8 <> 9 29 1.697396 0.648634 0.000000 900 43 7 <> 10 4 2.818789 -0.002724 0.000000 900 2 6 1 11 7 3.943815 0.642409 0.000000 900 2 6 <> 12 15 3.947187 1.939418 0.000000 900 70 8 <> 13 5 2.813342 -1.301289 0.000000 900 2 6 <> 14 2 1.701027 -1.938120 0.000000 900 2 6 <> 15 7 1.673531 -3.242393 0.000000 900 2 6 <> 16 7 0.553174 -3.908277 0.000000 900 2 6 <> 17 2 -0.565366 -3.229682 0.000000 900 2 6 <> 18 17 -1.702843 -3.880002 0.000000 900 70 8 <> 19 7 0.559919 -1.298436 0.000000 900 2 6 <> 20 2 -0.582746 -1.925410 0.000000 900 2 6 <> 21 2 -1.688835 -1.280018 0.000000 900 2 6 <> 22 7 -1.659004 0.022179 0.000000 900 2 6 <> 23 2 -2.814120 -1.949015 0.000000 900 2 6 <> 24 17 -2.819827 -3.232795 0.000000 900 70 8 <> 25 7 -3.930326 -1.271458 0.000000 900 2 6 <> 26 7 -3.947187 0.030999 0.000000 900 2 6 <> 27 2 -2.798815 0.659529 0.000000 900 2 6 <> ::: } m_bond[31] { # First column is bond index # i_m_from i_m_to i_m_order i_sd_original_parity ::: 1 1 27 1 <> 2 1 2 1 <> 3 2 3 2 <> 4 2 4 1 <> 5 4 5 1 <> 6 5 6 1 6 7 5 7 1 <> 8 6 5 1 6 9 7 8 2 <> 10 7 9 1 <> 11 9 10 1 <> 12 10 11 1 1 13 10 13 1 <> 14 11 10 1 1 15 11 12 2 <> 16 13 14 1 <> 17 14 15 2 <> 18 14 19 1 <> 19 15 16 1 <> 20 16 17 2 <> 21 17 20 1 <> 22 17 18 1 <> 23 19 20 2 <> 24 20 21 1 <> 25 21 22 2 <> 26 21 23 1 <> 27 22 27 1 <> 28 23 24 1 <> 29 23 25 2 <> 30 25 26 1 <> 31 26 27 2 <> ::: } } coordgenlibs-3.0.2/test/test_smilesparser.cpp000066400000000000000000000027241436654770400214460ustar00rootroot00000000000000#define BOOST_TEST_MODULE Test_smilesparser #include #include #include "../sketcherMinimizer.h" #include "coordgenBasicSMILES.h" using namespace schrodinger; static std::unique_ptr operator"" _smiles(const char * smiles, size_t len) { return std::unique_ptr(approxSmilesParse({smiles, len})); } BOOST_AUTO_TEST_CASE(Basics) { auto mol = "CCCC"_smiles; BOOST_TEST(mol->getAtoms().size() == 4); mol = "CNO"_smiles; auto& atoms = mol->getAtoms(); auto c = atoms[0]; auto n = atoms[1]; auto o = atoms[2]; BOOST_TEST(c->getAtomicNumber() == 6); BOOST_TEST(n->getAtomicNumber() == 7); BOOST_TEST(o->getAtomicNumber() == 8); BOOST_TEST(c->isNeighborOf(n)); BOOST_TEST(n->isNeighborOf(o)); BOOST_TEST(!c->isNeighborOf(o)); } BOOST_AUTO_TEST_CASE(Rings) { // 4 membered ring with a tail auto mol = "C1CCC1C"_smiles; BOOST_TEST(mol->getAtoms().size() == 5); BOOST_TEST(mol->getBonds().size() == 5); BOOST_TEST(mol->getAtoms()[0]->isNeighborOf(mol->getAtoms()[3])); } BOOST_AUTO_TEST_CASE(Branching) { auto mol = "CC(C)(C)C"_smiles; BOOST_TEST(mol->getAtoms()[1]->getBonds().size() == 4); mol = "CC(C)(CC)C"_smiles; BOOST_TEST(mol->getAtoms()[3]->getBonds().size() == 2); } BOOST_AUTO_TEST_CASE(BondOrder) { auto mol = "C=C"_smiles; BOOST_TEST(mol->getBonds()[0]->getBondOrder() == 2); }coordgenlibs-3.0.2/xcshareddata/000077500000000000000000000000001436654770400166415ustar00rootroot00000000000000coordgenlibs-3.0.2/xcshareddata/xcschemes/000077500000000000000000000000001436654770400206235ustar00rootroot00000000000000coordgenlibs-3.0.2/xcshareddata/xcschemes/coordgen_standalone.xcscheme000066400000000000000000000100131436654770400263470ustar00rootroot00000000000000