Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.actelion.research.chem.chemicalspaces.ChemicalSpaceCreator Maven / Gradle / Ivy
package com.actelion.research.chem.chemicalspaces;
import com.actelion.research.chem.*;
import com.actelion.research.chem.chemicalspaces.synthon.SynthonCreator;
import com.actelion.research.chem.chemicalspaces.synthon.SynthonReactor;
import com.actelion.research.chem.descriptor.DescriptorHandlerLongFFP512;
import com.actelion.research.chem.io.DWARFileCreator;
import com.actelion.research.chem.reaction.Reaction;
import com.actelion.research.chem.reaction.Reactor;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.stream.Collectors;
public class ChemicalSpaceCreator {
private File outdirectory;
private Set bbs;
private Map>> bbData;
private List reactions;
private final List functionalizations;
public ChemicalSpaceCreator(Set bbs, List reactions, File outdirectory) {
this.bbs = bbs;
this.reactions = reactions;
this.outdirectory = outdirectory;
this.functionalizations = new ArrayList<>(); //reactions that only consist of modifications ("functionalizations") of one building block are treated specially
for(Reaction rxn : reactions ) {
if(rxn.getReactants()==1)
functionalizations.add(rxn);
}
reactions.removeAll(functionalizations);
}
public void setOutdirectory(File outdirectory) {
this.outdirectory = outdirectory;
}
public void setBBs(Set bbs) {
this.bbs = bbs;
}
public void setBBData(Map>> bbData) {
this.bbData = bbData;
}
public void setReactions(List reactions) {
this.reactions = reactions;
}
public void create() {
Map> allSynthonTransformations = new HashMap>();
generateSynthonTransformations(reactions,allSynthonTransformations);
ConcurrentMap processedToOrigIDCode = new ConcurrentHashMap();
ConcurrentMap>> reactionsWithSynthons = new ConcurrentHashMap>>();
processBuildingBlocks(this.bbs,processedToOrigIDCode,functionalizations);
ConcurrentMap fps = new ConcurrentHashMap<>();
calcFragFPs(processedToOrigIDCode.keySet(), fps);
generateSynthons(reactions, processedToOrigIDCode, reactionsWithSynthons, fps,allSynthonTransformations);
generateCombinatoriaLibraries(reactionsWithSynthons, allSynthonTransformations);
}
private static void calcFragFPs(Collection idcodes, ConcurrentMap fps) {
idcodes.parallelStream().forEach(idc -> {
IDCodeParser parser = new IDCodeParser();
DescriptorHandlerLongFFP512 dhf = new DescriptorHandlerLongFFP512();
StereoMolecule mol = new StereoMolecule();
try {
parser.parse(mol, idc);
long[] desc = dhf.createDescriptor(mol);
fps.put(idc, desc);
}
catch(Exception e) {}
});
}
private static void processBuildingBlocks(Collection bbs, ConcurrentMap processedToOrigIDCode, List functionalizations) {
bbs.parallelStream().forEach( idcode -> {
StereoMolecule mol = new IDCodeParser().getCompactMolecule(idcode);
if (mol != null) {
mol.ensureHelperArrays(Molecule.cHelperCIP);
mol.stripSmallFragments();
mol.normalizeAmbiguousBonds();
if(processedToOrigIDCode.get(mol.getIDCode())!=null)
return;
processedToOrigIDCode.put(mol.getIDCode(), idcode);
for(Reaction functionalization : functionalizations) {
SSSearcher searcher = new SSSearcher();
searcher.setFragment(functionalization.getReactant(0));
searcher.setMolecule(mol);
if (searcher.isFragmentInMolecule()) {
StereoMolecule product = getProduct(functionalization,Arrays.asList(mol));
if(product!=null)
processedToOrigIDCode.put(product.getIDCode(), idcode);
}
}
}
});
}
private static void generateSynthons(List reactions,
ConcurrentMap processedBBToBB,
ConcurrentMap>> reactionsWithSynthons,ConcurrentMap fps,
Map> allSynthonTransformations) {
for(Reaction rxn : reactions) {
processReaction(rxn, processedBBToBB, reactionsWithSynthons, fps, allSynthonTransformations);
}
}
private static void generateSynthonTransformations(List reactions, Map> allSynthonTransformations) {
for(Reaction rxn : reactions) {
List synthonTransformations = new ArrayList<>();
try {
Reaction[] transformations = SynthonCreator.create(rxn);
synthonTransformations = Arrays.asList(transformations);
}
catch(Exception e) {
e.printStackTrace();
}
allSynthonTransformations.put(rxn.getName(), synthonTransformations);
}
}
private static void processReaction(Reaction rxn, ConcurrentMap processedToOrigBB,
ConcurrentMap>> reactionsWithSynthons, ConcurrentMap fps,
Map> synthonTransformations) {
List> reactants = new ArrayList<>();
//System.out.println(rxn);
getReactants(rxn, processedToOrigBB, reactants,fps);
reactionsWithSynthons.putIfAbsent(rxn.getName(), new ArrayList<>());
//System.out.println("bbs");
for(int i=0;i rList = reactants.get(i);
ConcurrentMap synthonList = new ConcurrentHashMap();
reactionsWithSynthons.get(rxn.getName()).add(synthonList);
Reaction synthonTransformation = synthonTransformations.get(rxn.getName()).get(i);
//for(String idcode : rList) {
rList.parallelStream().forEach(idcode -> {
IDCodeParser parser = new IDCodeParser();
StereoMolecule bb = new StereoMolecule();
parser.parse(bb, idcode);
bb.ensureHelperArrays(Molecule.cHelperCIP);
String synthonIDCode = transformToSynthon(synthonTransformation,bb);
String origIDCode = processedToOrigBB.get(idcode);
if(synthonIDCode!=null) {
synthonList.put(synthonIDCode, origIDCode);
}
});
}
}
private static void getReactants(Reaction rxn, ConcurrentMap processedToOrigIDCode,
List> reactants, Map fps) {
SSSearcherWithIndex[] searchers = new SSSearcherWithIndex[rxn.getReactants()];
for(int i=0;i reactantList = Collections.synchronizedList(new ArrayList());
final int ii = i;
processedToOrigIDCode.keySet().stream().forEach(processedIDcode -> {
StereoMolecule mol = new IDCodeParser().getCompactMolecule(processedIDcode);
if (mol != null) {
long[] fp = fps.get(processedIDcode);
if(fp==null)
return;
boolean matchesReaction = matchesReactionRole(rxn, searchers,ii,mol,fp);
if(matchesReaction)
reactantList.add(processedIDcode);
}
});
reactants.add(reactantList);
}
}
private static String transformToSynthon(Reaction synthonTransformation, StereoMolecule bb) {
String synthonIDCode = null;
Reactor reactor = new Reactor(synthonTransformation, Reactor.MODE_RETAIN_COORDINATES
+Reactor.MODE_FULLY_MAP_REACTIONS+Reactor.MODE_REMOVE_DUPLICATE_PRODUCTS+Reactor.MODE_ALLOW_CHARGE_CORRECTIONS, Integer.MAX_VALUE);
bb.ensureHelperArrays(Molecule.cHelperCIP);
reactor.setReactant(0, bb);
String[][] productCodes = reactor.getProductIDCodes();
int productCount = getNormalizedProductsCount(reactor.getProducts());
if(productCount==0 || productCount>1)
return synthonIDCode;
else {
synthonIDCode = productCodes[0][0];
}
return synthonIDCode;
}
private static StereoMolecule getProduct(Reaction rxn, List reactants) {
Reactor reactor = new Reactor(rxn, Reactor.MODE_RETAIN_COORDINATES
+Reactor.MODE_FULLY_MAP_REACTIONS+Reactor.MODE_REMOVE_DUPLICATE_PRODUCTS+Reactor.MODE_ALLOW_CHARGE_CORRECTIONS, Integer.MAX_VALUE);
for(int i=0;i normalizedProducts = new HashSet<>();
for(int i=0;i>> reactionsWithSynthons,
Map> synthonTransformations) {
// iterate over reactions twice (inner loop, outer loop)
// check if synthons from the first reaction match the generic substructure of the second
Map> productsWithSynthons = new HashMap>();
Map> productsWithBBs = new HashMap>();
Map> productsWithReactions = new HashMap>();
Set functionalizations = new HashSet();
for(Reaction rxn : reactions) {
if(rxn.getReactants()==1)
functionalizations.add(rxn);
}
List sizes = new ArrayList<>();
reactions.stream().forEach(reaction -> {
if(reaction.getReactants()<2)
return;
IDCodeParser parser = new IDCodeParser();
CombinatorialLibrary combiLibrary = new CombinatorialLibrary();
combiLibrary.reaction = reaction;
String libraryReaction = reaction.getName();
combiLibrary.bbSynthons = reactionsWithSynthons.get(libraryReaction);
List>>> precursorLibs = new ArrayList<>();
combiLibrary.precursorLibs = precursorLibs;
if(reaction.getReactants()>2) { //no addditional steps for 3-cmpd reactions
combiLibrary.cleanup();
sizes.add(combiLibrary.getSize());
try {
writeCombinatorialLibrary(combiLibrary);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return;
}
SSSearcherWithIndex[] searchers = new SSSearcherWithIndex[reaction.getReactants()];
for(int i=0;i>> precursorLib = new HashMap>>();
precursorLibs.add(precursorLib);
Reaction synthonTransformation = synthonTransformations.get(libraryReaction).get(libReactantID);
StereoMolecule genericProduct = synthonTransformation.getProduct(0);
int offset = 0; //offset is required to correctly mutate connector atoms
for(int a=0;a=92)
offset++;
}
for(Reaction reactionPrec : reactions) { // precursor reaction
if(reactionPrec.getReactants()!=2)
continue;
String precursorReaction = reactionPrec.getName();
for(int reactantID=0;reactantID> libSynthons = new ArrayList<>();
String precursorName = null;
precursorName = precursorReaction + "_" + reactantID;
precursorLib.put(precursorName, libSynthons);
Map dummyReactants = new HashMap();
for(int l=0;l precursorSynthons = new HashMap();
libSynthons.add(precursorSynthons);
}
Map twoConnectorSynthons = libSynthons.get(reactantID);
Map synthons = reactionsWithSynthons.get(precursorReaction).get(reactantID);
for(String synthon : synthons.keySet()) {
StereoMolecule mol = new StereoMolecule();
String bb = synthons.get(synthon);
parser.parse(mol, synthon);
//if (reactionPrec.getReactants() <= reactantID) // to prevent OutOfBoundsExceptions; TLS 25-Mar-2024 in dummyReaction
// continue;
StereoMolecule reactedBB = dummyReaction(bb,reactionPrec,dummyReactants,reactantID);
if(reactedBB==null)
continue;
// we create candidate products by a "dummy reaction" and see if it still matches the substructure query of rxn1
if (matchesReactionRole(reaction, searchers, libReactantID, reactedBB,null)) { // synthon also matches library rxn
mutateConnectorAtoms(mol,offset);
String transformedSynthon = transformToSynthon(synthonTransformation,mol);
if(transformedSynthon!=null)
twoConnectorSynthons.put(transformedSynthon,bb);
}
//now check if a functionalization/deprotection step can lead to additional matches to the library rxn
else {
for(Reaction functionalization : functionalizations) {
if(functionalizations.contains(reactionPrec))
continue; //don't couple two functionalization reactions
SSSearcher ssearcher = new SSSearcher();
ssearcher.setFragment(functionalization.getReactant(0));
ssearcher.setMolecule(reactedBB);
if (ssearcher.isFragmentInMolecule()) {// can be functionalized
StereoMolecule product = getProduct(functionalization,Arrays.asList(reactedBB));
if(product==null)
continue;
else {
if(matchesReactionRole(reaction, searchers,libReactantID, product,null)) { //functionalized BB matches rxn1
//now functionalize synthon BB and create second linker
StereoMolecule prod = getProduct(functionalization,Arrays.asList(mol));
if(prod==null)
continue;
mutateConnectorAtoms(prod,offset);
String transformedSynthon = transformToSynthon(synthonTransformation,prod);
if(!precursorLib.containsKey(precursorName)) {
List> libSynthons2 = new ArrayList<>();
precursorLib.put(precursorName, libSynthons2);
for(int i=0;i precursorSynthons2 = new HashMap();
libSynthons2.add(precursorSynthons2);
}
}
precursorLib.get(precursorName).get(reactantID).put(transformedSynthon, bb);
}
}
}
}
}
}
// if the BB that is used in the precursor step also matches any role of the second reaction, it is excluded (otherwise multiple products may be formed)
for(int j=0;j compatibleSynthons = reactionsWithSynthons.get(precursorReaction).get(j);
Map mutatedSynthons = new HashMap();
for(String s: compatibleSynthons.keySet()) {
StereoMolecule mutatedSynthon = new StereoMolecule();
boolean compatible = true;
parser.parse(mutatedSynthon, s);
for(SSSearcherWithIndex sssearcher : searchers) {
sssearcher.setMolecule(mutatedSynthon,(long[]) null);
if(sssearcher.isFragmentInMolecule())
compatible = false;
}
if(!compatible) //matches also role from second reaction --> don't add to library
continue;
mutateConnectorAtoms(mutatedSynthon,offset);
mutatedSynthons.put(mutatedSynthon.getIDCode(), compatibleSynthons.get(s));
}
libSynthons.get(j).putAll(mutatedSynthons);
}
}
}
}
}
combiLibrary.cleanup();
sizes.add(combiLibrary.getSize());
System.out.println(reaction.getName());
combiLibrary.generateRandomProducts(1000,productsWithSynthons,productsWithBBs,productsWithReactions);
try {
writeCombinatorialLibrary(combiLibrary);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
});
try {
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("space.dwar"), StandardCharsets.UTF_8));
DWARFileCreator creator = new DWARFileCreator(writer);
List synthonColumns = new ArrayList<>();
for(int i=0;i<4;i++) {
synthonColumns.add(creator.addStructureColumn("Synthon" + (i + 1), "IDcode"));
}
List bbColumns = new ArrayList<>();
for(int i=0;i<4;i++) {
bbColumns.add(creator.addStructureColumn("BB" + (i + 1), "IDcode"));
}
List reactionColumns = new ArrayList<>();
for(int i=0;i<3;i++) {
reactionColumns.add(creator.addAlphanumericalColumn("Reaction" + (i + 1)));
}
int structureColumn = creator.addStructureColumn("Product", "IDcode");
creator.writeHeader(-1);
productsWithSynthons.entrySet().stream().forEach(e -> {
creator.setRowStructure(e.getKey(), structureColumn);
List synthons = e.getValue();
for(int i=0;i bbs = productsWithBBs.get(e.getKey());
for(int i=0;i reactions = productsWithReactions.get(e.getKey());
for(int i=0;i e1+e2);
System.out.println("totSize");
System.out.println(size);
}
private static StereoMolecule dummyReaction(String bbIDCode, Reaction rxn, Map reactants, int reactantID){
StereoMolecule product = null;
SSSearcher searcher = new SSSearcher();
searcher.setFragment(rxn.getReactant(reactantID));
StereoMolecule mol = new IDCodeParser().getCompactMolecule(bbIDCode);
if (mol != null) {
searcher.setMolecule(mol);
if (searcher.isFragmentInMolecule()) {
Reactor reactor = new Reactor(rxn, Reactor.MODE_RETAIN_COORDINATES
+Reactor.MODE_FULLY_MAP_REACTIONS+Reactor.MODE_REMOVE_DUPLICATE_PRODUCTS+Reactor.MODE_ALLOW_CHARGE_CORRECTIONS, Integer.MAX_VALUE);
reactor.setReactant(reactantID, mol);
for(int i : reactants.keySet()) {
reactor.setReactant(i, reactants.get(i));
}
StereoMolecule[][] products = reactor.getProducts();
if(products.length == 1 && products[0].length == 1)
product = products[0][0];
}
}
return product;
}
private static void mutateConnectorAtoms(StereoMolecule mol, int offset) {
for(int a=0;a=92) {
atomicNo += offset;
mol.setAtomicNo(a, atomicNo);
}
}
mol.ensureHelperArrays(Molecule.cHelperRings);
}
private void writeCombinatorialLibrary(CombinatorialLibrary combiLib) throws IOException {
File htmcdir = new File(this.outdirectory + "/CombinatorialLibraries/");
htmcdir.mkdir();
File htmcSubDir = new File(htmcdir.getAbsolutePath() + "/" + combiLib.reaction.getName());
htmcSubDir.mkdir();
File dirA = new File(htmcSubDir.getAbsolutePath() + "/A");
dirA.mkdir();
File dirB = new File(htmcSubDir.getAbsolutePath() + "/B");
dirB.mkdir();
File dirC = null;
File dirD = null;
if(combiLib.bbSynthons.size()>2) {
dirC = new File(htmcSubDir.getAbsolutePath() + "/C");
dirC.mkdir();
}
if(combiLib.bbSynthons.size()>3) {
dirD = new File(htmcSubDir.getAbsolutePath() + "/D");
dirD.mkdir();
}
if(combiLib.precursorLibs.size()==2) {
for(int i=0;i> flowSynthons = combiLib.precursorLibs.get(i).get(flowReaction);
int counter=1;
for(Map synthons : flowSynthons) {
if(synthons.isEmpty())
continue;
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(
new FileOutputStream(flowDir + "_" + counter + ".dwar"), StandardCharsets.UTF_8));
DWARFileCreator creator = new DWARFileCreator(writer);
int synthonColumn = creator.addStructureColumn("Synthon", "IDcode");
int structureColumn = creator.addStructureColumn("Building Block", "IDcode");
List fields = new ArrayList<>();
if (bbData != null) {
bbData.values().stream().forEach(e -> {
for (String key : e.keySet()) {
if (!fields.contains(key))
fields.add(key);
}
});
}
List fieldIndexes = new ArrayList<>();
for(String field : fields) {
int columnIndex = creator.addAlphanumericalColumn(field);
fieldIndexes.add(columnIndex);
}
creator.writeHeader(-1);
for(String s : synthons.keySet()) {
String origIDCode = synthons.get(s);
if (bbData != null) {
Map> propertyMap = bbData.get(origIDCode);
for(int j=0;j values = propertyMap.get(field);
if(values!=null) {
values.forEach(e -> sb.append(e).append(";"));
}
creator.setRowValue(sb.toString(), fieldIndexes.get(j));
}
}
creator.setRowStructure(s, synthonColumn);
creator.setRowStructure(origIDCode,structureColumn);
creator.writeCurrentRow();
}
creator.writeEnd();
counter++;
}
}
}
}
int i=0;
for(Map synthons : combiLib.bbSynthons) {
if(synthons.isEmpty())
continue;
File dir = null;
switch(i) {
case 0:
dir = dirA;
break;
case 1:
dir = dirB;
break;
case 2:
dir = dirC;
break;
case 3:
dir = dirD;
break;
default:
break;
}
String outfile = dir + "/" + combiLib.reaction.getName() + ".dwar";
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outfile), StandardCharsets.UTF_8));
DWARFileCreator creator = new DWARFileCreator(writer);
int synthonColumn = creator.addStructureColumn("Synthon", "IDcode");
int structureColumn = creator.addStructureColumn("Building Block", "IDcode");
List fields = new ArrayList<>();
if (bbData != null) {
bbData.values().stream().forEach(e -> {
for (String key : e.keySet()) {
if (!fields.contains(key))
fields.add(key);
}
});
}
List fieldIndeces = new ArrayList<>();
for(String field : fields) {
int columnIndex = creator.addAlphanumericalColumn(field);
fieldIndeces.add(columnIndex);
}
creator.writeHeader(-1);
for(String s : synthons.keySet()) {
String origIDCode = synthons.get(s);
if (bbData != null) {
Map> propertyMap = bbData.get(origIDCode);
for(int j=0;j values = propertyMap.get(field);
if(values!=null) {
values.forEach(e -> sb.append(e + ";"));
}
creator.setRowValue(sb.toString(), fieldIndeces.get(j));
}
}
creator.setRowStructure(s, synthonColumn);
creator.setRowStructure(synthons.get(s),structureColumn);
creator.writeCurrentRow();
}
creator.writeEnd();
i++;
}
}
private static class CombinatorialLibrary {
public Reaction reaction;
public List> bbSynthons;
public List>>> precursorLibs;
List toRemove = new ArrayList<>();
private void cleanup() { //remove precursor reactions with missing synthon sets
for(Map>> precursorLib : precursorLibs) {
for(String reaction : precursorLib.keySet()) {
for(Map synthons : precursorLib.get(reaction)) {
if(synthons==null)
toRemove.add(reaction);
else if(synthons.isEmpty())
toRemove.add(reaction);
}
}
for(String r : toRemove) {
precursorLib.remove(r);
}
toRemove = new ArrayList<>();
}
}
public long getSize() {
long sizeOneStep = 1;
// first calculate size of the single-step space
for(Map synthons : bbSynthons) {
sizeOneStep*=synthons.size();
}
if(precursorLibs.size()==2) {
long reactantsA = bbSynthons.get(0).size();
Map>> precursorLibsA = precursorLibs.get(0);
long reactantsB = bbSynthons.get(1).size();
Map>> precursorLibsB = precursorLibs.get(1);
for(String precReaction : precursorLibsA.keySet()) {
List> precLibA = precursorLibsA.get(precReaction);
int precSize = 1;
for(Map precLib : precLibA) {
precSize*=precLib.size();
}
reactantsA += precSize;
}
for(String precReaction : precursorLibsB.keySet()) {
List> precLibB = precursorLibsB.get(precReaction);
int precSize = 1;
for(Map precLib : precLibB) {
precSize*=precLib.size();
}
reactantsB += precSize;
}
return reactantsA*reactantsB;
}
else
return sizeOneStep;
}
public void generateRandomProducts(int nProducts, Map> productsWithSynthons, Map> productsWithBBs, Map> productsWithReactions ) {
Random rnd = new Random();
IDCodeParser parser = new IDCodeParser();
long max = productsWithSynthons.keySet().size() + Math.min(getSize(), nProducts);
while(productsWithSynthons.keySet().size() synthons = new ArrayList<>();
List bbs = new ArrayList<>();
List reactions = new ArrayList<>();
List preCoupledSynthons = new ArrayList<>();
String precursorName = "";
reactions.add(reaction.getName());
for(int i=0;i>> libs = precursorLibs.get(i);
if(libs.isEmpty() || r==0) { //pick commercial bb
if(bbSynthons.get(i).isEmpty())
return ;
int r2 = rnd.nextInt(bbSynthons.get(i).size());
StereoMolecule mol = new StereoMolecule();
Map s = bbSynthons.get(i);
List keys = new ArrayList<>(s.keySet());
parser.parse(mol, keys.get(r2));
synthons.add(mol);
bbs.add(s.get(keys.get(r2)));
preCoupledSynthons.add(mol);
}
else { //create random virtual bb
//pick random precursor reaction
List precursors = new ArrayList<>();
int reactionNr = rnd.nextInt(libs.keySet().size());
List keys = new ArrayList<>(libs.keySet());
List> lib = libs.get(keys.get(reactionNr));
precursorName = keys.get(reactionNr);
reactions.add(precursorName);
for(Map precursorBBs : lib) {
List keySet2 = new ArrayList<>(precursorBBs.keySet());
int r3 = rnd.nextInt(keySet2.size());
StereoMolecule mol = new StereoMolecule();
parser.parse(mol, keySet2.get(r3));
synthons.add(mol);
bbs.add(precursorBBs.get(keySet2.get(r3)));
precursors.add(mol);
}
try {
preCoupledSynthons.add(SynthonReactor.react(precursors));
}
catch(Exception e) {
e.printStackTrace();
}
}
}
try {
StereoMolecule product = SynthonReactor.react(preCoupledSynthons);
if(product == null || productsWithSynthons.containsKey(product.getIDCode()))
continue;
List bbIDCodes = synthons.stream().map(e -> e.getIDCode()).collect(Collectors.toList());
productsWithSynthons.put(product.getIDCode(),bbIDCodes);
productsWithBBs.put(product.getIDCode(),bbs);
productsWithReactions.put(product.getIDCode(),reactions);
}
catch(Exception e) {
e.printStackTrace();
}
}
}
}
public static boolean matchesReactionRole(Reaction rxn, SSSearcherWithIndex[] searchers, int component, StereoMolecule reactant,
long[] index) {
boolean isMatch = true;
SSSearcherWithIndex searcher = searchers[component];
searcher.setMolecule(reactant,index);
if (searcher.isFragmentInMolecule()) {
//check if reactant also matches other roles in the reaction, if yes, exclude it (to prevent self-polymerization)
for(int j=0;j