Codebase list schroedinger-coordgenlibs / upstream/1.1 CoordgenFragmentBuilder.h
upstream/1.1

Tree @upstream/1.1 (Download .tar.gz)

CoordgenFragmentBuilder.h @upstream/1.1raw · history · blame

/*
 Contributors: Nicola Zonta
 Copyright Schrodinger, LLC. All rights reserved
 */

#ifndef COORDGEN_FRAGMENT_BUILDER_H
#define COORDGEN_FRAGMENT_BUILDER_H

#include <iostream>
#include <vector>
#include <stack>
#include <queue>
#include <map>
#include <set>

#include "CoordgenMacrocycleBuilder.h"

class sketcherMinimizerAtom;
class sketcherMinimizerBond;
class sketcherMinimizerRing;
class sketcherMinimizerFragment;
class sketcherMinimizerPointF;

/*
 class that handles the creation of 2d coordinates for a molecular fragment
 */
class 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<sketcherMinimizerAtom*> orderRingAtoms(const sketcherMinimizerRing* r);

    /*
     return a vector of atoms so that bound atoms are placed next to each other
     */
    static std::vector<sketcherMinimizerAtom*>
    orderChainOfAtoms(const std::vector<sketcherMinimizerAtom*> atoms,
                      sketcherMinimizerAtom* startAtom);

    /*
     return a list of coordinates representing a regular polygon for the given atoms in a ring
     */
    static std::vector<sketcherMinimizerPointF>
    listOfCoordinatesFromListofRingAtoms(
        const std::vector<sketcherMinimizerAtom*> 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 coordiantes for
     */
    sketcherMinimizerRing* getSharedAtomsWithAlreadyDrawnRing(
        const sketcherMinimizerRing* ring,
        std::vector<sketcherMinimizerAtom*>& 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<sketcherMinimizerRing*> centralRings) const;
    sketcherMinimizerRing* findCentralRingOfSystem(
        const std::vector<sketcherMinimizerRing*> rings) const;

    /*
     find a template to generate coordinates for a ring system
     */
    bool findTemplate(const std::vector<sketcherMinimizerRing*> rings) const;

    /*
     generate coordinates for rings that have been stripped away from the core (see buildRings)
     */
    void generateCoordinatesSideRings(
        std::stack<sketcherMinimizerRing*> 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<sketcherMinimizerRing*> allRings,
                       std::stack<sketcherMinimizerRing*>& sideRings,
                       std::vector<sketcherMinimizerRing*>& 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<sketcherMinimizerAtom*>& atomQueue,
        std::set<sketcherMinimizerAtom*>& isAtomVisited,
        const sketcherMinimizerFragment* fragment) const;

    /*return a list of angles that bonds frmo the given atoms should form*/
    std::vector<float>
    neighborsAnglesAtCenter(const sketcherMinimizerAtom* atom) const;

    /*initialize data to generate coordinates of atoms bound to a non-ring atom*/
    void initializeVariablesForNeighboursCoordinates(
        sketcherMinimizerAtom* atom,
        std::set<sketcherMinimizerAtom*>& isAtomVisited,
        sketcherMinimizerPointF& startCoordinates,
        std::vector<sketcherMinimizerAtom*>& orderedNeighbours,
        std::vector<float>& angles) const;

    /*initialize data to generate coordinates of atoms bound to a ring atom*/
    void initializeVariablesForNeighboursCoordinatesRingAtom(
        const sketcherMinimizerAtom* atom,
        std::set<sketcherMinimizerAtom*>& isAtomVisited,
        sketcherMinimizerPointF& startCoordinates,
        std::vector<sketcherMinimizerAtom*>& orderedNeighbours,
        std::vector<float>& 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<sketcherMinimizerAtom*>& isAtomVisited) const;

    /* assign a score to the possibility of rings to be drawn on a plane*/
    float newScorePlanarity(const std::vector<sketcherMinimizerRing*> rings)
        const;

    /*the macrocycle builder*/
    CoordgenMacrocycleBuilder m_macrocycleBuilder;
};

#endif /* defined(COORDGEN_FRAGMENT_BUILDER_H) */