/*
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) */