List of usage examples for org.apache.commons.collections4 Bag equals
boolean equals(Object o);
From source file:com.act.biointerpretation.Utils.ReactionProjector.java
/** * This function takes as input an array of molecules and a Reactor and outputs the products of the transformation. * The results are returned as a map from orderings of the substrates to the products produced by those orderings. * In most cases the map will have only one entry, but in some cases different orderings of substrates can lead to * different valid predictions.//from ww w .j av a2s. c o m * <p> * Note that, for efficient two substrate expansion, the specialized method * fastProjectionOfTwoSubstrateRoOntoTwoMolecules should be used instead of this one. * * @param mols An array of molecules representing the chemical reactants. * @param reactor A Reactor representing the reaction to apply. * @param maxProducts The maximum number of products to compute before exiting. No limit is imposed for max values * of null or 0. * @return The substrate -> product map. */ public Map<Molecule[], List<Molecule[]>> getRoProjectionMap(Molecule[] mols, Reactor reactor, Integer maxProducts) throws ReactionException, IOException { Map<Molecule[], List<Molecule[]>> resultsMap = new HashMap<>(); if (mols.length != reactor.getReactantCount()) { LOGGER.debug("Tried to project RO with %d substrates on set of %d substrates", reactor.getReactantCount(), mols.length); return resultsMap; } // If there is only one reactant, we can do just a simple reaction computation. However, if we have multiple reactants, // we have to use the ConcurrentReactorProcessor API since it gives us the ability to combinatorially explore all // possible matching combinations of reactants on the substrates of the RO. if (mols.length == 1) { List<Molecule[]> productSets = getProductsFixedOrder(reactor, mols, maxProducts); if (!productSets.isEmpty()) { resultsMap.put(mols, productSets); } } else if (useSubstructureFiltering) { Optional<List<Set<Integer>>> viableSubstrateIndexes; try { viableSubstrateIndexes = matchCandidatesToSubstrateStructures(reactor, mols); } catch (SearchException e) { throw new ReactionException("Caught exception when performing pre-reaction substructure search", e); } if (viableSubstrateIndexes.isPresent()) { List<Integer> allIndexes = new ArrayList<Integer>(mols.length) { { for (int i = 0; i < mols.length; i++) { add(i); } } }; int permutationIndex = 0; PermutationIterator<Integer> iter = new PermutationIterator<>(allIndexes); while (iter.hasNext()) { permutationIndex++; List<Integer> permutation = iter.next(); if (permutationFitsSubstructureMatches(permutation, viableSubstrateIndexes.get())) { Molecule[] substrates = indexPermutationToMolecules(mols, permutation); reactor.setReactants(substrates); Molecule[] products; List<Molecule[]> results = new ArrayList<>(); while ((products = reactor.react()) != null) { results.add(products); if (maxProducts != null && maxProducts > 0 && results.size() >= maxProducts) { break; } } if (results.size() > 0) { resultsMap.put(substrates, results); } } } } // Otherwise just return the empty map. } else { // TODO: why not make one of these per ReactionProjector object? // TODO: replace this with Apache commons PermutationIterator for clean iteration over distinct permutations. ConcurrentReactorProcessor reactorProcessor = new ConcurrentReactorProcessor(); reactorProcessor.setReactor(reactor); // This step is needed by ConcurrentReactorProcessor for the combinatorial exploration. // The iterator takes in the same substrates in each iteration step to build a matrix of combinations. // For example, if we have A + B -> C, the iterator creates this array: [[A,B], [A,B]]. Based on this, // ConcurrentReactorProcessor will cross the elements in the first index with the second, creating the combinations // A+A, A+B, B+A, B+B and operates all of those on the RO, which is what is desired. MoleculeIterator[] iterator = new MoleculeIterator[mols.length]; for (int i = 0; i < mols.length; i++) { iterator[i] = MoleculeIteratorFactory.createMoleculeIterator(mols); } reactorProcessor.setReactantIterators(iterator, ConcurrentReactorProcessor.MODE_COMBINATORIAL); // Bag is a multi-set class that ships with Apache commons collection, and we already use many commons libs--easy! Bag<Molecule> originalReactantsSet = new HashBag<>(Arrays.asList(mols)); // This set keeps track of substrate combinations we've used, and avoids repeats. Repeats can occur // when several substrates are identical, and can be put in "different" but symmetric orderings. Set<String> substrateHashes = new HashSet<>(); List<Molecule[]> results = null; int reactantCombination = 0; while ((results = reactorProcessor.reactNext()) != null) { reactantCombination++; Molecule[] reactants = reactorProcessor.getReactants(); if (results.isEmpty()) { LOGGER.debug("No results found for reactants combination %d, skipping", reactantCombination); continue; } Bag<Molecule> thisReactantSet = new HashBag<>(Arrays.asList(reactants)); if (!originalReactantsSet.equals(thisReactantSet)) { LOGGER.debug("Reactant set %d does not represent original, complete reactant sets, skipping", reactantCombination); continue; } String thisHash = getStringHash(reactants); if (substrateHashes.contains(thisHash)) { continue; } substrateHashes.add(thisHash); resultsMap.put(reactants, results); if (maxProducts != null && maxProducts > 0 && resultsMap.size() >= maxProducts) { break; } } } return resultsMap; }