/** * Recognise the cyclic carbohydrate projections. * * @param projections the types of projections to recognise * @return recognised stereocenters */ List<IStereoElement> recognise(Set<Projection> projections) { if (!projections.contains(Projection.Haworth) && !projections.contains(Projection.Chair)) return Collections.emptyList(); List<IStereoElement> elements = new ArrayList<IStereoElement>(); RingSearch ringSearch = new RingSearch(container, graph); for (int[] isolated : ringSearch.isolated()) { if (isolated.length < 5 || isolated.length > 7) continue; int[] cycle = Arrays.copyOf(GraphUtil.cycle(graph, isolated), isolated.length); Point2d[] points = coordinatesOfCycle(cycle, container); Turn[] turns = turns(points); WoundProjection projection = WoundProjection.ofTurns(turns); if (!projections.contains(projection.projection)) continue; // ring is not aligned correctly for haworth if (projection.projection == Projection.Haworth && !checkHaworthAlignment(points)) continue; final Point2d horizontalXy = horizontalOffset(points, turns, projection.projection); // near vertical, should also flag as potentially ambiguous if (1 - Math.abs(horizontalXy.y) < QUART_CARDINALITY_THRESHOLD) continue; int[] above = cycle.clone(); int[] below = cycle.clone(); if (!assignSubstituents(cycle, above, below, projection, horizontalXy)) continue; elements.addAll(newTetrahedralCenters(cycle, above, below, projection)); } return elements; }
/** * Create a predicate to match components for the provided query and target. The target is * converted to an adjacency list ({@link GraphUtil#toAdjList(IAtomContainer)}) and the query * components extracted from the property {@link #KEY} in the query. * * @param query query structure * @param target target structure */ public ComponentGrouping(IAtomContainer query, IAtomContainer target) { this(query, GraphUtil.toAdjList(target)); }