use of org.openscience.cdk.stereo.ExtendedCisTrans in project cdk by cdk.
the class InChIToStructure method generateAtomContainerFromInchi.
/**
* Gets structure from InChI, and converts InChI library data structure
* into an IAtomContainer.
*
* @throws CDKException
*/
protected void generateAtomContainerFromInchi(IChemObjectBuilder builder) throws CDKException {
InchiInput input = output.getInchiInput();
// molecule = new AtomContainer();
molecule = builder.newInstance(IAtomContainer.class);
Map<InchiAtom, IAtom> inchiCdkAtomMap = new HashMap<>();
List<InchiAtom> atoms = input.getAtoms();
for (int i = 0; i < atoms.size(); i++) {
InchiAtom iAt = atoms.get(i);
IAtom cAt = builder.newInstance(IAtom.class);
inchiCdkAtomMap.put(iAt, cAt);
cAt.setID("a" + i);
cAt.setAtomicNumber(Elements.ofString(iAt.getElName()).number());
// Ignore coordinates - all zero - unless aux info was given... but
// the CDK doesn't have an API to provide that
// InChI does not have unset properties so we set charge,
// hydrogen count (implicit) and isotopic mass
cAt.setFormalCharge(iAt.getCharge());
cAt.setImplicitHydrogenCount(iAt.getImplicitHydrogen());
int isotopicMass = iAt.getIsotopicMass();
if (isotopicMass != 0) {
if (isotopicMass > ISOTOPIC_SHIFT_THRESHOLD) {
try {
int massNumber = Isotopes.getInstance().getMajorIsotope(cAt.getAtomicNumber()).getMassNumber();
cAt.setMassNumber(massNumber + (isotopicMass - ISOTOPIC_SHIFT_FLAG));
} catch (IOException e) {
throw new CDKException("Could not load Isotopes data", e);
}
} else {
cAt.setMassNumber(isotopicMass);
}
}
molecule.addAtom(cAt);
cAt = molecule.getAtom(molecule.getAtomCount() - 1);
addHydrogenIsotopes(builder, cAt, 2, iAt.getImplicitDeuterium());
addHydrogenIsotopes(builder, cAt, 3, iAt.getImplicitTritium());
}
List<InchiBond> bonds = input.getBonds();
for (InchiBond iBo : bonds) {
IBond cBo = builder.newInstance(IBond.class);
IAtom atO = inchiCdkAtomMap.get(iBo.getStart());
IAtom atT = inchiCdkAtomMap.get(iBo.getEnd());
cBo.setAtoms(new IAtom[] { atO, atT });
InchiBondType type = iBo.getType();
switch(type) {
case SINGLE:
cBo.setOrder(IBond.Order.SINGLE);
break;
case DOUBLE:
cBo.setOrder(IBond.Order.DOUBLE);
break;
case TRIPLE:
cBo.setOrder(IBond.Order.TRIPLE);
break;
case ALTERN:
cBo.setIsInRing(true);
break;
default:
throw new CDKException("Unknown bond type: " + type);
}
InchiBondStereo stereo = iBo.getStereo();
switch(stereo) {
case NONE:
cBo.setStereo(IBond.Stereo.NONE);
break;
case SINGLE_1DOWN:
cBo.setStereo(IBond.Stereo.DOWN);
break;
case SINGLE_1UP:
cBo.setStereo(IBond.Stereo.UP);
break;
case SINGLE_2DOWN:
cBo.setStereo(IBond.Stereo.DOWN_INVERTED);
break;
case SINGLE_2UP:
cBo.setStereo(IBond.Stereo.UP_INVERTED);
break;
case SINGLE_1EITHER:
cBo.setStereo(IBond.Stereo.UP_OR_DOWN);
break;
case SINGLE_2EITHER:
cBo.setStereo(IBond.Stereo.UP_OR_DOWN_INVERTED);
break;
}
molecule.addBond(cBo);
}
List<InchiStereo> stereos = input.getStereos();
for (InchiStereo stereo0d : stereos) {
if (stereo0d.getType() == InchiStereoType.Tetrahedral || stereo0d.getType() == InchiStereoType.Allene) {
InchiAtom central = stereo0d.getCentralAtom();
InchiAtom[] neighbours = stereo0d.getAtoms();
IAtom focus = inchiCdkAtomMap.get(central);
IAtom[] neighbors = new IAtom[] { inchiCdkAtomMap.get(neighbours[0]), inchiCdkAtomMap.get(neighbours[1]), inchiCdkAtomMap.get(neighbours[2]), inchiCdkAtomMap.get(neighbours[3]) };
ITetrahedralChirality.Stereo stereo;
// anti-clockwise
if (stereo0d.getParity() == InchiStereoParity.ODD) {
stereo = ITetrahedralChirality.Stereo.ANTI_CLOCKWISE;
} else if (stereo0d.getParity() == InchiStereoParity.EVEN) {
stereo = ITetrahedralChirality.Stereo.CLOCKWISE;
} else {
// CDK Only supports parities of + or -
continue;
}
IStereoElement stereoElement = null;
if (stereo0d.getType() == InchiStereoType.Tetrahedral) {
stereoElement = builder.newInstance(ITetrahedralChirality.class, focus, neighbors, stereo);
} else if (stereo0d.getType() == InchiStereoType.Allene) {
// The periphals (p<i>) and terminals (t<i>) are refering to
// the following atoms. The focus (f) is also shown.
//
// p0 p2
// \ /
// t0 = f = t1
// / \
// p1 p3
IAtom[] peripherals = neighbors;
IAtom[] terminals = ExtendedTetrahedral.findTerminalAtoms(molecule, focus);
// case
for (IAtom terminal : terminals) {
if (peripherals[1].equals(terminal)) {
peripherals[1] = findOtherSinglyBonded(molecule, terminal, peripherals[0]);
} else if (peripherals[2].equals(terminal)) {
peripherals[2] = findOtherSinglyBonded(molecule, terminal, peripherals[3]);
} else if (peripherals[0].equals(terminal)) {
peripherals[0] = findOtherSinglyBonded(molecule, terminal, peripherals[1]);
} else if (peripherals[3].equals(terminal)) {
peripherals[3] = findOtherSinglyBonded(molecule, terminal, peripherals[2]);
}
}
stereoElement = new ExtendedTetrahedral(focus, peripherals, stereo);
}
assert stereoElement != null;
molecule.addStereoElement(stereoElement);
} else if (stereo0d.getType() == InchiStereoType.DoubleBond) {
boolean extended = false;
InchiAtom[] neighbors = stereo0d.getAtoms();
// from JNI InChI doc
// neighbor[4] : {#X,#A,#B,#Y} in this order
// X central_atom : NO_ATOM
// \ X Y type : INCHI_StereoType_DoubleBond
// A == B \ /
// \ A == B
// Y
IAtom x = inchiCdkAtomMap.get(neighbors[0]);
IAtom a = inchiCdkAtomMap.get(neighbors[1]);
IAtom b = inchiCdkAtomMap.get(neighbors[2]);
IAtom y = inchiCdkAtomMap.get(neighbors[3]);
IBond stereoBond = molecule.getBond(a, b);
if (stereoBond == null) {
extended = true;
IBond tmp = null;
// A = C = C = B
stereoBond = ExtendedCisTrans.findCentralBond(molecule, a);
if (stereoBond == null)
// warn on invalid input?
continue;
IAtom[] ends = ExtendedCisTrans.findTerminalAtoms(molecule, stereoBond);
assert ends != null;
if (ends[0] != a)
flip(stereoBond);
} else {
if (!stereoBond.getBegin().equals(a))
flip(stereoBond);
}
int config = IStereoElement.TOGETHER;
if (stereo0d.getParity() == InchiStereoParity.EVEN)
config = IStereoElement.OPPOSITE;
if (extended) {
molecule.addStereoElement(new ExtendedCisTrans(stereoBond, new IBond[] { molecule.getBond(x, a), molecule.getBond(b, y) }, config));
} else {
molecule.addStereoElement(new DoubleBondStereochemistry(stereoBond, new IBond[] { molecule.getBond(x, a), molecule.getBond(b, y) }, config));
}
}
}
}
use of org.openscience.cdk.stereo.ExtendedCisTrans in project cdk by cdk.
the class AtomContainerManipulator method suppressHydrogens.
/**
* Suppress any explicit hydrogens in the provided container. Only hydrogens
* that can be represented as a hydrogen count value on the atom are
* suppressed. The container is updated and no elements are copied, please
* use either {@link #copyAndSuppressedHydrogens} if you would to preserve
* the old instance.
*
* @param org the container from which to remove hydrogens
* @return the input for convenience
* @see #copyAndSuppressedHydrogens
*/
public static IAtomContainer suppressHydrogens(IAtomContainer org) {
boolean anyHydrogenPresent = false;
for (IAtom atom : org.atoms()) {
if (atom.getAtomicNumber() == IElement.H) {
anyHydrogenPresent = true;
break;
}
}
if (!anyHydrogenPresent)
return org;
// crossing atoms, positional variation atoms etc
Set<IAtom> xatoms = Collections.emptySet();
Collection<Sgroup> sgroups = org.getProperty(CDKConstants.CTAB_SGROUPS);
if (sgroups != null) {
xatoms = new HashSet<>();
for (Sgroup sgroup : sgroups) {
for (IBond bond : sgroup.getBonds()) {
xatoms.add(bond.getBegin());
xatoms.add(bond.getEnd());
}
}
}
// we need fast adjacency checks (to check for suppression and
// update hydrogen counts)
GraphUtil.EdgeToBondMap bondmap = GraphUtil.EdgeToBondMap.withSpaceFor(org);
final int[][] graph = GraphUtil.toAdjList(org, bondmap);
final int nOrgAtoms = org.getAtomCount();
final int nOrgBonds = org.getBondCount();
int nCpyAtoms = 0;
int nCpyBonds = 0;
final Set<IAtom> hydrogens = new HashSet<>(nOrgAtoms);
final Set<IBond> bondsToHydrogens = new HashSet<>();
final IAtom[] cpyAtoms = new IAtom[nOrgAtoms];
// be suppressed
for (int v = 0; v < nOrgAtoms; v++) {
final IAtom atom = org.getAtom(v);
if (suppressibleHydrogen(org, graph, bondmap, v) && !xatoms.contains(atom)) {
hydrogens.add(atom);
incrementImplHydrogenCount(org.getAtom(graph[v][0]));
} else {
cpyAtoms[nCpyAtoms++] = atom;
}
}
// none of the hydrogens could be suppressed - no changes need to be made
if (hydrogens.isEmpty())
return org;
// we now update the bonds - we have auxiliary variable remaining that
// bypasses the set membership checks if all suppressed bonds are found
IBond[] cpyBonds = new IBond[nOrgBonds - hydrogens.size()];
int remaining = hydrogens.size();
for (final IBond bond : org.bonds()) {
if (remaining > 0 && (hydrogens.contains(bond.getBegin()) || hydrogens.contains(bond.getEnd()))) {
bondsToHydrogens.add(bond);
remaining--;
continue;
}
cpyBonds[nCpyBonds++] = bond;
}
// same number of bonds otherwise the containers is a strange
if (nCpyBonds != cpyBonds.length)
throw new IllegalArgumentException("number of removed bonds was less than the number of removed hydrogens");
List<IStereoElement> elements = new ArrayList<>();
for (IStereoElement se : org.stereoElements()) {
if (se instanceof ITetrahedralChirality) {
ITetrahedralChirality tc = (ITetrahedralChirality) se;
IAtom focus = tc.getChiralAtom();
IAtom[] neighbors = tc.getLigands();
boolean updated = false;
for (int i = 0; i < neighbors.length; i++) {
if (hydrogens.contains(neighbors[i])) {
neighbors[i] = focus;
updated = true;
}
}
// no changes
if (!updated) {
elements.add(tc);
} else {
TetrahedralChirality e = new TetrahedralChirality(focus, neighbors, tc.getStereo());
e.setGroupInfo(tc.getGroupInfo());
elements.add(e);
}
} else if (se instanceof ExtendedTetrahedral) {
ExtendedTetrahedral tc = (ExtendedTetrahedral) se;
IAtom focus = tc.getFocus();
IAtom[] carriers = tc.getCarriers().toArray(new IAtom[4]);
IAtom[] ends = ExtendedTetrahedral.findTerminalAtoms(org, focus);
boolean updated = false;
for (int i = 0; i < carriers.length; i++) {
if (hydrogens.contains(carriers[i])) {
if (org.getBond(carriers[i], ends[0]) != null)
carriers[i] = ends[0];
else
carriers[i] = ends[1];
updated = true;
}
}
// no changes
if (!updated) {
elements.add(tc);
} else {
elements.add(new ExtendedTetrahedral(focus, carriers, tc.getConfigOrder()));
}
} else if (se instanceof IDoubleBondStereochemistry) {
IDoubleBondStereochemistry db = (IDoubleBondStereochemistry) se;
Conformation conformation = db.getStereo();
IBond orgStereo = db.getStereoBond();
IBond orgLeft = db.getBonds()[0];
IBond orgRight = db.getBonds()[1];
// we use the following variable names to refer to the
// double bond atoms and substituents
// x y
// \ /
// u = v
IAtom u = orgStereo.getBegin();
IAtom v = orgStereo.getEnd();
IAtom x = orgLeft.getOther(u);
IAtom y = orgRight.getOther(v);
// if xNew == x and yNew == y we don't need to find the
// connecting bonds
IAtom xNew = x;
IAtom yNew = y;
if (hydrogens.contains(x)) {
conformation = conformation.invert();
xNew = findSingleBond(org, u, x);
}
if (hydrogens.contains(y)) {
conformation = conformation.invert();
yNew = findSingleBond(org, v, y);
}
// is removed. example [2H]/C=C/[H]
if (x == null || y == null || xNew == null || yNew == null)
continue;
// no changes
if (x.equals(xNew) && y.equals(yNew)) {
elements.add(db);
continue;
}
// XXX: may perform slow operations but works for now
IBond cpyLeft = !Objects.equals(xNew, x) ? org.getBond(u, xNew) : orgLeft;
IBond cpyRight = !Objects.equals(yNew, y) ? org.getBond(v, yNew) : orgRight;
elements.add(new DoubleBondStereochemistry(orgStereo, new IBond[] { cpyLeft, cpyRight }, conformation));
} else if (se instanceof ExtendedCisTrans) {
ExtendedCisTrans db = (ExtendedCisTrans) se;
int config = db.getConfigOrder();
IBond focus = db.getFocus();
IBond orgLeft = db.getCarriers().get(0);
IBond orgRight = db.getCarriers().get(1);
// we use the following variable names to refer to the
// extended double bond atoms and substituents
// x y
// \ /
// u===v
IAtom[] ends = ExtendedCisTrans.findTerminalAtoms(org, focus);
IAtom u = ends[0];
IAtom v = ends[1];
IAtom x = orgLeft.getOther(u);
IAtom y = orgRight.getOther(v);
// if xNew == x and yNew == y we don't need to find the
// connecting bonds
IAtom xNew = x;
IAtom yNew = y;
if (hydrogens.contains(x)) {
config ^= 0x3;
xNew = findSingleBond(org, u, x);
}
if (hydrogens.contains(y)) {
config ^= 0x3;
yNew = findSingleBond(org, v, y);
}
// is removed. example [2H]/C=C/[H]
if (x == null || y == null || xNew == null || yNew == null)
continue;
// no changes
if (x.equals(xNew) && y.equals(yNew)) {
elements.add(db);
continue;
}
// XXX: may perform slow operations but works for now
IBond cpyLeft = !Objects.equals(xNew, x) ? org.getBond(u, xNew) : orgLeft;
IBond cpyRight = !Objects.equals(yNew, y) ? org.getBond(v, yNew) : orgRight;
elements.add(new ExtendedCisTrans(focus, new IBond[] { cpyLeft, cpyRight }, config));
} else if (se instanceof Atropisomeric) {
// can not have any H's
elements.add(se);
}
}
org.setAtoms(Arrays.copyOf(cpyAtoms, nCpyAtoms));
org.setBonds(cpyBonds);
org.setStereoElements(elements);
if (org.getSingleElectronCount() > 0) {
Set<ISingleElectron> remove = new HashSet<>();
for (ISingleElectron se : org.singleElectrons()) {
if (hydrogens.contains(se.getAtom()))
remove.add(se);
}
for (ISingleElectron se : remove) {
org.removeSingleElectron(se);
}
}
if (org.getLonePairCount() > 0) {
Set<ILonePair> remove = new HashSet<>();
for (ILonePair lp : org.lonePairs()) {
if (hydrogens.contains(lp.getAtom()))
remove.add(lp);
}
for (ILonePair lp : remove) {
org.removeLonePair(lp);
}
}
if (sgroups != null) {
for (Sgroup sgroup : sgroups) {
if (sgroup.getValue(SgroupKey.CtabParentAtomList) != null) {
Collection<IAtom> pal = sgroup.getValue(SgroupKey.CtabParentAtomList);
pal.removeAll(hydrogens);
}
for (IAtom hydrogen : hydrogens) sgroup.removeAtom(hydrogen);
for (IBond bondToHydrogen : bondsToHydrogens) sgroup.removeBond(bondToHydrogen);
}
org.setProperty(CDKConstants.CTAB_SGROUPS, sgroups);
}
return org;
}
use of org.openscience.cdk.stereo.ExtendedCisTrans in project cdk by cdk.
the class SmilesParserTest method extendedExtendedCis5.
@Test
public void extendedExtendedCis5() throws Exception {
IAtomContainer mol = load("C/C=C=C=C=C=C\\C");
for (IStereoElement se : mol.stereoElements()) {
if (se instanceof ExtendedCisTrans) {
ExtendedCisTrans ect = (ExtendedCisTrans) se;
assertThat(ect.getConfigOrder(), is(IStereoElement.TOGETHER));
assertThat(ect.getFocus(), is(mol.getBond(3)));
assertThat(ect.getCarriers().get(0), is(mol.getBond(0)));
assertThat(ect.getCarriers().get(1), is(mol.getBond(6)));
}
}
}
use of org.openscience.cdk.stereo.ExtendedCisTrans in project cdk by cdk.
the class SmilesParserTest method extendedExtendedTrans3.
@Test
public void extendedExtendedTrans3() throws Exception {
IAtomContainer mol = load("C/C=C=C=C/C");
for (IStereoElement se : mol.stereoElements()) {
if (se instanceof ExtendedCisTrans) {
ExtendedCisTrans ect = (ExtendedCisTrans) se;
assertThat(ect.getConfigOrder(), is(IStereoElement.OPPOSITE));
assertThat(ect.getFocus(), is(mol.getBond(2)));
assertThat(ect.getCarriers().get(0), is(mol.getBond(0)));
assertThat(ect.getCarriers().get(1), is(mol.getBond(4)));
}
}
}
use of org.openscience.cdk.stereo.ExtendedCisTrans in project cdk by cdk.
the class SmilesParserTest method extendedExtendedCis3.
@Test
public void extendedExtendedCis3() throws Exception {
IAtomContainer mol = load("C/C=C=C=C\\C");
for (IStereoElement se : mol.stereoElements()) {
if (se instanceof ExtendedCisTrans) {
ExtendedCisTrans ect = (ExtendedCisTrans) se;
assertThat(ect.getConfigOrder(), is(IStereoElement.TOGETHER));
assertThat(ect.getFocus(), is(mol.getBond(2)));
assertThat(ect.getCarriers().get(0), is(mol.getBond(0)));
assertThat(ect.getCarriers().get(1), is(mol.getBond(4)));
}
}
}
Aggregations