Exemple #1
0
  bool CHEM3D1Format::ReadChem3d(istream &ifs,OBMol &mol,bool mmads,const char *type_key)
  {
    char buffer[BUFF_SIZE];
    int natoms,i;
    char tmp[16],tmp1[16];
    char atomic_type[16];
    double exponent = 0.0;
    double divisor = 1.0;
    double Alpha,Beta,Gamma,A,B,C;
    bool has_fractional = false, has_divisor = false;
    matrix3x3 m;

    vector<string> vs;
    ifs.getline(buffer,BUFF_SIZE);
    tokenize(vs,buffer);

    if (mmads)
      {
        if (vs.empty())
          return(false);
        natoms = atoi((char*)vs[0].c_str());
        if (vs.size() == 2)
          mol.SetTitle(vs[1]);
      }
    else
      {
        switch(vs.size())
          {
          case 7 :
            sscanf(buffer,"%d%lf%lf%lf%lf%lf%lf",
                   &natoms,&Alpha,&Beta,&Gamma,&A,&B,&C);
            m.FillOrth(Alpha,Beta,Gamma,A,B,C);
            has_fractional = true;
            break;
          case 8 :
            sscanf(buffer,"%d%lf%lf%lf%lf%lf%lf%lf",
                   &natoms,&Alpha,&Beta,&Gamma,&A,&B,&C,&exponent);
            m.FillOrth(Alpha,Beta,Gamma,A,B,C);
            has_fractional = true;
            has_divisor = true;
            break;
          default :
            sscanf(buffer,"%d",&natoms);
            break;
          }
      }

    if (!natoms)
      return(false);
    divisor = pow(10.0,exponent);
    mol.ReserveAtoms(natoms);

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

    OBAtom *atom;
    double x,y,z;
    vector3 v;

    unsigned int k;
    for (i = 1; i <= natoms; i++)
      {
        ifs.getline(buffer,BUFF_SIZE);
        sscanf(buffer,"%15s%*d%lf%lf%lf%15s",
               atomic_type,
               &x,
               &y,
               &z,
               tmp);
        v.Set(x,y,z);
        if (has_fractional)
          v *= m;
        if (has_divisor)
          v/= divisor;

        tokenize(vs,buffer);
        if (vs.empty())
          return(false);

        atom = mol.NewAtom();
        ttab.Translate(tmp1,tmp);
        atom->SetType(tmp1);
        atom->SetVector(v);
        atom->SetAtomicNum(etab.GetAtomicNum(atomic_type));

        for (k = 6;k < vs.size(); k++)
          mol.AddBond(atom->GetIdx(),atoi((char*)vs[k].c_str()),1);
      }

    // clean out remaining blank lines
    while(ifs.peek() != EOF && ifs.good() &&
          (ifs.peek() == '\n' || ifs.peek() == '\r'))
      ifs.getline(buffer,BUFF_SIZE);

    mol.PerceiveBondOrders();

    return(true);
  }
  static bool parseAtomRecord(char *buffer, OBMol &mol,int /*chainNum*/)
  /* ATOMFORMAT "(i5,1x,a4,a1,a3,1x,a1,i4,a1,3x,3f8.3,2f6.2,a2,a2)" */
  {
    string sbuf = &buffer[6];
    if (sbuf.size() < 48)
      return(false);

    bool hetatm = (EQn(buffer,"HETATM",6)) ? true : false;
    bool elementFound = false; // true if correct element found in col 77-78

    /* serial number */
    string serno = sbuf.substr(0,5);

    /* atom name */
    string atmid = sbuf.substr(6,4);
    
    /* chain */
    char chain = sbuf.substr(15,1)[0];

    /* element */
    string element = "  ";
    if (sbuf.size() > 71)
      {
        element = sbuf.substr(70,2);
        if (isalpha(element[1]))
          {
            if (element[0] == ' ')
              {
                element.erase(0, 1);
                elementFound = true;
              }
            else if (isalpha(element[0]))
              {
                elementFound = true;
              }
          }
      }

    if (!elementFound)
      {
        stringstream errorMsg;
        errorMsg << "WARNING: Problems reading a PDB file\n"
                 << "  Problems reading a HETATM or ATOM record.\n"
                 << "  According to the PDB specification,\n"
                 << "  columns 77-78 should contain the element symbol of an atom.\n"
                 << "  but OpenBabel found '" << element << "' (atom " << mol.NumAtoms()+1 << ")";
        obErrorLog.ThrowError(__FUNCTION__, errorMsg.str(), obWarning);
      }
    
    // charge - optional
    string scharge;
    if (sbuf.size() > 73)
      {
        scharge = sbuf.substr(72,2);
      }

    //trim spaces on the right and left sides
    while (!atmid.empty() && atmid[0] == ' ')
      atmid = atmid.erase(0, 1);

    while (!atmid.empty() && atmid[atmid.size()-1] == ' ')
      atmid = atmid.substr(0,atmid.size()-1);

    /* residue name */
    string resname = sbuf.substr(11,3);
    if (resname == "   ")
      resname = "UNK";
    else
      {
        while (!resname.empty() && resname[0] == ' ')
          resname = resname.substr(1,resname.size()-1);

        while (!resname.empty() && resname[resname.size()-1] == ' ')
          resname = resname.substr(0,resname.size()-1);
      }

    string type;
    if (!elementFound) {
      // OK, we have to fall back to determining the element from the atom type
      // This is unreliable, but there's no other choice
      if (EQn(buffer,"ATOM",4)) {
        type = atmid.substr(0,2);
        if (isdigit(type[0])) {
          // sometimes non-standard files have, e.g 11HH
          if (!isdigit(type[1])) type = atmid.substr(1,1);
          else type = atmid.substr(2,1); 
        } else if (sbuf[6] == ' ' &&
                   strncasecmp(type.c_str(), "Zn", 2) != 0 &&
                   strncasecmp(type.c_str(), "Fe", 2) != 0 ||
                   isdigit(type[1]))	//type[1] is digit in Platon
          type = atmid.substr(0,1);     // one-character element


        if (resname.substr(0,2) == "AS" || resname[0] == 'N') {
          if (atmid == "AD1")
            type = "O";
          if (atmid == "AD2")
            type = "N";
        }
        if (resname.substr(0,3) == "HIS" || resname[0] == 'H') {
          if (atmid == "AD1" || atmid == "AE2")
            type = "N";
          if (atmid == "AE1" || atmid == "AD2")
            type = "C";
        }
        if (resname.substr(0,2) == "GL" || resname[0] == 'Q') {
          if (atmid == "AE1")
            type = "O";
          if (atmid == "AE2")
            type = "N";
        }
        // fix: #2002557
        if (atmid[0] == 'H' && 
            (atmid[1] == 'D' || atmid[1] == 'E' || 
             atmid[1] == 'G' || atmid[1] == 'H')) // HD, HE, HG, HH, ..
          type = "H";
      } else { //must be hetatm record
        if (isalpha(element[1]) && (isalpha(element[0]) || (element[0] == ' '))) {
          if (isalpha(element[0]))
            type = element.substr(0,2);
          else
            type = element.substr(1,1);

          if (type.size() == 2)
            type[1] = tolower(type[1]);
        } else { // no element column to use
          if (isalpha(atmid[0])) {
            if (atmid.size() > 2 && (atmid[2] == '\0' || atmid[2] == ' '))
              type = atmid.substr(0,2);
            else if (atmid[0] == 'A') // alpha prefix
              type = atmid.substr(1, atmid.size() - 1);
            else
              type = atmid.substr(0,1);
          } else if (atmid[0] == ' ')
            type = atmid.substr(1,1); // one char element
          else
            type = atmid.substr(1,2);

          // Some cleanup steps
          if (atmid == resname) {
            type = atmid;
            if (type.size() == 2)
              type[1] = tolower(type[1]);
          } else
            if (resname == "ADR" || resname == "COA" || resname == "FAD" ||
                resname == "GPG" || resname == "NAD" || resname == "NAL" ||
                resname == "NDP" || resname == "ABA") {
              if (type.size() > 1)
                type = type.substr(0,1);
              //type.erase(1,type.size()-1);
            } else // other residues
              if (isdigit(type[0])){
                type = type.substr(1,1);
              }
              else
                if (type.size() > 1 && isdigit(type[1]))
                  type = type.substr(0,1);
                else
                  if (type.size() > 1 && isalpha(type[1])) {
                    if (type[0] == 'O' && type[1] == 'H')
                      type = type.substr(0,1); // no "Oh" element (e.g. 1MBN)
                    else if(isupper(type[1])) {
                      type[1] = tolower(type[1]);
                    }
                  }
        }

      } // HETATM records
    } // no element column to use

    OBAtom atom;
    /* X, Y, Z */
    string xstr = sbuf.substr(24,8);
    string ystr = sbuf.substr(32,8);
    string zstr = sbuf.substr(40,8);
    vector3 v(atof(xstr.c_str()),atof(ystr.c_str()),atof(zstr.c_str()));
    atom.SetVector(v);
    atom.ForceImplH();

    // useful for debugging unknown atom types (e.g., PR#1577238)
    //    cout << mol.NumAtoms() + 1  << " : '" << element << "'" << " " << etab.GetAtomicNum(element.c_str()) << endl;
    if (elementFound)
      atom.SetAtomicNum(etab.GetAtomicNum(element.c_str()));
    else // use our old-style guess from athe atom type
      atom.SetAtomicNum(etab.GetAtomicNum(type.c_str()));

    if ( (! scharge.empty()) && "  " != scharge )
      {
        if ( isdigit(scharge[0]) && ('+' == scharge[1] || '-' == scharge[1]) )
          {
            const char reorderCharge[3] = { scharge[1], scharge[0], '\0' };
            const int charge = atoi(reorderCharge);
            atom.SetFormalCharge(charge);
          }
        else
          {
            stringstream errorMsg;
            errorMsg << "WARNING: Problems reading a PDB file\n"
                     << "  Problems reading a HETATM or ATOM record.\n"
                     << "  According to the PDB specification,\n"
                     << "  columns 79-80 should contain charge of the atom\n"
                     << "  but OpenBabel found '" << scharge << "' (atom " << mol.NumAtoms()+1 << ").";
            obErrorLog.ThrowError(__FUNCTION__, errorMsg.str(), obWarning);
          }
      }
    else {
      atom.SetFormalCharge(0);
    }

    /* residue sequence number */
    string resnum = sbuf.substr(16,4);
    OBResidue *res  = (mol.NumResidues() > 0) ? mol.GetResidue(mol.NumResidues()-1) : NULL;
    if (res == NULL || res->GetName() != resname 
        || res->GetNumString() != resnum)
      {
        vector<OBResidue*>::iterator ri;
        for (res = mol.BeginResidue(ri) ; res ; res = mol.NextResidue(ri))
          if (res->GetName() == resname 
              && res->GetNumString() == resnum
              && static_cast<int>(res->GetChain()) == chain)
            break;

        if (res == NULL) {
          res = mol.NewResidue();
          res->SetChain(chain);
          res->SetName(resname);
          res->SetNum(resnum);
        }
      }

    if (!mol.AddAtom(atom))
      return(false);
    else {
      OBAtom *atom = mol.GetAtom(mol.NumAtoms());

      res->AddAtom(atom);
      res->SetSerialNum(atom, atoi(serno.c_str()));
      res->SetAtomID(atom, sbuf.substr(6,4));
      res->SetHetAtom(atom, hetatm);

      return(true);
    }
  } // end reading atom records
Exemple #3
0
  //! Calculate the signed volume for an atom.  If the atom has a valence of 3
  //! the coordinates of an attached hydrogen are calculated
  //! Puts attached Hydrogen last at the moment, like mol V3000 format.
  //! If ReZero=false (the default is true) always make pseudo z coords and leave them in mol
  double CalcSignedVolume(OBMol &mol,OBAtom *atm, bool ReZeroZ)
  {
    vector3 tmp_crd;
    vector<unsigned int> nbr_atms;
    vector<vector3> nbr_crds;
    bool use_central_atom = false,is2D=false;
    //   double hbrad = etab.CorrectedBondRad(1,0);
           
    if (!ReZeroZ || !mol.Has3D()) //give pseudo Z coords if mol is 2D
      {
        vector3 v,vz(0.0,0.0,1.0);
        is2D = true;
        OBAtom *nbr;
        OBBond *bond;
        vector<OBBond*>::iterator i;
        for (bond = atm->BeginBond(i);bond;bond = atm->NextBond(i))
          {
            nbr = bond->GetEndAtom();
            if (nbr != atm)
              {
                v = nbr->GetVector();
                if (bond->IsWedge())
                  v += vz;
                else
                  if (bond->IsHash())
                    v -= vz;

                nbr->SetVector(v);
              }
            else
              {
                nbr = bond->GetBeginAtom();
                v = nbr->GetVector();
                if (bond->IsWedge())
                  v -= vz;
                else
                  if (bond->IsHash())
                    v += vz;

                nbr->SetVector(v);
              }
          }
      }
    
    if (atm->GetHvyValence() < 3)
      {
        stringstream errorMsg;
        errorMsg << "Cannot calculate a signed volume for an atom with a heavy atom valence of " << atm->GetHvyValence() << endl;
        obErrorLog.ThrowError(__FUNCTION__, errorMsg.str(), obInfo);
        return(0.0);
      }

    // Create a vector with the coordinates of the neighbor atoms
    // Also make a vector with Atom IDs
    OBAtom *nbr;
    vector<OBBond*>::iterator bint;
    for (nbr = atm->BeginNbrAtom(bint);nbr;nbr = atm->NextNbrAtom(bint))
      {
        nbr_atms.push_back(nbr->GetIdx());
      }
    // sort the neighbor atoms to insure a consistent ordering
    sort(nbr_atms.begin(),nbr_atms.end());
    for (unsigned int i = 0; i < nbr_atms.size(); ++i)
      {
        OBAtom *tmp_atm = mol.GetAtom(nbr_atms[i]);
        nbr_crds.push_back(tmp_atm->GetVector());
      }
    /*
    // If we have three heavy atoms we need to calculate the position of the fourth
    if (atm->GetHvyValence() == 3)
    {
    double bondlen = hbrad+etab.CorrectedBondRad(atm->GetAtomicNum(),atm->GetHyb());
    atm->GetNewBondVector(tmp_crd,bondlen);
    nbr_crds.push_back(tmp_crd);
    }
    */
    for(unsigned int j=0;j < nbr_crds.size();++j) // Checks for a neighbour having 0 co-ords (added hydrogen etc)
      {
        // are the coordinates zero to 6 or more significant figures
        if (nbr_crds[j].IsApprox(VZero, 1.0e-6) && use_central_atom==false)
          use_central_atom=true;
        else if (nbr_crds[j].IsApprox(VZero, 1.0e-6))
          {
            obErrorLog.ThrowError(__FUNCTION__, "More than 2 neighbours have 0 co-ords when attempting 3D chiral calculation", obInfo);
          }
      }

    // If we have three heavy atoms we can use the chiral center atom itself for the fourth
    // will always give same sign (for tetrahedron), magnitude will be smaller.
    if(nbr_atms.size()==3 || use_central_atom==true)
      {
        nbr_crds.push_back(atm->GetVector());
        nbr_atms.push_back(mol.NumAtoms()+1); // meed to add largest number on end to work
      }
    OBChiralData* cd=(OBChiralData*)atm->GetData(OBGenericDataType::ChiralData); //Set the output atom4refs to the ones used
    if(cd==NULL)
      {
        cd = new OBChiralData;
        cd->SetOrigin(perceived);
        atm->SetData(cd);
      }
    cd->SetAtom4Refs(nbr_atms,calcvolume);
    
    //re-zero psuedo-coords
    if (is2D && ReZeroZ)
      {
        vector3 v;
        OBAtom *atom;
        vector<OBAtom*>::iterator k;
        for (atom = mol.BeginAtom(k);atom;atom = mol.NextAtom(k))
          {
            v = atom->GetVector();
            v.SetZ(0.0);
            atom->SetVector(v);
          }
      }
    
    return(signed_volume(nbr_crds[0],nbr_crds[1],nbr_crds[2],nbr_crds[3]));
  }
  void SuperCellExtension::fillCell()
  {
    /* Change coords back to inverse space, apply the space group transforms
     *  then change coords back to real space
     */
    if (!m_molecule)
      return;

    OBUnitCell *uc = m_molecule->OBUnitCell();
    if (!uc) {
      qDebug() << "No unit cell found - fillCell() returning...";
      return;
    }

    const SpaceGroup *sg = uc->GetSpaceGroup(); // the actual space group and transformations for this unit cell
    if (sg) {
      qDebug() << "Space group:" << sg->GetId();// << sg->GetHMName();
      // We operate on a copy of the Avogadro molecule
      // For each atom, we loop through:
      // * convert the coords back to inverse space
      // * apply the transformations
      // * create new (duplicate) atoms
      OBMol mol = m_molecule->OBMol();
      vector3 uniqueV, newV;
      list<vector3> transformedVectors; // list of symmetry-defined copies of the atom
      list<vector3>::iterator transformIterator, duplicateIterator;
      vector3 updatedCoordinate;
      bool foundDuplicate;

      OBAtom *addAtom;
      QList<OBAtom*> atoms; // keep the current list of unique atoms -- don't double-create
      list<vector3> coordinates; // all coordinates to prevent duplicates
      FOR_ATOMS_OF_MOL(atom, mol)
        atoms.push_back(&(*atom));

      foreach(OBAtom *atom, atoms) {
        uniqueV = atom->GetVector();
        // Assert: won't crash because we already ensure uc != NULL
        uniqueV = uc->CartesianToFractional(uniqueV);
        uniqueV = transformedFractionalCoordinate(uniqueV);
        coordinates.push_back(uniqueV);

        transformedVectors = sg->Transform(uniqueV);
        for (transformIterator = transformedVectors.begin();
             transformIterator != transformedVectors.end(); ++transformIterator) {
          // coordinates are in reciprocal space -- check if it's in the unit cell
          // if not, transform it in place
          updatedCoordinate = transformedFractionalCoordinate(*transformIterator);
          foundDuplicate = false;

          // Check if the transformed coordinate is a duplicate of an atom
          for (duplicateIterator = coordinates.begin();
               duplicateIterator != coordinates.end(); ++duplicateIterator) {
            if (duplicateIterator->distSq(updatedCoordinate) < 1.0e-4) {
              foundDuplicate = true;
              break;
            }
          }
          if (foundDuplicate)
            continue;

          coordinates.push_back(updatedCoordinate); // make sure to check the new atom for dupes
          addAtom = mol.NewAtom();
          addAtom->Duplicate(atom);
          addAtom->SetVector(uc->FractionalToCartesian(updatedCoordinate));
        } // end loop of transformed atoms

        // Put the original atom into the proper space in the unit cell too
        atom->SetVector(uc->FractionalToCartesian(uniqueV));
      } // end loop of atoms

      m_molecule->setOBMol(&mol);
      qDebug() << "Spacegroups done...";

      // Need a fresh pointer to the new unit cell - setOBMol is invalidating
      // the old one. This should be cleaned up to use a more permanent data
      // structure.
      uc = m_molecule->OBUnitCell();
      uc->SetSpaceGroup(1);
    }
Exemple #5
0
  //! Transform the supplied vector<OBInternalCoord*> into cartesian and update
  //! the OBMol accordingly. The size of supplied internal coordinate vector
  //! has to be the same as the number of atoms in molecule (+ NULL in the
  //! beginning).
  //! Implements <a href="http://qsar.sourceforge.net/dicts/blue-obelisk/index.xhtml#zmatrixCoordinatesIntoCartesianCoordinates">blue-obelisk:zmatrixCoordinatesIntoCartesianCoordinates</a>
  void InternalToCartesian(std::vector<OBInternalCoord*> &vic,OBMol &mol)
  {
    vector3 n,nn,v1,v2,v3,avec,bvec,cvec;
    double dst = 0.0, ang = 0.0, tor = 0.0;
    OBAtom *atom;
    vector<OBAtom*>::iterator i;
    unsigned int index;

    if (vic.empty())
      return;

    if (vic[0] != NULL) {
      std::vector<OBInternalCoord*>::iterator it = vic.begin();
      vic.insert(it, static_cast<OBInternalCoord*>(NULL));
    }

    if (vic.size() != mol.NumAtoms() + 1) {
      string error = "Number of internal coordinates is not the same as";
      error += " the number of atoms in molecule";
      obErrorLog.ThrowError(__FUNCTION__, error, obError);
      return;
    }

    obErrorLog.ThrowError(__FUNCTION__,
                          "Ran OpenBabel::InternalToCartesian", obAuditMsg);

    for (atom = mol.BeginAtom(i);atom;atom = mol.NextAtom(i))
      {
        index = atom->GetIdx();

        // make sure we always have valid pointers
        if (index >= vic.size() || !vic[index])
          return;

        if (vic[index]->_a) // make sure we have a valid ptr
          {
            avec = vic[index]->_a->GetVector();
            dst = vic[index]->_dst;
          }
        else
          {
            // atom 1
            atom->SetVector(0.0, 0.0, 0.0);
            continue;
          }

        if (vic[index]->_b)
          {
            bvec = vic[index]->_b->GetVector();
            ang = vic[index]->_ang * DEG_TO_RAD;
          }
        else
          {
            // atom 2
            atom->SetVector(dst, 0.0, 0.0);
            continue;
          }

        if (vic[index]->_c)
          {
            cvec = vic[index]->_c->GetVector();
            tor = vic[index]->_tor * DEG_TO_RAD;
          }
        else
          {
            // atom 3
            cvec = VY;
            tor = 90. * DEG_TO_RAD;
          }

        v1 = avec - bvec;
        v2 = avec - cvec;
        n = cross(v1,v2);
        nn = cross(v1,n);
        n.normalize();
        nn.normalize();

        n  *= -sin(tor);
        nn *= cos(tor);
        v3 = n + nn;
        v3.normalize();
        v3 *= dst * sin(ang);
        v1.normalize();
        v1 *= dst * cos(ang);
        v2 = avec + v3 - v1;

        atom->SetVector(v2);
      }

    // Delete dummy atoms
    vector<OBAtom*> for_deletion;
    FOR_ATOMS_OF_MOL(a, mol)
      if (a->GetAtomicNum() == 0)
        for_deletion.push_back(&(*a));
    for(vector<OBAtom*>::iterator a_it=for_deletion.begin(); a_it!=for_deletion.end(); ++a_it)
      mol.DeleteAtom(*a_it);

  }
Exemple #6
0
  bool BGFFormat::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;
    mol.SetTitle( pConv->GetTitle()); //default title is the filename
    mol.BeginModify();

    char buffer[BUFF_SIZE];
    char tmp[16],tmptyp[16];

    while (ifs.getline(buffer,BUFF_SIZE))
      if (EQn(buffer,"FORMAT",6))
        break;

    ttab.SetFromType("DRE");
    ttab.SetToType("INT");
    OBAtom *atom;
    double x,y,z,chrg;
    for (;;)
      {
        if (!ifs.getline(buffer,BUFF_SIZE))
          break;
        if (EQn(buffer,"FORMAT",6))
          break;

        sscanf(buffer,"%*s %*s %*s %*s %*s %*s %lf %lf %lf %15s %*s %*s %lf",
               &x,&y,&z,
               tmptyp,
               &chrg);
        atom = mol.NewAtom();

        ttab.Translate(tmp,tmptyp);
        atom->SetType(tmp);

        CleanAtomType(tmptyp);
        atom->SetAtomicNum(etab.GetAtomicNum(tmptyp));

        atom->SetVector(x,y,z);
      }
    unsigned int i;
    vector<int> vtmp;
    vector<vector<int> > vcon;
    vector<vector<int> > vord;

    for (i = 0; i < mol.NumAtoms();i++)
      {
        vcon.push_back(vtmp);
        vord.push_back(vtmp);
      }

    unsigned int bgn;
    vector<string> vs;
    for (;;)
      {
        if (!ifs.getline(buffer,BUFF_SIZE) || EQn(buffer,"END",3))
          break;

        tokenize(vs,buffer);
        if (vs.empty() || vs.size() < 3 || vs.size() > 10)
          continue;

        if (EQn(buffer,"CONECT",6))
          {
            bgn = atoi((char*)vs[1].c_str()) - 1;
            if (bgn < 1 || bgn > mol.NumAtoms())
              continue;
            for (i = 2;i < vs.size();i++)
              {
                vcon[bgn].push_back(atoi((char*)vs[i].c_str()));
                vord[bgn].push_back(1);
              }
          }
        else
          if (EQn(buffer,"ORDER",5))
            {
              bgn = atoi((char*)vs[1].c_str()) - 1;
              if (bgn < 1 || bgn > mol.NumAtoms())
                continue;
              if (vs.size() > vord[bgn].size()+2)
                continue;
              for (i = 2;i < vs.size();i++)
                vord[bgn][i-2] = atoi((char*)vs[i].c_str());
            }
      }

    unsigned int j;
    for (i = 1;i <= mol.NumAtoms();i++)
      if (!vcon[i - 1].empty())
        for (j = 0;j < vcon[i - 1].size();j++)
          {
            mol.AddBond(i,vcon[i - 1][j],vord[i - 1][j]);
          }

    //load up the next line after the END marker
    ifs.getline(buffer,BUFF_SIZE);

    mol.EndModify();
    return(true);
  }
Exemple #7
0
bool CCCFormat::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;
    mol.SetTitle( pConv->GetTitle()); //default title is the filename

    char buffer[BUFF_SIZE];
    ifs.getline(buffer,BUFF_SIZE);

    if (strlen(buffer) > 5)
        mol.SetTitle(&buffer[5]);
    mol.SetEnergy(0.0);

    int natoms;
    ifs.getline(buffer,BUFF_SIZE);
    sscanf(buffer,"%*s%d",&natoms);
    mol.ReserveAtoms(natoms);
    mol.BeginModify();

    int end,order;
    double x,y,z;
    OBAtom atom;
    vector3 v;
    vector<string> vs;
    char element[3];
    element[2] = '\0';

    for (int i = 1;i <= natoms;i++)
    {
        if (!ifs.getline(buffer,BUFF_SIZE))
            return(false);
        atom.Clear();
        element[0] = buffer[0];
        element[1] = (buffer[1] != ' ') ? buffer[1]:'\0';
        atom.SetAtomicNum(etab.GetAtomicNum(element));
        sscanf(&buffer[15],"%lf%lf%lf",&x,&y,&z);
        v.Set(x,y,z);
        atom.SetVector(v);

        if (!mol.AddAtom(atom))
            return(false);
        tokenize(vs,&buffer[60]);
        vector<string>::iterator j;

        for (j = vs.begin();j != vs.end();j++)
            if (!j->empty())
            {
                //get the bond order
                switch((char)(*j)[j->size()-1])
                {
                case 'S':
                    order = 1;
                    break;
                case 'D':
                    order = 2;
                    break;
                case 'T':
                    order = 3;
                    break;
                default:
                    order = 1;
                }
                (*j)[j->size()-1] = ' ';
                end = atoi(j->c_str());
                if (i>end)
                    mol.AddBond(i,end,order);
            }
    }

    mol.EndModify();
    return(true);
}
Exemple #8
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;
  }
  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);
  }
Exemple #10
0
  bool MSIFormat::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];

    stringstream errorMsg;

    if (!ifs)
      return false; // we're attempting to read past the end of the file

    if (!ifs.getline(buffer,BUFF_SIZE))
      {
        obErrorLog.ThrowError(__FUNCTION__,
                              "Problems reading an MSI file: Cannot read the first line.", obWarning);
        return(false);
      }

    if (!EQn(buffer, "# MSI CERIUS2 DataModel File", 28))
      {
        obErrorLog.ThrowError(__FUNCTION__,
                              "Problems reading an MSI file: The first line must contain the MSI header.", obWarning);
        return(false);
      }

    // "records" start with
    // (1 Model
    // ....
    //   and end with
    // ....
    // )
    unsigned int openParens = 0; // the count of "open parentheses" tags
    unsigned int startBondAtom, endBondAtom, bondOrder;
    bool atomRecord = false;
    bool bondRecord = false;
    OBAtom *atom;
//    OBBond *bond;
    vector<string> vs;
    const SpaceGroup *sg;
    bool setSpaceGroup = false;
    double x,y,z;
    vector3 translationVectors[3];
    int numTranslationVectors = 0;

    mol.BeginModify();
    while (ifs.getline(buffer,BUFF_SIZE))
      {
        // model record
        if (strstr(buffer, "Model") != NULL) {
          openParens++;
          continue;
        }

        // atom record
        if (!bondRecord && strstr(buffer, "Atom") != NULL) {
          atomRecord = true;
          openParens++;
          continue;
        }

        if (strstr(buffer, "Bond") != NULL) {
          bondRecord = true;
          startBondAtom = endBondAtom = 0;
          bondOrder = 1;
          openParens++;
          continue;
        }

        /* (A I PeriodicType 100)
           (A D A3 (6.2380000000000004 0 0))
           (A D B3 (0 6.9909999999999997 0))
           (A D C3 (0 0 6.9960000000000004))
           (A C SpaceGroup "63 5")
        */
        if (strstr(buffer, "PeriodicType") != NULL) {
          ifs.getline(buffer,BUFF_SIZE); // next line should be translation vector
          tokenize(vs,buffer);
            while (vs.size() == 6) {
              x = atof((char*)vs[3].erase(0,1).c_str());
              y = atof((char*)vs[4].c_str());
              z = atof((char*)vs[5].c_str());

              translationVectors[numTranslationVectors++].Set(x, y, z);
              if (!ifs.getline(buffer,BUFF_SIZE))
                break;
              tokenize(vs,buffer);
            }
        }

        if (strstr(buffer, "SpaceGroup") != NULL) {
          tokenize(vs, buffer);
          if (vs.size() != 5)
            continue; // invalid space group
          setSpaceGroup = true;
          sg = SpaceGroup::GetSpaceGroup(vs[4]); // remove the initial " character
        }

        // atom information
        if (atomRecord) {
          if (strstr(buffer, "ACL") != NULL) {
            tokenize(vs, buffer);
            // size should be 5 -- need a test here
            if (vs.size() != 5) return false; // timvdm 18/06/2008
            vs[3].erase(0,1); // "6 => remove the first " character
            unsigned int atomicNum = atoi(vs[3].c_str());
            if (atomicNum == 0)
              atomicNum = 1; // hydrogen ?

            // valid element, so create the atom
            atom = mol.NewAtom();
            atom->SetAtomicNum(atomicNum);
            continue;
          }
          else if (strstr(buffer, "XYZ") != NULL) {
            tokenize(vs, buffer);
            // size should be 6 -- need a test here
            if (vs.size() != 6) return false; // timvdm 18/06/2008
            vs[3].erase(0,1); // remove ( character
            vs[5].erase(vs[5].length()-2, 2); // remove trailing )) characters
            atom->SetVector(atof(vs[3].c_str()),
                            atof(vs[4].c_str()),
                            atof(vs[5].c_str()));
            continue;
          }
        } // end of atom records

        // bond information
        if (bondRecord) {
          if (strstr(buffer, "Atom1") != NULL) {
            tokenize(vs, buffer);
            if (vs.size() < 4) return false; // timvdm 18/06/2008
            vs[3].erase(vs[3].length()-1,1);
            startBondAtom = atoi(vs[3].c_str());
            continue;
          }
          else if (strstr(buffer, "Atom2") != NULL) {
            tokenize(vs, buffer);
            if (vs.size() < 4) return false; // timvdm 18/06/2008
            vs[3].erase(vs[3].length()-1,1);
            endBondAtom = atoi(vs[3].c_str());
            continue;
          }
          else if (strstr(buffer, "Type") != NULL) {
            tokenize(vs, buffer);
            if (vs.size() < 4) return false; // timvdm 18/06/2008
            vs[3].erase(vs[3].length()-1,1);
            bondOrder = atoi(vs[3].c_str());
            if (bondOrder == 4) // triple bond?
              bondOrder = 3;
            else if (bondOrder == 8) // aromatic?
              bondOrder = 5;
            else if (bondOrder != 2) // 1 OK, 2 OK, others unknown
              bondOrder = 1;
            continue;
          }
        }

        // ending a "tag" -- a lone ")" on a line
        if (strstr(buffer,")") != NULL && strstr(buffer, "(") == NULL) {
          openParens--;
          if (atomRecord) {
            atomRecord = false;
          }
          if (bondRecord) {
            // Bond records appear to be questionable
            mol.AddBond(startBondAtom - 1, endBondAtom - 1, bondOrder);
            bondRecord = false;
          }

          if (openParens == 0) {
            ifs.getline(buffer, BUFF_SIZE);
            break; // closed this molecule
          }
        }
      }

    mol.EndModify();

    // clean out any remaining blank lines
    while(ifs.peek() != EOF && ifs.good() &&
          (ifs.peek() == '\n' || ifs.peek() == '\r'))
      ifs.getline(buffer,BUFF_SIZE);

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

    if (numTranslationVectors > 0) {
      OBUnitCell* uc = new OBUnitCell;
      uc->SetData(translationVectors[0], translationVectors[1], translationVectors[2]);
      uc->SetOrigin(fileformatInput);
      if (setSpaceGroup) {
        uc->SetSpaceGroup(sg);
      }
      mol.SetData(uc);
    }

    return(true);
  }
Exemple #11
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);
  }
Exemple #12
0
bool TurbomoleFormat::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;
    double UnitConv=AAU;
    if(pConv->IsOption("a", OBConversion::INOPTIONS))
      UnitConv=1;


    char buffer[BUFF_SIZE];
    do
    {
        ifs.getline(buffer,BUFF_SIZE);
	if (ifs.peek() == EOF || !ifs.good())
	  return false;
    }
    while(strncmp(buffer,"$coord",6));

    mol.BeginModify();
    OBAtom atom;
    while(!(!ifs))
    {
        ifs.getline(buffer,BUFF_SIZE);
        if(*buffer=='$')
            break;
        if(*buffer=='#')
            continue;
        float x,y,z;
        char atomtype[8];
        if(sscanf(buffer,"%f %f %f %7s",&x,&y,&z,atomtype)!=4)
            return false;

        atom.SetVector(x*UnitConv, y*UnitConv, z*UnitConv);
        atom.SetAtomicNum(OBElements::GetAtomicNum(atomtype));
        atom.SetType(atomtype);

        if(!mol.AddAtom(atom))
            return false;
        atom.Clear();
    }
    while(!(!ifs) && strncmp(buffer,"$end",4))
        ifs.getline(buffer,BUFF_SIZE);

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

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

    mol.EndModify();
    return true;
}
Exemple #13
0
  bool OBDepict::DrawMolecule(OBMol *mol)
  {
    if (!d->painter)
      return false;

    d->mol = mol;

    OBAtom *atom;
    OBBondIterator j;
    OBAtomIterator i;

    // scale bond lengths
    double bondLengthSum = 0.0;
    for (OBBond *bond = mol->BeginBond(j); bond; bond = mol->NextBond(j))
      bondLengthSum += bond->GetLength();
    const double averageBondLength = bondLengthSum / mol->NumBonds();
    const double f = mol->NumBonds() ? d->bondLength / averageBondLength : 1.0;
    for (atom = mol->BeginAtom(i); atom; atom = mol->NextAtom(i))
      atom->SetVector(atom->GetX() * f, atom->GetY() * f, 0.0);

    // find min/max values
    double min_x, max_x;
    double min_y, max_y;
    atom = mol->BeginAtom(i);
    min_x = max_x = atom->GetX();
    min_y = max_y = atom->GetY();
    for (atom = mol->NextAtom(i); atom; atom = mol->NextAtom(i)) {
      min_x = std::min(min_x, atom->GetX());
      max_x = std::max(max_x, atom->GetX());
      min_y = std::min(min_y, atom->GetY());
      max_y = std::max(max_y, atom->GetY());
    }

    const double margin = 40.0;
    // translate all atoms so the bottom-left atom is at margin,margin
    for (atom = mol->BeginAtom(i); atom; atom = mol->NextAtom(i))
      atom->SetVector(atom->GetX() - min_x + margin, atom->GetY() - min_y + margin, 0.0);

    double width = max_x - min_x + 2*margin;
    double height = max_y - min_y + 2*margin;
    
    //d->painter->SetPenWidth(d->penWidth);
    //d->painter->SetPenColor(d->pen));
    //d->painter->SetFillColor(OBColor("black"));
    d->painter->NewCanvas(width, height);
    
    // draw bonds
    for (OBBond *bond = mol->BeginBond(j); bond; bond = mol->NextBond(j)) {
      OBAtom *begin = bond->GetBeginAtom();
      OBAtom *end = bond->GetEndAtom();

      if (bond->IsWedge()) {
        d->DrawWedge(begin, end);
      } else if (bond->IsHash()) {
        d->DrawHash(begin, end);
      } else if (!bond->IsInRing()) {
        d->DrawSimpleBond(begin, end, bond->GetBO());
      }
    }
    
    // draw ring bonds
    std::vector<OBRing*> rings(mol->GetSSSR());
    OBBitVec drawnBonds;
    for (std::vector<OBRing*>::iterator k = rings.begin(); k != rings.end(); ++k) {
      OBRing *ring = *k;
      std::vector<int> indexes = ring->_path;
      vector3 center(VZero);
      for (std::vector<int>::iterator l = indexes.begin(); l != indexes.end(); ++l) {
        center += mol->GetAtom(*l)->GetVector();        
      }
      center /= indexes.size();

      for (unsigned int l = 0; l < indexes.size(); ++l) {
        OBAtom *begin = mol->GetAtom(indexes[l]);
        OBAtom *end;
        if (l+1 < indexes.size())
          end = mol->GetAtom(indexes[l+1]);
        else
          end = mol->GetAtom(indexes[0]);

        OBBond *ringBond = mol->GetBond(begin, end);
        if (drawnBonds.BitIsSet(ringBond->GetId()))
          continue;
        d->DrawRingBond(begin, end, center, ringBond->GetBO());
        drawnBonds.SetBitOn(ringBond->GetId());
      }

    }

    // draw atom labels
    for (atom = mol->BeginAtom(i); atom; atom = mol->NextAtom(i)) {
      double x = atom->GetX();
      double y = atom->GetY();

      int alignment = GetLabelAlignment(atom);
      bool rightAligned = false;
      switch (alignment) {
        case TopRight:
        case CenterRight:
        case BottomRight:
          rightAligned = true;
        default:
          break;
      }

      d->painter->SetPenColor(OBColor(etab.GetRGB(atom->GetAtomicNum())));

      //charge and radical NEEDS REVISION
      int charge = atom->GetFormalCharge();
      int spin = atom->GetSpinMultiplicity();
      if(charge || spin) {
        OBFontMetrics metrics = d->painter->GetFontMetrics("N");
        double yoffset = d->HasLabel(atom) ? 0.4 * metrics.height : 0.0;
        switch (GetLabelAlignment(atom)) {
          case TopCenter:
          case TopRight:
          case TopLeft:
          case CenterLeft:
          case CenterRight:
            yoffset = - 1.2 * metrics.height;
        }
        stringstream ss;
        if(charge) {
          if(abs(charge)!=1)
            ss << abs(charge);
          ss << (charge>0 ? "+" : "-") ;
        }
        if(spin) {
          ss << (spin==2 ? "." : "..");
          yoffset += 0.5 * metrics.height;
        }
        if(spin || charge<0)
          d->painter->SetFontSize(2 * metrics.fontSize);
        d->painter->DrawText(x-0.4*metrics.width, y-yoffset, ss.str());
        d->painter->SetFontSize(metrics.fontSize);//restore
      }
 
      if (atom->IsCarbon()) { 
        if (atom->GetValence() > 1)
          continue;
        if ((atom->GetValence() == 1) && !d->drawTerminalC)
          continue;
      }

      stringstream ss;
      AliasData* ad = NULL;
      if(d->aliasMode && atom->HasData(AliasDataType))
        ad = static_cast<AliasData*>(atom->GetData(AliasDataType));
      
      //For unexpanded aliases use appropriate form of alias instead of element symbol, Hs, etc
      if(ad && !ad->IsExpanded())
      {
        ss <<ad->GetAlias(rightAligned);
        OBColor aliasColor = !ad->GetColor().empty() ? ad->GetColor() : d->bondColor; 
          d->painter->SetPenColor(aliasColor);
      }
      else {
        unsigned int hCount = atom->ImplicitHydrogenCount();
        // rightAligned:  
        //   false  CH3
        //   true   H3C
        if (hCount && rightAligned)
          ss << "H";
        if ((hCount > 1) && rightAligned)
          ss << hCount;
        ss << etab.GetSymbol(atom->GetAtomicNum());
        if (hCount && !rightAligned)
          ss << "H";
        if ((hCount > 1) && !rightAligned)
          ss << hCount;
      }
      d->DrawAtomLabel(ss.str(), alignment, vector3(x, y, 0.0));
    }

    return true;
  }
Exemple #14
0
int mol(int argc, char* argv[])
{
  int defaultchoice = 1;
  
  int choice = defaultchoice;

  if (argc > 1) {
    if(sscanf(argv[1], "%d", &choice) != 1) {
      printf("Couldn't parse that input as a number\n");
      return -1;
    }
  }


  // Define location of file formats for testing
  #ifdef FORMATDIR
    char env[BUFF_SIZE];
    snprintf(env, BUFF_SIZE, "BABEL_LIBDIR=%s", FORMATDIR);
    putenv(env);
  #endif

  cout << "# Unit tests for OBMol \n";

  cout << "ok 1\n"; // for loading tests

  OBMol emptyMol, testMol1;
  cout << "ok 2\n"; // ctor works

  testMol1.ReserveAtoms(-1);
  testMol1.ReserveAtoms(0);
  testMol1.ReserveAtoms(2);
  cout << "ok 3\n";

  // atom component tests

  if (testMol1.NumAtoms() == 0) {
    cout << "ok 4\n";
  } else {
    cout << "not ok 4\n";
  }

  testMol1.NewAtom();
  if (testMol1.NumAtoms() == 1) {
    cout << "ok 5\n";
  } else {
    cout << "not ok 5\n";
  }

  testMol1.NewAtom();
  testMol1.AddBond(1, 2, 1);
  if (testMol1.NumBonds() == 1) {
    cout << "ok 6\n";
  } else {
    cout << "not ok 6\n";
  }

  testMol1.Clear();
  if (testMol1.NumAtoms() == 0) {
    cout << "ok 7\n";
  } else {
    cout << "not ok 7\n";
  }

  ifstream ifs1(kd3file.c_str());
  if (!ifs1)
    {
      cout << "Bail out! Cannot read input file!" << endl;
      return(-1);
    }
  OBConversion conv(&ifs1, &cout);
  OBFormat* pFormat;
  
  pFormat = conv.FindFormat("XYZ");
  if ( pFormat == NULL )
    {
      cout << "Bail out! Cannot read file format!" << endl;
      return(-1);
    }
  if (! conv.SetInAndOutFormats(pFormat, pFormat))
    {
      cout << "Bail out! File format isn't loaded" << endl;
      return (-1);
    }

  OBMol testMol2D, testMol3D;
  if (conv.Read(&testMol3D))
    cout << "ok 8\n";
  else
    cout << "not ok 8\n";
  testMol3D.Center();
  
  // test bond insertion (PR#1665649)
  OBMol doubleBondMol;
  OBAtom *a1, *a2;
  OBBond *b;
  doubleBondMol.BeginModify();
  a1 = doubleBondMol.NewAtom();
  a1->SetVector(0.0, 0.0, 0.0);
  a1->SetAtomicNum(6);
  a2 = doubleBondMol.NewAtom();
  a2->SetVector(1.6, 0.0, 0.0);
  a2->SetAtomicNum(6);
  b = doubleBondMol.NewBond();
  b->SetBegin(a1);
  b->SetEnd(a2);
  a1->AddBond(b);
  a2->AddBond(b);
  doubleBondMol.EndModify();
  cout << "ok 9" << endl;

  // test AddHydrogens
  OBMol testMolH;
  testMolH.BeginModify();
  OBAtom *testAtom = testMolH.NewAtom();
  testAtom->SetVector(0.5f, 0.5f, 0.5f);
  testAtom->SetAtomicNum(6);
  testAtom->SetImplicitHCount(4);
  testMolH.EndModify();
  testMolH.AddHydrogens();
  if (testMolH.NumAtoms() == 5) {
    cout << "ok 10" << endl;
  } else {
    cout << "not ok 10" << endl;
  }

  // test AddHydrogens (pr #1665519)
  OBMol testMolH2;
  OBAtom *testAtom2 = testMolH2.NewAtom();
  testAtom2->SetVector(0.5f, 0.5f, 0.5f);
  testAtom2->SetAtomicNum(6);
  testAtom2->SetImplicitHCount(4);
  testMolH2.AddHydrogens();
  if (testMolH2.NumAtoms() == 5) {
    cout << "ok 11" << endl;
  } else {
    cout << "not ok 11 # hydrogen additions" << endl;
  }
  
  // Attempt to write an empty InChI (PR#2864334)
  pFormat = conv.FindFormat("InChI");
  if ( pFormat != NULL && conv.SetOutFormat(pFormat))
    {
      if (conv.Write(&emptyMol))
        cout << "ok 12" << endl;
      else
        cout << "not ok 12 # failed empty InChI" << endl;
    }

  OBMol testMolFormula;
  string formula("C6");
  testMolFormula.SetFormula(formula);
  if ( testMolFormula.GetFormula() == formula ) {
     cout << "ok 13" << endl;
  } else {
    cout << "not ok 13 # SetFormula "<< endl;
  }
  // Reset the formula to test for a double delete error
  testMolFormula.SetFormula(formula);
  
  // Test molecular formulas with large atomic numbers
  OBMol testLgAtNo;
  testLgAtNo.BeginModify();
  OBAtom *lgAtom = testLgAtNo.NewAtom();
  lgAtom->SetAtomicNum(118);
  // Undefined atomic numbers should be ignored with an obWarning instead of segfault
  lgAtom = testLgAtNo.NewAtom();
  lgAtom->SetAtomicNum(200);
  lgAtom = testLgAtNo.NewAtom();
  lgAtom->SetAtomicNum(1);
  lgAtom->SetIsotope(2);
  testLgAtNo.EndModify();
  if ( testLgAtNo.GetFormula() == "DOg" ) {
    cout << "ok 14" << endl;
  } else {
    cout << "not ok 14" << endl;
  }
  

  double dihedral = CalcTorsionAngle(vector3(-1., -1.,  0.),
                                     vector3(-1.,  0.,  0.),
                                     vector3( 1.,  0.,  0.),
                                     vector3( 1.,  1.,  0.));

  double dihedral_error = fabs(dihedral) - 180.0;

  if (fabs(dihedral_error) < 0.001) {
      std::cout << "ok 15 " << dihedral_error << std::endl;
  } else {

      std::cout << "not ok 15 # CalcTorsionAngle " << dihedral << "!= 180.0" << std::endl;
  }

  cout << "1..15\n"; // total number of tests for Perl's "prove" tool
  return(0);
}
bool TinkerFormat::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();

    int natoms;
    char buffer[BUFF_SIZE];
    vector<string> vs;

    ifs.getline(buffer, BUFF_SIZE);
    tokenize(vs,buffer);
    if (vs.size() < 2)
        return false;
    natoms = atoi(vs[0].c_str());

    // title is 2nd token (usually add tokens for the atom types)
    mol.SetTitle(vs[1]);

    mol.ReserveAtoms(natoms);
    mol.BeginModify();

    string str;
    double x,y,z;
    OBAtom *atom;
    int atomicNum;

    for (int i = 1; i <= natoms; ++i)
    {
        if (!ifs.getline(buffer,BUFF_SIZE))
            return(false);
        tokenize(vs,buffer);
        // e.g. "2  C      2.476285    0.121331   -0.001070     2     1     3    14"
        if (vs.size() < 5)
            return(false);

        atom = mol.NewAtom();
        x = atof((char*)vs[2].c_str());
        y = atof((char*)vs[3].c_str());
        z = atof((char*)vs[4].c_str());
        atom->SetVector(x,y,z); //set coordinates

        //set atomic number
        atom->SetAtomicNum(etab.GetAtomicNum(vs[1].c_str()));

        // add bonding
        if (vs.size() > 6)
            for (int j = 6; j < vs.size(); ++j)
                mol.AddBond(mol.NumAtoms(), atoi((char *)vs[j].c_str()), 1); // we don't know the bond order

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

    // clean out remaining blank lines
    while(ifs.peek() != EOF && ifs.good() &&
            (ifs.peek() == '\n' || ifs.peek() == '\r'))
        ifs.getline(buffer,BUFF_SIZE);

    mol.EndModify();
    mol.SetTitle(title);
    return(true);
}