/**
  * Adds 3D coordinates for singly-bonded ligands of a reference atom (A). Initially designed for
  * hydrogens. The ligands of refAtom are identified and those with 3D coordinates used to generate
  * the new points. (This allows structures with partially known 3D coordinates to be used, as when
  * groups are added.) "Bent" and "non-planar" groups can be formed by taking a subset of the
  * calculated points. Thus R-NH2 could use 2 of the 3 points calculated from (1,iii) nomenclature:
  * A is point to which new ones are "attached". A may have ligands B, C... B may have ligands J,
  * K.. points X1, X2... are returned The cases (see individual routines, which use idealised
  * geometry by default): (0) zero ligands of refAtom. The resultant points are randomly oriented:
  * (i) 1 points required; +x,0,0 (ii) 2 points: use +x,0,0 and -x,0,0 (iii) 3 points: equilateral
  * triangle in xy plane (iv) 4 points x,x,x, x,-x,-x, -x,x,-x, -x,-x,x (1a) 1 ligand(B) of refAtom
  * which itself has a ligand (J) (i) 1 points required; vector along AB vector (ii) 2 points: 2
  * vectors in ABJ plane, staggered and eclipsed wrt J (iii) 3 points: 1 staggered wrt J, the
  * others +- gauche wrt J (1b) 1 ligand(B) of refAtom which has no other ligands. A random J is
  * generated and (1a) applied (2) 2 ligands(B, C) of refAtom A (i) 1 points required; vector in
  * ABC plane bisecting AB, AC. If ABC is linear, no points (ii) 2 points: 2 vectors at angle ang,
  * whose resultant is 2i (3) 3 ligands(B, C, D) of refAtom A (i) 1 points required; if A, B, C, D
  * coplanar, no points. else vector is resultant of BA, CA, DA
  *
  * <p>fails if atom itself has no coordinates or >4 ligands
  *
  * @param atomContainer describing the ligands of refAtom. It could be the whole molecule, or
  *     could be a selected subset of ligands
  * @param refAtom (A) to which new ligands coordinates could be added
  * @param length A-X length
  * @param angle B-A-X angle (used in certain cases)
  * @return Point3D[] points calculated. If request could not be fulfilled (e.g. too many atoms, or
  *     strange geometry, returns empty array (zero length, not null)
  * @cdk.keyword coordinate generation
  */
 public static Point3d[] calculate3DCoordinatesForLigands(
     AtomContainer atomContainer, IAtom refAtom, int nwanted, double length, double angle) {
   Point3d newPoints[] = new Point3d[0];
   Point3d aPoint = refAtom.getPoint3d();
   // get ligands
   List connectedAtoms = atomContainer.getConnectedAtomsList(refAtom);
   if (connectedAtoms == null) {
     return newPoints;
   }
   int nligands = connectedAtoms.size();
   AtomContainer ligandsWithCoords = new AtomContainer();
   for (int i = 0; i < nligands; i++) {
     Atom ligand = (Atom) connectedAtoms.get(i);
     if (ligand.getPoint3d() != null) {
       ligandsWithCoords.addAtom(ligand);
     }
   }
   int nwithCoords = ligandsWithCoords.getAtomCount();
   // too many ligands at present
   if (nwithCoords > 3) {
     return newPoints;
   }
   if (nwithCoords == 0) {
     newPoints = calculate3DCoordinates0(refAtom.getPoint3d(), nwanted, length);
   } else if (nwithCoords == 1) {
     // ligand on A
     IAtom bAtom = ligandsWithCoords.getAtom(0);
     connectedAtoms = ligandsWithCoords.getConnectedAtomsList(bAtom);
     // does B have a ligand (other than A)
     Atom jAtom = null;
     for (int i = 0; i < connectedAtoms.size(); i++) {
       Atom connectedAtom = (Atom) connectedAtoms.get(i);
       if (!connectedAtom.equals(refAtom)) {
         jAtom = connectedAtom;
         break;
       }
     }
     newPoints =
         calculate3DCoordinates1(
             aPoint,
             bAtom.getPoint3d(),
             (jAtom != null) ? jAtom.getPoint3d() : null,
             nwanted,
             length,
             angle);
   } else if (nwithCoords == 2) {
     Point3d bPoint = ligandsWithCoords.getAtom(0).getPoint3d();
     Point3d cPoint = ligandsWithCoords.getAtom(1).getPoint3d();
     newPoints = calculate3DCoordinates2(aPoint, bPoint, cPoint, nwanted, length, angle);
   } else if (nwithCoords == 3) {
     Point3d bPoint = ligandsWithCoords.getAtom(0).getPoint3d();
     Point3d cPoint = ligandsWithCoords.getAtom(1).getPoint3d();
     Point3d dPoint = ligandsWithCoords.getAtom(2).getPoint3d();
     newPoints = new Point3d[1];
     newPoints[0] = calculate3DCoordinates3(aPoint, bPoint, cPoint, dPoint, length);
   }
   return newPoints;
 }
Exemplo n.º 2
0
  /*
   * this is a test contributed by mario baseda / see bug #1610997
   *  @cdk.bug 1610997
   */
  @Test
  public void testModel3D_bug_1610997() throws Exception {
    Assume.assumeTrue(runSlowTests());

    boolean notCalculatedResults = false;
    List inputList = new ArrayList();

    ////////////////////////////////////////////////////////////////////////////////////////////
    // generate the input molecules. This are molecules without x, y, z coordinats

    String[] smiles =
        new String[] {
          "CC",
          "OCC",
          "O(C)CCC",
          "c1ccccc1",
          "C(=C)=C",
          "OCC=CCc1ccccc1(C=C)",
          "O(CC=C)CCN",
          "CCCCCCCCCCCCCCC",
          "OCC=CCO",
          "NCCCCN"
        };
    SmilesParser sp = new SmilesParser(NoNotificationChemObjectBuilder.getInstance());
    IAtomContainer[] atomContainer = new IAtomContainer[smiles.length];
    for (int i = 0; i < smiles.length; i++) {
      atomContainer[i] = sp.parseSmiles(smiles[i]);

      inputList.add(atomContainer[i]);
    }
    System.out.println(inputList.size());
    ///////////////////////////////////////////////////////////////////////////////////////////
    // Generate 2D coordinats for the input molecules with the Structure Diagram Generator

    StructureDiagramGenerator str;
    List resultList = new ArrayList();
    for (Iterator iter = inputList.iterator(); iter.hasNext(); ) {
      IAtomContainer molecules = (IAtomContainer) iter.next();
      str = new StructureDiagramGenerator();
      str.setMolecule((IMolecule) molecules);
      str.generateCoordinates();
      resultList.add(str.getMolecule());
    }
    inputList = resultList;

    /////////////////////////////////////////////////////////////////////////////////////////////
    // Delete x and y coordinats

    for (Iterator iter = inputList.iterator(); iter.hasNext(); ) {
      IAtomContainer molecules = (IAtomContainer) iter.next();
      for (Iterator atom = molecules.atoms().iterator(); atom.hasNext(); ) {
        Atom last = (Atom) atom.next();
        last.setPoint2d(null);
      }
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////
    // Test for the method Model3DBuildersWithMM2ForceField

    ModelBuilder3D mb3d = ModelBuilder3D.getInstance();
    for (Iterator iter = inputList.iterator(); iter.hasNext(); ) {
      IAtomContainer molecules = (IAtomContainer) iter.next();
      IMolecule mol = molecules.getBuilder().newInstance(IMolecule.class, molecules);
      mol = mb3d.generate3DCoordinates(mol, false);
      System.out.println("Calculation done");
    }

    for (Iterator iter = inputList.iterator(); iter.hasNext(); ) {
      IAtomContainer molecule = (IAtomContainer) iter.next();
      checkAverageBondLength(molecule);
      for (Iterator atom = molecule.atoms().iterator(); atom.hasNext(); ) {
        Atom last = (Atom) atom.next();
        if (last.getPoint3d() == null) notCalculatedResults = true;
      }
    }
    Assert.assertFalse(notCalculatedResults);
  }