pax_global_header00006660000000000000000000000064135117041260014512gustar00rootroot0000000000000052 comment=e3457fb7bd5ff9e9f70722a7bfbc08b7054ca283 coordgenlibs-1.3/000077500000000000000000000000001351170412600140275ustar00rootroot00000000000000coordgenlibs-1.3/.clang-format000066400000000000000000000035271351170412600164110ustar00rootroot00000000000000--- 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-1.3/.gitignore000066400000000000000000000000551351170412600160170ustar00rootroot00000000000000*.build *.pro *.swp *.xc* Debug build qt*.mk coordgenlibs-1.3/.travis.yml000066400000000000000000000014141351170412600161400ustar00rootroot00000000000000sudo: false language: cpp before_script: - git clone https://github.com/schrodinger/maeparser.git - mkdir maeparser/build - pushd maeparser/build - cmake .. -DCMAKE_INSTALL_PREFIX=$TRAVIS_BUILD_DIR/installation -DCMAKE_BUILD_TYPE=Debug - make install - popd script: - mkdir build - cd build - export CXX="g++-4.8" - export CMAKE_PREFIX_PATH=$TRAVIS_BUILD_DIR/installation/lib/cmake - cmake .. -DCMAKE_BUILD_TYPE=Debug - make - ctest -V -T memcheck --output-on-failure || (cat Testing/Temporary/MemoryChecker.*.log && exit 29) addons: apt: sources: - george-edison55-precise-backports - ubuntu-toolchain-r-test packages: - cmake - cmake-data - gcc-4.8 - g++-4.8 - libboost-all-dev - valgrind coordgenlibs-1.3/CMakeLists.txt000066400000000000000000000044001351170412600165650ustar00rootroot00000000000000cmake_minimum_required(VERSION 3.2) project(coordgen) # Options & Project configuration set(CMAKE_CXX_STANDARD 11) option(COORDGEN_BUILD_TESTS "Whether test executables should be built" ON) option(COORDGEN_BUILD_EXAMPLE "Whether to build the sample executable" ON) # Dependencies find_package(Boost COMPONENTS iostreams REQUIRED) find_package(maeparser REQUIRED) # Source files & headers file(GLOB SOURCES "*.cpp") include_directories(${Boost_INCLUDE_DIRS}) include_directories(${maeparser_INCLUDE_DIRS}) # Build Targets & Configuration -- coordgen library add_library(coordgen SHARED ${SOURCES}) target_compile_definitions(coordgen PRIVATE IN_COORDGEN) set_property(TARGET coordgen PROPERTY CXX_VISIBILITY_PRESET "hidden") target_link_libraries(coordgen maeparser) set_target_properties(coordgen PROPERTIES VERSION 1.3 SOVERSION 1 ) # Install configuration install(TARGETS coordgen EXPORT coordgen-targets ARCHIVE DESTINATION lib RUNTIME DESTINATION bin LIBRARY DESTINATION lib) 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(FILES templates.mae DESTINATION share/coordgen) install(EXPORT coordgen-targets FILE ${PROJECT_NAME}-config.cmake DESTINATION lib/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-1.3/CoordgenConfig.hpp000066400000000000000000000005311351170412600174250ustar00rootroot00000000000000#pragma once #ifndef STATIC_COORDGEN #ifdef IN_COORDGEN #ifdef WIN32 #define EXPORT_COORDGEN __declspec(dllexport) #else #define EXPORT_COORDGEN __attribute__((visibility("default"))) #endif #else #ifdef WIN32 #define EXPORT_COORDGEN __declspec(dllimport) #else #define EXPORT_COORDGEN #endif #endif #else #define EXPORT_COORDGEN #endif coordgenlibs-1.3/CoordgenFragmentBuilder.cpp000066400000000000000000001135671351170412600213030ustar00rootroot00000000000000/* Contributors: Nicola Zonta Copyright Schrodinger, LLC. All rights reserved */ #include "CoordgenFragmentBuilder.h" #include "CoordgenMinimizer.h" #include "sketcherMinimizerFragment.h" #include "sketcherMinimizer.h" #include #include 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; void CoordgenFragmentBuilder::initializeCoordinates( sketcherMinimizerFragment* fragment) const { assert(fragment->getAtoms().size()); 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.size() > 0) { 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 (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 = 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.size() > 0) 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 = rings.at(0); int high_score = -1; for (sketcherMinimizerRing* r : rings) { int priority = 0; if (r->isMacrocycle()) priority += 1000; if (r->_atoms.size() == 6) priority += 100; priority += r->_atoms.size(); priority += 10 * (r->fusedWith.size()); if (priority > high_score) { highest = r; high_score = priority; } } 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.size() != 0) { 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) == NULL) { 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 += 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.size()) { sketcherMinimizerRing* ring = sideRings.top(); sideRings.pop(); buildRing(ring); } } sketcherMinimizerRing* CoordgenFragmentBuilder::getSharedAtomsWithAlreadyDrawnRing( const sketcherMinimizerRing* ring, vector& fusionAtoms, sketcherMinimizerBond*& fusionBond) const { sketcherMinimizerRing* parent = NULL; for (unsigned int i = 0; i < ring->fusedWith.size(); i++) { if (ring->fusedWith[i]->coordinatesGenerated) { if (!parent) parent = ring->fusedWith[i]; else { if (ring->fusedWith[i]->_atoms.size() > parent->_atoms.size()) parent = ring->fusedWith[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 = NULL; sketcherMinimizerBond* fusionBond = NULL; 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 = NULL; sketcherMinimizerAtom* pivotAtomOnParent = NULL; if (!fusionAtoms.empty()) { pivotAtom = fusionAtoms.at(0); pivotAtomOnParent = fusionAtoms.at(0); } else { assert(fusionBond != NULL); 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 (unsigned int i = 0; i < coords.size(); i++) { coords[i] -= coordinatesOfPivotAtom; } sketcherMinimizerPointF center = accumulate(coords.begin(), coords.end(), sketcherMinimizerPointF(0, 0)) / coords.size(); center.normalize(); int neighborsN = 0; sketcherMinimizerPointF neighborsMean(0.f, 0.f); for (sketcherMinimizerAtom* neighbor : pivotAtomOnParent->neighbors) { if (parent->containsAtom(neighbor)) { neighborsMean += neighbor->getCoordinates(); ++neighborsN; } } assert(neighborsN == 2); neighborsMean *= 0.5; sketcherMinimizerPointF pivotAtomCoordinates = pivotAtomOnParent->getCoordinates(); sketcherMinimizerPointF direction = pivotAtomCoordinates - neighborsMean; direction.normalize(); sketcherMinimizerPointF bondVector(0.f, 0.f); if (fusionBond != NULL) { bondVector = direction * bondLength; } for (unsigned int i = 0; i < coords.size(); i++) { sketcherMinimizerPointF coordinates = coords[i]; coordinates.rotate(center.y(), center.x()); coordinates.rotate(-direction.y(), direction.x()); coords[i] = 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 (unsigned int i = 0; i < coords2.size(); i++) { coords2[i] = sketcherMinimizerPointF(coords2[i].x(), -coords2[i].y()); } map map1, map2; for (unsigned int i = 0; i < atoms.size(); i++) { map1[atoms[i]] = coords[i]; map2[atoms[i]] = coords2[i]; } int 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 (unsigned int i = 0; i < fusionAtoms.size(); i++) fusionMap[fusionAtoms[i]] = 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]); } // TODO forbid if double bond to ring if (ring->fusedWith.size() == 1 && (*fusionAtoms.begin())->hasNoStereoActiveBonds() && (*fusionAtoms.rbegin())->hasNoStereoActiveBonds()) { CoordgenFlipRingDOF* dof = new CoordgenFlipRingDOF(ring, fusionAtoms); ring->getAtoms().at(0)->fragment->addDof(dof); } } } 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.size()); float a = 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.size()) { generateCoordinatesNeighborsOfFirstAtomInQueue(q, isAtomVisited, fragment); } } vector CoordgenFragmentBuilder::neighborsAnglesAtCenter( const sketcherMinimizerAtom* atom) const { int 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(M_PI / 3); angles.push_back(M_PI * 0.5); angles.push_back(2 * M_PI / 3); angles.push_back(M_PI * 0.5); } } if (!angles.size()) { for (unsigned int i = 0; i < atom->neighbors.size(); i++) { angles.push_back(2 * M_PI / angleDivision); } } return angles; } void CoordgenFragmentBuilder::initializeVariablesForNeighboursCoordinates( sketcherMinimizerAtom* atom, set& isAtomVisited, sketcherMinimizerPointF& startCoordinates, vector& orderedNeighbors, vector& angles) const { if (atom->rings.size()) { return initializeVariablesForNeighboursCoordinatesRingAtom( atom, isAtomVisited, startCoordinates, orderedNeighbors, angles); } orderedNeighbors.clear(); if (atom->neighbors.size() != 4) { orderedNeighbors = atom->neighbors; } else { vector atomPriorities; for (unsigned int i = 0; i < atom->neighbors.size(); i++) { sketcherMinimizerAtomPriority p; p.a = atom->neighbors[i]; 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 += 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 += 2 * M_PI; gaps.push_back(gap); bool rin = false; float mid = ringNeighboursAndAngles[i].first + gap * 0.5; float sine = sin(-mid); float cosine = cos(-mid); sketcherMinimizerPointF p(bondLength * 0.1, 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; else if (rin) scaledGap *= 0.2; 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()) { CoordgenScaleAtomsDOF* 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)) { CoordgenInvertBondDOF* 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 = NULL; 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 == NULL) return; if (atomsToMirror.size() && doubleBond) { sketcherMinimizerAtom* firstCIPNeighborStart = doubleBond->startAtomCIPFirstNeighbor(); if (firstCIPNeighborStart == NULL) return; sketcherMinimizerAtom* firstCIPNeighborEnd = doubleBond->endAtomCIPFirstNeighbor(); if (firstCIPNeighborEnd == NULL) 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 = NULL; 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 != NULL); 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 (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-1.3/CoordgenFragmentBuilder.h000066400000000000000000000151041351170412600207340ustar00rootroot00000000000000/* Contributors: Nicola Zonta Copyright Schrodinger, LLC. All rights reserved */ #ifndef COORDGEN_FRAGMENT_BUILDER_H #define COORDGEN_FRAGMENT_BUILDER_H #include #include #include #include #include #include #include "CoordgenMacrocycleBuilder.h" #include "CoordgenConfig.hpp" 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& orderedNeighbours, 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& orderedNeighbours, 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-1.3/CoordgenFragmenter.cpp000066400000000000000000000336571351170412600203240ustar00rootroot00000000000000/* Contributors: Nicola Zonta Copyright Schrodinger, LLC. All rights reserved */ #include "CoordgenFragmenter.h" #include "sketcherMinimizerMolecule.h" #include "sketcherMinimizerAtom.h" #include "sketcherMinimizerBond.h" #include "sketcherMinimizerRing.h" #include "sketcherMinimizerFragment.h" #include "sketcherMinimizerMaths.h" #include #include using namespace std; void CoordgenFragmenter::splitIntoFragments(sketcherMinimizerMolecule* molecule) { /* split input molecule into rigid fragments */ vector fragments; foreach (sketcherMinimizerAtom* atom, molecule->getAtoms()) { atom->setFragment(NULL); } /* molecule with a single atom and no bonds */ if (molecule->getAtoms().size() == 1) { sketcherMinimizerFragment* fragment = new sketcherMinimizerFragment(); sketcherMinimizerAtom* onlyAtom = molecule->getAtoms().at(0); fragment->addAtom(onlyAtom); fragments.push_back(fragment); } foreach (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() != NULL); } #endif if (fragments.size()) { 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() == NULL) { sketcherMinimizerFragment* fragment = new sketcherMinimizerFragment(); fragment->addAtom(bond->getStartAtom()); fragments.push_back(fragment); } if (bond->getEndAtom()->getFragment() == NULL) { sketcherMinimizerFragment* fragment = new sketcherMinimizerFragment(); fragment->addAtom(bond->getEndAtom()); fragments.push_back(fragment); } } void CoordgenFragmenter::processBondInternalToFragment( sketcherMinimizerBond* bond, vector& fragments) { if (bond->getStartAtom()->getFragment() == NULL && bond->getEndAtom()->getFragment() == NULL) { /* add the two atoms to a new fragment */ sketcherMinimizerFragment* fragment = new sketcherMinimizerFragment(); fragment->addAtom(bond->getStartAtom()); fragment->addAtom(bond->getEndAtom()); fragments.push_back(fragment); } else if (bond->getEndAtom()->getFragment() == NULL) { /* extend fragment of start atom */ bond->getStartAtom()->getFragment()->addAtom(bond->getEndAtom()); } else if (bond->getStartAtom()->getFragment() == NULL) { /* 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) { foreach (sketcherMinimizerAtom* atom, fragment2->atoms()) { fragment1->addAtom(atom); } // remove fragment2 from fragments and free memory std::vector::iterator positionOfFragment2 = remove(fragments.begin(), fragments.end(), fragment2); fragments.erase(positionOfFragment2, fragments.end()); delete fragment2; } 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); } bool CoordgenFragmenter::setFixedInfo(sketcherMinimizerFragment* fragment) { fragment->fixed = (find_if(fragment->atoms().begin(), fragment->atoms().end(), isAtomFixed) != fragment->atoms().end()); return fragment->fixed; } bool CoordgenFragmenter::setConstrainedInfo(sketcherMinimizerFragment* fragment) { fragment->constrained = (find_if(fragment->atoms().begin(), fragment->atoms().end(), isAtomConstrained) != fragment->atoms().end()); return fragment->constrained; } void CoordgenFragmenter::setChainInfo(sketcherMinimizerFragment* fragment) { fragment->isChain = isChain(fragment); } bool CoordgenFragmenter::isAtomFixed(const sketcherMinimizerAtom* atom) { // needed for the find_if algorithm return atom->fixed; } bool CoordgenFragmenter::isAtomConstrained(const sketcherMinimizerAtom* atom) { // needed for the find_if algorithm return atom->constrained; } bool CoordgenFragmenter::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; foreach (sketcherMinimizerAtom* atom, fragmentAtoms) { if (atom->getBonds().size() > 3) return false; if (atom->getRings().size()) return false; } vector fragmentBonds = fragment->getBonds(); foreach (sketcherMinimizerBond* bond, fragmentBonds) { if (bond->getBondOrder() > 2) return false; } return true; } bool CoordgenFragmenter::hasPriority(const sketcherMinimizerFragment* fragment1, const sketcherMinimizerFragment* fragment2) { bool checkNoMore = false; int checkN = 0; while (!checkNoMore) { int leftValue = getValueOfCheck(fragment1, checkN, checkNoMore); int rightValue = getValueOfCheck(fragment2, checkN, checkNoMore); if (leftValue > rightValue) return true; if (leftValue < rightValue) return false; ++checkN; } return false; } int 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( vector fragments) { sketcherMinimizerFragment* mainFragment = *(min_element(fragments.begin(), fragments.end(), hasPriority)); mainFragment = considerChains(fragments, mainFragment); return mainFragment; } sketcherMinimizerFragment* CoordgenFragmenter::considerChains(vector fragments, sketcherMinimizerFragment* mainFragment) { foreach (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( vector fragments) { vector longestChain; foreach (sketcherMinimizerFragment* fragment, fragments) { if (!fragment->isChain) continue; int chainN = 0; foreach (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 = NULL; while (q.size()) { lastFragment = q.front(); q.pop(); foreach (sketcherMinimizerBond* b, lastFragment->_interFragmentBonds) { sketcherMinimizerFragment* childFragment = (b->getStartAtom()->getFragment() != lastFragment ? b->getStartAtom()->getFragment() : b->getEndAtom()->getFragment()); if (parentMap[childFragment] != NULL) 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, vector fragments) { queue fragmentsQueue; fragmentsQueue.push(mainFragment); while (fragmentsQueue.size() > 0) { sketcherMinimizerFragment* fragment = fragmentsQueue.front(); fragmentsQueue.pop(); foreach (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); } } foreach (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.size()) { sketcherMinimizerFragment* fragment = q.front(); q.pop(); new_fragments.push_back(fragment); foreach (sketcherMinimizerFragment* child, fragment->_children) q.push(child); } assert(fragments.size() == new_fragments.size()); fragments = new_fragments; } coordgenlibs-1.3/CoordgenFragmenter.h000066400000000000000000000106261351170412600177600ustar00rootroot00000000000000/* Contributors: Nicola Zonta Copyright Schrodinger, LLC. All rights reserved */ #ifndef COORDGEN_FRAGMENTER_H #define COORDGEN_FRAGMENTER_H #include class sketcherMinimizerFragment; class sketcherMinimizerMolecule; class sketcherMinimizerBond; class sketcherMinimizerRing; class sketcherMinimizerAtom; /* class to divide a molecule into rigid fragments */ class 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); /* check if fragment is part of an aliphatic chain and sets the appropriate flag */ static void setChainInfo(sketcherMinimizerFragment* fragment); /* check if fragment has fixed coordinates and sets the appropriate flag */ static bool setFixedInfo(sketcherMinimizerFragment* fragment); /* check if fragment has constrained coordinates and set the appropriate flag */ static bool setConstrainedInfo(sketcherMinimizerFragment* fragment); /* check if atom has fixed cooordinates */ static bool isAtomFixed(const sketcherMinimizerAtom* atom); /* check if atom has constrained cooordinates */ static bool isAtomConstrained(const sketcherMinimizerAtom* atom); /* check if fragment is part of an aliphatic chain */ static bool isChain(const sketcherMinimizerFragment* fragment); /* 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 int getValueOfCheck(const sketcherMinimizerFragment* fragment, int checkN, bool& checkNoMore); /* find the main fragment */ static sketcherMinimizerFragment* findMainFragment(std::vector fragments); /* if molecule has a long enough chain return the start of the chain as main fragment instead */ static sketcherMinimizerFragment* considerChains(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(std::vector fragments); /* initialize parent-child info of bound fragments */ static void addParentRelationsToFragments( sketcherMinimizerFragment* mainFragment, 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); }; #endif /* defined(COORDGEN_FRAGMENTER_H) */ coordgenlibs-1.3/CoordgenMacrocycleBuilder.cpp000066400000000000000000001264351351170412600216170ustar00rootroot00000000000000/* Contributors: Nicola Zonta Copyright Schrodinger, LLC. All rights reserved */ #include "CoordgenMacrocycleBuilder.h" #include "CoordgenMinimizer.h" #include "sketcherMinimizer.h" #include #include #include "sketcherMinimizerMaths.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 (unsigned int i = 0; i < rhs.m_list.size(); i++) { addHex(rhs.m_list[i]->coords()); } reassignHexs(); } Polyomino& Polyomino::operator=(const Polyomino& rhs) { clear(); resizeGrid(1); pentagonVertices = rhs.pentagonVertices; for (unsigned int i = 0; i < rhs.m_list.size(); i++) { addHex(rhs.m_list[i]->coords()); } reassignHexs(); return *this; } Polyomino::~Polyomino() { clear(); } void Polyomino::clear() { for (unsigned int i = 0; i < m_list.size(); i++) { delete m_list[i]; } m_list.clear(); } int 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 (unsigned int j = 0; j < m_grid.size(); j++) { m_grid[j] = NULL; } for (unsigned int i = 0; i < m_list.size(); i++) { Hex* hex = m_list[i]; 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; foreach (Hex* hex, p.m_list) { targetCoords.push_back(hex->coords()); } if (!targetCoords.size()) return true; // both polyominoes are empty int lowestx = m_list[0]->coords().x; int lowesty = m_list[0]->coords().y; foreach (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 (unsigned int j = 0; j < targetCoords.size(); j++) { targetCoords[j] = hexCoords(targetCoords[j].x + lowestx - lowestTargetX, targetCoords[j].y + lowesty - lowestTargetY); } // check bool same = true; for (unsigned int j = 0; j < targetCoords.size(); j++) { if (!getHex(targetCoords[j])) { same = false; break; } } if (same) { return true; } // rotate for (unsigned int j = 0; j < targetCoords.size(); j++) { targetCoords[j] = targetCoords[j].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(); int previousMultiplicity = hexagonsAtVertex(pathV[pathV.size() - 1]); int thisMultiplicity = hexagonsAtVertex(pathV[0]); int nextMultiplicity = 0; for (unsigned int i = 0; i < pathV.size(); i++) { int 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 (unsigned int i = 0; i < pathV.size(); i++) { int 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); } int 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.push_back(hexCoords(v.x - direction, v.y)); h = getHex(hexCoords(v.x, v.y - direction)); if (!h) out.push_back(hexCoords(v.x, v.y - direction)); h = getHex(hexCoords(v.x, v.y)); // z - direction if (!h) out.push_back(hexCoords(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 (unsigned int i = 0; i < m_list.size(); i++) { Hex* h = m_list[i]; 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 vertexCoords(0, 0, 0); } int Polyomino::countNeighbors(hexCoords h) const { int out = 0; vector neighs = Hex::neighboringPositions(h); for (unsigned int i = 0; i < neighs.size(); i++) { if (getHex(neighs[i]) != NULL) out++; } return out; } std::vector Polyomino::allFreeNeighbors() const { for (unsigned int i = 0; i < m_list.size(); i++) { // make sure that the grid is big enough to store every neighbor getIndexInList(hexCoords(m_list[i]->x() + 1, m_list[i]->y() + 1)); getIndexInList(hexCoords(m_list[i]->x() - 1, m_list[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 (unsigned int i = 0; i < m_list.size(); i++) { std::vector neighborsCoords = m_list[i]->neighbors(); for (unsigned int j = 0; j < neighborsCoords.size(); j++) { bool isPresent = (getHex(neighborsCoords[j]) != NULL); if (isPresent) continue; int index = getIndexInList(neighborsCoords[j]); if (visited[index]) continue; visited[index] = true; out.push_back(neighborsCoords[j]); } } 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] == NULL); 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 != NULL); 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] = NULL; } 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]) != NULL && getHex(neighs[i2]) != NULL && getHex(neighs[i3]) != NULL) return true; } return false; } vertexCoords Polyomino::coordinatesOfSubstituent(const vertexCoords pos) const { vector neighbors = vertexNeighbors(pos); assert(neighbors.size() != 0); 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.size()) { for (unsigned int j = 0; j < pentagonVertices.size(); j++) { if (pentagonVertices[j] == 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.push_back(hexCoords(xx + 1, yy)); // z-1 out.push_back(hexCoords(xx + 1, yy - 1)); out.push_back(hexCoords(xx, yy - 1)); // z+1 out.push_back(hexCoords(xx - 1, yy)); // z+1 out.push_back(hexCoords(xx - 1, yy + 1)); out.push_back(hexCoords(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 vertexCoords(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. Polyomino p; p.buildWithVerticesN(atoms.size()); vector pols; pols.push_back(p); vector squarePols = buildSquaredShapes(atoms.size()); 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(atoms.size()); 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.size()); } if (found) { vector path = chosenP.getPath(); writePolyominoCoordinates(path, atoms, startOfChosen); if (chosenP.pentagonVertices.size()) { 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; foreach (sketcherMinimizerAtom* atom, atoms) { coordinates.push_back(atom->getCoordinates()); } return coordinates; } sketcherMinimizerBond* CoordgenMacrocycleBuilder::findBondToOpen(sketcherMinimizerRing* ring) const { sketcherMinimizerBond* bestBond = NULL; float bestScore = 0.f; foreach (sketcherMinimizerBond* bond, ring->_bonds) { int 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(); if (bestBond == NULL || 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.m_minimizer.skipMinimization = true; min.m_fragmentBuilder.setForceOpenMacrocycles(true); sketcherMinimizerMolecule* minMol = new sketcherMinimizerMolecule; sketcherMinimizerBond* bondToBreak = findBondToOpen(ring); if (!bondToBreak) return false; sketcherMinimizerAtom* a = ring->_atoms[0]; // vector atoms = a->getFragment()->getAtoms(); vector atoms = a->molecule->getAtoms(); foreach (sketcherMinimizerAtom* at, atoms) { if (at->isResidue()) continue; sketcherMinimizerAtom* 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(); foreach (sketcherMinimizerBond* bo, bonds) { if (bo == bondToBreak || bo->isResidueInteraction()) continue; sketcherMinimizerBond* 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.m_minimizer.buildFromFragments(true); sketcherMinimizerBond* 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.m_minimizer.avoidClashesOfMolecule(minMol, extraInteractions); foreach (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(vector l) const { vector out; for (unsigned int i = 0; i < l.size(); i++) { vector newV = listOfEquivalent(l[i]); out.reserve(out.size() + newV.size()); out.insert(out.end(), newV.begin(), newV.end()); } return out; } vector CoordgenMacrocycleBuilder::listOfEquivalent( 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; int pentagonVs = p.pentagonVertices.size(); for (unsigned int i = 0; i < l.size(); i++) { hexCoords c = l[i]->coords(); if (p.isEquivalentWithout(c)) { Polyomino newP = p; newP.pentagonVertices.clear(); newP.removeHex(c); for (int 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 < (int) 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 (unsigned int jj = 0; jj < a->neighbors.size(); jj++) { sketcherMinimizerAtom* n = a->neighbors[jj]; if (find(atoms.begin(), atoms.end(), n) == atoms.end()) { if (r->containsAtom(n)) forceOutside = true; break; } } out.push_back(ringConstraint(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 (unsigned int r = 0; r < b->rings.size(); r++) { if (b->rings[r]->_atoms.size() < MACROCYCLE) { smallRingBond = true; break; } } } if (smallRingBond) continue; unsigned int previousI = (i + atoms.size() - 1) % atoms.size(); unsigned 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.size()) { sketcherMinimizerAtom* thisA = q.front(); q.pop(); visited[thisA] = true; n++; for (unsigned int i = 0; i < thisA->neighbors.size(); i++) { sketcherMinimizerAtom* n = thisA->neighbors[i]; 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; unsigned int prevI = (i + atoms.size() - 1) % atoms.size(); unsigned 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.push_back(pair(i, totN)); } } pr.heteroAtoms = heteroAtoms; pr.substitutedAtoms = substitutedAtoms; return pr; } bool CoordgenMacrocycleBuilder::checkDoubleBoundConstraints( vector& dbConstraints, vector& vertices, int& startI) const { for (unsigned int i = 0; i < dbConstraints.size(); i++) { unsigned int counter = (startI + dbConstraints[i].previousAtom) % vertices.size(); sketcherMinimizerPointF p1 = coordsOfVertex(vertices[counter]); counter = (startI + dbConstraints[i].atom1) % vertices.size(); sketcherMinimizerPointF p2 = coordsOfVertex(vertices[counter]); counter = startI + dbConstraints[i].atom2; if (counter >= vertices.size()) counter -= vertices.size(); sketcherMinimizerPointF p3 = coordsOfVertex(vertices[counter]); counter = startI + dbConstraints[i].followingAtom; if (counter >= vertices.size()) counter -= vertices.size(); sketcherMinimizerPointF p4 = coordsOfVertex(vertices[counter]); if (sketcherMinimizerMaths::sameSide(p1, p4, p2, p3) == dbConstraints[i].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 (unsigned int i = 0; i < pr.heteroAtoms.size(); i++) { int counter = (pr.heteroAtoms[i] + 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 (unsigned int i = 0; i < ringConstraints.size(); i++) { unsigned int counter = (ringConstraints[i].atom + startI) % path.size(); if (ringConstraints[i].forceOutside) { if (neighborNs[counter] != 1) { return false; } } sketcherMinimizerRing* r = ringConstraints[i].ring; vector newPos = p.freeVertexNeighborPositions(path[counter]); vector oldPos = allowedHexs[r]; vector nextPos; if (!oldPos.size()) { nextPos = newPos; } else { for (unsigned int pp = 0; pp < newPos.size(); pp++) { hexCoords toCheck = newPos[pp]; 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.size()) { return false; } allowedHexs[r] = nextPos; } return true; } vector CoordgenMacrocycleBuilder::getVertexNeighborNs(Polyomino& p, vector& path) const { vector out; for (unsigned int i = 0; i < path.size(); i++) { out.push_back(p.hexagonsAtVertex(path[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 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; } } } if (bestScore > PATH_FAILED) { return true; } return false; } sketcherMinimizerPointF CoordgenMacrocycleBuilder::coordsOfVertex(vertexCoords& v) const { return sketcherMinimizerPointF( BONDLENGTH * SQRT3HALF * v.x - BONDLENGTH * SQRT3HALF * v.z, -BONDLENGTH * 0.5 * v.x + BONDLENGTH * v.y + -BONDLENGTH * 0.5 * v.z); } void CoordgenMacrocycleBuilder::writePolyominoCoordinates( vector& path, 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 (unsigned int i = 0; i < pols.size(); i++) { bool duplicate = false; for (unsigned int j = 0; j < out.size(); j++) { if (pols[i].isTheSameAs(out[j])) { duplicate = true; break; } } if (!duplicate) { out.push_back(pols[i]); } } 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-1.3/CoordgenMacrocycleBuilder.h000066400000000000000000000306531351170412600212600ustar00rootroot00000000000000/* Contributors: Nicola Zonta Copyright Schrodinger, LLC. All rights reserved */ #ifndef COORDGEN_MACROCYCLE_BUILDER_H #define COORDGEN_MACROCYCLE_BUILDER_H #include #include #include #include "CoordgenConfig.hpp" 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 { if (x == rhs.x && y == rhs.y && z == rhs.z) return true; return false; } 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 { if (x == rhs.x && y == rhs.y) return true; return false; } 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 hexCoords(-z, -x); } vertexCoords toVertexCoords() const { return vertexCoords(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& p); ~Polyomino(); Polyomino& operator=(const Polyomino& rhv); /* 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 */ int 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 */ int 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() : m_forceOpenMacrocycles(false){}; ~CoordgenMacrocycleBuilder(){}; /* 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; 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(Polyomino p) const; std::vector listOfEquivalents(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, 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-1.3/CoordgenMinimizer.cpp000066400000000000000000001631241351170412600201660ustar00rootroot00000000000000/* Contributors: Nicola Zonta Copyright Schrodinger, LLC. All rights reserved */ #include "CoordgenMinimizer.h" #include "sketcherMinimizerAtom.h" #include "sketcherMinimizerBond.h" #include "sketcherMinimizerResidue.h" #include "sketcherMinimizerResidueInteraction.h" #include "sketcherMinimizerFragment.h" #include "sketcherMinimizerRing.h" #include "sketcherMinimizerClashInteraction.h" #include "sketcherMinimizerBendInteraction.h" #include "sketcherMinimizerEZConstrainInteraction.h" #include "sketcherMinimizerStretchInteraction.h" #include "sketcherMinimizerConstraintInteraction.h" #include "sketcherMinimizer.h" // should be removed at the end of refactoring #include #include #include "sketcherMinimizerMaths.h" 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.3; 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; CoordgenMinimizer::CoordgenMinimizer() { m_maxIterations = 500; skipMinimization = false; skipFlipFragments = false; skipAvoidClashes = false; m_scoreResidueInteractions = true; m_precision = 1.f; } CoordgenMinimizer::~CoordgenMinimizer() { clearInteractions(); } void CoordgenMinimizer::clearInteractions() { for (unsigned int i = 0; i < _interactions.size(); i++) { delete _interactions[i]; } _interactions.clear(); _intramolecularClashInteractions.clear(); _extraInteractions.clear(); _stretchInteractions.clear(); _bendInteractions.clear(); } void CoordgenMinimizer::run() { if (skipMinimization) return; if (!_interactions.size()) setupInteractions(); for (int iterations = 0; iterations < m_maxIterations; ++iterations) { scoreInteractions(); if (!applyForces()) break; } fixRingsShape(); } bool CoordgenMinimizer::applyForces(float maxd) { float delta = 0.001; // minimum squared displacement float distance = 0.f; for (unsigned int i = 0; i < _atoms.size(); i++) { sketcherMinimizerAtom* atom = _atoms[i]; 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); } if (distance < delta) { return false; } return true; } /* 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) { foreach (sketcherMinimizerAtom* atom, atoms) { if (atom->isResidue()) continue; foreach (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; foreach (sketcherMinimizerAtom* n, at1->neighbors) { if (n->isNeighborOf(at2)) continue; } if (at3->isNeighborOf(at2)) continue; foreach (sketcherMinimizerAtom* n, at3->neighbors) { if (n->isNeighborOf(at2)) continue; } if (!(at1->rigid && at2->rigid && at3->rigid)) { // } sketcherMinimizerClashInteraction* interaction = new sketcherMinimizerClashInteraction(at1, at2, at3); float restVK = 0.8; if (at2->atomicNumber == 6 && at2->charge == 0) restVK -= 0.1; if (at1->atomicNumber == 6 && at1->charge == 0 && at3->atomicNumber == 6 && at3->charge == 0) restVK -= 0.1; interaction->restV = (bondLength * restVK) * (bondLength * restVK); _intramolecularClashInteractions.push_back(interaction); _interactions.push_back(interaction); } } } } } void CoordgenMinimizer::addStretchInteractionsOfMolecule( sketcherMinimizerMolecule* molecule) { vector bonds = molecule->getBonds(); foreach (sketcherMinimizerBond* bo, bonds) { if (bo->isResidueInteraction()) continue; sketcherMinimizerAtom* at1 = bo->startAtom; sketcherMinimizerAtom* at2 = bo->endAtom; sketcherMinimizerStretchInteraction* interaction = new sketcherMinimizerStretchInteraction(at1, at2); interaction->k *= 0.1; interaction->restV = bondLength; if (at1->rigid && at2->rigid) { sketcherMinimizerPointF v = at2->coordinates - at1->coordinates; interaction->restV = v.length(); } _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(std::vector allAtoms) { 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(std::vector allAtoms) { 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(std::vector allAtoms, std::set chetoCs, std::set aminoNs) { 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, std::set firstSet, std::set secondSet, std::set thirdSet, 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 = 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]); sketcherMinimizerEZConstrainInteraction* 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(); foreach (sketcherMinimizerAtom* at, atoms) { vector interactions; vector ringInteractions; vector nonRingInteractions; int nbonds = 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]; sketcherMinimizerBendInteraction* 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 += r->fusedWith[i]->_atoms.size() - r->fusionAtoms[i].size(); } } interaction->isRing = true; interaction->k *= 10; interaction->restV = 180 - (360 / (r->size() + extraAtoms)); ringInteractions.push_back(interaction); } else { if (nbonds == 3) { sketcherMinimizerAtom* otherAtom = NULL; 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.size()) { // subtract all the ring angles from 360 // and divide the remaining equally // between the other interactions float totalAngleInRings = 0; foreach (sketcherMinimizerBendInteraction* i, ringInteractions) { totalAngleInRings += i->restV; } if (invertedMacrocycleBond) { totalAngleInRings = 360 - totalAngleInRings; } foreach (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) { foreach (sketcherMinimizerBendInteraction* i, nonRingInteractions) { i->restV = 360 / nonRingInteractions.size(); } } } foreach (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( 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.5; for (auto res : _residues) { for (auto res2 : _residues) { if (res2 >= res) { continue; } sketcherMinimizerClashInteraction* minimizerInteraction = new sketcherMinimizerClashInteraction(res, res2, res); minimizerInteraction->restV = CLASH_DISTANCE * CLASH_DISTANCE; _interactions.push_back(minimizerInteraction); } } } void CoordgenMinimizer::setupInteractionsProteinOnly( std::map> chains) { clearInteractions(); std::set interactions; std::set residues; for (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; } sketcherMinimizerClashInteraction* 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 : _molecules) { addInteractionsOfMolecule(molecule, intrafragmentClashes); } } float CoordgenMinimizer::scoreInteractions() { float totalEnergy = 0.f; for (unsigned int i = 0; i < _interactions.size(); i++) { sketcherMinimizerInteraction* interaction = _interactions[i]; 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; foreach (sketcherMinimizerAtom* a, mol1->_atoms) { foreach (sketcherMinimizerAtom* a2, mol2->_atoms) { if (sketcherMinimizerMaths::squaredDistance( a->coordinates, a2->coordinates) < threshold2) return true; } } foreach (sketcherMinimizerAtom* a, mol1->_atoms) { foreach (sketcherMinimizerBond* b, mol2->_bonds) { if (sketcherMinimizerMaths::squaredDistancePointSegment( a->coordinates, b->startAtom->coordinates, b->endAtom->coordinates) < threshold2) return true; } } foreach (sketcherMinimizerAtom* a, mol2->_atoms) { foreach (sketcherMinimizerBond* b, mol1->_bonds) { if (sketcherMinimizerMaths::squaredDistancePointSegment( a->coordinates, b->startAtom->coordinates, b->endAtom->coordinates) < threshold2) return true; } } foreach (sketcherMinimizerBond* b, mol1->_bonds) { foreach (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( 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; } void CoordgenMinimizer::fixRingsShape() { for (unsigned int i = 0; i < _bendInteractions.size(); i++) { sketcherMinimizerBendInteraction* in = _bendInteractions[i]; if (in->isRing) { in->k *= 10; } } for (unsigned int i = 0; i < _stretchInteractions.size(); i++) { sketcherMinimizerStretchInteraction* in = _stretchInteractions[i]; if (sketcherMinimizer::sameRing(in->atom1, in->atom2)) { in->k *= 10; } } for (int iterations = 0; iterations < m_maxIterations; ++iterations) { scoreInteractions(); if (!applyForces(1)) break; } } float CoordgenMinimizer::scoreClashes( sketcherMinimizerMolecule* molecule, bool residueInteractions, bool scoreProximityRelationsOnOppositeSid) const { float E = 0.f; foreach (auto i, _intramolecularClashInteractions) { i->score(E, true); } foreach (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 (auto fragment : molecule->getFragments()) { for (auto dof : fragment->getDofs()) { E += dof->getCurrentPenalty(); } } return E; } float CoordgenMinimizer::scoreCrossBonds(sketcherMinimizerMolecule* molecule, bool residueInteractions) const { if (m_scoreResidueInteractions == false) 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; 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 (_residueInteractions.size() && residueInteractions) { for (unsigned int a = 0; a < _residues.size(); a++) { sketcherMinimizerResidue* r = _residues[a]; 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.2, a2->coordinates + a2->getSingleAdditionVector() * 0.2, a1->coordinates, a2->coordinates)) { out += 15.f; } for (unsigned int bb = 0; bb < _bonds.size(); bb++) { sketcherMinimizerBond* b2 = _bonds[bb]; 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; foreach (sketcherMinimizerMolecule* m, _molecules) { foreach (sketcherMinimizerRing* r, m->_rings) { if (r->_atoms.size() > MACROCYCLE) continue; if (r->_atoms.size() < 3) continue; sketcherMinimizerPointF c = r->findCenter(); foreach (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; foreach (sketcherMinimizerMolecule* m, _molecules) { if (m->_atoms.size() < 2) continue; for (unsigned int i = 0; i < m->m_proximityRelations.size(); i++) { sketcherMinimizerPointF v1, v2; sketcherMinimizerMolecule* otherMol1 = NULL; sketcherMinimizerBond* pr1 = m->m_proximityRelations[i]; sketcherMinimizerFragment* f1 = NULL; 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 = NULL; 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, 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(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; int bestScoreForRun = bestScore; std::vector>> bestSolutions; for (auto solution : growingSolutions) { bestSolutions.push_back( std::pair>(solution.second, solution.first)); } sort(bestSolutions.begin(), bestSolutions.end()); growingSolutions.clear(); int maxN = 6 * getPrecision(); if (maxN < 1) maxN = 1; int n = 0; for (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 { ++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, vector dofs, int levels, float& clashE, CoordgenDOFSolutions& solutions) { bool downhill = false; auto combinationsOfDofs = buildTuplesOfDofs(dofs, levels); do { downhill = false; for (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::runLocalSearch(sketcherMinimizerMolecule* molecule, vector dofs, float& clashE) { float bestResult = clashE; bool downhill = true; do { downhill = false; for (auto dof : dofs) { for (int i = 1; i < dof->numberOfStates(); ++i) { dof->changeState(); buildMoleculeFromFragments(molecule); float result = scoreClashes(molecule, true); if (result < clashEnergyThreshold) { dof->storeCurrentValueAsOptimal(); dof->setToOptimalValue(); clashE = result; return true; } else if (result < bestResult - SKETCHER_EPSILON) { bestResult = result; clashE = result; downhill = true; dof->storeCurrentValueAsOptimal(); } } dof->setToOptimalValue(); } } 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, std::vector extraInteractions) { clearInteractions(); addClashInteractionsOfMolecule(molecule, false); addPeptideBondInversionConstraintsOfMolecule(molecule); foreach (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; foreach (sketcherMinimizerMolecule* molecule, _molecules) { auto cleanPose = avoidClashesOfMolecule(molecule); allCleanPoses = allCleanPoses && cleanPose; } return allCleanPoses; } void CoordgenMinimizer::avoidInternalClashes( sketcherMinimizerFragment* fragment) { // avoid intraFragmentClashes vector fragmentAtoms = fragment->getAtoms(); foreach (sketcherMinimizerAtom* a, fragmentAtoms) { if (a->neighbors.size() != 1) continue; if (a->needsCheckForClashes) continue; if (a->fixed) continue; if (!fragment->getDofsOfAtom(a).empty()) continue; foreach (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.5) continue; if (dx < -bondLength * 0.5) continue; float dy = a2->coordinates.y() - a->coordinates.y(); if (dy > bondLength * 0.5) continue; if (dy < -bondLength * 0.5) continue; float squareD = dx * dx + dy * dy; if (squareD > bondLength * 0.5 * bondLength * 0.5) continue; sketcherMinimizerPointF vec = a->coordinates - a->neighbors[0]->coordinates; vec *= 0.3; 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; } 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(vector rings) { bool found = false; for (unsigned int rr = 0; rr < rings.size(); rr++) { sketcherMinimizerRing* r = rings[rr]; if (r->_atoms.size() == 5) { for (unsigned int i = 0; i < r->_atoms.size(); i++) { if (r->_atoms[i]->rings.size() > 2) found = true; } } if (r->isMacrocycle() && r->_atoms.size() % 2 != 0) { for (unsigned int i = 0; i < r->_atoms.size(); i++) { if (r->_atoms[i]->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 { foreach (sketcherMinimizerMolecule* molecule, _molecules) { buildMoleculeFromFragments(molecule, firstTime); } } bool CoordgenMinimizer::hasValid3DCoordinates( vector atoms) { foreach (sketcherMinimizerAtom* atom, atoms) { if (!atom->hasValid3DCoordinates()) { return false; } } return true; } void CoordgenMinimizer::fallbackOn3DCoordinates( vector atoms) { float scale = 35.f; // ratio between average bond length and 2d bond length /* TODO find best projection */ foreach (sketcherMinimizerAtom* atom, atoms) { atom->setCoordinates( sketcherMinimizerPointF(atom->m_x3D * scale, -atom->m_y3D * scale)); } } bool CoordgenMinimizer::hasNaNCoordinates( std::vector atoms) { foreach (sketcherMinimizerAtom* a, atoms) if (a->coordinates.x() != a->coordinates.x() || a->coordinates.y() != a->coordinates.y()) return true; return false; } bool CoordgenMinimizer::hasNaNCoordinates() { return hasNaNCoordinates(_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.25, 0.f)); coordsVect.push_back(oldCoordinates + sketcherMinimizerPointF(-bondLength * 0.25, 0.f)); coordsVect.push_back(oldCoordinates + sketcherMinimizerPointF(0.f, bondLength * 0.25)); coordsVect.push_back(oldCoordinates + sketcherMinimizerPointF(0.f, -bondLength * 0.25)); coordsVect.push_back(oldCoordinates + sketcherMinimizerPointF(bondLength * 0.25 * 0.7071, -bondLength * 0.25 * 0.7071)); coordsVect.push_back(oldCoordinates + sketcherMinimizerPointF(-bondLength * 0.25 * 0.7071, -bondLength * 0.25 * 0.7071)); coordsVect.push_back(oldCoordinates + sketcherMinimizerPointF(-bondLength * 0.25 * 0.7071, bondLength * 0.25 * 0.7071)); coordsVect.push_back(oldCoordinates + sketcherMinimizerPointF(bondLength * 0.25 * 0.7071, bondLength * 0.25 * 0.7071)); float bestE = 999999; float 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(); foreach (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); } foreach (sketcherMinimizerBond* b, a->bonds) { vector atoms = a->getFragment()->getAtoms(); foreach (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( 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(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-1.3/CoordgenMinimizer.h000066400000000000000000000325151351170412600176320ustar00rootroot00000000000000/* Contributors: Nicola Zonta Copyright Schrodinger, LLC. All rights reserved */ #ifndef COORDGEN_MINIMIZER_H #define COORDGEN_MINIMIZER_H #include #include #include #include #include "CoordgenConfig.hpp" class sketcherMinimizerInteraction; class sketcherMinimizerStretchInteraction; class sketcherMinimizerBendInteraction; class sketcherMinimizerClashInteraction; class sketcherMinimizerMolecule; class sketcherMinimizerResidue; class sketcherMinimizerResidueInteraction; class sketcherMinimizerAtom; class sketcherMinimizerBond; class sketcherMinimizerRing; class sketcherMinimizerFragment; 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(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(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(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( 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( 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(std::vector mols, float threshold); /* run a minimization of the molecules rings constraining their shape to * regular polygons */ void fixRingsShape(); /* 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, 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, 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(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, 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(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(std::vector allAtoms); /* find a list of nitrogens from the backbon NH of a peptide */ std::set getAminoNs(std::vector allAtoms); /* find a list of alpha carbons of a peptide */ std::set getAlphaCs(std::vector allAtoms, std::set chetoCs, std::set aminoNs); /* check the atom for clashes with other atoms */ static void checkForClashes(sketcherMinimizerAtom* a); /* return true if atoms have NaN coordinates */ static bool hasNaNCoordinates(std::vector atoms); bool hasNaNCoordinates(); /* return true if the atom has valid 3d coordinates */ static bool hasValid3DCoordinates(std::vector atoms); /* use 3d coordinates in 2d (e.g. when a reasonable 2d structure cannot be * found) */ static void fallbackOn3DCoordinates(std::vector atoms); /* add the given constraint to the minimizer */ void addExtraInteraction(sketcherMinimizerMolecule* molecule, sketcherMinimizerInteraction* interaction); std::vector _atoms; std::vector _bonds; bool m_evenAngles; std::vector _residues; std::vector _residueInteractions; std::vector _fragments; std::vector _molecules; bool skipMinimization, skipAvoidClashes, skipFlipFragments, m_scoreResidueInteractions; private: /* 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); /* 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, std::set firstSet, std::set secondSet, std::set thirdSet, std::set fourthSet) const; std::vector _interactions; std::vector _stretchInteractions; std::vector _bendInteractions; std::vector _intramolecularClashInteractions; std::vector _extraInteractions; std::map> _extraInteractionsOfMolecule; float m_maxIterations; float m_precision; }; #endif /* defined(COORDGEN_MINIMIZER_H) */ coordgenlibs-1.3/Info.plist000066400000000000000000000013151351170412600157770ustar00rootroot00000000000000 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-1.3/LICENSE000066400000000000000000000027561351170412600150460ustar00rootroot00000000000000BSD 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-1.3/README.md000066400000000000000000000040031351170412600153030ustar00rootroot00000000000000# CoordgenLibs [![Build Status](https://travis-ci.org/schrodinger/coordgenlibs.svg?branch=master)](https://travis-ci.org/schrodinger/coordgenlibs) [![Build_Status](https://ci.appveyor.com/api/projects/status/github/schrodinger/coordgenlibs?branch=master&svg=true)](https://ci.appveyor.com/project/torcolvin/coordgenlibs-3h7cs) This is **Schrodinger, 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 ### 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. coordgenlibs-1.3/appveyor.yml000066400000000000000000000027041351170412600164220ustar00rootroot00000000000000environment: BOOST_ROOT_DIR: c:\Libraries\boost BOOST_LIBRARY_PATH: c:\Libraries\boost\lib64-msvc-12.0 INSTALL_PREFIX : c:\installation CMAKE_PREFIX_PATH : c:\installation\lib\cmake image: Visual Studio 2013 platform: x64 configuration: - Release # - Debug install: # by default, all script lines are interpreted as batch build: project: build\INSTALL.vcxproj parallel: true before_build: - git clone https://github.com/schrodinger/maeparser.git %APPVEYOR_BUILD_FOLDER%\maeparser - mkdir %APPVEYOR_BUILD_FOLDER%\maeparser\build - cd %APPVEYOR_BUILD_FOLDER%\maeparser\build - cmake .. -G "Visual Studio 12 Win64" ^ -DBOOST_ROOT="%BOOST_ROOT_DIR%" ^ -DBOOST_LIBRARYDIR="%BOOST_LIBRARY_PATH%" ^ -DCMAKE_INSTALL_PREFIX="%INSTALL_PREFIX%" - cmake --build . --target install --config Release - mkdir %APPVEYOR_BUILD_FOLDER%\build - cd %APPVEYOR_BUILD_FOLDER%\build - cmake .. -G "Visual Studio 12 Win64" ^ -DBOOST_ROOT="%BOOST_ROOT_DIR%" ^ -DBOOST_LIBRARYDIR="%BOOST_LIBRARY_PATH%" ^ -DCMAKE_PREFIX_PATH="%CMAKE_PREFIX_PATH%" ^ -DCMAKE_INSTALL_PREFIX="%INSTALL_PREFIX%" test_script: - set PATH=%PATH%;%BOOST_LIBRARY_PATH%;%INSTALL_PREFIX%\bin # For whatever reason, boost_iostreams depends on libbz2.dll (required for maeparser) - copy %BOOST_LIBRARY_PATH%\boost_bzip2-vc120-mt-1_56.dll %INSTALL_PREFIX%\bin\libbz2.dll - cd %APPVEYOR_BUILD_FOLDER%\build - ctest -j2 --output-on-failure coordgenlibs-1.3/example_dir/000077500000000000000000000000001351170412600163205ustar00rootroot00000000000000coordgenlibs-1.3/example_dir/CMakeLists.txt000066400000000000000000000001141351170412600210540ustar00rootroot00000000000000add_executable(example example.cpp) target_link_libraries(example coordgen) coordgenlibs-1.3/example_dir/example.cpp000066400000000000000000000014301351170412600204550ustar00rootroot00000000000000#include #include "../sketcherMinimizer.h" int main() { sketcherMinimizer minimizer; /* create a molecule */ sketcherMinimizerMolecule* 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-1.3/maeparser/000077500000000000000000000000001351170412600160065ustar00rootroot00000000000000coordgenlibs-1.3/project.pbxproj000066400000000000000000000647071351170412600171210ustar00rootroot00000000000000// !$*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-1.3/project.xcworkspace/000077500000000000000000000000001351170412600200255ustar00rootroot00000000000000coordgenlibs-1.3/project.xcworkspace/xcshareddata/000077500000000000000000000000001351170412600224605ustar00rootroot00000000000000coordgenlibs-1.3/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings000066400000000000000000000004101351170412600302470ustar00rootroot00000000000000 IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded coordgenlibs-1.3/qt_makeqmake.mak000066400000000000000000000510641351170412600171670ustar00rootroot00000000000000############################################################################# # 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-1.3/qt_preprocess.mak000066400000000000000000000036101351170412600174120ustar00rootroot00000000000000############################################################################# # 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-1.3/sketcherMinimizer.cpp000066400000000000000000004113361351170412600202370ustar00rootroot00000000000000/* * sketcherMinimizer.cpp * 2d_sketcher * * Created by Nicola Zonta on 13/04/2010. * Copyright Schrodinger, LLC. All rights reserved * */ #include "sketcherMinimizer.h" #include "sketcherMinimizerMaths.h" #include "sketcherMinimizerStretchInteraction.h" #include "sketcherMinimizerBendInteraction.h" #include "sketcherMinimizerClashInteraction.h" #include #include #include #include "CoordgenFragmenter.h" #include "CoordgenMacrocycleBuilder.h" #include "maeparser/Reader.hpp" #include using namespace std; #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.82; static const float SCORE_MULTIPLIER_FOR_SINGLE_BONDED_HETEROATOMS = 0.9; static const float SCORE_MULTIPLIER_FOR_FRAGMENTS = 0.1; const int MAX_NUMBER_OF_RINGS = 40; sketcherMinimizer::sketcherMinimizer(float precision) { m_fragmentBuilder.m_evenAngles = false; m_minimizer.m_evenAngles = 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; } foreach (sketcherMinimizerAtom* at, minMol->_atoms) { at->neighbors.clear(); at->bonds.clear(); } foreach (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 (unsigned int i = 0; i < minMol->_bonds.size(); i++) { minMol->_bonds[i]->_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.size()) { 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(); _referenceAtoms = minMol->_atoms; _referenceBonds = minMol->_bonds; for (unsigned int bb = 0; bb < minMol->_bonds.size(); bb++) { if (minMol->_bonds[bb]->skip) continue; if (minMol->_bonds[bb]->bondOrder == 1 || minMol->_bonds[bb]->bondOrder == 2) { if (sketcherMinimizerAtom::isMetal( minMol->_bonds[bb]->startAtom->atomicNumber) || sketcherMinimizerAtom::isMetal( minMol->_bonds[bb]->endAtom->atomicNumber)) { minMol->_bonds[bb]->bondOrder = 0; } } } for (unsigned int bb = 0; bb < minMol->_bonds.size(); bb++) { if (minMol->_bonds[bb]->skip) continue; if (minMol->_bonds[bb]->bondOrder == 0) { m_proximityRelations.push_back(minMol->_bonds[bb]); } else if (minMol->_bonds[bb]->isResidueInteraction()) { if (!minMol->_bonds[bb]->startAtom->isResidue() && !minMol->_bonds[bb]->endAtom->isResidue()) m_proximityRelations.push_back(minMol->_bonds[bb]); } } for (unsigned int bb = 0; bb < m_extraBonds.size(); bb++) { if (m_extraBonds[bb]->skip) continue; if (m_extraBonds[bb]->bondOrder == 0) { m_proximityRelations.push_back(m_extraBonds[bb]); } else if (m_extraBonds[bb]->isResidueInteraction()) { if (!m_extraBonds[bb]->startAtom->isResidue() && !m_extraBonds[bb]->endAtom->isResidue()) m_proximityRelations.push_back(m_extraBonds[bb]); } } for (unsigned int bb = 0; bb < minMol->_bonds.size(); bb++) { if (minMol->_bonds[bb]->skip || minMol->_bonds[bb]->bondOrder == 0) { minMol->_bonds.erase(minMol->_bonds.begin() + bb); bb--; } else if (minMol->_bonds[bb]->startAtom->hidden || minMol->_bonds[bb]->endAtom->hidden) { minMol->_bonds.erase(minMol->_bonds.begin() + bb); bb--; } } for (unsigned int aa = 0; aa < minMol->_atoms.size(); aa++) { if (minMol->_atoms[aa]->hidden) { minMol->_atoms.erase(minMol->_atoms.begin() + aa); aa--; } } canonicalOrdering(minMol); // order atoms and bonds using morgan indices to // make the result input independent foreach (sketcherMinimizerAtom* a, minMol->_atoms) { if (!a->hidden) { _atoms.push_back(a); } if (a->isResidue()) _residues.push_back(static_cast(a)); } foreach (sketcherMinimizerBond* b, minMol->_bonds) { if (!b->startAtom->hidden && !b->endAtom->hidden) { _bonds.push_back(b); } if (b->isResidueInteraction()) _residueInteractions.push_back( static_cast(b)); } minMol->forceUpdateStruct(minMol->_atoms, minMol->_bonds, minMol->_rings); splitIntoMolecules(minMol, _molecules); foreach (sketcherMinimizerBond* 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._atoms = _atoms; m_minimizer._bonds = _bonds; m_minimizer._molecules = _molecules; m_minimizer._residues = _residues; m_minimizer._residueInteractions = _residueInteractions; } bool sketcherMinimizer::structurePassSanityCheck() const { if (!_atoms.size()) return false; for (auto molecule : _molecules) { if (molecule->_rings.size() > MAX_NUMBER_OF_RINGS) { return false; } } return true; } bool sketcherMinimizer::runGenerateCoordinates() { bool cleanPose = true; if (structurePassSanityCheck()) { findFragments(); m_minimizer.buildFromFragments(true); cleanPose = m_minimizer.avoidClashes(); bestRotation(); maybeFlip(); arrangeMultipleMolecules(); writeStereoChemistry(); } return cleanPose; } void sketcherMinimizer::flagCrossAtoms() { foreach (sketcherMinimizerAtom* at, _atoms) if (at->atomicNumber == 16 || at->atomicNumber == 15) at->crossLayout = true; foreach (sketcherMinimizerAtom* at, _atoms) { if (at->crossLayout) continue; int cross = 0; foreach (sketcherMinimizerAtom* n, at->neighbors) { if (n->neighbors.size() > 3) { cross++; } } if (cross > 2) { at->crossLayout = true; } } } /* void sketcherMinimizer::exportCoordinates(ChmMol& molecule) { foreach (sketcherMinimizerAtom* a, _referenceAtoms) { a->setCoordinates(a->coordinates); // round the coordinates // set NaN coordinates to (0); if (a->coordinates.x() != a->coordinates.x()) { cerr << "coordgen warning: NaN coordinates" << endl; a->coordinates.setX(0.f); } if (a->coordinates.y() != a->coordinates.y()) { cerr << "coordgen warning: NaN coordinates" << endl; a->coordinates.setY(0.f); } } ChmAtoms as = molecule.getAtoms(true); unsigned int i = 0; while (as.hasNext()) { ChmAtom& chma = as.next(); // if (chma.isDummy ()) continue; if (i < _referenceAtoms.size() && !_referenceAtoms[i]->hidden) { sketcherMinimizerPointF& p = _referenceAtoms[i]->coordinates; ChmPoint pt(p.x() / 35.f, p.y() / 35.f, 0.0f); if (pt.isZero()) { // apply gaussian random deviate to coordinates placed at origin ChmPoint offset((float) m_random.nextGaussian(0.0, 1e-20), (float) m_random.nextGaussian(0.0, 1e-20), 0); pt += offset; } chma.setCoords(pt); } i++; } unsigned int j = 0; ChmBonds bs = molecule.getBonds(true); while (bs.hasNext()) { ChmBond& chmb = bs.next(); if (chmb.atom1().isDummy() && !chmb.atom1().isWildcard()) continue; if (chmb.atom2().isDummy() && !chmb.atom2().isWildcard()) continue; if (chmb.isHidden()) { chmb.setBondDirectionHint(ChmBond::directionNone); continue; // do not increment j } const bool stereoBonds = _referenceBonds[j]->hasStereochemistryDisplay; if (stereoBonds) { if (_referenceBonds[j]->isWedge) { chmb.setBondDirectionHint(ChmBond::directionUp); } else { chmb.setBondDirectionHint(ChmBond::directionDown); } } else { chmb.setBondDirectionHint(ChmBond::directionNone); } j++; } } */ void sketcherMinimizer::clear() { for (unsigned int i = 0; i < _referenceAtoms.size(); i++) { delete _referenceAtoms[i]; } _referenceAtoms.clear(); _residues.clear(); for (unsigned int i = 0; i < _referenceBonds.size(); i++) { delete _referenceBonds[i]; } _referenceBonds.clear(); for (unsigned int i = 0; i < m_extraBonds.size(); i++) { delete m_extraBonds[i]; } m_extraBonds.clear(); for (unsigned int i = 0; i < _fragments.size(); i++) { delete _fragments[i]; } _fragments.clear(); for (unsigned int i = 0; i < _molecules.size(); i++) { delete _molecules[i]; } _molecules.clear(); } /* void sketcherMinimizer::initializeFromMolecule(ChmMol& mol) { sketcherMinimizerMolecule* minMol = new sketcherMinimizerMolecule; ChmAtoms as = mol.getAtoms(true); unsigned int i = 0; while (as.hasNext()) { ChmAtom& chma = as.next(); sketcherMinimizerAtom* min_at = new sketcherMinimizerAtom; min_at->_generalUseN = i; min_at->_generalUseN2 = i; // generalUseN will be changed by initialise, // we need a second counter to assign atom // chirality min_at->m_chmN = chma.getMolIndex(); i++; min_at->charge = chma.getFormalCharge(); min_at->atomicNumber = chma.getAtomicNumber(); min_at->fixed = chma.isFixed(); min_at->constrained = chma.isConstrained(); min_at->coordinates = sketcherMinimizerPointF(chma.getX() * 35.f, chma.getY() * 35.f); min_at->templateCoordinates = min_at->coordinates; min_at->hidden = chma.isHidden(); if (chma.isDummy() && !chma.isWildcard()) min_at->hidden = true; min_at->molecule = minMol; minMol->_atoms.push_back(min_at); } ChmBonds bs = mol.getBonds(true); while (bs.hasNext()) { ChmBond& chmb = bs.next(); // do not create sketcher bond to any hidden atoms // this means that bond vectors will be out of sequence if (chmb.atom1().isHidden() || chmb.atom2().isHidden()) continue; if ((chmb.atom1().isDummy() && !chmb.atom1().isWildcard()) || (chmb.atom2().isDummy() && !chmb.atom2().isWildcard())) continue; sketcherMinimizerBond* min_bo = new sketcherMinimizerBond; min_bo->startAtom = minMol->_atoms[chmb.atom1().getMolIndex()]; min_bo->endAtom = minMol->_atoms[chmb.atom2().getMolIndex()]; int order = chmb.getOrder(); if (chmb.isAromatic()) order -= 4; min_bo->bondOrder = order; minMol->_bonds.push_back(min_bo); } vector> zobs = mol.getZeroOrderBonds(); const unsigned int zbsz = (int) zobs.size(); unsigned int atomsize = (int) as.size(); if (minMol->_atoms.size() < atomsize) atomsize = (int) minMol->_atoms.size(); for (unsigned int i = 0; i < zbsz; i++) { pair& pr = zobs[i]; const unsigned int i1 = pr.first; const unsigned int i2 = pr.second; if (i1 >= atomsize || i2 >= atomsize) continue; ChmAtom& atom1 = as[i1]; ChmAtom& atom2 = as[i2]; if (atom1.isHidden() || atom2.isHidden()) continue; if ((atom1.isDummy() && !atom1.isWildcard()) || (atom2.isDummy() && !atom2.isWildcard())) continue; sketcherMinimizerBond* min_bo = new sketcherMinimizerBond; min_bo->startAtom = minMol->_atoms[i1]; min_bo->endAtom = minMol->_atoms[i2]; min_bo->bondOrder = 0; minMol->_bonds.push_back(min_bo); } sketcherMinimizerMolecule::assignBondsAndNeighbors(minMol->_atoms, minMol->_bonds); foreach (sketcherMinimizerBond* b, minMol->_bonds) { if (b->bondOrder == 2) { sketcherMinimizerAtom* startA = b->startAtomCIPFirstNeighbor(); sketcherMinimizerAtom* endA = b->endAtomCIPFirstNeighbor(); if (startA && endA) { ChmBond chb = mol.getBond(mol.getAtom(b->startAtom->_generalUseN2), mol.getAtom(b->endAtom->_generalUseN2)); if (chb.getStereo() == BondCis) { int i1 = -1, i2 = -1; chb.getCis(i1, i2); bool isZ = true; if (!(i1 == startA->_generalUseN2 || i1 == endA->_generalUseN2)) isZ = !isZ; if (!(i2 == startA->_generalUseN2 || i2 == endA->_generalUseN2)) isZ = !isZ; b->isZ = isZ; // cerr << "translating it to "<_generalUseN2 || i1 == endA->_generalUseN2)) isZ = !isZ; if (!(i2 == startA->_generalUseN2 || i2 == endA->_generalUseN2)) isZ = !isZ; b->isZ = isZ; } else { b->m_ignoreZE = true; } } } } initialize(minMol); for (unsigned int j = 0; j < minMol->_atoms.size(); j++) { sketcherMinimizerAtom* a = minMol->_atoms[j]; ChmAtom atom = mol.getAtom(a->_generalUseN2); ChmChiralityInfo info = atom.getChiralityInfo(); a->setStereochemistryFromChmChiralityInfo(info); } } */ void sketcherMinimizer::splitIntoMolecules( sketcherMinimizerMolecule* mol, vector& mols) { if (!mol->_atoms.size()) { mols.push_back(mol); return; } foreach (sketcherMinimizerAtom* a, mol->_atoms) a->_generalUseVisited = false; queue q; q.push(mol->_atoms[0]); foreach (sketcherMinimizerAtom* a, mol->_atoms) { if (!a->hidden) { q.push(a); break; } } while (q.size()) { sketcherMinimizerAtom* a = q.front(); q.pop(); a->_generalUseVisited = true; foreach (sketcherMinimizerAtom* n, a->neighbors) { if (!n->_generalUseVisited && !n->hidden) q.push(n); } } vector newAtoms; foreach (sketcherMinimizerAtom* a, mol->_atoms) { if (!a->_generalUseVisited && !a->hidden) { newAtoms.push_back(a); } } if (!newAtoms.size()) { mols.push_back(mol); foreach (sketcherMinimizerMolecule* m, mols) { foreach (sketcherMinimizerAtom* a, m->_atoms) { a->_generalUseVisited = false; } } } else { sketcherMinimizerMolecule* 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.size()) return NULL; if (!at2->rings.size()) return NULL; if (!at3->rings.size()) return NULL; sketcherMinimizerRing* r = 0; foreach (sketcherMinimizerRing* ring, at1->rings) { if (ring->isMacrocycle()) continue; foreach (sketcherMinimizerRing* ring2, at2->rings) { if (ring != ring2) continue; foreach (sketcherMinimizerRing* ring3, at3->rings) { if (ring3 == ring2) { if (!r) r = ring2; else if (ring2->_atoms.size() < r->_atoms.size()) r = ring2; } } } } foreach (sketcherMinimizerRing* ring, at1->rings) { foreach (sketcherMinimizerRing* ring2, at2->rings) { if (ring != ring2) continue; foreach (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() { foreach (sketcherMinimizerAtom* a, _atoms) { if (a->hasStereochemistrySet) a->writeStereoChemistry(); } assignPseudoZ(); } void sketcherMinimizer::assignPseudoZ() { foreach (sketcherMinimizerMolecule* mol, _molecules) { foreach (sketcherMinimizerAtom* a, mol->_atoms) { a->_generalUseVisited = false; } sketcherMinimizerAtom* lastAtom = NULL; bool finished = false; while (!finished) { lastAtom = NULL; foreach (sketcherMinimizerAtom* a, mol->_atoms) { if (!a->_generalUseVisited) { lastAtom = a; break; } } if (lastAtom) { queue q; q.push(lastAtom); while (q.size()) { 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 == false) || (b->endAtom == lastAtom && b->isReversed == true)) { Z += 1.f; } else if ((b->startAtom == lastAtom && b->isReversed == true) || (b->endAtom == lastAtom && b->isReversed == false)) { Z -= 1.f; } } else { if ((b->startAtom == lastAtom && b->isReversed == false) || (b->endAtom == lastAtom && b->isReversed == true)) { Z -= 1.f; } else if ((b->startAtom == lastAtom && b->isReversed == true) || (b->endAtom == lastAtom && b->isReversed == false)) { Z += 1.f; } } } lastAtom->neighbors[i]->m_pseudoZ = Z; q.push(lastAtom->neighbors[i]); } } } else finished = true; } } } void sketcherMinimizer::maybeFlipPeptides( 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() { foreach (sketcherMinimizerMolecule* mol, _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); foreach (sketcherMinimizerAtom* a, mol->_atoms) cent += a->coordinates; if (mol->_atoms.size()) cent /= mol->_atoms.size(); foreach (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); int totalN = 0; int totalRings = 0; foreach (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; foreach (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.5; float meany = (maxy + miny) * 0.5; if (meanx - cent.x() > SKETCHER_EPSILON) scoreX -= 0.5; else if (meanx - cent.x() < -SKETCHER_EPSILON) scoreX += 0.5; if (meany - cent.y() > SKETCHER_EPSILON) scoreY += 0.5; else if (meany - cent.y() < -SKETCHER_EPSILON) scoreY -= 0.5; foreach (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) { foreach (sketcherMinimizerAtom* a, mol->_atoms) { a->coordinates.setY(-a->coordinates.y()); } } if (0.f > scoreX) { foreach (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 += M_PI; for (unsigned int i = 0; i < angles.size(); i++) { if (angles[i].second < angle - SKETCHER_EPSILON) { if (i == angles.size() - 1) { angles.push_back(pair(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.size()) angles.push_back(pair(weight, angle)); } /* if a peptide chain is present rotate the molecule so it's horizontal */ void sketcherMinimizer::addBestRotationInfoForPeptides( vector>& angles, 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() { foreach (sketcherMinimizerMolecule* mol, _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; float increment = M_PI / 6; foreach (sketcherMinimizerAtom* a, mol->_atoms) { if (a->rings.size()) 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); } } } } foreach (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 += 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 -= M_PI; } } foreach (sketcherMinimizerFragment* f, mol->_fragments) { vector rings = f->getRings(); vector inPlaneRings = rings; int 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(); foreach (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; foreach (sketcherMinimizerRing* r, inPlaneRings) { if (r->_atoms.size() == 6) { rings.push_back(r); } } foreach (sketcherMinimizerRing* r, rings) { for (unsigned int i = 0; i < r->fusionAtoms.size(); i++) { vector fusionAts = r->fusionAtoms[i]; 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 = 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.size()) { 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); foreach (sketcherMinimizerAtom* at, mol->_atoms) center += at->coordinates; if (mol->_atoms.size()) center /= mol->_atoms.size(); foreach (sketcherMinimizerAtom* at, mol->_atoms) { sketcherMinimizerPointF v = at->coordinates - center; v.rotate(s, c); at->setCoordinates(center + v); } } } } void sketcherMinimizer::findFragments() { assert(_molecules.size()); foreach (sketcherMinimizerMolecule* mol, _molecules) { CoordgenFragmenter::splitIntoFragments(mol); if (!mol->_fragments.size()) continue; vector fragments = mol->_fragments; _fragments.reserve(_fragments.size() + fragments.size()); _fragments.insert(_fragments.end(), fragments.begin(), fragments.end()); _independentFragments.push_back(mol->getMainFragment()); } m_minimizer._fragments = _fragments; initializeFragments(); } void sketcherMinimizer::placeResiduesProteinOnlyModeCircleStyle( std::map> chains) { int totalResiduesNumber = _residues.size() + chains.size(); float angle = 2.f * M_PI / totalResiduesNumber; const float residueRadius = 30; const float circumference = totalResiduesNumber * residueRadius * 2; const float radius = circumference * 0.5 / M_PI; int i = 0; for (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( std::map> chains) { map molMap; sketcherMinimizerMolecule* metaMol = new sketcherMinimizerMolecule; for (auto chainPair : chains) { sketcherMinimizerAtom* a = new sketcherMinimizerAtom; a->molecule = metaMol; metaMol->_atoms.push_back(a); molMap[chainPair.first] = a; } for (auto chainPair : chains) { for (auto residue : chainPair.second) { for (auto interaction : residue->residueInteractions) { if (interaction->startAtom->isResidue() && interaction->endAtom->isResidue()) { sketcherMinimizerResidue* r1 = static_cast( interaction->startAtom); sketcherMinimizerResidue* 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) { sketcherMinimizerBond* newBond = new sketcherMinimizerBond; newBond->startAtom = at1; newBond->endAtom = at2; metaMol->_bonds.push_back(newBond); } } } } } } sketcherMinimizer min; if (metaMol->_atoms.size()) { min.m_fragmentBuilder.m_evenAngles = true; min.m_minimizer.m_evenAngles = true; min.initialize(metaMol); min.findFragments(); min.m_minimizer.buildFromFragments(true); min.m_minimizer.avoidClashes(); min.bestRotation(); min.maybeFlip(); min.arrangeMultipleMolecules(); } std::map positions; for (auto iter : molMap) { positions[iter.first] = iter.second->coordinates * 10.; } return positions; } void sketcherMinimizer::shortenInteractions( std::map> chains) { for (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( std::map> chains) { std::vector vec; for (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.size()) { auto topResidue = residueQueue.front(); finalVec.push_back(topResidue); residueQueue.pop(); for (auto partner : topResidue->residueInteractionPartners) { sketcherMinimizerResidue* partnerRes = static_cast(partner); if (visitedResidues.find(partnerRes) == visitedResidues.end()) { residueQueue.push(partnerRes); visitedResidues.insert(partnerRes); } } } } return finalVec; } void sketcherMinimizer::placeResiduesProteinOnlyModeLIDStyle( std::map> chains) { auto positions = computeChainsStartingPositionsMetaMol(chains); sketcherMinimizerPointF p; for (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) { int partnersAlreadySet = 0; sketcherMinimizerResidue* firstPartner = NULL; for (auto partner : res->residueInteractionPartners) { if (partner->coordinatesSet) { ++partnersAlreadySet; 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 : _residues) { string chainOfResidue = residue->chain; chains[chainOfResidue].push_back(residue); } placeResiduesProteinOnlyModeLIDStyle(chains); m_minimizer.minimizeProteinOnlyLID(chains); } void sketcherMinimizer::placeResiduesInCrowns() { auto SSEs = groupResiduesInSSEs(_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 (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( sketcherMinimizerPointF coordinates1, sketcherMinimizerPointF coordinates2) { const float stretchPenalty = 400.f; auto squaredLength = (coordinates2 - coordinates1).squareLength(); return squaredLength * stretchPenalty; } float sketcherMinimizer::getResidueDistance( float startF, float increment, sketcherMinimizerResidue* resToConsider, vector SSE) { float totalF = startF; sketcherMinimizerResidue* lastRes = nullptr; for (auto res : SSE) { if (lastRes) { float result = res->resnum - lastRes->resnum; /* if the gap is more than 1, make the distance a bit smaller for * aesthetic reasons */ result = 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( 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(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.push_back( pair(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.size())) { 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( pair solution, 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(vector shape, float floatPosition) { float normalizedF = floatPosition; while (normalizedF < 0) normalizedF += 1.f; while (normalizedF >= 1.f) normalizedF -= 1.f; int counter = shape.size() * normalizedF; return counter; } vector> sketcherMinimizer::groupResiduesInSSEs( 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 auto atoms = _atoms; auto bonds = _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(i); float pointY = ms.toRealy(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.size() > 0) { for (unsigned int i = 0; i < result.at(0).size(); i += 2) { returnValue.push_back(sketcherMinimizerPointF( 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 : _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(vector atoms) { if (!_residues.size()) { return; } if (!atoms.size()) { placeResiduesProteinOnlyMode(); return; } findClosestAtomToResidues(atoms); placeResiduesInCrowns(); m_minimizer.minimizeResidues(); return; } /* 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 (unsigned int pc = 0; pc < pointstoTest.size(); pc++) { noClash = true; v = pointstoTest[pc]; foreach (sketcherMinimizerAtom* at, mol->_atoms) { sketcherMinimizerPointF placeNextTo = at->coordinates + v; foreach (sketcherMinimizerMolecule* m, _molecules) { if (!m->isPlaced) continue; if (m == mol) continue; foreach (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( sketcherMinimizerPointF centerOfGrid, unsigned int levels, float gridD, float dx, float dy, float distanceFromAtoms, bool watermap, sketcherMinimizerResidue* residueForInteractions, 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 (unsigned int pc = 0; pc < pointstoTest.size(); pc++) { noClash = true; sketcherMinimizerPointF point = pointstoTest[pc] - centerOfGrid; placeNextTo = point.y() * direction + point.x() * directionNormal + centerOfGrid; foreach (sketcherMinimizerMolecule* m, _molecules) { if (!m->isPlaced) continue; foreach (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; foreach (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); foreach (sketcherMinimizerBond* pr, mol->m_proximityRelations) { sketcherMinimizerAtom* otherMetaAtom = NULL; sketcherMinimizerAtom* targetAtom = NULL; 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 *= -M_PI / 180.f; float s = sin(rotationAngle); float c = cos(rotationAngle); foreach (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; foreach (sketcherMinimizerAtom* n, metaAtom->neighbors) { v1.push_back(n->coordinates - metaAtom->coordinates); } v2 = additionVectors; float rotMat[4]; alignmentMatrix(v1, v2, rotMat); sketcherMinimizerPointF center = mol->center(); foreach (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 (unsigned int m = 0; m < proximityMols.size(); m++) { sketcherMinimizerMolecule* mol = proximityMols[m]; 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.size()) { sketcherMinimizerPointF atomsCenter = sketcherMinimizerPointF(0, 0); int atomsN = 0; foreach (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; foreach (sketcherMinimizerAtom* a, mol->_atoms) { a->coordinates += placeNextTo - atomsCenter; } mol->isPlaced = true; } } if (cleverPlacing) { // replace single terminal atoms for (unsigned int m = 0; m < proximityMols.size(); m++) { sketcherMinimizerMolecule* mol = proximityMols[m]; if (mol->_atoms.size() == 1) { sketcherMinimizerAtom* metaAtom = molMap[mol]; if (metaAtom->neighbors.size() == 1) { int bondsN = 0; sketcherMinimizerPointF coords(0, 0); foreach (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 foreach (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; sketcherMinimizerMolecule* metaMol = new sketcherMinimizerMolecule; foreach (sketcherMinimizerMolecule* mol, _molecules) { if (mol->m_proximityRelations.size()) { sketcherMinimizerAtom* a = new sketcherMinimizerAtom; a->molecule = metaMol; metaMol->_atoms.push_back(a); molMap[mol] = a; } } foreach (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; foreach (sketcherMinimizerBond* b, metaMol->_bonds) { if ((b->startAtom == at1 && b->endAtom == at2) || (b->startAtom == at2 && b->endAtom == at1)) { found = true; } } if (!found) { sketcherMinimizerBond* newBond = new sketcherMinimizerBond; newBond->startAtom = at1; newBond->endAtom = at2; metaMol->_bonds.push_back(newBond); } } sketcherMinimizer min(m_minimizer.getPrecision()); if (metaMol->_atoms.size()) { min.m_fragmentBuilder.m_evenAngles = true; min.m_minimizer.m_evenAngles = true; min.initialize(metaMol); min.findFragments(); min.m_minimizer.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._molecules) { if (molecule->_rings.size() > 0) { // 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]; foreach (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; foreach (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.size()) { sketcherMinimizerMolecule* mol = q.front(); q.pop(); if (mol->isPlaced) continue; if (mol == centralMol) { mol->isPlaced = true; } else { sketcherMinimizerMolecule* parent = getParent[mol]; if (parent != NULL) placeMolResidueLigandStyle(mol, parent); } foreach (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(); foreach (sketcherMinimizerBond* b, mol->m_proximityRelations) { sketcherMinimizerAtom *at = NULL, *parentAt = NULL; 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 == NULL || parentAt == NULL) continue; n++; sketcherMinimizerPointF paddV = parentAt->getSingleAdditionVector(); if (b->isResidueInteraction()) { sketcherMinimizerResidueInteraction* ri = static_cast(b); if (ri->startAtom->molecule == parent && ri->m_otherStartAtoms.size()) { paddV = sketcherMinimizerAtom::getSingleAdditionVector( ri->getAllStartAtoms()); } else if (ri->endAtom->molecule == parent && ri->m_otherEndAtoms.size()) { 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); float angle = sketcherMinimizerMaths::signedAngle( startingPos - parentV, sketcherMinimizerPointF(0, 0), -additionV) / 180 * M_PI; float s = sin(angle); float c = cos(angle); foreach (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 foreach (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 = NULL; sketcherMinimizerAtom* p2 = NULL; 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(); foreach (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 (unsigned int i = 0; i < _residues.size(); i++) { // replace residues _residues[i]->coordinatesSet = false; } if (_molecules.size() > 1) { // find centers for molecules bound by proximity relations vector proximityMols; foreach (sketcherMinimizerMolecule* mol, _molecules) { if (mol->m_proximityRelations.size()) { proximityMols.push_back(mol); } } sketcherMinimizerPointF center(0.f, 0.f); if (proximityMols.size()) { placeMoleculesWithProximityRelations(proximityMols); } else { int maxI = 0; maxI = 0; int maxSize = _molecules[0]->_atoms.size(); for (unsigned int i = 0; i < _molecules.size(); i++) { sketcherMinimizerMolecule* m = _molecules[i]; int size = m->_atoms.size(); if (size > maxSize) { maxI = i; maxSize = size; } } sketcherMinimizerMolecule* centralMol = _molecules[maxI]; centralMol->isPlaced = true; foreach (sketcherMinimizerAtom* a, _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; foreach (sketcherMinimizerMolecule* mol, _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); foreach (sketcherMinimizerAtom* a, mol->_atoms) { a->coordinates += placeNextTo - counterionCenter; } mol->isPlaced = true; } } } // placing counterions foundCounterion = true; while (foundCounterion) { foundCounterion = false; foreach (sketcherMinimizerMolecule* mol, _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 foreach (sketcherMinimizerMolecule* m, _molecules) { bool found = false; if (!m->isPlaced) continue; foreach (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); foreach (sketcherMinimizerAtom* a, mol->_atoms) { a->coordinates += placeNextTo - counterionCenter; } mol->isPlaced = true; } } } vector ligandAtoms; foreach (sketcherMinimizerAtom* a, _atoms) if (a->m_isLigand) ligandAtoms.push_back(a); placeResidues(ligandAtoms); } } void sketcherMinimizer::initializeFragments() { if (!_fragments.size()) { cerr << "Sketcherlibs warning: no fragments to initialize" << endl; return; } foreach (sketcherMinimizerFragment* indf, _independentFragments) { assignNumberOfChildrenAtomsFromHere( indf); // recursively assign it to children } foreach (sketcherMinimizerFragment* f, _fragments) { m_fragmentBuilder.initializeCoordinates(f); } foreach (sketcherMinimizerFragment* indf, _independentFragments) { assignLongestChainFromHere(indf); // recursively assign it to children } } bool sketcherMinimizer::alignWithParentDirectionConstrained( sketcherMinimizerFragment* fragment, sketcherMinimizerPointF position, float angle) { vector templates, plainCoordinates, flippedCoordinates; float sine = sin(angle); float cosine = cos(angle); for (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.push_back( std::pair(direction, score)); } return chainDirs; } float sketcherMinimizer::testAlignment( sketcherMinimizerPointF direction, 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, 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 (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, 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) { float cumulatedNumberOfAtoms = 0; float cumulatedNumberOfAtomsRanks = 0; float childrenAtoms = 0; foreach (sketcherMinimizerFragment* child, f->_children) { assignNumberOfChildrenAtomsFromHere(child); cumulatedNumberOfAtoms += child->numberOfChildrenAtoms; cumulatedNumberOfAtomsRanks += child->numberOfChildrenAtomsRank; childrenAtoms += child->getAtoms().size(); } f->numberOfChildrenAtoms = cumulatedNumberOfAtoms + childrenAtoms; f->numberOfChildrenAtomsRank = 0.01f * cumulatedNumberOfAtomsRanks + childrenAtoms; } void sketcherMinimizer::assignLongestChainFromHere(sketcherMinimizerFragment* f) { float longestDist = 0; foreach (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 NULL; } sketcherMinimizerAtom* sketcherMinimizer::pickBestAtom(vector& atoms) { vector candidates, oldCandidates; int biggestSize = atoms[0]->fragment->numberOfChildrenAtoms; foreach (sketcherMinimizerAtom* a, atoms) { int 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(); biggestSize = oldCandidates[0]->fragment->numberOfChildrenAtomsRank; foreach (sketcherMinimizerAtom* a, oldCandidates) { int 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(); biggestSize = oldCandidates[0]->atomicNumber; foreach (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(vector constrained) { if (constrained.size() == _referenceAtoms.size()) { for (unsigned int i = 0; i < constrained.size(); i++) { if (constrained[i]) { _referenceAtoms[i]->constrained = true; } } } else { cerr << "warning, wrong size of vector for constrained atoms. Ignoring" << endl; } } void sketcherMinimizer::fixAtoms(vector fixed) { if (fixed.size() == _referenceAtoms.size()) { for (unsigned int i = 0; i < fixed.size(); i++) { if (fixed[i]) _referenceAtoms[i]->fixed = true; } } else { cerr << "warning, wrong size of vector for fixed atoms. Ignoring" << endl; } } void sketcherMinimizer::findClosestAtomToResidues( vector atoms) { if (!atoms.size()) atoms = _atoms; foreach (sketcherMinimizerAtom* r, _residues) { float squareD = 9999999.f; sketcherMinimizerAtom* closestA = NULL; foreach (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); } foreach (sketcherMinimizerBond* b, _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(vector templates, vector points) { assert(templates.size() == points.size()); int 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(vector ref, 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]; float phi = 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]; float theta = 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 * Su[1] * Su[2]); Sig[0] = sqrt((SUsum + SUdif) * 0.5); Sig[1] = 0.f; Sig[2] = 0.f; Sig[3] = sqrt((SUsum - SUdif) * 0.5); 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(vector atoms, 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; unsigned int 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 (unsigned int mb = 0; mb < bonds.size(); mb++) { if (bonds[mb]->bondOrder == 2) { sketcherMinimizerBond* b = bonds[mb]; if (b->m_ignoreZE) continue; bool ok = false; if (b->rings.size() == 0) ok = true; else { ok = true; for (unsigned int rr = 0; rr < b->rings.size(); rr++) { if (b->rings[rr]->_atoms.size() < MACROCYCLE) { ok = false; } } } if (!ok) continue; sketcherMinimizerAtom* startA = b->startAtomCIPFirstNeighbor(); sketcherMinimizerAtom* endA = b->endAtomCIPFirstNeighbor(); sketcherMinimizerAtom* startN = NULL; sketcherMinimizerAtom* endN = NULL; for (unsigned int i = 0; i < b->startAtom->neighbors.size(); i++) { if (b->startAtom->neighbors[i] == b->endAtom) continue; bool found = false; for (unsigned int aa = 0; aa < atoms.size(); aa++) { if (atoms[aa] == 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 (unsigned int aa = 0; aa < atoms.size(); aa++) { if (atoms[aa] == 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; int in2 = bonds[mb]->endAtom->_generalUseN; if (in1 < in2) { molBonds[in2].push_back(in1); } else { molBonds[in1].push_back(in2); } } for (unsigned int tb = 0; tb < templ->_bonds.size(); tb++) { int in1 = templ->_bonds[tb]->startAtom->_generalUseN; int in2 = templ->_bonds[tb]->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, unsigned int size, bool& found, vector& mapping) { solution.push_back(newSol); if (solution.size() == size) { // check double bonds stereo bool doubleBondsStereoOk = true; for (unsigned int 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 = 0; ss < solution.size(); ss++) { if (solution[ss] == i) { check = false; break; } } if (check) { for (unsigned int bi = 0; bi < molBonds[solution.size()].size(); bi++) { check = false; int high = i; int low = solution[molBonds[solution.size()][bi]]; if (low > high) { int swap = low; low = high; high = swap; } for (unsigned int ch = 0; ch < templateBonds[high].size(); ch++) { if (templateBonds[high][ch] == low) { check = true; break; } } if (check == false) break; } } if (check) checkIdentity(solution, i, matrix, templateCoordinates, molBonds, templateBonds, molCisTransChains, molIsCis, size, found, mapping); } } } void sketcherMinimizer::setTemplateFileDir(string dir) { sketcherMinimizer::m_templates.setTemplateDir(dir); } 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("f_m_ct")) != nullptr) { auto molecule = new sketcherMinimizerMolecule(); int atomCounter = 0; // Atom data is in the m_atom indexed block { const auto atom_data = b->getIndexedBlock("m_atom"); // All atoms are gauranteed to have these three field names: const auto atomic_numbers = atom_data->getIntProperty("i_m_atomic_number"); const auto xs = atom_data->getRealProperty("r_m_x_coord"); const auto ys = atom_data->getRealProperty("r_m_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 = new sketcherMinimizerAtom(); atom->coordinates = sketcherMinimizerPointF(xs->at(i), ys->at(i)); atom->atomicNumber = atomic_numbers->at(i); atom->_generalUseN = atomCounter++; molecule->_atoms.push_back(atom); } } // Bond data is in the m_bond indexed block { const auto bond_data = b->getIndexedBlock("m_bond"); // All bonds are gauranteed to have these three field names: auto from_atoms = bond_data->getIntProperty("i_m_from"); auto to_atoms = bond_data->getIntProperty("i_m_to"); auto orders = bond_data->getIntProperty("i_m_order"); const auto size = from_atoms->size(); for (size_t i = 0; i < size; ++i) { // Maestro atoms are 1 indexed! const auto from_atom = from_atoms->at(i) - 1; const auto to_atom = to_atoms->at(i) - 1; const auto order = orders->at(i); auto bond = new sketcherMinimizerBond(); bond->startAtom = molecule->_atoms.at(from_atom); bond->endAtom = molecule->_atoms.at(to_atom); bond->bondOrder = order; molecule->_bonds.push_back(bond); } } templates.push_back(molecule); } fclose(pFile); for (auto mol : templates) { // normalize bond length vector dds; vector ns; for (unsigned int i = 0; i < mol->_bonds.size(); i++) { sketcherMinimizerPointF v = mol->_bonds[i]->startAtom->coordinates - mol->_bonds[i]->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.size()) { 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; } } } } void sketcherMinimizer::loadTemplates() { static int loaded = 0; if (loaded || m_templates.getTemplates().size()) return; string filename = getTempFileProjDir() + "templates.mae"; loadTemplate(filename, m_templates.getTemplates()); filename = getUserTemplateFileName(); loadTemplate(filename, m_templates.getTemplates()); loaded = 1; } int sketcherMinimizer::morganScores(vector atoms, 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; int idx1, idx2; int oldTies = atoms.size(); int newTies = oldTies; 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()); 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; } CoordgenTemplates sketcherMinimizer::m_templates; coordgenlibs-1.3/sketcherMinimizer.h000066400000000000000000000441611351170412600177020ustar00rootroot00000000000000/* * sketcherMinimizer.h * * Created by Nicola Zonta on 13/04/2010. * Copyright Schrodinger, LLC. All rights reserved. * */ #ifndef sketcherMINIMIZER #define sketcherMINIMIZER #include #include #include #include "sketcherMinimizerAtom.h" #include "sketcherMinimizerBond.h" #include "sketcherMinimizerResidue.h" #include "sketcherMinimizerResidueInteraction.h" #include "sketcherMinimizerStretchInteraction.h" #include "sketcherMinimizerClashInteraction.h" #include "sketcherMinimizerBendInteraction.h" #include "sketcherMinimizerFragment.h" #include "sketcherMinimizerMolecule.h" #include "sketcherMinimizerRing.h" #include "sketcherMinimizerMarchingSquares.h" #include #include "CoordgenFragmentBuilder.h" #include "CoordgenMinimizer.h" #include "CoordgenConfig.hpp" static const float SKETCHER_STANDARD_PRECISION = 1.f; static const float SKETCHER_QUICK_PRECISION = 0.2; static const float SKETCHER_BEST_PRECISION = 3; class sketcherAtom; class sketcherBond; class sketcherMolecule; class sketcherMinimimizerInteraction; 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() {} ~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 = dir; if (dir.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(); CoordgenFragmentBuilder m_fragmentBuilder; CoordgenMinimizer m_minimizer; /* run coordinates generation and return true if the pose is considered * optimal */ bool runGenerateCoordinates(); /* 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(); /* initialize data from given molecule */ void initialize(sketcherMinimizerMolecule* minMol); /* put atoms in a canonical order to reduce dependency from order in the * input vector */ static void canonicalOrdering(sketcherMinimizerMolecule* minMol); // void initializeFromMolecule(ChmMol& mol); /* if mol contains separate molecules, split them into a vector */ void splitIntoMolecules(sketcherMinimizerMolecule* mol, std::vector& mols); /* flag atoms that will be drawn with 90° angles (e.g. phosphate P) */ void flagCrossAtoms(); /* assign coordinates to all molecules and residues */ void minimizeAll(); /* assign coordinates to given molecule */ void minimizeMolecule(sketcherMinimizerMolecule* molecule); /* 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, std::vector atoms); /* if a peptide chain is present make sure that the N term is on the left */ void maybeFlipPeptides(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(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(std::vector SSE, const std::vector& shape, int shapeN, std::vector& penalties, float f, float increment); /* score the distance between the two given points of connected residues */ float scoreSSEBondStretch(sketcherMinimizerPointF coordinates1, sketcherMinimizerPointF coordinates2); /* 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, std::vector SSE); /* return the vector index corresponding to floatPosition */ int getShapeIndex(std::vector shape, float floatPosition); /* 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(std::pair solution, 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(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(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( std::map> chains); /* assign coordinates to residues in a protein-protein interaction diagram shaped as a LID */ void placeResiduesProteinOnlyModeLIDStyle( 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( 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( std::map> chains); /* place interacting residues closer to each other, so they end up at the * periphery of the chain */ void shortenInteractions( std::map> chains); /* explore positions in a grid around the current one to ease clashes */ sketcherMinimizerPointF exploreGridAround( sketcherMinimizerPointF centerOfGrid, unsigned int levels, float gridD, float dx = 0.f, float dy = 0.f, float distanceFromAtoms = -1.f, bool watermap = false, sketcherMinimizerResidue* residueForInteractions = NULL, 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); /* return a score of the alignment between direction and templat.first, * weight on the angle between the two and templat.second */ static float testAlignment(sketcherMinimizerPointF direction, 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, std::vector> directions, bool& invert); /* align the fragment to its parent */ static void alignWithParentDirection(sketcherMinimizerFragment* f, sketcherMinimizerPointF position, float angle); /* align the fragment to its parent in the case of constrained coordinates */ static bool alignWithParentDirectionConstrained(sketcherMinimizerFragment* fragment, 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); std::vector getAtoms() { return _atoms; } std::vector _atoms; std::vector _referenceAtoms; std::vector _residues; std::vector _residueInteractions; std::vector _fragments; std::vector _independentFragments; std::vector _bonds; std::vector _referenceBonds; std::vector m_proximityRelations; std::vector m_extraBonds; std::vector _molecules; void assignLongestChainFromHere(sketcherMinimizerFragment* f); void assignNumberOfChildrenAtomsFromHere(sketcherMinimizerFragment* f); // void exportCoordinates(ChmMol& molecule); /* split molecules into rigid fragments */ void findFragments(); /* initialize data and coordinates for each fragment */ void initializeFragments(); /* constrain coordinates on all atoms */ void constrainAllAtoms(); /* constrain coordinates on atoms corresponding to true */ void constrainAtoms(std::vector constrained); /* fix cooordinates (i.e. guarantee they will not change) on atoms marked as * true */ void fixAtoms(std::vector fixed); /* set a flag to enable/disable the scoring of interactions with residues */ void setScoreResidueInteractions(bool b); /* pick one atom out of the vector. Arbitrary criteria such as atomic number * and connectivity are used */ static sketcherMinimizerAtom* pickBestAtom(std::vector& atoms); /* 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); /* for each residue, find the closest atom among atoms, or all atoms if none are given */ void findClosestAtomToResidues(std::vector atoms = std::vector(0)); /* calculate root mean square deviation between templates and points */ static float RMSD(std::vector templates, 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(std::vector ref, 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, unsigned int 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(std::vector atoms, std::vector bonds, sketcherMinimizerMolecule* templ, std::vector& mapping); /* calculate morgan scores for the given input */ static int morganScores(std::vector atoms, std::vector bonds, std::vector& scores); std::string m_chainHint; /* load the templates from the template file */ static void setTemplateFileDir(std::string dir); static void loadTemplates(); static CoordgenTemplates m_templates; }; #endif // sketcherMINIMIZER coordgenlibs-1.3/sketcherMinimizerAtom.cpp000066400000000000000000001457451351170412600210700ustar00rootroot00000000000000/* * sketcherMinimizerAtom.h * * Created by Nicola Zonta on 19/10/2010. * Copyright Schrodinger, LLC. All rights reserved. * */ #include "sketcherMinimizerAtom.h" #include "sketcherMinimizerBond.h" #include "sketcherMinimizer.h" #include "sketcherMinimizerMaths.h" #include #include 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 (unsigned int 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]]; unsigned int s = (meds.size() < meds2.size()) ? meds.size() : meds2.size(); for (unsigned int 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; } unsigned int siz = theseAtoms.size(); if (rhs.theseAtoms.size() < siz) siz = rhs.theseAtoms.size(); for (unsigned int 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 (unsigned int 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 (unsigned int 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 (unsigned int i = 0; i < a.allParents.size(); i++) { os << a.allParents[i]->atomicNumber << "(" << (*a.scores)[a.allParents[i]] << ")"; if ((*a.medals)[a.allParents[i]].size()) { cerr << "<"; for (unsigned int ii = 0; ii < (*a.medals)[a.allParents[i]].size(); ii++) { cerr << (*a.medals)[a.allParents[i]][ii] << "|"; } cerr << ">"; } cerr << " "; } os << "-"; for (unsigned int i = 0; i < a.theseAtoms.size(); i++) { os << " " << a.theseAtoms[i].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 (unsigned int 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]]; unsigned int s = (meds.size() < meds2.size()) ? meds.size() : meds2.size(); for (unsigned int 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; } unsigned int siz = theseAtoms.size(); if (rhs.theseAtoms.size() < siz) siz = rhs.theseAtoms.size(); for (unsigned int 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(){}; 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(NULL), 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.size()) return NULL; if (!atom2->rings.size()) return NULL; foreach (sketcherMinimizerRing* ring, atom1->rings) { if (ring->isMacrocycle()) continue; foreach (sketcherMinimizerRing* ring2, atom2->rings) { if (ring == ring2) return ring; } } foreach (sketcherMinimizerRing* ring, atom1->rings) { foreach (sketcherMinimizerRing* ring2, atom2->rings) { if (ring == ring2) return ring; } } return NULL; } unsigned int sketcherMinimizerAtom::findHsNumber() const { int valence = _valence; if (valence == -10) valence = expectedValence(atomicNumber); // valence is not yet set unsigned int nBondOrders = 0; for (unsigned int i = 0; i < bonds.size(); i++) nBondOrders += bonds[i]->bondOrder; if (atomicNumber == 16) { // sulphite & sulphate int nOs = 0; for (unsigned int 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 (unsigned int 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 orderedNeighs; vector neighs = neighbors; int lastPoppedIndex = 0; sketcherMinimizerAtom* lastPoppedAtom = neighs[lastPoppedIndex]; orderedNeighs.push_back(lastPoppedAtom); neighs.erase(neighs.begin() + lastPoppedIndex); while (neighs.size()) { 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; } } lastPoppedAtom = neighs[lastPoppedIndex]; orderedNeighs.push_back(lastPoppedAtom); neighs.erase(neighs.begin() + lastPoppedIndex); } return orderedNeighs; } void sketcherMinimizerAtom::writeStereoChemistry() // sets stereochemistry for // this atom and from // hasStereochemistrySet and // isR { assert(neighbors.size() == bonds.size()); if (!hasStereochemistrySet) return; int n = neighbors.size(); if (n != 3 && n != 4) { 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.size()) { // 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 = 0; for (unsigned int ai = 0; ai < angles.size(); ai++) totalAngle += angles[ai]; angles.push_back(360.f - totalAngle); if (angles.size() == 3) { for (unsigned int i = 0; i < angles.size(); i++) { if (angles[i] > 180.f) { int precI = i - 1; if (precI < 0) precI += angles.size(); } } } vector atomPriorities, orderedAtomPriorities; for (unsigned int i = 0; i < orderedNeighs.size(); i++) { sketcherMinimizerAtomPriority p; p.a = orderedNeighs[i]; 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 = NULL; 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 == true) || (readS == 1 && isR == false)) { // 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 (unsigned int i = 0; i < bonds.size(); i++) { sketcherMinimizerBond* b = bonds[i]; 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; writeStereoChemistry(); 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 = 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 (unsigned int j = 0; j < center->molecule->_atoms.size(); j++) { center->molecule->_atoms[j]->_generalUseVisited = false; } q.push(atomPriorities[i].a); center->_generalUseVisited = true; atomPriorities[i].a->_generalUseVisited = true; int counter = 0; while (q.size()) { counter++; sketcherMinimizerAtom* at = q.front(); q.pop(); for (unsigned int ni = 0; ni < at->neighbors.size(); ni++) { sketcherMinimizerAtom* n = at->neighbors[ni]; if (!n->_generalUseVisited) { q.push(n); n->_generalUseVisited = true; } } } weights[i] = 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 solphoxide 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 (unsigned int i = 0; i < atomPriorities.size(); i++) { atomPriorities[i].priority = 3; } if (atomPriorities.size() != 4) { // cerr << "coordgen: stereo error. (wrong number of atom priorities: // "<< atomPriorities.size () << ")"< found(4, false); for (unsigned int i = 0; i < atomPriorities.size(); i++) { if (found[atomPriorities[i].priority]) return false; // two atoms have the same priority found[atomPriorities[i].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.size()); 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.push_back(pair(at1->atomicNumber, at1)); v2.push_back(pair(at2->atomicNumber, at2)); vector parents1, parents2; parents1.push_back(center); parents1.push_back(at1); parents2.push_back(center); parents2.push_back(at2); AN1.push_back(CIPAtom(v1, center, parents1, &score1, &medals1, &visited1)); AN2.push_back(CIPAtom(v2, center, parents2, &score2, &medals2, &visited2)); int level = 1; while (AN1.size() || AN2.size()) { level++; 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); unsigned int nn = AN1.size(); if (AN2.size() < nn) nn = AN2.size(); for (unsigned int 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 0; } void sketcherMinimizerAtom::chooseFirstAndSortAccordingly(vector& V) { if (V.size() < 2) return; vector copyV = V; V.clear(); map friendsMask; while (copyV.size()) { 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 (unsigned int i = 0; i < newBest.allParents.size(); i++) { friendsMask[newBest.allParents[i]] |= (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 (unsigned int an = 0; an < oldV.size(); an++) { for (unsigned int aa = 0; aa < oldV[an].theseAtoms.size(); aa++) { sketcherMinimizerAtom* a = oldV[an].theseAtoms[aa].second; if (a == NULL) 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 = oldV[an].visited; map>* medals = oldV[an].medals; map* scores = oldV[an].scores; vector allParents = oldV[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 != oldV[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.push_back(pair( neigh->atomicNumber, ghost ? ((sketcherMinimizerAtom*) NULL) : 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.push_back(pair( neigh->atomicNumber, (sketcherMinimizerAtom*) NULL)); } else if (a->bonds[n]->bondOrder == 3) { theseAts.push_back(pair( neigh->atomicNumber, (sketcherMinimizerAtom*) NULL)); theseAts.push_back(pair( neigh->atomicNumber, (sketcherMinimizerAtom*) NULL)); } } for (int counter = 0; counter < a->_implicitHs; counter++) { // put ghosts for implicit Hs theseAts.push_back(pair( 1, (sketcherMinimizerAtom*) NULL)); } stable_sort(theseAts.begin(), theseAts.end()); reverse(theseAts.begin(), theseAts.end()); newV.push_back( CIPAtom(theseAts, a, allParents, scores, medals, visited)); } } return newV; } void sketcherMinimizerAtom::assignMedals(vector& v) { if (v.size() < 1) 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 (unsigned int pC = 0; pC < v[i].allParents.size(); pC++) { vector medalsV = (*medals)[v[i].allParents[pC]]; while (medalsV.size() < medalLvl) medalsV.push_back(0); if (medalsV.size() > medalLvl) medalsV[medalLvl] = medalsV[medalLvl] + 1; else medalsV.push_back(1); (*medals)[v[i].allParents[pC]] = medalsV; } medalLvl++; } } void sketcherMinimizerAtom::finalizeScores(vector& v) { if (v.size() < 1) 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 (unsigned int pC = 0; pC < v[i].allParents.size(); pC++) { if ((*scores)[v[i].allParents[pC]] == 0) (*scores)[v[i].allParents[pC]] = 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 NULL; } 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.size()) { // 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 (unsigned int ai = 0; ai < angles.size(); ai++) totalAngle += angles[ai]; angles.push_back(360.f - totalAngle); bool semiplane = false; sketcherMinimizerAtom* centralAtom = NULL; if (angles.size() == 3) { for (unsigned int i = 0; i < angles.size(); i++) { if (angles[i] > 180.f) { semiplane = true; int precI = i - 1; if (precI < 0) precI += angles.size(); 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; int 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 (unsigned int i = 0; i < orderedNeighs.size(); i++) { sketcherMinimizerAtomPriority p; p.a = orderedNeighs[i]; 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 (unsigned int nn = 0; nn < neighbors.size(); nn++) { sketcherMinimizerAtom* n = neighbors[nn]; for (unsigned int i = 0; i < atomPriorities.size(); i++) { if (atomPriorities[i].a == n) { m_RSPriorities.push_back(atomPriorities[i].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( 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.size()) { for (unsigned int i = 0; i < neighbors.size(); i++) { float f = 1.f; if (sketcherMinimizer::sameRing(this, neighbors[i])) f = 4.f; out += f * (neighbors[i]->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.size()) { sketcherMinimizerAtom* atom = q.front(); subMolecule.push_back(atom); q.pop(); foreach (sketcherMinimizerAtom* neighbor, atom->neighbors) { if (!isVisited[neighbor]) { q.push(neighbor); isVisited[neighbor] = true; } } } return subMolecule; } coordgenlibs-1.3/sketcherMinimizerAtom.h000066400000000000000000000233141351170412600205200ustar00rootroot00000000000000/* * sketcherMinimizerAtom.h * * Created by Nicola Zonta on 13/04/2010. * Copyright Schrodinger, LLC. All rights reserved. * */ #ifndef sketcherMINIMIZERATOM_H #define sketcherMINIMIZERATOM_H // #include #include #include #include #include "CoordgenConfig.hpp" #include "sketcherMinimizerMaths.h" 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; float 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 = us; parent = dad; scores = scors; medals = meds; visited = visits; allParents = allPars; } 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; } std::vector getBonds() const { return bonds; } 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; 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 (unsigned int i = 0; i < at2->neighbors.size(); i++) { if (at2->neighbors[i] == 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; unsigned 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(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-1.3/sketcherMinimizerBendInteraction.h000066400000000000000000000123671351170412600226760ustar00rootroot00000000000000/* * 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; }; virtual ~sketcherMinimizerBendInteraction(){}; /* 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-1.3/sketcherMinimizerBond.cpp000066400000000000000000000137171351170412600210430ustar00rootroot00000000000000/* 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 NULL; 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; foreach (sketcherMinimizerAtom* n, a->neighbors) { if (n != endAtom) ats.push_back(n); } if (ats.size() == 2) return sketcherMinimizerAtom::CIPPriority(ats[0], ats[1], startAtom); return NULL; } else return NULL; } sketcherMinimizerAtom* sketcherMinimizerBond::endAtomCIPFirstNeighbor() const { if (bondOrder != 2) return NULL; 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; foreach (sketcherMinimizerAtom* n, a->neighbors) { if (n != startAtom) ats.push_back(n); } if (ats.size() == 2) return sketcherMinimizerAtom::CIPPriority(ats[0], ats[1], endAtom); return NULL; } else return NULL; } 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 == NULL) return true; sketcherMinimizerAtom* firstCIPNeighborEnd = endAtomCIPFirstNeighbor(); if (firstCIPNeighborEnd == NULL) 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()); if (ring && !ring->isMacrocycle()) return false; return true; } void sketcherMinimizerBond::flip() { int totalAtomsNumber = getStartAtom()->getMolecule()->getAtoms().size(); vector atoms = getStartAtom()->getSubmolecule(getEndAtom()); if (atoms.size() > totalAtomsNumber * 0.5) { atoms = getEndAtom()->getSubmolecule(getStartAtom()); } vector allBonds = getStartAtom()->getMolecule()->getBonds(); foreach (sketcherMinimizerAtom* atom, atoms) { sketcherMinimizerAtom::mirrorCoordinates(atom, this); } foreach (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-1.3/sketcherMinimizerBond.h000066400000000000000000000072301351170412600205010ustar00rootroot00000000000000/* * sketcherMinimizerBond.h * * Created by Nicola Zonta on 03/05/2010. * Copyright Schrodinger, LLC. All rights reserved. * */ #ifndef sketcherMINIMIZERBOND_H #define sketcherMINIMIZERBOND_H #include #include #include "CoordgenConfig.hpp" 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() : startAtom(NULL), endAtom(NULL), bondOrder(1), skip(false), isZEActive(false), isZ(false), isWedge(false), isReversed(false), hasStereochemistryDisplay(false), _SSSRVisited(false), _SSSRParentAtStart(true), m_ignoreZE(false), _SSSRParent(NULL), rings() { } sketcherMinimizerBond(sketcherMinimizerAtom* at1, sketcherMinimizerAtom* at2) : sketcherMinimizerBond() { startAtom = at1; endAtom = at2; } virtual ~sketcherMinimizerBond(){}; virtual bool isResidueInteraction() { return false; } sketcherMinimizerAtom* startAtom; sketcherMinimizerAtom* endAtom; 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; bool skip; bool isZEActive; // does it have a Z and E form? bool isZ; // 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; bool isReversed; bool hasStereochemistryDisplay; bool _SSSRVisited; bool _SSSRParentAtStart; bool m_ignoreZE; sketcherMinimizerBond* _SSSRParent; std::vector rings; }; #endif // sketcherMINIMIZERBOND_H coordgenlibs-1.3/sketcherMinimizerClashInteraction.h000066400000000000000000000045151351170412600230540ustar00rootroot00000000000000/* * sketcherMinimizerClashInteraction.h * * Created by Nicola Zonta on 19/04/2010. * Copyright Schrodinger, LLC. All rights reserved. * */ #ifndef sketcherMINIMIZERCLASHMINIMIZERINTERACTION #define sketcherMINIMIZERCLASHMINIMIZERINTERACTION #include "sketcherMinimizerInteraction.h" #include #include "sketcherMinimizerMaths.h" /* forcefield clash */ class sketcherMinimizerClashInteraction : public sketcherMinimizerInteraction { public: sketcherMinimizerClashInteraction(sketcherMinimizerAtom* at1, sketcherMinimizerAtom* at2, sketcherMinimizerAtom* at3) : sketcherMinimizerInteraction(at1, at2) { atom3 = at3; restV = 900; k2 = 0.1f; }; virtual ~sketcherMinimizerClashInteraction(){}; /* calculate the energy of the clash */ void energy(float& e) override { float 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; sketcherMinimizerPointF atomP = atom2->coordinates; sketcherMinimizerPointF bondP1 = atom1->coordinates; sketcherMinimizerPointF bondP2 = atom3->coordinates; float squaredDistance = sketcherMinimizerMaths::squaredDistancePointSegment(atomP, bondP1, bondP2); if (squaredDistance > restV) return; 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; }; #endif // sketcherMINIMIZERCLASHINTERACTION coordgenlibs-1.3/sketcherMinimizerConstraintInteraction.h000066400000000000000000000023771351170412600241520ustar00rootroot00000000000000/* * 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, sketcherMinimizerPointF position) : sketcherMinimizerInteraction(at1, at1), origin(position) { k = CONSTRAINT_SCALE; }; virtual ~sketcherMinimizerConstraintInteraction(){}; /* 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); return; }; private: sketcherMinimizerPointF origin; }; #endif // sketcherMINIMIZERCONSTRAINTINTERACTION coordgenlibs-1.3/sketcherMinimizerEZConstrainInteraction.h000066400000000000000000000061701351170412600242200ustar00rootroot00000000000000/* * 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; }; virtual ~sketcherMinimizerEZConstrainInteraction(){}; /* 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-1.3/sketcherMinimizerFragment.cpp000066400000000000000000000317221351170412600217200ustar00rootroot00000000000000/* Contributors: Nicola Zonta Copyright Schrodinger, LLC. All rights reserved */ #include "sketcherMinimizerFragment.h" #include "sketcherMinimizerBond.h" #include "sketcherMinimizerAtom.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 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() { } 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 { if (m_fragment->isChain && m_fragment->getParent() && m_fragment->getParent()->isChain) { return BREAK_CHAIN_PENALTY; } return 0.f; } int CoordgenFlipFragmentDOF::numberOfStates() const { if (m_fragment->getParent() == NULL) 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().size() == 0) return 1; return 5; } int CoordgenScaleFragmentDOF::tier() const { return SCALE_FRAGMENT_TIER; } void CoordgenScaleFragmentDOF::apply() const { if (m_currentState != 0) { float scale = 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.4; 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) { float scale = 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() == NULL) return 1; return 5; } int CoordgenRotateFragmentDOF::tier() const { return ROTATE_FRAGMENT_TIER; } void CoordgenRotateFragmentDOF::apply() const { if (m_currentState != 0) { float angle = 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) != NULL); 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, 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(NULL), longestChainFromHere(0.f), numberOfChildrenAtoms(0), numberOfChildrenAtomsRank(0.f), m_parent(NULL) { 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); } std::vector sketcherMinimizerFragment::getDofs() { return m_dofs; } unsigned int sketcherMinimizerFragment::totalWeight() const { int n = 0; for (unsigned int i = 0; i < m_atoms.size(); i++) n += m_atoms[i]->atomicNumber + m_atoms[i]->_implicitHs; return n; }; unsigned int sketcherMinimizerFragment::countDoubleBonds() const { int n = 0; for (unsigned int i = 0; i < m_bonds.size(); i++) if (m_bonds[i]->bondOrder == 2) ++n; return n; }; unsigned int sketcherMinimizerFragment::countHeavyAtoms() const { int n = 0; for (unsigned int i = 0; i < m_atoms.size(); i++) if (m_atoms[i]->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() { foreach (sketcherMinimizerAtom* atom, m_atoms) { atom->setCoordinatesToTemplate(); } if (_bondToParent) { _bondToParent->startAtom->setCoordinatesToTemplate(); _bondToParent->endAtom->setCoordinatesToTemplate(); } foreach (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(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-1.3/sketcherMinimizerFragment.h000066400000000000000000000201351351170412600213610ustar00rootroot00000000000000/* * * * Created by Nicola Zonta on 03/05/2010. * Copyright Schrodinger, LLC. All rights reserved. * */ #ifndef sketcherMINIMIZERFRAGMENT #define sketcherMINIMIZERFRAGMENT #include #include #include #include #include "sketcherMinimizerMaths.h" 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; int tier() const; void apply() const; float getCurrentPenalty() const; }; /* flip the fragment along the bond to its parent */ class CoordgenFlipFragmentDOF : public CoordgenFragmentDOF { public: CoordgenFlipFragmentDOF(sketcherMinimizerFragment* fragment); int numberOfStates() const; int tier() const; void apply() const; float getCurrentPenalty() const; }; /* scale the coordinates of the given atoms */ class CoordgenScaleAtomsDOF : public CoordgenFragmentDOF { public: CoordgenScaleAtomsDOF(sketcherMinimizerAtom* pivotAtom); int numberOfStates() const; int tier() const; void apply() const; float getCurrentPenalty() const; private: sketcherMinimizerAtom* m_pivotAtom; }; /* scale the coordinates of the whole fragment */ class CoordgenScaleFragmentDOF : public CoordgenFragmentDOF { public: CoordgenScaleFragmentDOF(sketcherMinimizerFragment* fragment); int numberOfStates() const; int tier() const; void apply() const; float getCurrentPenalty() const; }; /* extend or shorten the bond to the parent fragment */ class CoordgenChangeParentBondLengthFragmentDOF : public CoordgenFragmentDOF { public: CoordgenChangeParentBondLengthFragmentDOF( sketcherMinimizerFragment* fragment); int numberOfStates() const; int tier() const; void apply() const; float getCurrentPenalty() const; }; /* 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; int tier() const; void apply() const; float getCurrentPenalty() const; 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, std::vector fusionAtoms); int numberOfStates() const; int tier() const; void apply() const; float getCurrentPenalty() const; private: sketcherMinimizerAtom* m_pivotAtom1; sketcherMinimizerAtom* m_pivotAtom2; int m_penalty; }; /* class that represents a rigid molecular fragment */ class 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 */ 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; bool isChain; sketcherMinimizerBond* _bondToParent; float longestChainFromHere; int numberOfChildrenAtoms; float numberOfChildrenAtomsRank; /* translate and rotate the fragment and set the resulting coordinates to * every atom */ void setCoordinates(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-1.3/sketcherMinimizerInteraction.h000066400000000000000000000037211351170412600220770ustar00rootroot00000000000000/* * 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(){}; /* 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-1.3/sketcherMinimizerMarchingSquares.cpp000066400000000000000000000200141351170412600232410ustar00rootroot00000000000000/* * sketcherMarchingSquares.h * * * Created by Nicola Zonta on 13/3/2011. * Copyright Schrodinger, LLC. All rights reserved * */ #include "sketcherMinimizerMarchingSquares.h" #include #include #include "sketcherMinimizer.h" using namespace std; sketcherMinimizerMarchingSquares::sketcherMinimizerMarchingSquares() { } 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 = (dx / x_interval) + 2; m_YN = (dy / y_interval) + 2; m_grid.clear(); m_grid.resize(m_XN * m_YN, 0.f); m_lastRowPoints.resize(m_XN, NULL); } 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 (unsigned int i = 0; i < m_points.size(); i++) delete m_points[i]; m_points.clear(); for (unsigned int i = 0; i < m_sides.size(); i++) delete m_sides[i]; 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) { sketcherMinimizerMarchingSquaresSide* 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 (unsigned int i = 0; i < m_points.size(); i++) { out.push_back(m_points[i]->x); out.push_back(m_points[i]->y); } return out; } std::vector> sketcherMinimizerMarchingSquares::getOrderedCoordinatesPoints() const { std::vector> out; bool newShape = true; sketcherMinimizerMarchingSquaresPoint* nextPoint = NULL; while (newShape) { newShape = false; nextPoint = NULL; for (unsigned int i = 0; i < m_points.size(); i++) { if (m_points[i]->visited == false) { newShape = true; nextPoint = m_points[i]; break; } } if (nextPoint) { std::vector newVec; while (nextPoint) { nextPoint->visited = true; newVec.push_back(nextPoint->x); newVec.push_back(nextPoint->y); sketcherMinimizerMarchingSquaresPoint* followingPoint1 = NULL; if (nextPoint->side1) followingPoint1 = nextPoint->side1->p1; if (followingPoint1 == nextPoint) followingPoint1 = nextPoint->side1->p2; sketcherMinimizerMarchingSquaresPoint* followingPoint2 = NULL; if (nextPoint->side2) followingPoint2 = nextPoint->side2->p1; if (followingPoint2 == nextPoint) followingPoint2 = nextPoint->side2->p2; bool found = false; if (followingPoint1) if (followingPoint1->visited == false) { nextPoint = followingPoint1; found = true; } if (!found) if (followingPoint2) if (followingPoint2->visited == false) { nextPoint = followingPoint2; found = true; } if (!found) nextPoint = NULL; } out.push_back(newVec); } } return out; } void sketcherMinimizerMarchingSquares::run() { for (unsigned int j = 0; j < m_YN - 1; j++) { m_lastCellRightPoint = NULL; 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 = NULL; sketcherMinimizerMarchingSquaresPoint* tp = NULL; 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(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(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 = NULL, *p2 = NULL; 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 = NULL; } }coordgenlibs-1.3/sketcherMinimizerMarchingSquares.h000066400000000000000000000056001351170412600227120ustar00rootroot00000000000000/* * sketcherMarchingSquares.h * * * Created by Nicola Zonta on 19/11/2010. * Copyright Schrodinger, LLC. All rights reserved * */ #ifndef sketcherMINIMIZERMARCHINGSQUARES_H #define sketcherMINIMIZERMARCHINGSQUARES_H #include #include #include "CoordgenConfig.hpp" class sketcherMinimizerPointF; struct sketcherMinimizerMarchingSquaresPoint; struct sketcherMinimizerMarchingSquaresSide { sketcherMinimizerMarchingSquaresPoint* p1; sketcherMinimizerMarchingSquaresPoint* p2; }; struct sketcherMinimizerMarchingSquaresPoint { public: sketcherMinimizerMarchingSquaresPoint(float ix, float iy) { x = ix; y = iy; side1 = NULL; side2 = NULL; 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 std::vector /* 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 */ getCoordinatesPoints() const; std::vector> /* 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. */ getOrderedCoordinatesPoints() const; inline std::vector getRawData() const { return m_grid; }; // returns a vector of all the data set with setValue. float getNodeValue(unsigned int i, unsigned int j) 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-1.3/sketcherMinimizerMaths.h000066400000000000000000000551051351170412600206770ustar00rootroot00000000000000/* * 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 #ifndef foreach #define foreach SKETCHER_FOREACH #endif #define SKETCHER_FOREACH(variable, container) for (variable : container) inline float roundToTwoDecimalDigits(float f) { return floor(f * 100 + 0.5) * 0.01; } inline float roundToPrecision(float f, int precision) { return 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() : xp(0.f), yp(0.f){}; sketcherMinimizerPointF(const sketcherMinimizerPointF& p) : xp(p.x()), yp(p.y()){}; sketcherMinimizerPointF(float xpos, float ypos) : xp(xpos), yp(ypos){}; 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(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; }; sketcherMinimizerPointF& operator*=(float c) { xp *= c; yp *= c; return *this; }; sketcherMinimizerPointF& operator/=(float c) { xp /= c; yp /= 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); }; friend inline const sketcherMinimizerPointF operator*(const sketcherMinimizerPointF& p1, float c) { return sketcherMinimizerPointF(p1.xp * c, p1.yp * c); }; friend inline const sketcherMinimizerPointF operator/(const sketcherMinimizerPointF& p1, float c) { return sketcherMinimizerPointF(p1.xp / c, p1.yp / c); }; 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; float yp; }; /* 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(sketcherMinimizerPointF s1p1, sketcherMinimizerPointF s1p2, sketcherMinimizerPointF s2p1, sketcherMinimizerPointF s2p2, sketcherMinimizerPointF* result = NULL) { /* 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. */ sketcherMinimizerPointF p = s1p1; sketcherMinimizerPointF r = s1p2 - s1p1; sketcherMinimizerPointF q = s2p1; sketcherMinimizerPointF s = s2p2 - s2p1; int 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(sketcherMinimizerPointF p1, sketcherMinimizerPointF p2, 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(sketcherMinimizerPointF p1, sketcherMinimizerPointF p2, 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(sketcherMinimizerPointF p1, 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((float) (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(sketcherMinimizerPointF p, sketcherMinimizerPointF sp1, 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(sketcherMinimizerPointF p, sketcherMinimizerPointF sp1, sketcherMinimizerPointF sp2, float* returnT = NULL) { sketcherMinimizerPointF l1 = p - sp1; sketcherMinimizerPointF l2 = sp2 - p; sketcherMinimizerPointF l3 = sp2 - sp1; float segmentl = sqrt(l3.x() * l3.x() + l3.y() * l3.y()); // float l1l = sqrt ( l1.x () * l1.x () + l1.y() * l1.y() ); if (segmentl < SKETCHER_EPSILON) segmentl = SKETCHER_EPSILON; float t = (l1.x() * l3.x() + l1.y() * l3.y()) / (segmentl * segmentl); if (returnT != NULL) { 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(sketcherMinimizerPointF p1, sketcherMinimizerPointF p2) { return (p1.x() - p2.x()) * (p1.x() - p2.x()) + (p1.y() - p2.y()) * (p1.y() - p2.y()); } static std::vector tridiagonalSolve(std::vector a, std::vector b, std::vector c, std::vector rhs) { assert(a.size() == b.size() && a.size() == c.size() && a.size() == rhs.size()); assert(b[0] != 0.f); unsigned int n = (unsigned int) 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(std::vector a, std::vector b, std::vector c, float alpha, float beta, std::vector rhs) { assert(a.size() == b.size() && a.size() == c.size()); unsigned int n = (unsigned int) 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(sketcherMinimizerPointF p1, sketcherMinimizerPointF cp1, sketcherMinimizerPointF cp2, 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( std::vector knots, std::vector& firstControlPoints, std::vector& secondControlPoints) { unsigned int n = (unsigned int) 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(sketcherMinimizerPointF point, sketcherMinimizerPointF segmentPoint1, 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(sketcherMinimizerPointF a, sketcherMinimizerPointF b) { return (a.x() * b.x() + a.y() * b.y()); } /* cross product of two vectors */ static float crossProduct(sketcherMinimizerPointF a, 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 acos(dp / (l1 * l2)) * 180.f / M_PI; } /* diheadral 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-1.3/sketcherMinimizerMolecule.cpp000066400000000000000000000202741351170412600217220ustar00rootroot00000000000000/* * 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(NULL), m_requireMinimization(false){}; sketcherMinimizerMolecule::~sketcherMinimizerMolecule() { for (auto ring : _rings) { delete ring; } }; 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 (unsigned int i = 0; i < _atoms.size(); i++) charge += _atoms[i]->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.size()) { min = _atoms[0]->coordinates; max = _atoms[0]->coordinates; for (unsigned int i = 0; i < _atoms.size(); i++) { sketcherMinimizerAtom* a = _atoms[i]; 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.size()) return sketcherMinimizerPointF(0.f, 0.f); sketcherMinimizerPointF c(.0f, .0f); for (unsigned int i = 0; i < _atoms.size(); i++) { c += _atoms[i]->coordinates; } return c / _atoms.size(); } void sketcherMinimizerMolecule::assignBondsAndNeighbors( std::vector& atoms, std::vector& bonds) { for (unsigned int i = 0; i < atoms.size(); i++) { sketcherMinimizerAtom* atom = atoms[i]; atom->bonds.clear(); atom->neighbors.clear(); atom->residueInteractionPartners.clear(); atom->residueInteractions.clear(); atom->rings.clear(); } for (unsigned int i = 0; i < bonds.size(); i++) { sketcherMinimizerBond* bond = bonds[i]; 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 (unsigned int i = 0; i < atoms.size(); i++) { if (atoms[i]->_implicitHs == -1) atoms[i]->_implicitHs = atoms[i]->findHsNumber(); } } void sketcherMinimizerMolecule::forceUpdateStruct( std::vector& atoms, std::vector& bonds, std::vector& rings) { sketcherMinimizerMolecule::assignBondsAndNeighbors(atoms, bonds); findRings(bonds, rings); for (unsigned int i = 0; i < bonds.size(); i++) { for (unsigned int j = 0; j < bonds[i]->rings.size(); j++) { sketcherMinimizerRing* ring = bonds[i]->rings[j]; bool found = false; for (unsigned int k = 0; k < bonds[i]->startAtom->rings.size(); k++) { if (bonds[i]->startAtom->rings[k] == ring) { found = true; break; } } if (!found) bonds[i]->startAtom->rings.push_back(ring); found = false; for (unsigned int k = 0; k < bonds[i]->endAtom->rings.size(); k++) { if (bonds[i]->endAtom->rings[k] == ring) { found = true; break; } } if (!found) bonds[i]->endAtom->rings.push_back(ring); } } for (unsigned int i = 0; i < atoms.size(); i++) { for (unsigned int j = 0; j < atoms[i]->rings.size(); j++) { atoms[i]->rings[j]->_atoms.push_back(atoms[i]); } } } void sketcherMinimizerMolecule::findRings( std::vector& bonds, std::vector& rings) { for (unsigned int i = 0; i < rings.size(); i++) delete rings[i]; rings.clear(); for (unsigned int i = 0; i < bonds.size(); i++) { for (unsigned int ii = 0; ii < bonds.size(); ii++) { bonds[ii]->_SSSRVisited = false; bonds[ii]->_SSSRParent = NULL; bonds[ii]->_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 (unsigned int i = 0; i < rings.size(); i++) { sketcherMinimizerRing* ring = rings[i]; 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) { sketcherMinimizerRing* 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 (unsigned int i = 0; i < rings.size(); i++) { if (rings[i]->sameAs(ring)) { found = true; break; } } if (!found) { rings.push_back(ring); } else { delete ring; } } coordgenlibs-1.3/sketcherMinimizerMolecule.h000066400000000000000000000073601351170412600213700ustar00rootroot00000000000000/* * sketcherMinimizerMolecule.h * * Created by Nicola Zonta on 03/05/2010. * Copyright Schrodinger, LLC. All rights reserved. * */ #include #include #include "CoordgenConfig.hpp" #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 = 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-1.3/sketcherMinimizerResidue.cpp000066400000000000000000000007021351170412600215470ustar00rootroot00000000000000/* * sketcherMinimizerResidue.cpp * * Created by Nicola Zonta on 13/05/2011. * Copyright Schrodinger, LLC. All rights reserved. * */ #include "sketcherMinimizerResidue.h" using namespace std; sketcherMinimizerResidue::sketcherMinimizerResidue() : sketcherMinimizerAtom() { m_closestLigandAtom = NULL; } sketcherMinimizerResidue::~sketcherMinimizerResidue() { } bool sketcherMinimizerResidue::isResidue() const { return true; } coordgenlibs-1.3/sketcherMinimizerResidue.h000066400000000000000000000034201351170412600212140ustar00rootroot00000000000000/* * 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(); virtual ~sketcherMinimizerResidue(); virtual bool isResidue() const; /* 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 (unsigned int i = 0; i < residueInteractions.size(); i++) { sketcherMinimizerAtom* n = residueInteractions[i]->endAtom; if (n == this) n = residueInteractions[i]->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-1.3/sketcherMinimizerResidueInteraction.cpp000066400000000000000000000016211351170412600237500ustar00rootroot00000000000000/* * 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() { } 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-1.3/sketcherMinimizerResidueInteraction.h000066400000000000000000000020331351170412600234130ustar00rootroot00000000000000/* * 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(); virtual ~sketcherMinimizerResidueInteraction(); virtual bool isResidueInteraction(); /* 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-1.3/sketcherMinimizerRing.cpp000066400000000000000000000104731351170412600210540ustar00rootroot00000000000000/* * 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() { } sketcherMinimizerPointF sketcherMinimizerRing::findCenter() { sketcherMinimizerPointF o(0.f, 0.f); for (unsigned int i = 0; i < _atoms.size(); i++) o += _atoms[i]->coordinates; o /= _atoms.size(); return o; } bool sketcherMinimizerRing::isBenzene() { if (_atoms.size() != 6) return false; for (unsigned int i = 0; i < _atoms.size(); i++) if (_atoms[i]->atomicNumber != 6) return false; for (unsigned int i = 0; i < _atoms.size(); i++) { sketcherMinimizerAtom* a = _atoms[i]; bool found = false; for (unsigned int j = 0; j < a->bonds.size(); j++) { if (a->bonds[j]->bondOrder == 2) { found = true; break; } } if (!found) return false; } return true; } bool sketcherMinimizerRing::isAromatic() // not chemically accurate, but good // enough for minimizer { int bonds = _bonds.size(); int doubleBonds = 0; int NSOCount = 0; for (unsigned int i = 0; i < _bonds.size(); i++) { if (_bonds[i]->bondOrder == 2) doubleBonds++; } for (unsigned int i = 0; i < _atoms.size(); i++) { int an = _atoms[i]->atomicNumber; bool doubleBound = false; for (unsigned int b = 0; b < _atoms[i]->bonds.size(); b++) if (_atoms[i]->bonds[b]->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 (unsigned int i = 0; i < _atoms.size(); i++) if (_atoms[i] == a) return true; return false; } bool sketcherMinimizerRing::containsBond(sketcherMinimizerBond* b) { for (unsigned int i = 0; i < _bonds.size(); i++) if (_bonds[i] == b) return true; return false; } bool sketcherMinimizerRing::isFusedWith(sketcherMinimizerRing* ring) { for (unsigned int i = 0; i < fusedWith.size(); i++) { if (fusedWith[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 (unsigned int i = 0; i < _bonds.size(); i++) { if (!ring->containsBond(_bonds[i])) { return false; } } return true; } bool sketcherMinimizerRing::contains(sketcherMinimizerPointF p) { int n = 0; for (unsigned int i = 0; i < _bonds.size(); i++) { sketcherMinimizerBond* b = _bonds[i]; 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++; } } } if ((n % 2) != 0) return true; return false; } // std::vector _bonds; coordgenlibs-1.3/sketcherMinimizerRing.h000066400000000000000000000043231351170412600205160ustar00rootroot00000000000000/* * sketcherMinimizerRing.h * * Created by Nicola Zonta on 03/05/2010. * Copyright Schrodinger, LLC. All rights reserved. * */ #include #include #include "sketcherMinimizerMaths.h" #include "CoordgenConfig.hpp" #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 (int) _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(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-1.3/sketcherMinimizerStretchInteraction.h000066400000000000000000000025101351170412600234270ustar00rootroot00000000000000/* * 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){}; virtual ~sketcherMinimizerStretchInteraction(){}; /* 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 = restV - m; float shortBondThreshold = restV * 0.4; 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; }; }; #endif // sketcherMINIMIZERSTRETCHINTERACTION coordgenlibs-1.3/templates.mae000066400000000000000000005127121351170412600165210ustar00rootroot00000000000000{ 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 1 entry /Users/nicola/schrodinger/coordgen_standalone templates.mae 1 templates->templates->templates templates->templates1->templates11 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 900 2 6 A0A0A0 2 7 4.195900 -5.285600 0.000000 900 2 6 A0A0A0 3 7 4.195900 -3.857000 0.000000 900 2 6 A0A0A0 4 2 5.433100 -3.142700 0.000000 900 2 6 A0A0A0 5 7 6.670300 -3.857000 0.000000 900 2 6 A0A0A0 6 7 6.670300 -5.285600 0.000000 900 2 6 A0A0A0 7 7 3.208400 -6.993000 0.000000 900 2 6 A0A0A0 8 7 1.970400 -7.705800 0.000000 900 2 6 A0A0A0 9 2 1.968600 -9.134300 0.000000 900 2 6 A0A0A0 10 7 3.205000 -9.850100 0.000000 900 2 6 A0A0A0 11 7 4.443000 -9.137300 0.000000 900 2 6 A0A0A0 12 2 4.444700 -7.708700 0.000000 900 2 6 A0A0A0 13 7 -0.007200 -7.705600 0.000000 900 2 6 A0A0A0 14 7 -1.245100 -6.992600 0.000000 900 2 6 A0A0A0 15 2 -2.481500 -7.708100 0.000000 900 2 6 A0A0A0 16 7 -2.480000 -9.136700 0.000000 900 2 6 A0A0A0 17 7 -1.242100 -9.849700 0.000000 900 2 6 A0A0A0 18 2 -0.005700 -9.134100 0.000000 900 2 6 A0A0A0 19 2 -3.469800 -5.999100 0.000000 900 2 6 A0A0A0 20 7 -2.232600 -5.284900 0.000000 900 2 6 A0A0A0 21 7 -2.232500 -3.856300 0.000000 900 2 6 A0A0A0 22 2 -3.469700 -3.142000 0.000000 900 2 6 A0A0A0 23 7 -4.706900 -3.856200 0.000000 900 2 6 A0A0A0 24 7 -4.706900 -5.284800 0.000000 900 2 6 A0A0A0 25 7 -2.479600 -0.004500 0.000000 900 2 6 A0A0A0 26 2 -2.481300 -1.433100 0.000000 900 2 6 A0A0A0 27 7 -1.244900 -2.148800 0.000000 900 2 6 A0A0A0 28 7 -0.006900 -1.436000 0.000000 900 2 6 A0A0A0 29 2 -0.005200 -0.007400 0.000000 900 2 6 A0A0A0 30 7 -1.241600 0.708300 0.000000 900 2 6 A0A0A0 31 7 3.208400 -2.149200 0.000000 900 2 6 A0A0A0 32 7 1.970500 -1.436200 0.000000 900 2 6 A0A0A0 33 2 1.969100 -0.007600 0.000000 900 2 6 A0A0A0 34 7 3.205500 0.707900 0.000000 900 2 6 A0A0A0 35 7 4.443400 -0.005100 0.000000 900 2 6 A0A0A0 36 2 4.444900 -1.433700 0.000000 900 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_st_Chirality_1 s_m_subgroup_title s_m_subgroupid b_m_subgroup_collapsed i_m_ct_format ::: CRDGEN-118_template 2 CRDGEN-118_template.1 /Users/nicola/schrodinger/coordgen_standalone templates.mae 2 9_R_8_6_10 templates->templates->templates templates->templates1->templates11 0 2 m_depend[1] { # First column is dependency index # i_m_depend_dependency s_m_depend_property ::: 1 10 s_st_Chirality_1 ::: } 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 900 2 6 A0A0A0 C1 2 7 -6.772600 1.617700 0.000000 900 2 6 A0A0A0 C2 3 7 -6.574500 0.816900 0.000000 900 2 6 A0A0A0 C3 4 7 -5.781800 0.588100 0.000000 900 2 6 A0A0A0 C4 5 2 -5.187400 1.160100 0.000000 900 2 6 A0A0A0 C5 6 2 -5.385500 1.960900 0.000000 900 2 6 A0A0A0 C6 7 29 -6.205500 3.014300 0.000000 900 43 7 5757FF N7 8 5 -5.429700 3.295100 0.000000 900 2 6 A0A0A0 C8 9 4 -4.791000 2.533000 0.000000 900 2 6 A0A0A0 C9 10 7 -3.880500 2.628300 0.000000 900 2 6 A0A0A0 C10 11 29 -4.247400 0.695600 0.000000 900 43 7 5757FF N11 12 5 -3.813500 -0.134700 0.000000 900 2 6 A0A0A0 C12 13 5 -2.696800 -0.068900 0.000000 900 2 6 A0A0A0 C14 14 7 -3.113100 2.296900 0.000000 900 2 6 A0A0A0 C15 15 7 -2.899600 1.500000 0.000000 900 2 6 A0A0A0 C16 16 7 -2.102700 1.286500 0.000000 900 2 6 A0A0A0 C17 17 7 -1.889200 0.489600 0.000000 900 2 6 A0A0A0 C18 18 7 -1.092300 0.276100 0.000000 900 2 6 A0A0A0 C19 19 5 -1.400400 -0.510900 0.000000 900 2 6 A0A0A0 C20 20 5 0.103700 0.542600 0.000000 900 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 ::: "Untitled Document-1" 3 template.1_mol1 /Users/nicola/schrodinger/coordgen_standalone templates.mae 3 templates->templates->templates templates->templates1->templates11 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 900 2 6 A0A0A0 2 5 -0.561400 1.399200 0.000000 900 2 6 A0A0A0 3 5 0.153000 0.986700 0.000000 900 2 6 A0A0A0 4 5 0.867500 1.399200 0.000000 900 2 6 A0A0A0 5 4 0.867500 2.224200 0.000000 900 2 6 A0A0A0 6 5 0.153000 2.636700 0.000000 900 2 6 A0A0A0 7 5 0.153000 3.461700 0.000000 900 2 6 A0A0A0 8 5 0.867500 3.874200 0.000000 900 2 6 A0A0A0 9 5 1.582000 2.636700 0.000000 900 2 6 A0A0A0 10 4 1.582000 3.461700 0.000000 900 2 6 A0A0A0 11 5 2.296400 3.874200 0.000000 900 2 6 A0A0A0 12 5 2.296400 4.699200 0.000000 900 2 6 A0A0A0 13 5 1.582000 5.111700 0.000000 900 2 6 A0A0A0 14 5 0.867500 4.699200 0.000000 900 2 6 A0A0A0 15 5 0.153000 5.111700 0.000000 900 2 6 A0A0A0 16 5 -0.561400 4.699200 0.000000 900 2 6 A0A0A0 17 5 -0.561400 3.874200 0.000000 900 2 6 A0A0A0 18 4 -1.275900 3.461700 0.000000 900 2 6 A0A0A0 19 4 -1.275900 2.636700 0.000000 900 2 6 A0A0A0 20 5 -1.990400 3.874200 0.000000 900 2 6 A0A0A0 21 5 -2.704900 3.461700 0.000000 900 2 6 A0A0A0 22 5 -2.704900 2.636700 0.000000 900 2 6 A0A0A0 23 5 -1.990400 2.224200 0.000000 900 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 ::: "Untitled Document-1" 4 template.1_mol2 /Users/nicola/schrodinger/coordgen_standalone templates.mae 4 templates->templates->templates templates->templates1->templates11 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 900 2 6 A0A0A0 2 5 -1.663800 -2.571700 0.000000 900 2 6 A0A0A0 3 5 -0.838800 -2.571700 0.000000 900 2 6 A0A0A0 4 5 -0.426300 -3.286200 0.000000 900 2 6 A0A0A0 5 4 0.398700 -3.286200 0.000000 900 2 6 A0A0A0 6 5 0.769000 -4.023400 0.000000 900 2 6 A0A0A0 7 5 1.592000 -4.080900 0.000000 900 2 6 A0A0A0 8 5 2.061300 -3.402400 0.000000 900 2 6 A0A0A0 9 5 0.811200 -2.571700 0.000000 900 2 6 A0A0A0 10 4 1.717100 -2.652600 0.000000 900 2 6 A0A0A0 11 5 2.129600 -1.938100 0.000000 900 2 6 A0A0A0 12 5 1.717100 -1.223700 0.000000 900 2 6 A0A0A0 13 5 0.892100 -1.223700 0.000000 900 2 6 A0A0A0 14 5 0.479600 -0.509200 0.000000 900 2 6 A0A0A0 15 5 -0.234900 -0.096700 0.000000 900 2 6 A0A0A0 16 5 -0.234900 0.728300 0.000000 900 2 6 A0A0A0 17 5 -0.949400 1.140800 0.000000 900 2 6 A0A0A0 18 5 -1.663800 0.728300 0.000000 900 2 6 A0A0A0 19 5 -1.663800 -0.096700 0.000000 900 2 6 A0A0A0 20 4 -2.378300 -0.509200 0.000000 900 2 6 A0A0A0 21 4 -2.378300 -1.334200 0.000000 900 2 6 A0A0A0 22 5 -3.092800 -0.096700 0.000000 900 2 6 A0A0A0 23 5 -3.807200 -0.509200 0.000000 900 2 6 A0A0A0 24 5 -3.807200 -1.334200 0.000000 900 2 6 A0A0A0 25 5 -3.092800 -1.746700 0.000000 900 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 ::: "Untitled Document-1" 5 template.1_mol3 /Users/nicola/schrodinger/coordgen_standalone templates.mae 5 templates->templates->templates templates->templates1->templates11 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 900 2 6 A0A0A0 2 5 0.071600 -8.387500 0.000000 900 2 6 A0A0A0 3 5 0.786100 -8.800000 0.000000 900 2 6 A0A0A0 4 5 1.500500 -8.387500 0.000000 900 2 6 A0A0A0 5 4 2.215000 -8.800000 0.000000 900 2 6 A0A0A0 6 5 2.215000 -9.625000 0.000000 900 2 6 A0A0A0 7 5 2.929500 -10.037500 0.000000 900 2 6 A0A0A0 8 5 3.643900 -9.625000 0.000000 900 2 6 A0A0A0 9 5 2.929500 -8.387500 0.000000 900 2 6 A0A0A0 10 4 3.643900 -8.800000 0.000000 900 2 6 A0A0A0 11 5 4.358400 -8.387500 0.000000 900 2 6 A0A0A0 12 5 4.358400 -7.562500 0.000000 900 2 6 A0A0A0 13 5 3.643900 -7.150000 0.000000 900 2 6 A0A0A0 14 5 3.643900 -6.325000 0.000000 900 2 6 A0A0A0 15 5 2.929500 -5.912500 0.000000 900 2 6 A0A0A0 16 5 2.929500 -5.087500 0.000000 900 2 6 A0A0A0 17 5 2.215000 -4.675000 0.000000 900 2 6 A0A0A0 18 7 1.500500 -5.087500 0.000000 900 2 6 A0A0A0 19 7 1.500500 -5.912500 0.000000 900 2 6 A0A0A0 20 5 0.786100 -6.325000 0.000000 900 2 6 A0A0A0 21 5 0.071600 -5.912500 0.000000 900 2 6 A0A0A0 22 4 -0.642900 -6.325000 0.000000 900 2 6 A0A0A0 23 4 -0.642900 -7.150000 0.000000 900 2 6 A0A0A0 24 5 -1.357400 -5.912500 0.000000 900 2 6 A0A0A0 25 5 -2.071800 -6.325000 0.000000 900 2 6 A0A0A0 26 5 -2.071800 -7.150000 0.000000 900 2 6 A0A0A0 27 5 -1.357400 -7.562500 0.000000 900 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 ::: "Untitled Document-1" 6 template.1_mol4 /Users/nicola/schrodinger/coordgen_standalone templates.mae 6 templates->templates->templates templates->templates1->templates11 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 900 2 6 A0A0A0 2 5 -1.746800 7.192300 0.000000 900 2 6 A0A0A0 3 5 -0.921800 7.192300 0.000000 900 2 6 A0A0A0 4 5 -0.509300 6.477800 0.000000 900 2 6 A0A0A0 5 4 0.315700 6.477800 0.000000 900 2 6 A0A0A0 6 5 0.728200 5.763300 0.000000 900 2 6 A0A0A0 7 5 1.553200 5.763300 0.000000 900 2 6 A0A0A0 8 5 1.965700 6.477800 0.000000 900 2 6 A0A0A0 9 5 0.728200 7.192300 0.000000 900 2 6 A0A0A0 10 4 1.553200 7.192300 0.000000 900 2 6 A0A0A0 11 5 1.965700 7.906800 0.000000 900 2 6 A0A0A0 12 5 1.553200 8.608600 0.000000 900 2 6 A0A0A0 13 5 0.728200 8.608600 0.000000 900 2 6 A0A0A0 14 5 0.315700 9.323100 0.000000 900 2 6 A0A0A0 15 5 -0.509300 9.323100 0.000000 900 2 6 A0A0A0 16 5 -0.921800 10.037500 0.000000 900 2 6 A0A0A0 17 5 -1.746800 10.037500 0.000000 900 2 6 A0A0A0 18 5 -2.159300 9.323100 0.000000 900 2 6 A0A0A0 19 4 -2.929500 9.027400 0.000000 900 2 6 A0A0A0 20 4 -2.929500 8.202400 0.000000 900 2 6 A0A0A0 21 5 -3.643900 9.439900 0.000000 900 2 6 A0A0A0 22 5 -4.358400 9.027400 0.000000 900 2 6 A0A0A0 23 5 -4.358400 8.202400 0.000000 900 2 6 A0A0A0 24 5 -3.643900 7.789900 0.000000 900 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.mol 7 template.1 /Users/nicola/schrodinger/coordgen_standalone templates.mae 7 templates->templates->templates templates->templates1->templates11 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 900 2 6 A0A0A0 2 5 -0.714500 0.206200 0.000000 900 2 6 A0A0A0 3 5 -1.428900 -0.206300 0.000000 900 2 6 A0A0A0 4 5 -1.428900 -1.031300 0.000000 900 2 6 A0A0A0 5 4 -0.714500 -1.443800 0.000000 900 2 6 A0A0A0 6 5 -0.714500 -2.268800 0.000000 900 2 6 A0A0A0 7 5 -0.000000 -2.681200 0.000000 900 2 6 A0A0A0 8 5 0.714500 -2.268800 0.000000 900 2 6 A0A0A0 9 5 0.000000 -1.031300 0.000000 900 2 6 A0A0A0 10 4 0.714500 -1.443800 0.000000 900 2 6 A0A0A0 11 5 1.428900 -1.031300 0.000000 900 2 6 A0A0A0 12 5 2.143400 -1.443800 0.000000 900 2 6 A0A0A0 13 5 2.857900 -1.031300 0.000000 900 2 6 A0A0A0 14 5 2.857900 -0.206300 0.000000 900 2 6 A0A0A0 15 5 2.143400 0.206200 0.000000 900 2 6 A0A0A0 16 5 2.143400 1.031200 0.000000 900 2 6 A0A0A0 17 5 1.428900 1.443700 0.000000 900 2 6 A0A0A0 18 5 1.428900 2.268700 0.000000 900 2 6 A0A0A0 19 5 0.714500 2.681200 0.000000 900 2 6 A0A0A0 20 5 0.000000 2.268700 0.000000 900 2 6 A0A0A0 21 5 -0.714500 2.681200 0.000000 900 2 6 A0A0A0 22 4 -1.428900 2.268700 0.000000 900 2 6 A0A0A0 23 4 -1.428900 1.443700 0.000000 900 2 6 A0A0A0 24 5 -2.143400 2.681200 0.000000 900 2 6 A0A0A0 25 5 -2.857900 2.268700 0.000000 900 2 6 A0A0A0 26 5 -2.857900 1.443700 0.000000 900 2 6 A0A0A0 27 5 -2.143400 1.031200 0.000000 900 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.mol 8 template.1 /Users/nicola/schrodinger/coordgen_standalone templates.mae 8 templates->templates->templates templates->templates1->templates11 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 900 2 6 A0A0A0 2 5 -0.714400 -0.178900 0.000000 900 2 6 A0A0A0 3 5 -0.000000 -0.591400 0.000000 900 2 6 A0A0A0 4 5 0.714400 -0.178900 0.000000 900 2 6 A0A0A0 5 4 1.428900 -0.591400 0.000000 900 2 6 A0A0A0 6 5 1.428900 -1.416400 0.000000 900 2 6 A0A0A0 7 5 2.143300 -1.828800 0.000000 900 2 6 A0A0A0 8 5 2.857800 -1.416400 0.000000 900 2 6 A0A0A0 9 5 2.143300 -0.178900 0.000000 900 2 6 A0A0A0 10 4 2.857800 -0.591400 0.000000 900 2 6 A0A0A0 11 5 3.572300 -0.178900 0.000000 900 2 6 A0A0A0 12 5 3.572300 0.646100 0.000000 900 2 6 A0A0A0 13 5 2.845200 1.058600 0.000000 900 2 6 A0A0A0 14 5 2.549500 1.828800 0.000000 900 2 6 A0A0A0 15 5 1.724500 1.828800 0.000000 900 2 6 A0A0A0 16 5 1.428900 1.058600 0.000000 900 2 6 A0A0A0 17 5 0.714400 0.646100 0.000000 900 2 6 A0A0A0 18 5 -0.000000 1.058600 0.000000 900 2 6 A0A0A0 19 5 -0.714400 0.646100 0.000000 900 2 6 A0A0A0 20 5 -1.428900 1.058600 0.000000 900 2 6 A0A0A0 21 4 -2.143400 0.646100 0.000000 900 2 6 A0A0A0 22 4 -2.143400 -0.178900 0.000000 900 2 6 A0A0A0 23 5 -2.857800 1.058600 0.000000 900 2 6 A0A0A0 24 5 -3.572300 0.646100 0.000000 900 2 6 A0A0A0 25 5 -3.572300 -0.178900 0.000000 900 2 6 A0A0A0 26 5 -2.857800 -0.591400 0.000000 900 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 ::: "Untitled Document-1" 9 newTemp.1 /Users/nicola/schrodinger/coordgen_standalone templates.mae 9 templates->templates->templates templates->templates1->templates11 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 900 2 6 0 A0A0A0 2 7 -1.464000 -1.720700 0.000000 900 2 6 0 A0A0A0 3 7 -2.178500 -1.308200 0.000000 900 2 6 0 A0A0A0 4 2 -2.178500 -0.483200 0.000000 900 2 6 0 A0A0A0 5 7 -2.893000 -0.070700 0.000000 900 2 6 0 A0A0A0 6 7 -2.893000 0.754300 0.000000 900 2 6 0 A0A0A0 7 7 -2.178500 1.166800 0.000000 900 2 6 0 A0A0A0 8 2 -1.464000 0.754300 0.000000 900 2 6 0 A0A0A0 9 18 -0.648200 0.876700 0.000000 900 70 8 -1 FF2F2F 10 2 -1.464000 -0.070700 0.000000 900 2 6 0 A0A0A0 11 31 -0.749600 -0.483200 0.000000 900 43 7 1 5757FF 12 163 0.587100 0.100900 0.000000 900 4 13 3 1E1EE1 13 31 0.749600 1.550400 0.000000 900 43 7 1 5757FF 14 2 1.464000 1.962900 0.000000 900 2 6 0 A0A0A0 15 2 1.464000 2.787900 0.000000 900 2 6 0 A0A0A0 16 7 0.749600 3.200400 0.000000 900 2 6 0 A0A0A0 17 7 0.035100 2.787900 0.000000 900 2 6 0 A0A0A0 18 7 0.035100 1.962900 0.000000 900 2 6 0 A0A0A0 19 7 2.178500 3.200400 0.000000 900 2 6 0 A0A0A0 20 7 2.893000 2.787900 0.000000 900 2 6 0 A0A0A0 21 7 2.893000 1.962900 0.000000 900 2 6 0 A0A0A0 22 2 2.178500 1.550400 0.000000 900 2 6 0 A0A0A0 23 18 1.876500 0.782700 0.000000 900 70 8 -1 FF2F2F 24 31 0.532800 -1.356800 0.000000 900 43 7 1 5757FF 25 2 1.178200 -1.870700 0.000000 900 2 6 0 A0A0A0 26 2 1.945900 -1.568700 0.000000 900 2 6 0 A0A0A0 27 18 1.761200 -0.764600 0.000000 900 70 8 -1 FF2F2F 28 7 2.591300 -2.082600 0.000000 900 2 6 0 A0A0A0 29 7 2.468900 -2.898500 0.000000 900 2 6 0 A0A0A0 30 7 1.701200 -3.200400 0.000000 900 2 6 0 A0A0A0 31 2 1.055800 -2.686500 0.000000 900 2 6 0 A0A0A0 32 7 0.288100 -2.988500 0.000000 900 2 6 0 A0A0A0 33 7 -0.357300 -2.474600 0.000000 900 2 6 0 A0A0A0 34 7 -0.235000 -1.658700 0.000000 900 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 ::: "Untitled Document-2" 10 newTemp.1 /Users/nicola/schrodinger/coordgen_standalone templates.mae 10 templates->templates->templates templates->templates1->templates11 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 900 2 6 A0A0A0 C1 2 7 0.859700 2.621000 0.000000 900 2 6 A0A0A0 C2 3 2 0.859700 1.796000 0.000000 900 2 6 A0A0A0 C3 4 7 -0.581000 2.692600 0.000000 900 2 6 A0A0A0 C4 5 2 -0.662800 1.871700 0.000000 900 2 6 A0A0A0 C5 6 7 0.082700 1.518500 0.000000 900 2 6 A0A0A0 C6 7 5 -1.341500 1.402600 0.000000 900 2 6 A0A0A0 C7 8 5 -1.274600 0.580400 0.000000 900 2 6 A0A0A0 C8 9 27 -1.809300 -0.048800 0.000000 900 43 7 5757FF N9 10 5 -1.531900 -0.825800 0.000000 900 2 6 A0A0A0 C10 11 5 -0.720300 -0.973900 0.000000 900 2 6 A0A0A0 C11 12 2 -0.251200 -1.652600 0.000000 900 2 6 A0A0A0 C12 13 7 0.559600 -1.500100 0.000000 900 2 6 A0A0A0 C13 14 2 1.097000 -2.126000 0.000000 900 2 6 A0A0A0 C14 15 7 0.823700 -2.904400 0.000000 900 2 6 A0A0A0 C15 16 7 0.012900 -3.056900 0.000000 900 2 6 A0A0A0 C16 17 7 -0.524500 -2.431000 0.000000 900 2 6 A0A0A0 C17 18 5 1.775700 -1.656900 0.000000 900 2 6 A0A0A0 C18 19 5 1.380100 -0.933000 0.000000 900 2 6 A0A0A0 C19 20 5 1.809300 -0.228400 0.000000 900 2 6 A0A0A0 C20 21 5 1.340200 0.450300 0.000000 900 2 6 A0A0A0 C21 22 5 1.488400 1.261900 0.000000 900 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 ::: "Untitled Document-2" 11 newTemp.2 /Users/nicola/schrodinger/coordgen_standalone templates.mae 11 templates->templates->templates templates->templates1->templates11 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 900 2 6 A0A0A0 2 27 0.714500 0.825000 0.000000 900 43 7 5757FF 3 5 1.428900 0.412500 0.000000 900 2 6 A0A0A0 4 5 0.000000 2.062500 0.000000 900 2 6 A0A0A0 5 4 -0.714500 1.650000 0.000000 900 2 6 A0A0A0 6 5 -1.428900 2.062500 0.000000 900 2 6 A0A0A0 7 5 -2.143400 1.650000 0.000000 900 2 6 A0A0A0 8 5 -2.143400 0.825000 0.000000 900 2 6 A0A0A0 9 5 -0.714500 0.825000 0.000000 900 2 6 A0A0A0 10 4 -1.428900 0.412500 0.000000 900 2 6 A0A0A0 11 16 -1.428900 -0.412500 0.000000 900 70 8 FF2F2F 12 5 -2.143400 -0.825000 0.000000 900 2 6 A0A0A0 13 5 -2.143400 -1.650000 0.000000 900 2 6 A0A0A0 14 5 -1.428900 -2.062500 0.000000 900 2 6 A0A0A0 15 5 -0.714500 -1.650000 0.000000 900 2 6 A0A0A0 16 27 0.000000 -2.062500 0.000000 900 43 7 5757FF 17 4 0.714500 -1.650000 0.000000 900 2 6 A0A0A0 18 5 0.714500 -0.825000 0.000000 900 2 6 A0A0A0 19 5 1.428900 -2.062500 0.000000 900 2 6 A0A0A0 20 5 2.143400 -1.650000 0.000000 900 2 6 A0A0A0 21 5 2.143400 -0.825000 0.000000 900 2 6 A0A0A0 22 4 1.428900 -0.412500 0.000000 900 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 ::: "Untitled Document-2" 12 newTemp.1 /Users/nicola/schrodinger/coordgen_standalone templates.mae 12 templates->templates->templates templates->templates1->templates11 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 900 2 6 A0A0A0 C1 2 5 0.206300 1.071700 0.000000 900 2 6 A0A0A0 C2 3 29 1.031300 1.071700 0.000000 900 43 7 5757FF N3 4 5 -1.031200 1.786200 0.000000 900 2 6 A0A0A0 C4 5 5 -1.443700 1.071700 0.000000 900 2 6 A0A0A0 C5 6 5 -2.268700 1.071700 0.000000 900 2 6 A0A0A0 C6 7 5 -2.681200 0.357200 0.000000 900 2 6 A0A0A0 C7 8 5 -2.268700 -0.357200 0.000000 900 2 6 A0A0A0 C8 9 5 -1.443700 -0.357200 0.000000 900 2 6 A0A0A0 C9 10 5 -1.031200 -1.071700 0.000000 900 2 6 A0A0A0 C10 11 27 -0.206200 -1.071700 0.000000 900 43 7 5757FF N11 12 5 0.206300 -1.786200 0.000000 900 2 6 A0A0A0 C12 13 5 1.031300 -1.786200 0.000000 900 2 6 A0A0A0 C13 14 2 1.443800 -1.071700 0.000000 900 2 6 A0A0A0 C14 15 7 1.031300 -0.357200 0.000000 900 2 6 A0A0A0 C15 16 2 1.443800 0.357200 0.000000 900 2 6 A0A0A0 C16 17 7 2.268800 -1.071700 0.000000 900 2 6 A0A0A0 C17 18 7 2.681200 -0.357200 0.000000 900 2 6 A0A0A0 C18 19 7 2.268800 0.357200 0.000000 900 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 ::: "New Entry" 13 entry /Users/nicola/schrodinger/coordgen_standalone templates.mae 13 templates->templates->templates templates->templates1->templates11 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 900 43 7 5757FF 2 27 3.230400 -1.703100 0.000000 900 43 7 5757FF 3 26 0.947900 -2.321500 0.000000 900 43 7 5757FF 4 4 0.600500 -1.146200 0.000000 900 2 6 A0A0A0 5 4 -0.515400 -2.828800 0.000000 900 2 6 A0A0A0 6 4 -1.525500 -1.818600 0.000000 900 2 6 A0A0A0 7 5 1.380300 -0.368400 0.000000 900 2 6 A0A0A0 8 5 0.000000 0.000000 0.000000 900 2 6 A0A0A0 9 5 -2.905400 -2.188300 0.000000 900 2 6 A0A0A0 10 5 -3.275200 -3.568200 0.000000 900 2 6 A0A0A0 11 5 -2.265100 -4.578400 0.000000 900 2 6 A0A0A0 12 5 -0.885200 -4.208700 0.000000 900 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 14 CRDGEN-85_template_2.1 /Users/nicola/schrodinger/coordgen_standalone templates.mae 14 templates->templates->templates templates->templates1->templates11 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 900 2 6 A0A0A0 2 4 -16.863400 -2.422000 0.000000 900 2 6 A0A0A0 3 4 -16.256600 -0.995200 0.000000 900 2 6 A0A0A0 4 5 -16.664200 -0.306500 0.000000 900 2 6 A0A0A0 5 5 -13.305800 -3.061000 0.000000 900 2 6 A0A0A0 6 4 -13.370000 -1.860200 0.000000 900 2 6 A0A0A0 7 5 -14.160600 -1.624400 0.000000 900 2 6 A0A0A0 8 4 -13.924800 -0.833800 0.000000 900 2 6 A0A0A0 9 5 -14.684000 -0.510900 0.000000 900 2 6 A0A0A0 10 5 -13.789500 -3.729300 0.000000 900 2 6 A0A0A0 11 5 -14.515300 -4.121600 0.000000 900 2 6 A0A0A0 12 5 -15.339400 -4.160100 0.000000 900 2 6 A0A0A0 13 5 -16.098600 -3.837200 0.000000 900 2 6 A0A0A0 14 5 -16.642500 -3.216900 0.000000 900 2 6 A0A0A0 15 5 -16.300300 -1.819000 0.000000 900 2 6 A0A0A0 16 5 -15.508100 -0.549400 0.000000 900 2 6 A0A0A0 17 5 -13.134200 -1.069700 0.000000 900 2 6 A0A0A0 18 5 -18.479200 -2.308500 0.000000 900 2 6 A0A0A0 19 5 -17.336000 0.070600 0.000000 900 2 6 A0A0A0 20 5 -18.944700 -1.666200 0.000000 900 2 6 A0A0A0 21 5 -18.863600 -0.722000 0.000000 900 2 6 A0A0A0 22 5 -18.219900 -0.017800 0.000000 900 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 15 CRDGEN-85_template.1 /Users/nicola/schrodinger/coordgen_standalone templates.mae 15 templates->templates->templates templates->templates1->templates11 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 900 2 6 A0A0A0 2 5 -17.682300 -2.522000 0.000000 900 2 6 A0A0A0 3 4 -16.863400 -2.422000 0.000000 900 2 6 A0A0A0 4 4 -16.256600 -0.995200 0.000000 900 2 6 A0A0A0 5 5 -16.752600 -0.336000 0.000000 900 2 6 A0A0A0 6 5 -17.556400 -0.149800 0.000000 900 2 6 A0A0A0 7 5 -18.291700 -0.523900 0.000000 900 2 6 A0A0A0 8 5 -18.614600 -1.283100 0.000000 900 2 6 A0A0A0 9 5 -13.305800 -3.061000 0.000000 900 2 6 A0A0A0 10 4 -13.370000 -1.860200 0.000000 900 2 6 A0A0A0 11 5 -14.160600 -1.624400 0.000000 900 2 6 A0A0A0 12 4 -13.924800 -0.833800 0.000000 900 2 6 A0A0A0 13 5 -14.684000 -0.510900 0.000000 900 2 6 A0A0A0 14 5 -13.789500 -3.729300 0.000000 900 2 6 A0A0A0 15 5 -14.515300 -4.121600 0.000000 900 2 6 A0A0A0 16 5 -15.339400 -4.160100 0.000000 900 2 6 A0A0A0 17 5 -16.098600 -3.837200 0.000000 900 2 6 A0A0A0 18 5 -16.642500 -3.216900 0.000000 900 2 6 A0A0A0 19 5 -16.300300 -1.819000 0.000000 900 2 6 A0A0A0 20 5 -15.508100 -0.549400 0.000000 900 2 6 A0A0A0 21 5 -13.134200 -1.069700 0.000000 900 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 ::: "Untitled Document-1" 16 newTemp.1 /Users/nicola/schrodinger/coordgen_standalone templates.mae 16 templates->templates->templates templates->templates1->templates11 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 900 2 6 A0A0A0 2 5 -1.820500 -0.016500 0.000000 900 2 6 A0A0A0 3 4 -1.027000 -0.242200 0.000000 900 2 6 A0A0A0 4 4 -0.434800 0.332100 0.000000 900 2 6 A0A0A0 5 4 -0.636100 1.132200 0.000000 900 2 6 A0A0A0 6 5 -1.429600 1.357900 0.000000 900 2 6 A0A0A0 7 3 0.388400 0.276300 0.000000 900 2 6 A0A0A0 8 4 0.695800 1.041900 0.000000 900 2 6 A0A0A0 9 5 0.062600 1.570900 0.000000 900 2 6 A0A0A0 10 5 0.897700 -0.372700 0.000000 900 2 6 A0A0A0 11 5 1.714400 -0.256100 0.000000 900 2 6 A0A0A0 12 5 2.021800 0.509500 0.000000 900 2 6 A0A0A0 13 5 1.512500 1.158500 0.000000 900 2 6 A0A0A0 14 5 -1.077700 -1.065700 0.000000 900 2 6 A0A0A0 15 5 0.589700 -0.523700 0.000000 900 2 6 A0A0A0 16 5 0.359100 -1.315900 0.000000 900 2 6 A0A0A0 17 5 -0.425500 -1.570900 0.000000 900 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_st_Chirality_1 s_st_Chirality_2 s_m_subgroup_title s_m_subgroupid b_m_subgroup_collapsed i_m_ct_format ::: "Untitled Document-4" 17 newTemplates2.1 /Users/nicola/schrodinger/coordgen_standalone templates.mae 17 3_S_4_6_2 7_S_8_9_6_10 templates->templates->templates templates->templates1->templates11 0 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[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 900 2 6 A0A0A0 C1 2 5 0.370300 1.157000 0.000000 900 2 6 A0A0A0 C2 3 4 -0.326500 0.715300 0.000000 900 2 6 A0A0A0 C3 4 5 0.085100 0.000400 0.000000 900 2 6 A0A0A0 C4 5 26 -0.328300 -0.713600 0.000000 900 43 7 5757FF N5 6 5 -1.151500 0.716400 0.000000 900 2 6 A0A0A0 C6 7 5 -1.564900 0.002400 0.000000 900 2 6 A0A0A0 C7 8 5 -1.153300 -0.712600 0.000000 900 2 6 A0A0A0 C9 9 2 1.724800 0.410800 0.000000 900 2 6 A0A0A0 C12 10 2 1.723800 -0.414200 0.000000 900 2 6 A0A0A0 C13 11 5 1.183800 -1.037900 0.000000 900 2 6 A0A0A0 C14 12 5 0.367400 -1.157000 0.000000 900 2 6 A0A0A0 C15 13 7 2.508100 -0.670100 0.000000 900 2 6 A0A0A0 C16 14 7 2.993800 -0.003300 0.000000 900 2 6 A0A0A0 C17 15 29 2.509700 0.664800 0.000000 900 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 i_m_stars 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 ::: "Untitled Document-4" 3 18 newTemplates2.2 /Users/nicola/schrodinger/coordgen_standalone templates.mae 18 templates->templates->templates templates->templates1->templates11 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 900 2 6 A0A0A0 2 4 -1.155700 -1.360400 0.000000 900 2 6 A0A0A0 3 4 -0.441300 -2.597800 0.000000 900 2 6 A0A0A0 4 5 0.273100 -2.185300 0.000000 900 2 6 A0A0A0 5 5 0.273100 -1.360400 0.000000 900 2 6 A0A0A0 6 4 -0.441300 -0.947900 0.000000 900 2 6 A0A0A0 7 5 -0.227800 -1.800900 0.000000 900 2 6 A0A0A0 8 5 -0.028800 -0.233400 0.000000 900 2 6 A0A0A0 9 5 -0.028800 0.591600 0.000000 900 2 6 A0A0A0 10 3 -0.743300 1.004100 0.000000 900 2 6 A0A0A0 11 5 -1.155700 0.289600 0.000000 900 2 6 A0A0A0 12 5 -1.155700 -0.535400 0.000000 900 2 6 A0A0A0 13 5 -0.159900 1.587500 0.000000 900 2 6 A0A0A0 14 27 -0.373500 2.384200 0.000000 900 43 7 5757FF 15 5 -1.170300 2.597800 0.000000 900 2 6 A0A0A0 16 5 -1.753600 2.014400 0.000000 900 2 6 A0A0A0 17 5 -1.540100 1.217600 0.000000 900 2 6 A0A0A0 18 5 -1.870200 -0.947900 0.000000 900 2 6 A0A0A0 19 5 -2.584600 -1.360400 0.000000 900 2 6 A0A0A0 20 5 -2.584600 -2.185300 0.000000 900 2 6 A0A0A0 21 5 -1.870200 -2.597800 0.000000 900 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 i_m_stars 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 ::: "Untitled Document-4" 3 19 newTemplates2.2 /Users/nicola/schrodinger/coordgen_standalone templates.mae 19 templates->templates->templates templates->templates1->templates11 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 900 2 6 A0A0A0 2 4 -1.155700 -1.360400 0.000000 900 2 6 A0A0A0 3 4 -0.441300 -2.597800 0.000000 900 2 6 A0A0A0 4 4 0.273100 -2.185300 0.000000 900 2 6 A0A0A0 5 4 0.273100 -1.360400 0.000000 900 2 6 A0A0A0 6 4 -0.441300 -0.947900 0.000000 900 2 6 A0A0A0 7 5 0.987600 -2.597800 0.000000 900 2 6 A0A0A0 8 4 1.702100 -2.185300 0.000000 900 2 6 A0A0A0 9 5 1.702100 -1.360400 0.000000 900 2 6 A0A0A0 10 4 0.987600 -0.947900 0.000000 900 2 6 A0A0A0 11 5 1.870300 -0.480400 0.000000 900 2 6 A0A0A0 12 5 2.584600 -0.892900 0.000000 900 2 6 A0A0A0 13 5 2.584600 -1.717800 0.000000 900 2 6 A0A0A0 14 5 -0.227800 -1.800900 0.000000 900 2 6 A0A0A0 15 5 -0.028800 -0.233400 0.000000 900 2 6 A0A0A0 16 5 -0.028800 0.591600 0.000000 900 2 6 A0A0A0 17 3 -0.743300 1.004100 0.000000 900 2 6 A0A0A0 18 5 -1.155700 0.289600 0.000000 900 2 6 A0A0A0 19 5 -1.155700 -0.535400 0.000000 900 2 6 A0A0A0 20 5 -0.159900 1.587500 0.000000 900 2 6 A0A0A0 21 27 -0.373500 2.384200 0.000000 900 43 7 5757FF 22 5 -1.170300 2.597800 0.000000 900 2 6 A0A0A0 23 5 -1.753600 2.014400 0.000000 900 2 6 A0A0A0 24 5 -1.540100 1.217600 0.000000 900 2 6 A0A0A0 25 5 -1.870200 -0.947900 0.000000 900 2 6 A0A0A0 26 5 -2.584600 -1.360400 0.000000 900 2 6 A0A0A0 27 5 -2.584600 -2.185300 0.000000 900 2 6 A0A0A0 28 5 -1.870200 -2.597800 0.000000 900 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 ::: "Untitled Document-4" 20 newTemplates2.2 /Users/nicola/schrodinger/coordgen_standalone templates.mae 20 templates->templates->templates templates->templates1->templates11 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 900 2 6 A0A0A0 2 4 -1.155700 -1.360400 0.000000 900 2 6 A0A0A0 3 4 -0.441300 -2.597800 0.000000 900 2 6 A0A0A0 4 4 0.273100 -2.185300 0.000000 900 2 6 A0A0A0 5 4 0.273100 -1.360400 0.000000 900 2 6 A0A0A0 6 4 -0.441300 -0.947900 0.000000 900 2 6 A0A0A0 7 5 0.987600 -2.597800 0.000000 900 2 6 A0A0A0 8 4 1.702100 -2.185300 0.000000 900 2 6 A0A0A0 9 5 1.702100 -1.360400 0.000000 900 2 6 A0A0A0 10 4 0.987600 -0.947900 0.000000 900 2 6 A0A0A0 11 5 1.870300 -0.480400 0.000000 900 2 6 A0A0A0 12 5 2.584600 -0.892900 0.000000 900 2 6 A0A0A0 13 5 2.584600 -1.717800 0.000000 900 2 6 A0A0A0 14 5 -0.227800 -1.800900 0.000000 900 2 6 A0A0A0 15 5 -0.028800 -0.233400 0.000000 900 2 6 A0A0A0 16 5 -0.028800 0.591600 0.000000 900 2 6 A0A0A0 17 5 -0.743300 1.004100 0.000000 900 2 6 A0A0A0 18 5 -1.155700 0.289600 0.000000 900 2 6 A0A0A0 19 5 -1.155700 -0.535400 0.000000 900 2 6 A0A0A0 20 5 -1.870200 -0.947900 0.000000 900 2 6 A0A0A0 21 5 -2.584600 -1.360400 0.000000 900 2 6 A0A0A0 22 5 -2.584600 -2.185300 0.000000 900 2 6 A0A0A0 23 5 -1.870200 -2.597800 0.000000 900 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 ::: "Untitled Document-4" 21 newTemplates2.2 /Users/nicola/schrodinger/coordgen_standalone templates.mae 21 templates->templates->templates templates->templates1->templates11 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 900 2 6 A0A0A0 2 5 -1.155700 -1.360400 0.000000 900 2 6 A0A0A0 3 4 -0.441300 -2.597800 0.000000 900 2 6 A0A0A0 4 4 0.273100 -2.185300 0.000000 900 2 6 A0A0A0 5 4 0.273100 -1.360400 0.000000 900 2 6 A0A0A0 6 4 -0.441300 -0.947900 0.000000 900 2 6 A0A0A0 7 5 0.987600 -2.597800 0.000000 900 2 6 A0A0A0 8 4 1.702100 -2.185300 0.000000 900 2 6 A0A0A0 9 5 1.702100 -1.360400 0.000000 900 2 6 A0A0A0 10 4 0.987600 -0.947900 0.000000 900 2 6 A0A0A0 11 5 1.870300 -0.480400 0.000000 900 2 6 A0A0A0 12 5 2.584600 -0.892900 0.000000 900 2 6 A0A0A0 13 5 2.584600 -1.717800 0.000000 900 2 6 A0A0A0 14 5 -0.227800 -1.800900 0.000000 900 2 6 A0A0A0 15 5 -0.028800 -0.233400 0.000000 900 2 6 A0A0A0 16 5 -0.028800 0.591600 0.000000 900 2 6 A0A0A0 17 5 -0.743300 1.004100 0.000000 900 2 6 A0A0A0 18 5 -1.155700 0.289600 0.000000 900 2 6 A0A0A0 19 5 -1.155700 -0.535400 0.000000 900 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 ::: "Untitled Document-4" 22 newTemplates2.3 /Users/nicola/schrodinger/coordgen_standalone templates.mae 22 templates->templates->templates templates->templates1->templates11 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 900 2 6 A0A0A0 2 5 -1.661900 -0.285000 0.000000 900 2 6 A0A0A0 3 3 -0.877200 -0.540000 0.000000 900 2 6 A0A0A0 4 3 -0.392300 0.127500 0.000000 900 2 6 A0A0A0 5 5 -0.877200 0.794900 0.000000 900 2 6 A0A0A0 6 5 -0.392300 -1.207400 0.000000 900 2 6 A0A0A0 7 4 0.392300 -0.952500 0.000000 900 2 6 A0A0A0 8 3 0.392300 -0.127500 0.000000 900 2 6 A0A0A0 9 5 1.176900 -1.207400 0.000000 900 2 6 A0A0A0 10 5 1.661900 -0.540000 0.000000 900 2 6 A0A0A0 11 5 1.176900 0.127500 0.000000 900 2 6 A0A0A0 12 5 0.877200 0.540000 0.000000 900 2 6 A0A0A0 13 5 0.392300 1.207400 0.000000 900 2 6 A0A0A0 14 4 -0.392300 0.952500 0.000000 900 2 6 A0A0A0 15 5 0.191100 0.369100 0.000000 900 2 6 A0A0A0 16 5 -0.080300 -0.326400 0.000000 900 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_st_Chirality_1 s_m_subgroup_title s_m_subgroupid b_m_subgroup_collapsed i_m_ct_format ::: "New Entry" 23 entry /Users/nicola/schrodinger/coordgen_standalone templates.mae 23 23_S_24_30_22 templates->templates->templates templates->templates1->templates11 0 2 m_depend[1] { # First column is dependency index # i_m_depend_dependency s_m_depend_property ::: 1 10 s_st_Chirality_1 ::: } 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 900 2 6 A0A0A0 2 5 4.962100 -6.138900 0.000000 900 2 6 A0A0A0 3 5 5.921200 -3.598100 0.000000 900 2 6 A0A0A0 4 5 3.696800 -6.944900 0.000000 900 2 6 A0A0A0 5 5 2.316900 -6.320000 0.000000 900 2 6 A0A0A0 6 5 0.936500 -6.962100 0.000000 900 2 6 A0A0A0 7 5 -0.412600 -6.371100 0.000000 900 2 6 A0A0A0 8 5 -1.938500 -6.828600 0.000000 900 2 6 A0A0A0 9 7 -3.054400 -5.860300 0.000000 900 2 6 A0A0A0 10 7 -3.398600 -4.417100 0.000000 900 2 6 A0A0A0 11 7 -5.285000 -2.489400 0.000000 900 2 6 A0A0A0 12 5 -5.193900 -0.959100 0.000000 900 2 6 A0A0A0 13 7 -4.760500 -3.865500 0.000000 900 2 6 A0A0A0 14 29 -4.285700 0.000000 0.000000 900 43 7 5757FF 15 2 -0.714300 -1.237200 0.000000 900 2 6 A0A0A0 16 7 0.000000 -2.474500 0.000000 900 2 6 A0A0A0 17 2 0.000000 0.000000 0.000000 900 2 6 A0A0A0 18 5 -2.142900 -1.237200 0.000000 900 2 6 A0A0A0 19 2 1.428600 0.000000 0.000000 900 2 6 A0A0A0 20 4 -0.714300 1.237200 0.000000 900 2 6 A0A0A0 21 2 2.142900 -1.237200 0.000000 900 2 6 A0A0A0 22 5 2.327400 1.110100 0.000000 900 2 6 A0A0A0 23 4 3.661100 0.598300 0.000000 900 2 6 A0A0A0 24 16 3.586500 -0.828400 0.000000 900 70 8 FF2F2F 25 7 1.428600 -2.474500 0.000000 900 2 6 A0A0A0 26 2 -2.857100 0.000000 0.000000 900 2 6 A0A0A0 27 2 -2.142900 1.237200 0.000000 900 2 6 A0A0A0 28 7 5.972100 -2.067500 0.000000 900 2 6 A0A0A0 29 7 5.041000 -1.200200 0.000000 900 2 6 A0A0A0 30 16 5.143000 0.126400 0.000000 900 70 8 FF2F2F 31 5 -0.272800 2.595900 0.000000 900 2 6 A0A0A0 32 5 -1.428600 3.435600 0.000000 900 2 6 A0A0A0 33 5 -2.584300 2.595900 0.000000 900 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 ::: "Untitled Document-3" 24 newTemplates.1 /Users/nicola/schrodinger/coordgen_standalone templates.mae 24 templates->templates->templates templates->templates1->templates11 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 900 2 6 A0A0A0 2 2 0.106700 1.603600 0.000000 900 2 6 A0A0A0 3 7 0.909500 1.793700 0.000000 900 2 6 A0A0A0 4 7 -0.130100 0.813400 0.000000 900 2 6 A0A0A0 5 7 0.435900 0.213100 0.000000 900 2 6 A0A0A0 6 5 -1.276800 1.571800 0.000000 900 2 6 A0A0A0 7 16 -2.066700 1.771000 0.000000 900 70 8 FF2F2F 8 5 -2.573200 0.900600 0.000000 900 2 6 A0A0A0 9 5 -1.843400 0.201500 0.000000 900 2 6 A0A0A0 10 5 -2.041000 -0.778600 0.000000 900 2 6 A0A0A0 11 2 -1.052300 -1.065400 0.000000 900 2 6 A0A0A0 12 7 -0.491600 -0.460300 0.000000 900 2 6 A0A0A0 13 7 0.312900 -0.643200 0.000000 900 2 6 A0A0A0 14 7 -0.808800 -1.853700 0.000000 900 2 6 A0A0A0 15 7 -0.004400 -2.036900 0.000000 900 2 6 A0A0A0 16 2 0.556800 -1.431300 0.000000 900 2 6 A0A0A0 17 16 1.509000 -1.201000 0.000000 900 70 8 FF2F2F 18 2 1.238700 0.403200 0.000000 900 2 6 A0A0A0 19 2 1.475500 1.193500 0.000000 900 2 6 A0A0A0 20 4 1.917100 -0.066200 0.000000 900 2 6 A0A0A0 21 5 2.573200 0.433900 0.000000 900 2 6 A0A0A0 22 5 2.292800 1.214600 0.000000 900 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_st_Chirality_1 s_m_subgroup_title s_m_subgroupid b_m_subgroup_collapsed i_m_ct_format ::: "Untitled Document-3" 25 newTemplates.2 /Users/nicola/schrodinger/coordgen_standalone templates.mae 25 5_S_10_6_4 templates->templates->templates templates->templates1->templates11 0 2 m_depend[1] { # First column is dependency index # i_m_depend_dependency s_m_depend_property ::: 1 10 s_st_Chirality_1 ::: } 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 900 2 6 A0A0A0 2 5 1.372900 0.766800 0.000000 900 2 6 A0A0A0 3 5 1.627800 -0.017800 0.000000 900 2 6 A0A0A0 4 5 -0.146300 1.056000 0.000000 900 2 6 A0A0A0 5 4 -0.671700 0.420000 0.000000 900 2 6 A0A0A0 6 5 -1.456300 0.165000 0.000000 900 2 6 A0A0A0 7 5 -1.627800 -0.641900 0.000000 900 2 6 A0A0A0 8 5 -1.014700 -1.194000 0.000000 900 2 6 A0A0A0 9 26 -0.230100 -0.939000 0.000000 900 43 7 5757FF 10 5 -0.058600 -0.132100 0.000000 900 2 6 A0A0A0 11 5 0.568800 -1.144800 0.000000 900 2 6 A0A0A0 12 5 1.308000 -0.778300 0.000000 900 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 ::: "Untitled Document-3" 26 newTemplates.3 /Users/nicola/schrodinger/coordgen_standalone templates.mae 26 templates->templates->templates templates->templates1->templates11 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 900 2 6 A0A0A0 2 4 0.004100 0.617000 0.000000 900 2 6 A0A0A0 3 3 -0.000000 -0.208000 0.000000 900 2 6 A0A0A0 4 5 0.712400 -0.624100 0.000000 900 2 6 A0A0A0 5 5 1.428900 -0.215200 0.000000 900 2 6 A0A0A0 6 5 1.433000 0.609800 0.000000 900 2 6 A0A0A0 7 4 -0.708300 1.033000 0.000000 900 2 6 A0A0A0 8 5 -1.424800 0.624100 0.000000 900 2 6 A0A0A0 9 4 -1.428900 -0.200900 0.000000 900 2 6 A0A0A0 10 5 -0.716500 -0.617000 0.000000 900 2 6 A0A0A0 11 5 -0.712400 0.208000 0.000000 900 2 6 A0A0A0 12 5 -0.004100 -1.033000 0.000000 900 2 6 A0A0A0 13 4 -1.433000 -1.025900 0.000000 900 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_st_Chirality_1 s_st_Chirality_2 s_m_subgroup_title s_m_subgroupid b_m_subgroup_collapsed i_m_ct_format ::: "Untitled Document-3" 27 newTemplates.4 /Users/nicola/schrodinger/coordgen_standalone templates.mae 27 11_R_13_12_10 26_S_29_25_27 templates->templates->templates templates->templates1->templates11 0 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[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 900 2 6 A0A0A0 2 25 3.226500 0.030300 0.000000 900 43 7 5757FF 3 7 2.549300 0.501500 0.000000 900 2 6 A0A0A0 4 25 1.891900 0.003100 0.000000 900 43 7 5757FF 5 2 2.162800 -0.776200 0.000000 900 2 6 A0A0A0 6 5 1.081600 0.158100 0.000000 900 2 6 A0A0A0 7 2 0.810700 0.937400 0.000000 900 2 6 A0A0A0 8 7 1.350100 1.561600 0.000000 900 2 6 A0A0A0 9 5 1.079200 2.340900 0.000000 900 2 6 A0A0A0 10 5 0.268900 2.495900 0.000000 900 2 6 A0A0A0 11 4 -0.270500 1.871600 0.000000 900 2 6 A0A0A0 12 5 0.000400 1.092400 0.000000 900 2 6 A0A0A0 13 16 -1.068900 2.030800 0.000000 900 70 8 FF2F2F 14 2 -1.608300 1.406600 0.000000 900 2 6 A0A0A0 15 7 -1.337400 0.627300 0.000000 900 2 6 A0A0A0 16 2 -1.876800 0.003100 0.000000 900 2 6 A0A0A0 17 2 -2.687100 0.158100 0.000000 900 2 6 A0A0A0 18 7 -2.958000 0.937400 0.000000 900 2 6 A0A0A0 19 7 -2.418600 1.561600 0.000000 900 2 6 A0A0A0 20 7 -3.226500 -0.466100 0.000000 900 2 6 A0A0A0 21 7 -2.955600 -1.245400 0.000000 900 2 6 A0A0A0 22 7 -2.145300 -1.400400 0.000000 900 2 6 A0A0A0 23 2 -1.605900 -0.776200 0.000000 900 2 6 A0A0A0 24 25 -0.795600 -0.931200 0.000000 900 43 7 5757FF 25 5 -0.524700 -1.710400 0.000000 900 2 6 A0A0A0 26 4 0.285600 -1.865500 0.000000 900 2 6 A0A0A0 27 5 0.559100 -1.087100 0.000000 900 2 6 A0A0A0 28 5 -0.065100 -0.547700 0.000000 900 2 6 A0A0A0 29 27 0.817800 -2.495900 0.000000 900 43 7 5757FF 30 5 1.597000 -2.225000 0.000000 900 2 6 A0A0A0 31 5 1.623400 -1.400400 0.000000 900 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 ::: "Untitled Document-3" 28 newTemplates.5 /Users/nicola/schrodinger/coordgen_standalone templates.mae 28 templates->templates->templates templates->templates1->templates11 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 900 2 6 A0A0A0 2 5 -1.571300 -1.360400 0.000000 900 2 6 A0A0A0 3 4 -0.856800 -2.597900 0.000000 900 2 6 A0A0A0 4 4 -0.142400 -2.185400 0.000000 900 2 6 A0A0A0 5 4 -0.142400 -1.360400 0.000000 900 2 6 A0A0A0 6 4 -0.856800 -0.947900 0.000000 900 2 6 A0A0A0 7 5 0.572100 -2.597900 0.000000 900 2 6 A0A0A0 8 4 1.286600 -2.185400 0.000000 900 2 6 A0A0A0 9 5 1.286600 -1.360400 0.000000 900 2 6 A0A0A0 10 4 0.572100 -0.947900 0.000000 900 2 6 A0A0A0 11 5 1.454800 -0.480400 0.000000 900 2 6 A0A0A0 12 5 2.169200 -0.892900 0.000000 900 2 6 A0A0A0 13 5 2.169200 -1.717900 0.000000 900 2 6 A0A0A0 14 5 -0.643300 -1.801000 0.000000 900 2 6 A0A0A0 15 5 -0.444300 -0.233400 0.000000 900 2 6 A0A0A0 16 5 -0.444300 0.591600 0.000000 900 2 6 A0A0A0 17 3 -1.158800 1.004100 0.000000 900 2 6 A0A0A0 18 5 -1.571300 0.289600 0.000000 900 2 6 A0A0A0 19 5 -1.571300 -0.535400 0.000000 900 2 6 A0A0A0 20 5 -0.575400 1.587500 0.000000 900 2 6 A0A0A0 21 27 -0.789000 2.384300 0.000000 900 43 7 5757FF 22 5 -1.585900 2.597900 0.000000 900 2 6 A0A0A0 23 5 -2.169200 2.014500 0.000000 900 2 6 A0A0A0 24 5 -1.955700 1.217600 0.000000 900 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 ::: "Untitled Document-3" 29 newTemplates.6 /Users/nicola/schrodinger/coordgen_standalone templates.mae 29 templates->templates->templates templates->templates1->templates11 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 900 2 6 A0A0A0 2 5 -2.500600 1.010100 0.000000 900 2 6 A0A0A0 3 4 -1.786200 0.597600 0.000000 900 2 6 A0A0A0 4 4 -1.071700 1.010100 0.000000 900 2 6 A0A0A0 5 4 -1.071700 1.835100 0.000000 900 2 6 A0A0A0 6 5 -1.786200 2.247600 0.000000 900 2 6 A0A0A0 7 5 -0.357200 0.597600 0.000000 900 2 6 A0A0A0 8 4 0.357200 1.010100 0.000000 900 2 6 A0A0A0 9 5 0.357200 1.835100 0.000000 900 2 6 A0A0A0 10 5 -0.357200 2.247600 0.000000 900 2 6 A0A0A0 11 4 1.071700 0.597600 0.000000 900 2 6 A0A0A0 12 4 1.071700 -0.227400 0.000000 900 2 6 A0A0A0 13 4 1.786200 -0.639900 0.000000 900 2 6 A0A0A0 14 5 2.500600 -0.227400 0.000000 900 2 6 A0A0A0 15 5 2.500600 0.597600 0.000000 900 2 6 A0A0A0 16 5 1.786200 1.010100 0.000000 900 2 6 A0A0A0 17 5 0.458600 -0.779400 0.000000 900 2 6 A0A0A0 18 4 0.794200 -1.533100 0.000000 900 2 6 A0A0A0 19 5 1.614700 -1.446900 0.000000 900 2 6 A0A0A0 20 5 0.381700 -2.247600 0.000000 900 2 6 A0A0A0 21 5 -0.470800 -2.247600 0.000000 900 2 6 A0A0A0 22 4 -0.988300 -1.678000 0.000000 900 2 6 A0A0A0 23 5 -1.047700 -0.855200 0.000000 900 2 6 A0A0A0 24 4 -1.848600 -0.657300 0.000000 900 2 6 A0A0A0 25 5 -2.284300 -1.357900 0.000000 900 2 6 A0A0A0 26 5 -1.752600 -1.988800 0.000000 900 2 6 A0A0A0 27 5 -2.311500 0.025600 0.000000 900 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 ::: "Untitled Document-3" 30 newTemplates.7 /Users/nicola/schrodinger/coordgen_standalone templates.mae 30 templates->templates->templates templates->templates1->templates11 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 900 2 6 A0A0A0 2 7 -2.500600 -0.412500 0.000000 900 2 6 A0A0A0 3 7 -2.500600 0.412500 0.000000 900 2 6 A0A0A0 4 7 -1.786200 0.825000 0.000000 900 2 6 A0A0A0 5 2 -1.071700 0.412500 0.000000 900 2 6 A0A0A0 6 2 -1.071700 -0.412500 0.000000 900 2 6 A0A0A0 7 29 -0.357200 0.825000 0.000000 900 43 7 5757FF 8 5 -0.357200 1.650000 0.000000 900 2 6 A0A0A0 9 29 0.357200 2.062500 0.000000 900 43 7 5757FF 10 2 1.071700 1.650000 0.000000 900 2 6 A0A0A0 11 25 1.071700 0.825000 0.000000 900 43 7 5757FF 12 2 1.786200 0.412500 0.000000 900 2 6 A0A0A0 13 7 2.500600 0.825000 0.000000 900 2 6 A0A0A0 14 25 2.500600 1.650000 0.000000 900 43 7 5757FF 15 7 1.786200 2.062500 0.000000 900 2 6 A0A0A0 16 16 1.786200 -0.412500 0.000000 900 70 8 FF2F2F 17 5 2.305400 -1.053600 0.000000 900 2 6 A0A0A0 18 5 1.892900 -1.768100 0.000000 900 2 6 A0A0A0 19 5 1.071700 -1.650000 0.000000 900 2 6 A0A0A0 20 5 0.357200 -2.062500 0.000000 900 2 6 A0A0A0 21 5 -0.357200 -1.650000 0.000000 900 2 6 A0A0A0 22 16 -0.357200 -0.825000 0.000000 900 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_st_Chirality_1 s_st_Chirality_2 s_m_subgroup_title s_m_subgroupid b_m_subgroup_collapsed i_m_ct_format ::: "Untitled Document-2" 31 newTemps.1 /Users/nicola/schrodinger/coordgen_standalone templates.mae 31 6_S_5_9_1_17 5_S_7_6_4 templates->templates->templates templates->templates1->templates11 0 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[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 900 2 6 0 A0A0A0 2 7 -1.774900 0.119000 0.000000 900 2 6 0 A0A0A0 3 5 -2.026400 -0.666800 0.000000 900 2 6 0 A0A0A0 4 5 -1.471700 -1.277400 0.000000 900 2 6 0 A0A0A0 5 4 -0.665500 -1.102400 0.000000 900 2 6 0 A0A0A0 6 3 -0.414000 -0.316600 0.000000 900 2 6 0 A0A0A0 7 16 0.004100 -1.584400 0.000000 900 70 8 0 FF2F2F 8 2 0.669400 -1.096500 0.000000 900 2 6 0 A0A0A0 9 2 0.411000 -0.313000 0.000000 900 2 6 0 A0A0A0 10 2 0.960300 0.302500 0.000000 900 2 6 0 A0A0A0 11 7 1.768000 0.134500 0.000000 900 2 6 0 A0A0A0 12 7 2.026400 -0.649000 0.000000 900 2 6 0 A0A0A0 13 7 1.477100 -1.264500 0.000000 900 2 6 0 A0A0A0 14 7 0.951700 1.127400 0.000000 900 2 6 0 A0A0A0 15 36 0.374800 1.584400 0.000000 900 43 7 1 5757FF 16 5 -0.444400 1.383500 0.000000 900 2 6 0 A0A0A0 17 5 -0.644900 0.659400 0.000000 900 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_st_Chirality_1 s_st_Chirality_2 s_m_subgroup_title s_m_subgroupid b_m_subgroup_collapsed i_m_ct_format ::: "Untitled Document-2" 32 newTemps.2 /Users/nicola/schrodinger/coordgen_standalone templates.mae 32 4_S_5_3_11 31_S_32_30_33 templates->templates->templates templates->templates1->templates11 0 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[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 900 2 6 A0A0A0 2 16 -1.169200 -0.369900 0.000000 900 70 8 FF2F2F 3 5 -1.581700 -1.084300 0.000000 900 2 6 A0A0A0 4 4 -2.351900 -1.380000 0.000000 900 2 6 A0A0A0 5 26 -2.351900 -2.205000 0.000000 900 43 7 5757FF 6 5 -1.581700 -2.500600 0.000000 900 2 6 A0A0A0 7 5 -1.169200 -3.215100 0.000000 900 2 6 A0A0A0 8 5 -3.066400 -2.617500 0.000000 900 2 6 A0A0A0 9 5 -3.780800 -2.205000 0.000000 900 2 6 A0A0A0 10 5 -3.780800 -1.380000 0.000000 900 2 6 A0A0A0 11 5 -3.066400 -0.967500 0.000000 900 2 6 A0A0A0 12 5 -1.169200 1.059100 0.000000 900 2 6 A0A0A0 13 5 -1.581700 1.786200 0.000000 900 2 6 A0A0A0 14 5 -1.169200 2.500600 0.000000 900 2 6 A0A0A0 15 7 -0.344200 2.500600 0.000000 900 2 6 A0A0A0 16 7 0.068300 3.215100 0.000000 900 2 6 A0A0A0 17 5 0.893300 3.215100 0.000000 900 2 6 A0A0A0 18 5 1.305800 3.929600 0.000000 900 2 6 A0A0A0 19 5 2.130800 3.929600 0.000000 900 2 6 A0A0A0 20 5 2.543300 3.215100 0.000000 900 2 6 A0A0A0 21 5 3.368300 3.215100 0.000000 900 2 6 A0A0A0 22 5 3.780800 2.500600 0.000000 900 2 6 A0A0A0 23 7 3.368300 1.786200 0.000000 900 2 6 A0A0A0 24 7 3.780800 1.071700 0.000000 900 2 6 A0A0A0 25 7 3.368300 0.357200 0.000000 900 2 6 A0A0A0 26 7 3.780800 -0.357200 0.000000 900 2 6 A0A0A0 27 7 3.368300 -1.071700 0.000000 900 2 6 A0A0A0 28 7 2.543300 -1.071700 0.000000 900 2 6 A0A0A0 29 5 2.130800 -1.786200 0.000000 900 2 6 A0A0A0 30 5 1.305800 -1.786200 0.000000 900 2 6 A0A0A0 31 4 0.893300 -2.500600 0.000000 900 2 6 A0A0A0 32 16 0.068300 -2.500600 0.000000 900 70 8 FF2F2F 33 5 1.305800 -3.215100 0.000000 900 2 6 A0A0A0 34 5 0.893300 -3.929600 0.000000 900 2 6 A0A0A0 35 5 0.068300 -3.929600 0.000000 900 2 6 A0A0A0 36 4 -0.344200 -3.215100 0.000000 900 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 ::: "New Entry" 33 entry /Users/nicola/schrodinger/coordgen_standalone templates.mae 33 templates->templates->templates templates->templates1->templates11 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 900 4 26 1E1EE1 2 49 -4.501700 3.198400 0.000000 900 13 16 E1E11E 3 159 -4.501700 4.627000 0.000000 900 4 26 1E1EE1 4 49 -5.738900 5.341300 0.000000 900 13 16 E1E11E 5 159 -6.976100 4.627000 0.000000 900 4 26 1E1EE1 6 49 -6.976100 3.198400 0.000000 900 13 16 E1E11E 7 163 -6.296900 3.863900 0.000000 900 4 26 1E1EE1 8 49 -4.863700 3.914300 0.000000 900 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 ::: "New Entry" 34 entry /Users/nicola/schrodinger/coordgen_standalone templates.mae 34 templates->templates->templates templates->templates1->templates11 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 900 2 6 A0A0A0 2 5 1.276000 -3.213500 0.000000 900 2 6 A0A0A0 3 5 0.741100 -1.221300 0.000000 900 2 6 A0A0A0 4 27 -1.374200 -2.504900 0.000000 900 43 7 5757FF 5 5 2.684500 -2.974700 0.000000 900 2 6 A0A0A0 6 5 3.594400 -1.873400 0.000000 900 2 6 A0A0A0 7 5 3.563300 -0.445200 0.000000 900 2 6 A0A0A0 8 4 2.606200 0.615400 0.000000 900 2 6 A0A0A0 9 4 1.188600 0.792400 0.000000 900 2 6 A0A0A0 10 26 0.000000 0.000000 0.000000 900 43 7 5757FF 11 5 -1.428200 -0.031200 0.000000 900 2 6 A0A0A0 12 5 -2.115300 -1.283600 0.000000 900 2 6 A0A0A0 13 5 3.468300 1.754600 0.000000 900 2 6 A0A0A0 14 5 2.912700 3.070700 0.000000 900 2 6 A0A0A0 15 5 1.495200 3.247700 0.000000 900 2 6 A0A0A0 16 5 0.633100 2.108500 0.000000 900 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_st_Chirality_1 s_m_subgroup_title s_m_subgroupid b_m_subgroup_collapsed i_m_ct_format ::: newTemp.mol 35 newTemp.1 /Users/nicola/schrodinger/coordgen_standalone templates.mae 35 1_R_12_9_2 templates->templates->templates templates->templates1->templates11 0 2 m_depend[1] { # First column is dependency index # i_m_depend_dependency s_m_depend_property ::: 1 10 s_st_Chirality_1 ::: } 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 900 2 6 A0A0A0 2 5 -0.309800 -1.156700 0.000000 900 2 6 A0A0A0 3 5 -1.123200 -1.018800 0.000000 900 2 6 A0A0A0 4 5 -1.648700 -0.382800 0.000000 900 2 6 A0A0A0 5 5 -1.630700 0.442000 0.000000 900 2 6 A0A0A0 6 5 -1.078000 1.054500 0.000000 900 2 6 A0A0A0 7 5 -0.259300 1.156700 0.000000 900 2 6 A0A0A0 8 26 0.427100 0.699100 0.000000 900 43 7 5757FF 9 5 -0.000900 -0.006200 0.000000 900 2 6 A0A0A0 10 5 1.251900 0.681100 0.000000 900 2 6 A0A0A0 11 5 1.648700 -0.042200 0.000000 900 2 6 A0A0A0 12 27 1.220700 -0.747500 0.000000 900 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_st_Chirality_1 s_m_subgroup_title s_m_subgroupid b_m_subgroup_collapsed i_m_ct_format ::: "Untitled Document-1" 36 newTemps.1 /Users/nicola/schrodinger/coordgen_standalone templates.mae 36 12_S_14_13_11 templates->templates->templates templates->templates1->templates11 0 2 m_depend[1] { # First column is dependency index # i_m_depend_dependency s_m_depend_property ::: 1 10 s_st_Chirality_1 ::: } 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 900 2 6 A0A0A0 2 16 0.706200 2.198700 0.000000 900 70 8 FF2F2F 3 5 1.520600 2.066500 0.000000 900 2 6 A0A0A0 4 2 1.795700 1.288700 0.000000 900 2 6 A0A0A0 5 2 1.330900 0.607100 0.000000 900 2 6 A0A0A0 6 3 0.526600 0.790700 0.000000 900 2 6 A0A0A0 7 7 2.618300 1.227100 0.000000 900 2 6 A0A0A0 8 7 2.976300 0.483800 0.000000 900 2 6 A0A0A0 9 7 2.511600 -0.197900 0.000000 900 2 6 A0A0A0 10 2 1.688900 -0.136200 0.000000 900 2 6 A0A0A0 11 5 1.330900 -0.879500 0.000000 900 2 6 A0A0A0 12 4 0.526600 -1.063100 0.000000 900 2 6 A0A0A0 13 5 -0.006400 -0.136200 0.000000 900 2 6 A0A0A0 14 4 -0.118400 -0.548700 0.000000 900 2 6 A0A0A0 15 4 -0.118400 0.276300 0.000000 900 2 6 A0A0A0 16 5 -0.832900 0.688800 0.000000 900 2 6 A0A0A0 17 4 -1.547400 0.276300 0.000000 900 2 6 A0A0A0 18 2 -1.547400 -0.548700 0.000000 900 2 6 A0A0A0 19 2 -0.832900 -0.961200 0.000000 900 2 6 A0A0A0 20 7 -0.832900 -1.786200 0.000000 900 2 6 A0A0A0 21 7 -1.547400 -2.198700 0.000000 900 2 6 A0A0A0 22 7 -2.261800 -1.786200 0.000000 900 2 6 A0A0A0 23 2 -2.261800 -0.961200 0.000000 900 2 6 A0A0A0 24 5 -2.976300 -0.548700 0.000000 900 2 6 A0A0A0 25 16 -2.976300 0.276300 0.000000 900 70 8 FF2F2F 26 5 -2.261800 0.688800 0.000000 900 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_st_Chirality_1 s_st_Chirality_2 s_st_Chirality_3 s_st_Chirality_4 s_st_Chirality_5 s_m_subgroup_title s_m_subgroupid b_m_subgroup_collapsed i_m_ct_format ::: "Untitled Document-1" 37 newTemps.2 /Users/nicola/schrodinger/coordgen_standalone templates.mae 37 3_S_4_2_5 7_R_9_8_6 11_R_15_10_12 9_S_17_7_10_14 10_S_9_11_18 templates->templates->templates templates->templates1->templates11 0 2 m_depend[5] { # 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 3 10 s_st_Chirality_3 4 10 s_st_Chirality_4 5 10 s_st_Chirality_5 ::: } 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 900 2 6 A0A0A0 2 5 -1.957900 -1.311100 0.000000 900 2 6 A0A0A0 3 4 -2.315900 -0.567800 0.000000 900 2 6 A0A0A0 4 5 -1.231600 -0.219500 0.000000 900 2 6 A0A0A0 5 5 -1.957900 0.175500 0.000000 900 2 6 A0A0A0 6 5 -1.153600 0.359100 0.000000 900 2 6 A0A0A0 7 4 -0.508600 -0.155300 0.000000 900 2 6 A0A0A0 8 3 -0.508600 -0.980300 0.000000 900 2 6 A0A0A0 9 3 0.205800 0.257200 0.000000 900 2 6 A0A0A0 10 4 0.920300 -0.155300 0.000000 900 2 6 A0A0A0 11 4 1.634800 0.257200 0.000000 900 2 6 A0A0A0 12 5 2.315900 -0.027000 0.000000 900 2 6 A0A0A0 13 5 1.787601 -0.327842 0.000000 900 2 6 A0A0A0 14 5 0.954927 0.369280 0.000000 900 2 6 A0A0A0 15 5 1.634800 1.082200 0.000000 900 2 6 A0A0A0 16 16 0.920300 1.494700 0.000000 900 70 8 FF2F2F 17 5 0.205800 1.082200 0.000000 900 2 6 A0A0A0 18 5 0.920300 -0.980300 0.000000 900 2 6 A0A0A0 19 5 0.205800 -1.392800 0.000000 900 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 ::: "Untitled Document-1" 38 newTemps.3 /Users/nicola/schrodinger/coordgen_standalone templates.mae 38 templates->templates->templates templates->templates1->templates11 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 900 43 7 5757FF "N1" 2 16 1.428900 0.412500 0.000000 900 70 8 FF2F2F "O2" 3 4 0.714500 -0.825000 0.000000 900 2 6 A0A0A0 "" 4 4 0.000000 -0.412500 0.000000 900 2 6 A0A0A0 "" 5 4 0.000000 0.412500 0.000000 900 2 6 A0A0A0 "" 6 4 0.714500 0.825000 0.000000 900 2 6 A0A0A0 "" 7 7 1.056500 0.309400 0.000000 900 2 6 A0A0A0 "C7" 8 7 1.056500 -0.309400 0.000000 900 2 6 A0A0A0 "C8" 9 4 -0.714500 0.825000 0.000000 900 2 6 A0A0A0 "" 10 25 -1.428900 0.412500 0.000000 900 43 7 5757FF "N10" 11 25 -1.428900 -0.412500 0.000000 900 43 7 5757FF "N11" 12 4 -0.714500 -0.825000 0.000000 900 2 6 A0A0A0 "" 13 5 -1.056500 -0.309400 0.000000 900 2 6 A0A0A0 "" 14 5 -1.056500 0.309400 0.000000 900 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 ::: "Untitled Document-1" 39 newTemps.4 /Users/nicola/schrodinger/coordgen_standalone templates.mae 39 templates->templates->templates templates->templates1->templates11 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 900 2 6 A0A0A0 2 5 1.771500 -0.859900 0.000000 900 2 6 A0A0A0 3 5 2.026400 -0.075300 0.000000 900 2 6 A0A0A0 4 4 1.474400 0.537800 0.000000 900 2 6 A0A0A0 5 5 0.908100 1.031400 0.000000 900 2 6 A0A0A0 6 16 0.083100 0.343900 0.000000 900 70 8 FF2F2F 7 4 0.667400 0.366300 0.000000 900 2 6 A0A0A0 8 5 -0.000000 0.851200 0.000000 900 2 6 A0A0A0 9 2 -0.667400 0.366300 0.000000 900 2 6 A0A0A0 10 3 -0.412500 -0.418300 0.000000 900 2 6 A0A0A0 11 3 0.412500 -0.418300 0.000000 900 2 6 A0A0A0 12 7 -1.474400 0.537800 0.000000 900 2 6 A0A0A0 13 4 -2.026400 -0.075300 0.000000 900 2 6 A0A0A0 14 5 -1.593200 -0.517100 0.000000 900 2 6 A0A0A0 15 5 -0.988000 -0.645700 0.000000 900 2 6 A0A0A0 16 5 -1.771500 -0.859900 0.000000 900 2 6 A0A0A0 17 5 -0.964500 -1.031400 0.000000 900 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 ::: "Untitled Document-1" 40 newTemps.5 /Users/nicola/schrodinger/coordgen_standalone templates.mae 40 templates->templates->templates templates->templates1->templates11 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 900 43 7 5757FF "N1" 2 5 -1.579200 0.995900 0.000000 900 2 6 A0A0A0 "" 3 3 -0.995900 0.412500 0.000000 900 2 6 A0A0A0 "" 4 3 -0.412500 0.995900 0.000000 900 2 6 A0A0A0 "" 5 5 -0.412500 -0.170900 0.000000 900 2 6 A0A0A0 "" 6 5 0.170900 0.412500 0.000000 900 2 6 A0A0A0 "" 7 5 -0.995900 -0.412500 0.000000 900 2 6 A0A0A0 "" 8 5 -0.412500 -0.995900 0.000000 900 2 6 A0A0A0 "" 9 3 0.412500 -0.995900 0.000000 900 2 6 A0A0A0 "" 10 3 0.995900 -0.412500 0.000000 900 2 6 A0A0A0 "" 11 5 0.995900 0.412500 0.000000 900 2 6 A0A0A0 "" 12 5 0.412500 0.995900 0.000000 900 2 6 A0A0A0 "" 13 5 1.102600 -0.810900 0.000000 900 2 6 A0A0A0 "" 14 5 0.510524 -1.402976 0.000000 900 2 6 A0A0A0 "" 15 27 1.579200 -0.995900 0.000000 900 43 7 5757FF "N15" 16 27 0.995900 -1.579200 0.000000 900 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 41 twistane.1 /Users/nicola/schrodinger/coordgen_standalone templates.mae 41 templates->templates->templates templates->templates1->templates11 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 900 2 6 A0A0A0 2 4 1.714300 0.857100 0.000000 900 2 6 A0A0A0 3 27 -1.428600 0.428600 0.000000 900 43 7 5757FF 4 27 0.142900 -1.428600 0.000000 900 43 7 5757FF 5 5 1.571400 2.285700 0.000000 900 2 6 A0A0A0 6 5 3.142900 0.428600 0.000000 900 2 6 A0A0A0 7 5 0.142900 2.285700 0.000000 900 2 6 A0A0A0 8 4 0.000000 0.857100 0.000000 900 2 6 A0A0A0 9 4 1.714300 0.000000 0.000000 900 2 6 A0A0A0 10 5 1.571400 -1.428600 0.000000 900 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 ::: "New Entry" 42 entry /Users/nicola/schrodinger/coordgen_standalone templates.mae 42 templates->templates->templates templates->templates1->templates11 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 900 43 7 5757FF "N1" 2 26 0.866300 3.103500 0.000000 900 43 7 5757FF "N2" 3 158 -0.370900 1.246300 0.000000 900 20 8 9F5F9F "3" 4 27 2.103500 2.674900 0.000000 900 43 7 5757FF "N4" 5 5 1.580600 2.152000 0.000000 900 2 6 A0A0A0 "" 6 4 2.103500 1.246300 0.000000 900 2 6 A0A0A0 "" 7 5 0.866300 0.817800 0.000000 900 2 6 A0A0A0 "" 8 5 2.817800 0.294900 0.000000 900 2 6 A0A0A0 "" 9 5 0.343400 0.294900 0.000000 900 2 6 A0A0A0 "" 10 4 1.580600 0.723400 0.000000 900 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 ::: Structure 43 Structure /Users/nicola/schrodinger/coordgen_standalone templates.mae 43 templates->templates->templates templates->templates1->templates11 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 900 2 6 A0A0A0 2 7 3.230400 -1.703100 0.000000 900 2 6 A0A0A0 3 4 0.947900 -2.321500 0.000000 900 2 6 A0A0A0 4 4 0.600500 -1.146200 0.000000 900 2 6 A0A0A0 5 5 -0.515400 -2.828800 0.000000 900 2 6 A0A0A0 6 5 -1.525500 -1.818600 0.000000 900 2 6 A0A0A0 7 2 1.380300 -0.368400 0.000000 900 2 6 A0A0A0 8 2 0.000000 0.000000 0.000000 900 2 6 A0A0A0 9 5 2.157100 0.830500 0.000000 900 2 6 A0A0A0 10 5 1.257000 1.939800 0.000000 900 2 6 A0A0A0 11 5 -0.076200 1.426500 0.000000 900 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_sd_Author_Affiliation s_sd_Citation i_sd_Citation_ID i_sd_Compound_Label s_sd_Set\_Name i_sd_Row_Number s_m_subgroup_title s_m_subgroupid b_m_subgroup_collapsed i_m_ct_format ::: 10 44 rifapentine_core.1 /Users/nicola/schrodinger/coordgen_standalone templates.mae 44 "Hoffmann-La Roche" "Patent 2012 WO2012007375" 3700 10 irak4_sar_14 63 templates->templates->templates templates->templates1->templates11 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 900 2 6 A0A0A0 2 2 -7.721800 -2.173600 0.000000 900 2 6 A0A0A0 3 7 -7.721800 -3.602600 0.000000 900 2 6 A0A0A0 4 7 -6.896800 -3.602600 0.000000 900 2 6 A0A0A0 5 2 -6.484300 -2.888100 0.000000 900 2 6 A0A0A0 6 5 -8.240900 -1.532500 0.000000 900 2 6 A0A0A0 7 4 -9.011100 -1.828100 0.000000 900 2 6 A0A0A0 8 16 -8.968000 -2.652000 0.000000 900 70 8 FF2F2F 9 2 -8.134300 -2.888100 0.000000 900 2 6 A0A0A0 10 16 -9.866900 -2.100600 0.000000 900 70 8 FF2F2F 11 5 -5.659300 -1.459100 0.000000 900 2 6 A0A0A0 12 5 -6.484300 -1.459100 0.000000 900 2 6 A0A0A0 13 7 -5.659300 -2.888100 0.000000 900 2 6 A0A0A0 14 2 -5.246800 -2.173600 0.000000 900 2 6 A0A0A0 15 29 -4.421800 -2.173600 0.000000 900 43 7 5757FF 16 5 -3.897300 -2.727500 0.000000 900 2 6 A0A0A0 17 7 -9.808000 -2.866700 0.000000 900 2 6 A0A0A0 18 7 -10.345700 -3.367600 0.000000 900 2 6 A0A0A0 19 5 -10.316300 -4.251500 0.000000 900 2 6 A0A0A0 20 5 -9.762400 -4.893800 0.000000 900 2 6 A0A0A0 21 5 -9.762400 -5.718800 0.000000 900 2 6 A0A0A0 22 5 -9.031700 -6.184300 0.000000 900 2 6 A0A0A0 23 5 -8.234800 -5.823400 0.000000 900 2 6 A0A0A0 24 5 -7.437600 -6.194200 0.000000 900 2 6 A0A0A0 25 5 -6.658500 -5.852900 0.000000 900 2 6 A0A0A0 26 5 -5.777300 -6.117100 0.000000 900 2 6 A0A0A0 27 7 -3.844700 -3.611200 0.000000 900 2 6 A0A0A0 28 7 -4.147600 -4.405900 0.000000 900 2 6 A0A0A0 29 7 -4.934100 -4.724500 0.000000 900 2 6 A0A0A0 30 7 -5.132900 -5.557900 0.000000 900 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 ::: "Untitled Document-1" 45 senecionine.1 /Users/nicola/schrodinger/coordgen_standalone templates.mae 45 templates->templates->templates templates->templates1->templates11 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 900 2 6 A0A0A0 2 4 -0.044700 -1.618800 0.000000 900 2 6 A0A0A0 3 5 0.739900 -1.873700 0.000000 900 2 6 A0A0A0 4 5 1.224800 -1.206300 0.000000 900 2 6 A0A0A0 5 4 0.739900 -0.538800 0.000000 900 2 6 A0A0A0 6 4 -0.829300 -0.538800 0.000000 900 2 6 A0A0A0 7 5 -1.314300 -1.206300 0.000000 900 2 6 A0A0A0 8 5 -0.829300 -1.873700 0.000000 900 2 6 A0A0A0 9 5 -0.809300 0.245800 0.000000 900 2 6 A0A0A0 10 5 -1.428900 1.461200 0.000000 900 2 6 A0A0A0 11 5 -1.428900 0.636200 0.000000 900 2 6 A0A0A0 12 5 0.000000 1.461200 0.000000 900 2 6 A0A0A0 13 5 -0.714500 1.873700 0.000000 900 2 6 A0A0A0 14 5 0.714500 0.223700 0.000000 900 2 6 A0A0A0 15 5 1.428900 0.636200 0.000000 900 2 6 A0A0A0 16 5 1.428900 1.461200 0.000000 900 2 6 A0A0A0 17 5 0.714500 1.873700 0.000000 900 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 ::: "Untitled Document-2" 46 temp.1 /Users/nicola/schrodinger/coordgen_standalone templates.mae 46 templates->templates->templates templates->templates1->templates11 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 900 2 6 A0A0A0 "" 2 5 -1.428900 1.650000 0.000000 900 2 6 A0A0A0 "" 3 5 -0.714500 2.062500 0.000000 900 2 6 A0A0A0 "" 4 4 -0.714500 2.887500 0.000000 900 2 6 A0A0A0 "" 5 27 -1.428900 3.300000 0.000000 900 43 7 5757FF "N5" 6 27 -2.143400 2.887500 0.000000 900 43 7 5757FF "N6" 7 5 0.714500 2.062500 0.000000 900 2 6 A0A0A0 "" 8 4 0.714500 2.887500 0.000000 900 2 6 A0A0A0 "" 9 5 0.000000 3.300000 0.000000 900 2 6 A0A0A0 "" 10 5 1.428900 1.650000 0.000000 900 2 6 A0A0A0 "" 11 4 2.143400 2.062500 0.000000 900 2 6 A0A0A0 "" 12 27 2.143400 2.887500 0.000000 900 43 7 5757FF "N12" 13 27 1.428900 3.300000 0.000000 900 43 7 5757FF "N13" 14 5 -2.857900 1.650000 0.000000 900 2 6 A0A0A0 "" 15 4 -2.857900 0.825000 0.000000 900 2 6 A0A0A0 "" 16 27 -3.572400 0.412500 0.000000 900 43 7 5757FF "N16" 17 27 -3.572400 -0.412500 0.000000 900 43 7 5757FF "N17" 18 5 -2.143400 0.412500 0.000000 900 2 6 A0A0A0 "" 19 5 -2.143400 -0.412500 0.000000 900 2 6 A0A0A0 "" 20 4 -2.857900 -0.825000 0.000000 900 2 6 A0A0A0 "" 21 27 2.857900 1.650000 0.000000 900 43 7 5757FF "N21" 22 4 2.857900 0.825000 0.000000 900 2 6 A0A0A0 "" 23 5 -2.857900 -1.650000 0.000000 900 2 6 A0A0A0 "" 24 4 -2.143400 -2.062500 0.000000 900 2 6 A0A0A0 "" 25 5 -1.428900 -1.650000 0.000000 900 2 6 A0A0A0 "" 26 5 -0.714500 -2.062500 0.000000 900 2 6 A0A0A0 "" 27 4 -0.714500 -2.887500 0.000000 900 2 6 A0A0A0 "" 28 27 -1.428900 -3.300000 0.000000 900 43 7 5757FF "N28" 29 27 -2.143400 -2.887500 0.000000 900 43 7 5757FF "N29" 30 5 2.143400 0.412500 0.000000 900 2 6 A0A0A0 "" 31 5 2.143400 -0.412500 0.000000 900 2 6 A0A0A0 "" 32 4 2.857900 -0.825000 0.000000 900 2 6 A0A0A0 "" 33 27 3.572400 -0.412500 0.000000 900 43 7 5757FF "N33" 34 27 3.572400 0.412500 0.000000 900 43 7 5757FF "N34" 35 5 2.857900 -1.650000 0.000000 900 2 6 A0A0A0 "" 36 4 2.143400 -2.062500 0.000000 900 2 6 A0A0A0 "" 37 5 0.000000 -3.300000 0.000000 900 2 6 A0A0A0 "" 38 4 0.714500 -2.887500 0.000000 900 2 6 A0A0A0 "" 39 5 0.714500 -2.062500 0.000000 900 2 6 A0A0A0 "" 40 5 1.428900 -1.650000 0.000000 900 2 6 A0A0A0 "" 41 27 2.143400 -2.887500 0.000000 900 43 7 5757FF "N41" 42 27 1.428900 -3.300000 0.000000 900 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_st_Chirality_1 s_st_Chirality_2 s_st_Chirality_3 s_st_Chirality_4 s_st_Chirality_5 s_st_AtomNumChirality_1 s_st_AtomNumChirality_2 s_m_subgroup_title s_m_subgroupid b_m_subgroup_collapsed i_m_ct_format ::: temp.mol 47 temp2.1 /Users/nicola/schrodinger/coordgen_standalone templates.mae 47 3_ANS_1_4_6 6_S_7_17_3 16_ANS_2_5_15_17 15_R_18_16_14 17_S_6_12_16_20 3_ANS_1_4_6 16_ANS_2_5_15_17 templates->templates->templates templates->templates1->templates11 0 2 m_depend[7] { # 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 3 10 s_st_Chirality_3 4 10 s_st_Chirality_4 5 10 s_st_Chirality_5 6 10 s_st_AtomNumChirality_1 7 10 s_st_AtomNumChirality_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 900 2 6 A0A0A0 2 5 1.649400 0.593500 0.000000 900 2 6 A0A0A0 3 4 1.650600 -0.835500 0.000000 900 2 6 A0A0A0 4 5 1.688500 -0.217900 0.000000 900 2 6 A0A0A0 5 5 1.378700 0.317700 0.000000 900 2 6 A0A0A0 6 4 0.825600 -0.836100 0.000000 900 2 6 A0A0A0 7 16 0.001000 -1.384000 0.000000 900 70 8 FF2F2F 8 2 -0.824400 -0.837400 0.000000 900 2 6 A0A0A0 9 7 -1.649400 -0.838000 0.000000 900 2 6 A0A0A0 10 7 -2.062500 -0.123900 0.000000 900 2 6 A0A0A0 11 7 -1.650600 0.590900 0.000000 900 2 6 A0A0A0 12 2 -0.412500 -0.122600 0.000000 900 2 6 A0A0A0 13 2 -0.825600 0.591500 0.000000 900 2 6 A0A0A0 14 5 -0.413600 1.306300 0.000000 900 2 6 A0A0A0 15 4 0.411400 1.307000 0.000000 900 2 6 A0A0A0 16 3 0.824400 0.592800 0.000000 900 2 6 A0A0A0 17 3 0.412500 -0.122000 0.000000 900 2 6 A0A0A0 18 27 1.336300 1.384000 0.000000 900 43 7 5757FF 19 5 1.822900 0.593600 0.000000 900 2 6 A0A0A0 20 5 1.337500 -0.197500 0.000000 900 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_st_Chirality_1 s_st_Chirality_2 s_st_Chirality_3 s_m_subgroup_title s_m_subgroupid b_m_subgroup_collapsed i_m_ct_format ::: temp2.mol 48 temp3.1 /Users/nicola/schrodinger/coordgen_standalone templates.mae 48 4_S_5_15_3 13_R_16_14_12 15_S_4_10_14_18 templates->templates->templates templates->templates1->templates11 0 2 m_depend[3] { # 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 3 10 s_st_Chirality_3 ::: } 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 900 2 6 A0A0A0 2 5 1.649400 0.593500 0.000000 900 2 6 A0A0A0 3 5 1.650600 -0.835500 0.000000 900 2 6 A0A0A0 4 4 0.825600 -0.836100 0.000000 900 2 6 A0A0A0 5 16 0.001000 -1.384000 0.000000 900 70 8 FF2F2F 6 2 -0.824400 -0.837400 0.000000 900 2 6 A0A0A0 7 7 -1.649400 -0.838000 0.000000 900 2 6 A0A0A0 8 7 -2.062500 -0.123900 0.000000 900 2 6 A0A0A0 9 7 -1.650600 0.590900 0.000000 900 2 6 A0A0A0 10 2 -0.412500 -0.122600 0.000000 900 2 6 A0A0A0 11 2 -0.825600 0.591500 0.000000 900 2 6 A0A0A0 12 5 -0.413600 1.306300 0.000000 900 2 6 A0A0A0 13 4 0.411400 1.307000 0.000000 900 2 6 A0A0A0 14 4 0.824400 0.592800 0.000000 900 2 6 A0A0A0 15 3 0.412500 -0.122000 0.000000 900 2 6 A0A0A0 16 27 1.336300 1.384000 0.000000 900 43 7 5757FF 17 5 1.822900 0.593600 0.000000 900 2 6 A0A0A0 18 5 1.337500 -0.197500 0.000000 900 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 ::: "Untitled Document-2" 49 temp4.1 /Users/nicola/schrodinger/coordgen_standalone templates.mae 49 templates->templates->templates templates->templates1->templates11 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 900 2 6 A0A0A0 2 5 -1.428900 -2.268700 0.000000 900 2 6 A0A0A0 3 5 -0.714500 -2.681200 0.000000 900 2 6 A0A0A0 4 5 0.000000 -2.268700 0.000000 900 2 6 A0A0A0 5 5 0.000000 -1.443800 0.000000 900 2 6 A0A0A0 6 4 -0.714500 -1.031200 0.000000 900 2 6 A0A0A0 7 5 0.714500 -2.681200 0.000000 900 2 6 A0A0A0 8 5 1.428900 -2.268700 0.000000 900 2 6 A0A0A0 9 5 1.428900 -1.443800 0.000000 900 2 6 A0A0A0 10 4 0.714500 -1.031200 0.000000 900 2 6 A0A0A0 11 5 0.714500 -0.206200 0.000000 900 2 6 A0A0A0 12 5 -0.714500 -0.206200 0.000000 900 2 6 A0A0A0 13 5 -0.714500 1.443800 0.000000 900 2 6 A0A0A0 14 5 -1.428900 1.031200 0.000000 900 2 6 A0A0A0 15 5 -1.428900 0.206200 0.000000 900 2 6 A0A0A0 16 5 1.428900 0.206200 0.000000 900 2 6 A0A0A0 17 5 1.428900 1.031200 0.000000 900 2 6 A0A0A0 18 5 0.714500 1.443800 0.000000 900 2 6 A0A0A0 19 5 0.714500 2.268700 0.000000 900 2 6 A0A0A0 20 5 0.000000 2.681200 0.000000 900 2 6 A0A0A0 21 5 -0.714500 2.268700 0.000000 900 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 ::: "Untitled Document-2" 50 temp5.1 /Users/nicola/schrodinger/coordgen_standalone templates.mae 50 templates->templates->templates templates->templates1->templates11 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 900 2 6 A0A0A0 2 4 1.786200 -1.650000 0.000000 900 2 6 A0A0A0 3 5 2.500600 -2.062500 0.000000 900 2 6 A0A0A0 4 5 3.215100 -1.650000 0.000000 900 2 6 A0A0A0 5 5 3.215100 -0.825000 0.000000 900 2 6 A0A0A0 6 5 2.500600 -0.412500 0.000000 900 2 6 A0A0A0 7 5 1.071700 -2.062500 0.000000 900 2 6 A0A0A0 8 5 0.357200 -1.650000 0.000000 900 2 6 A0A0A0 9 5 -0.357200 -2.062500 0.000000 900 2 6 A0A0A0 10 5 -1.071700 -1.650000 0.000000 900 2 6 A0A0A0 11 5 -1.786200 -2.062500 0.000000 900 2 6 A0A0A0 12 4 -2.500600 -1.650000 0.000000 900 2 6 A0A0A0 13 4 -2.500600 -0.825000 0.000000 900 2 6 A0A0A0 14 5 -3.215100 -1.237500 0.000000 900 2 6 A0A0A0 15 5 -1.786200 -0.412500 0.000000 900 2 6 A0A0A0 16 5 -1.786200 0.412500 0.000000 900 2 6 A0A0A0 17 5 -1.071700 0.825000 0.000000 900 2 6 A0A0A0 18 5 -1.071700 1.650000 0.000000 900 2 6 A0A0A0 19 5 -0.357200 2.062500 0.000000 900 2 6 A0A0A0 20 4 0.357200 1.650000 0.000000 900 2 6 A0A0A0 21 5 1.181700 -0.302500 0.000000 900 2 6 A0A0A0 22 5 0.357200 0.825000 0.000000 900 2 6 A0A0A0 23 4 1.141900 0.570100 0.000000 900 2 6 A0A0A0 24 5 1.626800 1.237500 0.000000 900 2 6 A0A0A0 25 5 1.141900 1.904900 0.000000 900 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 ::: temps2.sdf 51 temp6.1 /Users/nicola/schrodinger/coordgen_standalone templates.mae 51 templates->templates->templates templates->templates1->templates11 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 900 2 6 A0A0A0 2 5 -1.596700 -0.783000 0.000000 900 2 6 A0A0A0 3 3 -0.983600 -0.230900 0.000000 900 2 6 A0A0A0 4 26 -0.440700 -1.450400 0.000000 900 43 7 5757FF 5 4 -0.269100 -0.643400 0.000000 900 2 6 A0A0A0 6 4 0.445300 -0.230900 0.000000 900 2 6 A0A0A0 7 4 0.445300 0.594100 0.000000 900 2 6 A0A0A0 8 2 1.089000 1.110200 0.000000 900 2 6 A0A0A0 9 5 -0.424500 1.907700 0.000000 900 2 6 A0A0A0 10 26 -1.768200 0.849000 0.000000 900 43 7 5757FF 11 4 -0.983600 0.594100 0.000000 900 2 6 A0A0A0 12 5 -0.269100 1.006600 0.000000 900 2 6 A0A0A0 13 5 -2.253200 0.181600 0.000000 900 2 6 A0A0A0 14 5 -1.768200 -0.485900 0.000000 900 2 6 A0A0A0 15 7 1.893700 0.928500 0.000000 900 2 6 A0A0A0 16 5 2.253200 0.185900 0.000000 900 2 6 A0A0A0 17 16 1.896500 -0.558000 0.000000 900 70 8 FF2F2F 18 4 1.092400 -0.742700 0.000000 900 2 6 A0A0A0 19 5 0.995000 -1.561900 0.000000 900 2 6 A0A0A0 20 5 0.246000 -1.907700 0.000000 900 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 ::: "Untitled Document-1" 52 template.1 /Users/nicola/schrodinger/coordgen_standalone templates.mae 52 templates->templates->templates templates->templates1->templates11 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 900 2 6 A0A0A0 2 5 -2.516200 -1.428900 0.000000 900 2 6 A0A0A0 3 4 -2.103800 -0.714500 0.000000 900 2 6 A0A0A0 4 4 -2.516200 0.000000 0.000000 900 2 6 A0A0A0 5 4 -3.341300 0.000000 0.000000 900 2 6 A0A0A0 6 5 -3.753800 -0.714500 0.000000 900 2 6 A0A0A0 7 4 -2.103800 0.714500 0.000000 900 2 6 A0A0A0 8 5 -2.516200 1.428900 0.000000 900 2 6 A0A0A0 9 5 -3.341300 1.428900 0.000000 900 2 6 A0A0A0 10 5 -3.753800 0.714500 0.000000 900 2 6 A0A0A0 11 5 -1.691200 -1.428900 0.000000 900 2 6 A0A0A0 12 4 -0.866200 -1.428900 0.000000 900 2 6 A0A0A0 13 5 -1.691200 1.428900 0.000000 900 2 6 A0A0A0 14 4 -0.866200 1.428900 0.000000 900 2 6 A0A0A0 15 5 -0.453700 0.714500 0.000000 900 2 6 A0A0A0 16 5 0.371300 0.714500 0.000000 900 2 6 A0A0A0 17 5 0.783800 1.428900 0.000000 900 2 6 A0A0A0 18 4 0.371300 2.143400 0.000000 900 2 6 A0A0A0 19 5 -0.453700 2.143400 0.000000 900 2 6 A0A0A0 20 5 -0.453700 -2.143400 0.000000 900 2 6 A0A0A0 21 5 0.371300 -2.143400 0.000000 900 2 6 A0A0A0 22 4 0.783800 -1.428900 0.000000 900 2 6 A0A0A0 23 5 0.371300 -0.714500 0.000000 900 2 6 A0A0A0 24 5 -0.453700 -0.714500 0.000000 900 2 6 A0A0A0 25 5 1.691200 -1.428900 0.000000 900 2 6 A0A0A0 26 4 2.103800 -0.714500 0.000000 900 2 6 A0A0A0 27 5 2.516200 -1.428900 0.000000 900 2 6 A0A0A0 28 5 3.341300 -1.428900 0.000000 900 2 6 A0A0A0 29 5 3.753800 -0.714500 0.000000 900 2 6 A0A0A0 30 4 3.341300 0.000000 0.000000 900 2 6 A0A0A0 31 4 2.516200 0.000000 0.000000 900 2 6 A0A0A0 32 5 3.753800 0.714500 0.000000 900 2 6 A0A0A0 33 5 3.341300 1.428900 0.000000 900 2 6 A0A0A0 34 4 2.516200 1.428900 0.000000 900 2 6 A0A0A0 35 5 2.103800 0.714500 0.000000 900 2 6 A0A0A0 36 5 2.103800 2.143400 0.000000 900 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_st_Chirality_1 s_st_Chirality_2 s_st_Chirality_3 s_m_subgroup_title s_m_subgroupid b_m_subgroup_collapsed i_m_ct_format ::: temps.sdf 53 temps.1 /Users/nicola/schrodinger/coordgen_standalone templates.mae 53 15_R_14_16_27 18_R_17_19_21 41_S_20_42_40 templates->templates->templates templates->templates1->templates11 0 2 m_depend[3] { # 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 3 10 s_st_Chirality_3 ::: } 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 900 2 6 A0A0A0 2 7 -2.441700 2.181600 0.000000 900 2 6 A0A0A0 3 2 -2.441700 3.006600 0.000000 900 2 6 A0A0A0 4 16 -1.727200 3.419100 0.000000 900 70 8 FF2F2F 5 7 -3.156200 3.419100 0.000000 900 2 6 A0A0A0 6 7 -3.870700 3.006600 0.000000 900 2 6 A0A0A0 7 2 -3.870700 2.181600 0.000000 900 2 6 A0A0A0 8 5 -4.585100 1.769100 0.000000 900 2 6 A0A0A0 9 5 -4.585100 0.944100 0.000000 900 2 6 A0A0A0 10 5 -3.870700 0.531600 0.000000 900 2 6 A0A0A0 11 27 -3.156200 0.944100 0.000000 900 43 7 5757FF 12 5 -2.441700 0.531600 0.000000 900 2 6 A0A0A0 13 5 -1.727200 0.944100 0.000000 900 2 6 A0A0A0 14 27 -1.012800 0.531600 0.000000 900 43 7 5757FF 15 4 -0.298300 0.944100 0.000000 900 2 6 A0A0A0 16 5 0.416200 0.531600 0.000000 900 2 6 A0A0A0 17 27 1.130600 0.944100 0.000000 900 43 7 5757FF 18 4 1.845100 0.531600 0.000000 900 2 6 A0A0A0 19 5 2.559600 0.944100 0.000000 900 2 6 A0A0A0 20 27 3.274100 0.531600 0.000000 900 43 7 5757FF 21 2 1.907300 -0.291100 0.000000 900 2 6 A0A0A0 22 7 2.650800 -0.648600 0.000000 900 2 6 A0A0A0 23 2 2.613900 -1.475500 0.000000 900 2 6 A0A0A0 24 7 1.916600 -1.916400 0.000000 900 2 6 A0A0A0 25 7 1.192900 -1.520300 0.000000 900 2 6 A0A0A0 26 7 1.188100 -0.695400 0.000000 900 2 6 A0A0A0 27 2 -0.298300 1.769100 0.000000 900 2 6 A0A0A0 28 7 0.416200 2.181600 0.000000 900 2 6 A0A0A0 29 7 -1.012800 2.181600 0.000000 900 2 6 A0A0A0 30 2 -1.012800 3.006600 0.000000 900 2 6 A0A0A0 31 7 -0.298300 3.419100 0.000000 900 2 6 A0A0A0 32 2 0.416200 3.006600 0.000000 900 2 6 A0A0A0 33 16 1.130600 3.419100 0.000000 900 70 8 FF2F2F 34 2 1.845100 3.006600 0.000000 900 2 6 A0A0A0 35 7 1.845100 2.181600 0.000000 900 2 6 A0A0A0 36 7 2.559600 1.769100 0.000000 900 2 6 A0A0A0 37 7 2.559600 3.419100 0.000000 900 2 6 A0A0A0 38 7 3.274100 3.006600 0.000000 900 2 6 A0A0A0 39 2 3.274100 2.181600 0.000000 900 2 6 A0A0A0 40 5 3.988500 1.769100 0.000000 900 2 6 A0A0A0 41 4 3.988500 0.944100 0.000000 900 2 6 A0A0A0 42 5 4.567000 0.323700 0.000000 900 2 6 A0A0A0 43 27 4.133800 -0.378400 0.000000 900 43 7 5757FF 44 5 4.447200 -1.141600 0.000000 900 2 6 A0A0A0 45 2 4.051300 -1.865400 0.000000 900 2 6 A0A0A0 46 2 3.239600 -2.013300 0.000000 900 2 6 A0A0A0 47 7 4.585100 -2.494400 0.000000 900 2 6 A0A0A0 48 7 4.307300 -3.271200 0.000000 900 2 6 A0A0A0 49 7 3.495700 -3.419100 0.000000 900 2 6 A0A0A0 50 7 2.961800 -2.790100 0.000000 900 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_st_Chirality_1 s_m_subgroup_title s_m_subgroupid b_m_subgroup_collapsed i_m_ct_format ::: temps.sdf 54 temps.2 /Users/nicola/schrodinger/coordgen_standalone templates.mae 54 2_S_6_1_3 templates->templates->templates templates->templates1->templates11 0 2 m_depend[1] { # First column is dependency index # i_m_depend_dependency s_m_depend_property ::: 1 10 s_st_Chirality_1 ::: } 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 900 2 6 A0A0A0 2 4 0.418000 -1.600800 0.000000 900 2 6 A0A0A0 3 5 1.100100 -2.064900 0.000000 900 2 6 A0A0A0 4 5 1.752300 -1.559600 0.000000 900 2 6 A0A0A0 5 2 1.473200 -0.783200 0.000000 900 2 6 A0A0A0 6 25 0.648600 -0.808700 0.000000 900 43 7 5757FF 7 7 1.937300 -0.101100 0.000000 900 2 6 A0A0A0 8 2 1.604800 0.653900 0.000000 900 2 6 A0A0A0 9 5 2.020200 1.366700 0.000000 900 2 6 A0A0A0 10 5 1.470600 1.982000 0.000000 900 2 6 A0A0A0 11 2 0.715600 1.649500 0.000000 900 2 6 A0A0A0 12 25 0.798500 0.828700 0.000000 900 43 7 5757FF 13 7 0.002800 2.064900 0.000000 900 2 6 A0A0A0 14 2 -0.713300 1.655300 0.000000 900 2 6 A0A0A0 15 5 -1.465700 1.993900 0.000000 900 2 6 A0A0A0 16 5 -2.020200 1.383000 0.000000 900 2 6 A0A0A0 17 2 -1.610500 0.666900 0.000000 900 2 6 A0A0A0 18 25 -0.802900 0.835100 0.000000 900 43 7 5757FF 19 7 -1.949100 -0.085500 0.000000 900 2 6 A0A0A0 20 2 -1.490600 -0.771300 0.000000 900 2 6 A0A0A0 21 29 -0.666200 -0.803400 0.000000 900 43 7 5757FF 22 5 -1.775800 -1.545400 0.000000 900 2 6 A0A0A0 23 5 -1.127800 -2.055900 0.000000 900 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 ::: temps.sdf 55 temps.3 /Users/nicola/schrodinger/coordgen_standalone templates.mae 55 templates->templates->templates templates->templates1->templates11 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 900 2 6 A0A0A0 "" 2 7 0.095200 -0.635500 0.000000 900 2 6 A0A0A0 "" 3 7 -0.577900 -0.158400 0.000000 900 2 6 A0A0A0 "" 4 2 -1.327600 -0.502800 0.000000 900 2 6 A0A0A0 "" 5 25 -1.404200 -1.324200 0.000000 900 43 7 5757FF "N5" 6 25 -0.731100 -1.801300 0.000000 900 43 7 5757FF "N6" 7 16 -1.886800 0.103800 0.000000 900 70 8 FF2F2F "" 8 5 -1.641100 0.891400 0.000000 900 2 6 A0A0A0 "" 9 5 -0.836200 1.072300 0.000000 900 2 6 A0A0A0 "" 10 5 -0.432100 1.791600 0.000000 900 2 6 A0A0A0 "" 11 5 0.392900 1.801300 0.000000 900 2 6 A0A0A0 "" 12 27 0.813700 1.091700 0.000000 900 43 7 5757FF "" 13 5 1.622700 0.929600 0.000000 900 2 6 A0A0A0 "" 14 5 1.886800 0.148100 0.000000 900 2 6 A0A0A0 "" 15 27 1.342000 -0.471500 0.000000 900 43 7 5757FF "" 16 5 1.437800 -1.290900 0.000000 900 2 6 A0A0A0 "" 17 5 0.776100 -1.783600 0.000000 900 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 ::: temps.sdf 56 temps.4 /Users/nicola/schrodinger/coordgen_standalone templates.mae 56 templates->templates->templates templates->templates1->templates11 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 900 2 6 A0A0A0 2 25 1.936000 0.667400 0.000000 900 43 7 5757FF 3 2 1.151400 0.412500 0.000000 900 2 6 A0A0A0 4 2 1.151400 -0.412500 0.000000 900 2 6 A0A0A0 5 25 2.421000 0.000000 0.000000 900 43 7 5757FF 6 7 1.936000 -0.667400 0.000000 900 2 6 A0A0A0 7 25 1.186700 2.013300 0.000000 900 43 7 5757FF 8 2 0.436900 1.650000 0.000000 900 2 6 A0A0A0 9 25 0.436900 0.825000 0.000000 900 43 7 5757FF 10 29 -0.277500 2.062500 0.000000 900 43 7 5757FF 11 2 -0.992000 1.650000 0.000000 900 2 6 A0A0A0 12 7 -0.992000 0.825000 0.000000 900 2 6 A0A0A0 13 2 -1.706500 0.412500 0.000000 900 2 6 A0A0A0 14 7 -2.421000 0.825000 0.000000 900 2 6 A0A0A0 15 7 -2.420900 1.650000 0.000000 900 2 6 A0A0A0 16 7 -1.706500 2.062500 0.000000 900 2 6 A0A0A0 17 29 -1.706500 -0.412500 0.000000 900 43 7 5757FF 18 5 -0.992000 -0.825000 0.000000 900 2 6 A0A0A0 19 5 -0.992000 -1.650000 0.000000 900 2 6 A0A0A0 20 5 -0.277500 -2.062500 0.000000 900 2 6 A0A0A0 21 5 0.436900 -1.650000 0.000000 900 2 6 A0A0A0 22 5 0.436900 -0.825000 0.000000 900 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 ::: temps.sdf 57 temps.5 /Users/nicola/schrodinger/coordgen_standalone templates.mae 57 templates->templates->templates templates->templates1->templates11 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 900 2 6 A0A0A0 "" 2 5 1.071700 1.650000 0.000000 900 2 6 A0A0A0 "" 3 27 -0.357200 1.650000 0.000000 900 43 7 5757FF "" 4 5 -1.071700 2.062500 0.000000 900 2 6 A0A0A0 "" 5 5 -1.786200 1.650000 0.000000 900 2 6 A0A0A0 "" 6 27 -1.786200 0.825000 0.000000 900 43 7 5757FF "" 7 5 -1.071700 0.412500 0.000000 900 2 6 A0A0A0 "" 8 5 -1.071700 -0.412500 0.000000 900 2 6 A0A0A0 "" 9 5 -0.357200 -0.825000 0.000000 900 2 6 A0A0A0 "" 10 5 -0.357200 -1.650000 0.000000 900 2 6 A0A0A0 "" 11 5 0.357200 -2.062500 0.000000 900 2 6 A0A0A0 "" 12 16 1.071700 -1.650000 0.000000 900 70 8 FF2F2F "" 13 2 1.071700 -0.825000 0.000000 900 2 6 A0A0A0 "" 14 25 1.786200 -0.412500 0.000000 900 43 7 5757FF "N14" 15 25 1.786200 0.412500 0.000000 900 43 7 5757FF "N15" 16 2 1.071700 0.825000 0.000000 900 2 6 A0A0A0 "" 17 7 0.357200 -0.412500 0.000000 900 2 6 A0A0A0 "" 18 7 0.357200 0.412500 0.000000 900 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_st_Chirality_1 s_st_Chirality_2 s_st_Chirality_3 s_st_Chirality_4 s_st_Chirality_5 s_st_Chirality_6 s_m_subgroup_title s_m_subgroupid b_m_subgroup_collapsed i_m_ct_format ::: temps.sdf 58 temps.6 /Users/nicola/schrodinger/coordgen_standalone templates.mae 58 4_R_5_7_3 7_R_9_4_8 9_S_6_10_7_1 10_R_9_11_12 11_R_10_8_15_17 14_S_15_16_13 templates->templates->templates templates->templates1->templates11 0 2 m_depend[6] { # 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 3 10 s_st_Chirality_3 4 10 s_st_Chirality_4 5 10 s_st_Chirality_5 6 10 s_st_Chirality_6 ::: } 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 900 2 6 A0A0A0 2 5 1.887700 -0.695100 0.000000 900 2 6 A0A0A0 3 5 2.142600 0.089500 0.000000 900 2 6 A0A0A0 4 4 1.590600 0.702600 0.000000 900 2 6 A0A0A0 5 5 0.932100 0.874800 0.000000 900 2 6 A0A0A0 6 16 0.426300 0.419300 0.000000 900 70 8 FF2F2F 7 4 0.783600 0.531100 0.000000 900 2 6 A0A0A0 8 5 0.116200 1.016000 0.000000 900 2 6 A0A0A0 9 3 0.528700 -0.253500 0.000000 900 2 6 A0A0A0 10 4 -0.296300 -0.253500 0.000000 900 2 6 A0A0A0 11 3 -0.551300 0.531100 0.000000 900 2 6 A0A0A0 12 5 -0.750800 -0.942100 0.000000 900 2 6 A0A0A0 13 5 -1.572500 -1.016000 0.000000 900 2 6 A0A0A0 14 4 -2.142600 -0.419700 0.000000 900 2 6 A0A0A0 15 5 -1.073600 -0.401900 0.000000 900 2 6 A0A0A0 16 5 -2.031900 0.397800 0.000000 900 2 6 A0A0A0 17 5 -1.323700 0.821000 0.000000 900 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_st_Chirality_1 s_st_Chirality_2 s_st_Chirality_3 s_st_Chirality_4 s_st_Chirality_5 s_st_Chirality_6 s_m_subgroup_title s_m_subgroupid b_m_subgroup_collapsed i_m_ct_format ::: temps.sdf 59 temps.7 /Users/nicola/schrodinger/coordgen_standalone templates.mae 59 3_R_5_4_1 5_S_7_3_6 7_S_9_5_8 10_S_9_11_4 11_R_12_10_15 15_R_11_8_14_6 templates->templates->templates templates->templates1->templates11 0 2 m_depend[6] { # 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 3 10 s_st_Chirality_3 4 10 s_st_Chirality_4 5 10 s_st_Chirality_5 6 10 s_st_Chirality_6 ::: } 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 900 2 6 A0A0A0 2 5 -1.349200 1.053100 0.000000 900 2 6 A0A0A0 3 4 -2.063700 -0.184400 0.000000 900 2 6 A0A0A0 4 5 -0.830600 1.036600 0.000000 900 2 6 A0A0A0 5 4 -1.349200 -0.596900 0.000000 900 2 6 A0A0A0 6 5 -0.150000 -1.053100 0.000000 900 2 6 A0A0A0 7 4 -0.634800 -0.184400 0.000000 900 2 6 A0A0A0 8 5 0.079700 -0.596900 0.000000 900 2 6 A0A0A0 9 26 -0.634800 0.640600 0.000000 900 43 7 5757FF 10 4 0.079700 1.053100 0.000000 900 2 6 A0A0A0 11 4 0.794200 0.640600 0.000000 900 2 6 A0A0A0 12 27 1.578800 0.895500 0.000000 900 43 7 5757FF 13 5 2.063700 0.228100 0.000000 900 2 6 A0A0A0 14 5 1.578800 -0.439300 0.000000 900 2 6 A0A0A0 15 3 0.794200 -0.184400 0.000000 900 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_st_Chirality_1 s_st_Chirality_2 s_st_Chirality_3 s_st_Chirality_4 s_st_Chirality_5 s_m_subgroup_title s_m_subgroupid b_m_subgroup_collapsed i_m_ct_format ::: temps.sdf 60 temps.8 /Users/nicola/schrodinger/coordgen_standalone templates.mae 60 4_S_16_5_3 7_R_8_10_6 11_R_10_12_16 15_R_16_14_1 16_R_9_11_15_4 templates->templates->templates templates->templates1->templates11 0 2 m_depend[5] { # 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 3 10 s_st_Chirality_3 4 10 s_st_Chirality_4 5 10 s_st_Chirality_5 ::: } 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 900 2 6 A0A0A0 2 5 1.624500 -0.949300 0.000000 900 2 6 A0A0A0 3 5 0.910000 -1.361800 0.000000 900 2 6 A0A0A0 4 4 0.195500 -0.949300 0.000000 900 2 6 A0A0A0 5 5 -0.394700 -1.525700 0.000000 900 2 6 A0A0A0 6 5 -1.212000 -1.413200 0.000000 900 2 6 A0A0A0 7 4 -1.624500 -0.698700 0.000000 900 2 6 A0A0A0 8 16 -0.930100 -0.961700 0.000000 900 70 8 FF2F2F 9 16 -0.222000 -0.738200 0.000000 900 70 8 FF2F2F 10 16 -1.313300 0.065300 0.000000 900 70 8 FF2F2F 11 4 -0.518900 0.288200 0.000000 900 2 6 A0A0A0 12 16 -0.518900 1.113200 0.000000 900 70 8 FF2F2F 13 5 0.195500 1.525700 0.000000 900 2 6 A0A0A0 14 5 0.910000 1.113200 0.000000 900 2 6 A0A0A0 15 4 0.910000 0.288200 0.000000 900 2 6 A0A0A0 16 3 0.195500 -0.124300 0.000000 900 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_st_Chirality_1 s_st_Chirality_2 s_st_AtomNumChirality_1 s_m_subgroup_title s_m_subgroupid b_m_subgroup_collapsed i_m_ct_format ::: temps.sdf 61 temps.9 /Users/nicola/schrodinger/coordgen_standalone templates.mae 61 4_S_5_6_3 8_R_5_7_9 5_ANR_1_4_8_11 templates->templates->templates templates->templates1->templates11 0 2 m_depend[3] { # 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 3 10 s_st_AtomNumChirality_1 ::: } 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 900 2 6 A0A0A0 2 5 0.000000 1.207400 0.000000 900 2 6 A0A0A0 3 5 0.784600 0.952500 0.000000 900 2 6 A0A0A0 4 4 0.784600 0.127500 0.000000 900 2 6 A0A0A0 5 3 0.000000 -0.127500 0.000000 900 2 6 A0A0A0 6 7 1.269500 -0.540000 0.000000 900 2 6 A0A0A0 7 7 0.784600 -1.207400 0.000000 900 2 6 A0A0A0 8 4 0.000000 -0.952500 0.000000 900 2 6 A0A0A0 9 5 -0.784600 -1.207400 0.000000 900 2 6 A0A0A0 10 5 -1.269500 -0.540000 0.000000 900 2 6 A0A0A0 11 5 -0.784600 0.127500 0.000000 900 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 ::: "Untitled Document-3" 62 temps2.1 /Users/nicola/schrodinger/coordgen_standalone templates.mae 62 templates->templates->templates templates->templates1->templates11 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 900 2 6 A0A0A0 2 4 -1.981300 0.099500 0.000000 900 2 6 A0A0A0 3 16 -1.241900 -0.266500 0.000000 900 70 8 FF2F2F 4 5 -1.648100 -0.632700 0.000000 900 2 6 A0A0A0 5 5 -1.634800 1.545100 0.000000 900 2 6 A0A0A0 6 5 -0.809800 1.536100 0.000000 900 2 6 A0A0A0 7 5 -0.302500 0.885600 0.000000 900 2 6 A0A0A0 8 3 -0.494800 0.083300 0.000000 900 2 6 A0A0A0 9 5 0.289400 0.262300 0.000000 900 2 6 A0A0A0 10 4 -0.843800 -0.641400 0.000000 900 2 6 A0A0A0 11 5 -0.494800 -1.366100 0.000000 900 2 6 A0A0A0 12 5 0.289400 -1.545100 0.000000 900 2 6 A0A0A0 13 4 0.918300 -1.043600 0.000000 900 2 6 A0A0A0 14 3 0.918300 -0.239200 0.000000 900 2 6 A0A0A0 15 5 1.683300 -1.292200 0.000000 900 2 6 A0A0A0 16 16 2.156100 -0.641400 0.000000 900 70 8 FF2F2F 17 4 1.683300 0.009300 0.000000 900 2 6 A0A0A0 18 5 1.801300 0.825900 0.000000 900 2 6 A0A0A0 19 5 1.041400 1.146900 0.000000 900 2 6 A0A0A0 20 16 0.538300 0.493000 0.000000 900 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 ::: "Untitled Document-3" 63 temps2.2 /Users/nicola/schrodinger/coordgen_standalone templates.mae 63 templates->templates->templates templates->templates1->templates11 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 900 2 6 A0A0A0 2 5 -0.813100 -1.494700 0.000000 900 2 6 A0A0A0 3 4 -1.975300 -0.567800 0.000000 900 2 6 A0A0A0 4 5 -1.190300 -1.293700 0.000000 900 2 6 A0A0A0 5 5 -1.617400 0.175500 0.000000 900 2 6 A0A0A0 6 5 -0.813100 0.359100 0.000000 900 2 6 A0A0A0 7 4 -0.168100 -0.155300 0.000000 900 2 6 A0A0A0 8 3 0.546400 0.257200 0.000000 900 2 6 A0A0A0 9 5 0.888400 -0.258400 0.000000 900 2 6 A0A0A0 10 16 0.888400 -0.877200 0.000000 900 70 8 FF2F2F 11 4 1.260900 -0.155300 0.000000 900 2 6 A0A0A0 12 5 1.260900 -0.980300 0.000000 900 2 6 A0A0A0 13 4 0.546400 -1.392800 0.000000 900 2 6 A0A0A0 14 3 -0.168100 -0.980300 0.000000 900 2 6 A0A0A0 15 5 0.546400 1.082200 0.000000 900 2 6 A0A0A0 16 5 1.260900 1.494700 0.000000 900 2 6 A0A0A0 17 5 1.975300 1.082200 0.000000 900 2 6 A0A0A0 18 5 1.975300 0.257200 0.000000 900 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 ::: "Untitled Document-3" 64 temps2.3 /Users/nicola/schrodinger/coordgen_standalone templates.mae 64 templates->templates->templates templates->templates1->templates11 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 900 2 6 A0A0A0 2 7 -1.786200 1.856200 0.000000 900 2 6 A0A0A0 3 7 -1.786200 1.031200 0.000000 900 2 6 A0A0A0 4 5 -1.071700 0.618700 0.000000 900 2 6 A0A0A0 5 3 -0.357200 1.031200 0.000000 900 2 6 A0A0A0 6 3 -0.357200 1.856200 0.000000 900 2 6 A0A0A0 7 16 0.357200 1.443700 0.000000 900 70 8 FF2F2F 8 3 0.357200 0.618700 0.000000 900 2 6 A0A0A0 9 7 1.071700 1.031200 0.000000 900 2 6 A0A0A0 10 7 1.071700 1.856200 0.000000 900 2 6 A0A0A0 11 5 0.357200 2.268700 0.000000 900 2 6 A0A0A0 12 16 -0.357200 0.206300 0.000000 900 70 8 FF2F2F 13 2 -0.357200 -0.618700 0.000000 900 2 6 A0A0A0 14 2 0.357200 -1.031200 0.000000 900 2 6 A0A0A0 15 2 0.357200 -1.856200 0.000000 900 2 6 A0A0A0 16 7 -0.357200 -2.268700 0.000000 900 2 6 A0A0A0 17 7 -1.071700 -1.856200 0.000000 900 2 6 A0A0A0 18 7 -1.071700 -1.031200 0.000000 900 2 6 A0A0A0 19 7 1.071700 -2.268700 0.000000 900 2 6 A0A0A0 20 7 1.786200 -1.856200 0.000000 900 2 6 A0A0A0 21 7 1.786200 -1.031200 0.000000 900 2 6 A0A0A0 22 2 1.071700 -0.618700 0.000000 900 2 6 A0A0A0 23 16 1.071700 0.206300 0.000000 900 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 65 entry /Users/nicola/schrodinger/coordgen_standalone templates.mae 65 templates->templates->templates templates->templates1->templates11 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 900 2 6 A0A0A0 C1 2 7 -2.013100 0.807700 0.000000 900 2 6 A0A0A0 C2 3 7 -2.013100 2.236300 0.000000 900 2 6 A0A0A0 C3 4 2 -3.250200 2.950600 0.000000 900 2 6 A0A0A0 C4 5 154 -4.487400 2.236300 0.000000 900 20 8 9F5F9F 5 6 25 -4.487400 0.807700 0.000000 900 43 7 5757FF N6 7 5 -2.542900 4.180000 0.000000 900 2 6 A0A0A0 C7 8 5 -2.542900 -1.151500 0.000000 900 2 6 A0A0A0 C8 9 2 1.566300 0.093400 0.000000 900 2 6 A0A0A0 C9 10 25 2.803400 0.807700 0.000000 900 43 7 5757FF N10 11 154 2.803400 2.236300 0.000000 900 20 8 9F5F9F 11 12 2 1.566300 2.950600 0.000000 900 2 6 A0A0A0 C12 13 7 0.329100 2.236300 0.000000 900 2 6 A0A0A0 C13 14 7 0.329100 0.807700 0.000000 900 2 6 A0A0A0 C14 15 5 0.857100 4.180000 0.000000 900 2 6 A0A0A0 C15 16 5 0.857100 -1.151500 0.000000 900 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 ::: "Untitled Document-1" 66 untitled.1 /Users/nicola/schrodinger/coordgen_standalone templates.mae 66 templates->templates->templates templates->templates1->templates11 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 900 2 6 A0A0A0 2 2 1.707000 0.667400 0.000000 900 2 6 A0A0A0 3 2 0.667400 1.707000 0.000000 900 2 6 A0A0A0 4 25 -0.000000 1.222100 0.000000 900 43 7 5757FF 5 2 -0.667400 1.707000 0.000000 900 2 6 A0A0A0 6 7 -0.412500 2.491600 0.000000 900 2 6 A0A0A0 7 7 0.412500 2.491600 0.000000 900 2 6 A0A0A0 8 7 -1.452100 1.452100 0.000000 900 2 6 A0A0A0 9 2 -1.707000 0.667400 0.000000 900 2 6 A0A0A0 10 25 -1.222100 0.000000 0.000000 900 43 7 5757FF 11 2 -1.707000 -0.667400 0.000000 900 2 6 A0A0A0 12 7 -2.491600 -0.412500 0.000000 900 2 6 A0A0A0 13 7 -2.491600 0.412500 0.000000 900 2 6 A0A0A0 14 7 -1.452100 -1.452100 0.000000 900 2 6 A0A0A0 15 2 -0.667400 -1.707000 0.000000 900 2 6 A0A0A0 16 25 -0.000000 -1.222100 0.000000 900 43 7 5757FF 17 161 -0.006300 0.020800 0.000000 900 4 28 1E1EE1 18 2 0.667400 -1.707000 0.000000 900 2 6 A0A0A0 19 7 0.412500 -2.491600 0.000000 900 2 6 A0A0A0 20 7 -0.412500 -2.491600 0.000000 900 2 6 A0A0A0 21 7 1.452100 -1.452100 0.000000 900 2 6 A0A0A0 22 2 1.707000 -0.667400 0.000000 900 2 6 A0A0A0 23 25 1.222100 0.000000 0.000000 900 43 7 5757FF 24 7 2.491600 -0.412500 0.000000 900 2 6 A0A0A0 25 7 2.491600 0.412500 0.000000 900 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 ::: "Untitled Document-1" 67 untitled.2 /Users/nicola/schrodinger/coordgen_standalone templates.mae 67 templates->templates->templates templates->templates1->templates11 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 900 2 6 A0A0A0 2 2 1.707000 0.667400 0.000000 900 2 6 A0A0A0 3 2 0.667400 1.707000 0.000000 900 2 6 A0A0A0 4 25 -0.000000 1.222100 0.000000 900 43 7 5757FF 5 2 -0.667400 1.707000 0.000000 900 2 6 A0A0A0 6 7 -0.412500 2.491600 0.000000 900 2 6 A0A0A0 7 5 0.412500 2.491600 0.000000 900 2 6 A0A0A0 8 7 -1.452100 1.452100 0.000000 900 2 6 A0A0A0 9 2 -1.707000 0.667400 0.000000 900 2 6 A0A0A0 10 25 -1.222100 0.000000 0.000000 900 43 7 5757FF 11 2 -1.707000 -0.667400 0.000000 900 2 6 A0A0A0 12 7 -2.491600 -0.412500 0.000000 900 2 6 A0A0A0 13 7 -2.491600 0.412500 0.000000 900 2 6 A0A0A0 14 7 -1.452100 -1.452100 0.000000 900 2 6 A0A0A0 15 2 -0.667400 -1.707000 0.000000 900 2 6 A0A0A0 16 25 -0.000000 -1.222100 0.000000 900 43 7 5757FF 17 153 -0.006300 0.020800 0.000000 900 4 28 1E1EE1 18 2 0.667400 -1.707000 0.000000 900 2 6 A0A0A0 19 7 0.412500 -2.491600 0.000000 900 2 6 A0A0A0 20 5 -0.412500 -2.491600 0.000000 900 2 6 A0A0A0 21 7 1.452100 -1.452100 0.000000 900 2 6 A0A0A0 22 2 1.707000 -0.667400 0.000000 900 2 6 A0A0A0 23 25 1.222100 0.000000 0.000000 900 43 7 5757FF 24 7 2.491600 -0.412500 0.000000 900 2 6 A0A0A0 25 7 2.491600 0.412500 0.000000 900 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 ::: "Untitled Document-1" 68 untitled.2 /Users/nicola/schrodinger/coordgen_standalone templates.mae 68 templates->templates->templates templates->templates1->templates11 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 900 2 6 A0A0A0 2 2 1.707000 0.667400 0.000000 900 2 6 A0A0A0 3 2 0.667400 1.707000 0.000000 900 2 6 A0A0A0 4 25 -0.000000 1.222100 0.000000 900 43 7 5757FF 5 2 -0.667400 1.707000 0.000000 900 2 6 A0A0A0 6 7 -0.412500 2.491600 0.000000 900 2 6 A0A0A0 7 5 0.412500 2.491600 0.000000 900 2 6 A0A0A0 8 7 -1.452100 1.452100 0.000000 900 2 6 A0A0A0 9 2 -1.707000 0.667400 0.000000 900 2 6 A0A0A0 10 29 -1.222100 0.000000 0.000000 900 43 7 5757FF 11 2 -1.707000 -0.667400 0.000000 900 2 6 A0A0A0 12 7 -2.491600 -0.412500 0.000000 900 2 6 A0A0A0 13 7 -2.491600 0.412500 0.000000 900 2 6 A0A0A0 14 7 -1.452100 -1.452100 0.000000 900 2 6 A0A0A0 15 2 -0.667400 -1.707000 0.000000 900 2 6 A0A0A0 16 25 -0.000000 -1.222100 0.000000 900 43 7 5757FF 17 2 0.667400 -1.707000 0.000000 900 2 6 A0A0A0 18 7 0.412500 -2.491600 0.000000 900 2 6 A0A0A0 19 5 -0.412500 -2.491600 0.000000 900 2 6 A0A0A0 20 7 1.452100 -1.452100 0.000000 900 2 6 A0A0A0 21 2 1.707000 -0.667400 0.000000 900 2 6 A0A0A0 22 29 1.222100 0.000000 0.000000 900 43 7 5757FF 23 7 2.491600 -0.412500 0.000000 900 2 6 A0A0A0 24 7 2.491600 0.412500 0.000000 900 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 ::: newTemps.sdf 69 newTemps.1 /Users/nicola/schrodinger/coordgen_standalone templates.mae 69 templates->templates->templates templates->templates1->templates11 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 900 43 7 5757FF 2 27 0.204600 1.031200 0.000000 900 43 7 5757FF 3 27 1.633600 1.031200 0.000000 900 43 7 5757FF 4 4 1.633600 0.206200 0.000000 900 2 6 A0A0A0 5 5 1.938800 -0.442800 0.000000 900 2 6 A0A0A0 6 5 1.388800 -0.965300 0.000000 900 2 6 A0A0A0 7 5 0.481300 -0.552800 0.000000 900 2 6 A0A0A0 8 4 0.919100 -0.206200 0.000000 900 2 6 A0A0A0 9 3 0.204600 0.206200 0.000000 900 2 6 A0A0A0 10 5 0.919100 -1.031200 0.000000 900 2 6 A0A0A0 11 5 0.204600 -1.443800 0.000000 900 2 6 A0A0A0 12 3 -0.509800 -1.031200 0.000000 900 2 6 A0A0A0 13 4 -0.509800 -0.206200 0.000000 900 2 6 A0A0A0 14 5 -1.224300 0.206200 0.000000 900 2 6 A0A0A0 15 4 -1.938800 -0.206200 0.000000 900 2 6 A0A0A0 16 5 -1.663200 -0.760300 0.000000 900 2 6 A0A0A0 17 5 -1.127400 -1.069600 0.000000 900 2 6 A0A0A0 18 27 -1.938800 -1.031200 0.000000 900 43 7 5757FF 19 27 -1.224300 -1.443800 0.000000 900 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_st_Chirality_1 s_m_subgroup_title s_m_subgroupid b_m_subgroup_collapsed i_m_ct_format ::: newTemps.sdf 70 newTemps.2 /Users/nicola/schrodinger/coordgen_standalone templates.mae 70 16_S_17_20_15 templates->templates->templates templates->templates1->templates11 0 2 m_depend[1] { # First column is dependency index # i_m_depend_dependency s_m_depend_property ::: 1 10 s_st_Chirality_1 ::: } 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 900 2 6 A0A0A0 2 16 0.135700 0.221700 0.000000 900 70 8 FF2F2F 3 5 -0.674300 0.378200 0.000000 900 2 6 A0A0A0 4 5 -1.301600 -0.157600 0.000000 900 2 6 A0A0A0 5 5 -2.029600 0.230700 0.000000 900 2 6 A0A0A0 6 5 -2.729800 -0.205600 0.000000 900 2 6 A0A0A0 7 16 -2.702000 -1.030200 0.000000 900 70 8 FF2F2F 8 5 -1.974100 -1.418400 0.000000 900 2 6 A0A0A0 9 5 -1.273900 -0.982100 0.000000 900 2 6 A0A0A0 10 5 -0.612000 -1.474500 0.000000 900 2 6 A0A0A0 11 5 0.185700 -1.264000 0.000000 900 2 6 A0A0A0 12 16 0.518500 -0.509100 0.000000 900 70 8 FF2F2F 13 4 1.342800 -0.543100 0.000000 900 2 6 A0A0A0 14 5 2.042900 -0.979400 0.000000 900 2 6 A0A0A0 15 5 2.729800 -0.522400 0.000000 900 2 6 A0A0A0 16 4 2.597700 0.292000 0.000000 900 2 6 A0A0A0 17 27 2.717600 1.108200 0.000000 900 43 7 5757FF 18 27 1.978400 1.474500 0.000000 900 43 7 5757FF 19 4 1.401600 0.884700 0.000000 900 2 6 A0A0A0 20 4 1.784300 0.153800 0.000000 900 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 ::: newTemps.sdf 71 newTemps.3 /Users/nicola/schrodinger/coordgen_standalone templates.mae 71 templates->templates->templates templates->templates1->templates11 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 900 2 6 A0A0A0 2 5 1.115600 1.494700 0.000000 900 2 6 A0A0A0 3 5 1.830100 1.082200 0.000000 900 2 6 A0A0A0 4 4 1.830100 0.257200 0.000000 900 2 6 A0A0A0 5 5 2.120600 -0.393500 0.000000 900 2 6 A0A0A0 6 16 0.855600 -0.476000 0.000000 900 70 8 FF2F2F 7 4 1.115600 -0.155300 0.000000 900 2 6 A0A0A0 8 5 1.115600 -0.980300 0.000000 900 2 6 A0A0A0 9 5 0.401100 -1.392800 0.000000 900 2 6 A0A0A0 10 3 0.401100 0.257200 0.000000 900 2 6 A0A0A0 11 4 -0.313300 -0.155300 0.000000 900 2 6 A0A0A0 12 3 -0.313300 -0.980300 0.000000 900 2 6 A0A0A0 13 5 -0.958300 0.359100 0.000000 900 2 6 A0A0A0 14 5 -1.762600 0.175500 0.000000 900 2 6 A0A0A0 15 4 -2.120600 -0.567800 0.000000 900 2 6 A0A0A0 16 5 -1.098400 -0.254400 0.000000 900 2 6 A0A0A0 17 5 -1.762600 -1.311100 0.000000 900 2 6 A0A0A0 18 5 -0.958300 -1.494700 0.000000 900 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 ::: newTemps.sdf 72 newTemps.4 /Users/nicola/schrodinger/coordgen_standalone templates.mae 72 templates->templates->templates templates->templates1->templates11 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 900 2 6 A0A0A0 2 5 1.143200 1.363300 0.000000 900 2 6 A0A0A0 3 5 1.720700 1.060800 0.000000 900 2 6 A0A0A0 4 4 1.590600 0.355300 0.000000 900 2 6 A0A0A0 5 5 2.142600 -0.257800 0.000000 900 2 6 A0A0A0 6 16 1.887700 -1.042400 0.000000 900 70 8 FF2F2F 7 5 1.080700 -1.214000 0.000000 900 2 6 A0A0A0 8 4 0.783600 0.183700 0.000000 900 2 6 A0A0A0 9 5 0.116200 0.668700 0.000000 900 2 6 A0A0A0 10 3 0.528700 -0.600900 0.000000 900 2 6 A0A0A0 11 4 -0.296300 -0.600900 0.000000 900 2 6 A0A0A0 12 3 -0.551300 0.183700 0.000000 900 2 6 A0A0A0 13 5 -0.750800 -1.289400 0.000000 900 2 6 A0A0A0 14 5 -1.572500 -1.363300 0.000000 900 2 6 A0A0A0 15 4 -2.142600 -0.767000 0.000000 900 2 6 A0A0A0 16 5 -1.073600 -0.749200 0.000000 900 2 6 A0A0A0 17 5 -2.031900 0.050500 0.000000 900 2 6 A0A0A0 18 5 -1.323700 0.473600 0.000000 900 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 ::: "Untitled Document-1" 73 newTemp.1 /Users/nicola/schrodinger/coordgen_standalone templates.mae 73 templates->templates->templates templates->templates1->templates11 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 900 2 6 A0A0A0 2 27 -0.412500 1.328100 0.000000 900 43 7 5757FF 3 5 0.412500 1.328100 0.000000 900 2 6 A0A0A0 4 2 0.825000 0.613700 0.000000 900 2 6 A0A0A0 5 7 0.412500 -0.100800 0.000000 900 2 6 A0A0A0 6 2 0.825000 -0.815300 0.000000 900 2 6 A0A0A0 7 7 1.650000 0.613700 0.000000 900 2 6 A0A0A0 8 7 2.062500 -0.100800 0.000000 900 2 6 A0A0A0 9 7 1.650000 -0.815300 0.000000 900 2 6 A0A0A0 10 5 -1.650000 2.042600 0.000000 900 2 6 A0A0A0 11 16 -2.062500 1.328100 0.000000 900 70 8 FF2F2F 12 5 -1.650000 0.613700 0.000000 900 2 6 A0A0A0 13 7 -2.062500 -0.100800 0.000000 900 2 6 A0A0A0 14 7 -1.650000 -0.815300 0.000000 900 2 6 A0A0A0 15 5 -1.779100 -1.630100 0.000000 900 2 6 A0A0A0 16 5 -1.064600 -2.042600 0.000000 900 2 6 A0A0A0 17 27 -0.412500 -1.529700 0.000000 900 43 7 5757FF 18 5 0.412500 -1.529700 0.000000 900 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 ::: "Untitled Document-1" 74 newTemp.2 /Users/nicola/schrodinger/coordgen_standalone templates.mae 74 templates->templates->templates templates->templates1->templates11 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 900 2 6 A0A0A0 2 27 -0.758800 2.261800 0.000000 900 43 7 5757FF 3 5 0.066200 2.261800 0.000000 900 2 6 A0A0A0 4 2 0.478700 1.547400 0.000000 900 2 6 A0A0A0 5 7 0.066200 0.832900 0.000000 900 2 6 A0A0A0 6 2 0.580600 0.187900 0.000000 900 2 6 A0A0A0 7 7 1.298800 1.637000 0.000000 900 2 6 A0A0A0 8 7 1.771300 0.960700 0.000000 900 2 6 A0A0A0 9 7 1.404900 0.221500 0.000000 900 2 6 A0A0A0 10 5 -0.758800 0.832900 0.000000 900 2 6 A0A0A0 11 16 -1.273200 0.187900 0.000000 900 70 8 FF2F2F 12 5 -1.089600 -0.616400 0.000000 900 2 6 A0A0A0 13 7 -1.771300 -1.081200 0.000000 900 2 6 A0A0A0 14 7 -1.709600 -1.903900 0.000000 900 2 6 A0A0A0 15 5 -0.966300 -2.261800 0.000000 900 2 6 A0A0A0 16 5 -0.284700 -1.797100 0.000000 900 2 6 A0A0A0 17 27 -0.346300 -0.974400 0.000000 900 43 7 5757FF 18 5 0.397000 -0.616400 0.000000 900 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 ::: "Untitled Document-1" 75 template.1 /Users/nicola/schrodinger/coordgen_standalone templates.mae 75 templates->templates->templates templates->templates1->templates11 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 900 2 6 A0A0A0 2 5 -0.357200 -1.650000 0.000000 900 2 6 A0A0A0 3 5 0.357200 -2.062500 0.000000 900 2 6 A0A0A0 4 5 1.071700 -1.650000 0.000000 900 2 6 A0A0A0 5 4 1.071700 -0.825000 0.000000 900 2 6 A0A0A0 6 5 0.357200 -0.412500 0.000000 900 2 6 A0A0A0 7 5 0.357200 0.412500 0.000000 900 2 6 A0A0A0 8 5 1.071700 0.825000 0.000000 900 2 6 A0A0A0 9 5 1.786200 -0.412500 0.000000 900 2 6 A0A0A0 10 4 1.786200 0.412500 0.000000 900 2 6 A0A0A0 11 5 2.500600 0.825000 0.000000 900 2 6 A0A0A0 12 5 2.500600 1.650000 0.000000 900 2 6 A0A0A0 13 5 1.786200 2.062500 0.000000 900 2 6 A0A0A0 14 5 1.071700 1.650000 0.000000 900 2 6 A0A0A0 15 5 0.357200 2.062500 0.000000 900 2 6 A0A0A0 16 5 -0.357200 1.650000 0.000000 900 2 6 A0A0A0 17 5 -0.357200 0.825000 0.000000 900 2 6 A0A0A0 18 4 -1.071700 0.412500 0.000000 900 2 6 A0A0A0 19 4 -1.071700 -0.412500 0.000000 900 2 6 A0A0A0 20 5 -1.786200 0.825000 0.000000 900 2 6 A0A0A0 21 5 -2.500600 0.412500 0.000000 900 2 6 A0A0A0 22 5 -2.500600 -0.412500 0.000000 900 2 6 A0A0A0 23 5 -1.786200 -0.825000 0.000000 900 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 ::: "Untitled Document-1" 76 template.2 /Users/nicola/schrodinger/coordgen_standalone templates.mae 76 templates->templates->templates templates->templates1->templates11 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 900 2 6 A0A0A0 2 5 -0.825000 -1.101700 0.000000 900 2 6 A0A0A0 3 5 -0.000000 -1.101700 0.000000 900 2 6 A0A0A0 4 5 0.412500 -1.816100 0.000000 900 2 6 A0A0A0 5 4 1.237500 -1.816100 0.000000 900 2 6 A0A0A0 6 5 1.607800 -2.553300 0.000000 900 2 6 A0A0A0 7 5 2.430800 -2.610800 0.000000 900 2 6 A0A0A0 8 5 2.900100 -1.932300 0.000000 900 2 6 A0A0A0 9 5 1.650000 -1.101700 0.000000 900 2 6 A0A0A0 10 4 2.555900 -1.182600 0.000000 900 2 6 A0A0A0 11 5 2.968400 -0.468100 0.000000 900 2 6 A0A0A0 12 5 2.555900 0.246400 0.000000 900 2 6 A0A0A0 13 5 1.730900 0.246400 0.000000 900 2 6 A0A0A0 14 5 1.318400 0.960800 0.000000 900 2 6 A0A0A0 15 5 0.603900 1.373300 0.000000 900 2 6 A0A0A0 16 5 0.603900 2.198300 0.000000 900 2 6 A0A0A0 17 5 -0.110500 2.610800 0.000000 900 2 6 A0A0A0 18 5 -0.825000 2.198300 0.000000 900 2 6 A0A0A0 19 5 -0.825000 1.373300 0.000000 900 2 6 A0A0A0 20 4 -1.539500 0.960800 0.000000 900 2 6 A0A0A0 21 4 -1.539500 0.135800 0.000000 900 2 6 A0A0A0 22 5 -2.253900 1.373300 0.000000 900 2 6 A0A0A0 23 5 -2.968400 0.960800 0.000000 900 2 6 A0A0A0 24 5 -2.968400 0.135800 0.000000 900 2 6 A0A0A0 25 5 -2.253900 -0.276700 0.000000 900 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 ::: "Untitled Document-1" 77 template.3 /Users/nicola/schrodinger/coordgen_standalone templates.mae 77 templates->templates->templates templates->templates1->templates11 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 900 2 6 A0A0A0 2 5 -1.071700 -1.031300 0.000000 900 2 6 A0A0A0 3 5 -0.357200 -1.443800 0.000000 900 2 6 A0A0A0 4 5 0.357200 -1.031300 0.000000 900 2 6 A0A0A0 5 4 1.071700 -1.443800 0.000000 900 2 6 A0A0A0 6 5 1.071700 -2.268800 0.000000 900 2 6 A0A0A0 7 5 1.786200 -2.681200 0.000000 900 2 6 A0A0A0 8 5 2.500600 -2.268800 0.000000 900 2 6 A0A0A0 9 5 1.786200 -1.031300 0.000000 900 2 6 A0A0A0 10 4 2.500600 -1.443800 0.000000 900 2 6 A0A0A0 11 5 3.215100 -1.031300 0.000000 900 2 6 A0A0A0 12 5 3.215100 -0.206300 0.000000 900 2 6 A0A0A0 13 5 2.500600 0.206200 0.000000 900 2 6 A0A0A0 14 5 2.500600 1.031200 0.000000 900 2 6 A0A0A0 15 5 1.786200 1.443700 0.000000 900 2 6 A0A0A0 16 5 1.786200 2.268700 0.000000 900 2 6 A0A0A0 17 5 1.071700 2.681200 0.000000 900 2 6 A0A0A0 18 7 0.357200 2.268700 0.000000 900 2 6 A0A0A0 19 7 0.357200 1.443700 0.000000 900 2 6 A0A0A0 20 5 -0.357200 1.031200 0.000000 900 2 6 A0A0A0 21 5 -1.071700 1.443700 0.000000 900 2 6 A0A0A0 22 4 -1.786200 1.031200 0.000000 900 2 6 A0A0A0 23 4 -1.786200 0.206200 0.000000 900 2 6 A0A0A0 24 5 -2.500600 1.443700 0.000000 900 2 6 A0A0A0 25 5 -3.215100 1.031200 0.000000 900 2 6 A0A0A0 26 5 -3.215100 0.206200 0.000000 900 2 6 A0A0A0 27 5 -2.500600 -0.206300 0.000000 900 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 ::: "Untitled Document-1" 78 template.4 /Users/nicola/schrodinger/coordgen_standalone templates.mae 78 templates->templates->templates templates->templates1->templates11 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 900 2 6 A0A0A0 2 5 -0.550400 -0.708200 0.000000 900 2 6 A0A0A0 3 5 0.274600 -0.708200 0.000000 900 2 6 A0A0A0 4 5 0.687100 -1.422600 0.000000 900 2 6 A0A0A0 5 4 1.512100 -1.422600 0.000000 900 2 6 A0A0A0 6 5 1.924600 -2.137100 0.000000 900 2 6 A0A0A0 7 5 2.749600 -2.137100 0.000000 900 2 6 A0A0A0 8 5 3.162100 -1.422600 0.000000 900 2 6 A0A0A0 9 5 1.924600 -0.708200 0.000000 900 2 6 A0A0A0 10 4 2.749600 -0.708200 0.000000 900 2 6 A0A0A0 11 5 3.162100 0.006300 0.000000 900 2 6 A0A0A0 12 5 2.749600 0.708200 0.000000 900 2 6 A0A0A0 13 5 1.924600 0.708200 0.000000 900 2 6 A0A0A0 14 5 1.512100 1.422600 0.000000 900 2 6 A0A0A0 15 5 0.687100 1.422600 0.000000 900 2 6 A0A0A0 16 5 0.274600 2.137100 0.000000 900 2 6 A0A0A0 17 5 -0.550400 2.137100 0.000000 900 2 6 A0A0A0 18 5 -0.962900 1.422600 0.000000 900 2 6 A0A0A0 19 4 -1.733100 1.127000 0.000000 900 2 6 A0A0A0 20 4 -1.733100 0.302000 0.000000 900 2 6 A0A0A0 21 5 -2.447600 1.539500 0.000000 900 2 6 A0A0A0 22 5 -3.162100 1.127000 0.000000 900 2 6 A0A0A0 23 5 -3.162100 0.302000 0.000000 900 2 6 A0A0A0 24 5 -2.447600 -0.110500 0.000000 900 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 79 cubane.1 /Users/nicola/schrodinger/coordgen_standalone templates.mae 79 templates->templates 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 900 2 6 A0A0A0 2 4 -1.763400 1.898200 0.000000 900 2 6 A0A0A0 3 4 -0.938400 1.898200 0.000000 900 2 6 A0A0A0 4 4 -0.938400 2.723200 0.000000 900 2 6 A0A0A0 5 4 -2.114500 1.508300 0.000000 900 2 6 A0A0A0 6 4 -1.289500 1.508300 0.000000 900 2 6 A0A0A0 7 4 -2.114500 2.333300 0.000000 900 2 6 A0A0A0 8 4 -1.289500 2.333300 0.000000 900 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 80 template.1 /Users/nicola/schrodinger/coordgen_standalone templates.mae 80 templates templates 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 900 2 6 A0A0A0 "" 2 27 -2.522500 0.077700 0.000000 900 43 7 5757FF "N2" 3 5 -2.522500 -0.747400 0.000000 900 2 6 A0A0A0 "" 4 4 -1.808000 -1.159800 0.000000 900 2 6 A0A0A0 "" 5 5 -1.093500 -0.747400 0.000000 900 2 6 A0A0A0 "" 6 27 -1.093500 0.077700 0.000000 900 43 7 5757FF "N6" 7 5 -1.507100 -0.112700 0.000000 900 2 6 A0A0A0 "" 8 5 -2.042000 -0.579300 0.000000 900 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 ::: } } coordgenlibs-1.3/test/000077500000000000000000000000001351170412600150065ustar00rootroot00000000000000coordgenlibs-1.3/test/CMakeLists.txt000066400000000000000000000001401351170412600175410ustar00rootroot00000000000000# Use the example executable as a test add_test(example ${CMAKE_BINARY_DIR}/example_dir/example)coordgenlibs-1.3/xcshareddata/000077500000000000000000000000001351170412600164625ustar00rootroot00000000000000coordgenlibs-1.3/xcshareddata/xcschemes/000077500000000000000000000000001351170412600204445ustar00rootroot00000000000000coordgenlibs-1.3/xcshareddata/xcschemes/coordgen_standalone.xcscheme000066400000000000000000000100131351170412600261700ustar00rootroot00000000000000