#include <openbabel/babelconfig.h>
#include <openbabel/obmolecformat.h>
#include <openbabel/mol.h>
#include <openbabel/atom.h>
#include <openbabel/bond.h>
#include <openbabel/obiter.h>
#include <openbabel/elements.h>
#include <openbabel/generic.h>
#include <cstdlib>
using namespace std;
namespace OpenBabel
{
class FHIaimsFormat : public OBMoleculeFormat
{
public:
FHIaimsFormat()
{
OBConversion::RegisterFormat("fhiaims",this);
}
virtual const char* Description() {
return
"FHIaims XYZ format\n"
"Read Options e.g. -as\n"
" s Output single bonds only\n"
" b Disable bonding entirely\n\n";
};
virtual const char* SpecificationURL()
{return "http://www.fhi-berlin.mpg.de/th/aims/";};
virtual unsigned int Flags()
{
return READONEONLY | WRITEONEONLY;
};
virtual bool ReadMolecule(OBBase* pOb, OBConversion* pConv);
virtual bool WriteMolecule(OBBase* pOb, OBConversion* pConv);
};
FHIaimsFormat theFHIaimsFormat;
bool FHIaimsFormat::ReadMolecule(OBBase* pOb, OBConversion* pConv)
{
OBMol* pmol = pOb->CastAndClear<OBMol>();
if (pmol == nullptr)
return false;
istream &ifs = *pConv->GetInStream();
OBMol &mol = *pmol;
const char* title = pConv->GetTitle();
char buffer[BUFF_SIZE];
string str;
double x,y,z;
OBAtom *atom;
vector<string> vs;
vector<vector3> lattice;
mol.BeginModify();
while (ifs.getline(buffer,BUFF_SIZE)) {
if (buffer[0] == '#')
continue;
if (strstr(buffer, "atom") != nullptr) {
tokenize(vs,buffer);
if (vs.size() < 5)
continue; atom = mol.NewAtom();
x = atof((char*)vs[1].c_str());
y = atof((char*)vs[2].c_str());
z = atof((char*)vs[3].c_str());
atom->SetVector(x,y,z);
int atomicNum = OBElements::GetAtomicNum(vs[4].c_str());
atom->SetAtomicNum(atomicNum);
} else if (strstr(buffer, "lattice_vector") != nullptr) {
tokenize(vs,buffer);
if (vs.size() < 4)
continue;
x = atof((char*)vs[1].c_str());
y = atof((char*)vs[2].c_str());
z = atof((char*)vs[3].c_str());
lattice.push_back(vector3(x, y, z));
}
}
if (!pConv->IsOption("b",OBConversion::INOPTIONS))
mol.ConnectTheDots();
if (!pConv->IsOption("s",OBConversion::INOPTIONS) && !pConv->IsOption("b",OBConversion::INOPTIONS))
mol.PerceiveBondOrders();
std::streampos ipos;
do
{
ipos = ifs.tellg();
ifs.getline(buffer,BUFF_SIZE);
}
while(strlen(buffer) == 0 && !ifs.eof() );
ifs.seekg(ipos);
mol.EndModify();
if (lattice.size() == 3) {
OBUnitCell *uc = new OBUnitCell;
uc->SetOrigin(fileformatInput);
uc->SetData(lattice[0], lattice[1], lattice[2]);
mol.SetData(uc);
}
mol.SetTitle(title);
return(true);
}
bool FHIaimsFormat::WriteMolecule(OBBase* pOb, OBConversion* pConv)
{
OBMol* pmol = dynamic_cast<OBMol*>(pOb);
if (pmol == nullptr)
return false;
ostream &ofs = *pConv->GetOutStream();
OBMol &mol = *pmol;
char buffer[BUFF_SIZE];
ofs << "#\n";
ofs << "# " << mol.GetTitle() << '\n';
ofs << "# Generated by Open Babel " << BABEL_VERSION << '\n';
ofs << "#\n";
FOR_ATOMS_OF_MOL(atom, mol) {
snprintf(buffer, BUFF_SIZE,
"atom %15.5f%15.5f%15.5f %s",
atom->GetX(),
atom->GetY(),
atom->GetZ(),
OBElements::GetSymbol(atom->GetAtomicNum()));
ofs << buffer << '\n';
}
if (mol.HasData(OBGenericDataType::UnitCell)) {
OBUnitCell *uc = (OBUnitCell*)mol.GetData(OBGenericDataType::UnitCell);
ofs << "#\n";
ofs << "# unit cell\n";
ofs << "#\n";
vector<vector3> v = uc->GetCellVectors();
for (unsigned int i = 0; i < v.size(); ++i) {
snprintf(buffer, BUFF_SIZE,
"lattice_vector %15.5f%15.5f%15.5f\n", v[i].x(), v[i].y(), v[i].z());
ofs << buffer;
}
}
return(true);
}
}