├── README.md ├── build.gradle ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── settings.gradle └── src └── main ├── java └── com │ └── idorsia │ └── research │ └── chem │ └── phesa │ ├── App.java │ ├── PheSADescGenerationMulticore.java │ ├── PheSAFlexTest.java │ ├── PheSAScreenMulticore.java │ ├── PheSATest.java │ ├── ShapeDockingTest.java │ └── Utils.java └── resources ├── astex_1n46_ligand.mol ├── astex_1n46_protein.mol2 ├── bace_crystal_ligand.mol2 ├── chembl_random.txt ├── dude_bace1_actives_final.dwar └── dude_bace1_crystal_ligand.dwar /README.md: -------------------------------------------------------------------------------- 1 | Examples that showcase the usage of PheSA for shape-based docking (negative receptor image) and PheSA screening (flexible and rigid) 2 | 3 | We use gradle as a build management tool. 4 | 5 | The examples can be run by using gradle: 6 | 7 | ``` 8 | ./gradlew run 9 | ``` 10 | 11 | In the main method App.java all examples that will be run are listed. Depending on your needs, you can comment out or delete certain examples. 12 | 13 | The concepts are explained briefly 14 | 15 | Dependencies: PheSA is part of the OpenChemLib https://github.com/Actelion/openchemlib 16 | 17 | ## Ligand-based PheSA for molecular alignments and virtual screening 18 | 19 | PheSA is implemented as a descriptor in the OpenChemLib and requires first a descriptor generation step using a DescriptorHandler. 20 | There are two DescriptorHandlers for two different purposes: A) generating a PheSA descriptor from a single, bioactive 3D query conformation 21 | and B) generating a descriptor for a candidate molecule, where first a conformer ensemble is generated by the OpenChemLib. 22 | 23 | For case A, the ```DescriptorHandlerShapeOneConf``` has to be used, whereas ```StereoMolecule nativeLigandPose```requires 3D coordinates to be present. 24 | StereoMolecules are usually obtained by parsing an SD-File, SMILES Text File, Molfile or a DWAR File. If 3D coordinates are specifiecd in the field, 25 | they will be parsed per default. 26 | 27 | ``` 28 | DescriptorHandlerShapeOneConf dhsSC = new DescriptorHandlerShapeOneConf(); 29 | PheSAMolecule queryShape = dhs.createDescriptor(nativeLigandPose); 30 | ``` 31 | 32 | whereas for case B, ```DescriptorHandlerShape``` is used and ```StereoMolecule candidateMol```does not require the presence of 3D Coordinate. 33 | 34 | ``` 35 | DescriptorHandlerShape dhs = new DescriptorHandlerShape(); 36 | PheSAMolecule candidateShape = dhs.createDescriptor(candidateMol); 37 | ``` 38 | 39 | The descriptor generation step from ```DescriptorHandlerShape``` by default creates a maximum of 200 conformers. This can be adjusted via the constructor: 40 | 41 | ```DescriptorHandlerShape(int maxConfs,double ppWeight)``` where the number of conformers and the pharmacophore weight for the similarity calculation can be adjusted. 42 | 43 | After creating the PheSA descriptors (instances of ```PheSAMolecule```) the similarity and the optimal 3D alignment can be calculated: 44 | ``` 45 | double sim = dhs.getSimilarity(queryShape, candidateShape); 46 | StereoMolecule[] previousAlignment = dhs.getPreviousAlignment(); 47 | StereoMolecule referenceMol = previousAlignment[0]; 48 | StereoMolecule candidateMol = previousAlignment[1] 49 | ``` 50 | referenceMol and candidateMol can be written to SD-Files as demonstrated in the examples and visualized in any chemistry visualization program supporting .sdf imports. 51 | 52 | For using flexible refinement of the alignments, PheSAFlex can be activated via: 53 | 54 | ``` 55 | dhs.setFlexible(true) 56 | ``` 57 | 58 | Further control over the PheSA parameters and settings can be exerted via the ```PheSASetting```class, where for example the triangle alignments can be turned off 59 | for faster performance: 60 | 61 | ``` 62 | PheSASetting setting = new PheSASetting(); 63 | setting.setUseTriangle(false); 64 | ``` 65 | Examples on how to use PheSA and PheSAFlex are provided in the classes ```PheSATest``` and ```PheSAFlexTest```. 66 | 67 | ## Negative Binding Site Images 68 | 69 | To create shape and pharmacophore representation of the receptor binding site, we rely on the ```NegativeReceptorImageCreator```class: 70 | 71 | ``` 72 | TransformationSequence transform = new TransformationSequence(); 73 | ShapeVolume bsVolume = NegativeReceptorImageCreator.create(nativeLigandPose, receptor,transform); 74 | ShapeDocking shapeDocking = new ShapeDocking(bsVolume,transform); 75 | ``` 76 | 77 | nativeLigandPose and receptor are of type ```StereoMolecule``` and rely on the presence of 3D coordinates. The TransformationSequence can be used to later transform the coordinates 78 | of the docked ligand for visual inspection with respect to the protein structure. This step is necessary since the created ```ShapeVolume```is centered at the origin of the coordinate 79 | system. 80 | A candidate molecule (no 3D coordinates required) can then aligned to the receptor image: 81 | 82 | ``` 83 | shapeDocking.dock(toDock) 84 | ``` 85 | 86 | Which return a List of aligned StereoMolecules sorted by decreasing score. ```ShapeDockingTest```demonstrates how to use the shape-based docking. 87 | 88 | 89 | ## Starting an own Virtual Screening Campaign 90 | 91 | Since the most expensive step in the PheSA workflow is to create the conformers of the screening library, it can save computational resources to precalculate them 92 | and store them into a file, so that they can be reused again for subsequent screenings. The PheSA DescriptorHandler contains methods to encode and decode instances of ```PheSAMolecule```. Which is a full representation of shape and 93 | pharmacophore of a conformational ensemble (if ```DescriptorHandlerShape```was used as opposed to ```DescriptorHandlerShapeOneConf```). 94 | 95 | ``` 96 | DescriptorHandlerShape dhs = new DescriptorHandlerShape(); 97 | PheSAMolecule candidateShape = dhs.createDescriptor(candidateMol); 98 | String encodedShape = dhs.encode(candidateShape); 99 | candidateShape = dhs.decode(encodedShape); 100 | ``` 101 | ### Parallelization of the calculation 102 | 103 | The exeuction of both PheSA descriptor generation and PheSA similarity calculation can be dramatically speeded up by using Java Multithreading. 104 | The ```DescriptorHandlerShape```is not thread-safe, so every thread requires it's own copy of this class. 105 | 106 | Vast libraries can be screened with low-memory consumption using Java's Stream API. The examples ```PheSADescGenerationMulticore``` 107 | and ```PheSAScreenMulticore``` demonstrate how to 1) precalculate PheSA descriptors of 100'000 SMILES strings and persist them in a file 108 | and 2) run a subsequent screening and write the best results (similarities, 3D alignments) to an SD-File. 109 | 110 | 111 | 112 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | // Apply the java-library plugin to add support for Java Library 3 | id 'java' 4 | id 'eclipse' 5 | id 'application' 6 | 7 | } 8 | 9 | def thisVersion = '0.0.1'; 10 | 11 | sourceCompatibility = 1.11 12 | targetCompatibility = 1.11 13 | 14 | repositories { 15 | mavenCentral() 16 | } 17 | 18 | application { 19 | mainClassName = 'com.idorsia.research.chem.phesa.App' 20 | } 21 | 22 | dependencies { 23 | implementation 'com.actelion.research:openchemlib:2024.4.2' 24 | } 25 | 26 | configurations.all { 27 | resolutionStrategy.cacheChangingModulesFor 0, 'seconds' 28 | resolutionStrategy.cacheDynamicVersionsFor 0, 'seconds' 29 | } 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joewah/PheSAExamples/8eebc55c487eebaf757458b6f6ada8aa849dc559/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Attempt to set APP_HOME 10 | # Resolve links: $0 may be a link 11 | PRG="$0" 12 | # Need this for relative symlinks. 13 | while [ -h "$PRG" ] ; do 14 | ls=`ls -ld "$PRG"` 15 | link=`expr "$ls" : '.*-> \(.*\)$'` 16 | if expr "$link" : '/.*' > /dev/null; then 17 | PRG="$link" 18 | else 19 | PRG=`dirname "$PRG"`"/$link" 20 | fi 21 | done 22 | SAVED="`pwd`" 23 | cd "`dirname \"$PRG\"`/" >/dev/null 24 | APP_HOME="`pwd -P`" 25 | cd "$SAVED" >/dev/null 26 | 27 | APP_NAME="Gradle" 28 | APP_BASE_NAME=`basename "$0"` 29 | 30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 31 | DEFAULT_JVM_OPTS="" 32 | 33 | # Use the maximum available, or set MAX_FD != -1 to use that value. 34 | MAX_FD="maximum" 35 | 36 | warn () { 37 | echo "$*" 38 | } 39 | 40 | die () { 41 | echo 42 | echo "$*" 43 | echo 44 | exit 1 45 | } 46 | 47 | # OS specific support (must be 'true' or 'false'). 48 | cygwin=false 49 | msys=false 50 | darwin=false 51 | nonstop=false 52 | case "`uname`" in 53 | CYGWIN* ) 54 | cygwin=true 55 | ;; 56 | Darwin* ) 57 | darwin=true 58 | ;; 59 | MINGW* ) 60 | msys=true 61 | ;; 62 | NONSTOP* ) 63 | nonstop=true 64 | ;; 65 | esac 66 | 67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 68 | 69 | # Determine the Java command to use to start the JVM. 70 | if [ -n "$JAVA_HOME" ] ; then 71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 72 | # IBM's JDK on AIX uses strange locations for the executables 73 | JAVACMD="$JAVA_HOME/jre/sh/java" 74 | else 75 | JAVACMD="$JAVA_HOME/bin/java" 76 | fi 77 | if [ ! -x "$JAVACMD" ] ; then 78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 79 | 80 | Please set the JAVA_HOME variable in your environment to match the 81 | location of your Java installation." 82 | fi 83 | else 84 | JAVACMD="java" 85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 86 | 87 | Please set the JAVA_HOME variable in your environment to match the 88 | location of your Java installation." 89 | fi 90 | 91 | # Increase the maximum file descriptors if we can. 92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 93 | MAX_FD_LIMIT=`ulimit -H -n` 94 | if [ $? -eq 0 ] ; then 95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 96 | MAX_FD="$MAX_FD_LIMIT" 97 | fi 98 | ulimit -n $MAX_FD 99 | if [ $? -ne 0 ] ; then 100 | warn "Could not set maximum file descriptor limit: $MAX_FD" 101 | fi 102 | else 103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 104 | fi 105 | fi 106 | 107 | # For Darwin, add options to specify how the application appears in the dock 108 | if $darwin; then 109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 110 | fi 111 | 112 | # For Cygwin, switch paths to Windows format before running java 113 | if $cygwin ; then 114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 116 | JAVACMD=`cygpath --unix "$JAVACMD"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Escape application args 158 | save () { 159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 160 | echo " " 161 | } 162 | APP_ARGS=$(save "$@") 163 | 164 | # Collect all arguments for the java command, following the shell quoting and substitution rules 165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 166 | 167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong 168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then 169 | cd "$(dirname "$0")" 170 | fi 171 | 172 | exec "$JAVACMD" "$@" 173 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * This file was generated by the Gradle 'init' task. 3 | * 4 | * The settings file is used to specify which projects to include in your build. 5 | * 6 | * Detailed information about configuring a multi-project build in Gradle can be found 7 | * in the user guide at https://docs.gradle.org/4.8.1/userguide/multi_project_builds.html 8 | */ 9 | 10 | rootProject.name = 'PheSAExamples' 11 | -------------------------------------------------------------------------------- /src/main/java/com/idorsia/research/chem/phesa/App.java: -------------------------------------------------------------------------------- 1 | package com.idorsia.research.chem.phesa; 2 | 3 | /** 4 | * entrypoint to run the test calculations. Tasks that should be omitted are commented out 5 | */ 6 | public class App { 7 | 8 | public static void main(String[] args) { 9 | try { 10 | //ShapeDockingTest.dock(); 11 | //PheSATest.align(); 12 | //PheSAFlexTest.align(); 13 | //new PheSADescGenerationMulticore().genDescs(); 14 | new PheSAScreenMulticore().screenLib(); 15 | } catch (Exception e) { 16 | // TODO Auto-generated catch block 17 | e.printStackTrace(); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/idorsia/research/chem/phesa/PheSADescGenerationMulticore.java: -------------------------------------------------------------------------------- 1 | package com.idorsia.research.chem.phesa; 2 | 3 | import java.io.BufferedWriter; 4 | import java.io.File; 5 | import java.io.FileNotFoundException; 6 | import java.io.FileOutputStream; 7 | import java.io.IOException; 8 | import java.io.OutputStreamWriter; 9 | import java.io.UnsupportedEncodingException; 10 | import java.net.URISyntaxException; 11 | import java.nio.file.Files; 12 | import java.nio.file.Path; 13 | import java.util.ArrayList; 14 | import java.util.List; 15 | import java.util.Objects; 16 | import java.util.concurrent.BlockingQueue; 17 | import java.util.concurrent.LinkedBlockingQueue; 18 | import java.util.concurrent.atomic.AtomicInteger; 19 | import java.util.function.Consumer; 20 | import java.util.function.Function; 21 | import java.util.stream.Stream; 22 | 23 | import com.actelion.research.chem.MolfileCreator; 24 | import com.actelion.research.chem.SmilesParser; 25 | import com.actelion.research.chem.StereoMolecule; 26 | import com.actelion.research.chem.io.DWARFileParser; 27 | import com.actelion.research.chem.phesa.DescriptorHandlerShape; 28 | import com.actelion.research.chem.phesa.DescriptorHandlerShapeOneConf; 29 | import com.actelion.research.chem.phesa.PheSAMolecule; 30 | 31 | /** 32 | * Multithreaded descriptor generation: A File of SMILES is streamed into a 33 | * pipeline of 1) parsing SMILES into StereMolecules 2) Descriptor Calculation (involves conformer generation) 34 | * 3) writing the descriptors into a file 35 | * usage of Stream.parallel() leads to multihreaded data processing 36 | * to not slow down the writing, this step is done by a single thread fetching result from a queue 37 | */ 38 | public class PheSADescGenerationMulticore { 39 | 40 | static AtomicInteger count = new AtomicInteger(); 41 | private BlockingQueue queue; 42 | 43 | public void genDescs() throws URISyntaxException, IOException { 44 | 45 | 46 | Stream smilesStream = Files.lines(Path.of(PheSATest.class.getClassLoader().getResource("chembl_random.txt").toURI())); 47 | 48 | DescriptorWriter writer = new DescriptorWriter("descriptors.txt"); 49 | DescriptorGenerator generator = new DescriptorGenerator(); 50 | smilesStream.parallel().map(e -> { //parallel parsing in the first and parallel descriptor generation in 2nd map step 51 | StereoMolecule mol = new StereoMolecule(); 52 | try { 53 | new SmilesParser().parse(mol, e); 54 | } catch (Exception e2) { 55 | // TODO Auto-generated catch block 56 | e2.printStackTrace(); 57 | return null; 58 | } 59 | return mol; 60 | }).filter(Objects::nonNull).map(e -> generator.apply(e)).forEach(e -> writer.accept(e)); 61 | 62 | writer.finalizeWrite(); 63 | 64 | 65 | 66 | 67 | } 68 | 69 | /** 70 | * writer class that buffers incoming descriptors into a queue and writes them to disc 71 | * this step is executed in a single thread 72 | */ 73 | public static class DescriptorWriter implements Consumer { 74 | 75 | private BufferedWriter writer; 76 | private DescriptorHandlerShape dhs; 77 | private BlockingQueue queue; 78 | private volatile boolean running; 79 | 80 | public DescriptorWriter(String filePath) { 81 | dhs = new DescriptorHandlerShape(); 82 | queue = new LinkedBlockingQueue<>(); 83 | running = true; 84 | try { 85 | writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(filePath), "utf-8")); 86 | } catch (UnsupportedEncodingException | FileNotFoundException e) { 87 | e.printStackTrace(); 88 | } 89 | new Thread(this::writeFromQueue).start(); 90 | } 91 | 92 | private void writeFromQueue() { 93 | try { 94 | while (running || !queue.isEmpty()) { 95 | PheSAMolecule molecule = queue.poll(); 96 | if (molecule != null) { 97 | writer.write(dhs.encode(molecule)); 98 | writer.write(System.lineSeparator()); 99 | } 100 | } 101 | } catch (IOException e) { 102 | e.printStackTrace(); 103 | } finally { 104 | try { 105 | writer.close(); 106 | } catch (IOException e) { 107 | e.printStackTrace(); 108 | } 109 | } 110 | } 111 | 112 | public void finalizeWrite() { 113 | running = false; 114 | } 115 | 116 | @Override 117 | public void accept(PheSAMolecule t) { 118 | queue.add(t); 119 | } 120 | } 121 | 122 | /** 123 | * Helper class to generate descriptors from StereoMolecules, used by the parallel stream in the mapping step 124 | * of the pipeline to map StereoMolecules to PheSAMolecules (PheSA descriptors) 125 | */ 126 | public static class DescriptorGenerator implements Function { 127 | 128 | private DescriptorHandlerShape dhs; 129 | 130 | public DescriptorGenerator() { 131 | //50 conformers 132 | dhs = new DescriptorHandlerShape(50, 0.5); 133 | } 134 | 135 | @Override 136 | public PheSAMolecule apply(StereoMolecule t) { 137 | PheSAMolecule desc= dhs.createDescriptor(t); 138 | return desc; 139 | 140 | } 141 | 142 | } 143 | 144 | } 145 | -------------------------------------------------------------------------------- /src/main/java/com/idorsia/research/chem/phesa/PheSAFlexTest.java: -------------------------------------------------------------------------------- 1 | package com.idorsia.research.chem.phesa; 2 | 3 | import java.io.BufferedWriter; 4 | import java.io.File; 5 | import java.io.FileNotFoundException; 6 | import java.io.FileOutputStream; 7 | import java.io.IOException; 8 | import java.io.OutputStreamWriter; 9 | import java.io.UnsupportedEncodingException; 10 | import java.net.URISyntaxException; 11 | import java.util.ArrayList; 12 | import java.util.List; 13 | 14 | import com.actelion.research.chem.MolfileCreator; 15 | import com.actelion.research.chem.StereoMolecule; 16 | import com.actelion.research.chem.io.DWARFileParser; 17 | import com.actelion.research.chem.phesa.DescriptorHandlerShape; 18 | import com.actelion.research.chem.phesa.DescriptorHandlerShapeOneConf; 19 | import com.actelion.research.chem.phesa.PheSAMolecule; 20 | 21 | 22 | /** 23 | * same as PheSATest, but dhs.setFlexible is set to true to enable flexible refinements 24 | */ 25 | public class PheSAFlexTest { 26 | 27 | public static void align() throws URISyntaxException, UnsupportedEncodingException, FileNotFoundException, IOException { 28 | File queryFile = new File(PheSATest.class.getClassLoader().getResource("dude_bace1_crystal_ligand.dwar").toURI()); 29 | File libFile = new File(PheSATest.class.getClassLoader().getResource("dude_bace1_actives_final.dwar").toURI()); 30 | DWARFileParser queryParser = new DWARFileParser(queryFile); 31 | queryParser.next(); 32 | StereoMolecule query = queryParser.getMolecule(); 33 | DWARFileParser libParser = new DWARFileParser(libFile); 34 | //DescriptorHandlerOneConf should be used for the query molecule, so that the 35 | //input 3D coordinates are taken and no coordinates are generated 36 | DescriptorHandlerShapeOneConf dhsOC = new DescriptorHandlerShapeOneConf(); 37 | DescriptorHandlerShape dhs = new DescriptorHandlerShape(); 38 | PheSAMolecule refVol = dhsOC.createDescriptor(query); 39 | PheSAMolecule refVolConfGen = dhs.createDescriptor(query); 40 | double sim = dhs.getSimilarity(refVol, refVolConfGen); 41 | System.out.println(sim); 42 | StereoMolecule[] previousAlignment = dhs.getPreviousAlignment(); 43 | List alignedMols = new ArrayList<>(); 44 | alignedMols.add(previousAlignment[0]); 45 | alignedMols.add(previousAlignment[1]); 46 | int maxComparisons = 50; 47 | int comparisons = 0; 48 | dhs.setFlexible(true); //use PheSAFlex! 49 | while(libParser.next()) { 50 | if(comparisons>maxComparisons) 51 | break; 52 | StereoMolecule libMol = libParser.getMolecule(); 53 | PheSAMolecule libVol = dhs.createDescriptor(libMol); 54 | sim = dhs.getSimilarity(refVol, libVol); 55 | System.out.println(sim); 56 | //getPreviousAlignment returns the query and candidate molecule in optimal alignment, it 57 | //they are returned in an array with length 2 58 | previousAlignment = dhs.getPreviousAlignment(); 59 | alignedMols.add(previousAlignment[1]); 60 | comparisons++; 61 | } 62 | 63 | 64 | try(BufferedWriter structureWriter = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("aligned_flex.sdf"), "utf-8"))){ 65 | for(StereoMolecule optimized: alignedMols) { 66 | MolfileCreator mfc = new MolfileCreator(optimized,false); 67 | mfc.writeMolfile(structureWriter); 68 | structureWriter.write(" \n" ); 69 | structureWriter.write("$$$$ \n" ); 70 | } 71 | 72 | } 73 | 74 | 75 | } 76 | } -------------------------------------------------------------------------------- /src/main/java/com/idorsia/research/chem/phesa/PheSAScreenMulticore.java: -------------------------------------------------------------------------------- 1 | package com.idorsia.research.chem.phesa; 2 | 3 | import java.io.BufferedWriter; 4 | import java.io.File; 5 | import java.io.FileNotFoundException; 6 | import java.io.FileOutputStream; 7 | import java.io.FileWriter; 8 | import java.io.IOException; 9 | import java.io.OutputStreamWriter; 10 | import java.io.UnsupportedEncodingException; 11 | import java.net.URISyntaxException; 12 | import java.nio.file.Files; 13 | import java.nio.file.Paths; 14 | import java.util.concurrent.atomic.AtomicInteger; 15 | import java.util.function.Consumer; 16 | import java.util.function.Function; 17 | 18 | import com.actelion.research.chem.MolfileCreator; 19 | import com.actelion.research.chem.StereoMolecule; 20 | import com.actelion.research.chem.alignment3d.PheSAAlignmentOptimizer.PheSASetting; 21 | import com.actelion.research.chem.io.DWARFileParser; 22 | import com.actelion.research.chem.io.Mol2FileParser; 23 | import com.actelion.research.chem.phesa.DescriptorHandlerShape; 24 | import com.actelion.research.chem.phesa.DescriptorHandlerShapeOneConf; 25 | import com.actelion.research.chem.phesa.PheSAMolecule; 26 | 27 | /** 28 | * Showcases a parallel virtual screening pipeline: encoded descriptors are streamed into a pipeline of 29 | * 1) descriptor decoding into PheSAMolecules 2) result calculation (similarity + alignment) and 3) writing 30 | * the best results to a SD-file 31 | * using Stream.parallel() leads to multithreaded PheSA calculation 32 | */ 33 | public class PheSAScreenMulticore { 34 | 35 | private BufferedWriter writer; 36 | static AtomicInteger atomicInt = new AtomicInteger(); 37 | 38 | public PheSAScreenMulticore() throws UnsupportedEncodingException, FileNotFoundException { 39 | writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("results.sdf"), "utf-8")); 40 | } 41 | 42 | public void screenLib() { 43 | double simCutoff = 0.4; 44 | 45 | StereoMolecule queryMol = parseLigand("bace_crystal_ligand.mol2"); 46 | PheSAMolecule query = new DescriptorHandlerShapeOneConf().createDescriptor(queryMol); 47 | DescriptorHandlerShape dh = new DescriptorHandlerShape(); 48 | //align confs of query molecule to generated conformers 49 | System.out.println(dh.getSimilarity(query, dh.createDescriptor(queryMol))); 50 | 51 | try { 52 | Utils.writeMoleculeRecord(writer,dh.getPreviousAlignment()[0]); 53 | writer.write("$$$$ \n" ); 54 | } catch (IOException e) { 55 | // TODO Auto-generated catch block 56 | e.printStackTrace(); 57 | } 58 | String filePath = "descriptors.txt"; 59 | PheSASetting setting = new PheSASetting(); 60 | //turn off triangles for faster screening 61 | setting.setUseTriangle(false); 62 | PheSAWriter pheSAwriter = new PheSAWriter(writer); 63 | PheSAScreener screener = new PheSAScreener(setting,query); 64 | DescriptorHandlerShape dhs = new DescriptorHandlerShape(); 65 | try { 66 | Files.lines(Paths.get(filePath)).map(str -> dhs.decode(str)).parallel() 67 | .map(candidate -> screener.apply(candidate)).filter(e -> e.similarity>simCutoff).forEach(result -> pheSAwriter.writeResult(result)); 68 | } catch (IOException e) { 69 | // TODO Auto-generated catch block 70 | e.printStackTrace(); 71 | } 72 | System.out.println("screened" + atomicInt.get()); 73 | 74 | } 75 | 76 | public StereoMolecule parseLigand(String ligfile) { 77 | StereoMolecule lig = new StereoMolecule(); 78 | Mol2FileParser m2fp = new Mol2FileParser(); 79 | try { 80 | lig = m2fp.load(new File(ShapeDockingTest.class.getClassLoader().getResource(ligfile).toURI())); 81 | } catch (Exception e) { 82 | // TODO Auto-generated catch block 83 | e.printStackTrace(); 84 | } 85 | return lig; 86 | } 87 | 88 | 89 | public static class PheSAWriter { 90 | private final String delim = System.getProperty("line.separator"); 91 | private BufferedWriter writer; 92 | 93 | public PheSAWriter(BufferedWriter writer) { 94 | this.writer = writer; 95 | } 96 | 97 | public void writeResult(PheSAResult result) { 98 | try { 99 | Utils.writeMoleculeRecord(writer, result.candidate); 100 | writeField("similarity", Double.toString(result.similarity)); 101 | writer.write("$$$$"); 102 | writer.write(delim); 103 | writer.flush(); 104 | } catch (IOException e) { 105 | // TODO Auto-generated catch block 106 | e.printStackTrace(); 107 | } 108 | 109 | } 110 | 111 | private void writeField(String name, String value) throws IOException { 112 | String delim = System.getProperty("line.separator"); 113 | writer.write("> <" + name + ">"); 114 | writer.write(delim); 115 | writer.write(value); 116 | writer.write(delim); 117 | writer.write(delim); 118 | } 119 | 120 | } 121 | 122 | /** 123 | * Screener class used in the map step to convert an input PheSADescriptor into a PheSAResult 124 | * containing the similarity and the aligned molecule 125 | */ 126 | public static class PheSAScreener implements Function { 127 | 128 | private PheSASetting setting; 129 | private PheSAMolecule query; 130 | 131 | public PheSAScreener(PheSASetting setting, PheSAMolecule query) { 132 | this.setting = setting; 133 | this.query = query; 134 | } 135 | 136 | 137 | @Override 138 | public PheSAResult apply(PheSAMolecule candidate) { 139 | atomicInt.getAndIncrement(); 140 | DescriptorHandlerShape dhs = new DescriptorHandlerShape(); 141 | dhs.setPhesaSetting(setting); 142 | PheSAResult result = new PheSAResult(); 143 | try { 144 | result.similarity = dhs.getSimilarity(query,candidate); 145 | 146 | result.reference = dhs.getPreviousAlignment()[0]; 147 | result.candidate = dhs.getPreviousAlignment()[1]; 148 | } 149 | catch(Exception e) { 150 | System.err.println("could not align molecule"); 151 | } 152 | return result; 153 | } 154 | 155 | } 156 | 157 | 158 | public static class PheSAResult { 159 | double similarity; 160 | StereoMolecule reference; 161 | StereoMolecule candidate; 162 | } 163 | } 164 | -------------------------------------------------------------------------------- /src/main/java/com/idorsia/research/chem/phesa/PheSATest.java: -------------------------------------------------------------------------------- 1 | package com.idorsia.research.chem.phesa; 2 | 3 | import java.io.BufferedWriter; 4 | import java.io.File; 5 | import java.io.FileNotFoundException; 6 | import java.io.FileOutputStream; 7 | import java.io.IOException; 8 | import java.io.OutputStreamWriter; 9 | import java.io.UnsupportedEncodingException; 10 | import java.net.URISyntaxException; 11 | import java.util.ArrayList; 12 | import java.util.List; 13 | 14 | import com.actelion.research.chem.MolfileCreator; 15 | import com.actelion.research.chem.StereoMolecule; 16 | import com.actelion.research.chem.io.DWARFileParser; 17 | import com.actelion.research.chem.phesa.DescriptorHandlerShape; 18 | import com.actelion.research.chem.phesa.DescriptorHandlerShapeOneConf; 19 | import com.actelion.research.chem.phesa.PheSAMolecule; 20 | 21 | public class PheSATest { 22 | 23 | /** 24 | * parses a DWAR File with a 3D bioactive conformation and aligns a set of molecules on it 25 | */ 26 | public static void align() throws URISyntaxException, UnsupportedEncodingException, FileNotFoundException, IOException { 27 | File queryFile = new File(PheSATest.class.getClassLoader().getResource("dude_bace1_crystal_ligand.dwar").toURI()); 28 | File libFile = new File(PheSATest.class.getClassLoader().getResource("dude_bace1_actives_final.dwar").toURI()); 29 | DWARFileParser queryParser = new DWARFileParser(queryFile); 30 | queryParser.next(); 31 | StereoMolecule query = queryParser.getMolecule(); 32 | DWARFileParser libParser = new DWARFileParser(libFile); 33 | //DescriptorHandlerOneConf should be used for the query molecule, so that the 34 | //input 3D coordinates are taken and no coordinates are generated 35 | DescriptorHandlerShapeOneConf dhsOC = new DescriptorHandlerShapeOneConf(); 36 | //for the candidate molecules, the standard DescriptorHandlerShape should be used, which calculates conformers 37 | DescriptorHandlerShape dhs = new DescriptorHandlerShape(); 38 | PheSAMolecule refVol = dhsOC.createDescriptor(query); 39 | PheSAMolecule refVolConfGen = dhs.createDescriptor(query); 40 | double sim = dhs.getSimilarity(refVol, refVolConfGen); 41 | //self-alignment check: align generated conformers of the query on the original 3D input structure 42 | StereoMolecule[] previousAlignment = dhs.getPreviousAlignment(); 43 | List alignedMols = new ArrayList<>(); 44 | alignedMols.add(previousAlignment[0]); 45 | alignedMols.add(previousAlignment[1]); 46 | while(libParser.next()) { 47 | StereoMolecule libMol = libParser.getMolecule(); 48 | PheSAMolecule libVol = dhs.createDescriptor(libMol); 49 | sim = dhs.getSimilarity(refVol, libVol); 50 | System.out.println(sim); 51 | //getPreviousAlignment returns the query and candidate molecule in optimal alignment, it 52 | //they are returned in an array with length 2 53 | previousAlignment = dhs.getPreviousAlignment(); 54 | alignedMols.add(previousAlignment[1]); 55 | } 56 | 57 | //write the 3D alignments to an SD-File 58 | try(BufferedWriter structureWriter = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("aligned.sdf"), "utf-8"))){ 59 | for(StereoMolecule optimized: alignedMols) { 60 | Utils.writeMoleculeRecord(structureWriter, optimized); 61 | structureWriter.write("$$$$ \n" ); 62 | } 63 | 64 | } 65 | 66 | 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/main/java/com/idorsia/research/chem/phesa/ShapeDockingTest.java: -------------------------------------------------------------------------------- 1 | package com.idorsia.research.chem.phesa; 2 | 3 | import com.actelion.research.chem.Molecule; 4 | import com.actelion.research.chem.MolfileCreator; 5 | import com.actelion.research.chem.MolfileParser; 6 | import com.actelion.research.chem.StereoMolecule; 7 | import com.actelion.research.chem.alignment3d.transformation.TransformationSequence; 8 | import com.actelion.research.chem.conf.Conformer; 9 | import com.actelion.research.chem.conf.SymmetryCorrectedRMSDCalculator; 10 | import com.actelion.research.chem.docking.DockingFailedException; 11 | import com.actelion.research.chem.docking.receptorpharmacophore.NegativeReceptorImageCreator; 12 | import com.actelion.research.chem.docking.shape.ShapeDocking; 13 | import com.actelion.research.chem.io.Mol2FileParser; 14 | import com.actelion.research.chem.phesa.ShapeVolume; 15 | 16 | import java.io.File; 17 | import java.io.FileWriter; 18 | import java.io.IOException; 19 | 20 | 21 | /** 22 | * demonstrates how to use PheSA-based shape docking to dock a ligand into a binding site 23 | * first step is create a Shape and Pharmacophore representation of the binding site ("Negative Binding Site Image") 24 | * which then is used in the shape docking algorithm 25 | */ 26 | public class ShapeDockingTest { 27 | 28 | 29 | public static void dock() throws Exception { 30 | Mol2FileParser m2fp = new Mol2FileParser(); 31 | MolfileParser mfp = new MolfileParser(); 32 | //parse ligand and receptor into StereoMolecules 33 | StereoMolecule lig = mfp.getCompactMolecule(new File(ShapeDockingTest.class.getClassLoader().getResource("astex_1n46_ligand.mol").toURI())); 34 | StereoMolecule rec = m2fp.load(new File(ShapeDockingTest.class.getClassLoader().getResource("astex_1n46_protein.mol2").toURI())); 35 | selfDockShapeOnly(rec,lig); 36 | 37 | } 38 | 39 | public static void selfDockShapeOnly(StereoMolecule receptor, StereoMolecule nativeLigandPose) throws DockingFailedException { 40 | double rmsd = -1.0; 41 | 42 | 43 | StereoMolecule toDock = new StereoMolecule(nativeLigandPose); 44 | toDock.ensureHelperArrays(Molecule.cHelperParities); 45 | //we can store the transformation that is generated by the NegativeReceptorImageCreator to place the 46 | //binding site in the origin of the coordinate system, so that we can later backtransform the 47 | //aligned ligand and inspect the pose with respect to the original protein structure if desired 48 | TransformationSequence transform = new TransformationSequence(); 49 | ShapeVolume bsVolume = NegativeReceptorImageCreator.create(nativeLigandPose, receptor,transform); 50 | ShapeDocking shapeDocking = new ShapeDocking(bsVolume,transform); 51 | //shape docking creates a list of poses, we take the first one which is the highest-scored 52 | StereoMolecule docked = shapeDocking.dock(toDock).get(0); 53 | 54 | //we use a symmetry corrected rmsd calculator to check how close we are to the true bioactive conformer 55 | SymmetryCorrectedRMSDCalculator rmsdCalc = new SymmetryCorrectedRMSDCalculator(new Conformer(nativeLigandPose), 56 | new Conformer(shapeDocking.dock(toDock).get(0))); 57 | 58 | rmsd = rmsdCalc.calculate(); 59 | 60 | System.out.println(rmsd); 61 | 62 | String delim = System.getProperty("line.separator"); 63 | File outfile = new File(receptor.getName()+ "_docked.sdf"); 64 | FileWriter fileWriter; 65 | try { 66 | 67 | fileWriter = new FileWriter(outfile); 68 | MolfileCreator mfc = new MolfileCreator(docked); 69 | mfc.writeMolfile(fileWriter); 70 | fileWriter.write(delim); 71 | fileWriter.write("$$$$"); 72 | fileWriter.write(delim); 73 | fileWriter.flush(); 74 | fileWriter.close(); 75 | } catch (IOException e) { 76 | // TODO Auto-generated catch block 77 | e.printStackTrace(); 78 | } 79 | 80 | 81 | 82 | 83 | } 84 | 85 | 86 | } 87 | -------------------------------------------------------------------------------- /src/main/java/com/idorsia/research/chem/phesa/Utils.java: -------------------------------------------------------------------------------- 1 | package com.idorsia.research.chem.phesa; 2 | 3 | import java.io.BufferedWriter; 4 | import java.io.IOException; 5 | 6 | import com.actelion.research.chem.MolfileCreator; 7 | import com.actelion.research.chem.StereoMolecule; 8 | 9 | public class Utils { 10 | 11 | public static void writeMoleculeRecord(BufferedWriter writer, StereoMolecule mol) throws IOException { 12 | MolfileCreator mfc = new MolfileCreator(mol,false); 13 | mfc.writeMolfile(writer); 14 | writer.write(" \n" ); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/main/resources/astex_1n46_ligand.mol: -------------------------------------------------------------------------------- 1 | LIGAND 2 | Insight 3D 0 3 | 4 | 47 49 0 0 0 0 0 5 | 17.2230 5.2550 6.1390 O 0 0 0 0 0 0 6 | 18.0230 4.3770 6.2680 C 0 0 0 0 0 0 7 | 17.9770 3.3560 7.1890 N 0 0 0 0 0 0 8 | 18.9470 2.3970 7.2460 C 0 0 0 0 0 0 9 | 18.9550 1.4890 8.0470 O 0 0 0 0 0 0 10 | 19.0230 4.4100 5.4000 N 0 0 0 0 0 0 11 | 20.0320 3.4130 5.4060 N 0 0 0 0 0 0 12 | 20.0190 2.4460 6.2520 C 0 0 0 0 0 0 13 | 20.7915 1.6774 6.2294 H 0 0 0 0 0 0 14 | 19.2990 5.4070 4.4430 C 0 0 0 0 0 0 15 | 20.4930 6.1760 4.7530 C 0 0 0 0 0 0 16 | 21.0919 5.9476 5.6346 H 0 0 0 0 0 0 17 | 20.8590 7.2330 3.8770 C 0 0 0 0 0 0 18 | 22.0400 8.0590 4.1150 C 0 0 0 0 0 0 19 | 22.9152 7.5765 3.6799 H 0 0 0 0 0 0 20 | 21.8987 9.0370 3.6550 H 0 0 0 0 0 0 21 | 22.1887 8.1808 5.1879 H 0 0 0 0 0 0 22 | 18.5530 5.7190 3.3210 C 0 0 0 0 0 0 23 | 17.6193 5.1846 3.1457 H 0 0 0 0 0 0 24 | 18.9560 6.7020 2.3970 C 0 0 0 0 0 0 25 | 18.0880 7.0200 1.1620 C 0 0 0 0 0 0 26 | 18.0951 8.0945 0.9792 H 0 0 0 0 0 0 27 | 18.4897 6.5013 0.2916 H 0 0 0 0 0 0 28 | 17.0650 6.6892 1.3413 H 0 0 0 0 0 0 29 | 20.1030 7.4820 2.6960 C 0 0 0 0 0 0 30 | 20.3800 8.5040 1.8130 O 0 0 0 0 0 0 31 | 21.4190 8.3390 0.9100 C 0 0 0 0 0 0 32 | 21.6800 7.0750 0.2610 C 0 0 0 0 0 0 33 | 21.0727 6.1918 0.4590 H 0 0 0 0 0 0 34 | 22.2200 9.5120 0.6640 C 0 0 0 0 0 0 35 | 22.0033 10.4492 1.1767 H 0 0 0 0 0 0 36 | 23.2950 9.4250 -0.2570 C 0 0 0 0 0 0 37 | 24.2110 10.6460 -0.5040 C 0 0 0 0 0 0 38 | 24.8058 10.4373 -1.3933 H 0 0 0 0 0 0 39 | 23.2930 11.8890 -0.7160 C 0 0 0 0 0 0 40 | 23.9092 12.7704 -0.8933 H 0 0 0 0 0 0 41 | 22.6450 11.7203 -1.5761 H 0 0 0 0 0 0 42 | 22.6823 12.0462 0.1731 H 0 0 0 0 0 0 43 | 25.0970 10.7800 0.7600 C 0 0 0 0 0 0 44 | 25.7693 11.6302 0.6446 H 0 0 0 0 0 0 45 | 24.4636 10.9342 1.6336 H 0 0 0 0 0 0 46 | 25.6823 9.8700 0.8922 H 0 0 0 0 0 0 47 | 23.5830 8.1750 -0.8550 C 0 0 0 0 0 0 48 | 22.7560 7.0450 -0.6370 C 0 0 0 0 0 0 49 | 22.9628 6.1251 -1.1839 H 0 0 0 0 0 0 50 | 24.6370 8.0360 -1.7310 O 0 0 0 0 0 0 51 | 24.8021 8.9301 -2.2149 H 0 0 0 0 0 0 52 | 1 2 2 0 0 0 53 | 2 3 1 0 0 0 54 | 2 6 1 0 0 0 55 | 3 4 1 0 0 0 56 | 4 5 2 0 0 0 57 | 4 8 1 0 0 0 58 | 6 7 1 0 0 0 59 | 6 10 1 0 0 0 60 | 7 8 2 0 0 0 61 | 8 9 1 0 0 0 62 | 10 11 1 0 0 0 63 | 10 18 2 0 0 0 64 | 11 13 2 0 0 0 65 | 11 12 1 0 0 0 66 | 13 14 1 0 0 0 67 | 13 25 1 0 0 0 68 | 14 15 1 0 0 0 69 | 14 16 1 0 0 0 70 | 14 17 1 0 0 0 71 | 18 20 1 0 0 0 72 | 18 19 1 0 0 0 73 | 20 21 1 0 0 0 74 | 20 25 2 0 0 0 75 | 21 22 1 0 0 0 76 | 21 23 1 0 0 0 77 | 21 24 1 0 0 0 78 | 25 26 1 0 0 0 79 | 26 27 1 0 0 0 80 | 27 28 1 0 0 0 81 | 27 30 2 0 0 0 82 | 28 44 2 0 0 0 83 | 28 29 1 0 0 0 84 | 30 32 1 0 0 0 85 | 30 31 1 0 0 0 86 | 32 33 1 0 0 0 87 | 32 43 2 0 0 0 88 | 33 35 1 0 0 0 89 | 33 39 1 0 0 0 90 | 33 34 1 0 0 0 91 | 35 36 1 0 0 0 92 | 35 37 1 0 0 0 93 | 35 38 1 0 0 0 94 | 39 40 1 0 0 0 95 | 39 41 1 0 0 0 96 | 39 42 1 0 0 0 97 | 43 44 1 0 0 0 98 | 43 46 1 0 0 0 99 | 44 45 1 0 0 0 100 | 46 47 1 0 0 0 101 | -------------------------------------------------------------------------------- /src/main/resources/bace_crystal_ligand.mol2: -------------------------------------------------------------------------------- 1 | @MOLECULE 2 | BDV_1_3L5D 3 | 65 66 0 0 0 4 | SMALL 5 | USER_CHARGES 6 | 7 | @ATOM 8 | 1 C1 28.2520 10.2950 20.2960 C.3 1 <0> -0.0652 9 | 2 C2 23.4340 12.0520 19.4210 C.3 1 <0> -0.0625 10 | 3 C3 23.6780 9.8530 20.6550 C.3 1 <0> -0.0625 11 | 4 C4 19.1580 10.4820 21.5830 C.3 1 <0> -0.0098 12 | 5 C5 24.2730 15.3070 24.7810 C.ar 1 <0> -0.0568 13 | 6 C6 25.2310 13.5550 23.3320 C.ar 1 <0> -0.0568 14 | 7 C7 23.1860 14.4410 25.1120 C.ar 1 <0> -0.0568 15 | 8 C8 24.1490 12.6920 23.6630 C.ar 1 <0> -0.0568 16 | 9 C9 28.8260 11.4220 21.1330 C.3 1 <0> -0.0545 17 | 10 C10 28.4300 12.7910 20.6080 C.3 1 <0> -0.0376 18 | 11 C11 29.2580 13.9080 21.2460 C.3 1 <0> 0.0130 19 | 12 C12 26.4520 15.7820 23.5370 C.3 1 <0> 0.0383 20 | 13 C13 21.9650 12.2050 24.9040 C.3 1 <0> 0.0502 21 | 14 C14 21.3900 10.9180 20.3920 C.3 1 <0> 0.0041 22 | 15 C15 25.2970 14.8650 23.8900 C.ar 1 <0> -0.0303 23 | 16 C16 23.1210 13.1300 24.5530 C.ar 1 <0> -0.0297 24 | 17 C17 21.7630 10.0660 23.6080 C.3 1 <0> 0.0736 25 | 18 C18 20.9070 11.8540 22.6750 C.2 1 <0> 0.2753 26 | 19 C19 22.8940 11.1590 20.5390 C.3 1 <0> -0.0409 27 | 20 C20 28.3980 14.3670 23.4560 C.2 1 <0> 0.2999 28 | 21 C21 20.6810 10.6720 21.7290 C.3 1 <0> 0.0706 29 | 22 N1 22.3880 9.3370 24.5310 N.4 1 <0> 0.2701 30 | 23 N2 21.2830 9.5630 22.4480 N.4 1 <0> 0.2881 31 | 24 N3 29.3240 13.7470 22.6950 N.am 1 <0> -0.2994 32 | 25 N4 27.4880 15.0870 22.7670 N.am 1 <0> -0.2953 33 | 26 N5 21.5530 11.3910 23.7570 N.am 1 <0> -0.2106 34 | 27 O1 20.5470 13.0130 22.4570 O.2 1 <0> -0.2687 35 | 28 O2 28.3810 14.2820 24.6840 O.2 1 <0> -0.2529 36 | 29 H1 28.5668 9.3284 20.7163 H 1 <0> 0.0230 37 | 30 H2 27.1538 10.3569 20.3017 H 1 <0> 0.0230 38 | 31 H3 28.6190 10.3823 19.2627 H 1 <0> 0.0230 39 | 32 H4 22.8426 12.9782 19.3729 H 1 <0> 0.0232 40 | 33 H5 24.4862 12.2992 19.6253 H 1 <0> 0.0232 41 | 34 H6 23.3618 11.5208 18.4605 H 1 <0> 0.0232 42 | 35 H7 23.2575 9.2433 21.4683 H 1 <0> 0.0232 43 | 36 H8 23.6084 9.2984 19.7076 H 1 <0> 0.0232 44 | 37 H9 24.7328 10.0768 20.8724 H 1 <0> 0.0232 45 | 38 H10 18.7127 10.3105 22.5741 H 1 <0> 0.0292 46 | 39 H11 18.7174 11.3846 21.1344 H 1 <0> 0.0292 47 | 40 H12 18.9571 9.6153 20.9360 H 1 <0> 0.0292 48 | 41 H13 24.3201 16.2987 25.2060 H 1 <0> 0.0621 49 | 42 H14 26.0033 13.2169 22.6570 H 1 <0> 0.0621 50 | 43 H15 22.4128 14.7791 25.7860 H 1 <0> 0.0621 51 | 44 H16 24.1047 11.6998 23.2387 H 1 <0> 0.0621 52 | 45 H17 28.4497 11.3200 22.1616 H 1 <0> 0.0263 53 | 46 H18 29.9232 11.3455 21.1167 H 1 <0> 0.0263 54 | 47 H19 28.5908 12.8110 19.5200 H 1 <0> 0.0280 55 | 48 H20 27.3685 12.9634 20.8394 H 1 <0> 0.0280 56 | 49 H21 30.2781 13.8759 20.8358 H 1 <0> 0.0462 57 | 50 H22 28.7905 14.8765 21.0147 H 1 <0> 0.0462 58 | 51 H23 26.0664 16.6173 22.9341 H 1 <0> 0.0512 59 | 52 H24 26.8994 16.1589 24.4686 H 1 <0> 0.0512 60 | 53 H25 22.2832 11.5349 25.7162 H 1 <0> 0.0518 61 | 54 H26 21.1099 12.8162 25.2284 H 1 <0> 0.0518 62 | 55 H27 20.9434 11.8081 19.9248 H 1 <0> 0.0330 63 | 56 H28 21.2444 10.0313 19.7575 H 1 <0> 0.0330 64 | 57 H29 22.2539 9.3238 24.2547 H 1 <0> 0.1733 65 | 58 H30 23.0409 11.6992 21.4859 H 1 <0> 0.0298 66 | 59 H31 22.6507 9.9229 25.2976 H 1 <0> 0.2071 67 | 60 H32 21.7761 8.6163 24.8569 H 1 <0> 0.2071 68 | 61 H33 23.2065 8.9242 24.1315 H 1 <0> 0.2071 69 | 62 H34 22.0233 9.1597 21.9102 H 1 <0> 0.2104 70 | 63 H35 20.6010 8.8549 22.6309 H 1 <0> 0.2104 71 | 64 H36 30.0400 13.1893 23.1149 H 1 <0> 0.1502 72 | 65 H37 27.5192 15.1443 21.7691 H 1 <0> 0.1506 73 | @BOND 74 | 1 1 9 1 75 | 2 2 19 1 76 | 3 3 19 1 77 | 4 4 21 1 78 | 5 5 7 ar 79 | 6 5 15 ar 80 | 7 6 8 ar 81 | 8 6 15 ar 82 | 9 7 16 ar 83 | 10 8 16 ar 84 | 11 9 10 1 85 | 12 10 11 1 86 | 13 11 24 1 87 | 14 12 15 1 88 | 15 12 25 1 89 | 16 13 16 1 90 | 17 13 26 1 91 | 18 14 19 1 92 | 19 14 21 1 93 | 20 17 22 1 94 | 21 17 23 1 95 | 22 17 26 1 96 | 23 18 21 1 97 | 24 18 26 am 98 | 25 18 27 2 99 | 26 20 24 am 100 | 27 20 25 am 101 | 28 20 28 2 102 | 29 21 23 1 103 | 30 1 29 1 104 | 31 1 30 1 105 | 32 1 31 1 106 | 33 2 32 1 107 | 34 2 33 1 108 | 35 2 34 1 109 | 36 3 35 1 110 | 37 3 36 1 111 | 38 3 37 1 112 | 39 4 38 1 113 | 40 4 39 1 114 | 41 4 40 1 115 | 42 5 41 1 116 | 43 6 42 1 117 | 44 7 43 1 118 | 45 8 44 1 119 | 46 9 45 1 120 | 47 9 46 1 121 | 48 10 47 1 122 | 49 10 48 1 123 | 50 11 49 1 124 | 51 11 50 1 125 | 52 12 51 1 126 | 53 12 52 1 127 | 54 13 53 1 128 | 55 13 54 1 129 | 56 14 55 1 130 | 57 14 56 1 131 | 58 17 57 1 132 | 59 19 58 1 133 | 60 22 59 1 134 | 61 22 60 1 135 | 62 22 61 1 136 | 63 23 62 1 137 | 64 23 63 1 138 | 65 24 64 1 139 | 66 25 65 1 140 | -------------------------------------------------------------------------------- /src/main/resources/dude_bace1_crystal_ligand.dwar: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | Structure idcoordinates2D FragFp idcoordinates3D Name 21 | fcwh`BDLdWhFlfTyEEEHecEDcdeLdbLbejjj`hBijjDXQD@ #q@ggfa{VvTftWYPbd`KZjqpGsiXeZ}zDq~TUiwEgxzTwLntgBj]uJuchO@@Co|RHqXRwBo[YLYH]BSOzyig}}ubWNkjFKbBBJIfmsI]MSakUOKJ~{qxNCm?qnVmol{@oY]ul^{@oY\FndiX]SbH]wSEVyBNlVWZtCgcMAO^abbWxdx]LXR{MXKR?}se{nSfN_ees{n{fmxhVpsp_JP?Im^~ic`iWz_ZVRoUdJG[w\QArELctf[GtgaTru]VIAwPTN{ejLkLKeP|xaTtjmRUjV\RttGuhdKLvenOYkD?imrFfC\dg|RSJIO]dfdrLMQTfEFcFYRmXLHOriqekbXcyFrqWEtgHTSE@aman\ubmv]yxeMQtKESj|sZW\YE{Y]WgsiQlLmevvK|GeMNHzypNVNYt]z_hsgEUMfZUJAbvL^TEtwkoKMCu{]ZtzWZmMPQyEkQiY]O[Ip[FJ_o[[dvQAccDv~`YID[FTkCnvXWjAKeg\bsTzs\SSWbG~zwfUGfmkbykG@@dAGpD #q@ggfa{VvTftWYPbd`KZjqpGsiXeZ}zDq~TUiwEgxzTwLntgBj]uJuchO@@Co|RHqXRwBo[YLYH]BSOzyig}}ubWNkjFKbBBJIfmsI]MSakUOKJ~{qxNCm?qnVmol{@oY]ul^{@oY\FndiX]SbH]wSEVyBNlVWZtCgcMAO^abbWxdx]LXR{MXKR?}se{nSfN_ees{n{fmxhVpsp_JP?Im^~ic`iWz_ZVRoUdJG[w\QArELctf[GtgaTru]VIAwPTN{ejLkLKeP|xaTtjmRUjV\RttGuhdKLvenOYkD?imrFfC\dg|RSJIO]dfdrLMQTfEFcFYRmXLHOriqekbXcyFrqWEtgHTSE@aman\ubmv]yxeMQtKESj|sZW\YE{Y]WgsiQlLmevvK|GeMNHzypNVNYt]z_hsgEUMfZUJAbvL^TEtwkoKMCu{]ZtzWZmMPQyEkQiY]O[Ip[FJ_o[[dvQAccDv~`YID[FTkCnvXWjAKeg\bsTzs\SSWbG~zwfUGfmkbykG@@dAGpD BDV_1_3L5D 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | --------------------------------------------------------------------------------