Repository 'sucos_max_score'
hg clone https://toolshed.g2.bx.psu.edu/repos/bgruening/sucos_max_score

Changeset 0:bb5365381c8f (2019-10-02)
Next changeset 1:8eab6d2b7bdf (2019-10-11)
Commit message:
"planemo upload for repository https://github.com/bgruening/galaxytools/tree/master/chemicaltoolbox/sucos commit ef86cfa5f7ab5043de420511211579d03df58645"
added:
sucos.py
sucos_cluster.py
sucos_macros.xml
sucos_max.py
sucos_max.xml
test-data/cluster1.sdf
test-data/cluster2.sdf
test-data/cluster3.sdf
test-data/cluster4.sdf
test-data/cluster5.sdf
test-data/cluster6.sdf
test-data/split_1.sdf
test-data/split_2.sdf
test-data/split_3.sdf
test-data/split_4.sdf
test-data/sucos_cluster.sdf
test-data/sucos_inputs.sdf
test-data/sucos_refmol.mol
utils.py
b
diff -r 000000000000 -r bb5365381c8f sucos.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sucos.py Wed Oct 02 12:57:54 2019 -0400
[
b'@@ -0,0 +1,202 @@\n+#!/usr/bin/env python\n+"""\n+Basic SuCOS scoring. Allows a set of molecules from a SD file to be overlayed to a reference molecule,\n+with the resulting scores being written as properties in the output SD file.\n+\n+SuCOS is the work of Susan Leung.\n+GitHub: https://github.com/susanhleung/SuCOS\n+Publication: https://doi.org/10.26434/chemrxiv.8100203.v1\n+"""\n+\n+from __future__ import print_function\n+import argparse, os, sys, gzip\n+import numpy as np\n+from rdkit import Chem, rdBase, RDConfig\n+from rdkit.Chem import AllChem, rdShapeHelpers\n+from rdkit.Chem.FeatMaps import FeatMaps\n+import utils\n+\n+\n+### start function definitions #########################################\n+\n+# Setting up the features to use in FeatureMap\n+fdef = AllChem.BuildFeatureFactory(os.path.join(RDConfig.RDDataDir, \'BaseFeatures.fdef\'))\n+\n+fmParams = {}\n+for k in fdef.GetFeatureFamilies():\n+    fparams = FeatMaps.FeatMapParams()\n+    fmParams[k] = fparams\n+\n+keep = (\'Donor\', \'Acceptor\', \'NegIonizable\', \'PosIonizable\', \'ZnBinder\',\n+        \'Aromatic\', \'Hydrophobe\', \'LumpedHydrophobe\')\n+\n+def filterFeature(f):\n+    result = f.GetFamily() in keep\n+    # TODO - nothing ever seems to be filtered. Is this expected?\n+    if not result:\n+        utils.log("Filtered out feature type", f.GetFamily())\n+    return result\n+\n+def getRawFeatures(mol):\n+\n+    rawFeats = fdef.GetFeaturesForMol(mol)\n+    # filter that list down to only include the ones we\'re interested in\n+    filtered = list(filter(filterFeature, rawFeats))\n+    return filtered\n+\n+def get_FeatureMapScore(small_feats, large_feats, tani=False, score_mode=FeatMaps.FeatMapScoreMode.All):\n+    """\n+    Generate the feature map score.\n+\n+    :param small_feats:\n+    :param large_feats:\n+    :param tani:\n+    :return:\n+    """\n+\n+    featLists = []\n+    for rawFeats in [small_feats, large_feats]:\n+        # filter that list down to only include the ones we\'re interested in\n+        featLists.append(rawFeats)\n+    fms = [FeatMaps.FeatMap(feats=x, weights=[1] * len(x), params=fmParams) for x in featLists]\n+    # set the score mode\n+    fms[0].scoreMode = score_mode\n+\n+    try:\n+        if tani:\n+            c = fms[0].ScoreFeats(featLists[1])\n+            A = fms[0].GetNumFeatures()\n+            B = len(featLists[1])\n+            if B != fms[1].GetNumFeatures():\n+                utils.log("Why isn\'t B equal to number of features...?!")\n+            tani_score = float(c) / (A+B-c)\n+            return tani_score\n+        else:\n+            fm_score = fms[0].ScoreFeats(featLists[1]) / min(fms[0].GetNumFeatures(), len(featLists[1]))\n+            return fm_score\n+    except ZeroDivisionError:\n+        utils.log("ZeroDivisionError")\n+        return 0\n+\n+    if tani:\n+        tani_score = float(c) / (A+B-c)\n+        return tani_score\n+    else:\n+        fm_score = fms[0].ScoreFeats(featLists[1]) / min(fms[0].GetNumFeatures(), len(featLists[1]))\n+        return fm_score\n+\n+\n+def get_SucosScore(ref_mol, query_mol, tani=False, ref_features=None, query_features=None, score_mode=FeatMaps.FeatMapScoreMode.All):\n+    """\n+    This is the key function that calculates the SuCOS scores and is expected to be called from other modules.\n+    To improve performance you can pre-calculate the features and pass them in as optional parameters to avoid having\n+    to recalculate them. Use the getRawFeatures function to pre-calculate the features.\n+\n+    :param ref_mol: The reference molecule to compare to\n+    :param query_mol: The molecule to align to the reference\n+    :param tani: Whether to calculate Tanimoto distances\n+    :param ref_features: An optional feature map for the reference molecule, avoiding the need to re-calculate it.\n+    :param query_features: An optional feature map for the query molecule, avoiding the need to re-calculate it.\n+    :return: A tuple of 3 values. 1 the sucos score, 2 the feature map score,\n+        3 the Tanimoto distance or 1 minus the protrude distance\n+    """\n+\n+    if not ref_features'..b'rs.ShapeTanimotoDist(ref_mol, query_mol))\n+        tani_sim = np.clip(tani_sim, 0, 1)\n+        SuCOS_score = 0.5*fm_score + 0.5*tani_sim\n+        return SuCOS_score, fm_score, tani_sim\n+    else:\n+        protrude_dist = rdShapeHelpers.ShapeProtrudeDist(ref_mol, query_mol, allowReordering=False)\n+        protrude_dist = np.clip(protrude_dist, 0, 1)\n+        protrude_val = 1.0 - protrude_dist\n+        SuCOS_score = 0.5 * fm_score + 0.5 * protrude_val\n+        return SuCOS_score, fm_score, protrude_val\n+\n+def process(refmol_filename, inputs_filename, outputs_filename, refmol_index=None,\n+            refmol_format=None, tani=False, score_mode=FeatMaps.FeatMapScoreMode.All):\n+\n+    ref_mol = utils.read_single_molecule(refmol_filename, index=refmol_index, format=refmol_format)\n+    #utils.log("Reference mol has", ref_mol.GetNumHeavyAtoms(), "heavy atoms")\n+    ref_features = getRawFeatures(ref_mol)\n+\n+    input_file = utils.open_file_for_reading(inputs_filename)\n+    suppl = Chem.ForwardSDMolSupplier(input_file)\n+    output_file = utils.open_file_for_writing(outputs_filename)\n+    writer = Chem.SDWriter(output_file)\n+\n+    count = 0\n+    total = 0\n+    errors = 0\n+    for mol in suppl:\n+        count +=1\n+        if mol is None:\n+            continue\n+        #utils.log("Mol has", str(mol.GetNumHeavyAtoms()), "heavy atoms")\n+        try:\n+            sucos_score, fm_score, val3 = get_SucosScore(ref_mol, mol, tani=tani, ref_features=ref_features, score_mode=score_mode)\n+            mol.SetDoubleProp("SuCOS_Score", sucos_score)\n+            mol.SetDoubleProp("SuCOS_FeatureMap_Score", fm_score)\n+            if tani:\n+                mol.SetDoubleProp("SuCOS_Tanimoto_Score", val3)\n+            else:\n+                mol.SetDoubleProp("SuCOS_Protrude_Score", val3)\n+            utils.log("Scores:", sucos_score, fm_score, val3)\n+            writer.write(mol)\n+            total +=1\n+        except ValueError as e:\n+            errors +=1\n+            utils.log("Molecule", count, "failed to score:", e.message)\n+\n+    input_file.close()\n+    writer.flush()\n+    writer.close()\n+    output_file.close()\n+\n+    utils.log("Completed.", total, "processed, ", count, "succeeded, ", errors, "errors")\n+\n+def parse_score_mode(value):\n+    if value == None or value == \'all\':\n+        return FeatMaps.FeatMapScoreMode.All\n+    elif value == \'closest\':\n+        return FeatMaps.FeatMapScoreMode.Closest\n+    elif value == \'best\':\n+        return FeatMaps.FeatMapScoreMode.Best\n+    else:\n+        raise ValueError(value + " is not a valid scoring mode option")\n+\n+\n+### start main execution #########################################\n+\n+def main():\n+\n+    parser = argparse.ArgumentParser(description=\'SuCOS with RDKit\')\n+    parser.add_argument(\'-i\', \'--input\', help=\'Input file in SDF format. Can be gzipped (*.gz).\')\n+    parser.add_argument(\'-r\', \'--refmol\', help=\'Molecule to compare against in Molfile (.mol) or SDF (.sdf) format\')\n+    parser.add_argument(\'--refmol-format\', help="Format for the reference molecule (mol or sdf). " +\n+                                                "Only needed if files don\'t have the expected extensions")\n+    parser.add_argument(\'--refmolidx\', help=\'Reference molecule index in SD file if not the first\', type=int, default=1)\n+    parser.add_argument(\'-o\', \'--output\', help=\'Output file in SDF format. Can be gzipped (*.gz).\')\n+    parser.add_argument(\'--tanimoto\', action=\'store_true\', help=\'Include Tanimoto distance in score\')\n+    parser.add_argument(\'--score_mode\', choices=[\'all\', \'closest\', \'best\'],\n+                        help="choose the scoring mode for the feature map, default is \'all\'.")\n+\n+    args = parser.parse_args()\n+    utils.log("SuCOS Args: ", args)\n+\n+    score_mode = parse_score_mode(args.score_mode)\n+\n+    process(args.refmol, args.input, args.output, refmol_index=args.refmolidx,\n+            refmol_format=args.refmol_format, tani=args.tanimoto, score_mode=score_mode)\n+\n+\n+if __name__ == "__main__":\n+    main()\n'
b
diff -r 000000000000 -r bb5365381c8f sucos_cluster.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sucos_cluster.py Wed Oct 02 12:57:54 2019 -0400
[
@@ -0,0 +1,134 @@
+#!/usr/bin/env python
+"""
+Cluster a set of molecules based on their 3D overlays as determined by the SuCOS score.
+
+This will generate a set of SD files, one for each cluster of molecules (presumably corresponding to a
+binding pocket in the protein target).
+
+
+SuCOS is the work of Susan Leung.
+GitHub: https://github.com/susanhleung/SuCOS
+Publication: https://doi.org/10.26434/chemrxiv.8100203.v1
+"""
+
+import sucos, utils
+import argparse, gzip
+from rdkit import Chem
+import numpy as np
+import pandas as pd
+from scipy.cluster.hierarchy import linkage, fcluster
+
+### start main execution #########################################
+
+
+def calc_distance_matrix(mols):
+    """
+    Calculate a full distance matrix for the given molecules. Identical molecules get a score of 0.0 with the maximum
+    distance possible being 1.0.
+    :param mols: A list of molecules. It must be possible to iterate through this list multiple times
+    :return: A NxN 2D array of distance scores, with N being the number of molecules in the input
+    """
+
+    # TODO - do we need to calculate both sides of the matrix? Tanimoto is supposed to be a symmetric distance measure,
+    #  but the matrix that is generated does not seem to be symmetric.
+
+    mol_fm_tuples = []
+    for mol in mols:
+        features = sucos.getRawFeatures(mol)
+        mol_fm_tuples.append((mol, features))
+
+    matrix = []
+    for tuple1 in mol_fm_tuples:
+        tmp = []
+        for tuple2 in mol_fm_tuples:
+            if tuple1[0] == tuple2[0]:
+                tmp.append(0.0)
+            else:
+                #utils.log("Calculating SuCOS between", mol1, mol2)
+                sucos_score, fm_score, tani_score = sucos.get_SucosScore(tuple1[0], tuple2[0],
+                    tani=True, ref_features=tuple1[1], query_features=tuple2[1])
+                tmp.append(1.0 - sucos_score)
+        matrix.append(tmp)
+
+
+    return matrix
+
+
+def cluster(matrix, threshold=0.8):
+    """
+    Cluster the supplied distance matrix returning an array of clusters.
+    :param matrix: the distance matrix, as calculated with the calc_distance_matrix function.
+    :param threshold: The clustering cuttoff. The default of 0.8 is a reasonable value to use.
+    :return: An array of clusters, each cluster being an array of the indices from the matrix.
+    """
+
+    indexes = [x for x in range(0, len(matrix))]
+    cols = [x for x in range(0, len(matrix[0]))]
+    #utils.log("indexes", indexes)
+    #utils.log("cols", cols)
+    df = pd.DataFrame(matrix, columns=cols, index=indexes)
+    utils.log("DataFrame:", df.shape)
+    #utils.log(df)
+    indices = np.triu_indices(df.shape[0], k=1)
+    #utils.log("Indices:", indices)
+    t = np.array(df)[indices]
+    Z = linkage(t, 'average')
+    lig_clusters = []
+    cluster_arr = fcluster(Z, t=threshold, criterion='distance')
+    for i in range(np.amax(cluster_arr)):
+        clus = df.columns[np.argwhere(cluster_arr==i+1)]
+        lig_clusters.append([x[0] for x in clus.tolist()])
+
+    utils.log("Clusters", lig_clusters)
+    return lig_clusters
+
+def write_clusters_to_sdfs(mols, clusters, basename, gzip=False):
+    """
+    Write the molecules to SDF files, 1 file for each cluster.
+    :param mols The molecules to write:
+    :param clusters The clusters, as returned by the cluster function:
+    :param basename The basename for the file name. e.g. if basename is 'output' then files like
+    output1.sdf, output2.sdf will be written:
+    :param gzip Whether to gzip the output
+    :return:
+    """
+
+    i = 0
+    for cluster in clusters:
+        i += 1
+        filename = basename + str(i) + ".sdf"
+        if gzip:
+            filename += ".gz"
+        utils.log("Writing ", len(cluster), "molecules in cluster", i, "to file", filename)
+        output_file = utils.open_file_for_writing(filename)
+        writer = Chem.SDWriter(output_file)
+        for index in cluster:
+            mol = mols[index]
+            writer.write(mol)
+        writer.flush()
+        writer.close()
+        output_file.close()
+
+
+
+def main():
+    parser = argparse.ArgumentParser(description='Clustering with SuCOS and RDKit')
+    parser.add_argument('-i', '--input', help='Input file in SDF format. Can be gzipped (*.gz).')
+    parser.add_argument('-o', '--output', default="cluster", help="Base name for output files in SDF format. " +
+                                               "e.g. if value is 'output' then files like output1.sdf, output2.sdf will be created")
+    parser.add_argument('--gzip', action='store_true', help='Gzip the outputs generating files like output1.sdf.gz, output2.sdf.gz')
+    parser.add_argument('-t', '--threshold', type=float, default=0.8, help='Clustering threshold')
+
+    args = parser.parse_args()
+    utils.log("SuCOS Cluster Args: ", args)
+
+    input_file = utils.open_file_for_reading(args.input)
+    suppl = Chem.ForwardSDMolSupplier(input_file)
+    mols = list(suppl)
+    matrix = calc_distance_matrix(mols)
+    clusters = cluster(matrix, threshold=args.threshold)
+    write_clusters_to_sdfs(mols, clusters, args.output, gzip=args.gzip)
+
+
+if __name__ == "__main__":
+    main()
\ No newline at end of file
b
diff -r 000000000000 -r bb5365381c8f sucos_macros.xml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sucos_macros.xml Wed Oct 02 12:57:54 2019 -0400
b
@@ -0,0 +1,19 @@
+<macros>
+    <xml name="citations">
+        <citations>
+            <citation type="doi">10.26434/chemrxiv.8100203.v1</citation>
+            <citation type="bibtex">
+                @article{rdkit,
+                author = {Greg Landrum and others},
+                title = {RDKit: Open-source cheminformatics},
+                url ={http://www.rdkit.org}
+                }</citation>
+        </citations>
+    </xml>
+    <xml name="requirements">
+        <requirements>
+            <requirement type="package" version="2019.03.2.0">rdkit</requirement>
+            <yield />
+        </requirements>
+    </xml>
+</macros>
b
diff -r 000000000000 -r bb5365381c8f sucos_max.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sucos_max.py Wed Oct 02 12:57:54 2019 -0400
[
@@ -0,0 +1,154 @@
+#!/usr/bin/env python
+"""
+Assess ligands against a second set of molecules using SuCOS scores.
+This is a quite specialised function that is designed to take a set of potential follow up
+compounds and compare them to a set of clustered fragment hits to help identify which follow up
+ligands best map to the binding space of the hits.
+
+The clustering of the fragment hits is expected to be performed with the sucos_cluster.py module
+and will generate a set of SD files, one for each cluster of hits (presumably corresponding to a
+binding pocket in the protein target).
+
+Each molecule in the input ligands is then compared (using SuCOS) to each hit in the clusters. There
+ are different modes which determine how the ligand is assessed.
+
+In mode 'max' the hit with the best SuCOS score is identified. The output is a SD file with each of the ligands,
+with these additional fields for each molecule:
+Max_SuCOS_Score - the best score
+Max_SuCOS_FeatureMap_Score - the feature map score for the hit that has the best SuCOS score
+Max_SuCOS_Protrude_Score - the protrude volume for the hit that has the best SuCOS score
+Max_SuCOS_Cluster - the name of the cluster SD file that contains the best hit
+Max_SuCOS_Index - the index of the best hit in the SD file
+
+In mode 'cum' the sum of all the scores is calculated and reported as the following properties for each molecule:
+Cum_SuCOS_Score property: the sum of the SuCOS scores
+Cum_SuCOS_FeatureMap_Score: the sum of the feature map scores
+Cum_SuCOS_Protrude_Score: the sum of the protrude volume scores
+
+If a molecule has no alignment to any of the clustered hits (all alignment scores of zero) then it is not
+included in the results.
+
+
+SuCOS is the work of Susan Leung.
+GitHub: https://github.com/susanhleung/SuCOS
+Publication: https://doi.org/10.26434/chemrxiv.8100203.v1
+"""
+
+import sucos, utils
+import argparse, gzip, os
+from rdkit import Chem
+
+
+def process(inputfilename, clusterfilenames, outputfilename, mode):
+
+    all_clusters = {}
+    for filename in clusterfilenames:
+        cluster = []
+        cluster_file = utils.open_file_for_reading(filename)
+        suppl = Chem.ForwardSDMolSupplier(cluster_file)
+        i = 0
+        for mol in suppl:
+            i += 1
+            if not mol:
+                utils.log("WARNING: failed to generate molecule", i, "in cluster", filename)
+                continue
+            try:
+                features = sucos.getRawFeatures(mol)
+                cluster.append((mol, features))
+            except:
+                utils.log("WARNING: failed to generate features for molecule", i, "in cluster", filename)
+
+        cluster_file.close()
+        all_clusters[filename] = cluster
+
+    input_file = utils.open_file_for_reading(inputfilename)
+    suppl = Chem.ForwardSDMolSupplier(input_file)
+    output_file = utils.open_file_for_writing(outputfilename)
+    writer = Chem.SDWriter(output_file)
+
+    comparisons = 0
+    mol_num = 0
+
+    for mol in suppl:
+        mol_num += 1
+        if not mol:
+            utils.log("WARNING: failed to generate molecule", mol_num, "in input")
+            continue
+        try:
+            query_features = sucos.getRawFeatures(mol)
+        except:
+            utils.log("WARNING: failed to generate features for molecule", mol_num, "in input")
+            continue
+        scores = [0, 0, 0]
+        for clusterfilename in all_clusters:
+            cluster = all_clusters[clusterfilename]
+            index = 0
+            for entry in cluster:
+                hit = entry[0]
+                ref_features = entry[1]
+                index += 1
+                comparisons += 1
+                sucos_score, fm_score, vol_score = sucos.get_SucosScore(hit, mol,
+                    tani=False, ref_features=ref_features, query_features=query_features)
+                if mode == 'max':
+                    if sucos_score > scores[0]:
+                        scores[0] = sucos_score
+                        scores[1] = fm_score
+                        scores[2] = vol_score
+                        cluster_name = clusterfilename
+                        cluster_index = index
+                elif mode == 'cum':
+                    scores[0] += sucos_score
+                    scores[1] += fm_score
+                    scores[2] += vol_score
+                else:
+                    raise ValueError("Invalid mode: " + mode)
+
+        if scores[0] > 0:
+            if mode == 'max':
+                cluster_file_name_only = cluster_name.split(os.sep)[-1]
+                #utils.log("Max SuCOS:", scores[0], "FM:", scores[1], "P:", scores[2],"File:", cluster_file_name_only, "Index:", cluster_index)
+                mol.SetDoubleProp("Max_SuCOS_Score", scores[0])
+                mol.SetDoubleProp("Max_SuCOS_FeatureMap_Score", scores[1])
+                mol.SetDoubleProp("Max_SuCOS_Protrude_Score", scores[2])
+                mol.SetProp("Max_SuCOS_Cluster", cluster_file_name_only)
+                mol.SetIntProp("Max_SuCOS_Index", cluster_index)
+
+            else:
+                #utils.log("Cum SuCOS:", scores[0], "FM:", scores[1], "P:", scores[2])
+                mol.SetDoubleProp("Cum_SuCOS_Score", scores[0])
+                mol.SetDoubleProp("Cum_SuCOS_FeatureMap_Score", scores[1])
+                mol.SetDoubleProp("Cum_SuCOS_Protrude_Score", scores[2])
+
+            writer.write(mol)
+
+        else:
+            utils.log("Molecule", mol_num, "did not overlay. Omitting from results")
+
+
+    input_file.close()
+    writer.flush()
+    writer.close()
+    output_file.close()
+
+    utils.log("Completed", comparisons, "comparisons")
+
+
+### start main execution #########################################
+
+def main():
+    parser = argparse.ArgumentParser(description='Max SuCOS scores with RDKit')
+    parser.add_argument('-i', '--input', help='Input file to score in SDF format. Can be gzipped (*.gz).')
+    parser.add_argument('-o', '--output', help='Output file in SDF format. Can be gzipped (*.gz).')
+    parser.add_argument('-m', '--mode', choices=['max', 'cum'],
+                        default='max', help='Score mode: max = best score, cum = sum of all scores')
+    parser.add_argument('clusters', nargs='*', help="One or more SDF files with the clustered hits")
+
+    args = parser.parse_args()
+    utils.log("Max SuCOS Args: ", args)
+
+    process(args.input, args.clusters, args.output, args.mode)
+
+
+if __name__ == "__main__":
+    main()
\ No newline at end of file
b
diff -r 000000000000 -r bb5365381c8f sucos_max.xml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sucos_max.xml Wed Oct 02 12:57:54 2019 -0400
[
@@ -0,0 +1,85 @@
+<tool id="sucos_max_score" name="Max SuCOS score" version="0.1">
+    <description>- determine maximum SuCOS score of ligands against clustered fragment hits</description>
+    <macros>
+        <import>sucos_macros.xml</import>
+    </macros>
+    <expand macro="requirements"/>
+    <command detect_errors="aggressive"><![CDATA[
+        python '$__tool_directory__/sucos_max.py'
+            -i '$input'
+            -o '$output'
+            -m $mode
+        #for $cluster in $clusters
+            '$cluster'
+        #end for
+    ]]></command>
+    <inputs>
+        <param name="input" type="data" format="sdf" label="Ligands to be scored" help="Input in SDF format." />
+        <param name="clusters" type="data" format="sdf" multiple="true" label="Set of clusters to score against" help="Clusters in SDF format." />
+        <param name="mode" type="select" value="max" label="Mode">
+            <option value="max">Max score</option>
+            <option value="cum">Cumulative score</option>
+        </param>
+    </inputs>
+    <outputs>
+        <data format="sdf" name="output" label="The scored ligands"/>
+    </outputs>
+    <tests>
+        <test>
+            <param name="input" ftype="sdf" value="sucos_cluster.sdf"/>
+            <param name="clusters" ftype="sdf" value="cluster1.sdf,cluster2.sdf,cluster3.sdf,cluster4.sdf,cluster5.sdf,cluster6.sdf"/>
+            <param name="mode" value="max"/>
+            <output name="output" ftype="sdf">
+                <assert_contents>
+                    <has_text text="Max_SuCOS_Score" />
+                </assert_contents>
+            </output>
+        </test>
+        <test>
+            <param name="input" ftype="sdf" value="sucos_cluster.sdf"/>
+            <param name="clusters" ftype="sdf" value="cluster1.sdf,cluster2.sdf,cluster3.sdf,cluster4.sdf,cluster5.sdf,cluster6.sdf"/>
+            <param name="mode" value="cum"/>
+            <output name="output" ftype="sdf">
+                <assert_contents>
+                    <has_text text="Cum_SuCOS_Score" />
+                </assert_contents>
+            </output>
+        </test>
+    </tests>
+    <help><![CDATA[
+
+.. class:: infomark
+
+**What it does**
+
+This tool determines the maximum SuCOS score of ligands, presumed to be potential follow on compounds, compared to a
+set of clustered reference compounds, presumed to be fragment screening hits. Each ligand to be scored is compared to
+all of the reference compounds with the highest score being recorded, along with the cluster it came from and the index
+of the molecule within that cluster.
+
+The original SuCOS code is on GitHub_ under a MIT license. The SuCOS work is described here_.
+
+.. _GitHub: https://github.com/susanhleung/SuCOS
+.. _here: https://chemrxiv.org/articles/SuCOS_is_Better_than_RMSD_for_Evaluating_Fragment_Elaboration_and_Docking_Poses/8100203
+
+.. class:: infomark
+
+**Input**
+
+The clustered reference compounds are likely to have been generated using the "Cluster ligands using SuCOS" tool and
+will comprise a SDF format file for each cluster. The ligands to be scored are supplied in a SDF file.
+
+.. class:: infomark
+
+**Output**
+
+The same SD file as the input ligands with a "Max_SuCOS_Score" property added containing the best (maximum) SuCOS score
+along with the "Max_SuCOS_FeatureMap_Score" and "Max_SuCOS_Tanimoto_Score" of that comparison.
+
+In addition, the "Max_SuCOS_Cluster" field shows the name of the cluster file that contained the molecule with this best 
+score and the "Max_SuCOS_Index" shows the index (first record is index 1) of that molecule in the file.
+
+    ]]></help>
+    <expand macro="citations"/>
+</tool>
+
b
diff -r 000000000000 -r bb5365381c8f test-data/cluster1.sdf
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test-data/cluster1.sdf Wed Oct 02 12:57:54 2019 -0400
b
@@ -0,0 +1,77 @@
+
+     RDKit          3D
+
+ 16 18  0  0  0  0  0  0  0  0999 V2000
+   19.9510   12.4320   19.9980 C   0  0  0  0  0  0  0  0  0  0  0  0
+   20.0820   11.0800   19.7160 C   0  0  0  0  0  0  0  0  0  0  0  0
+   20.2110   12.9210   21.2780 C   0  0  0  0  0  0  0  0  0  0  0  0
+   20.4730   10.2080   20.7160 C   0  0  0  0  0  0  0  0  0  0  0  0
+   20.6070   12.0470   22.2840 C   0  0  0  0  0  0  0  0  0  0  0  0
+   20.7310   10.6920   21.9840 C   0  0  0  0  0  0  0  0  0  0  0  0
+   20.8690   12.5020   23.5750 N   0  0  0  0  0  0  0  0  0  0  0  0
+   21.1210    9.8120   22.9630 N   0  0  0  0  0  0  0  0  0  0  0  0
+   21.2630   11.6100   24.5730 C   0  0  0  0  0  0  0  0  0  0  0  0
+   21.3860   10.2600   24.2390 C   0  0  0  0  0  0  0  0  0  0  0  0
+   21.5170   12.0970   25.8880 N   0  0  0  0  0  0  0  0  0  0  0  0
+   21.7700    9.2670   25.1440 N   0  0  0  0  0  0  0  0  0  0  0  0
+   20.6720   13.9160   27.1880 C   0  0  0  0  0  0  0  0  0  0  0  0
+   20.3000   12.6550   27.9160 C   0  0  0  0  0  0  0  0  0  0  0  0
+   21.7880   13.5100   26.2340 C   0  0  0  0  0  0  0  0  0  0  0  0
+   20.8880   11.5200   27.1000 C   0  0  0  0  0  0  0  0  0  0  0  0
+  2  1  2  0
+  3  1  1  0
+  4  2  1  0
+  5  3  2  0
+  6  4  2  0
+  6  5  1  0
+  7  5  1  0
+  8  6  1  0
+  9  7  2  0
+ 10  8  2  0
+ 10  9  1  0
+ 11  9  1  0
+ 12 10  1  0
+ 14 13  1  0
+ 15 13  1  0
+ 15 11  1  0
+ 16 11  1  0
+ 16 14  1  0
+M  END
+$$$$
+
+     RDKit          3D
+
+ 15 16  0  0  0  0  0  0  0  0999 V2000
+   18.6370   11.5460   19.0470 Cl  0  0  0  0  0  0  0  0  0  0  0  0
+   19.3410   11.4910   20.6100 C   0  0  0  0  0  0  0  0  0  0  0  0
+   19.1300   12.5410   21.5090 C   0  0  0  0  0  0  0  0  0  0  0  0
+   20.1120   10.3920   20.9640 C   0  0  0  0  0  0  0  0  0  0  0  0
+   19.7080   12.5060   22.7780 C   0  0  0  0  0  0  0  0  0  0  0  0
+   20.6710   10.3800   22.2200 C   0  0  0  0  0  0  0  0  0  0  0  0
+   20.4820   11.4070   23.1080 C   0  0  0  0  0  0  0  0  0  0  0  0
+   21.4530    9.4460   22.7560 N   0  0  0  0  0  0  0  0  0  0  0  0
+   21.7320    9.9040   23.9840 C   0  0  0  0  0  0  0  0  0  0  0  0
+   21.1510   11.1000   24.2190 N   0  0  0  0  0  0  0  0  0  0  0  0
+   22.5310    9.1910   24.8790 N   0  0  0  0  0  0  0  0  0  0  0  0
+   21.2170   11.9110   25.4550 C   0  0  0  0  0  0  0  0  0  0  0  0
+   20.4620   11.2450   26.6090 C   0  0  0  0  0  0  0  0  0  0  0  0
+   21.0350   11.5770   27.9760 C   0  0  0  0  0  0  0  0  0  0  0  0
+   20.9480   12.9640   28.2400 O   0  0  0  0  0  0  0  0  0  0  0  0
+  2  1  1  0
+  3  2  2  0
+  4  2  1  0
+  5  3  1  0
+  6  4  2  0
+  7  6  1  0
+  7  5  2  0
+  8  6  1  0
+  9  8  2  0
+ 10  9  1  0
+ 10  7  1  0
+ 11  9  1  0
+ 12 10  1  0
+ 13 12  1  0
+ 14 13  1  0
+ 15 14  1  0
+M  END
+$$$$
b
diff -r 000000000000 -r bb5365381c8f test-data/cluster2.sdf
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test-data/cluster2.sdf Wed Oct 02 12:57:54 2019 -0400
b
@@ -0,0 +1,167 @@
+
+     RDKit          3D
+
+ 10 10  0  0  0  0  0  0  0  0999 V2000
+   24.4730   11.1990   19.8620 C   0  0  0  0  0  0  0  0  0  0  0  0
+   25.5530   12.0600   20.0930 C   0  0  0  0  0  0  0  0  0  0  0  0
+   23.9840   11.0460   18.5670 C   0  0  0  0  0  0  0  0  0  0  0  0
+   23.8330   10.4330   20.9970 C   0  0  0  0  0  0  0  0  0  0  0  0
+   26.1360   12.7690   19.0380 C   0  0  0  0  0  0  0  0  0  0  0  0
+   24.5550   11.7420   17.5050 C   0  0  0  0  0  0  0  0  0  0  0  0
+   22.3160   10.6870   21.0270 C   0  0  0  0  0  0  0  0  0  0  0  0
+   25.6290   12.6010   17.7470 C   0  0  0  0  0  0  0  0  0  0  0  0
+   21.6740   10.0940   22.2270 N   0  0  0  0  0  0  0  0  0  0  0  0
+   26.1850   13.2880   16.6940 O   0  0  0  0  0  0  0  0  0  0  0  0
+  2  1  2  0
+  3  1  1  0
+  4  1  1  0
+  5  2  1  0
+  6  3  2  0
+  7  4  1  0
+  8  6  1  0
+  8  5  2  0
+  9  7  1  0
+ 10  8  1  0
+M  END
+$$$$
+
+     RDKit          3D
+
+ 11 11  0  0  0  0  0  0  0  0999 V2000
+   23.8350   12.2020   19.5760 C   0  0  0  0  0  0  0  0  0  0  0  0
+   23.4520   11.9220   18.2610 C   0  0  0  0  0  0  0  0  0  0  0  0
+   25.0420   12.8700   19.8340 C   0  0  0  0  0  0  0  0  0  0  0  0
+   22.9370   11.8100   20.7250 C   0  0  0  0  0  0  0  0  0  0  0  0
+   24.2680   12.2940   17.1940 C   0  0  0  0  0  0  0  0  0  0  0  0
+   25.8750   13.2520   18.7790 C   0  0  0  0  0  0  0  0  0  0  0  0
+   22.8350   10.2970   20.9620 C   0  0  1  0  0  0  0  0  0  0  0  0
+   25.4680   12.9560   17.4710 C   0  0  0  0  0  0  0  0  0  0  0  0
+   24.1570    9.7480   21.5040 C   0  0  0  0  0  0  0  0  0  0  0  0
+   21.7030    9.9910   21.9220 N   0  0  0  0  0  0  0  0  0  0  0  0
+   26.2630   13.3220   16.4230 O   0  0  0  0  0  0  0  0  0  0  0  0
+  2  1  2  0
+  3  1  1  0
+  4  1  1  0
+  5  2  1  0
+  6  3  2  0
+  7  4  1  0
+  8  6  1  0
+  8  5  2  0
+  7  9  1  1
+ 10  7  1  0
+ 11  8  1  0
+M  END
+$$$$
+
+     RDKit          3D
+
+ 12 12  0  0  0  0  0  0  0  0999 V2000
+   26.5880   11.6480   19.1670 C   0  0  0  0  0  0  0  0  0  0  0  0
+   25.9260   11.0670   20.2530 C   0  0  0  0  0  0  0  0  0  0  0  0
+   25.8770   11.8420   17.9690 C   0  0  0  0  0  0  0  0  0  0  0  0
+   28.0300   12.0720   19.2730 C   0  0  0  0  0  0  0  0  0  0  0  0
+   24.5820   10.6900   20.1310 C   0  0  0  0  0  0  0  0  0  0  0  0
+   24.5420   11.4720   17.8340 C   0  0  0  0  0  0  0  0  0  0  0  0
+   26.4990   12.4120   16.8870 O   0  0  0  0  0  0  0  0  0  0  0  0
+   28.9860   10.8940   19.5000 C   0  0  0  0  0  0  0  0  0  0  0  0
+   23.8950   10.8910   18.9250 C   0  0  0  0  0  0  0  0  0  0  0  0
+   23.8700   10.0590   21.2980 C   0  0  0  0  0  0  0  0  0  0  0  0
+   22.8110   11.0000   21.8820 C   0  0  0  0  0  0  0  0  0  0  0  0
+   21.6380   10.2010   22.3970 N   0  0  0  0  0  0  0  0  0  0  0  0
+  2  1  2  0
+  3  1  1  0
+  4  1  1  0
+  5  2  1  0
+  6  3  2  0
+  7  3  1  0
+  8  4  1  0
+  9  5  2  0
+  9  6  1  0
+ 10  5  1  0
+ 11 10  1  0
+ 12 11  1  0
+M  END
+$$$$
+
+     RDKit          3D
+
+ 16 17  0  0  0  0  0  0  0  0999 V2000
+   26.3090   11.5670   19.1200 C   0  0  0  0  0  0  0  0  0  0  0  0
+   27.7750   11.8580   19.3620 C   0  0  0  0  0  0  0  0  0  0  0  0
+   25.5460   10.8930   20.0800 C   0  0  0  0  0  0  0  0  0  0  0  0
+   25.6820   11.9660   17.9260 C   0  0  0  0  0  0  0  0  0  0  0  0
+   27.9150   13.1100   20.2510 C   0  0  0  0  0  0  0  0  0  0  0  0
+   28.4910   10.6030   19.9180 C   0  0  0  0  0  0  0  0  0  0  0  0
+   24.1900   10.6200   19.8540 C   0  0  0  0  0  0  0  0  0  0  0  0
+   24.3290   11.7060   17.6830 C   0  0  0  0  0  0  0  0  0  0  0  0
+   26.3920   12.6330   16.9610 O   0  0  0  0  0  0  0  0  0  0  0  0
+   29.3630   13.3270   20.6990 C   0  0  0  0  0  0  0  0  0  0  0  0
+   29.8080   10.8590   20.6700 C   0  0  0  0  0  0  0  0  0  0  0  0
+   23.5890   11.0260   18.6540 C   0  0  0  0  0  0  0  0  0  0  0  0
+   23.3960    9.8840   20.9090 C   0  0  0  0  0  0  0  0  0  0  0  0
+   29.7810   12.1210   21.5440 C   0  0  0  0  0  0  0  0  0  0  0  0
+   22.0220   10.5180   21.1760 C   0  0  0  0  0  0  0  0  0  0  0  0
+   21.2950    9.8120   22.2580 N   0  0  0  0  0  0  0  0  0  0  0  0
+  2  1  1  0
+  3  1  2  0
+  4  1  1  0
+  5  2  1  0
+  6  2  1  0
+  7  3  1  0
+  8  4  2  0
+  9  4  1  0
+ 10  5  1  0
+ 11  6  1  0
+ 12  7  2  0
+ 12  8  1  0
+ 13  7  1  0
+ 14 11  1  0
+ 14 10  1  0
+ 15 13  1  0
+ 16 15  1  0
+M  END
+$$$$
+
+     RDKit          3D
+
+ 18 20  0  0  0  0  0  0  0  0999 V2000
+   28.6970   10.5240   20.4750 C   0  0  0  0  0  0  0  0  0  0  0  0
+   27.9220   11.6800   20.9560 N   0  0  0  0  0  0  0  0  0  0  0  0
+   28.7880   12.6650   21.6350 C   0  0  0  0  0  0  0  0  0  0  0  0
+   27.0810   12.2010   19.9710 C   0  0  0  0  0  0  0  0  0  0  0  0
+   27.4190   13.2930   19.2740 N   0  0  0  0  0  0  0  0  0  0  0  0
+   26.6450   13.8320   18.3200 C   0  0  0  0  0  0  0  0  0  0  0  0
+   25.4810   13.2870   17.9980 N   0  0  0  0  0  0  0  0  0  0  0  0
+   25.0290   12.1840   18.6310 C   0  0  0  0  0  0  0  0  0  0  0  0
+   23.7860   11.6150   18.3040 C   0  0  0  0  0  0  0  0  0  0  0  0
+   23.3430   10.5040   18.9720 C   0  0  0  0  0  0  0  0  0  0  0  0
+   24.1080    9.9180   19.9810 C   0  0  0  0  0  0  0  0  0  0  0  0
+   25.3250   10.4360   20.3200 C   0  0  0  0  0  0  0  0  0  0  0  0
+   25.8200   11.5870   19.6640 C   0  0  0  0  0  0  0  0  0  0  0  0
+   27.1160   14.9710   17.6690 N   0  0  0  0  0  0  0  0  0  0  0  0
+   27.3480   16.1150   18.5710 C   0  0  0  0  0  0  0  0  0  0  0  0
+   27.6660   17.2890   17.6050 C   0  0  0  0  0  0  0  0  0  0  0  0
+   26.8670   16.9430   16.3140 C   0  0  0  0  0  0  0  0  0  0  0  0
+   26.3130   15.5200   16.5590 C   0  0  0  0  0  0  0  0  0  0  0  0
+  2  1  1  0
+  3  2  1  0
+  4  2  1  0
+  5  4  2  0
+  6  5  1  0
+  7  6  2  0
+  8  7  1  0
+  9  8  2  0
+ 10  9  1  0
+ 11 10  2  0
+ 12 11  1  0
+ 13 12  2  0
+ 13  8  1  0
+ 13  4  1  0
+ 14  6  1  0
+ 15 14  1  0
+ 16 15  1  0
+ 17 16  1  0
+ 18 14  1  0
+ 18 17  1  0
+M  END
+$$$$
b
diff -r 000000000000 -r bb5365381c8f test-data/cluster3.sdf
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test-data/cluster3.sdf Wed Oct 02 12:57:54 2019 -0400
b
b'@@ -0,0 +1,1024 @@\n+\n+     RDKit          3D\n+\n+ 19 20  0  0  0  0  0  0  0  0999 V2000\n+   25.8690   10.6750   17.9260 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   24.7660   11.4770   18.5500 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   24.1650   12.4880   17.8120 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   23.1480   13.2570   18.3640 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   22.7300   13.0010   19.6620 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   21.6190   13.8450   20.2480 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   23.3280   11.9670   20.4090 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   22.9000   11.7560   21.6900 O   0  0  0  0  0  0  0  0  0  0  0  0\n+   23.1990   10.4520   22.2010 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   22.3800   10.3250   23.4930 C   0  0  1  0  0  0  0  0  0  0  0  0\n+   22.7510    9.1510   24.2170 O   0  0  0  0  0  0  0  0  0  0  0  0\n+   22.5930   11.5910   24.3570 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   22.2540   11.3630   25.7760 N   0  0  0  0  0  0  0  0  0  0  0  0\n+   22.5710   12.5910   26.5330 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   22.1760   12.4110   28.0100 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   20.7810   12.0710   28.1350 O   0  0  0  0  0  0  0  0  0  0  0  0\n+   20.5060   10.8660   27.4060 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   20.8170   11.0700   25.9210 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   24.3600   11.2090   19.8480 C   0  0  0  0  0  0  0  0  0  0  0  0\n+  2  1  1  0\n+  3  2  2  0\n+  4  3  1  0\n+  5  4  2  0\n+  6  5  1  0\n+  7  5  1  0\n+  8  7  1  0\n+  9  8  1  0\n+ 10  9  1  0\n+ 10 11  1  1\n+ 12 10  1  0\n+ 13 12  1  0\n+ 14 13  1  0\n+ 15 14  1  0\n+ 16 15  1  0\n+ 17 16  1  0\n+ 18 17  1  0\n+ 18 13  1  0\n+ 19  7  2  0\n+ 19  2  1  0\n+M  END\n+$$$$\n+\n+     RDKit          3D\n+\n+ 11 12  0  0  0  0  0  0  0  0999 V2000\n+   22.8090    9.2070   24.2800 N   0  0  0  0  0  0  0  0  0  0  0  0\n+   22.4710   10.1080   23.3190 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   21.8900    9.6340   22.1960 N   0  0  0  0  0  0  0  0  0  0  0  0\n+   21.5680   10.5170   21.2440 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   21.7580   11.8790   21.3690 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   22.3130   12.3920   22.5320 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   22.5210   13.7530   22.7260 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   23.0810   14.2110   23.9020 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   23.4470   13.3190   24.8860 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   23.2450   11.9700   24.7110 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   22.6750   11.4850   23.5440 C   0  0  0  0  0  0  0  0  0  0  0  0\n+  2  1  1  0\n+  3  2  2  0\n+  4  3  1  0\n+  5  4  2  0\n+  6  5  1  0\n+  7  6  2  0\n+  8  7  1  0\n+  9  8  2  0\n+ 10  9  1  0\n+ 11  2  1  0\n+ 11 10  2  0\n+ 11  6  1  0\n+M  END\n+$$$$\n+\n+     RDKit          3D\n+\n+ 11 12  0  0  0  0  0  0  0  0999 V2000\n+   22.7770    9.1670   24.9740 N   0  0  0  0  0  0  0  0  0  0  0  0\n+   22.4280   10.0140   24.0880 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   22.6770   11.3690   24.2670 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   22.2930   12.2600   23.2950 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   21.6430   11.7880   22.1650 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   21.2220   12.6270   21.1460 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   20.5740   12.1120   20.0440 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   20.3400   10.7540   19.9450 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   20.7580    9.9010   20.9470 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   21.4090   10.3980   22.0610 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   21.7960    9.5320   23.0070 N   0  0  0  0  0  0  0  0  0  0  0  0\n+  2  1  1  0\n+  3  2  2  0\n+  4  3  1  0\n+  5  4  2  0\n+  6  5  1  0\n+  7  6  2  0\n+  8  7  1  0\n+  9  8  2  0\n+ 10  9  1  0\n+ 10  5  1  0\n+ 11 10  2  0\n+ 11  2  1  0\n+M  END\n+$$$$\n+\n+     RDKit          3D\n+\n+ 15 16  0  0  0  0  0  0  0  0999 V2000\n+   22.4510    9.0090   24.4670 N   0  0  0  0  0  0  0  0  0  0  0  0\n+   22.5180   10.3550   24.1060 C   0  0  0  0  0  0  0  0  0  0'..b'9.3450    9.6270   21.1760 O   0  0  0  0  0  0  0  0  0  0  0  0\n+   22.4790   11.8080   24.2920 S   0  0  0  0  0  0  0  0  0  0  0  0\n+   19.5140   11.7630   22.5130 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   22.7100    9.2150   24.7670 N   0  0  0  0  0  0  0  0  0  0  0  0\n+   20.5550    9.7530   20.5440 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   22.8590   10.7120   20.6250 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   24.1020   10.1890   21.0270 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   25.2620   10.3730   20.2980 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   22.8630   11.5080   19.3970 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   21.5800   10.5280   21.4490 C   0  0  2  0  0  0  0  0  0  0  0  0\n+   20.9500   11.9060   21.9290 C   0  0  2  0  0  0  0  0  0  0  0  0\n+   21.9600   12.7150   22.7910 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   22.3230   10.0930   23.7780 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   24.0040   11.6730   18.6170 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   25.2010   11.1170   19.0930 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   21.7570   12.0240   18.8700 F   0  0  0  0  0  0  0  0  0  0  0  0\n+   26.3200   11.2980   18.4090 F   0  0  0  0  0  0  0  0  0  0  0  0\n+  3  1  1  0\n+  5  1  1  0\n+  7  3  1  0\n+  9  8  2  0\n+ 10  9  1  0\n+ 11  8  1  0\n+ 12  7  1  0\n+ 12  8  1  6\n+ 12  2  1  0\n+ 13 12  1  0\n+ 13  5  1  1\n+ 14 13  1  0\n+ 14  4  1  0\n+ 15  6  1  0\n+ 15  2  2  0\n+ 15  4  1  0\n+ 16 11  2  0\n+ 17 10  2  0\n+ 17 16  1  0\n+ 18 11  1  0\n+ 19 17  1  0\n+M  END\n+$$$$\n+\n+     RDKit          3D\n+\n+ 16 17  0  0  0  0  0  0  0  0999 V2000\n+   20.6950    9.9560   20.8820 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   22.2050    9.8930   22.6900 N   0  0  0  0  0  0  0  0  0  0  0  0\n+   23.0060   12.0970   24.2220 S   0  0  0  0  0  0  0  0  0  0  0  0\n+   21.8910   10.6980   21.5060 C   0  0  2  0  0  0  0  0  0  0  0  0\n+   22.8690    9.5480   24.8150 N   0  0  0  0  0  0  0  0  0  0  0  0\n+   21.4800   12.1250   21.9040 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   22.5630   12.8770   22.6580 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   22.6270   10.3910   23.7940 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   23.1060   10.7640   20.5410 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   24.3720   10.2320   20.8590 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   25.4690   10.3640   20.0140 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   25.3420   11.0350   18.7800 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   24.1030   11.5640   18.3850 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   23.0130   11.4340   19.2760 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   21.8840   12.0230   18.8800 F   0  0  0  0  0  0  0  0  0  0  0  0\n+   26.4280   11.2380   18.0020 F   0  0  0  0  0  0  0  0  0  0  0  0\n+  4  1  1  6\n+  4  2  1  0\n+  6  4  1  0\n+  7  6  1  0\n+  7  3  1  0\n+  8  5  1  0\n+  8  2  2  0\n+  8  3  1  0\n+  9  4  1  0\n+ 10  9  2  0\n+ 11 10  1  0\n+ 12 11  2  0\n+ 13 12  1  0\n+ 14  9  1  0\n+ 14 13  2  0\n+ 15 14  1  0\n+ 16 12  1  0\n+M  END\n+$$$$\n+\n+     RDKit          3D\n+\n+ 11 12  0  0  0  0  0  0  0  0999 V2000\n+   23.8920   10.9750   19.7100 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   23.1430    9.6540   19.8400 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   23.7820   11.7530   20.9950 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   21.6770    9.8870   20.1680 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   22.1750   12.7870   22.6090 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   22.3660   10.1400   23.6660 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   22.3180   11.9530   21.3510 C   0  0  2  0  0  0  0  0  0  0  0  0\n+   21.5250   10.6490   21.4640 C   0  0  2  0  0  0  0  0  0  0  0  0\n+   22.7380    9.3100   24.6900 N   0  0  0  0  0  0  0  0  0  0  0  0\n+   21.9210    9.6990   22.5310 N   0  0  0  0  0  0  0  0  0  0  0  0\n+   22.5620   11.8400   24.1130 S   0  0  0  0  0  0  0  0  0  0  0  0\n+  2  1  1  0\n+  3  1  1  0\n+  4  2  1  0\n+  7  3  1  1\n+  7  5  1  0\n+  8  4  1  6\n+  8  7  1  0\n+  9  6  1  0\n+ 10  8  1  0\n+ 10  6  2  0\n+ 11  6  1  0\n+ 11  5  1  0\n+M  END\n+$$$$\n'
b
diff -r 000000000000 -r bb5365381c8f test-data/cluster4.sdf
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test-data/cluster4.sdf Wed Oct 02 12:57:54 2019 -0400
b
@@ -0,0 +1,47 @@
+
+     RDKit          3D
+
+ 20 21  0  0  0  0  0  0  0  0999 V2000
+   21.2480   11.2160   24.5450 C   0  0  0  0  0  0  0  0  0  0  0  0
+   21.1020   11.0880   25.9790 N   0  0  0  0  0  0  0  0  0  0  0  0
+   20.1520   11.7400   26.6430 C   0  0  0  0  0  0  0  0  0  0  0  0
+   19.2750   12.3940   26.0980 O   0  0  0  0  0  0  0  0  0  0  0  0
+   20.2050   11.6230   28.1500 C   0  0  0  0  0  0  0  0  0  0  0  0
+   20.1270   12.9990   28.8020 C   0  0  0  0  0  0  0  0  0  0  0  0
+   20.9520   13.0380   30.0790 C   0  0  0  0  0  0  0  0  0  0  0  0
+   22.6540   13.4720   29.6460 S   0  0  0  0  0  0  0  0  0  0  0  0
+   22.7090   11.4410   24.1690 C   0  0  0  0  0  0  0  0  0  0  0  0
+   22.8180   11.5780   22.6520 C   0  0  0  0  0  0  0  0  0  0  0  0
+   22.3510   10.3050   22.0930 N   0  0  0  0  0  0  0  0  0  0  0  0
+   20.9200   10.1140   22.3280 C   0  0  0  0  0  0  0  0  0  0  0  0
+   20.7360    9.9660   23.8360 C   0  0  0  0  0  0  0  0  0  0  0  0
+   22.5750   10.2440   20.6540 C   0  0  0  0  0  0  0  0  0  0  0  0
+   23.9890   10.6020   20.2540 C   0  0  0  0  0  0  0  0  0  0  0  0
+   25.0820    9.9220   20.7960 C   0  0  0  0  0  0  0  0  0  0  0  0
+   26.3780   10.2710   20.4140 C   0  0  0  0  0  0  0  0  0  0  0  0
+   26.5780   11.2950   19.4850 C   0  0  0  0  0  0  0  0  0  0  0  0
+   25.4840   11.9720   18.9430 C   0  0  0  0  0  0  0  0  0  0  0  0
+   24.1890   11.6250   19.3240 C   0  0  0  0  0  0  0  0  0  0  0  0
+  1  2  1  0
+  3  2  1  0
+  4  3  2  0
+  5  3  1  0
+  6  5  1  0
+  7  6  1  0
+  8  7  1  0
+  9  1  1  0
+ 10  9  1  0
+ 11 10  1  0
+ 12 11  1  0
+ 13 12  1  0
+ 13  1  1  0
+ 14 11  1  0
+ 15 14  1  0
+ 16 15  2  0
+ 17 16  1  0
+ 18 17  2  0
+ 19 18  1  0
+ 20 15  1  0
+ 20 19  2  0
+M  END
+$$$$
b
diff -r 000000000000 -r bb5365381c8f test-data/cluster5.sdf
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test-data/cluster5.sdf Wed Oct 02 12:57:54 2019 -0400
b
@@ -0,0 +1,47 @@
+
+     RDKit          3D
+
+ 20 21  0  0  0  0  0  0  0  0999 V2000
+   23.0110   10.6350   19.8150 C   0  0  0  0  0  0  0  0  0  0  0  0
+   24.2670   11.1650   19.1280 C   0  0  0  0  0  0  0  0  0  0  0  0
+   25.2960   11.1360   20.1630 N   0  0  0  0  0  0  0  0  0  0  0  0
+   24.9890   12.0920   21.2290 C   0  0  0  0  0  0  0  0  0  0  0  0
+   23.7420   11.5350   21.9210 C   0  0  2  0  0  0  0  0  0  0  0  0
+   22.6410   11.4290   20.9740 N   0  0  0  0  0  0  0  0  0  0  0  0
+   26.6000   11.4040   19.5610 C   0  0  0  0  0  0  0  0  0  0  0  0
+   27.7300   10.8900   20.4300 C   0  0  0  0  0  0  0  0  0  0  0  0
+   27.6290    9.6500   21.0680 C   0  0  0  0  0  0  0  0  0  0  0  0
+   28.6700    9.1850   21.8700 C   0  0  0  0  0  0  0  0  0  0  0  0
+   29.8180    9.9600   22.0270 C   0  0  0  0  0  0  0  0  0  0  0  0
+   29.9260   11.1970   21.3880 C   0  0  0  0  0  0  0  0  0  0  0  0
+   28.8800   11.6630   20.5900 C   0  0  0  0  0  0  0  0  0  0  0  0
+   23.3760   12.3720   23.1130 C   0  0  0  0  0  0  0  0  0  0  0  0
+   24.0930   12.1770   24.2210 N   0  0  0  0  0  0  0  0  0  0  0  0
+   22.4610   13.1780   23.0440 O   0  0  0  0  0  0  0  0  0  0  0  0
+   23.8850   12.9460   25.4360 C   0  0  0  0  0  0  0  0  0  0  0  0
+   24.7100   14.2290   25.4520 C   0  0  0  0  0  0  0  0  0  0  0  0
+   26.3830   13.8570   26.0370 S   0  0  0  0  0  0  0  0  0  0  0  0
+   30.8240    9.5080   22.7950 F   0  0  0  0  0  0  0  0  0  0  0  0
+  2  1  1  0
+  3  2  1  0
+  4  3  1  0
+  5  4  1  0
+  6  1  1  0
+  6  5  1  0
+  7  3  1  0
+  8  7  1  0
+  9  8  2  0
+ 10  9  1  0
+ 11 10  2  0
+ 12 11  1  0
+ 13  8  1  0
+ 13 12  2  0
+  5 14  1  1
+ 15 14  1  0
+ 16 14  2  0
+ 17 15  1  0
+ 18 17  1  0
+ 19 18  1  0
+ 20 11  1  0
+M  END
+$$$$
b
diff -r 000000000000 -r bb5365381c8f test-data/cluster6.sdf
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test-data/cluster6.sdf Wed Oct 02 12:57:54 2019 -0400
b
@@ -0,0 +1,22 @@
+
+     RDKit          3D
+
+  8  8  0  0  0  0  0  0  0  0999 V2000
+   43.2120    1.2010   21.1900 N   0  0  0  0  0  0  0  0  0  0  0  0
+   42.0970    1.7030   22.0340 C   0  0  2  0  0  0  0  0  0  0  0  0
+   41.2120    2.6840   21.2450 C   0  0  0  0  0  0  0  0  0  0  0  0
+   41.4260    2.9540   20.0390 O   0  0  0  0  0  0  0  0  0  0  0  0
+   42.6930    2.1910   23.3430 C   0  0  0  0  0  0  0  0  0  0  0  0
+   44.2130    1.9390   23.2340 C   0  0  0  0  0  0  0  0  0  0  0  0
+   44.4930    1.6950   21.7590 C   0  0  0  0  0  0  0  0  0  0  0  0
+   40.1570    3.2440   21.9570 N   0  0  0  0  0  0  0  0  0  0  0  0
+  2  1  1  0
+  2  3  1  6
+  4  3  2  0
+  5  2  1  0
+  6  5  1  0
+  7  1  1  0
+  7  6  1  0
+  8  3  1  0
+M  END
+$$$$
b
diff -r 000000000000 -r bb5365381c8f test-data/split_1.sdf
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test-data/split_1.sdf Wed Oct 02 12:57:54 2019 -0400
b
b'@@ -0,0 +1,389 @@\n+\n+     RDKit          3D\n+\n+ 19 20  0  0  0  0  0  0  0  0999 V2000\n+   25.8690   10.6750   17.9260 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   24.7660   11.4770   18.5500 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   24.1650   12.4880   17.8120 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   23.1480   13.2570   18.3640 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   22.7300   13.0010   19.6620 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   21.6190   13.8450   20.2480 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   23.3280   11.9670   20.4090 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   22.9000   11.7560   21.6900 O   0  0  0  0  0  0  0  0  0  0  0  0\n+   23.1990   10.4520   22.2010 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   22.3800   10.3250   23.4930 C   0  0  1  0  0  0  0  0  0  0  0  0\n+   22.7510    9.1510   24.2170 O   0  0  0  0  0  0  0  0  0  0  0  0\n+   22.5930   11.5910   24.3570 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   22.2540   11.3630   25.7760 N   0  0  0  0  0  0  0  0  0  0  0  0\n+   22.5710   12.5910   26.5330 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   22.1760   12.4110   28.0100 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   20.7810   12.0710   28.1350 O   0  0  0  0  0  0  0  0  0  0  0  0\n+   20.5060   10.8660   27.4060 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   20.8170   11.0700   25.9210 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   24.3600   11.2090   19.8480 C   0  0  0  0  0  0  0  0  0  0  0  0\n+  2  1  1  0\n+  3  2  2  0\n+  4  3  1  0\n+  5  4  2  0\n+  6  5  1  0\n+  7  5  1  0\n+  8  7  1  0\n+  9  8  1  0\n+ 10  9  1  0\n+ 10 11  1  1\n+ 12 10  1  0\n+ 13 12  1  0\n+ 14 13  1  0\n+ 15 14  1  0\n+ 16 15  1  0\n+ 17 16  1  0\n+ 18 17  1  0\n+ 18 13  1  0\n+ 19  7  2  0\n+ 19  2  1  0\n+M  END\n+$$$$\n+\n+     RDKit          3D\n+\n+ 11 12  0  0  0  0  0  0  0  0999 V2000\n+   22.8090    9.2070   24.2800 N   0  0  0  0  0  0  0  0  0  0  0  0\n+   22.4710   10.1080   23.3190 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   21.8900    9.6340   22.1960 N   0  0  0  0  0  0  0  0  0  0  0  0\n+   21.5680   10.5170   21.2440 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   21.7580   11.8790   21.3690 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   22.3130   12.3920   22.5320 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   22.5210   13.7530   22.7260 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   23.0810   14.2110   23.9020 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   23.4470   13.3190   24.8860 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   23.2450   11.9700   24.7110 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   22.6750   11.4850   23.5440 C   0  0  0  0  0  0  0  0  0  0  0  0\n+  2  1  1  0\n+  3  2  2  0\n+  4  3  1  0\n+  5  4  2  0\n+  6  5  1  0\n+  7  6  2  0\n+  8  7  1  0\n+  9  8  2  0\n+ 10  9  1  0\n+ 11  2  1  0\n+ 11 10  2  0\n+ 11  6  1  0\n+M  END\n+$$$$\n+\n+     RDKit          3D\n+\n+ 11 12  0  0  0  0  0  0  0  0999 V2000\n+   22.7770    9.1670   24.9740 N   0  0  0  0  0  0  0  0  0  0  0  0\n+   22.4280   10.0140   24.0880 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   22.6770   11.3690   24.2670 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   22.2930   12.2600   23.2950 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   21.6430   11.7880   22.1650 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   21.2220   12.6270   21.1460 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   20.5740   12.1120   20.0440 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   20.3400   10.7540   19.9450 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   20.7580    9.9010   20.9470 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   21.4090   10.3980   22.0610 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   21.7960    9.5320   23.0070 N   0  0  0  0  0  0  0  0  0  0  0  0\n+  2  1  1  0\n+  3  2  2  0\n+  4  3  1  0\n+  5  4  2  0\n+  6  5  1  0\n+  7  6  2  0\n+  8  7  1  0\n+  9  8  2  0\n+ 10  9  1  0\n+ 10  5  1  0\n+ 11 10  2  0\n+ 11  2  1  0\n+M  END\n+$$$$\n+\n+     RDKit          3D\n+\n+ 15 16  0  0  0  0  0  0  0  0999 V2000\n+   22.4510    9.0090   24.4670 N   0  0  0  0  0  0  0  0  0  0  0  0\n+   22.5180   10.3550   24.1060 C   0  0  0  0  0  0  0  0  0  0 '..b'   0  0  0  0  0  0  0  0  0  0  0  0\n+   22.6540   13.4720   29.6460 S   0  0  0  0  0  0  0  0  0  0  0  0\n+   22.7090   11.4410   24.1690 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   22.8180   11.5780   22.6520 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   22.3510   10.3050   22.0930 N   0  0  0  0  0  0  0  0  0  0  0  0\n+   20.9200   10.1140   22.3280 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   20.7360    9.9660   23.8360 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   22.5750   10.2440   20.6540 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   23.9890   10.6020   20.2540 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   25.0820    9.9220   20.7960 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   26.3780   10.2710   20.4140 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   26.5780   11.2950   19.4850 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   25.4840   11.9720   18.9430 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   24.1890   11.6250   19.3240 C   0  0  0  0  0  0  0  0  0  0  0  0\n+  1  2  1  0\n+  3  2  1  0\n+  4  3  2  0\n+  5  3  1  0\n+  6  5  1  0\n+  7  6  1  0\n+  8  7  1  0\n+  9  1  1  0\n+ 10  9  1  0\n+ 11 10  1  0\n+ 12 11  1  0\n+ 13 12  1  0\n+ 13  1  1  0\n+ 14 11  1  0\n+ 15 14  1  0\n+ 16 15  2  0\n+ 17 16  1  0\n+ 18 17  2  0\n+ 19 18  1  0\n+ 20 15  1  0\n+ 20 19  2  0\n+M  END\n+$$$$\n+\n+     RDKit          3D\n+\n+ 20 21  0  0  0  0  0  0  0  0999 V2000\n+   23.0110   10.6350   19.8150 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   24.2670   11.1650   19.1280 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   25.2960   11.1360   20.1630 N   0  0  0  0  0  0  0  0  0  0  0  0\n+   24.9890   12.0920   21.2290 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   23.7420   11.5350   21.9210 C   0  0  2  0  0  0  0  0  0  0  0  0\n+   22.6410   11.4290   20.9740 N   0  0  0  0  0  0  0  0  0  0  0  0\n+   26.6000   11.4040   19.5610 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   27.7300   10.8900   20.4300 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   27.6290    9.6500   21.0680 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   28.6700    9.1850   21.8700 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   29.8180    9.9600   22.0270 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   29.9260   11.1970   21.3880 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   28.8800   11.6630   20.5900 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   23.3760   12.3720   23.1130 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   24.0930   12.1770   24.2210 N   0  0  0  0  0  0  0  0  0  0  0  0\n+   22.4610   13.1780   23.0440 O   0  0  0  0  0  0  0  0  0  0  0  0\n+   23.8850   12.9460   25.4360 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   24.7100   14.2290   25.4520 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   26.3830   13.8570   26.0370 S   0  0  0  0  0  0  0  0  0  0  0  0\n+   30.8240    9.5080   22.7950 F   0  0  0  0  0  0  0  0  0  0  0  0\n+  2  1  1  0\n+  3  2  1  0\n+  4  3  1  0\n+  5  4  1  0\n+  6  1  1  0\n+  6  5  1  0\n+  7  3  1  0\n+  8  7  1  0\n+  9  8  2  0\n+ 10  9  1  0\n+ 11 10  2  0\n+ 12 11  1  0\n+ 13  8  1  0\n+ 13 12  2  0\n+  5 14  1  1\n+ 15 14  1  0\n+ 16 14  2  0\n+ 17 15  1  0\n+ 18 17  1  0\n+ 19 18  1  0\n+ 20 11  1  0\n+M  END\n+$$$$\n+\n+     RDKit          3D\n+\n+ 10 10  0  0  0  0  0  0  0  0999 V2000\n+   24.4730   11.1990   19.8620 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   25.5530   12.0600   20.0930 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   23.9840   11.0460   18.5670 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   23.8330   10.4330   20.9970 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   26.1360   12.7690   19.0380 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   24.5550   11.7420   17.5050 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   22.3160   10.6870   21.0270 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   25.6290   12.6010   17.7470 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   21.6740   10.0940   22.2270 N   0  0  0  0  0  0  0  0  0  0  0  0\n+   26.1850   13.2880   16.6940 O   0  0  0  0  0  0  0  0  0  0  0  0\n+  2  1  2  0\n+  3  1  1  0\n+  4  1  1  0\n+  5  2  1  0\n+  6  3  2  0\n+  7  4  1  0\n+  8  6  1  0\n+  8  5  2  0\n+  9  7  1  0\n+ 10  8  1  0\n+M  END\n+$$$$\n'
b
diff -r 000000000000 -r bb5365381c8f test-data/split_2.sdf
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test-data/split_2.sdf Wed Oct 02 12:57:54 2019 -0400
b
b'@@ -0,0 +1,385 @@\n+\n+     RDKit          3D\n+\n+ 11 11  0  0  0  0  0  0  0  0999 V2000\n+   23.8350   12.2020   19.5760 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   23.4520   11.9220   18.2610 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   25.0420   12.8700   19.8340 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   22.9370   11.8100   20.7250 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   24.2680   12.2940   17.1940 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   25.8750   13.2520   18.7790 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   22.8350   10.2970   20.9620 C   0  0  1  0  0  0  0  0  0  0  0  0\n+   25.4680   12.9560   17.4710 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   24.1570    9.7480   21.5040 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   21.7030    9.9910   21.9220 N   0  0  0  0  0  0  0  0  0  0  0  0\n+   26.2630   13.3220   16.4230 O   0  0  0  0  0  0  0  0  0  0  0  0\n+  2  1  2  0\n+  3  1  1  0\n+  4  1  1  0\n+  5  2  1  0\n+  6  3  2  0\n+  7  4  1  0\n+  8  6  1  0\n+  8  5  2  0\n+  7  9  1  1\n+ 10  7  1  0\n+ 11  8  1  0\n+M  END\n+$$$$\n+\n+     RDKit          3D\n+\n+ 12 12  0  0  0  0  0  0  0  0999 V2000\n+   26.5880   11.6480   19.1670 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   25.9260   11.0670   20.2530 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   25.8770   11.8420   17.9690 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   28.0300   12.0720   19.2730 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   24.5820   10.6900   20.1310 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   24.5420   11.4720   17.8340 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   26.4990   12.4120   16.8870 O   0  0  0  0  0  0  0  0  0  0  0  0\n+   28.9860   10.8940   19.5000 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   23.8950   10.8910   18.9250 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   23.8700   10.0590   21.2980 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   22.8110   11.0000   21.8820 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   21.6380   10.2010   22.3970 N   0  0  0  0  0  0  0  0  0  0  0  0\n+  2  1  2  0\n+  3  1  1  0\n+  4  1  1  0\n+  5  2  1  0\n+  6  3  2  0\n+  7  3  1  0\n+  8  4  1  0\n+  9  5  2  0\n+  9  6  1  0\n+ 10  5  1  0\n+ 11 10  1  0\n+ 12 11  1  0\n+M  END\n+$$$$\n+\n+     RDKit          3D\n+\n+ 16 17  0  0  0  0  0  0  0  0999 V2000\n+   26.3090   11.5670   19.1200 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   27.7750   11.8580   19.3620 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   25.5460   10.8930   20.0800 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   25.6820   11.9660   17.9260 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   27.9150   13.1100   20.2510 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   28.4910   10.6030   19.9180 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   24.1900   10.6200   19.8540 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   24.3290   11.7060   17.6830 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   26.3920   12.6330   16.9610 O   0  0  0  0  0  0  0  0  0  0  0  0\n+   29.3630   13.3270   20.6990 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   29.8080   10.8590   20.6700 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   23.5890   11.0260   18.6540 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   23.3960    9.8840   20.9090 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   29.7810   12.1210   21.5440 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   22.0220   10.5180   21.1760 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   21.2950    9.8120   22.2580 N   0  0  0  0  0  0  0  0  0  0  0  0\n+  2  1  1  0\n+  3  1  2  0\n+  4  1  1  0\n+  5  2  1  0\n+  6  2  1  0\n+  7  3  1  0\n+  8  4  2  0\n+  9  4  1  0\n+ 10  5  1  0\n+ 11  6  1  0\n+ 12  7  2  0\n+ 12  8  1  0\n+ 13  7  1  0\n+ 14 11  1  0\n+ 14 10  1  0\n+ 15 13  1  0\n+ 16 15  1  0\n+M  END\n+$$$$\n+\n+     RDKit          3D\n+\n+ 11 11  0  0  0  0  0  0  0  0999 V2000\n+   22.7740   12.1470   21.7380 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   22.7850   10.8240   21.5130 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   22.6560   12.6100   23.1270 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   22.6870    9.8820   22.6510 N   0  0  0  0  0  0  0  0  0  0  0  0\n+   22.5650   11.6780   24.1480 N   0  0  0  0  0 '..b'070   20.2350 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   23.7250   12.3660   20.5390 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   23.9740   13.5980   19.8680 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   23.0570   14.0730   18.8890 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   21.8900   13.3170   18.5790 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   21.6410   12.0820   19.2490 C   0  0  0  0  0  0  0  0  0  0  0  0\n+  3  2  2  0\n+  4  3  1  0\n+  5  4  1  0\n+  6  4  2  0\n+  7  6  1  0\n+  8  7  2  0\n+  8  2  1  0\n+  9  6  1  0\n+ 10  9  1  0\n+ 11 10  1  0\n+ 12 11  2  0\n+ 13 12  1  0\n+ 14 13  2  0\n+ 15  1  1  0\n+ 15 14  1  0\n+ 16 15  2  0\n+ 16 11  1  0\n+M  END\n+$$$$\n+\n+     RDKit          3D\n+\n+ 17 18  0  0  0  0  0  0  0  0999 V2000\n+   25.3290   10.4220   19.4450 Cl  0  0  0  0  0  0  0  0  0  0  0  0\n+   21.8630   10.2850   24.5540 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   21.7910   10.8780   25.7630 N   0  0  0  0  0  0  0  0  0  0  0  0\n+   19.3810   12.4340   23.7140 O   0  0  0  0  0  0  0  0  0  0  0  0\n+   20.2730   11.7550   24.2280 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   20.9910   10.7760   23.6530 N   0  0  0  0  0  0  0  0  0  0  0  0\n+   20.7520   11.8870   25.6690 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   22.7100    9.3050   24.2610 N   0  0  0  0  0  0  0  0  0  0  0  0\n+   19.5480   11.5280   26.5490 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   21.3220   13.3140   25.8640 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   20.8570   10.3260   22.2690 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   21.8180   11.0860   21.3800 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   21.5520   12.4460   21.0380 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   22.4570   13.1680   20.2040 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   23.6300   12.5320   19.7130 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   23.9010   11.1800   20.0500 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   22.9980   10.4540   20.8840 C   0  0  0  0  0  0  0  0  0  0  0  0\n+  3  2  1  0\n+  5  4  2  0\n+  6  5  1  0\n+  6  2  1  0\n+  7  3  1  0\n+  7  5  1  0\n+  8  2  2  0\n+  7  9  1  0\n+ 10  7  1  0\n+ 11  6  1  0\n+ 12 11  1  0\n+ 13 12  2  0\n+ 14 13  1  0\n+ 15 14  2  0\n+ 16  1  1  0\n+ 16 15  1  0\n+ 17 16  2  0\n+ 17 12  1  0\n+M  END\n+$$$$\n+\n+     RDKit          3D\n+\n+ 20 21  0  0  0  0  0  0  0  0999 V2000\n+   18.0360   15.1780   25.0870 Cl  0  0  0  0  0  0  0  0  0  0  0  0\n+   22.1580    9.9560   23.5460 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   21.7380    9.4450   22.3670 N   0  0  0  0  0  0  0  0  0  0  0  0\n+   21.3070   12.9370   22.1820 O   0  0  0  0  0  0  0  0  0  0  0  0\n+   21.5180   11.7630   22.4850 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   22.0160   11.2920   23.6430 N   0  0  0  0  0  0  0  0  0  0  0  0\n+   21.2400   10.5640   21.5800 C   0  0  1  0  0  0  0  0  0  0  0  0\n+   22.6590    9.2240   24.5370 N   0  0  0  0  0  0  0  0  0  0  0  0\n+   22.0010   10.7000   20.2550 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   19.7110   10.4760   21.4070 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   22.3150   12.0980   24.8270 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   21.0470   12.4840   25.5530 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   20.6470   11.7740   26.7230 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   19.4310   12.1180   27.3830 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   18.6170   13.1760   26.8780 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   19.0220   13.8920   25.7120 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   20.2380   13.5470   25.0530 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   24.3110    9.9210   20.9010 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   24.0210   11.7480   19.1870 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   23.4670   11.0980   20.4450 C   0  0  0  0  0  0  0  0  0  0  0  0\n+  3  2  1  0\n+  5  4  2  0\n+  6  5  1  0\n+  6  2  1  0\n+  7  3  1  0\n+  7  5  1  0\n+  8  2  2  0\n+  9  7  1  0\n+  7 10  1  6\n+ 11  6  1  0\n+ 12 11  1  0\n+ 13 12  2  0\n+ 14 13  1  0\n+ 15 14  2  0\n+ 16 15  1  0\n+ 16  1  1  0\n+ 17 16  2  0\n+ 17 12  1  0\n+ 20 18  1  0\n+ 20  9  1  0\n+ 20 19  1  0\n+M  END\n+$$$$\n'
b
diff -r 000000000000 -r bb5365381c8f test-data/split_3.sdf
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test-data/split_3.sdf Wed Oct 02 12:57:54 2019 -0400
b
b'@@ -0,0 +1,399 @@\n+\n+     RDKit          3D\n+\n+ 15 16  0  0  0  0  0  0  0  0999 V2000\n+   18.6370   11.5460   19.0470 Cl  0  0  0  0  0  0  0  0  0  0  0  0\n+   19.3410   11.4910   20.6100 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   19.1300   12.5410   21.5090 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   20.1120   10.3920   20.9640 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   19.7080   12.5060   22.7780 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   20.6710   10.3800   22.2200 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   20.4820   11.4070   23.1080 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   21.4530    9.4460   22.7560 N   0  0  0  0  0  0  0  0  0  0  0  0\n+   21.7320    9.9040   23.9840 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   21.1510   11.1000   24.2190 N   0  0  0  0  0  0  0  0  0  0  0  0\n+   22.5310    9.1910   24.8790 N   0  0  0  0  0  0  0  0  0  0  0  0\n+   21.2170   11.9110   25.4550 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   20.4620   11.2450   26.6090 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   21.0350   11.5770   27.9760 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   20.9480   12.9640   28.2400 O   0  0  0  0  0  0  0  0  0  0  0  0\n+  2  1  1  0\n+  3  2  2  0\n+  4  2  1  0\n+  5  3  1  0\n+  6  4  2  0\n+  7  6  1  0\n+  7  5  2  0\n+  8  6  1  0\n+  9  8  2  0\n+ 10  9  1  0\n+ 10  7  1  0\n+ 11  9  1  0\n+ 12 10  1  0\n+ 13 12  1  0\n+ 14 13  1  0\n+ 15 14  1  0\n+M  END\n+$$$$\n+\n+     RDKit          3D\n+\n+ 16 18  0  0  0  0  0  0  0  0999 V2000\n+   20.6710   12.3670   19.5500 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   20.3560   11.0080   19.5110 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   20.7970   10.1550   20.5260 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   21.5490   10.6510   21.5910 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   21.8550   12.0130   21.6470 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   21.4090   12.8650   20.6370 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   20.2040   13.2140   18.5400 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   18.9460   13.0790   18.0310 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   19.8500   14.9600   16.8550 S   0  0  0  0  0  0  0  0  0  0  0  0\n+   20.8860   14.2450   18.0080 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   18.5460   13.9340   17.0770 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   21.9520    9.8170   22.5630 N   0  0  0  0  0  0  0  0  0  0  0  0\n+   22.6670   10.2610   23.6190 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   23.0100   11.6160   23.7210 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   22.5970   12.5050   22.7210 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   23.0640    9.3990   24.5550 N   0  0  0  0  0  0  0  0  0  0  0  0\n+  2  1  2  0\n+  3  2  1  0\n+  4  3  2  0\n+  5  4  1  0\n+  6  1  1  0\n+  6  5  2  0\n+  7  1  1  0\n+  8  7  1  0\n+ 10  9  1  0\n+ 10  7  2  0\n+ 11  9  1  0\n+ 11  8  2  0\n+ 12  4  1  0\n+ 13 12  2  0\n+ 14 13  1  0\n+ 15  5  1  0\n+ 15 14  2  0\n+ 16 13  1  0\n+M  END\n+$$$$\n+\n+     RDKit          3D\n+\n+ 14 16  0  0  0  0  0  0  0  0999 V2000\n+   22.5850   11.1260   22.4670 C   0  0  1  0  0  0  0  0  0  0  0  0\n+   22.4650   13.2910   21.5170 N   0  0  0  0  0  0  0  0  0  0  0  0\n+   21.5180   12.9300   23.6420 O   0  0  0  0  0  0  0  0  0  0  0  0\n+   23.1760   11.1930   21.1020 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   22.7650    9.4680   24.1810 N   0  0  0  0  0  0  0  0  0  0  0  0\n+   22.1720   12.5670   22.6700 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   21.3450   10.2690   22.4850 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   23.5010   10.6150   23.5600 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   23.0740   12.4520   20.5910 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   23.7590   10.2030   20.3680 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   21.3310    9.5780   23.8310 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   23.5150   12.7690   19.3280 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   24.2170   10.4950   19.0970 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   24.1050   11.7710   18.5900 C   0  0  0  0  0  0  0  0  0  0  0  0\n+  4  1  1  0\n+  6  3  2  0\n+  6  2  1  0\n+  6  1  1  0\n+  1  7  1  6\n+  8 '..b' 17  0  0  0  0  0  0  0  0999 V2000\n+   21.3640   10.5720   21.8100 C   0  0  1  0  0  0  0  0  0  0  0  0\n+   22.5260   10.7940   20.8840 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   21.7650    9.7570   22.9510 N   0  0  0  0  0  0  0  0  0  0  0  0\n+   20.8520   11.9280   22.2760 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   20.2790    9.8280   21.0370 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   23.8090   10.3570   21.2290 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   22.3130   11.4350   19.6600 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   22.4050   10.1940   23.9570 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   22.0020   12.7140   22.8990 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   24.8880   10.5560   20.3660 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   23.3940   11.6280   18.7960 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   22.6430   11.8420   24.2920 S   0  0  0  0  0  0  0  0  0  0  0  0\n+   22.9320    9.2680   24.7800 N   0  0  0  0  0  0  0  0  0  0  0  0\n+   24.6750   11.1950   19.1430 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   25.7040   11.4130   18.2580 O   0  0  0  0  0  0  0  0  0  0  0  0\n+   27.1050   11.3380   18.6380 C   0  0  0  0  0  0  0  0  0  0  0  0\n+  2  1  1  0\n+  3  1  1  0\n+  4  1  1  0\n+  1  5  1  6\n+  6  2  2  0\n+  7  2  1  0\n+  8  3  2  0\n+  9  4  1  0\n+ 10  6  1  0\n+ 11  7  2  0\n+ 12  8  1  0\n+ 12  9  1  0\n+ 13  8  1  0\n+ 14 10  2  0\n+ 14 11  1  0\n+ 15 14  1  0\n+ 16 15  1  0\n+M  END\n+$$$$\n+\n+     RDKit          3D\n+\n+ 20 22  0  0  0  0  0  0  0  0999 V2000\n+   21.9670   12.1590   22.5710 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   22.0870    9.7810   22.3570 N   0  0  0  0  0  0  0  0  0  0  0  0\n+   21.7990   13.3470   22.3700 O   0  0  0  0  0  0  0  0  0  0  0  0\n+   21.7250   10.9910   21.5730 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   22.4050   11.6040   23.7520 N   0  0  0  0  0  0  0  0  0  0  0  0\n+   22.4510   10.1860   23.5940 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   22.8260    9.3810   24.5860 N   0  0  0  0  0  0  0  0  0  0  0  0\n+   22.7290   12.3950   24.9450 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   20.2460   10.8230   21.1770 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   19.8630    9.8830   20.2250 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   18.5290    9.7390   19.8610 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   17.5600   10.5330   20.4430 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   17.9210   11.4590   21.3960 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   19.2540   11.6030   21.7650 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   22.6070   11.2230   20.3330 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   22.4200   12.3320   19.5090 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   23.2410   12.5470   18.4040 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   24.2630   11.6640   18.1130 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   24.4610   10.5600   18.9190 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   23.6360   10.3370   20.0200 C   0  0  0  0  0  0  0  0  0  0  0  0\n+  3  1  2  0\n+  4  2  1  0\n+  4  1  1  0\n+  5  1  1  0\n+  6  2  1  0\n+  6  5  1  0\n+  7  6  2  0\n+  8  5  1  0\n+  4  9  1  0\n+ 10  9  2  0\n+ 11 10  1  0\n+ 12 11  2  0\n+ 13 12  1  0\n+ 14  9  1  0\n+ 14 13  2  0\n+ 15  4  1  0\n+ 16 15  2  0\n+ 17 16  1  0\n+ 18 17  2  0\n+ 19 18  1  0\n+ 20 19  2  0\n+ 20 15  1  0\n+M  END\n+$$$$\n+\n+     RDKit          3D\n+\n+  8  8  0  0  0  0  0  0  0  0999 V2000\n+   43.2120    1.2010   21.1900 N   0  0  0  0  0  0  0  0  0  0  0  0\n+   42.0970    1.7030   22.0340 C   0  0  2  0  0  0  0  0  0  0  0  0\n+   41.2120    2.6840   21.2450 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   41.4260    2.9540   20.0390 O   0  0  0  0  0  0  0  0  0  0  0  0\n+   42.6930    2.1910   23.3430 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   44.2130    1.9390   23.2340 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   44.4930    1.6950   21.7590 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   40.1570    3.2440   21.9570 N   0  0  0  0  0  0  0  0  0  0  0  0\n+  2  1  1  0\n+  2  3  1  6\n+  4  3  2  0\n+  5  2  1  0\n+  6  5  1  0\n+  7  1  1  0\n+  7  6  1  0\n+  8  3  1  0\n+M  END\n+$$$$\n'
b
diff -r 000000000000 -r bb5365381c8f test-data/split_4.sdf
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test-data/split_4.sdf Wed Oct 02 12:57:54 2019 -0400
b
@@ -0,0 +1,211 @@
+
+     RDKit          3D
+
+ 22 25  0  0  0  0  0  0  0  0999 V2000
+   23.9890   11.5960   18.4360 C   0  0  0  0  0  0  0  0  0  0  0  0
+   25.3210   11.4640   18.7840 C   0  0  0  0  0  0  0  0  0  0  0  0
+   25.6630   11.0960   20.0820 C   0  0  0  0  0  0  0  0  0  0  0  0
+   24.6490   10.8840   21.0220 C   0  0  0  0  0  0  0  0  0  0  0  0
+   23.3190   11.0270   20.6770 C   0  0  0  0  0  0  0  0  0  0  0  0
+   22.9880   11.3810   19.3750 C   0  0  0  0  0  0  0  0  0  0  0  0
+   22.2440   10.8070   21.7330 C   0  0  2  0  0  0  0  0  0  0  0  0
+   20.8520   10.8680   21.1250 C   0  0  0  0  0  0  0  0  0  0  0  0
+   19.8540   10.6460   22.2900 C   0  0  0  0  0  0  0  0  0  0  0  0
+   20.0450   11.6270   23.3000 O   0  0  0  0  0  0  0  0  0  0  0  0
+   20.9870   12.6610   22.9460 C   0  0  0  0  0  0  0  0  0  0  0  0
+   22.3270   11.9770   22.7910 C   0  0  1  0  0  0  0  0  0  0  0  0
+   22.7770   11.3400   23.9760 O   0  0  0  0  0  0  0  0  0  0  0  0
+   22.7260   10.0020   23.7830 C   0  0  0  0  0  0  0  0  0  0  0  0
+   22.4730    9.6360   22.5540 N   0  0  0  0  0  0  0  0  0  0  0  0
+   22.9310    9.1250   24.7980 N   0  0  0  0  0  0  0  0  0  0  0  0
+   27.0780   10.9870   20.5190 C   0  0  0  0  0  0  0  0  0  0  0  0
+   27.5170    9.9760   21.3750 C   0  0  0  0  0  0  0  0  0  0  0  0
+   28.7840    9.9640   21.7630 N   0  0  0  0  0  0  0  0  0  0  0  0
+   29.6370   10.8810   21.3400 C   0  0  0  0  0  0  0  0  0  0  0  0
+   29.2680   11.8600   20.5370 N   0  0  0  0  0  0  0  0  0  0  0  0
+   28.0170   11.9450   20.1110 C   0  0  0  0  0  0  0  0  0  0  0  0
+  2  1  2  0
+  3  2  1  0
+  4  3  2  0
+  5  4  1  0
+  6  5  2  0
+  6  1  1  0
+  7  5  1  6
+  8  7  1  0
+  9  8  1  0
+ 10  9  1  0
+ 11 10  1  0
+ 12 11  1  1
+ 12  7  1  0
+ 13 12  1  0
+ 14 13  1  0
+ 15  7  1  0
+ 15 14  2  0
+ 16 14  1  0
+ 17  3  1  0
+ 18 17  2  0
+ 19 18  1  0
+ 20 19  2  0
+ 21 20  1  0
+ 22 17  1  0
+ 22 21  2  0
+M  END
+$$$$
+
+     RDKit          3D
+
+ 19 21  0  0  0  0  0  0  0  0999 V2000
+   18.6790   10.8940   21.5160 C   0  0  0  0  0  0  0  0  0  0  0  0
+   21.8760    9.6220   22.6190 N   0  0  0  0  0  0  0  0  0  0  0  0
+   19.3450    9.6270   21.1760 O   0  0  0  0  0  0  0  0  0  0  0  0
+   22.4790   11.8080   24.2920 S   0  0  0  0  0  0  0  0  0  0  0  0
+   19.5140   11.7630   22.5130 C   0  0  0  0  0  0  0  0  0  0  0  0
+   22.7100    9.2150   24.7670 N   0  0  0  0  0  0  0  0  0  0  0  0
+   20.5550    9.7530   20.5440 C   0  0  0  0  0  0  0  0  0  0  0  0
+   22.8590   10.7120   20.6250 C   0  0  0  0  0  0  0  0  0  0  0  0
+   24.1020   10.1890   21.0270 C   0  0  0  0  0  0  0  0  0  0  0  0
+   25.2620   10.3730   20.2980 C   0  0  0  0  0  0  0  0  0  0  0  0
+   22.8630   11.5080   19.3970 C   0  0  0  0  0  0  0  0  0  0  0  0
+   21.5800   10.5280   21.4490 C   0  0  2  0  0  0  0  0  0  0  0  0
+   20.9500   11.9060   21.9290 C   0  0  2  0  0  0  0  0  0  0  0  0
+   21.9600   12.7150   22.7910 C   0  0  0  0  0  0  0  0  0  0  0  0
+   22.3230   10.0930   23.7780 C   0  0  0  0  0  0  0  0  0  0  0  0
+   24.0040   11.6730   18.6170 C   0  0  0  0  0  0  0  0  0  0  0  0
+   25.2010   11.1170   19.0930 C   0  0  0  0  0  0  0  0  0  0  0  0
+   21.7570   12.0240   18.8700 F   0  0  0  0  0  0  0  0  0  0  0  0
+   26.3200   11.2980   18.4090 F   0  0  0  0  0  0  0  0  0  0  0  0
+  3  1  1  0
+  5  1  1  0
+  7  3  1  0
+  9  8  2  0
+ 10  9  1  0
+ 11  8  1  0
+ 12  7  1  0
+ 12  8  1  6
+ 12  2  1  0
+ 13 12  1  0
+ 13  5  1  1
+ 14 13  1  0
+ 14  4  1  0
+ 15  6  1  0
+ 15  2  2  0
+ 15  4  1  0
+ 16 11  2  0
+ 17 10  2  0
+ 17 16  1  0
+ 18 11  1  0
+ 19 17  1  0
+M  END
+$$$$
+
+     RDKit          3D
+
+ 16 17  0  0  0  0  0  0  0  0999 V2000
+   20.6950    9.9560   20.8820 C   0  0  0  0  0  0  0  0  0  0  0  0
+   22.2050    9.8930   22.6900 N   0  0  0  0  0  0  0  0  0  0  0  0
+   23.0060   12.0970   24.2220 S   0  0  0  0  0  0  0  0  0  0  0  0
+   21.8910   10.6980   21.5060 C   0  0  2  0  0  0  0  0  0  0  0  0
+   22.8690    9.5480   24.8150 N   0  0  0  0  0  0  0  0  0  0  0  0
+   21.4800   12.1250   21.9040 C   0  0  0  0  0  0  0  0  0  0  0  0
+   22.5630   12.8770   22.6580 C   0  0  0  0  0  0  0  0  0  0  0  0
+   22.6270   10.3910   23.7940 C   0  0  0  0  0  0  0  0  0  0  0  0
+   23.1060   10.7640   20.5410 C   0  0  0  0  0  0  0  0  0  0  0  0
+   24.3720   10.2320   20.8590 C   0  0  0  0  0  0  0  0  0  0  0  0
+   25.4690   10.3640   20.0140 C   0  0  0  0  0  0  0  0  0  0  0  0
+   25.3420   11.0350   18.7800 C   0  0  0  0  0  0  0  0  0  0  0  0
+   24.1030   11.5640   18.3850 C   0  0  0  0  0  0  0  0  0  0  0  0
+   23.0130   11.4340   19.2760 C   0  0  0  0  0  0  0  0  0  0  0  0
+   21.8840   12.0230   18.8800 F   0  0  0  0  0  0  0  0  0  0  0  0
+   26.4280   11.2380   18.0020 F   0  0  0  0  0  0  0  0  0  0  0  0
+  4  1  1  6
+  4  2  1  0
+  6  4  1  0
+  7  6  1  0
+  7  3  1  0
+  8  5  1  0
+  8  2  2  0
+  8  3  1  0
+  9  4  1  0
+ 10  9  2  0
+ 11 10  1  0
+ 12 11  2  0
+ 13 12  1  0
+ 14  9  1  0
+ 14 13  2  0
+ 15 14  1  0
+ 16 12  1  0
+M  END
+$$$$
+
+     RDKit          3D
+
+ 11 12  0  0  0  0  0  0  0  0999 V2000
+   23.8920   10.9750   19.7100 C   0  0  0  0  0  0  0  0  0  0  0  0
+   23.1430    9.6540   19.8400 C   0  0  0  0  0  0  0  0  0  0  0  0
+   23.7820   11.7530   20.9950 C   0  0  0  0  0  0  0  0  0  0  0  0
+   21.6770    9.8870   20.1680 C   0  0  0  0  0  0  0  0  0  0  0  0
+   22.1750   12.7870   22.6090 C   0  0  0  0  0  0  0  0  0  0  0  0
+   22.3660   10.1400   23.6660 C   0  0  0  0  0  0  0  0  0  0  0  0
+   22.3180   11.9530   21.3510 C   0  0  2  0  0  0  0  0  0  0  0  0
+   21.5250   10.6490   21.4640 C   0  0  2  0  0  0  0  0  0  0  0  0
+   22.7380    9.3100   24.6900 N   0  0  0  0  0  0  0  0  0  0  0  0
+   21.9210    9.6990   22.5310 N   0  0  0  0  0  0  0  0  0  0  0  0
+   22.5620   11.8400   24.1130 S   0  0  0  0  0  0  0  0  0  0  0  0
+  2  1  1  0
+  3  1  1  0
+  4  2  1  0
+  7  3  1  1
+  7  5  1  0
+  8  4  1  6
+  8  7  1  0
+  9  6  1  0
+ 10  8  1  0
+ 10  6  2  0
+ 11  6  1  0
+ 11  5  1  0
+M  END
+$$$$
+
+     RDKit          3D
+
+ 18 20  0  0  0  0  0  0  0  0999 V2000
+   28.6970   10.5240   20.4750 C   0  0  0  0  0  0  0  0  0  0  0  0
+   27.9220   11.6800   20.9560 N   0  0  0  0  0  0  0  0  0  0  0  0
+   28.7880   12.6650   21.6350 C   0  0  0  0  0  0  0  0  0  0  0  0
+   27.0810   12.2010   19.9710 C   0  0  0  0  0  0  0  0  0  0  0  0
+   27.4190   13.2930   19.2740 N   0  0  0  0  0  0  0  0  0  0  0  0
+   26.6450   13.8320   18.3200 C   0  0  0  0  0  0  0  0  0  0  0  0
+   25.4810   13.2870   17.9980 N   0  0  0  0  0  0  0  0  0  0  0  0
+   25.0290   12.1840   18.6310 C   0  0  0  0  0  0  0  0  0  0  0  0
+   23.7860   11.6150   18.3040 C   0  0  0  0  0  0  0  0  0  0  0  0
+   23.3430   10.5040   18.9720 C   0  0  0  0  0  0  0  0  0  0  0  0
+   24.1080    9.9180   19.9810 C   0  0  0  0  0  0  0  0  0  0  0  0
+   25.3250   10.4360   20.3200 C   0  0  0  0  0  0  0  0  0  0  0  0
+   25.8200   11.5870   19.6640 C   0  0  0  0  0  0  0  0  0  0  0  0
+   27.1160   14.9710   17.6690 N   0  0  0  0  0  0  0  0  0  0  0  0
+   27.3480   16.1150   18.5710 C   0  0  0  0  0  0  0  0  0  0  0  0
+   27.6660   17.2890   17.6050 C   0  0  0  0  0  0  0  0  0  0  0  0
+   26.8670   16.9430   16.3140 C   0  0  0  0  0  0  0  0  0  0  0  0
+   26.3130   15.5200   16.5590 C   0  0  0  0  0  0  0  0  0  0  0  0
+  2  1  1  0
+  3  2  1  0
+  4  2  1  0
+  5  4  2  0
+  6  5  1  0
+  7  6  2  0
+  8  7  1  0
+  9  8  2  0
+ 10  9  1  0
+ 11 10  2  0
+ 12 11  1  0
+ 13 12  2  0
+ 13  8  1  0
+ 13  4  1  0
+ 14  6  1  0
+ 15 14  1  0
+ 16 15  1  0
+ 17 16  1  0
+ 18 14  1  0
+ 18 17  1  0
+M  END
+$$$$
b
diff -r 000000000000 -r bb5365381c8f test-data/sucos_cluster.sdf
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test-data/sucos_cluster.sdf Wed Oct 02 12:57:54 2019 -0400
b
b'@@ -0,0 +1,1384 @@\n+\n+     RDKit          3D\n+\n+ 19 20  0  0  0  0  0  0  0  0999 V2000\n+   25.8690   10.6750   17.9260 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   24.7660   11.4770   18.5500 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   24.1650   12.4880   17.8120 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   23.1480   13.2570   18.3640 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   22.7300   13.0010   19.6620 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   21.6190   13.8450   20.2480 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   23.3280   11.9670   20.4090 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   22.9000   11.7560   21.6900 O   0  0  0  0  0  0  0  0  0  0  0  0\n+   23.1990   10.4520   22.2010 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   22.3800   10.3250   23.4930 C   0  0  1  0  0  0  0  0  0  0  0  0\n+   22.7510    9.1510   24.2170 O   0  0  0  0  0  0  0  0  0  0  0  0\n+   22.5930   11.5910   24.3570 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   22.2540   11.3630   25.7760 N   0  0  0  0  0  0  0  0  0  0  0  0\n+   22.5710   12.5910   26.5330 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   22.1760   12.4110   28.0100 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   20.7810   12.0710   28.1350 O   0  0  0  0  0  0  0  0  0  0  0  0\n+   20.5060   10.8660   27.4060 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   20.8170   11.0700   25.9210 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   24.3600   11.2090   19.8480 C   0  0  0  0  0  0  0  0  0  0  0  0\n+  2  1  1  0\n+  3  2  2  0\n+  4  3  1  0\n+  5  4  2  0\n+  6  5  1  0\n+  7  5  1  0\n+  8  7  1  0\n+  9  8  1  0\n+ 10  9  1  0\n+ 10 11  1  1\n+ 12 10  1  0\n+ 13 12  1  0\n+ 14 13  1  0\n+ 15 14  1  0\n+ 16 15  1  0\n+ 17 16  1  0\n+ 18 17  1  0\n+ 18 13  1  0\n+ 19  7  2  0\n+ 19  2  1  0\n+M  END\n+$$$$\n+\n+     RDKit          3D\n+\n+ 11 12  0  0  0  0  0  0  0  0999 V2000\n+   22.8090    9.2070   24.2800 N   0  0  0  0  0  0  0  0  0  0  0  0\n+   22.4710   10.1080   23.3190 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   21.8900    9.6340   22.1960 N   0  0  0  0  0  0  0  0  0  0  0  0\n+   21.5680   10.5170   21.2440 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   21.7580   11.8790   21.3690 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   22.3130   12.3920   22.5320 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   22.5210   13.7530   22.7260 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   23.0810   14.2110   23.9020 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   23.4470   13.3190   24.8860 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   23.2450   11.9700   24.7110 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   22.6750   11.4850   23.5440 C   0  0  0  0  0  0  0  0  0  0  0  0\n+  2  1  1  0\n+  3  2  2  0\n+  4  3  1  0\n+  5  4  2  0\n+  6  5  1  0\n+  7  6  2  0\n+  8  7  1  0\n+  9  8  2  0\n+ 10  9  1  0\n+ 11  2  1  0\n+ 11 10  2  0\n+ 11  6  1  0\n+M  END\n+$$$$\n+\n+     RDKit          3D\n+\n+ 11 12  0  0  0  0  0  0  0  0999 V2000\n+   22.7770    9.1670   24.9740 N   0  0  0  0  0  0  0  0  0  0  0  0\n+   22.4280   10.0140   24.0880 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   22.6770   11.3690   24.2670 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   22.2930   12.2600   23.2950 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   21.6430   11.7880   22.1650 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   21.2220   12.6270   21.1460 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   20.5740   12.1120   20.0440 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   20.3400   10.7540   19.9450 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   20.7580    9.9010   20.9470 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   21.4090   10.3980   22.0610 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   21.7960    9.5320   23.0070 N   0  0  0  0  0  0  0  0  0  0  0  0\n+  2  1  1  0\n+  3  2  2  0\n+  4  3  1  0\n+  5  4  2  0\n+  6  5  1  0\n+  7  6  2  0\n+  8  7  1  0\n+  9  8  2  0\n+ 10  9  1  0\n+ 10  5  1  0\n+ 11 10  2  0\n+ 11  2  1  0\n+M  END\n+$$$$\n+\n+     RDKit          3D\n+\n+ 15 16  0  0  0  0  0  0  0  0999 V2000\n+   22.4510    9.0090   24.4670 N   0  0  0  0  0  0  0  0  0  0  0  0\n+   22.5180   10.3550   24.1060 C   0  0  0  0  0  0  0  0  0  0'..b' 0  0  0\n+   22.2050    9.8930   22.6900 N   0  0  0  0  0  0  0  0  0  0  0  0\n+   23.0060   12.0970   24.2220 S   0  0  0  0  0  0  0  0  0  0  0  0\n+   21.8910   10.6980   21.5060 C   0  0  2  0  0  0  0  0  0  0  0  0\n+   22.8690    9.5480   24.8150 N   0  0  0  0  0  0  0  0  0  0  0  0\n+   21.4800   12.1250   21.9040 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   22.5630   12.8770   22.6580 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   22.6270   10.3910   23.7940 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   23.1060   10.7640   20.5410 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   24.3720   10.2320   20.8590 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   25.4690   10.3640   20.0140 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   25.3420   11.0350   18.7800 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   24.1030   11.5640   18.3850 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   23.0130   11.4340   19.2760 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   21.8840   12.0230   18.8800 F   0  0  0  0  0  0  0  0  0  0  0  0\n+   26.4280   11.2380   18.0020 F   0  0  0  0  0  0  0  0  0  0  0  0\n+  4  1  1  6\n+  4  2  1  0\n+  6  4  1  0\n+  7  6  1  0\n+  7  3  1  0\n+  8  5  1  0\n+  8  2  2  0\n+  8  3  1  0\n+  9  4  1  0\n+ 10  9  2  0\n+ 11 10  1  0\n+ 12 11  2  0\n+ 13 12  1  0\n+ 14  9  1  0\n+ 14 13  2  0\n+ 15 14  1  0\n+ 16 12  1  0\n+M  END\n+$$$$\n+\n+     RDKit          3D\n+\n+ 11 12  0  0  0  0  0  0  0  0999 V2000\n+   23.8920   10.9750   19.7100 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   23.1430    9.6540   19.8400 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   23.7820   11.7530   20.9950 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   21.6770    9.8870   20.1680 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   22.1750   12.7870   22.6090 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   22.3660   10.1400   23.6660 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   22.3180   11.9530   21.3510 C   0  0  2  0  0  0  0  0  0  0  0  0\n+   21.5250   10.6490   21.4640 C   0  0  2  0  0  0  0  0  0  0  0  0\n+   22.7380    9.3100   24.6900 N   0  0  0  0  0  0  0  0  0  0  0  0\n+   21.9210    9.6990   22.5310 N   0  0  0  0  0  0  0  0  0  0  0  0\n+   22.5620   11.8400   24.1130 S   0  0  0  0  0  0  0  0  0  0  0  0\n+  2  1  1  0\n+  3  1  1  0\n+  4  2  1  0\n+  7  3  1  1\n+  7  5  1  0\n+  8  4  1  6\n+  8  7  1  0\n+  9  6  1  0\n+ 10  8  1  0\n+ 10  6  2  0\n+ 11  6  1  0\n+ 11  5  1  0\n+M  END\n+$$$$\n+\n+     RDKit          3D\n+\n+ 18 20  0  0  0  0  0  0  0  0999 V2000\n+   28.6970   10.5240   20.4750 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   27.9220   11.6800   20.9560 N   0  0  0  0  0  0  0  0  0  0  0  0\n+   28.7880   12.6650   21.6350 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   27.0810   12.2010   19.9710 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   27.4190   13.2930   19.2740 N   0  0  0  0  0  0  0  0  0  0  0  0\n+   26.6450   13.8320   18.3200 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   25.4810   13.2870   17.9980 N   0  0  0  0  0  0  0  0  0  0  0  0\n+   25.0290   12.1840   18.6310 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   23.7860   11.6150   18.3040 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   23.3430   10.5040   18.9720 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   24.1080    9.9180   19.9810 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   25.3250   10.4360   20.3200 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   25.8200   11.5870   19.6640 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   27.1160   14.9710   17.6690 N   0  0  0  0  0  0  0  0  0  0  0  0\n+   27.3480   16.1150   18.5710 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   27.6660   17.2890   17.6050 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   26.8670   16.9430   16.3140 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   26.3130   15.5200   16.5590 C   0  0  0  0  0  0  0  0  0  0  0  0\n+  2  1  1  0\n+  3  2  1  0\n+  4  2  1  0\n+  5  4  2  0\n+  6  5  1  0\n+  7  6  2  0\n+  8  7  1  0\n+  9  8  2  0\n+ 10  9  1  0\n+ 11 10  2  0\n+ 12 11  1  0\n+ 13 12  2  0\n+ 13  8  1  0\n+ 13  4  1  0\n+ 14  6  1  0\n+ 15 14  1  0\n+ 16 15  1  0\n+ 17 16  1  0\n+ 18 14  1  0\n+ 18 17  1  0\n+M  END\n+$$$$\n'
b
diff -r 000000000000 -r bb5365381c8f test-data/sucos_inputs.sdf
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test-data/sucos_inputs.sdf Wed Oct 02 12:57:54 2019 -0400
b
b"@@ -0,0 +1,1420 @@\n+=\n+ OpenBabel06141912503D\n+\n+ 18 19  0  0  1  0  0  0  0  0999 V2000\n+   34.9890  -44.7290   75.3400 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   33.7740  -44.3230   75.8900 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   32.5980  -44.5060   75.1780 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   32.6020  -45.0920   73.9050 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   33.8400  -45.4880   73.3780 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   35.0250  -45.3160   74.0770 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   31.3410  -45.2900   73.1330 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   30.1700  -44.5940   73.4530 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   29.0040  -44.7840   72.7210 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   28.9810  -45.6590   71.6540 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   30.1290  -46.3590   71.3190 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   31.2960  -46.1720   72.0490 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   36.1480  -44.5380   76.0590 O   0  0  0  0  0  0  0  0  0  0  0  0\n+   38.4940  -44.7080   76.2650 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   37.3560  -44.2790   75.3520 C   0  0  2  0  0  0  0  0  0  0  0  0\n+   37.3740  -42.7950   74.9960 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   37.0060  -41.9850   75.8700 O   0  0  0  0  0  0  0  0  0  0  0  0\n+   37.7410  -42.4950   73.8440 O   0  0  0  0  0  0  0  0  0  0  0  0\n+  1  2  1  0  0  0  0\n+  1 13  1  0  0  0  0\n+  3  2  2  0  0  0  0\n+  4  3  1  0  0  0  0\n+  5  4  2  0  0  0  0\n+  5  6  1  0  0  0  0\n+  6  1  2  0  0  0  0\n+  7  8  1  0  0  0  0\n+  7  4  1  0  0  0  0\n+  9  8  2  0  0  0  0\n+ 10  9  1  0  0  0  0\n+ 11 10  2  0  0  0  0\n+ 11 12  1  0  0  0  0\n+ 12  7  2  0  0  0  0\n+ 15 13  1  0  0  0  0\n+ 15 14  1  1  0  0  0\n+ 16 15  1  0  0  0  0\n+ 16 17  1  0  0  0  0\n+ 18 16  2  0  0  0  0\n+M  END\n+>  <MODEL>\n+1\n+\n+>  <REMARK>\n+ VINA RESULT:      -6.3      0.000      0.000\n+  Name = \n+  5 active torsions:\n+  status: ('A' for Active; 'I' for Inactive)\n+    1  A    between atoms: C_1  and  C_8\n+    2  A    between atoms: C_2  and  C_13\n+    3  A    between atoms: C_8  and  C_9\n+    4  A    between atoms: C_8  and  O_18\n+    5  A    between atoms: C_10  and  O_18\n+                            x       y       z     vdW  Elec       q    Type\n+                         _______ _______ _______ _____ _____    ______ ____\n+\n+>  <TORSDO>\n+F 4\n+\n+>  <SCORE>\n+-6.3\n+\n+>  <RMSD_LB>\n+0.000\n+\n+>  <RMSD_UB>\n+0.000\n+\n+$$$$\n+=\n+ OpenBabel06141912503D\n+\n+ 18 19  0  0  1  0  0  0  0  0999 V2000\n+   34.9980  -44.6860   75.3940 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   35.0270  -45.2910   74.1380 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   33.8490  -45.4620   73.4270 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   32.6180  -45.0400   73.9450 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   32.6210  -44.4360   75.2110 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   33.7890  -44.2540   75.9350 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   31.3460  -45.2230   73.1860 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   31.2400  -46.1600   72.1530 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   30.0470  -46.3240   71.4580 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   28.9380  -45.5680   71.7810 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   29.0210  -44.6340   72.8010 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   30.2120  -44.4670   73.4970 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   36.1760  -44.5260   76.0900 O   0  0  0  0  0  0  0  0  0  0  0  0\n+   38.5270  -44.6480   76.2620 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   37.3680  -44.2480   75.3630 C   0  0  2  0  0  0  0  0  0  0  0  0\n+   37.3510  -42.7680   74.9960 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   36.9750  -41.9580   75.8670 O   0  0  0  0  0  0  0  0  0  0  0  0\n+   37.7000  -42.4690   73.8370 O   0  0  0  0  0  0  0  0  0  0  0  0\n+  1  6  1  0  0  0  0\n+  1 13  1  0  0  0  0\n+  2  1  2  0  0  0  0\n+  3  4  2  0  0  0  0\n+  3  2  1  0  0  0  0\n+  4  5  1  0  0  0  0\n+  5  6  2  0  0  0  0\n+  7 12  1  0  0  0  0\n+  7  4  1  0  0  0  0\n+  8  7  2  0 "..b"0  0  0  0  0  0  0  0  0\n+   30.4880  -42.4910   76.4360 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   36.5680  -44.7780   76.1370 O   0  0  0  0  0  0  0  0  0  0  0  0\n+   38.0030  -45.7500   74.5340 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   37.1210  -44.5510   74.8450 C   0  0  2  0  0  0  0  0  0  0  0  0\n+   37.8730  -43.2240   74.8910 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   37.2700  -42.2030   74.5030 O   0  0  0  0  0  0  0  0  0  0  0  0\n+   39.0500  -43.2560   75.2990 O   0  0  0  0  0  0  0  0  0  0  0  0\n+  1  2  2  0  0  0  0\n+  2  3  1  0  0  0  0\n+  4  7  1  0  0  0  0\n+  4  3  2  0  0  0  0\n+  5  4  1  0  0  0  0\n+  6  5  2  0  0  0  0\n+  6  1  1  0  0  0  0\n+  7  8  2  0  0  0  0\n+  8  9  1  0  0  0  0\n+ 10  9  2  0  0  0  0\n+ 11 10  1  0  0  0  0\n+ 12 11  2  0  0  0  0\n+ 12  7  1  0  0  0  0\n+ 13  1  1  0  0  0  0\n+ 15 14  1  1  0  0  0\n+ 15 16  1  0  0  0  0\n+ 15 13  1  0  0  0  0\n+ 16 18  1  0  0  0  0\n+ 17 16  2  0  0  0  0\n+M  END\n+>  <MODEL>\n+19\n+\n+>  <REMARK>\n+ VINA RESULT:      -4.4      3.044      4.158\n+  Name = \n+  5 active torsions:\n+  status: ('A' for Active; 'I' for Inactive)\n+    1  A    between atoms: C_1  and  C_8\n+    2  A    between atoms: C_2  and  C_13\n+    3  A    between atoms: C_8  and  C_9\n+    4  A    between atoms: C_8  and  O_18\n+    5  A    between atoms: C_10  and  O_18\n+                            x       y       z     vdW  Elec       q    Type\n+                         _______ _______ _______ _____ _____    ______ ____\n+\n+>  <TORSDO>\n+F 4\n+\n+>  <SCORE>\n+-4.4\n+\n+>  <RMSD_LB>\n+3.044\n+\n+>  <RMSD_UB>\n+4.158\n+\n+$$$$\n+=\n+ OpenBabel06141912503D\n+\n+ 18 19  0  0  1  0  0  0  0  0999 V2000\n+   32.5500  -43.5500   76.7360 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   33.6520  -43.1880   77.5090 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   34.9240  -43.5810   77.1230 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   35.1310  -44.3420   75.9650 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   34.0020  -44.6910   75.2090 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   32.7230  -44.3040   75.5790 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   36.4970  -44.7690   75.5440 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   37.5820  -43.8860   75.5740 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   38.8510  -44.2990   75.1850 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   39.0680  -45.5970   74.7690 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   38.0080  -46.4890   74.7300 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   36.7380  -46.0790   75.1180 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   31.2920  -43.1540   77.1350 O   0  0  0  0  0  0  0  0  0  0  0  0\n+   30.7500  -40.8560   77.1260 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   30.6100  -42.1680   76.3690 C   0  0  2  0  0  0  0  0  0  0  0  0\n+   29.1670  -42.6320   76.1960 C   0  0  0  0  0  0  0  0  0  0  0  0\n+   28.9380  -43.8550   76.2740 O   0  0  0  0  0  0  0  0  0  0  0  0\n+   28.3130  -41.7520   75.9720 O   0  0  0  0  0  0  0  0  0  0  0  0\n+  1 13  1  0  0  0  0\n+  1  2  2  0  0  0  0\n+  3  2  1  0  0  0  0\n+  4  3  2  0  0  0  0\n+  5  6  2  0  0  0  0\n+  5  4  1  0  0  0  0\n+  6  1  1  0  0  0  0\n+  7  8  1  0  0  0  0\n+  7  4  1  0  0  0  0\n+  9  8  2  0  0  0  0\n+ 10  9  1  0  0  0  0\n+ 11 10  2  0  0  0  0\n+ 11 12  1  0  0  0  0\n+ 12  7  2  0  0  0  0\n+ 15 14  1  1  0  0  0\n+ 15 13  1  0  0  0  0\n+ 16 17  1  0  0  0  0\n+ 16 15  1  0  0  0  0\n+ 18 16  2  0  0  0  0\n+M  END\n+>  <MODEL>\n+20\n+\n+>  <REMARK>\n+ VINA RESULT:      -4.4      3.679      6.880\n+  Name = \n+  5 active torsions:\n+  status: ('A' for Active; 'I' for Inactive)\n+    1  A    between atoms: C_1  and  C_8\n+    2  A    between atoms: C_2  and  C_13\n+    3  A    between atoms: C_8  and  C_9\n+    4  A    between atoms: C_8  and  O_18\n+    5  A    between atoms: C_10  and  O_18\n+                            x       y       z     vdW  Elec       q    Type\n+                         _______ _______ _______ _____ _____    ______ ____\n+\n+>  <TORSDO>\n+F 4\n+\n+>  <SCORE>\n+-4.4\n+\n+>  <RMSD_LB>\n+3.679\n+\n+>  <RMSD_UB>\n+6.880\n+\n+$$$$\n"
b
diff -r 000000000000 -r bb5365381c8f test-data/sucos_refmol.mol
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test-data/sucos_refmol.mol Wed Oct 02 12:57:54 2019 -0400
b
@@ -0,0 +1,43 @@
+
+ OpenBabel06051719483D
+
+ 18 19  0  0  0  0              2 V2000
+   29.0700  -43.2240   73.7660 C   0  0  0  0  0
+   36.2650  -44.8070   74.9140 C   0  0  0  0  0
+   37.1260  -44.6280   73.8270 C   0  0  0  0  0
+   38.5050  -44.6030   73.9960 C   0  0  0  0  0
+   39.0530  -44.7650   75.2580 C   0  0  0  0  0
+   38.2200  -44.9420   76.3450 C   0  0  0  0  0
+   36.8400  -44.9680   76.1790 C   0  0  0  0  0
+   30.0630  -44.1750   73.1160 C   0  0  0  0  0
+   29.4310  -45.1480   72.1250 C   0  0  0  0  0
+   32.0050  -44.9160   74.3360 C   0  0  0  0  0
+   32.8370  -45.6680   73.5100 C   0  0  0  0  0
+   34.2080  -45.6230   73.7110 C   0  0  0  0  0
+   34.7860  -44.8390   74.7200 C   0  0  0  0  0
+   33.9230  -44.0930   75.5330 C   0  0  0  0  0
+   32.5490  -44.1280   75.3490 C   0  0  0  0  0
+   30.2050  -45.7640   71.3670 O   0  0  0  0  0
+   28.1910  -45.2760   72.1490 O   0  0  0  0  0
+   30.6380  -44.9430   74.1670 O   0  0  0  0  0
+  1  8  1  0  0  0
+  2  3  2  0  0  0
+  2  7  1  0  0  0
+  2 13  1  0  0  0
+  3  4  1  0  0  0
+  4  5  2  0  0  0
+  5  6  1  0  0  0
+  6  7  2  0  0  0
+  8  9  1  0  0  0
+  8 18  1  0  0  0
+  9 16  2  0  0  0
+  9 17  1  0  0  0
+ 10 11  2  0  0  0
+ 10 15  1  0  0  0
+ 10 18  1  0  0  0
+ 11 12  1  0  0  0
+ 12 13  2  0  0  0
+ 13 14  1  0  0  0
+ 14 15  2  0  0  0
+M  CHG  1  17  -1
+M  END
b
diff -r 000000000000 -r bb5365381c8f utils.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/utils.py Wed Oct 02 12:57:54 2019 -0400
b
@@ -0,0 +1,49 @@
+#!/usr/bin/env python
+"""
+Utility functions for SuCOS and other RDKit modules
+"""
+
+from __future__ import print_function
+import sys, gzip
+from rdkit import Chem
+
+def log(*args, **kwargs):
+    """Log output to STDERR
+    """
+    print(*args, file=sys.stderr, **kwargs)
+
+def open_file_for_reading(filename):
+    """Open the file gunzipping it if it ends with .gz."""
+    if filename.lower().endswith('.gz'):
+        return gzip.open(filename, 'rb')
+    else:
+        return open(filename, 'rb')
+
+def open_file_for_writing(filename):
+    if filename.lower().endswith('.gz'):
+        return gzip.open(filename, 'at')
+    else:
+        return open(filename, 'w+')
+
+def read_single_molecule(filename, index=1, format=None):
+    """Read a single molecule as a RDKit Mol object. This can come from a file in molfile or SDF format.
+    If SDF then you can also specify an index of the molecule that is read (default is the first)
+    """
+    mol = None
+    if format == 'mol' or filename.lower().endswith('.mol') or filename.lower().endswith('.mol.gz'):
+        file = open_file_for_reading(filename)
+        mol = Chem.MolFromMolBlock(file.read())
+        file.close()
+    elif format == 'sdf' or filename.lower().endswith('.sdf') or filename.lower().endswith('.sdf.gz'):
+        file = open_file_for_reading(filename)
+        supplier = Chem.ForwardSDMolSupplier(file)
+        for i in range(0,index):
+            if supplier.atEnd():
+                break
+            mol = next(supplier)
+        file.close()
+
+    if not mol:
+        raise ValueError("Unable to read molecule")
+
+    return mol
\ No newline at end of file