Example #1
0
  bool QEqCharges::ComputeCharges(OBMol &mol)
  {

     ///////////////////////////////////////////////////////////////////////////////
    //Some OpenBabel bookkeeping that I copied from the Gasteiger scheme
    mol.SetPartialChargesPerceived();

    OBPairData *dp = new OBPairData;
    dp->SetAttribute("PartialCharges");
    dp->SetValue("QEq");
    dp->SetOrigin(perceived);
    mol.SetData(dp);


    ///////////////////////////////////////////////////////////////////////////////
    //Read in atomic information from OpenBabel molecule and parameterize

    //Read in total number of atoms
    int i, N = mol.NumAtoms();

    Hardness = MatrixXd::Zero(N+1, N+1);
    Voltage = VectorXd::Zero(N+1);
    Electronegativity = VectorXd::Zero(N);
    VectorXd BasisSet = VectorXd::Zero(N);

    Vector3d Parameters;

    FOR_ATOMS_OF_MOL(atom, mol)
    {
       	Parameters = GetParameters(atom->GetAtomicNum(), atom->GetFormalCharge());
	i = atom->GetIdx() - 1;

	if (Parameters[0] == 0.)
        {
		stringstream msg;
		msg << "Some QEq Parameters not found!" << endl
	            << "Parameters not found for atom no. " << i+1 << endl
		    << "Atom will be ignored in the charge computation.";
		obErrorLog.ThrowError(__FUNCTION__, msg.str(), obError);
	}

	Electronegativity[i] = Parameters[0];
	Hardness(i,i) = Parameters[1];
	BasisSet[i] = Parameters[2];
    }
Example #2
0
/**
@since version 2.3
Adds an OBPairData object to each atom and bond in a substructure.
The substructure's atoms are specified in an input parameter, a
vector of atom indx; the bonds are those in the molecule that join
these atoms. The attribute and value of the OBPairObject (the same
for all the added objects) are specified as parameters.
**/
bool AddDataToSubstruct(OBMol* pmol,
        const std::vector<int>& atomIdxs,
        const std::string& attribute,
        const std::string& value)
{
  //Add data to atoms
  for(unsigned int j=0; j<atomIdxs.size(); ++j)
  {
    OBAtom* pAtom = pmol->GetAtom(atomIdxs[j]);
    if(!pAtom)
      continue;
    OBPairData* dp = new OBPairData;
    dp->SetAttribute(attribute);
    dp->SetValue(value);
    pAtom->SetData(dp);
  }

  OBBond* pBond;
  vector<OBBond*>::iterator i;
  for(pBond = pmol->BeginBond(i); pBond; pBond = pmol->NextBond(i))
  {
    //Add data to bond if it joins two atoms in list
    if(count(atomIdxs.begin(), atomIdxs.end(), pBond->GetBeginAtomIdx())
        && count(atomIdxs.begin(), atomIdxs.end(), pBond->GetEndAtomIdx()))
    {
      OBPairData* dp = new OBPairData;
      dp->SetAttribute(attribute);
      dp->SetValue(value);
      pBond->SetData(dp);
    }
  }
  return true;
}
Example #3
0
  unsigned int GetAtomSymClass(OBAtom *atom)
  {
    OBPairData *pd = dynamic_cast<OBPairData*>(atom->GetParent()->GetData("OpenBabel Symmetry Classes"));
    if (pd) {

      cout << "same? = " << pd->GetValue() << endl;

      istringstream iss(pd->GetValue());
      std::vector<unsigned int> symmetry_classes;
      copy(istream_iterator<unsigned int>(iss),
           istream_iterator<unsigned int>(),
           back_inserter<vector<unsigned int> >(symmetry_classes));
      // Now find the number of unique elements
      vector<unsigned int> copy_sym = symmetry_classes;
      sort(copy_sym.begin(), copy_sym.end());
      vector<unsigned int>::iterator end_pos = unique(copy_sym.begin(), copy_sym.end()); // Requires sorted elements
      int nclasses = end_pos - copy_sym.begin();

      cout << "sym_class[" << atom->GetIndex() << "] = " << symmetry_classes.at(atom->GetIndex()) << endl;
      return symmetry_classes.at(atom->GetIndex());
    }

    return 99;
  }
Example #4
0
  //! \return whether partial charges were successfully assigned to this molecule
  bool EQEqCharges::ComputeCharges(OBMol &mol)
  {
    int i, j, a, c, N = mol.NumAtoms();
    double cellVolume;
    VectorXf chi(N), J(N), b(N), x(N);
    MatrixXf J_ij(N, N), A(N, N);
    OBUnitCell *obuc;
    matrix3x3 unitcell, fourier;
    vector3 dx;
    int numNeighbors[3];
    OBAtom *atom;

    // If parameters have not yet been loaded, do that
    if (!_paramFileLoaded)
    {
      if (ParseParamFile())
      {
        _paramFileLoaded = true;
      } else
      {
        return false;
      }
    }

    // Calculate atomic properties based around their ionic charge
    for (i = 0; i < N; i++)
    {
      atom = mol.GetAtom(i + 1);
      a = atom->GetAtomicNum();
      c = _chargeCenter[a];

      // Fail if ionization data is missing for any atom in the molecule
      if (_ionizations[a][c + 1] == -1 || _ionizations[a][c] == -1 || a > TABLE_OF_ELEMENTS_SIZE)
      {
        obErrorLog.ThrowError(__FUNCTION__, "Insufficient ionization data for atoms in the given molecule. Update `data/eqeqIonizations.txt` with missing information and re-run this function.", obError);
        return false;
      }

      J(i) = _ionizations[a][c + 1] - _ionizations[a][c];
      chi(i) = 0.5 * (_ionizations[a][c + 1] + _ionizations[a][c]) - (a == 1? 0 : c * J(i));
    }

    // If a unit cell is defined, use the periodic Ewald calculation
    if (mol.HasData(OBGenericDataType::UnitCell))
    {
      // Get unit cell and calculate its Fourier transform + volume
      obuc = (OBUnitCell *) mol.GetData(OBGenericDataType::UnitCell);
      unitcell = obuc->GetCellMatrix();
      fourier = (2 * PI * unitcell.inverse()).transpose();
      cellVolume = obuc->GetCellVolume();

      // Get the number of radial unit cells to use in x, y, and z
      numNeighbors[0] = int(ceil(minCellLength / (2.0 * (obuc->GetA())))) - 1;
      numNeighbors[1] = int(ceil(minCellLength / (2.0 * (obuc->GetB())))) - 1;
      numNeighbors[2] = int(ceil(minCellLength / (2.0 * (obuc->GetC())))) - 1;

      for (i = 0; i < N; i++)
      {
        atom = mol.GetAtom(i + 1);
        for (j = 0; j < N; j++)
        {
          dx = atom->GetVector() - (mol.GetAtom(j + 1))->GetVector();
          J_ij(i, j) = GetPeriodicEwaldJij(J(i), J(j), dx, (i == j), unitcell, fourier, cellVolume, numNeighbors);
        }
      }
    // If no unit cell, use the simplified nonperiodic calculation
    } else
    {
      for (i = 0; i < N; i++)
      {
        atom = mol.GetAtom(i + 1);
        for (j = 0; j < N; j++)
        {
          J_ij(i, j) = GetNonperiodicJij(J(i), J(j), atom->GetDistance(j + 1), (i == j));
        }
        return false;
      }
    }

    // Formulate problem as A x = b, where x is the calculated partial charges
    // First equation is a simple overall balance: sum(Q) = 0
    A.row(0) = VectorXf::Ones(N);
    b(0) = 0;

    // Remaining equations are based off of the fact that, at equilibrium, the
    // energy of the system changes equally for a change in any charge:
    //     dE/dQ_1 = dE/dQ_2 = ... = dE/dQ_N
    A.block(1, 0, N - 1, N) = J_ij.block(0, 0, N - 1, N) - J_ij.block(1, 0, N - 1, N);
    b.tail(N - 1) = chi.tail(N - 1) - chi.head(N - 1);

    // The solution is a list of charges in the system
    x = A.colPivHouseholderQr().solve(b);

    // Now we are done calculating, pass all this back to OpenBabel molecule
    mol.SetPartialChargesPerceived();
    OBPairData *dp = new OBPairData;
    dp->SetAttribute("PartialCharges");
    dp->SetValue("EQEq");
    dp->SetOrigin(perceived);
    mol.SetData(dp);

    m_partialCharges.clear();
    m_partialCharges.reserve(N);
    m_formalCharges.clear();
    m_formalCharges.reserve(N);

    for (i = 0; i < N; i ++)
    {
      atom = mol.GetAtom(i + 1);
      atom->SetPartialCharge(x(i));
      m_partialCharges.push_back(x(i));
      m_formalCharges.push_back(atom->GetFormalCharge());
    }

    obErrorLog.ThrowError(__FUNCTION__, "EQEq charges successfully assigned.", obInfo);
    return true;
  }
Example #5
0
bool TinkerFormat::WriteMolecule(OBBase* pOb, OBConversion* pConv)
{
    OBMol* pmol = dynamic_cast<OBMol*>(pOb);
    if(pmol==NULL)
        return false;

    //Define some references so we can use the old parameter names
    ostream &ofs = *pConv->GetOutStream();
    OBMol &mol = *pmol;
    bool mmffTypes = pConv->IsOption("m",OBConversion::OUTOPTIONS) != NULL;

    unsigned int i;
    char buffer[BUFF_SIZE];
    OBBond *bond;
    vector<OBBond*>::iterator j;

    // Before we try output of MMFF94 atom types, check if it works
    OBForceField *ff = OpenBabel::OBForceField::FindForceField("MMFF94");
    if (mmffTypes && ff && ff->Setup(mol))
      mmffTypes = ff->GetAtomTypes(mol);
    else
      mmffTypes = false; // either the force field isn't available, or it doesn't work

    if (!mmffTypes)
      snprintf(buffer, BUFF_SIZE, "%6d %-20s   MM2 parameters\n",mol.NumAtoms(),mol.GetTitle());
    else
      snprintf(buffer, BUFF_SIZE, "%6d %-20s   MMFF94 parameters\n",mol.NumAtoms(),mol.GetTitle());
    ofs << buffer;

    ttab.SetFromType("INT");

    OBAtom *atom;
    string str,str1;
    for(i = 1;i <= mol.NumAtoms(); i++)
    {
        atom = mol.GetAtom(i);
        str = atom->GetType();
        ttab.SetToType("MM2");
        ttab.Translate(str1,str);

        if (mmffTypes) {
          // Override the MM2 typing
          OBPairData *type = (OpenBabel::OBPairData*)atom->GetData("FFAtomType");
          if (type)
            str1 = type->GetValue().c_str();
        }

        snprintf(buffer, BUFF_SIZE, "%6d %2s  %12.6f%12.6f%12.6f %5d",
                i,
                etab.GetSymbol(atom->GetAtomicNum()),
                atom->GetX(),
                atom->GetY(),
                atom->GetZ(),
                atoi((char*)str1.c_str()));
        ofs << buffer;

        for (bond = atom->BeginBond(j); bond; bond = atom->NextBond(j))
        {
            snprintf(buffer, BUFF_SIZE, "%6d", (bond->GetNbrAtom(atom))->GetIdx());
            ofs << buffer;
        }

        ofs << endl;
    }

    return(true);
}
Example #6
0
  bool PWscfFormat::ReadMolecule(OBBase* pOb, OBConversion* pConv)
  {
    OBMol* pmol = pOb->CastAndClear<OBMol>();
    if(pmol==NULL)
      return false;

    //Define some references so we can use the old parameter names
    istream &ifs = *pConv->GetInStream();

    char buffer[BUFF_SIZE], tag[BUFF_SIZE];
    double x,y,z;
    double alat = 1.0;
    vector<string> vs;
    matrix3x3 ortho;
    int atomicNum;
    OBUnitCell *cell = new OBUnitCell();
    bool hasEnthalpy=false;
    double enthalpy, pv;

    pmol->BeginModify();

    while (ifs.getline(buffer,BUFF_SIZE)) {

      // Older version of pwscf may use this for alat
      if (strstr(buffer, "lattice parameter (a_0)")) {
        tokenize(vs, buffer);
        alat = atof(vs.at(4).c_str());
      }

      // Newer versions will use this for alat instead
      if (strstr(buffer, "lattice parameter (alat)")) {
        tokenize(vs, buffer);
        alat = atof(vs.at(4).c_str());
      }

      // Unit cell info
      // Newer versions will also say "CELL_PARAMETERS" to complain that no
      // units were specified
      if (strstr(buffer, "CELL_PARAMETERS") &&
          !strstr(buffer, "no units specified in CELL_PARAMETERS card")) {
        // Discover units
        double conv = 1.0;
        tokenize(vs, buffer);

        if (strstr(vs[1].c_str(), "alat")) {
          conv = alat * BOHR_TO_ANGSTROM;
        }
        else if (strstr(vs[1].c_str(), "bohr")) {
          conv = BOHR_TO_ANGSTROM;
        }
        // Add others if needed

        double v11, v12, v13,
          v21, v22, v23,
          v31, v32, v33;

        ifs.getline(buffer,BUFF_SIZE); // v1
        tokenize(vs, buffer);
        v11 = atof(vs.at(0).c_str()) * conv;
        v12 = atof(vs.at(1).c_str()) * conv;
        v13 = atof(vs.at(2).c_str()) * conv;

        ifs.getline(buffer,BUFF_SIZE); // v2
        tokenize(vs, buffer);
        v21 = atof(vs.at(0).c_str()) * conv;
        v22 = atof(vs.at(1).c_str()) * conv;
        v23 = atof(vs.at(2).c_str()) * conv;

        ifs.getline(buffer,BUFF_SIZE); // v3
        tokenize(vs, buffer);
        v31 = atof(vs.at(0).c_str()) * conv;
        v32 = atof(vs.at(1).c_str()) * conv;
        v33 = atof(vs.at(2).c_str()) * conv;

        // Build unit cell
        cell->SetData(vector3(v11,v12,v13),
                      vector3(v21,v22,v23),
                      vector3(v31,v32,v33));
      }

      // Unit cell info (for non-variable cell calcs)
      if (strstr(buffer, "crystal axes: (cart. coord. in units of a_0)") ||
          strstr(buffer, "crystal axes: (cart. coord. in units of alat)")) {
        double conv = alat * BOHR_TO_ANGSTROM;
        double v11, v12, v13,
          v21, v22, v23,
          v31, v32, v33;

        ifs.getline(buffer,BUFF_SIZE); // v1
        tokenize(vs, buffer);
        v11 = atof(vs.at(3).c_str()) * conv;
        v12 = atof(vs.at(4).c_str()) * conv;
        v13 = atof(vs.at(5).c_str()) * conv;

        ifs.getline(buffer,BUFF_SIZE); // v2
        tokenize(vs, buffer);
        v21 = atof(vs.at(3).c_str()) * conv;
        v22 = atof(vs.at(4).c_str()) * conv;
        v23 = atof(vs.at(5).c_str()) * conv;

        ifs.getline(buffer,BUFF_SIZE); // v3
        tokenize(vs, buffer);
        v31 = atof(vs.at(3).c_str()) * conv;
        v32 = atof(vs.at(4).c_str()) * conv;
        v33 = atof(vs.at(5).c_str()) * conv;

        // Build unit cell
        cell->SetData(vector3(v11,v12,v13),
                      vector3(v21,v22,v23),
                      vector3(v31,v32,v33));
      }

      // Atoms info
      if (strstr(buffer, "ATOMIC_POSITIONS")) {
        // Clear old atoms from pmol
        vector<OBAtom*> toDelete;
        FOR_ATOMS_OF_MOL(a, *pmol)
          toDelete.push_back(&*a);
        for (size_t i = 0; i < toDelete.size(); i++)
          pmol->DeleteAtom(toDelete.at(i));


        // Discover units
        matrix3x3 conv (1);
        tokenize(vs, buffer);

        if (strstr(vs[1].c_str(), "alat")) {
          conv *= (alat * BOHR_TO_ANGSTROM);
        }
        else if (strstr(vs[1].c_str(), "crystal")) {
          // Set to the zero matrix and test below.
          conv = matrix3x3 (0.0);
        }
        // Add others if needed

        // Load new atoms from molecule
        ifs.getline(buffer,BUFF_SIZE); // First entry
        tokenize(vs, buffer);
        int size = vs.size();
        while (size == 4) {
          atomicNum = OBElements::GetAtomicNum(vs[0].c_str());
          x = atof((char*)vs[1].c_str());
          y = atof((char*)vs[2].c_str());
          z = atof((char*)vs[3].c_str());
          // Add atom
          OBAtom *atom = pmol->NewAtom();
          atom->SetAtomicNum(atomicNum);
          vector3 coords (x,y,z);
          if (conv.determinant() == 0.0) { // Fractional coords
            atom->SetVector(cell->FractionalToCartesian(coords));
          }
          else {
            atom->SetVector(conv * coords);
          }

          // Reset vars
          ifs.getline(buffer,BUFF_SIZE); // First entry
          tokenize(vs, buffer);
          size = vs.size();
        }
      }

      // Free energy
      if (strstr(buffer, "Final energy =")) {
        tokenize(vs, buffer);
        pmol->SetEnergy(atof(vs[3].c_str()) * RYDBERG_TO_KCAL_PER_MOL);
      }

      // H - PV = U energy
      if (strstr(buffer, "!    total energy              =")) {
        tokenize(vs, buffer);
        pmol->SetEnergy(atof(vs[4].c_str()) * RYDBERG_TO_KCAL_PER_MOL);
      }

      // Enthalphy
      if (strstr(buffer, "Final enthalpy =")) {
        tokenize(vs, buffer);

        hasEnthalpy = true;
        enthalpy = atof(vs.at(3).c_str()) * RYDBERG_TO_KCAL_PER_MOL;
        pv = enthalpy - pmol->GetEnergy();
      }
    }

    // set final unit cell
    pmol->SetData(cell);

    // Set enthalpy
    if (hasEnthalpy) {
      OBPairData *enthalpyPD = new OBPairData();
      OBPairData *enthalpyPD_pv = new OBPairData();
      OBPairData *enthalpyPD_eV = new OBPairData();
      OBPairData *enthalpyPD_pv_eV = new OBPairData();
      enthalpyPD->SetAttribute("Enthalpy (kcal/mol)");
      enthalpyPD_pv->SetAttribute("Enthalpy PV term (kcal/mol)");
      enthalpyPD_eV->SetAttribute("Enthalpy (eV)");
      enthalpyPD_pv_eV->SetAttribute("Enthalpy PV term (eV)");
      double en_kcal_per_mole = enthalpy;
      double pv_kcal_per_mole = pv;
      double en_eV = enthalpy / EV_TO_KCAL_PER_MOL;
      double pv_eV = pv / EV_TO_KCAL_PER_MOL;
      snprintf(tag, BUFF_SIZE, "%f", en_kcal_per_mole);
      enthalpyPD->SetValue(tag);
      snprintf(tag, BUFF_SIZE, "%f", pv_kcal_per_mole);
      enthalpyPD_pv->SetValue(tag);
      snprintf(tag, BUFF_SIZE, "%f", en_eV);
      enthalpyPD_eV->SetValue(tag);
      snprintf(tag, BUFF_SIZE, "%f", pv_eV);
      enthalpyPD_pv_eV->SetValue(tag);
      pmol->SetData(enthalpyPD);
      pmol->SetData(enthalpyPD_pv);
      pmol->SetData(enthalpyPD_eV);
      pmol->SetData(enthalpyPD_pv_eV);
    }

    pmol->EndModify();

    return true;
  }
Example #7
0
  bool PDBFormat::WriteMolecule(OBBase* pOb, OBConversion* pConv)
  {
    OBMol* pmol = dynamic_cast<OBMol*>(pOb);
    if(pmol==NULL)
      return false;

    //Define some references so we can use the old parameter names
    ostream &ofs = *pConv->GetOutStream();
    OBMol &mol = *pmol;

    unsigned int i;
    char buffer[BUFF_SIZE];
    char type_name[10], padded_name[10];
    char the_res[10];
    char the_chain = ' ';
    const char *element_name;
    int res_num;
    bool het=true;
    int model_num = 0;
    if (!pConv->IsLast() || pConv->GetOutputIndex() > 1)
      { // More than one molecule record
        model_num = pConv->GetOutputIndex(); // MODEL 1-based index
        snprintf(buffer, BUFF_SIZE, "MODEL %8d", model_num);
        ofs << buffer << endl;
      }

    // write back all fields (REMARKS, HELIX, SHEET, SITE, ...)
    bool compndWritten = false;
    bool authorWritten = false;
    std::vector<OBGenericData*> pairData = mol.GetAllData(OBGenericDataType::PairData);
    for (std::vector<OBGenericData*>::iterator data = pairData.begin(); data != pairData.end(); ++data) {
      OBPairData *pd = static_cast<OBPairData*>(*data);
      string attr = pd->GetAttribute();

      // filter to make sure we are writing pdb fields only
      if (attr != "HEADER" && attr != "OBSLTE" && attr != "TITLE" && attr != "SPLIT" &&
          attr != "CAVEAT" && attr != "COMPND" && attr != "SOURCE" && attr != "KEYWDS" &&
          attr != "EXPDTA" && attr != "NUMMDL" && attr != "MDLTYP" && attr != "AUTHOR" &&
          attr != "REVDAT" && attr != "SPRSDE" && attr != "JRNL" && attr != "REMARK" &&
          attr != "DBREF" && attr != "DBREF1" && attr != "DBREF2" && attr != "SEQADV" &&
          attr != "SEQRES" && attr != "MODRES" && attr != "HET" && attr != "HETNAM" &&
          attr != "HETSYN" && attr != "FORMUL" && attr != "HELIX" && attr != "SHEET" &&
          attr != "SSBOND" && attr != "LINK" && attr != "CISPEP" && attr != "SITE" &&
          attr != "ORIGX1" && attr != "ORIGX2" && attr != "ORIGX3" && attr != "SCALE1" &&
          attr != "SCALE2" && attr != "SCALE3" && attr != "MATRIX1" && attr != "MATRIX2" &&
          attr != "MATRIX3" && attr != "MODEL")
        continue;

      if (attr == "COMPND")
        compndWritten = true;
      if (attr == "AUTHOR")
        authorWritten = true;

      // compute spacing needed. HELIX, SITE, HET, ... are trimmed when reading
      int nSpacing = 6 - attr.size();
      for (int i = 0; i < nSpacing; ++i)
        attr += " ";


      std::string lines = pd->GetValue();
      string::size_type last = 0;
      string::size_type pos = lines.find('\n');
      while (last != string::npos) {
        string line = lines.substr(last, pos - last);
        if (pos == string::npos)
          last = string::npos;
        else
          last = pos + 1;
        pos = lines.find('\n', last);

        ofs << attr << line << endl;
      }
    }

    if (!compndWritten) {
      if (strlen(mol.GetTitle()) > 0)
        snprintf(buffer, BUFF_SIZE, "COMPND    %s ",mol.GetTitle());
      else
        snprintf(buffer, BUFF_SIZE, "COMPND    UNNAMED");
      ofs << buffer << endl;
    }

    if (!authorWritten) {
      snprintf(buffer, BUFF_SIZE, "AUTHOR    GENERATED BY OPEN BABEL %s",BABEL_VERSION);
      ofs << buffer << endl;
    }

    // Write CRYST1 record, containing unit cell parameters, space group
    // and Z value (supposed to be 1)
    if (pmol->HasData(OBGenericDataType::UnitCell))
      {
        OBUnitCell *pUC = (OBUnitCell*)pmol->GetData(OBGenericDataType::UnitCell);
        if(pUC->GetSpaceGroup()){
          string tmpHM=pUC->GetSpaceGroup()->GetHMName();
          // Do we have an extended HM symbol, with origin choice as ":1" or ":2" ? If so, remove it.
          size_t n=tmpHM.find(":");
          if(n!=string::npos) tmpHM=tmpHM.substr(0,n);
          snprintf(buffer, BUFF_SIZE,
                   "CRYST1%9.3f%9.3f%9.3f%7.2f%7.2f%7.2f %-11s 1",
                   pUC->GetA(), pUC->GetB(), pUC->GetC(),
                   pUC->GetAlpha(), pUC->GetBeta(), pUC->GetGamma(),
                   tmpHM.c_str());
        }
        else
          snprintf(buffer, BUFF_SIZE,
                   "CRYST1%9.3f%9.3f%9.3f%7.2f%7.2f%7.2f %-11s 1",
                   pUC->GetA(), pUC->GetB(), pUC->GetC(),
                   pUC->GetAlpha(), pUC->GetBeta(), pUC->GetGamma(),
                   "P1");

        ofs << buffer << endl;
      }

    // before we write any records, we should check to see if any coord < -1000
    // which will cause errors in the formatting

    double minX, minY, minZ;
    minX = minY = minZ = -999.0f;
    FOR_ATOMS_OF_MOL(a, mol)
      {
        if (a->GetX() < minX)
          minX = a->GetX();
        if (a->GetY() < minY)
          minY = a->GetY();
        if (a->GetZ() < minZ)
          minZ = a->GetZ();
      }
    vector3 transV = VZero;
    if (minX < -999.0)
      transV.SetX(-1.0*minX - 900.0);
    if (minY < -999.0)
      transV.SetY(-1.0*minY - 900.0);
    if (minZ < -999.0)
      transV.SetZ(-1.0*minZ - 900.0);

    // if minX, minY, or minZ was never changed, shift will be 0.0f
    // otherwise, move enough so that smallest coord is > -999.0f
    mol.Translate(transV);

    OBAtom *atom;
    OBResidue *res;
    for (i = 1; i <= mol.NumAtoms(); i++)
      {
        atom = mol.GetAtom(i);
        strncpy(type_name, etab.GetSymbol(atom->GetAtomicNum()), sizeof(type_name));
        type_name[sizeof(type_name) - 1] = '\0';

        //two char. elements are on position 13 and 14 one char. start at 14
        if (strlen(type_name) > 1)
          type_name[1] = toupper(type_name[1]);
        else
          {
            char tmp[10];
            strncpy(tmp, type_name, 9); // make sure to null-terminate tmp
            snprintf(type_name, sizeof(type_name), " %-3s", tmp);
          }

        if ( (res = atom->GetResidue()) != 0 )
          {
            het = res->IsHetAtom(atom);
            snprintf(the_res,4,"%s",(char*)res->GetName().c_str());
            the_res[4] = '\0';
            snprintf(type_name,5,"%s",(char*)res->GetAtomID(atom).c_str());
            the_chain = res->GetChain();

            //two char. elements are on position 13 and 14 one char. start at 14
            if (strlen(etab.GetSymbol(atom->GetAtomicNum())) == 1)
              {
                if (strlen(type_name) < 4)
                  {
                    char tmp[10];
                    strncpy(tmp, type_name, 9); // make sure to null-terminate tmp
                    snprintf(padded_name, sizeof(padded_name), " %-3s", tmp);
                    strncpy(type_name,padded_name,4);
                    type_name[4] = '\0';
                  }
                else
                  {
                    /*
                      type_name[4] = type_name[3];
                      type_name[3] = type_name[2];
                      type_name[2] = type_name[1];
                      type_name[1] = type_name[0];
                      type_name[0] = type_name[4];
                    */
                    type_name[4] = '\0';
                  }
              }
            res_num = res->GetNum();
          }
        else
          {
            strcpy(the_res,"UNK");
            the_res[3] = '\0';
            snprintf(padded_name,sizeof(padded_name), "%s",type_name);
            strncpy(type_name,padded_name,4);
            type_name[4] = '\0';
            res_num = 1;
          }

        element_name = etab.GetSymbol(atom->GetAtomicNum());

        int charge = atom->GetFormalCharge();
        char scharge[3] = { ' ', ' ', '\0' };
        if(0 != charge)
          {
            snprintf(scharge, 3, "%+d", charge);
            char tmp = scharge[1];
            scharge[1] = scharge[0];
            scharge[0] = tmp;
          }
        snprintf(buffer, BUFF_SIZE, "%s%5d %-4s %-3s %c%4d    %8.3f%8.3f%8.3f  1.00  0.00          %2s%2s\n",
                 het?"HETATM":"ATOM  ",
                 i,
                 type_name,
                 the_res,
                 the_chain,
                 res_num,
                 atom->GetX(),
                 atom->GetY(),
                 atom->GetZ(),
                 element_name,
                 scharge);
        ofs << buffer;
      }

    OBAtom *nbr;
    vector<OBBond*>::iterator k;
    for (i = 1; i <= mol.NumAtoms(); i ++)
      {
        atom = mol.GetAtom(i);
        if (atom->GetValence() == 0)
          continue; // no need to write a CONECT record -- no bonds

        snprintf(buffer, BUFF_SIZE, "CONECT%5d", i);
        ofs << buffer;
        // Write out up to 4 real bonds per line PR#1711154
        int currentValence = 0;
        for (nbr = atom->BeginNbrAtom(k);nbr;nbr = atom->NextNbrAtom(k))
          {
            snprintf(buffer, BUFF_SIZE, "%5d", nbr->GetIdx());
            ofs << buffer;
            if (++currentValence % 4 == 0) {
              // Add the trailing space to finish this record
              ofs << "                                       \n";
              // write the start of a new CONECT record
              snprintf(buffer, BUFF_SIZE, "CONECT%5d", i);
              ofs << buffer;
            }
          }

        // Add trailing spaces
        int remainingValence = atom->GetValence() % 4;
        for (int count = 0; count < (4 - remainingValence); count++) {
          snprintf(buffer, BUFF_SIZE, "     ");
          ofs << buffer;
        }
        ofs << "                                       \n";
      }

    snprintf(buffer, BUFF_SIZE, "MASTER        0    0    0    0    0    0    0    0 ");
    ofs << buffer;
    snprintf(buffer, BUFF_SIZE, "%4d    0 %4d    0\n",mol.NumAtoms(),mol.NumAtoms());
    ofs << buffer;

    ofs << "END\n";
    if (model_num) {
      ofs << "ENDMDL" << endl;
    }

    return(true);
  }
Example #8
0
bool RXNFormat::ReadMolecule(OBBase* pOb, OBConversion* pConv)
{
    OBMol* pmol = pOb->CastAndClear<OBMol>();
    if (pmol == NULL)
      return false;

    OBFormat* pMolFormat = pConv->FindFormat("MOL");
    if (pMolFormat==NULL)
      return false;

    istream &ifs = *pConv->GetInStream();
    string ln;
    // When MDLFormat reads the last product it may also read and discard
    // the line with $RXN for the next reaction. But it then sets $RXNread option.
    if(pConv->IsOption("$RXNread"))
      pConv->RemoveOption("$RXNread", OBConversion::OUTOPTIONS);
    else
    {
      if (!getline(ifs,ln))
        return(false);
      if(Trim(ln).find("$RXN")!=0)
        return false; //Has to start with $RXN
    }
    if (!getline(ifs,ln))
      return false; //reaction title
    pmol->SetTitle(Trim(ln));

    if (!getline(ifs,ln))
      return false; //creator
    if (!getline(ifs, ln))
      return false; //comment
    // Originally the comment was added to the reaction via:
    //     pmol->SetComment(Trim(ln));

    if (!getline(ifs, ln))
      return false; // num reactants, products, and optionally agents

    unsigned int nReactants = 0, nProducts = 0, nAgents = 0;
    bool ok = ParseComponent(ln.c_str() + 0, &nReactants);
    if (!ok)
      return false;
    ok = ParseComponent(ln.c_str() + 3, &nProducts);
    if (!ok)
      return false;
    if (ln[6] != '\0') { // optional agents
      ok = ParseComponent(ln.c_str() + 6, &nAgents);
      if (!ok)
        return false;
    }

    if(nReactants + nProducts + nAgents)
    {
      //Read the first $MOL. The others are read at the end of the previous MOL
      if(!getline(ifs, ln))
        return false;
      if(Trim(ln).find("$MOL")==string::npos)
        return false;
    }

    OBReactionFacade rxnfacade(pmol);

    // Note: If we supported it, we could read each of the rxn components directly
    // into the returned OBMol instead of having to do a copy. Unfortunately,
    // this isn't possible at the moment (MOL format will need some work first).
    // Here is some example code to do it:
    //
    //unsigned int old_numatoms = 0;
    //unsigned int compid = 1;
    //for (int i = 0; i<nReactants; i++)
    //{
    //  //Read a MOL file	using the same OBConversion object but with a different format
    //  if (!pMolFormat->ReadMolecule(pmol, pConv))
    //    obErrorLog.ThrowError(__FUNCTION__, "Failed to read a reactant", obWarning);
    //  unsigned int numatoms = pmol->NumAtoms();
    //  for (unsigned int idx = old_numatoms + 1; idx <= numatoms; ++idx) {
    //    OBAtom* atom = pmol->GetAtom(idx);
    //    rxnfacade.SetRole(atom, REACTANT);
    //    rxnfacade.SetComponentId(atom, compid);
    //  }
    //  old_numatoms = numatoms;
    //  compid++;
    //}

    const char* type[3] = {"a reactant", "a product", "an agent"};
    OBReactionRole role;
    unsigned int num_components;
    for(unsigned int N=0; N<3; N++) {
      switch(N) {
      case 0:
        role = REACTANT;
        num_components = nReactants;
        break;
      case 1:
        role = PRODUCT;
        num_components = nProducts;
        break;
      case 2:
        role = AGENT;
        num_components = nAgents;
        break;
      }
      for (int i=0; i<num_components; i++)
      {
        //Read a MOL file	using the same OBConversion object but with a different format
        OBMol mol;
        if (!pMolFormat->ReadMolecule(&mol, pConv)) {
          std::string error = "Failed to read ";
          error += type[N];
          obErrorLog.ThrowError(__FUNCTION__, error, obWarning);
          continue;
        }
        if (mol.NumAtoms() == 0) {
          OBAtom* dummy = mol.NewAtom(); // Treat the empty OBMol as having a single dummy atom
          OBPairData *pd = new OBPairData();
          pd->SetAttribute("rxndummy");
          pd->SetValue("");
          pd->SetOrigin(fileformatInput);
          dummy->SetData(pd);
        }

        rxnfacade.AddComponent(&mol, role);
      }
    }

    pmol->SetIsReaction();
    return true;
}
Example #9
0
int main(int argc,char *argv[])
{
  // turn off slow sync with C-style output (we don't use it anyway).
  std::ios::sync_with_stdio(false);

  OBConversion conv;
  OBFormat *inFormat, *canFormat;
  OBMol mol;
  ifstream ifs;
  vector<OBMol> fragments;
  unsigned int fragmentCount = 0; // track how many in library -- give a running count
  map<string, int> index; // index of cansmi
  string currentCAN;
  unsigned int size;
  OBAtom *atom;
  OBBond *bond;
  bool nonRingAtoms, nonRingBonds;
  char buffer[BUFF_SIZE];

  canFormat = conv.FindFormat("can");
  conv.SetOutFormat(canFormat);

  if (argc < 2)
    {
      cout << "Usage: obfragment <file>" << endl;
      return(-1);
    }

  for (int i = 1; i < argc; i++) {
    cerr << " Reading file " << argv[i] << endl;

    inFormat = conv.FormatFromExt(argv[i]);
    if(inFormat==NULL || !conv.SetInFormat(inFormat))
      {
        cerr << " Cannot read file format for " << argv[i] << endl;
        continue; // try next file
      }
    
    ifs.open(argv[i]);
    
    if (!ifs)
      {
        cerr << "Cannot read input file: " << argv[i] << endl;
        continue;
      }
    
    
    while(ifs.peek() != EOF && ifs.good())
      {
        conv.Read(&mol, &ifs);
        if (!mol.Has3D()) continue; // invalid coordinates!
        mol.DeleteHydrogens(); // remove these before we do anything else
        
        do {
          nonRingAtoms = false;
          size = mol.NumAtoms();
          for (unsigned int i = 1; i <= size; ++i)
            {
              atom = mol.GetAtom(i);
              if (!atom->IsInRing()) {
                mol.DeleteAtom(atom);
                nonRingAtoms = true;
                break; // don't know how many atoms there are
              } 
              // Previously, we changed atoms to carbon here.
              // Now we perform this alchemy in terms of string-rewriting
              // once the canonical SMILES is generated
            }
        } while (nonRingAtoms);
        
        if (mol.NumAtoms() < 3)
          continue;
        
        if (mol.NumBonds() == 0)
          continue;
        
        do {
          nonRingBonds = false;
          size = mol.NumBonds();
          for (unsigned int i = 0; i < size; ++i)
            {
              bond = mol.GetBond(i);
              if (!bond->IsInRing()) {
                mol.DeleteBond(bond);
                nonRingBonds = true;
                break; // don't know how many bonds there are
              }
            }        
        } while (nonRingBonds);

        fragments = mol.Separate();
        for (unsigned int i = 0; i < fragments.size(); ++i)
          {
            if (fragments[i].NumAtoms() < 3) // too small to care
              continue;
              
            currentCAN = conv.WriteString(&fragments[i], true);
            currentCAN = RewriteSMILES(currentCAN); // change elements to "a/A" for compression
            if (index.find(currentCAN) != index.end()) { // already got this
              index[currentCAN] += 1; // add to the count for bookkeeping
              continue;
            }

            index[currentCAN] = 1; // don't ever write this ring fragment again

            // OK, now retrieve the canonical ordering for the fragment
            vector<string> canonical_order;
            if (fragments[i].HasData("Canonical Atom Order")) {
              OBPairData *data = (OBPairData*)fragments[i].GetData("Canonical Atom Order");
              tokenize(canonical_order, data->GetValue().c_str());
            }

            // Write out an XYZ-style file with the CANSMI as the title
            cout << fragments[i].NumAtoms() << '\n';
            cout << currentCAN << '\n'; // endl causes a flush

            vector<string>::iterator can_iter;
            unsigned int order;
            OBAtom *atom;

            fragments[i].Center();
            fragments[i].ToInertialFrame();

            for (unsigned int index = 0; index < canonical_order.size(); 
                 ++index) {
              order = atoi(canonical_order[index].c_str());
              atom = fragments[i].GetAtom(order);
              
              snprintf(buffer, BUFF_SIZE, "C%8.3f%8.3f%8.3f\n",
                       atom->x(), atom->y(), atom->z());
              cout << buffer;
            }

          }
        fragments.clear();
        if (index.size() > fragmentCount) {
          fragmentCount = index.size();
          cerr << " Fragments: " << fragmentCount << endl;
        }

      } // while reading molecules (in this file)
    ifs.close();
    ifs.clear();
  } // while reading files

  // loop through the map and output frequencies
  map<string, int>::const_iterator indexItr;
  for (indexItr = index.begin(); indexItr != index.end(); ++indexItr) {
    cerr << (*indexItr).second << " INDEX " << (*indexItr).first << "\n";
  }
    
  return(0);
}
Example #10
0
bool OpAlign::Do(OBBase* pOb, const char* OptionText, OpMap* pmap, OBConversion* pConv)
{
  OBMol* pmol = dynamic_cast<OBMol*>(pOb);
  if(!pmol)
    return false;

  map<string,string>::const_iterator itr;

  // Is there an -s option?
  if(pConv->IsFirstInput())
  {
    _pOpIsoM = NULL; //assume no -s option
    itr = pmap->find("s");
    if(itr!=pmap->end())
    {
      //There is an -s option; check it is ok
      _pOpIsoM = static_cast<OpNewS*>(OBOp::FindType("s"));
      _stext = itr->second; //get its parameter(s)
      if(!_pOpIsoM || _stext.empty())
      {
        obErrorLog.ThrowError(__FUNCTION__,
        "No parameter on -s option, or its OBOp version is not loaded", obError);
        pConv->SetOneObjectOnly(); //to finish
        return false;
      }
    }
  }

  // If the output format is a 2D depiction format, then we should align
  // on the 2D coordinates and not the 3D coordinates (if present). This
  //means we need to generate the 2D coordinates at this point.
  if(pmol->GetDimension()==3 && (pConv->GetOutFormat()->Flags() & DEPICTION2D))
  {
    OBOp* pgen = OBOp::FindType("gen2D");
    if(pgen)
      pgen->Do(pmol);
  }

  // All molecules must have coordinates, so add them if 0D
  // They may be added again later when gen2D or gen3D is called, but they will be the same.
  // It would be better if this op was called after them, which would happen
  // if its name was alphabetically after "gen" (and before "s").
  if(pmol->GetDimension()==0)
  {
    //Will the coordinates be 2D or 3D?
    itr = pmap->find("gen3D");
    OBOp* pgen = (itr==pmap->end()) ? OBOp::FindType("gen2D") : OBOp::FindType("gen3D");
    if(pgen)
      pgen->Do(pmol);
  }

  //Do the alignment in 2D if the output format is svg, png etc. and there is no -xn option
  if(pmol->GetDimension()==3 && pConv && !pConv->IsOption("n"))
  {
    OBFormat* pOutFormat = pConv->GetOutFormat();
    if(pOutFormat->Flags() & DEPICTION2D)
    {
      OBOp* pgen = OBOp::FindType("gen2D");
      if(pgen)
        pgen->Do(pmol);
    }
  }

  if(pConv->IsFirstInput() || _refMol.NumAtoms()==0)
  {
    _refvec.clear();
    // Reference molecule is basically the first molecule
    _refMol = *pmol;
    if(!_pOpIsoM)
     //no -s option. Use a molecule reference.
     _align.SetRefMol(_refMol);
    else
    {
      //If there is a -s option, reference molecule has only those atoms that are matched
      //Call the -s option from here
      bool ret = _pOpIsoM->Do(pmol, _stext.c_str(), pmap, pConv);
      // Get the atoms that were matched
      vector<int> ats = _pOpIsoM->GetMatchAtoms();
      if(!ats.empty())
      {
        // Make a vector of the matching atom coordinates...
        for(vector<int>::iterator iter=ats.begin(); iter!=ats.end(); ++iter)
          _refvec.push_back((pmol->GetAtom(*iter))->GetVector());
        // ...and use a vector reference
        _align.SetRef(_refvec);
      }
      // Stop -s option being called normally, although it will still be called once
      //  in the DoOps loop already started for the current (first) molecule.
      pConv->RemoveOption("s",OBConversion::GENOPTIONS);
      if(!ret)
      {
        // the first molecule did not match the -s option so a reference molecule
        // could not be made. Keep trying.
        _refMol.Clear();
        //obErrorLog.ThrowError(__FUNCTION__, "The first molecule did not match the -s option\n"
        //  "so the reference structure was not derived from it", obWarning, onceOnly);
        return false; //not matched
      }
    }
  }

  //All molecules
  if(pmol->GetDimension()!= _refMol.GetDimension())
  {
    stringstream ss;
    ss << "The molecule" << pmol->GetTitle()
       << " does not have the same dimensions as the reference molecule "
       << _refMol.GetTitle() << " and is ignored.";
       obErrorLog.ThrowError(__FUNCTION__, ss.str().c_str(), obError);
    return false;
  }

  if(_pOpIsoM) //Using -s option
  {
    //Ignore mol if it does not pass -s option
    if(!_pOpIsoM->Do(pmol, "", pmap, pConv)) // "" means will use existing parameters
      return false;

    // Get the atoms equivalent to those in ref molecule
    vector<int> ats = _pOpIsoM->GetMatchAtoms();

    // Make a vector of their coordinates and get the centroid
    vector<vector3> vec;
    vector3 centroid;
    for(vector<int>::iterator iter=ats.begin(); iter!=ats.end(); ++iter) {
      vector3 v = pmol->GetAtom(*iter)->GetVector();
      centroid += v;
      vec.push_back(v);
    }
    centroid /= vec.size();

    // Do the alignment
    _align.SetTarget(vec);
    if(!_align.Align())
      return false;

    // Get the centroid of the reference atoms
    vector3 ref_centroid;
    for(vector<vector3>::iterator iter=_refvec.begin(); iter!=_refvec.end(); ++iter)
      ref_centroid += *iter;
    ref_centroid /= _refvec.size();

    //subtract the centroid, rotate the target molecule, then add the centroid
    matrix3x3 rotmatrix = _align.GetRotMatrix();
    for (unsigned int i = 1; i <= pmol->NumAtoms(); ++i)
    {
      vector3 tmpvec = pmol->GetAtom(i)->GetVector();
      tmpvec -= centroid;
      tmpvec *= rotmatrix; //apply the rotation
      tmpvec += ref_centroid;
      pmol->GetAtom(i)->SetVector(tmpvec);
    }
  }
  else //Not using -s option)
  {
    _align.SetTargetMol(*pmol);
    if(!_align.Align())
      return false;
    _align.UpdateCoords(pmol);
  }

  //Save rmsd as a property
  OBPairData* dp = new OBPairData;
  dp->SetAttribute("rmsd");
  double val = _align.GetRMSD();
  if(val<1e-12)
    val = 0.0;
  dp->SetValue(toString(val));
  dp->SetOrigin(local);
  pmol->SetData(dp);

  return true;
}
Example #11
0
  bool MOL2Format::WriteMolecule(OBBase* pOb, OBConversion* pConv)
  {
    OBMol* pmol = dynamic_cast<OBMol*>(pOb);
    if(pmol==NULL)
      return false;

    //Define some references so we can use the old parameter names
    ostream &ofs = *pConv->GetOutStream();
    OBMol &mol = *pmol;
    bool ligandsOnly = pConv->IsOption("l", OBConversion::OUTOPTIONS)!=NULL;
 
    //The old code follows....
    string str,str1;
    char buffer[BUFF_SIZE],label[BUFF_SIZE];
    char rnum[BUFF_SIZE],rlabel[BUFF_SIZE];

    ofs << "@<TRIPOS>MOLECULE" << endl;
    str = mol.GetTitle();
    if (str.empty())
      ofs << "*****" << endl;
    else
      ofs << str << endl;

    snprintf(buffer, BUFF_SIZE," %d %d 0 0 0", mol.NumAtoms(),mol.NumBonds());
    ofs << buffer << endl;
    ofs << "SMALL" << endl;

    OBPairData *dp = (OBPairData*)mol.GetData("PartialCharges");
    if (dp != NULL) {
        // Tripos spec says:
        // NO_CHARGES, DEL_RE, GASTEIGER, GAST_HUCK, HUCKEL, PULLMAN, 
        // GAUSS80_CHARGES, AMPAC_CHARGES, MULLIKEN_CHARGES, DICT_ CHARGES,
        // MMFF94_CHARGES, USER_CHARGES
      if (dp->GetValue() == "Mulliken")
        ofs << "MULLIKEN_CHARGES" << endl;
      else // should pick from the Tripos types
        ofs << "GASTEIGER" << endl;
    }
    else { // No idea what these charges are... all our code sets "PartialCharges"
        ofs << "GASTEIGER" << endl;
    }

    ofs << "Energy = " << mol.GetEnergy() << endl;

    if (mol.HasData(OBGenericDataType::CommentData))
      {
        OBCommentData *cd = (OBCommentData*)mol.GetData(OBGenericDataType::CommentData);
        ofs << cd->GetData();
      }

    ofs << endl;
    ofs << "@<TRIPOS>ATOM" << endl;

    OBAtom *atom;
    OBResidue *res;

    vector<OBAtom*>::iterator i;
    vector<int> labelcount;
    labelcount.resize( etab.GetNumberOfElements() );

    ttab.SetFromType("INT");
    ttab.SetToType("SYB");

    for (atom = mol.BeginAtom(i);atom;atom = mol.NextAtom(i))
      {

        //
        //  Use sequentially numbered atom names if no residues
        //

        snprintf(label,BUFF_SIZE, "%s%d",
                 etab.GetSymbol(atom->GetAtomicNum()),
                 ++labelcount[atom->GetAtomicNum()]);
        strcpy(rlabel,"<1>");
        strcpy(rnum,"1");

        str = atom->GetType();
        ttab.Translate(str1,str);

        //
        //  Use original atom names if there are residues
        //

        if (!ligandsOnly && (res = atom->GetResidue()) )
          {
            // use original atom names defined by residue
            snprintf(label,BUFF_SIZE,"%s",(char*)res->GetAtomID(atom).c_str());
            // make sure that residue name includes its number
            snprintf(rlabel,BUFF_SIZE,"%s%d",res->GetName().c_str(), res->GetNum());
            snprintf(rnum,BUFF_SIZE,"%d",res->GetNum());
          }

        snprintf(buffer,BUFF_SIZE,"%7d%1s%-6s%12.4f%10.4f%10.4f%1s%-5s%4s%1s %-8s%10.4f",
                 atom->GetIdx(),"",label,
                 atom->GetX(),atom->GetY(),atom->GetZ(),
                 "",str1.c_str(),
                 rnum,"",rlabel,
                 atom->GetPartialCharge());
        ofs << buffer << endl;
      }

    ofs << "@<TRIPOS>BOND" << endl;
    OBBond *bond;
    vector<OBBond*>::iterator j;
    OBSmartsPattern pat;
    string s1, s2;
    for (bond = mol.BeginBond(j);bond;bond = mol.NextBond(j))
      {
        s1 = bond->GetBeginAtom()->GetType();
        s2 = bond->GetEndAtom()->GetType();
        if (bond->IsAromatic() || s1 == "O.co2" || s2 == "O.co2") 
          strcpy(label,"ar");
        else if (bond->IsAmide())
          strcpy(label,"am");
        else
          snprintf(label,BUFF_SIZE,"%d",bond->GetBO());

        snprintf(buffer, BUFF_SIZE,"%6d%6d%6d%3s%2s",
                 bond->GetIdx()+1,bond->GetBeginAtomIdx(),bond->GetEndAtomIdx(),
                 "",label);
        ofs << buffer << endl;
      }
    // NO trailing blank line (PR#1868929).
    //    ofs << endl;

    return(true);
  }
  bool MOL2Format::ReadMolecule(OBBase* pOb, OBConversion* pConv)
  {

    OBMol* pmol = pOb->CastAndClear<OBMol>();
    if(pmol==NULL)
      return false;

    //Define some references so we can use the old parameter names
    istream &ifs = *pConv->GetInStream();
    OBMol &mol = *pmol;

    //Old code follows...
    bool foundAtomLine = false;
    char buffer[BUFF_SIZE];
    char *comment = NULL;
    string str,str1;
    vector<string> vstr;
    int len;

    mol.BeginModify();

    for (;;)
      {
        if (!ifs.getline(buffer,BUFF_SIZE))
          return(false);
        if (EQn(buffer,"@<TRIPOS>MOLECULE",17))
          break;
      }

    // OK, just read MOLECULE line
    int lcount;
    int natoms,nbonds;
    bool hasPartialCharges = true;
    for (lcount=0;;lcount++)
      {
        if (!ifs.getline(buffer,BUFF_SIZE))
          return(false);
        if (EQn(buffer,"@<TRIPOS>ATOM",13))
          {
            foundAtomLine = true;
            break;
          }

        if (lcount == 0)
          {
            tokenize(vstr,buffer);
            if (!vstr.empty())
              mol.SetTitle(buffer);
          }
        else if (lcount == 1)
          sscanf(buffer,"%d%d",&natoms,&nbonds);
        else if (lcount == 3) // charge descriptions
          {
            // Annotate origin of partial charges
            OBPairData *dp = new OBPairData;
            dp->SetAttribute("PartialCharges");
            dp->SetValue(buffer);
            dp->SetOrigin(fileformatInput);
            mol.SetData(dp);

            if (strncasecmp(buffer, "NO_CHARGES", 10) == 0)
              hasPartialCharges = false;
          }
        else if (lcount == 4) //energy (?)
          {
            tokenize(vstr,buffer);
            if (!vstr.empty() && vstr.size() == 3)
              if (vstr[0] == "Energy")
                mol.SetEnergy(atof(vstr[2].c_str()));
          }
        else if (lcount == 5) //comment
          {
            if ( buffer[0] )
              {
                len = (int) strlen(buffer)+1;
                //! @todo allow better multi-line comments
                // which don't allow ill-formed data to consume memory
                // Thanks to Andrew Dalke for the pointer
                if (comment != NULL)
                  delete [] comment;
                comment = new char [len];
                memcpy(comment,buffer,len);
              }
          }
      }

    if (!foundAtomLine)
      {
        mol.EndModify();
        mol.Clear();
        obErrorLog.ThrowError(__FUNCTION__, "Unable to read Mol2 format file. No atoms found.", obWarning);
        return(false);
      }

    mol.ReserveAtoms(natoms);

    int i;
    vector3 v;
    OBAtom atom;
    double x,y,z,pcharge;
    char temp_type[BUFF_SIZE], resname[BUFF_SIZE], atmid[BUFF_SIZE];
    int elemno, resnum = -1;

    ttab.SetFromType("SYB");
    for (i = 0;i < natoms;i++)
      {
        if (!ifs.getline(buffer,BUFF_SIZE))
          return(false);
        sscanf(buffer," %*s %1024s %lf %lf %lf %1024s %d %1024s %lf",
               atmid, &x,&y,&z, temp_type, &resnum, resname, &pcharge);

        atom.SetVector(x, y, z);

        // Handle "CL" and "BR" and other mis-typed atoms
        str = temp_type;
        if (strncmp(temp_type, "CL", 2) == 0) {
          str = "Cl";
        } else  if (strncmp(temp_type,"BR",2) == 0) {
          str = "Br";
        } else if (strncmp(temp_type,"S.o2", 4) == 02) {
          str = "S.O2";
        } else if (strncmp(temp_type,"S.o", 3) == 0) {
          str = "S.O";
        } else if (strncmp(temp_type,"SI", 2) == 0) {
          str = "Si";
        // The following cases are entries which are not in openbabel/data/types.txt
        // and should probably be added there
        } else if (strncmp(temp_type,"S.1", 3) == 0) {
          str = "S.2"; // no idea what the best type might be here
        } else if (strncmp(temp_type,"P.", 2) == 0) {
          str = "P.3";
        } else if (strncasecmp(temp_type,"Ti.", 3) == 0) { // e.g. Ti.th
          str = "Ti";
        } else if (strncasecmp(temp_type,"Ru.", 3) == 0) { // e.g. Ru.oh
          str = "Ru";
        }

        ttab.SetToType("ATN");
        ttab.Translate(str1,str);
        elemno = atoi(str1.c_str());
        ttab.SetToType("IDX");

        // We might have missed some SI or FE type things above, so here's
        // another check
        if( !elemno && isupper(temp_type[1]) )
          {
            temp_type[1] = (char)tolower(temp_type[1]);
            str = temp_type;
            ttab.Translate(str1,str);
            elemno = atoi(str1.c_str());
          }
        // One last check if there isn't a period in the type,
        // it's a malformed atom type, but it may be the element symbol
        // GaussView does this (PR#1739905)
        if ( !elemno ) {
          obErrorLog.ThrowError(__FUNCTION__, "This Mol2 file is non-standard. Cannot interpret atom types correctly, instead attempting to interpret as elements instead.", obWarning);

          string::size_type dotPos = str.find('.');
          if (dotPos == string::npos) {
            elemno = etab.GetAtomicNum(str.c_str());
          }
        }

        atom.SetAtomicNum(elemno);
        ttab.SetToType("INT");
        ttab.Translate(str1,str);
        atom.SetType(str1);
        atom.SetPartialCharge(pcharge);
        if (!mol.AddAtom(atom))
          return(false);
        if (!IsNearZero(pcharge))
          hasPartialCharges = true;

        // Add residue information if it exists
        if (resnum != -1 && resnum != 0 &&
            strlen(resname) != 0 && strncmp(resname,"<1>", 3) != 0)
          {
            OBResidue *res  = (mol.NumResidues() > 0) ?
              mol.GetResidue(mol.NumResidues()-1) : NULL;
            if (res == NULL || res->GetName() != resname ||
                static_cast<int>(res->GetNum()) != resnum)
              {
                vector<OBResidue*>::iterator ri;
                for (res = mol.BeginResidue(ri) ; res ; res = mol.NextResidue(ri))
                  if (res->GetName() == resname &&
                      static_cast<int>(res->GetNum()) == resnum)
                    break;

                if (res == NULL)
                  {
                    res = mol.NewResidue();
                    res->SetName(resname);
                    res->SetNum(resnum);
                  }
              }
            OBAtom *atomPtr = mol.GetAtom(mol.NumAtoms());
            res->AddAtom(atomPtr);
            res->SetAtomID(atomPtr, atmid);
          } // end adding residue info
      }

    for (;;)
      {
        if (!ifs.getline(buffer,BUFF_SIZE))
          return(false);
        str = buffer;
        if (!strncmp(buffer,"@<TRIPOS>BOND",13))
          break;
      }

    int start,end,order;
    for (i = 0; i < nbonds; i++)
      {
        if (!ifs.getline(buffer,BUFF_SIZE))
          return(false);

        sscanf(buffer,"%*d %d %d %1024s",&start,&end,temp_type);
        str = temp_type;
        order = 1;
        if (str == "ar" || str == "AR" || str == "Ar")
          order = 5;
        else if (str == "AM" || str == "am" || str == "Am")
          order = 1;
        else
          order = atoi(str.c_str());

        mol.AddBond(start,end,order);
      }

    // Suggestion by Liu Zhiguo 2008-01-26
    // Mol2 files define atom types -- there is no need to re-perceive
    mol.SetAtomTypesPerceived();
    mol.EndModify();

    //must add generic data after end modify - otherwise it will be blown away
    if (comment)
      {
        OBCommentData *cd = new OBCommentData;
        cd->SetData(comment);
        cd->SetOrigin(fileformatInput);
        mol.SetData(cd);
        delete [] comment;
        comment = NULL;
      }
    if (hasPartialCharges)
      mol.SetPartialChargesPerceived();

    /* Disabled due to PR#3048758 -- seekg is very slow with gzipped mol2
    // continue untill EOF or untill next molecule record
    streampos pos;
    for(;;)
      {
        pos = ifs.tellg();
        if (!ifs.getline(buffer,BUFF_SIZE))
          break;
        if (EQn(buffer,"@<TRIPOS>MOLECULE",17))
          break;
      }

    ifs.seekg(pos); // go back to the end of the molecule
    */
    return(true);
  }
Example #13
0
  bool TinkerFormat::WriteMolecule(OBBase* pOb, OBConversion* pConv)
  {
    OBMol* pmol = dynamic_cast<OBMol*>(pOb);
    if(pmol==NULL)
      return false;

    //Define some references so we can use the old parameter names
    ostream &ofs = *pConv->GetOutStream();
    OBMol &mol = *pmol;
    bool mm2Types = false;
    bool mmffTypes = pConv->IsOption("m",OBConversion::OUTOPTIONS) != NULL;
    bool mm3Types = pConv->IsOption("3",OBConversion::OUTOPTIONS) != NULL;
    bool classTypes = pConv->IsOption("c", OBConversion::OUTOPTIONS) != NULL;

    unsigned int i;
    char buffer[BUFF_SIZE];
    OBBond *bond;
    vector<OBBond*>::iterator j;

    // Before we try output of MMFF94 atom types, check if it works
    OBForceField *ff = OpenBabel::OBForceField::FindForceField("MMFF94");
    if (mmffTypes && ff && ff->Setup(mol))
      mmffTypes = ff->GetAtomTypes(mol);
    else
      mmffTypes = false; // either the force field isn't available, or it doesn't work

    if (!mmffTypes && !mm3Types && !classTypes) {
      snprintf(buffer, BUFF_SIZE, "%6d %-20s   MM2 parameters\n",mol.NumAtoms(),mol.GetTitle());
      mm2Types = true;
    }
    else if (mm3Types)
      snprintf(buffer, BUFF_SIZE, "%6d %-20s   MM3 parameters\n",mol.NumAtoms(),mol.GetTitle());
    else if (classTypes)
      snprintf(buffer, BUFF_SIZE, "%6d %-20s   Custom parameters\n",mol.NumAtoms(),mol.GetTitle());
    else
      snprintf(buffer, BUFF_SIZE, "%6d %-20s   MMFF94 parameters\n",mol.NumAtoms(),mol.GetTitle());
    ofs << buffer;

    ttab.SetFromType("INT");

    OBAtom *atom;
    string str,str1;
    int atomType;
    for(i = 1;i <= mol.NumAtoms(); i++)
      {
        atom = mol.GetAtom(i);
        str = atom->GetType();
        atomType = 0; // Something is very wrong if this doesn't get set below

        if (mm2Types) {
          ttab.SetToType("MM2");
          ttab.Translate(str1,str);
          atomType = atoi((char*)str1.c_str());
        }
        if (mmffTypes) {
          // Override the MM2 typing
          OBPairData *type = (OpenBabel::OBPairData*)atom->GetData("FFAtomType");
          if (type) {
            str1 = type->GetValue().c_str();
            atomType = atoi((char*)str1.c_str());
          }
        }
        if (mm3Types) {
          // convert to integer for MM3 typing
          atomType = SetMM3Type(atom);
        }
        if (classTypes) {
          // Atom classes are set by the user, so use those
          OBGenericData *data = atom->GetData("Atom Class");
          if (data) {
            OBPairInteger* acdata = dynamic_cast<OBPairInteger*>(data); // Could replace with C-style cast if willing to live dangerously
            if (acdata) {
              int ac = acdata->GetGenericValue();
              if (ac >= 0)
                atomType = ac;
            }
          }
        }

        snprintf(buffer, BUFF_SIZE, "%6d %2s  %12.6f%12.6f%12.6f %5d",
                 i,
                 OBElements::GetSymbol(atom->GetAtomicNum()),
                 atom->GetX(),
                 atom->GetY(),
                 atom->GetZ(),
                 atomType);
        ofs << buffer;

        for (bond = atom->BeginBond(j); bond; bond = atom->NextBond(j))
          {
            snprintf(buffer, BUFF_SIZE, "%6d", (bond->GetNbrAtom(atom))->GetIdx());
            ofs << buffer;
          }

        ofs << endl;
      }

    return(true);
  }
Example #14
0
  OBBase* OBMol::DoTransformations(const std::map<std::string, std::string>* pOptions, OBConversion* pConv)
  {
    // Perform any requested transformations
    // on a OBMol
    //The input map has option letters or name as the key and
    //any associated text as the value.
    //For normal(non-filter) transforms:
    // returns a pointer to the OBMol (this) if ok or NULL if not.
    //For filters returns a pointer to the OBMol (this) if there is a  match,
    //and NULL when not and in addition the OBMol object is deleted NULL.

    //This is now a virtual function. The OBBase version just returns the OBMol pointer.
    //This is declared in mol.h

    //The filter options, s and v allow a obgrep facility.
    //Used together they must both be true to allow a molecule through.

    //Parse GeneralOptions
    if(pOptions->empty())
      return this;

    // DoOps calls Do() for each of the plugin options in the map
    // It normally returns true, even if there are no options but
    // can return false if one of the options decides that the
    // molecule should not be output. If it is a filtering op, it
    // should delete the molecule itself (unlike the -s, --filter options,
    // which delete it in this function).
    if(!OBOp::DoOps(this, pOptions, pConv))
      return (OBBase *)NULL;

    bool ret=true;

    map<string,string>::const_iterator itr, itr2;

    if(pOptions->find("b")!=pOptions->end())
      if(!ConvertDativeBonds())
        ret=false;

    if(pOptions->find("d")!=pOptions->end())
      if(!DeleteHydrogens())
        ret=false;

    if(pOptions->find("h")!=pOptions->end())
      if(!AddHydrogens(false, false))
        ret=false;

    if(pOptions->find("r")!=pOptions->end()) {
      StripSalts();
      ret = true;
    }

    itr = pOptions->find("p");
    if(itr!=pOptions->end()) {
      double pH = strtod(itr->second.c_str(), 0);
      if(!AddHydrogens(false, true, pH))
        ret=false;
    }

    if(pOptions->find("c")!=pOptions->end())
      Center();

    itr = pOptions->find("title"); //Replaces title
    if(itr!=pOptions->end())
      SetTitle(itr->second.c_str());

    itr = pOptions->find("addtotitle"); //Appends text to title
    if(itr!=pOptions->end())
      {
        string title(GetTitle());
        title += itr->second;
        SetTitle(title.c_str());
      }

/*    itr = pOptions->find("addformula"); //Appends tab + formula to title
    if(itr!=pOptions->end())
      {
        string title(GetTitle());
        title += '\t' + GetSpacedFormula(1,"");//actually unspaced
        SetTitle(title.c_str());
      }
*/
    //Add an extra property to the molecule.
    //Parameter has atrribute and value separated by a space
    itr = pOptions->find("property");
    if(itr!=pOptions->end())
      {
        string txt(itr->second);
        string::size_type pos = txt.find(' ');
        if(pos==string::npos)
          {
            obErrorLog.ThrowError(__FUNCTION__, "Missing property value", obError);
            ret=false;
          }
        else
          {
            string attr(txt.substr(0,pos)), val(txt.substr(pos+1));
            //Update value if it already exists
            OBPairData* dp = dynamic_cast<OBPairData*>(GetData(attr));
            if(dp) {
              dp->SetValue(val);
              dp->SetOrigin(userInput);
            }
            else {
              // Pair did not exist; make new one
              dp = new OBPairData;
              dp->SetAttribute(attr);
              dp->SetValue(val);
              dp->SetOrigin(userInput);
              SetData(dp);
            }
          }
      }

    itr = pOptions->find("add");  //adds new properties from descriptors in list
    if(itr!=pOptions->end())
      OBDescriptor::AddProperties(this, itr->second);

    itr = pOptions->find("delete"); //deletes the specified properties
    if(itr!=pOptions->end())
      OBDescriptor::DeleteProperties(this, itr->second);

    itr = pOptions->find("append"); //Appends values of descriptors or properties to title
    if(itr!=pOptions->end())
      {
        string title(GetTitle());
        title += OBDescriptor::GetValues(this, itr->second);
        if(ispunct(title[0]))
          title[0]=' ';//a leading punct char is used only as a separator, not at start
        SetTitle(Trim(title).c_str());
      }



      //Filter using OBDescriptor comparison and (older) SMARTS tests
    //Continue only if previous test was true.
    bool fmatch = true;
    itr = pOptions->find("filter");
    if(itr!=pOptions->end())
      {
        std::istringstream optionText(itr->second);
        fmatch = OBDescriptor::FilterCompare(this, optionText, false);
      }

    if(fmatch)
      {
        itr = pOptions->find("v");
        if(itr!=pOptions->end() && !itr->second.empty())
          {
            //inverse match quoted SMARTS string which follows
            OBSmartsPattern sp;
            sp.Init(itr->second);
            fmatch = !sp.Match(*this); //(*pmol) ;
          }
      }
    if(fmatch)
    {
      itr = pOptions->find("s");
      if(itr!=pOptions->end() && !itr->second.empty())
        {
          //SMARTS filter
          //If exactmatch option set (probably in fastsearchformat) the
          //number of atoms in the pattern (passed as a string in the option text)
          //has to be the same as in the molecule.
          itr2 = pOptions->find("exactmatch");
          if(itr2!=pOptions->end() && NumHvyAtoms()!=atoi(itr2->second.c_str()))
            fmatch=false;
          else
            {
              //match quoted SMARTS string which follows
              OBSmartsPattern sp;
                sp.Init(itr->second.c_str());
                fmatch = sp.Match(*this);
            }
        }
    }

    if(!fmatch)
      {
        //filter failed: delete OBMol and return NULL
        delete this;
        return NULL;
      }
    else
      {
        if(ret==false)
          {
            obErrorLog.ThrowError(__FUNCTION__, "Error executing an option", obError);
            delete this; //added 9March2006
            return NULL;
          }
        else
          return this;
      }
  }
Example #15
0
// Reading Gaussian output has been tested for G98 and G03 to some degree
// If you have problems (or examples of older output), please contact
// the [email protected] mailing list and/or post a bug
bool GaussianOutputFormat::ReadMolecule(OBBase* pOb, OBConversion* pConv)
{
    OBMol* pmol = pOb->CastAndClear<OBMol>();
    if(pmol==NULL)
        return false;

    //Define some references so we can use the old parameter names
    istream &ifs = *pConv->GetInStream();
    OBMol &mol = *pmol;
    const char* title = pConv->GetTitle();

    char buffer[BUFF_SIZE];
    string str,str1,str2,thermo_method;
    double x,y,z;
    OBAtom *atom;
    vector<string> vs,vs2;
    int total_charge = 0;
    unsigned int spin_multiplicity = 1;
    bool hasPartialCharges = false;
    string chargeModel; // descriptor for charges (e.g. "Mulliken")

    // Variable for G2/G3/G4 etc. calculations
    double ezpe,Hcorr,Gcorr,E0,CV;
    bool ezpe_set=false,Hcorr_set=false,Gcorr_set=false,E0_set=false,CV_set=false;
    double temperature = 0; /* Kelvin */
    std::vector<double> Scomponents;
    // Electrostatic potential
    OBFreeGrid *esp = NULL;

    // coordinates of all steps
    // Set conformers to all coordinates we adopted
    std::vector<double*> vconf; // index of all frames/conformers
    std::vector<double> coordinates; // coordinates in each frame
    int natoms = 0; // number of atoms -- ensure we don't go to a new job with a different molecule

    // OBConformerData stores information about multiple steps
    // we can change attribute later if needed (e.g., IRC)
    OBConformerData *confData = new OBConformerData();
    confData->SetOrigin(fileformatInput);
    std::vector<unsigned short> confDimensions = confData->GetDimension(); // to be fair, set these all to 3D
    std::vector<double>         confEnergies   = confData->GetEnergies();
    std::vector< std::vector< vector3 > > confForces = confData->GetForces();

    //Vibrational data
    std::vector< std::vector< vector3 > > Lx;
    std::vector<double> Frequencies, Intensities;
    //Rotational data
    std::vector<double> RotConsts(3);
    int RotSymNum=1;
    OBRotationData::RType RotorType = OBRotationData::UNKNOWN;

    // Translation vectors (if present)
    vector3 translationVectors[3];
    int numTranslationVectors = 0;

    //Electronic Excitation data
    std::vector<double> Forces, Wavelengths, EDipole,
        RotatoryStrengthsVelocity, RotatoryStrengthsLength;

    // Orbital data
    std::vector<double> orbitals;
    std::vector<std::string> symmetries;
    int aHOMO, bHOMO, betaStart;
    aHOMO = bHOMO = betaStart = -1;

    int i=0;
    bool no_symmetry=false;
    char coords_type[25];

    //Prescan file to find second instance of "orientation:"
    //This will be the kind of coords used in the chk/fchk file
    //Unless the "nosym" keyword has been requested
    while (ifs.getline(buffer,BUFF_SIZE))
    {
        if (strstr(buffer,"Symmetry turned off by external request.") != NULL)
        {
            // The "nosym" keyword has been requested
            no_symmetry = true;
        }
        if (strstr(buffer,"orientation:") !=NULL)
        {
            i++;
            tokenize (vs, buffer);
            // gotta check what types of orientation are present
            strncpy (coords_type, vs[0].c_str(), 24);
            strcat (coords_type, " orientation:");
        }
        if ((no_symmetry && i==1) || i==2)
            break;
    }
    // Reset end-of-file pointers etc.
    ifs.clear();
    ifs.seekg(0);  //rewind

    mol.BeginModify();
    while (ifs.getline(buffer,BUFF_SIZE))
    {
        if(strstr(buffer, "Entering Gaussian") != NULL)
        {
            //Put some metadata into OBCommentData
            string comment("Gaussian ");

            if(NULL != strchr(buffer,'='))
            {
                comment += strchr(buffer,'=')+2;
                comment += "";
                for(unsigned i=0; i<115 && ifs; ++i)
                {
                    ifs.getline(buffer,BUFF_SIZE);
                    if(strstr(buffer,"Revision") != NULL)
                    {
                        if (buffer[strlen(buffer)-1] == ',')
                        {
                            buffer[strlen(buffer)-1] = '\0';
                        }
                        add_unique_pairdata_to_mol(&mol,"program",buffer,0);
                    }
                    else if(buffer[1]=='#')
                    {
                        //the line describing the method
                        comment += buffer;
                        OBCommentData *cd = new OBCommentData;
                        cd->SetData(comment);
                        cd->SetOrigin(fileformatInput);
                        mol.SetData(cd);

                        tokenize(vs,buffer);
                        if (vs.size() > 1)
                        {
                            char *str = strdup(vs[1].c_str());
                            char *ptr = strchr(str,'/');

                            if (NULL != ptr)
                            {
                                *ptr = ' ';
                                add_unique_pairdata_to_mol(&mol,"basis",ptr,0);
                                *ptr = '\0';
                                add_unique_pairdata_to_mol(&mol,"method",str,0);
                            }
                        }

                        break;
                    }
                }
            }
        }

        else if (strstr(buffer,"Multiplicity") != NULL)
        {
            tokenize(vs, buffer, " \t\n");
            if (vs.size() == 6)
            {
                total_charge = atoi(vs[2].c_str());
                spin_multiplicity = atoi(vs[5].c_str());
            }

            ifs.getline(buffer,BUFF_SIZE);
        }
        else if (strstr(buffer, coords_type) != NULL)
        {
            numTranslationVectors = 0; // ignore old translationVectors
            ifs.getline(buffer,BUFF_SIZE);      // ---------------
            ifs.getline(buffer,BUFF_SIZE);      // column headings
            ifs.getline(buffer,BUFF_SIZE);	// column headings
            ifs.getline(buffer,BUFF_SIZE);	// ---------------
            ifs.getline(buffer,BUFF_SIZE);
            tokenize(vs,buffer);
            while (vs.size()>4)
            {
                int corr = vs.size()==5 ? -1 : 0; //g94; later versions have an extra column
                x = atof((char*)vs[3+corr].c_str());
                y = atof((char*)vs[4+corr].c_str());
                z = atof((char*)vs[5+corr].c_str());
                int atomicNum = atoi((char*)vs[1].c_str());

                if (atomicNum > 0) // translation vectors are "-2"
                {
                    if (natoms == 0) { // first time reading the molecule, create each atom
                        atom = mol.NewAtom();
                        atom->SetAtomicNum(atoi((char*)vs[1].c_str()));
                    }
                    coordinates.push_back(x);
                    coordinates.push_back(y);
                    coordinates.push_back(z);
                }
                else {
                    translationVectors[numTranslationVectors++].Set(x, y, z);
                }

                if (!ifs.getline(buffer,BUFF_SIZE)) {
                    break;
                }
                tokenize(vs,buffer);
            }
            // done with reading atoms
            natoms = mol.NumAtoms();
            if(natoms==0)
                return false;
            // malloc / memcpy
            double *tmpCoords = new double [(natoms)*3];
            memcpy(tmpCoords, &coordinates[0], sizeof(double)*natoms*3);
            vconf.push_back(tmpCoords);
            coordinates.clear();
            confDimensions.push_back(3); // always 3D -- OBConformerData allows mixing 2D and 3D structures
        }
        else if(strstr(buffer,"Dipole moment") != NULL)
        {
            ifs.getline(buffer,BUFF_SIZE); // actual components   X ###  Y #### Z ###
            tokenize(vs,buffer);
            if (vs.size() >= 6)
            {
                OBVectorData *dipoleMoment = new OBVectorData;
                dipoleMoment->SetAttribute("Dipole Moment");
                double x, y, z;
                x = atof(vs[1].c_str());
                y = atof(vs[3].c_str());
                z = atof(vs[5].c_str());
                dipoleMoment->SetData(x, y, z);
                dipoleMoment->SetOrigin(fileformatInput);
                mol.SetData(dipoleMoment);
            }
            if (!ifs.getline(buffer,BUFF_SIZE)) break;
        }
        else if(strstr(buffer,"Traceless Quadrupole moment") != NULL)
        {
            ifs.getline(buffer,BUFF_SIZE); // actual components XX ### YY #### ZZ ###
            tokenize(vs,buffer);
            ifs.getline(buffer,BUFF_SIZE); // actual components XY ### XZ #### YZ ###
            tokenize(vs2,buffer);
            if ((vs.size() >= 6) && (vs2.size() >= 6))
            {
                double Q[3][3];
                OpenBabel::OBMatrixData *quadrupoleMoment = new OpenBabel::OBMatrixData;

                Q[0][0] = atof(vs[1].c_str());
                Q[1][1] = atof(vs[3].c_str());
                Q[2][2] = atof(vs[5].c_str());
                Q[1][0] = Q[0][1] = atof(vs2[1].c_str());
                Q[2][0] = Q[0][2] = atof(vs2[3].c_str());
                Q[2][1] = Q[1][2] = atof(vs2[5].c_str());
                matrix3x3 quad(Q);

                quadrupoleMoment->SetAttribute("Traceless Quadrupole Moment");
                quadrupoleMoment->SetData(quad);
                quadrupoleMoment->SetOrigin(fileformatInput);
                mol.SetData(quadrupoleMoment);
            }
            if (!ifs.getline(buffer,BUFF_SIZE)) break;
        }
        else if(strstr(buffer,"Exact polarizability") != NULL)
        {
            // actual components XX, YX, YY, XZ, YZ, ZZ
            tokenize(vs,buffer);
            if (vs.size() >= 8)
            {
                double Q[3][3];
                OpenBabel::OBMatrixData *pol_tensor = new OpenBabel::OBMatrixData;

                Q[0][0] = atof(vs[2].c_str());
                Q[1][1] = atof(vs[4].c_str());
                Q[2][2] = atof(vs[7].c_str());
                Q[1][0] = Q[0][1] = atof(vs[3].c_str());
                Q[2][0] = Q[0][2] = atof(vs[5].c_str());
                Q[2][1] = Q[1][2] = atof(vs[6].c_str());
                matrix3x3 pol(Q);

                pol_tensor->SetAttribute("Exact polarizability");
                pol_tensor->SetData(pol);
                pol_tensor->SetOrigin(fileformatInput);
                mol.SetData(pol_tensor);
            }
            if (!ifs.getline(buffer,BUFF_SIZE)) break;
        }
        else if(strstr(buffer,"Total atomic charges") != NULL ||
                strstr(buffer,"Mulliken atomic charges") != NULL)
        {
            hasPartialCharges = true;
            chargeModel = "Mulliken";
            ifs.getline(buffer,BUFF_SIZE);	// column headings
            ifs.getline(buffer,BUFF_SIZE);
            tokenize(vs,buffer);
            while (vs.size() >= 3 &&
                    strstr(buffer,"Sum of ") == NULL)
            {
                atom = mol.GetAtom(atoi(vs[0].c_str()));
                if (!atom)
                    break;
                atom->SetPartialCharge(atof(vs[2].c_str()));

                if (!ifs.getline(buffer,BUFF_SIZE)) break;
                tokenize(vs,buffer);
            }
        }
        else if (strstr(buffer, "Atomic Center") != NULL)
        {
            // Data points for ESP calculation
            tokenize(vs,buffer);
            if (NULL == esp)
                esp = new OpenBabel::OBFreeGrid();
            if (vs.size() == 8)
            {
                esp->AddPoint(atof(vs[5].c_str()),atof(vs[6].c_str()),
                              atof(vs[7].c_str()),0);
            }
            else if (vs.size() > 5)
            {
                double x,y,z;
                if (3 == sscanf(buffer+32,"%10lf%10lf%10lf",&x,&y,&z))
                {
                    esp->AddPoint(x,y,z,0);
                }
            }
        }
        else if (strstr(buffer, "ESP Fit Center") != NULL)
        {
            // Data points for ESP calculation
            tokenize(vs,buffer);
            if (NULL == esp)
                esp = new OpenBabel::OBFreeGrid();
            if (vs.size() == 9)
            {
                esp->AddPoint(atof(vs[6].c_str()),atof(vs[7].c_str()),
                              atof(vs[8].c_str()),0);
            }
            else if (vs.size() > 6)
            {
                double x,y,z;
                if (3 == sscanf(buffer+32,"%10lf%10lf%10lf",&x,&y,&z))
                {
                    esp->AddPoint(x,y,z,0);
                }
            }
        }
        else if (strstr(buffer, "Electrostatic Properties (Atomic Units)") != NULL)
        {
            int i,np;
            OpenBabel::OBFreeGridPoint *fgp;
            OpenBabel::OBFreeGridPointIterator fgpi;
            for(i=0; (i<5); i++)
            {
                ifs.getline(buffer,BUFF_SIZE);	// skip line
            }
            // Assume file is correct and that potentials are present
            // where they should.
            np = esp->NumPoints();
            fgpi = esp->BeginPoints();
            i = 0;
            for(fgp = esp->BeginPoint(fgpi); (NULL != fgp); fgp = esp->NextPoint(fgpi))
            {
                ifs.getline(buffer,BUFF_SIZE);
                tokenize(vs,buffer);
                if (vs.size() >= 2)
                {
                    fgp->SetV(atof(vs[2].c_str()));
                    i++;
                }
            }
            if (i == np)
            {
                esp->SetAttribute("Electrostatic Potential");
                mol.SetData(esp);
            }
            else
            {
                cout << "Read " << esp->NumPoints() << " ESP points i = " << i << "\n";
            }
        }
        else if (strstr(buffer, "Charges from ESP fit") != NULL)
        {
            hasPartialCharges = true;
            chargeModel = "ESP";
            ifs.getline(buffer,BUFF_SIZE);	// Charge / dipole line
            ifs.getline(buffer,BUFF_SIZE); // column header
            ifs.getline(buffer,BUFF_SIZE); // real charges
            tokenize(vs,buffer);
            while (vs.size() >= 3 &&
                    strstr(buffer,"-----") == NULL)
            {
                atom = mol.GetAtom(atoi(vs[0].c_str()));
                if (!atom)
                    break;
                atom->SetPartialCharge(atof(vs[2].c_str()));

                if (!ifs.getline(buffer,BUFF_SIZE)) break;
                tokenize(vs,buffer);
            }
        }
        else if(strstr(buffer,"Natural Population") != NULL)
        {
            hasPartialCharges = true;
            chargeModel = "NBO";
            ifs.getline(buffer,BUFF_SIZE);	// column headings
            ifs.getline(buffer,BUFF_SIZE);  // again
            ifs.getline(buffer,BUFF_SIZE);  // again (-----)
            ifs.getline(buffer,BUFF_SIZE); // real data
            tokenize(vs,buffer);
            while (vs.size() >= 3 &&
                    strstr(buffer,"=====") == NULL)
            {
                atom = mol.GetAtom(atoi(vs[1].c_str()));
                if (!atom)
                    break;
                atom->SetPartialCharge(atof(vs[2].c_str()));

                if (!ifs.getline(buffer,BUFF_SIZE)) break;
                tokenize(vs,buffer);
            }
        }
        else if(strstr(buffer, " Frequencies -- ")) //vibrational frequencies
        {
            //The info should appear only once as several blocks starting with this line
            tokenize(vs, buffer);
            for(unsigned int i=2; i<vs.size(); ++i)
                Frequencies.push_back(atof(vs[i].c_str()));
            ifs.getline(buffer,BUFF_SIZE); //Red. masses
            ifs.getline(buffer,BUFF_SIZE); //Frc consts
            ifs.getline(buffer,BUFF_SIZE); //IR Inten
            tokenize(vs, buffer);
            for(unsigned int i=3; i<vs.size(); ++i)
                Intensities.push_back(atof(vs[i].c_str()));

            ifs.getline(buffer, BUFF_SIZE); // column labels or Raman intensity
            if(strstr(buffer, "Raman Activ")) {
                ifs.getline(buffer, BUFF_SIZE); // Depolar (P)
                ifs.getline(buffer, BUFF_SIZE); // Depolar (U)
                ifs.getline(buffer, BUFF_SIZE); // column labels
            }
            ifs.getline(buffer, BUFF_SIZE); // actual displacement data
            tokenize(vs, buffer);
            vector<vector3> vib1, vib2, vib3;
            double x, y, z;
            while(vs.size() >= 5) {
                for (unsigned int i = 2; i < vs.size()-2; i += 3) {
                    x = atof(vs[i].c_str());
                    y = atof(vs[i+1].c_str());
                    z = atof(vs[i+2].c_str());

                    if (i == 2)
                        vib1.push_back(vector3(x, y, z));
                    else if (i == 5)
                        vib2.push_back(vector3(x, y, z));
                    else if (i == 8)
                        vib3.push_back(vector3(x, y, z));
                }

                if (!ifs.getline(buffer, BUFF_SIZE))
                    break;
                tokenize(vs,buffer);
            }
            Lx.push_back(vib1);
            if (vib2.size())
                Lx.push_back(vib2);
            if (vib3.size())
                Lx.push_back(vib3);
        }

        else if(strstr(buffer, " This molecule is "))//rotational data
        {
            if(strstr(buffer, "asymmetric"))
                RotorType = OBRotationData::ASYMMETRIC;
            else if(strstr(buffer, "symmetric"))
                RotorType = OBRotationData::SYMMETRIC;
            else if(strstr(buffer, "linear"))
                RotorType = OBRotationData::LINEAR;
            else
                RotorType = OBRotationData::UNKNOWN;
            ifs.getline(buffer,BUFF_SIZE); //symmetry number
            tokenize(vs, buffer);
            RotSymNum = atoi(vs[3].c_str());
        }

        else if(strstr(buffer, "Rotational constant"))
        {
            tokenize(vs, buffer);
            RotConsts.clear();
            for (unsigned int i=3; i<vs.size(); ++i)
                RotConsts.push_back(atof(vs[i].c_str()));
        }

        else if(strstr(buffer, "alpha electrons")) // # of electrons / orbital
        {
            tokenize(vs, buffer);
            if (vs.size() == 6) {
                // # alpha electrons # beta electrons
                aHOMO = atoi(vs[0].c_str());
                bHOMO = atoi(vs[3].c_str());
            }
        }
        else if(strstr(buffer, "rbital symmetries")) // orbital symmetries
        {
            symmetries.clear();
            std::string label; // used as a temporary to remove "(" and ")" from labels
            int iii,offset = 0;
            bool bDoneSymm;

            // Extract both Alpha and Beta symmetries
            ifs.getline(buffer, BUFF_SIZE); // skip the current line
            for(iii=0; (iii<2); iii++) {
                if (strstr(buffer, "electronic state"))
                    break; // We've gone too far!
                while (!ifs.eof() &&
                        ((NULL != strstr(buffer,"Alpha")) ||
                         (NULL != strstr(buffer,"Beta")))) {
                    // skip the Alpha: and Beta: title lines
                    ifs.getline(buffer, BUFF_SIZE);
                }
                do {
                    bDoneSymm = (NULL == strstr(buffer, "("));
                    if (!bDoneSymm) {
                        tokenize(vs, buffer);

                        if ((NULL != strstr(buffer, "Occupied")) || (NULL != strstr(buffer, "Virtual"))) {
                            offset = 1; // skip first token
                        } else {
                            offset = 0;
                        }
                        for (unsigned int i = offset; i < vs.size(); ++i) {
                            label = vs[i].substr(1, vs[i].length() - 2);
                            symmetries.push_back(label);
                        }
                        ifs.getline(buffer, BUFF_SIZE); // get a new line if we've been reading symmetries
                    }
                    // don't read a new line if we're done with symmetries
                } while (!ifs.eof() && !bDoneSymm);
            } // end alpha/beta section
        }
        else if (strstr(buffer, "Alpha") && strstr(buffer, ". eigenvalues --")) {
            orbitals.clear();
            betaStart = 0;
            while (strstr(buffer, ". eigenvalues --")) {
                tokenize(vs, buffer);
                if (vs.size() < 4)
                    break;
                if (vs[0].find("Beta") !=string::npos && betaStart == 0) // mark where we switch from alpha to beta
                    betaStart = orbitals.size();
                for (unsigned int i = 4; i < vs.size(); ++i) {
                    orbitals.push_back(atof(vs[i].c_str()));
                }
                ifs.getline(buffer, BUFF_SIZE);
            }
        }
        else if(strstr(buffer, " Excited State")) // Force and wavelength data
        {
            // The above line appears for each state, so just append the info to the vectors
            tokenize(vs, buffer);
            if (vs.size() >= 9) {
                double wavelength = atof(vs[6].c_str());
                double force = atof(vs[8].substr(2).c_str()); // remove the "f=" part
                Forces.push_back(force);
                Wavelengths.push_back(wavelength);
            }
        }
        else if(strstr(buffer, " Ground to excited state Transition electric dipole moments (Au):"))
            // Electronic dipole moments
        {
            ifs.getline(buffer, BUFF_SIZE); // Headings
            ifs.getline(buffer, BUFF_SIZE); // First entry
            tokenize(vs, buffer);
            while (vs.size() == 5) {
                double s = atof(vs[4].c_str());
                EDipole.push_back(s);
                ifs.getline(buffer, BUFF_SIZE);
                tokenize(vs, buffer);
            }
        }
        else if(strstr(buffer, "       state          X           Y           Z     R(velocity)")) {
            // Rotatory Strengths
            ifs.getline(buffer, BUFF_SIZE); // First entry
            tokenize(vs, buffer);
            while (vs.size() == 5) {
                double s = atof(vs[4].c_str());
                RotatoryStrengthsVelocity.push_back(s);
                ifs.getline(buffer, BUFF_SIZE);
                tokenize(vs, buffer);
            }
        }
        else if(strstr(buffer, "       state          X           Y           Z     R(length)")) {
            // Rotatory Strengths
            ifs.getline(buffer, BUFF_SIZE); // First entry
            tokenize(vs, buffer);
            while (vs.size() == 5) {
                double s = atof(vs[4].c_str());
                RotatoryStrengthsLength.push_back(s);
                ifs.getline(buffer, BUFF_SIZE);
                tokenize(vs, buffer);
            }
        }

        else if (strstr(buffer, "Forces (Hartrees/Bohr)"))
        {
            ifs.getline(buffer, BUFF_SIZE); // column headers
            ifs.getline(buffer, BUFF_SIZE); // ------
            ifs.getline(buffer, BUFF_SIZE); // real data
        }

        else if (strstr(buffer, "Isotropic = ")) // NMR shifts
        {
            tokenize(vs, buffer);
            if (vs.size() >= 4)
            {
                atom = mol.GetAtom(atoi(vs[0].c_str()));
                OBPairData *nmrShift = new OBPairData();
                nmrShift->SetAttribute("NMR Isotropic Shift");

                string shift = vs[4].c_str();
                nmrShift->SetValue(shift);

                atom->SetData(nmrShift);
            }
        }
        else if(strstr(buffer,"SCF Done:") != NULL)
        {
            tokenize(vs,buffer);
            mol.SetEnergy(atof(vs[4].c_str()) * HARTEE_TO_KCALPERMOL);
            confEnergies.push_back(mol.GetEnergy());
        }
        /* Temporarily commented out until the handling of energy in OBMol is sorted out
                // MP2 energies also use a different syntax

                // PM3 energies use a different syntax
                else if(strstr(buffer,"E (Thermal)") != NULL)
                  {
                    ifs.getline(buffer,BUFF_SIZE); //Headers
                    ifs.getline(buffer,BUFF_SIZE); //Total energy; what we want
                    tokenize(vs,buffer);
                    mol.SetEnergy(atof(vs[1].c_str()));
                    confEnergies.push_back(mol.GetEnergy());
                    }
        */
        else if(strstr(buffer,"Standard basis:") != NULL)
        {
            add_unique_pairdata_to_mol(&mol,"basis",buffer,2);
        }
        else if(strstr(buffer,"Zero-point correction=") != NULL)
        {
            tokenize(vs,buffer);
            ezpe = atof(vs[2].c_str());
            ezpe_set = true;
        }
        else if(strstr(buffer,"Thermal correction to Enthalpy=") != NULL)
        {
            tokenize(vs,buffer);
            Hcorr = atof(vs[4].c_str());
            Hcorr_set = true;
        }
        else if(strstr(buffer,"Thermal correction to Gibbs Free Energy=") != NULL)
        {
            tokenize(vs,buffer);
            Gcorr = atof(vs[6].c_str());
            Gcorr_set = true;
        }
        else if (strstr(buffer,"CV") != NULL)
        {
            ifs.getline(buffer,BUFF_SIZE); //Headers
            ifs.getline(buffer,BUFF_SIZE); //Total heat capacity
            tokenize(vs,buffer);
            if (vs.size() == 4)
            {
                if (vs[0].compare("Total") == 0)
                {
                    CV = atof(vs[2].c_str());
                    CV_set = true;
                }
            }
            ifs.getline(buffer,BUFF_SIZE); //Electronic
            ifs.getline(buffer,BUFF_SIZE); //Translational
            tokenize(vs,buffer);
            if ((vs.size() == 4) && (vs[0].compare("Translational") == 0) )
            {
                Scomponents.push_back(atof(vs[3].c_str()));
            }
            ifs.getline(buffer,BUFF_SIZE); //Rotational
            tokenize(vs,buffer);
            if ((vs.size() == 4) && (vs[0].compare("Rotational") == 0))
            {
                Scomponents.push_back(atof(vs[3].c_str()));
            }
            ifs.getline(buffer,BUFF_SIZE); //Vibrational
            tokenize(vs,buffer);
            if ((vs.size() == 4) && (vs[0].compare("Vibrational") == 0))
            {
                Scomponents.push_back(atof(vs[3].c_str()));
            }
        }
        else if ((strstr(buffer,"Temperature=") != NULL) &&
                 (strstr(buffer,"Pressure=") != NULL))
        {
            tokenize(vs,buffer);
            temperature = atof(vs[1].c_str());
        }
        else if (strstr(buffer, "(0 K)") != NULL)
        {
            /* This must be the last else */
            int i,nsearch;
            const char *search[] = { "CBS-QB3 (0 K)", "G2(0 K)", "G3(0 K)", "G4(0 K)", "W1BD (0 K)", "W1U  (0 K)" };
            const char *mymeth[] = { "CBS-QB3", "G2", "G3", "G4", "W1BD", "W1U" };
            const int myindex[] = { 3, 2, 2, 2, 3, 3 };

            nsearch = sizeof(search)/sizeof(search[0]);
            for(i=0; (i<nsearch); i++)
            {
                if(strstr(buffer,search[i]) != NULL)
                {
                    tokenize(vs,buffer);
                    E0 = atof(vs[myindex[i]].c_str());
                    E0_set = 1;
                    thermo_method = mymeth[i];
                    break;
                }
            }
        }
    } // end while

    if (mol.NumAtoms() == 0) { // e.g., if we're at the end of a file PR#1737209
        mol.EndModify();
        return false;
    }

    mol.EndModify();

    // Set conformers to all coordinates we adopted
    // but remove last geometry -- it's a duplicate
    if (vconf.size() > 1)
        vconf.pop_back();
    mol.SetConformers(vconf);
    mol.SetConformer(mol.NumConformers() - 1);
    // Copy the conformer data too
    confData->SetDimension(confDimensions);
    confData->SetEnergies(confEnergies);
    confData->SetForces(confForces);
    mol.SetData(confData);

    // Check whether we have data to extract heat of formation.
    if (ezpe_set && Hcorr_set && Gcorr_set && E0_set &&
            CV_set && (thermo_method.size() > 0))
    {
        extract_thermo(&mol,thermo_method,temperature,ezpe,
                       Hcorr,Gcorr,E0,CV,RotSymNum,Scomponents);
    }

    // Attach orbital data, if there is any
    if (orbitals.size() > 0)
    {
        OBOrbitalData *od = new OBOrbitalData;
        if (aHOMO == bHOMO) {
            od->LoadClosedShellOrbitals(orbitals, symmetries, aHOMO);
        } else {
            // we have to separate the alpha and beta vectors
            std::vector<double>      betaOrbitals;
            std::vector<std::string> betaSymmetries;
            unsigned int initialSize = orbitals.size();
            unsigned int symmSize = symmetries.size();
            if (initialSize != symmSize || betaStart == -1)
            {
                cerr << "Inconsistency: orbitals have " << initialSize << " elements while symmetries have " << symmSize << endl;
            }
            else
            {
                for (unsigned int i = betaStart; i < initialSize; ++i) {
                    betaOrbitals.push_back(orbitals[i]);
                    if (symmetries.size() > 0)
                        betaSymmetries.push_back(symmetries[i]);
                }
                // ok, now erase the end elements of orbitals and symmetries
                for (unsigned int i = betaStart; i < initialSize; ++i) {
                    orbitals.pop_back();
                    if (symmetries.size() > 0)
                        symmetries.pop_back();
                }
                // and load the alphas and betas
                od->LoadAlphaOrbitals(orbitals, symmetries, aHOMO);
                od->LoadBetaOrbitals(betaOrbitals, betaSymmetries, bHOMO);
            }
        }
        od->SetOrigin(fileformatInput);
        mol.SetData(od);
    }

    //Attach vibrational data, if there is any, to molecule
    if(Frequencies.size()>0)
    {
        OBVibrationData* vd = new OBVibrationData;
        vd->SetData(Lx, Frequencies, Intensities);
        vd->SetOrigin(fileformatInput);
        mol.SetData(vd);
    }
    //Attach rotational data, if there is any, to molecule
    if(RotConsts[0]!=0.0)
    {
        OBRotationData* rd = new OBRotationData;
        rd->SetData(RotorType, RotConsts, RotSymNum);
        rd->SetOrigin(fileformatInput);
        mol.SetData(rd);
    }
    // Attach unit cell translation vectors if found
    if (numTranslationVectors > 0) {
        OBUnitCell* uc = new OBUnitCell;
        uc->SetData(translationVectors[0], translationVectors[1], translationVectors[2]);
        uc->SetOrigin(fileformatInput);
        mol.SetData(uc);
    }
    //Attach electronic transition data, if there is any, to molecule
    if(Forces.size() > 0 && Forces.size() == Wavelengths.size())
    {
        OBElectronicTransitionData* etd = new OBElectronicTransitionData;
        etd->SetData(Wavelengths, Forces);
        if (EDipole.size() == Forces.size())
            etd->SetEDipole(EDipole);
        if (RotatoryStrengthsLength.size() == Forces.size())
            etd->SetRotatoryStrengthsLength(RotatoryStrengthsLength);
        if (RotatoryStrengthsVelocity.size() == Forces.size())
            etd->SetRotatoryStrengthsVelocity(RotatoryStrengthsVelocity);
        etd->SetOrigin(fileformatInput);
        mol.SetData(etd);
    }

    if (!pConv->IsOption("b",OBConversion::INOPTIONS))
        mol.ConnectTheDots();
    if (!pConv->IsOption("s",OBConversion::INOPTIONS) && !pConv->IsOption("b",OBConversion::INOPTIONS))
        mol.PerceiveBondOrders();

    if (hasPartialCharges) {
        mol.SetPartialChargesPerceived();

        // Annotate that partial charges come from Mulliken
        OBPairData *dp = new OBPairData;
        dp->SetAttribute("PartialCharges");
        dp->SetValue(chargeModel); // Mulliken, ESP, etc.
        dp->SetOrigin(fileformatInput);
        mol.SetData(dp);
    }
    mol.SetTotalCharge(total_charge);
    mol.SetTotalSpinMultiplicity(spin_multiplicity);

    mol.SetTitle(title);
    return(true);
}
Example #16
0
  // Reading Gaussian output has been tested for G98 and G03 to some degree
  // If you have problems (or examples of older output), please contact
  // the [email protected] mailing list and/or post a bug
  bool GaussianOutputFormat::ReadMolecule(OBBase* pOb, OBConversion* pConv)
  {
    OBMol* pmol = pOb->CastAndClear<OBMol>();
    if(pmol==NULL)
      return false;

    //Define some references so we can use the old parameter names
    istream &ifs = *pConv->GetInStream();
    OBMol &mol = *pmol;
    const char* title = pConv->GetTitle();

    char buffer[BUFF_SIZE];
    string str,str1;
    double x,y,z;
    OBAtom *atom;
    vector<string> vs;
    int charge = 0;
    unsigned int spin = 1;
    bool hasPartialCharges = false;
    string chargeModel; // descriptor for charges (e.g. "Mulliken")

    // coordinates of all steps
    // Set conformers to all coordinates we adopted
    std::vector<double*> vconf; // index of all frames/conformers
    std::vector<double> coordinates; // coordinates in each frame
    int natoms = 0; // number of atoms -- ensure we don't go to a new job with a different molecule

    // OBConformerData stores information about multiple steps
    // we can change attribute later if needed (e.g., IRC)
    OBConformerData *confData = new OBConformerData();
    confData->SetOrigin(fileformatInput);
    std::vector<unsigned short> confDimensions = confData->GetDimension(); // to be fair, set these all to 3D
    std::vector<double>         confEnergies   = confData->GetEnergies();
    std::vector< std::vector< vector3 > > confForces = confData->GetForces();

    //Vibrational data
    std::vector< std::vector< vector3 > > Lx;
    std::vector<double> Frequencies, Intensities;
    //Rotational data
    std::vector<double> RotConsts(3);
    int RotSymNum=1;
    OBRotationData::RType RotorType;

    // Translation vectors (if present)
    vector3 translationVectors[3];
    int numTranslationVectors = 0;

    //Electronic Excitation data
    std::vector<double> Forces, Wavelengths, EDipole,
      RotatoryStrengthsVelocity, RotatoryStrengthsLength;

    // Orbital data
    std::vector<double> orbitals;
    std::vector<std::string> symmetries;
    int aHOMO, bHOMO, betaStart;

    //Put some metadata into OBCommentData
    string comment("Gaussian ");
    ifs.getline(buffer,BUFF_SIZE);
    if(*buffer)
    {
      comment += strchr(buffer,'=')+2;
      comment += "";
      for(unsigned i=0; i<115, ifs; ++i)
      {
        ifs.getline(buffer,BUFF_SIZE);
        if(buffer[1]=='#')
        {
          //the line describing the method
          comment += buffer;
          OBCommentData *cd = new OBCommentData;
          cd->SetData(comment);
          cd->SetOrigin(fileformatInput);
          mol.SetData(cd);
          break;
        }
      }
    }

    int i=0;
    bool no_symmetry=false;
    char coords_type[25];

    //Prescan file to find second instance of "orientation:"
    //This will be the kind of coords used in the chk/fchk file
    //Unless the "nosym" keyword has been requested
    while (ifs.getline(buffer,BUFF_SIZE))
      {
        if (strstr(buffer,"Symmetry turned off by external request.") != NULL)
          {
            // The "nosym" keyword has been requested
            no_symmetry = true;
          }
        if (strstr(buffer,"orientation:") !=NULL)
          {
            i++;
            tokenize (vs, buffer);
            strcpy (coords_type, vs[0].c_str());
            strcat (coords_type, " orientation:");
          }
        if ((no_symmetry && i==1) || i==2)
           break;
	// Check for the last line of normal output and exit loop, otherwise,
	// the rewind below will no longer work.
        if (strstr(buffer,"Normal termination of Gaussian") != NULL)
           break;
      }
    ifs.seekg(0);  //rewind

    mol.BeginModify();
    while (ifs.getline(buffer,BUFF_SIZE))
      {
        if (strstr(buffer,"Multiplicity") != NULL)
          {
            tokenize(vs, buffer, " \t\n");
            if (vs.size() == 6)
              {
                charge = atoi(vs[2].c_str());
                spin = atoi(vs[5].c_str());
              }

            ifs.getline(buffer,BUFF_SIZE);
          }
        else if (strstr(buffer, coords_type) != NULL)
          {
            numTranslationVectors = 0; // ignore old translationVectors
            ifs.getline(buffer,BUFF_SIZE);      // ---------------
            ifs.getline(buffer,BUFF_SIZE);      // column headings
            ifs.getline(buffer,BUFF_SIZE);	// column headings
            ifs.getline(buffer,BUFF_SIZE);	// ---------------
            ifs.getline(buffer,BUFF_SIZE);
            tokenize(vs,buffer);
            while (vs.size() == 6)
              {
                x = atof((char*)vs[3].c_str());
                y = atof((char*)vs[4].c_str());
                z = atof((char*)vs[5].c_str());
                int atomicNum = atoi((char*)vs[1].c_str());

                if (atomicNum > 0) // translation vectors are "-2"
                  {
                    if (natoms == 0) { // first time reading the molecule, create each atom
                      atom = mol.NewAtom();
                      atom->SetAtomicNum(atoi((char*)vs[1].c_str()));
                    }
                    coordinates.push_back(x);
                    coordinates.push_back(y);
                    coordinates.push_back(z);
                  }
                else {
                  translationVectors[numTranslationVectors++].Set(x, y, z);
                }

                if (!ifs.getline(buffer,BUFF_SIZE)) {
                  break;
                }
                tokenize(vs,buffer);
              }
            // done with reading atoms
            natoms = mol.NumAtoms();
            // malloc / memcpy
            double *tmpCoords = new double [(natoms)*3];
            memcpy(tmpCoords, &coordinates[0], sizeof(double)*natoms*3);
            vconf.push_back(tmpCoords);
            coordinates.clear();
            confDimensions.push_back(3); // always 3D -- OBConformerData allows mixing 2D and 3D structures
          }
        else if(strstr(buffer,"Dipole moment") != NULL)
            {
              ifs.getline(buffer,BUFF_SIZE); // actual components   X ###  Y #### Z ###
              tokenize(vs,buffer);
              if (vs.size() >= 6)
                {
                  OBVectorData *dipoleMoment = new OBVectorData;
                  dipoleMoment->SetAttribute("Dipole Moment");
                  double x, y, z;
                  x = atof(vs[1].c_str());
                  y = atof(vs[3].c_str());
                  z = atof(vs[5].c_str());
                  dipoleMoment->SetData(x, y, z);
                  dipoleMoment->SetOrigin(fileformatInput);
                  mol.SetData(dipoleMoment);
                }
              if (!ifs.getline(buffer,BUFF_SIZE)) break;
            }
        else if(strstr(buffer,"Total atomic charges") != NULL ||
                strstr(buffer,"Mulliken atomic charges") != NULL)
          {
            hasPartialCharges = true;
            chargeModel = "Mulliken";
            ifs.getline(buffer,BUFF_SIZE);	// column headings
            ifs.getline(buffer,BUFF_SIZE);
            tokenize(vs,buffer);
            while (vs.size() >= 3 &&
                   strstr(buffer,"Sum of ") == NULL)
              {
                atom = mol.GetAtom(atoi(vs[0].c_str()));
                if (!atom)
                  break;
                atom->SetPartialCharge(atof(vs[2].c_str()));

                if (!ifs.getline(buffer,BUFF_SIZE)) break;
                tokenize(vs,buffer);
              }
          }
        else if (strstr(buffer, "Charges from ESP fit") != NULL)
          {
            hasPartialCharges = true;
            chargeModel = "ESP";
            ifs.getline(buffer,BUFF_SIZE);	// Charge / dipole line
            ifs.getline(buffer,BUFF_SIZE); // column header
            ifs.getline(buffer,BUFF_SIZE); // real charges
            tokenize(vs,buffer);
            while (vs.size() >= 3 &&
                   strstr(buffer,"-----") == NULL)
              {
                atom = mol.GetAtom(atoi(vs[0].c_str()));
                if (!atom)
                  break;
                atom->SetPartialCharge(atof(vs[2].c_str()));

                if (!ifs.getline(buffer,BUFF_SIZE)) break;
                tokenize(vs,buffer);
              }
          }
        else if(strstr(buffer,"Natural Population") != NULL)
          {
            hasPartialCharges = true;
            chargeModel = "NBO";
            ifs.getline(buffer,BUFF_SIZE);	// column headings
            ifs.getline(buffer,BUFF_SIZE);  // again
            ifs.getline(buffer,BUFF_SIZE);  // again (-----)
            ifs.getline(buffer,BUFF_SIZE); // real data
            tokenize(vs,buffer);
            while (vs.size() >= 3 &&
                   strstr(buffer,"=====") == NULL)
              {
                atom = mol.GetAtom(atoi(vs[1].c_str()));
                if (!atom)
                  break;
                atom->SetPartialCharge(atof(vs[2].c_str()));

                if (!ifs.getline(buffer,BUFF_SIZE)) break;
                tokenize(vs,buffer);
              }
          }
        else if(strstr(buffer, " Frequencies -- ")) //vibrational frequencies
        {
          //The info should appear only once as several blocks starting with this line
          tokenize(vs, buffer);
          for(unsigned int i=2; i<vs.size(); ++i)
            Frequencies.push_back(atof(vs[i].c_str()));
          ifs.getline(buffer,BUFF_SIZE); //Red. masses
          ifs.getline(buffer,BUFF_SIZE); //Frc consts
          ifs.getline(buffer,BUFF_SIZE); //IR Inten
          tokenize(vs, buffer);
          for(unsigned int i=3; i<vs.size(); ++i)
            Intensities.push_back(atof(vs[i].c_str()));

          ifs.getline(buffer, BUFF_SIZE); // column labels or Raman intensity
          if(strstr(buffer, "Raman Activ")) {
            ifs.getline(buffer, BUFF_SIZE); // Depolar (P)
            ifs.getline(buffer, BUFF_SIZE); // Depolar (U)
            ifs.getline(buffer, BUFF_SIZE); // column labels
          }
          ifs.getline(buffer, BUFF_SIZE); // actual displacement data
          tokenize(vs, buffer);
          vector<vector3> vib1, vib2, vib3;
          double x, y, z;
          while(vs.size() > 5) {
            for (unsigned int i = 2; i < vs.size()-2; i += 3) {
              x = atof(vs[i].c_str());
              y = atof(vs[i+1].c_str());
              z = atof(vs[i+2].c_str());

              if (i == 2)
                vib1.push_back(vector3(x, y, z));
              else if (i == 5)
                vib2.push_back(vector3(x, y, z));
              else if (i == 8)
                vib3.push_back(vector3(x, y, z));
            }

            if (!ifs.getline(buffer, BUFF_SIZE))
              break;
            tokenize(vs,buffer);
          }
          Lx.push_back(vib1);
          if (vib2.size())
            Lx.push_back(vib2);
          if (vib3.size())
            Lx.push_back(vib3);
        }

        else if(strstr(buffer, " This molecule is "))//rotational data
        {
          if(strstr(buffer, "asymmetric"))
            RotorType = OBRotationData::ASYMMETRIC;
          else if(strstr(buffer, "symmetric"))
            RotorType = OBRotationData::SYMMETRIC;
          else if(strstr(buffer, "linear"))
            RotorType = OBRotationData::LINEAR;
          else
             RotorType = OBRotationData::UNKNOWN;
          ifs.getline(buffer,BUFF_SIZE); //symmetry number
          tokenize(vs, buffer);
          RotSymNum = atoi(vs[3].c_str());
        }

        else if(strstr(buffer, "Rotational constant"))
        {
          tokenize(vs, buffer);
          RotConsts.clear();
          for (unsigned int i=3; i<vs.size(); ++i)
            RotConsts.push_back(atof(vs[i].c_str()));
        }

        else if(strstr(buffer, "alpha electrons")) // # of electrons / orbital
        {
          tokenize(vs, buffer);
          if (vs.size() == 6) {
            // # alpha electrons # beta electrons
            aHOMO = atoi(vs[0].c_str());
            bHOMO = atoi(vs[3].c_str());
          }
        }
        else if(strstr(buffer, "rbital symmetries")) // orbital symmetries
          {
            symmetries.clear();
            std::string label; // used as a temporary to remove "(" and ")" from labels
            int offset = 0;

            while(true) {
              ifs.getline(buffer, BUFF_SIZE);
              tokenize(vs, buffer); // parse first line "Occupied" ...
              for (unsigned int i = 1; i < vs.size(); ++i) {
                label = vs[i].substr(1, vs[i].length() - 2);
                symmetries.push_back(label);
              }
              ifs.getline(buffer, BUFF_SIZE);

              // Parse remaining lines
              while (strstr(buffer, "(")) {
                tokenize(vs, buffer);
                if (strstr(buffer, "Virtual")) {
                  offset = 1; // skip first token
                } else {
                  offset = 0;
                }
                for (unsigned int i = offset; i < vs.size(); ++i) {
                  label = vs[i].substr(1, vs[i].length() - 2);
                  symmetries.push_back(label);
                }
                ifs.getline(buffer, BUFF_SIZE); // get next line
              } // end parsing symmetry labels
              if (!strstr(buffer, "Beta")) // no beta orbitals
                break;
            } // end alpha/beta section
          }
        else if (strstr(buffer, "Alpha") && strstr(buffer, ". eigenvalues --")) {
          orbitals.clear();
          betaStart = 0;
          while (strstr(buffer, ". eigenvalues --")) {
            tokenize(vs, buffer);
            if (vs.size() < 4)
              break;
            if (vs[0].find("Beta") !=string::npos && betaStart == 0) // mark where we switch from alpha to beta
              betaStart = orbitals.size();
            for (unsigned int i = 4; i < vs.size(); ++i) {
              orbitals.push_back(atof(vs[i].c_str()));
            }
            ifs.getline(buffer, BUFF_SIZE);
          }
        }
        else if(strstr(buffer, " Excited State")) // Force and wavelength data
        {
          // The above line appears for each state, so just append the info to the vectors
          tokenize(vs, buffer);
          if (vs.size() == 9) {
            double wavelength = atof(vs[6].c_str());
            double force = atof(vs[8].substr(2).c_str());
            Forces.push_back(force);
            Wavelengths.push_back(wavelength);
          }
        }
        else if(strstr(buffer, " Ground to excited state Transition electric dipole moments (Au):"))
          // Electronic dipole moments
        {
          ifs.getline(buffer, BUFF_SIZE); // Headings
          ifs.getline(buffer, BUFF_SIZE); // First entry
          tokenize(vs, buffer);
          while (vs.size() == 5) {
            double s = atof(vs[4].c_str());
            EDipole.push_back(s);
            ifs.getline(buffer, BUFF_SIZE);
            tokenize(vs, buffer);
          }
        }
        else if(strstr(buffer, "       state          X           Y           Z     R(velocity)")) {
          // Rotatory Strengths
          ifs.getline(buffer, BUFF_SIZE); // First entry
          tokenize(vs, buffer);
          while (vs.size() == 5) {
            double s = atof(vs[4].c_str());
            RotatoryStrengthsVelocity.push_back(s);
            ifs.getline(buffer, BUFF_SIZE);
            tokenize(vs, buffer);
          }
        }
        else if(strstr(buffer, "       state          X           Y           Z     R(length)")) {
          // Rotatory Strengths
          ifs.getline(buffer, BUFF_SIZE); // First entry
          tokenize(vs, buffer);
          while (vs.size() == 5) {
            double s = atof(vs[4].c_str());
            RotatoryStrengthsLength.push_back(s);
            ifs.getline(buffer, BUFF_SIZE);
            tokenize(vs, buffer);
          }
        }

        else if (strstr(buffer, "Forces (Hartrees/Bohr)"))
          {
            ifs.getline(buffer, BUFF_SIZE); // column headers
            ifs.getline(buffer, BUFF_SIZE); // ------
            ifs.getline(buffer, BUFF_SIZE); // real data
          }

        else if (strstr(buffer, "Isotropic = ")) // NMR shifts
          {
            tokenize(vs, buffer);
            if (vs.size() >= 4)
              {
                atom = mol.GetAtom(atoi(vs[0].c_str()));
                OBPairData *nmrShift = new OBPairData();
                nmrShift->SetAttribute("NMR Isotropic Shift");

                string shift = vs[4].c_str();
                nmrShift->SetValue(shift);

                atom->SetData(nmrShift);
              }
          }

        else if(strstr(buffer,"SCF Done:") != NULL)
          {
#define HARTREE_TO_KCAL 627.509469
            tokenize(vs,buffer);
            mol.SetEnergy(atof(vs[4].c_str()) * HARTREE_TO_KCAL);
            confEnergies.push_back(mol.GetEnergy());
          }
/* Temporarily commented out until the handling of energy in OBMol is sorted out
        // MP2 energies also use a different syntax

        // PM3 energies use a different syntax
        else if(strstr(buffer,"E (Thermal)") != NULL)
          {
            ifs.getline(buffer,BUFF_SIZE); //Headers
            ifs.getline(buffer,BUFF_SIZE); //Total energy; what we want
            tokenize(vs,buffer);
            mol.SetEnergy(atof(vs[1].c_str()));
            confEnergies.push_back(mol.GetEnergy());
          }
*/
      } // end while

    if (mol.NumAtoms() == 0) { // e.g., if we're at the end of a file PR#1737209
      mol.EndModify();
      return false;
    }

    mol.EndModify();

    // Set conformers to all coordinates we adopted
    // but remove last geometry -- it's a duplicate
    if (vconf.size() > 1)
      vconf.pop_back();
    mol.SetConformers(vconf);
    mol.SetConformer(mol.NumConformers() - 1);
    // Copy the conformer data too
    confData->SetDimension(confDimensions);
    confData->SetEnergies(confEnergies);
    confData->SetForces(confForces);
    mol.SetData(confData);

    // Attach orbital data, if there is any
    if (orbitals.size() > 0)
      {
        OBOrbitalData *od = new OBOrbitalData;
        if (aHOMO == bHOMO) {
          od->LoadClosedShellOrbitals(orbitals, symmetries, aHOMO);
        } else {
          // we have to separate the alpha and beta vectors
          std::vector<double>      betaOrbitals;
          std::vector<std::string> betaSymmetries;
          unsigned int initialSize = orbitals.size();
          for (unsigned int i = betaStart; i < initialSize; ++i) {
            betaOrbitals.push_back(orbitals[i]);
            if (symmetries.size() > 0)
              betaSymmetries.push_back(symmetries[i]);
          }
          // ok, now erase the end elements of orbitals and symmetries
          for (unsigned int i = betaStart; i < initialSize; ++i) {
            orbitals.pop_back();
            if (symmetries.size() > 0)
              symmetries.pop_back();
          }
          // and load the alphas and betas
          od->LoadAlphaOrbitals(orbitals, symmetries, aHOMO);
          od->LoadBetaOrbitals(betaOrbitals, betaSymmetries, bHOMO);
        }
        od->SetOrigin(fileformatInput);
        mol.SetData(od);
      }

    //Attach vibrational data, if there is any, to molecule
    if(Frequencies.size()>0)
    {
      OBVibrationData* vd = new OBVibrationData;
      vd->SetData(Lx, Frequencies, Intensities);
      vd->SetOrigin(fileformatInput);
      mol.SetData(vd);
    }
    //Attach rotational data, if there is any, to molecule
    if(RotConsts[0]!=0.0)
    {
      OBRotationData* rd = new OBRotationData;
      rd->SetData(RotorType, RotConsts, RotSymNum);
      rd->SetOrigin(fileformatInput);
      mol.SetData(rd);
    }
    // Attach unit cell translation vectors if found
    if (numTranslationVectors > 0) {
      OBUnitCell* uc = new OBUnitCell;
      uc->SetData(translationVectors[0], translationVectors[1], translationVectors[2]);
      uc->SetOrigin(fileformatInput);
      mol.SetData(uc);
    }
    //Attach electronic transition data, if there is any, to molecule
    if(Forces.size() > 0 && Forces.size() == Wavelengths.size())
    {
      OBElectronicTransitionData* etd = new OBElectronicTransitionData;
      etd->SetData(Wavelengths, Forces);
      if (EDipole.size() == Forces.size())
        etd->SetEDipole(EDipole);
      if (RotatoryStrengthsLength.size() == Forces.size())
        etd->SetRotatoryStrengthsLength(RotatoryStrengthsLength);
      if (RotatoryStrengthsVelocity.size() == Forces.size())
        etd->SetRotatoryStrengthsVelocity(RotatoryStrengthsVelocity);
      etd->SetOrigin(fileformatInput);
      mol.SetData(etd);
    }

    if (!pConv->IsOption("b",OBConversion::INOPTIONS))
      mol.ConnectTheDots();
    if (!pConv->IsOption("s",OBConversion::INOPTIONS) && !pConv->IsOption("b",OBConversion::INOPTIONS))
      mol.PerceiveBondOrders();

    if (hasPartialCharges) {
      mol.SetPartialChargesPerceived();

      // Annotate that partial charges come from Mulliken
      OBPairData *dp = new OBPairData;
      dp->SetAttribute("PartialCharges");
      dp->SetValue(chargeModel); // Mulliken, ESP, etc.
      dp->SetOrigin(fileformatInput);
      mol.SetData(dp);
    }
    mol.SetTotalCharge(charge);
    mol.SetTotalSpinMultiplicity(spin);

    mol.SetTitle(title);
    return(true);
  }
void mmff94_validate()
{
  OBForceField* pFF = OBForceField::FindForceField("MMFF94");

  OBConversion conv;
  OBFormat *format_in = conv.FindFormat("mol2");
  vector<string> vs;
  vector<int> types;
  vector<double> fcharges, pcharges;
  vector<double> bond_lengths;
  char buffer[BUFF_SIZE], _logbuf[BUFF_SIZE];
  bool molfound, atomfound, bondfound, fchgfound, pchgfound;
  double etot, ebond, eangle, eoop, estbn, etor, evdw, eeq;
  double termcount; //1=bond, 2=angle, 3=strbnd, 4=torsion, 5=oop
  int n = 0;

  BOOST_REQUIRE_MESSAGE( format_in && conv.SetInFormat(format_in), "Could not set mol2 input format" );

  ifstream ifs, ifs2;
  ofstream ofs;

  ifs.open("MMFF94_dative.mol2");
  BOOST_REQUIRE_MESSAGE( ifs, "Could not open ./MMFF94_dative.mol2" );
 
  ifs2.open("MMFF94_opti.log");
  BOOST_REQUIRE_MESSAGE( ifs2, "Could not open ./MMFF94_opti.log" );
    
  ofs.open("MMFF94_openbabel.log");
  BOOST_REQUIRE_MESSAGE( ofs, "Could not open ./MMFF94_openbabel.log" );
    
  pFF->SetLogFile(&ofs);
  pFF->SetLogLevel(OBFF_LOGLVL_HIGH);
   
  OBMol mol;
  for (unsigned int c=1;; c++) {
    mol.Clear();
    types.clear();
    fcharges.clear();
    pcharges.clear();
    bond_lengths.clear();

    if (!conv.Read(&mol, &ifs))
      break;
    if (mol.Empty())
      break;
     
    BOOST_CHECK_MESSAGE( pFF->Setup(mol), "Could not setup calculations (missing parameters...)" );

    pFF->GetAtomTypes(mol);
    //pFF->GetFormalCharges(mol);
    pFF->GetPartialCharges(mol);

    termcount = 0;
    molfound = false;
    atomfound = false;
    bondfound = false;
    fchgfound = false;
    pchgfound = false;

    // Parse log file for types, charges, energies, ..
    while (ifs2.getline(buffer, 150)) {
      tokenize(vs, buffer);
      if (vs.size() == 0) {
        bondfound = false;
        continue;
      }
	
      string str(buffer);
      if (string::npos != str.find(mol.GetTitle(),0))
        molfound = true;

      // read atom types
      if (atomfound) {
        if (n) {
          types.push_back(atoi(vs[2].c_str()));
          types.push_back(atoi(vs[5].c_str()));
          types.push_back(atoi(vs[8].c_str()));
          types.push_back(atoi(vs[11].c_str()));
        } else {
          if (vs.size() > 2)
            types.push_back(atoi(vs[2].c_str()));
          if (vs.size() > 5)
            types.push_back(atoi(vs[5].c_str()));
          if (vs.size() > 8)
            types.push_back(atoi(vs[8].c_str()));
   
          atomfound = false;
        }
        n--;
      }
        
      // read formal charges
      if (fchgfound) {
        if (n) {
          fcharges.push_back(atof(vs[2].c_str()));
          fcharges.push_back(atof(vs[5].c_str()));
          fcharges.push_back(atof(vs[8].c_str()));
          fcharges.push_back(atof(vs[11].c_str()));
        } else {
          if (vs.size() > 2)
            fcharges.push_back(atof(vs[2].c_str()));
          if (vs.size() > 5)
            fcharges.push_back(atof(vs[5].c_str()));
          if (vs.size() > 8)
            fcharges.push_back(atof(vs[8].c_str()));
   
          fchgfound = false;
        }
        n--;
      }
 
      // read partial charges
      if (pchgfound) {
        if (n) {
          pcharges.push_back(atof(vs[2].c_str()));
          pcharges.push_back(atof(vs[5].c_str()));
          pcharges.push_back(atof(vs[8].c_str()));
          pcharges.push_back(atof(vs[11].c_str()));
        } else {
          if (vs.size() > 2)
            pcharges.push_back(atof(vs[2].c_str()));
          if (vs.size() > 5)
            pcharges.push_back(atof(vs[5].c_str()));
          if (vs.size() > 8)
            pcharges.push_back(atof(vs[8].c_str()));
   
          pchgfound = false;
        }
        n--;
      }
 
      // identify blocks
      if (molfound && EQn(buffer, " ATOM NAME  TYPE", 16)) {
        atomfound = true;
        n = mol.NumAtoms() / 4;
      }
      if (molfound && EQn(buffer, "   ATOM   FCHARGE", 17)) {
        fchgfound = true;
        n = mol.NumAtoms() / 4;
      }
      if (molfound && EQn(buffer, "   ATOM    CHARGE", 17)) {
        pchgfound = true;
        n = mol.NumAtoms() / 4;
      }

      if (bondfound)
        bond_lengths.push_back(atof(vs[7].c_str()));

      // Get the energies
      if (molfound) {
        if (EQn(buffer, " Total ENERGY", 13))
          etot = atof(vs[3].c_str());
        if (EQn(buffer, " Bond Stretching", 16))
          ebond = atof(vs[2].c_str());
        if (EQn(buffer, " Angle Bending", 14))
          eangle = atof(vs[2].c_str());
        if (EQn(buffer, " Out-of-Plane Bending", 21))
          eoop = atof(vs[2].c_str());
        if (EQn(buffer, " Stretch-Bend", 13))
          estbn = atof(vs[1].c_str());
        if (EQn(buffer, "     Total Torsion", 18))
          etor = atof(vs[2].c_str());
        if (EQn(buffer, "     Net vdW", 12))
          evdw = atof(vs[2].c_str());
        if (EQn(buffer, " Electrostatic", 14))
          eeq = atof(vs[1].c_str());
        if (EQn(buffer, " ---------------------", 22) && (termcount == 0)) {
          termcount++;
        bondfound = true;
        }
        if (EQn(buffer, " OPTIMOL>  # read next", 22))
          break;
      }
    } // while (getline)
      
    ostringstream os;
    vector<int>::iterator i;
    vector<double>::iterator di;
    unsigned int ni;
    bool failed;

    cout << "--------------------------------------------------------------------------------" << endl;
    cout << "                                                                                " << endl;
    cout << "  VALIDATE MOLECULE " << c << ": " << mol.GetTitle() << endl;
    cout << "                                                                                " << endl;
    cout << "IDX  HYB  AROM  OB_TYPE  LOG_TYPE       RESULT                                  " << endl;
    cout << "----------------------------------------------                                  " << endl;
 
    // 
    // validate atom types
    //
    ni = 1;
    failed = false;
    for (i = types.begin(); i != types.end();i++) {
      if (ni > mol.NumAtoms())
        continue;

      OBPairData *type = (OBPairData*) mol.GetAtom(ni)->GetData("FFAtomType");
      if (!type)
	continue;

      os.str("");
      os << "In molecule " << mol.GetTitle() << ": Wrong atom type for atom ";
      os << ni << " # found " << type->GetValue() << ", expected " << *i;
      BOOST_CHECK_MESSAGE( atoi(type->GetValue().c_str()) == (*i), os.str().c_str());
      
      if (atoi(type->GetValue().c_str()) == (*i))
        snprintf(_logbuf, BUFF_SIZE, "%2d   %3d  %4d    %3d      %3d          PASSED", 
                  mol.GetAtom(ni)->GetIdx(), mol.GetAtom(ni)->GetHyb(), 
                  mol.GetAtom(ni)->IsAromatic(), atoi(mol.GetAtom(ni)->GetType()), *i);
      else {
        snprintf(_logbuf, BUFF_SIZE, "%2d   %3d  %4d    %3d      %3d      XXX FAILED XXX", 
                  mol.GetAtom(ni)->GetIdx(), mol.GetAtom(ni)->GetHyb(), 
                  mol.GetAtom(ni)->IsAromatic(), atoi(type->GetValue().c_str()), *i);
        failed = true;
      }
      
      cout << _logbuf << endl;
        
      ni++;
    }

    /*
    cout << endl;
    cout << "IDX  OB_FCARGE  LOG_FCHARGE       RESULT" << endl;
    cout << "----------------------------------------" << endl;
            
    // 
    // validate formal charges
    //
    ni = 1;
    for (di = fcharges.begin(); di != fcharges.end(); di++) {
      if (ni > mol.NumAtoms())
        continue;
	
      if (fabs((*di) - mol.GetAtom(ni)->GetPartialCharge()) <= 0.001)
        snprintf(_logbuf, BUFF_SIZE, "%2d   %7.4f     %7.4f          PASSED", mol.GetAtom(ni)->GetIdx(), mol.GetAtom(ni)->GetPartialCharge(), *di);
      else {
        snprintf(_logbuf, BUFF_SIZE, "%2d   %7.4f     %7.4f      XXX FAILED XXX", mol.GetAtom(ni)->GetIdx(), mol.GetAtom(ni)->GetPartialCharge(), *di);
        failed = true;
      }
      
      cout << _logbuf << endl;
        
      ni++;
    }

    */

    cout << endl;
    cout << "IDX  OB_PCARGE  LOG_PCHARGE       RESULT" << endl;
    cout << "----------------------------------------" << endl;
      
    // 
    // validate partial charges
    //
    ni = 1;
    for (di = pcharges.begin(); di != pcharges.end(); di++) {
      if (ni > mol.NumAtoms())
        continue;
	
      OBPairData *chg = (OBPairData*) mol.GetAtom(ni)->GetData("FFPartialCharge");
      if (!chg)
	continue;

      os.str("");
      os << "In molecule " << mol.GetTitle() << ": Wrong partial charge for atom ";
      os << ni << " # found " << chg->GetValue() << ", expected " << *di;
      BOOST_CHECK_MESSAGE( fabs((*di) - atof(chg->GetValue().c_str())) <= 0.001, os.str().c_str());

      if (fabs((*di) - atof(chg->GetValue().c_str())) <= 0.001)
        snprintf(_logbuf, BUFF_SIZE, "%2d   %7.4f     %7.4f          PASSED", 
		  mol.GetAtom(ni)->GetIdx(), atof(chg->GetValue().c_str()), *di);
      else {
        snprintf(_logbuf, BUFF_SIZE, "%2d   %7.4f     %7.4f      XXX FAILED XXX",
                  mol.GetAtom(ni)->GetIdx(), atof(chg->GetValue().c_str()), *di);
        failed = true;
      }
      
      cout << _logbuf << endl;
        
      ni++;
    }

    double ene, delta;
    cout << endl;
    cout << "TERM                     OB ENERGY     LOG ENERGY         DELTA" << endl;
    cout << "---------------------------------------------------------------" << endl;
 
    // 
    // validate energies
    //
    
    // bond stretching
    ene = pFF->E_Bond();
    delta = (ene - ebond);
    
    os.str("");
    os << "In molecule " << mol.GetTitle() << ": Wrong bond stretching energy ";
    os << " # found " << ene << ", expected " << ebond;
    BOOST_CHECK_MESSAGE( delta < 0.005, os.str().c_str());

    snprintf(_logbuf, BUFF_SIZE, "Bond Stretching        %11.5f    %11.5f   %11.5f", ene, ebond, delta);
    cout << _logbuf << endl;
    
    // angle bending
    ene = pFF->E_Angle();
    delta = (ene - eangle);

    os.str("");
    os << "In molecule " << mol.GetTitle() << ": Wrong angle bending energy ";
    os << " # found " << ene << ", expected " << eangle;
    BOOST_CHECK_MESSAGE( delta < 0.005, os.str().c_str());

    snprintf(_logbuf, BUFF_SIZE, "Angle Bending          %11.5f    %11.5f   %11.5f", ene, eangle, delta);
    cout << _logbuf << endl;
    
    // stretch bending
    ene = pFF->E_StrBnd();
    delta = (ene - estbn);

    os.str("");
    os << "In molecule " << mol.GetTitle() << ": Wrong stretch bending energy ";
    os << " # found " << ene << ", expected " << estbn;
    BOOST_CHECK_MESSAGE( delta < 0.005, os.str().c_str());

    snprintf(_logbuf, BUFF_SIZE, "Stretch-Bending        %11.5f    %11.5f   %11.5f", ene, estbn, delta);
    cout << _logbuf << endl;
    
    // OOP
    ene = pFF->E_OOP();
    delta = (ene - eoop);

    os.str("");
    os << "In molecule " << mol.GetTitle() << ": Wrong out-of-plane bending energy ";
    os << " # found " << ene << ", expected " << eoop;
    BOOST_CHECK_MESSAGE( delta < 0.005, os.str().c_str());

    snprintf(_logbuf, BUFF_SIZE, "Out-Of-Plane Bending   %11.5f    %11.5f   %11.5f", ene, eoop, delta);
    cout << _logbuf << endl;
    
    // Torsional
    ene = pFF->E_Torsion();
    delta = (ene - etor);

    os.str("");
    os << "In molecule " << mol.GetTitle() << ": Wrong torsional energy ";
    os << " # found " << ene << ", expected " << etor;
    BOOST_CHECK_MESSAGE( delta < 0.005, os.str().c_str());
 
    snprintf(_logbuf, BUFF_SIZE, "Torsional              %11.5f    %11.5f   %11.5f", ene, etor, delta);
    cout << _logbuf << endl;
    
    // VDW
    ene = pFF->E_VDW();
    delta = (ene - evdw);

    os.str("");
    os << "In molecule " << mol.GetTitle() << ": Wrong van der waals energy ";
    os << " # found " << ene << ", expected " << evdw;
    BOOST_CHECK_MESSAGE( delta < 0.005, os.str().c_str());
 
    snprintf(_logbuf, BUFF_SIZE, "Van der Waals          %11.5f    %11.5f   %11.5f", ene, evdw, delta);
    cout << _logbuf << endl;
      
    // Electrostatic 
    ene = pFF->E_Electrostatic();
    delta = (ene - eeq);

    os << "In molecule " << mol.GetTitle() << ": Wrong electrostatic energy ";
    os << " # found " << ene << ", expected " << eeq;
    BOOST_CHECK_MESSAGE( delta < 0.005, os.str().c_str());
 
    snprintf(_logbuf, BUFF_SIZE, "Electrostatic          %11.5f    %11.5f   %11.5f", ene, eeq, delta);
    cout << _logbuf << endl;

    cout << endl;
    ene = pFF->Energy();
    delta = (ene - etot);

    os.str("");
    os << "In molecule " << mol.GetTitle() << ": Wrong total energy ";
    os << " # found " << ene << ", expected " << etot;
    BOOST_CHECK_MESSAGE( delta < 0.005, os.str().c_str());
 
    snprintf(_logbuf, BUFF_SIZE, "Total ENERGY           %11.5f    %11.5f   %11.5f", ene, etot, delta);
    cout << _logbuf << endl;

  } // for (unsigned int c;; c++ )
   
  if (ifs)
    ifs.close();
  if (ifs2)
    ifs2.close();
  if (ofs)
    ofs.close();
}
Example #18
0
  bool OutputFormat::ReadMolecule(OBBase* pOb, OBConversion* pConv)
  {
    // so we want to read through the file until we can figure out
    // what program actually created it
    // if we get to the end, emit a warning
    istream &ifs = *pConv->GetInStream();
    char buffer[BUFF_SIZE];
    OBFormat *pFormat = NULL;
    std::string formatName;

    // the detection strings are from the Chemical MIME project
    // http://chemical-mime.sourceforge.net/chemical-mime-data.html
    while (ifs.getline(buffer,BUFF_SIZE)) {
      if ((strstr(buffer,"GAMESS execution script") != NULL) ||
          (strstr(buffer,"PC GAMESS") != NULL) ||
          (strstr(buffer,"GAMESS VERSION") != NULL)) {
        // GAMESS output
        formatName = "gamout";
        break;
      } else if (strstr(buffer,"===  G A M E S S - U K    === ") != NULL) {
        // GAMESS-UK output
        formatName = "gukout";
        break;
      } else if (strstr(buffer,"Gaussian, Inc") != NULL) {
        // Gaussian output
        formatName = "g03";
        break;
      } else if (strstr(buffer,"GENERAL UTILITY LATTICE PROGRAM") != NULL) {
        // GULP output -- not currently supported
        break;
      } else if (strstr(buffer,"MOPAC") != NULL) {
        // MOPAC output
        formatName = "mopout";
        break;
      } else if (strstr(buffer,"Program PWSCF") != NULL) {
        // PWSCF
        formatName = "pwscf";
        break;
      } else if (strstr(buffer,"Welcome to Q-Chem") != NULL) {
        // Q-Chem output
        formatName = "qcout";
        break;
      } else if (strstr(buffer,"Amsterdam Density Functional") != NULL) {
        // ADF output
        // Determine the kind of ADF output
        while (ifs.getline(buffer, BUFF_SIZE)) {
          if (strstr(buffer, "|     A D F     |") != NULL) {
            formatName = "adfout";
            break;
          } else if (strstr(buffer, "|     B A N D     |") != NULL) {
            formatName = "adfband";
            break;
          } else if (strstr(buffer, "|     D F T B     |") != NULL) {
            formatName = "adfdftb";
            break;
          } else if (strstr(buffer, "DFTB Engine") != NULL) {
            // "|     D F T B     |" is no longer printed in ADF 2018
            // Hopefully, "DFTB Engine" will work fine...
            formatName = "adfdftb";
            break;
          }
        }
        break;
      } else if (strstr(buffer,"Northwest Computational Chemistry") != NULL) {
        // NWChem output
        formatName = "nwo";
        break;
      } else if (strstr(buffer,"MPQC: Massively Parallel Quantum Chemistry") != NULL) {
        // MPQC output
        formatName = "mpqc";
        break;
      } else if (strstr(buffer,"PROGRAM SYSTEM MOLPRO") != NULL) {
        // MOLPRO output
        formatName = "mpo";
        break;
      } else if ((strstr(buffer,"Schrodinger, Inc.") != NULL) &&
                 (strstr(buffer,"Jaguar") != NULL)) {
        // Jaguar
        formatName = "jout";
        break;
      } else if (strstr(buffer, "ABINIT") != NULL) {
        // Abinit
        formatName = "abinit";
        break;
      } else if (strstr(buffer, "ACES2") != NULL) {
        // ACESII
        formatName = "acesout";
        break;
      } else if (strstr(buffer, "CRYSTAL06") != NULL ||
                 strstr(buffer, "CRYSTAL09") != NULL) {
        // CRYSTAL09
        formatName = "c09out";
        break;
      } else if (strstr(buffer, "* O   R   C   A *") != NULL) {
        // ORCA
        formatName = "orca";
        break;
      } else if (strstr(buffer, "WELCOME TO SIESTA") != NULL) {
        // SIESTA
        formatName = "siesta";
        break;
      }
    }

    // if we assigned something above, let's try to find it
    if (formatName.length())
      pFormat = pConv->FindFormat(formatName);

    if (pFormat) {
      ifs.seekg (0, ios::beg); // reset the stream to the beginning
      ifs.clear();
      bool success = pFormat->ReadMolecule(pOb, pConv);

      // Tag the molecule with the format (e.g., if a program wants to know the kind of "out" or "log" file)
      // We have to do this *after* ReadMolecule returns, or the data might be cleared
      if (pOb) {
        OBPairData *dp = new OBPairData;
        dp->SetAttribute("File Format");
        dp->SetValue(formatName);
        dp->SetOrigin(fileformatInput);
        pOb->SetData(dp);
      }

      return success;
    }

    obErrorLog.ThrowError(__FUNCTION__,
                          "Problems reading an output file: Could not determine the format of this file. Please report it to the openbabel-discuss @ lists.sourceforge.net mailing list.", obError);
    return(false); // we couldn't figure out the format
  }
Example #19
0
  bool MacroModFormat::ReadMolecule(OBBase* pOb, OBConversion* pConv)
  {

    OBMol* pmol = pOb->CastAndClear<OBMol>();
    if(pmol==NULL)
      return false;

    //Define some references so we can use the old parameter names
    istream &ifs = *pConv->GetInStream();
    OBMol &mol = *pmol;
    const char* defaultTitle = pConv->GetTitle();

    // Get Title
    char buffer[BUFF_SIZE];
    int natoms;
    vector<vector<pair<int,int> > > connections;

    if (ifs.getline(buffer,BUFF_SIZE))
      {
        vector<string> vs;
        tokenize(vs,buffer," \n");

        if ( !vs.empty() && vs.size() > 0)
          sscanf(buffer,"%i%*s",&natoms);

        if (natoms == 0)
          return false;

        if ( !vs.empty() && vs.size() > 1)
          mol.SetTitle(vs[1]);
        else
          {
            string s = defaultTitle;
            mol.SetTitle(defaultTitle);
          }
      }
    else
      return(false);

    mol.BeginModify();
    mol.ReserveAtoms(natoms);
    connections.resize(natoms+1);

    /***********************************************************************/

    // Get Type Bonds, BondOrder, X, Y, Z

    double x,y,z;
    vector3 v;
    char temp_type[10];
    int i,j;
    double charge;
    OBAtom atom;

    ttab.SetFromType("MMD");
    for (i = 1; i <= natoms; i++)
      {
        if (!ifs.getline(buffer,BUFF_SIZE))
          break;

        int end[6], order[6];

        sscanf(buffer,"%9s%d%d%d%d%d%d%d%d%d%d%d%d%lf%lf%lf",
               temp_type,&end[0],&order[0],&end[1],&order[1],&end[2],&order[2],
               &end[3], &order[3], &end[4], &order[4], &end[5], &order[5],
               &x, &y, &z);

        pair<int,int> tmp;
        for ( j = 0 ; j <=5 ; j++ )
          {
            if ( end[j] > 0  && end[j] > i)
              {
                tmp.first = end[j];
                tmp.second = order[j];
                connections[i].push_back(tmp);
              }
          }

        v.SetX(x);
        v.SetY(y);
        v.SetZ(z);
        atom.SetVector(v);

        string str = temp_type,str1;
        ttab.SetToType("ATN");
        ttab.Translate(str1,str);
        atom.SetAtomicNum(atoi(str1.c_str()));
        ttab.SetToType("INT");
        ttab.Translate(str1,str);
        atom.SetType(str1);

        // stuff for optional fields

        buffer[109]='\0';
        sscanf(&buffer[101],"%lf", &charge);
        atom.SetPartialCharge(charge);
        mol.AddAtom(atom);
      }

    for (i = 1; i <= natoms; i++)
      for (j = 0; j < (signed)connections[i].size(); j++)
        mol.AddBond(i, connections[i][j].first, connections[i][j].second);

    mol.EndModify();
    mol.SetPartialChargesPerceived();
    // Annotate origin of partial charges
    OBPairData *dp = new OBPairData;
    dp->SetAttribute("PartialCharges");
    dp->SetValue("MACROMODEL");
    dp->SetOrigin(fileformatInput);
    mol.SetData(dp);

    OBBond *bond;
    vector<OBBond*>::iterator bi;
    for (bond = mol.BeginBond(bi);bond;bond = mol.NextBond(bi))
      if (bond->GetBondOrder() == 5 && !bond->IsInRing())
        bond->SetBondOrder(1);

    if ( natoms != (signed)mol.NumAtoms() )
      return(false);

    // clean out remaining blank lines
    std::streampos ipos;
    do
    {
      ipos = ifs.tellg();
      ifs.getline(buffer,BUFF_SIZE);
    }
    while(strlen(buffer) == 0 && !ifs.eof() );
    ifs.seekg(ipos);

    return(true);
  }