use of org.openscience.cdk.interfaces.ITetrahedralChirality in project cdk by cdk.
the class QueryStereoFilter method indexElements.
/**
* Index the stereo elements of the {@code container} into the the {@code
* elements} and {@code types} arrays. The {@code map} is used for looking
* up the index of atoms.
*
* @param map index of atoms
* @param elements array to fill with stereo elements
* @param types type of stereo element indexed
* @param container the container to index the elements of
* @return indices of atoms involved in stereo configurations
*/
private static int[] indexElements(Map<IAtom, Integer> map, IStereoElement[] elements, Type[] types, IAtomContainer container) {
int[] indices = new int[container.getAtomCount()];
int nElements = 0;
for (IStereoElement element : container.stereoElements()) {
if (element instanceof ITetrahedralChirality) {
ITetrahedralChirality tc = (ITetrahedralChirality) element;
int idx = map.get(tc.getChiralAtom());
elements[idx] = element;
types[idx] = Type.Tetrahedral;
indices[nElements++] = idx;
} else if (element instanceof IDoubleBondStereochemistry) {
IDoubleBondStereochemistry dbs = (IDoubleBondStereochemistry) element;
int idx1 = map.get(dbs.getStereoBond().getBegin());
int idx2 = map.get(dbs.getStereoBond().getEnd());
elements[idx2] = elements[idx1] = element;
types[idx1] = types[idx2] = Type.Geometric;
// only visit the first atom
indices[nElements++] = idx1;
}
}
return Arrays.copyOf(indices, nElements);
}
use of org.openscience.cdk.interfaces.ITetrahedralChirality in project cdk by cdk.
the class QueryStereoFilter method checkTetrahedral.
/**
* Verify the tetrahedral stereo-chemistry (clockwise/anticlockwise) of atom
* {@code u} is preserved in the target when the {@code mapping} is used.
*
* @param u tetrahedral index in the target
* @param mapping mapping of vertices
* @return the tetrahedral configuration is preserved
*/
private boolean checkTetrahedral(int u, int[] mapping) {
int v = mapping[u];
if (targetTypes[v] != null && targetTypes[v] != Type.Tetrahedral)
return false;
ITetrahedralChirality queryElement = (ITetrahedralChirality) queryElements[u];
ITetrahedralChirality targetElement = (ITetrahedralChirality) targetElements[v];
IAtom queryAtom = query.getAtom(u);
IAtom targetAtom = target.getAtom(v);
// check if unspecified was allowed
if (targetTypes[v] == null)
return ((QueryAtom) queryAtom).getExpression().matches(targetAtom, 0);
// target was non-tetrahedral
if (targetTypes[v] != Type.Tetrahedral)
return false;
int[] us = map(u, v, neighbors(queryElement, queryMap), mapping);
int[] vs = neighbors(targetElement, targetMap);
// adjustment needed for implicit neighbor (H or lone pair)
int focusIdx = targetMap.get(targetAtom);
for (int i = 0; i < 4; i++) {
// find mol neighbor in mapped query list
int j = indexOf(us, vs[i]);
// (which we store as focusIdx) with this neighbor
if (j < 0)
us[indexOf(us, focusIdx)] = vs[i];
}
int parity = permutationParity(us) * permutationParity(vs) * parity(targetElement.getStereo());
int groupInfo = targetElement.getGroupInfo();
if (groupInfo != 0) {
if (groupConfigAdjust == null)
groupConfigAdjust = new int[target.getAtomCount()];
// initialise the group
if (groupConfigAdjust[v] == 0) {
boolean leftOk = ((QueryAtom) queryAtom).getExpression().matches(targetAtom, IStereoElement.LEFT);
boolean rghtOk = ((QueryAtom) queryAtom).getExpression().matches(targetAtom, IStereoElement.RIGHT);
// element so wait till we find the next one
if (leftOk && rghtOk) {
return true;
}
int adjust = 1;
if ((parity == -1 && !leftOk) || (parity == 1 && !rghtOk))
adjust = -1;
for (int idx : targetStereoIndices) {
if (targetElements[idx].getGroupInfo() == groupInfo) {
groupConfigAdjust[idx] = adjust;
}
}
}
// make the adjustment
parity *= groupConfigAdjust[v];
}
if (parity < 0)
return ((QueryAtom) queryAtom).getExpression().matches(targetAtom, IStereoElement.LEFT);
else if (parity > 0)
return ((QueryAtom) queryAtom).getExpression().matches(targetAtom, IStereoElement.RIGHT);
else
return ((QueryAtom) queryAtom).getExpression().matches(targetAtom, 0);
}
use of org.openscience.cdk.interfaces.ITetrahedralChirality in project cdk by cdk.
the class StereoMatch method indexElements.
/**
* Index the stereo elements of the {@code container} into the the {@code
* elements} and {@code types} arrays. The {@code map} is used for looking
* up the index of atoms.
*
* @param map index of atoms
* @param elements array to fill with stereo elements
* @param types type of stereo element indexed
* @param container the container to index the elements of
* @return indices of atoms involved in stereo configurations
*/
private static int[] indexElements(Map<IAtom, Integer> map, IStereoElement[] elements, Type[] types, IAtomContainer container) {
int[] indices = new int[container.getAtomCount()];
int nElements = 0;
for (IStereoElement element : container.stereoElements()) {
if (element instanceof ITetrahedralChirality) {
ITetrahedralChirality tc = (ITetrahedralChirality) element;
int idx = map.get(tc.getChiralAtom());
elements[idx] = element;
types[idx] = Type.Tetrahedral;
indices[nElements++] = idx;
} else if (element instanceof IDoubleBondStereochemistry) {
IDoubleBondStereochemistry dbs = (IDoubleBondStereochemistry) element;
int idx1 = map.get(dbs.getStereoBond().getBegin());
int idx2 = map.get(dbs.getStereoBond().getEnd());
elements[idx2] = elements[idx1] = element;
types[idx1] = types[idx2] = Type.Geometric;
// only visit the first atom
indices[nElements++] = idx1;
}
}
return Arrays.copyOf(indices, nElements);
}
use of org.openscience.cdk.interfaces.ITetrahedralChirality in project cdk by cdk.
the class FischerRecognition method recognise.
/**
* Recognise the tetrahedral stereochemistry in the provided structure.
*
* @param projections allowed projection types
* @return zero of more stereo elements
*/
List<IStereoElement> recognise(Set<Projection> projections) {
if (!projections.contains(Projection.Fischer))
return Collections.emptyList();
// build atom index and only recognize 2D depictions
Map<IAtom, Integer> atomToIndex = new HashMap<>();
for (IAtom atom : container.atoms()) {
if (atom.getPoint2d() == null)
return Collections.emptyList();
atomToIndex.put(atom, atomToIndex.size());
}
RingSearch ringSearch = new RingSearch(container, graph);
final List<IStereoElement> elements = new ArrayList<>(5);
for (int v = 0; v < container.getAtomCount(); v++) {
IAtom focus = container.getAtom(v);
Elements elem = Elements.ofNumber(focus.getAtomicNumber());
if (elem != Carbon)
continue;
if (ringSearch.cyclic(v))
continue;
if (stereocenters.elementType(v) != Tetracoordinate)
continue;
if (!stereocenters.isStereocenter(v))
continue;
ITetrahedralChirality element = newTetrahedralCenter(focus, neighbors(v, graph, bonds));
if (element == null)
continue;
// east/west bonds must be to terminal atoms
IAtom east = element.getLigands()[EAST];
IAtom west = element.getLigands()[WEST];
if (!east.equals(focus) && !isTerminal(east, atomToIndex))
continue;
if (!west.equals(focus) && !isTerminal(west, atomToIndex))
continue;
elements.add(element);
}
return elements;
}
use of org.openscience.cdk.interfaces.ITetrahedralChirality in project cdk by cdk.
the class AtomContainerManipulator method convertImplicitToExplicitHydrogens.
/**
* Adds explicit hydrogens (without coordinates) to the IAtomContainer,
* equaling the number of set implicit hydrogens.
*
* @param atomContainer the atom container to consider
* @cdk.keyword hydrogens, adding
*/
public static void convertImplicitToExplicitHydrogens(IAtomContainer atomContainer) {
List<IAtom> hydrogens = new ArrayList<>();
List<IBond> newBonds = new ArrayList<>();
// store a single explicit hydrogen of each original neighbor
Map<IAtom, IAtom> hNeighbor = new HashMap<>(2 * atomContainer.getAtomCount());
for (IAtom atom : atomContainer.atoms()) {
if (atom.getAtomicNumber() != IElement.H) {
Integer hCount = atom.getImplicitHydrogenCount();
if (hCount != null) {
for (int i = 0; i < hCount; i++) {
IAtom hydrogen = atom.getBuilder().newInstance(IAtom.class, "H");
hydrogen.setAtomTypeName("H");
hydrogen.setImplicitHydrogenCount(0);
hydrogens.add(hydrogen);
newBonds.add(atom.getBuilder().newInstance(IBond.class, atom, hydrogen, Order.SINGLE));
if (hNeighbor.get(atom) == null)
hNeighbor.put(atom, hydrogen);
}
atom.setImplicitHydrogenCount(0);
}
}
}
for (IAtom atom : hydrogens) atomContainer.addAtom(atom);
for (IBond bond : newBonds) atomContainer.addBond(bond);
// update stereo elements with an implicit part
List<IStereoElement> stereos = new ArrayList<>();
for (IStereoElement stereo : atomContainer.stereoElements()) {
if (stereo instanceof ITetrahedralChirality) {
ITetrahedralChirality tc = (ITetrahedralChirality) stereo;
IAtom focus = tc.getFocus();
IAtom[] carriers = tc.getCarriers().toArray(new IAtom[4]);
IAtom hydrogen = hNeighbor.get(focus);
if (hydrogen != null) {
replaceAtom(carriers, focus, hydrogen);
TetrahedralChirality newStereo = new TetrahedralChirality(focus, carriers, tc.getStereo());
newStereo.setGroupInfo(tc.getGroupInfo());
stereos.add(newStereo);
} else {
stereos.add(stereo);
}
} else if (stereo instanceof ExtendedTetrahedral) {
ExtendedTetrahedral tc = (ExtendedTetrahedral) stereo;
IAtom focus = tc.getFocus();
IAtom[] carriers = tc.getCarriers().toArray(new IAtom[4]);
IAtom[] ends = ExtendedTetrahedral.findTerminalAtoms(atomContainer, focus);
IAtom h1 = hNeighbor.get(ends[0]);
IAtom h2 = hNeighbor.get(ends[1]);
if (h1 != null || h2 != null) {
if (h1 != null)
replaceAtom(carriers, ends[0], h1);
if (h2 != null)
replaceAtom(carriers, ends[1], h2);
stereos.add(new ExtendedTetrahedral(focus, carriers, tc.getConfigOrder()));
} else {
stereos.add(stereo);
}
} else {
stereos.add(stereo);
}
}
atomContainer.setStereoElements(stereos);
}
Aggregations