bool OBChemTsfm::Apply(OBMol &mol) { if (!_bgn.Match(mol)) return(false); mol.BeginModify(); vector<vector<int> > mlist = _bgn.GetUMapList(); obErrorLog.ThrowError(__FUNCTION__, "Ran OpenBabel::OBChemTransform", obAuditMsg); if (!_vchrg.empty()) //modify charges { vector<vector<int> >::iterator i; vector<pair<int,int> >::iterator j; for (i = mlist.begin();i != mlist.end();++i) for (j = _vchrg.begin();j != _vchrg.end();++j) if (j->first < (signed)i->size()) { //goof proofing OBAtom *atom = mol.GetAtom((*i)[j->first]); int old_charge = atom->GetFormalCharge(); atom->SetFormalCharge(j->second); int new_hcount = atom->GetImplicitHCount() + (j->second - old_charge); if (new_hcount < 0) new_hcount = 0; atom->SetImplicitHCount(new_hcount); } } if (!_vbond.empty()) //modify bond orders { OBBond *bond; vector<vector<int> >::iterator i; vector<pair<pair<int,int>,int> >::iterator j; for (i = mlist.begin();i != mlist.end();++i) for (j = _vbond.begin();j != _vbond.end();++j) { bond = mol.GetBond((*i)[j->first.first],(*i)[j->first.second]); if (!bond) { obErrorLog.ThrowError(__FUNCTION__, "unable to find bond", obDebug); continue; } unsigned int old_bond_order = bond->GetBondOrder(); bond->SetBondOrder(j->second); for (int k = 0; k < 2; ++k) { OBAtom* atom = k == 0 ? bond->GetBeginAtom() : bond->GetEndAtom(); int new_hcount = atom->GetImplicitHCount() - (j->second - old_bond_order); if (new_hcount < 0) new_hcount = 0; atom->SetImplicitHCount(new_hcount); } } } if (!_vadel.empty() || !_vele.empty()) //delete atoms and change elements { vector<int>::iterator j; vector<vector<int> >::iterator i; if (!_vele.empty()) { vector<pair<int,int> >::iterator k; for (i = mlist.begin();i != mlist.end();++i) for (k = _vele.begin();k != _vele.end();++k) mol.GetAtom((*i)[k->first])->SetAtomicNum(k->second); } //make sure same atom isn't deleted twice vector<bool> vda; vector<OBAtom*> vdel; vda.resize(mol.NumAtoms()+1,false); for (i = mlist.begin();i != mlist.end();++i) for (j = _vadel.begin();j != _vadel.end();++j) if (!vda[(*i)[*j]]) { vda[(*i)[*j]] = true; vdel.push_back(mol.GetAtom((*i)[*j])); } vector<OBAtom*>::iterator k; for (k = vdel.begin();k != vdel.end();++k) mol.DeleteAtom((OBAtom*)*k); } mol.EndModify(); return(true); }
int mol(int argc, char* argv[]) { int defaultchoice = 1; int choice = defaultchoice; if (argc > 1) { if(sscanf(argv[1], "%d", &choice) != 1) { printf("Couldn't parse that input as a number\n"); return -1; } } // Define location of file formats for testing #ifdef FORMATDIR char env[BUFF_SIZE]; snprintf(env, BUFF_SIZE, "BABEL_LIBDIR=%s", FORMATDIR); putenv(env); #endif cout << "# Unit tests for OBMol \n"; cout << "ok 1\n"; // for loading tests OBMol emptyMol, testMol1; cout << "ok 2\n"; // ctor works testMol1.ReserveAtoms(-1); testMol1.ReserveAtoms(0); testMol1.ReserveAtoms(2); cout << "ok 3\n"; // atom component tests if (testMol1.NumAtoms() == 0) { cout << "ok 4\n"; } else { cout << "not ok 4\n"; } testMol1.NewAtom(); if (testMol1.NumAtoms() == 1) { cout << "ok 5\n"; } else { cout << "not ok 5\n"; } testMol1.NewAtom(); testMol1.AddBond(1, 2, 1); if (testMol1.NumBonds() == 1) { cout << "ok 6\n"; } else { cout << "not ok 6\n"; } testMol1.Clear(); if (testMol1.NumAtoms() == 0) { cout << "ok 7\n"; } else { cout << "not ok 7\n"; } ifstream ifs1(kd3file.c_str()); if (!ifs1) { cout << "Bail out! Cannot read input file!" << endl; return(-1); } OBConversion conv(&ifs1, &cout); OBFormat* pFormat; pFormat = conv.FindFormat("XYZ"); if ( pFormat == NULL ) { cout << "Bail out! Cannot read file format!" << endl; return(-1); } if (! conv.SetInAndOutFormats(pFormat, pFormat)) { cout << "Bail out! File format isn't loaded" << endl; return (-1); } OBMol testMol2D, testMol3D; if (conv.Read(&testMol3D)) cout << "ok 8\n"; else cout << "not ok 8\n"; testMol3D.Center(); // test bond insertion (PR#1665649) OBMol doubleBondMol; OBAtom *a1, *a2; OBBond *b; doubleBondMol.BeginModify(); a1 = doubleBondMol.NewAtom(); a1->SetVector(0.0, 0.0, 0.0); a1->SetAtomicNum(6); a2 = doubleBondMol.NewAtom(); a2->SetVector(1.6, 0.0, 0.0); a2->SetAtomicNum(6); b = doubleBondMol.NewBond(); b->SetBegin(a1); b->SetEnd(a2); a1->AddBond(b); a2->AddBond(b); doubleBondMol.EndModify(); cout << "ok 9" << endl; // test AddHydrogens OBMol testMolH; testMolH.BeginModify(); OBAtom *testAtom = testMolH.NewAtom(); testAtom->SetVector(0.5f, 0.5f, 0.5f); testAtom->SetAtomicNum(6); testAtom->SetImplicitHCount(4); testMolH.EndModify(); testMolH.AddHydrogens(); if (testMolH.NumAtoms() == 5) { cout << "ok 10" << endl; } else { cout << "not ok 10" << endl; } // test AddHydrogens (pr #1665519) OBMol testMolH2; OBAtom *testAtom2 = testMolH2.NewAtom(); testAtom2->SetVector(0.5f, 0.5f, 0.5f); testAtom2->SetAtomicNum(6); testAtom2->SetImplicitHCount(4); testMolH2.AddHydrogens(); if (testMolH2.NumAtoms() == 5) { cout << "ok 11" << endl; } else { cout << "not ok 11 # hydrogen additions" << endl; } // Attempt to write an empty InChI (PR#2864334) pFormat = conv.FindFormat("InChI"); if ( pFormat != NULL && conv.SetOutFormat(pFormat)) { if (conv.Write(&emptyMol)) cout << "ok 12" << endl; else cout << "not ok 12 # failed empty InChI" << endl; } OBMol testMolFormula; string formula("C6"); testMolFormula.SetFormula(formula); if ( testMolFormula.GetFormula() == formula ) { cout << "ok 13" << endl; } else { cout << "not ok 13 # SetFormula "<< endl; } // Reset the formula to test for a double delete error testMolFormula.SetFormula(formula); // Test molecular formulas with large atomic numbers OBMol testLgAtNo; testLgAtNo.BeginModify(); OBAtom *lgAtom = testLgAtNo.NewAtom(); lgAtom->SetAtomicNum(118); // Undefined atomic numbers should be ignored with an obWarning instead of segfault lgAtom = testLgAtNo.NewAtom(); lgAtom->SetAtomicNum(200); lgAtom = testLgAtNo.NewAtom(); lgAtom->SetAtomicNum(1); lgAtom->SetIsotope(2); testLgAtNo.EndModify(); if ( testLgAtNo.GetFormula() == "DOg" ) { cout << "ok 14" << endl; } else { cout << "not ok 14" << endl; } double dihedral = CalcTorsionAngle(vector3(-1., -1., 0.), vector3(-1., 0., 0.), vector3( 1., 0., 0.), vector3( 1., 1., 0.)); double dihedral_error = fabs(dihedral) - 180.0; if (fabs(dihedral_error) < 0.001) { std::cout << "ok 15 " << dihedral_error << std::endl; } else { std::cout << "not ok 15 # CalcTorsionAngle " << dihedral << "!= 180.0" << std::endl; } cout << "1..15\n"; // total number of tests for Perl's "prove" tool return(0); }