Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add some features for Organometallic molecules #2616

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,4 @@ install

# editors
.vscode
.vs
3 changes: 3 additions & 0 deletions data/superatom.txt
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ NMe MeN NC
SMe MeS SC
OMe MeO OC
COO- -OOC C(=O)[O-]
Ph Ph c1ccccc1
CO CO C#O
CO CO O#C
## Only entries above this line are used to *generate* aliases.
Ph Ph c1ccccc1
OR RO O*
Expand Down
15 changes: 15 additions & 0 deletions include/openbabel/atom.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ namespace OpenBabel
#define OB_DONOR_ATOM (1<<7)
//! Atom is an electron acceptor
#define OB_ACCEPTOR_ATOM (1<<8)
//! Atom is part of a Cp ring
#define OB_CP_ATOM (1<<5)

#define SET_OR_UNSET_FLAG(X) \
if (value) SetFlag(X); \
Expand Down Expand Up @@ -166,6 +168,8 @@ namespace OpenBabel
void SetInRing(bool value=true) { SET_OR_UNSET_FLAG(OB_RING_ATOM); }
//! Clear the internal coordinate pointer
void ClearCoordPtr() { _c = nullptr; _cidx=0; }
//! Mark an atom as part of a Cp ring
void SetInCp(bool value = true) { SET_OR_UNSET_FLAG(OB_CP_ATOM); }
//@}

//! \name Methods to retrieve atomic information
Expand Down Expand Up @@ -451,6 +455,17 @@ namespace OpenBabel
bool HasAromaticBond() { return(HasBondOfOrder(5)); }
//! \return Whether this atom matches the first atom in a given SMARTS pattern
bool MatchesSMARTS(const char *);

//! \return Is this a metal commonnly present in organometallic compounds?
bool IsOgmMetal();
//! \return Is atom part of a Cp ring?
bool IsInCp() const;
//! \return Is this atom a Carbon (atomic number == 6)?
bool IsCarbon();
//! Debug method. Displays on basic output simple data to identify the atom
void Show();
//! \return Pair <bool, idx> whether this atom has a bond with a metal atom. If true, also returns metal idx
std::pair<bool, int> HasOgmMetalBond();
//@}

}; // class OBAtom
Expand Down
267 changes: 267 additions & 0 deletions include/openbabel/cpcomplex.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,267 @@
/**********************************************************************
cpcomplex.h - Handle and define Cp (cyclopentadienyl) structures.

Copyright (C) 2023 by Jesus N. M.

This file is part of the Open Babel project.
For more information, see <http://openbabel.org/>

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation version 2 of the License.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
***********************************************************************/

#ifndef OB_CPCOMPLEX_H
#define OB_CPCOMPLEX_H


#include <openbabel/babelconfig.h>

#include <openbabel/mol.h>
#include <openbabel/math/vector3.h>
#include <openbabel/oberror.h>
#include <openbabel/bond.h>



namespace OpenBabel {

#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif

#define deg2rads(deg) ((deg) * M_PI / 180.0)

#define PERSPECTIVE_DEG (75.0)

class BranchBlock {
unsigned int _idx; //!< Block identifier
std::vector<unsigned int> vidx_atoms; //!< Vector idx of the atoms that are part of the block.

public:
//! Default constructor
BranchBlock() {
_idx = 0;
vidx_atoms.clear();
}
//! Destructor
~BranchBlock() {}
//! \return the size of the block (number of atoms in the block)
int Size(){ return(vidx_atoms.empty() ? 0 : vidx_atoms.size()); }
//! \return the block identifier
unsigned int GetIdx() { return(_idx); }
//! Set the block identifier
void SetIdx(int idx) { _idx = idx; }
//! Add an atom's idx to the block
void AddAtom(int i){ vidx_atoms.push_back(i); }
//! \return the idx of the atom at position @p i. Zero based access.
unsigned int GetAtomIdx(int i)
{
if ((unsigned)i < 0 || (unsigned)i >= vidx_atoms.size())
{
obErrorLog.ThrowError(__FUNCTION__, "Requested AtomBlock Out of Range", obDebug);
}

return(vidx_atoms[i]);
}

//! \return Whether the @p idx exists within the atoms already inserted in the block
bool HasAtom(int idx)
{
return ((std::find(vidx_atoms.begin(), vidx_atoms.end(), idx) != vidx_atoms.end())
? true : false);
}

//! \return whether or not it appears to be a Cp block
// Cp will be possible if all the elements in the block are carbons up to that point and have a bond with an ogm metal.
bool IsPossibleCp(OBMol &mol) {
OBAtom* atom;
bool test = false;
for (int i = 0; i < vidx_atoms.size(); i++) {
atom = mol.GetAtom(vidx_atoms[i]);
if (!atom->IsCarbon()) {
return false;
}
else { //Si es un carbono, miramos si tiene algun bond con un Metal ogm
OBBond* bond;
OBBondIterator i;
for (bond = atom->BeginBond(i); bond && !test; bond = atom->NextBond(i)) {
test = bond->GetNbrAtom(atom)->IsOgmMetal();
}
if (!test) //Si no tiene ningun enlace con un ogm metal, devolvemos false
return false;
test = false; //Reseteamos el bool para el siguiente carbono
}
}
return true; //Si llegamos aqui es porque todos los carbonos de la branch tienen al menos 1 enlace con metal
}
};





class CpComplex {
protected:
OBMol* _parent; //!< Parent molecule
unsigned int _idx; //!< Cp identifier within the molecule
unsigned int metal_idx; //!< Atom idx of central metal
std::vector<OBAtom*> _cpAtoms; //!< Atoms for the carbons of the Cp structure
std::vector<unsigned int> idx_carbons; //!< Atom indexes for the carbons of the Cp structure
vector3 center; //!< Cp center, for normal bond connection with metal atom, and aromatic circle position
std::vector<vector3> circlePath; //!< Coordinates for the cp circle (needed to achieve a perspective circunference)
double radius; //!< Cp's aromatic circle radius
unsigned int dummy_idx; //!< Dummy central atom idx


public:
//! Constructor
CpComplex() {
_parent = nullptr;
_idx = 0;
metal_idx = 0;
_cpAtoms.clear();
idx_carbons.clear();
center.Set(0.0, 0.0, 0.0);
radius = 0.0;
dummy_idx = 0;
}


//! \name Methods to modify internal information
//@{
//! Attach an OBMol @p ptr as the parent container for this Cp
void SetParent(OBMol* ptr) { _parent = ptr; }
//! Set the center point of the Cp, sprecified by @p _v. It is equidistant to every carbon in th Cp, as they are disposed in a regular polygon
void SetCentroid(vector3& _v) { center = _v; }
//! Set the center point of the Cp, sprecified by @p v_x, v_y, v_z. It is equidistant to every carbon in th Cp, as they are disposed in a regular polygon
void SetCentroid(const double v_x, const double v_y, const double v_z) { center.Set(v_x, v_y, v_z); }
//! Set the radius of the Cp circle
void SetRadius(double r) { radius = r; }
//! Set the Cp identifier
void SetIdx(int idx) { _idx = idx; }
//! Set the idx of the central metal to which this Cp is attached
void SetMetalIdx(int midx) { metal_idx = midx; }
//! Dummy atom is created to make a perpendicular bond between the metal and the Cp drawing
//! Set the atom idx of the dummy atom created for this Cp
void SetDummyIdx(int idx) { dummy_idx = idx; }
//! Set the point of the Cp circle at index @p i to the coordinates specified by @p _v
void SetCircleCoord(unsigned int i, vector3 _v);
//! Set the point of the Cp circle at index @p i to the coordinates specified by @p _vx, _vy, _vz
void SetCircleCoord(unsigned int i, double _vx, double _vy, double _vz = 0.0);
//@}


//! \name Methods to retrieve information
//@{
//! \return number of carbon atoms in the cp
unsigned int GetCarbonsSize() { return idx_carbons.size(); }
//! \return the molecule which contains this Cp, or NULL if none exists
OBMol* GetParent() { return((OBMol*)_parent); }
//! \return dummy atom idx for this Cp structure, or 0 if none exists
unsigned int GetDummyIdx() const { return((int)dummy_idx); }
//! \return Cp identifier
unsigned int GetIdx() const { return((int)_idx); }
//! \return Central metal identifier
unsigned int GetMetalIdx() const { return((int)metal_idx); }
//! \return the whole contanier of carbon idx
const std::vector<unsigned int>& GetIdxCarbons() { return idx_carbons; }
//! \return the centroid of this Cp in a coordinate vector
vector3& GetCentroid() { return center; };
//! \return the radius of the Cp circle
double GetRadius() { return radius; }
//! \return the coordinate vector for the Cp circle point at position @p i in the container. Zero based access method to vector
vector3 GetCircleCoord(unsigned int i);
//! \return the number of points of the Cp circle
int GetCirclePathSize() const { return circlePath.size(); }
//! \return the whole container of coordinates of the Cp circle
std::vector<vector3> GetCircleCoords() const { return circlePath; }
//! \return carbon idx at position @p i in tha container. Zero based access method to vector
unsigned int GetCarbonIdx(int i) const
{
if ((unsigned)i < 0 || (unsigned)i >= idx_carbons.size())
{
obErrorLog.ThrowError(__FUNCTION__, "Requested CarbonIdx Out of Range", obDebug);
}

return(idx_carbons[i]);
}
//@}


//! \name Addition of data for a Cp
//@{
//! Adds a new atom idx to this Cp
void AddIdxCarbon(int idx) { idx_carbons.push_back(idx); }
//! Adds a new atom to this Cp
void AddCpAtom(OBAtom* atom) { _cpAtoms.push_back(atom); }
//! Adds a new point to the coordinate vector that forms the Cp circle
void AddCircleCoord(vector3 _v) { circlePath.push_back(_v); }
//@}


//! \name Iteration methods
//@{
//! Set the iterator to the beginning of the Cp atom list
//! \return the first atom, or NULL if none exist
OBAtom* CpComplex::BeginAtomCp(OBAtomIterator& i)
{
i = _cpAtoms.begin();
return i == _cpAtoms.end() ? nullptr : (OBAtom*)*i;
}
//! Advance the iterator to the next atom in the Cp
//! \return the next first atom record, or NULL if none exist
OBAtom* CpComplex::NextAtomCp(OBAtomIterator& i)
{
++i;
return i == _cpAtoms.end() ? nullptr : (OBAtom*)*i;
}
//@}


//! \name Other operations
//@{
//! Calculate and set the centroid of this Cp, taking into consideration all atoms stored in _cpAtoms
void FindCentroid();
//! Equivalence operator
bool operator==(const CpComplex* other) const { return (GetIdx() == other->GetIdx()); }
//@}



}; // class CpComplex

}// namespace OpenBabel

#endif // OB_CPCOMPLEX_H

//! \file cpcomplex.h
//! \brief Handle Cp structures























1 change: 1 addition & 0 deletions include/openbabel/depict/asciipainter.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ namespace OpenBabel
void DrawLine(double x1, double y1, double x2, double y2, const std::vector<double> & dashes=std::vector<double>());
void DrawPolygon(const std::vector<std::pair<double,double> > &points);
void DrawCircle(double x, double y, double r);
void DrawPolygonLine(const std::vector<std::pair<double, double> >& points);
void DrawBall(double x, double y, double r, double opacity = 1.0);
void DrawText(double x, double y, const std::string &text);
OBFontMetrics GetFontMetrics(const std::string &text);
Expand Down
1 change: 1 addition & 0 deletions include/openbabel/depict/commandpainter.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ namespace OpenBabel
void DrawLine(double x1, double y1, double x2, double y2, const std::vector<double> & dashes=std::vector<double>());
void DrawPolygon(const std::vector<std::pair<double,double> > &points);
void DrawCircle(double x, double y, double r);
void DrawPolygonLine(const std::vector<std::pair<double, double> >& points);
void DrawBall(double x, double y, double r, double opacity = 1.0);
void DrawText(double x, double y, const std::string &text);
OBFontMetrics GetFontMetrics(const std::string &text);
Expand Down
1 change: 1 addition & 0 deletions include/openbabel/depict/painter.h
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@ namespace OpenBabel
*/
virtual void DrawLine(double x1, double y1, double x2, double y2, const std::vector<double> & dashes=std::vector<double>()) = 0;
virtual void DrawCircle(double x, double y, double r) = 0;
virtual void DrawPolygonLine(const std::vector<std::pair<double, double> >& points) = 0;
/**
* Draw a polygon by connecting consecutive points. The last point will be
* connected to the first one. The lines are drawn using the current pen
Expand Down
4 changes: 4 additions & 0 deletions include/openbabel/depict/svgpainter.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@ namespace OpenBabel
void DrawText(double x, double y, const std::string &text);
OBFontMetrics GetFontMetrics(const std::string &text);
void WriteDefs();

//New
//! Inserts the necessary xml code in the .svg output file to draw a polygon according to the vector of points specified by @p points
void DrawPolygonLine(const std::vector<std::pair<double, double> >& points);
//@}

//! @name CairoPainter specific
Expand Down