├── setup.py ├── .gitignore ├── molecule_slide_generator ├── __init__.py ├── data_extraction.py └── slide_generator.py ├── tests ├── Raleway-Bold.ttf ├── test_default.png ├── test_example.png ├── test_from_images.png ├── tests.py └── bzr21.sdf ├── images ├── test_default.png ├── test_from_images.png └── example_slide_bzr.png ├── pyproject.toml ├── environment.yml ├── setup.cfg ├── license.txt └── README.md /setup.py: -------------------------------------------------------------------------------- 1 | import setuptools 2 | setuptools.setup() -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /dist/ 2 | /build/ 3 | /molecule_slide_generator.egg-info/ 4 | -------------------------------------------------------------------------------- /molecule_slide_generator/__init__.py: -------------------------------------------------------------------------------- 1 | from .slide_generator import * 2 | from .data_extraction import * -------------------------------------------------------------------------------- /tests/Raleway-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kienerj/molecule-slide-generator/HEAD/tests/Raleway-Bold.ttf -------------------------------------------------------------------------------- /tests/test_default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kienerj/molecule-slide-generator/HEAD/tests/test_default.png -------------------------------------------------------------------------------- /tests/test_example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kienerj/molecule-slide-generator/HEAD/tests/test_example.png -------------------------------------------------------------------------------- /images/test_default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kienerj/molecule-slide-generator/HEAD/images/test_default.png -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ["setuptools >= 42", "wheel"] 3 | build-backend = "setuptools.build_meta" -------------------------------------------------------------------------------- /images/test_from_images.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kienerj/molecule-slide-generator/HEAD/images/test_from_images.png -------------------------------------------------------------------------------- /tests/test_from_images.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kienerj/molecule-slide-generator/HEAD/tests/test_from_images.png -------------------------------------------------------------------------------- /images/example_slide_bzr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kienerj/molecule-slide-generator/HEAD/images/example_slide_bzr.png -------------------------------------------------------------------------------- /environment.yml: -------------------------------------------------------------------------------- 1 | name: slide_generator 2 | channels: 3 | - conda-forge 4 | - defaults 5 | dependencies: 6 | - python>=3.6 7 | - rdkit>=2020.09.1 8 | - numpy 9 | - pillow 10 | - pip 11 | - pip: 12 | - molecule-slide-generator -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [metadata] 2 | name = molecule-slide_generator 3 | version = 0.2.0 4 | author = Joos Kiener 5 | author_email = joos.kiener@gmail.com 6 | description = Generate images of molecules and their properties for use in presentations and reports 7 | long_description = file: README.md 8 | long_description_content_type = text/markdown 9 | url = https://github.com/kienerj/molecule-slide-generator 10 | project_urls = 11 | Bug Tracker = https://github.com/kienerj/molecule-slide-generator/issues 12 | classifiers = 13 | Programming Language :: Python :: 3 14 | License :: OSI Approved :: BSD License 15 | Operating System :: OS Independent 16 | Development Status :: 4 - Beta 17 | 18 | [options] 19 | packages = find: 20 | python_requires = >=3.6 21 | install_requires = 22 | numpy 23 | pillow -------------------------------------------------------------------------------- /license.txt: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2020, Joos Kiener 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | 3. Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /molecule_slide_generator/data_extraction.py: -------------------------------------------------------------------------------- 1 | from rdkit import Chem 2 | from rdkit.Chem import PandasTools 3 | from io import BytesIO 4 | import io 5 | from PIL import Image 6 | import re 7 | import pandas as pd 8 | import io 9 | 10 | 11 | class DataExtractor(object): 12 | """ 13 | Extracts the molecules and properties out of the image metadata into a pandas dataframe 14 | 15 | The extraction can be done on a single image (extract_single) or repeatedly called in a loop (extract). Properties 16 | not available for a specific molecule will be set to `None`. 17 | 18 | If an image doesn't contain a molecule, it is silently ignored. 19 | """ 20 | 21 | def __init__(self): 22 | 23 | self.reference = [] 24 | self.molecules = [] 25 | self.columns = [] 26 | self.data = {} 27 | self.image_number = 0 28 | 29 | def extract_single(self, image): 30 | """ 31 | Extracts molecules and properties from a single png image 32 | 33 | :param image: image bytes, file path or binary stream 34 | :return: DataFrame with the molecules and properties 35 | """ 36 | 37 | self.extract(image) 38 | return self.get_data() 39 | 40 | def extract(self, image): 41 | """ 42 | Extracts molecules and properties from a png image. 43 | 44 | This method can be called repeatedly in a loop and when all images are extracted, 45 | the data can be fetched by a call to `get_data()`. 46 | 47 | :param image: image bytes, file path or binary stream 48 | """ 49 | 50 | if isinstance(image, bytes): 51 | img = image 52 | elif isinstance(image, str): 53 | with open(image, 'rb') as f: 54 | img = f.read() 55 | elif isinstance(image, io.BufferedIOBase): 56 | img = image.read() 57 | else: 58 | raise ValueError("Can't determine data type of image. Supported are bytes, str or a binary stream.") 59 | 60 | stream = BytesIO(img) 61 | pil_image = Image.open(stream) 62 | pil_image.load() 63 | is_molimage = False 64 | for key, value in pil_image.info.items(): 65 | if key.startswith('rdkit'): 66 | is_molimage = True 67 | break 68 | if not is_molimage: 69 | # no molecule in image, do not process 70 | return 71 | 72 | mols = Chem.MolsFromPNGString(img) 73 | nprops = Chem.MetadataFromPNGString(img) 74 | 75 | if 'numProperties' in nprops: 76 | # remove structure data properties which all contain 'rdkit' 77 | rx = re.compile(r'rdkit') 78 | props = {key: nprops[key] for key in nprops if not rx.search(key)} 79 | num_props = int(props.pop('numProperties').decode('utf-8')) 80 | 81 | prop_names = list(props) 82 | for idx in range(num_props): 83 | name = prop_names[idx] 84 | if name not in self.columns: 85 | self.columns.append(name) 86 | self.data[name] = [] # initialize data 87 | if len(self.molecules) > 0: 88 | # not first image, fill list with none 89 | self.data[name] = [None] * len(self.molecules) 90 | else: 91 | props = {} 92 | for idx in range(len(mols)): 93 | for prop in self.columns: 94 | if idx > 0: 95 | key = prop + str(idx) 96 | else: 97 | key = prop 98 | if key in props: 99 | self.data[prop].append(props[key].decode('utf-8')) 100 | else: 101 | self.data[prop].append(None) 102 | 103 | self.molecules.extend(mols) # extend here to simplify above checks 104 | self.reference.extend([self.image_number] * len(mols)) 105 | self.image_number += 1 106 | 107 | def get_data(self): 108 | 109 | self.data['Molecule'] = self.molecules 110 | self.data['Reference'] = self.reference 111 | df = pd.DataFrame(data=self.data) 112 | PandasTools.ChangeMoleculeRendering(df) 113 | # reinitialize instance 114 | self.__init__() 115 | return df 116 | 117 | -------------------------------------------------------------------------------- /tests/tests.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import os 3 | from rdkit import Chem 4 | from rdkit.Chem import AllChem, Draw 5 | from molecule_slide_generator import * 6 | from PIL import Image 7 | import imagehash 8 | 9 | 10 | class ImageCreationTest(unittest.TestCase): 11 | """ 12 | Use ImageHash library to compare newly generated image to a pre-generated image 13 | This gives no guarantee the image is 100% correct but prevents from manual testing for every change 14 | """ 15 | 16 | def test_default_image(self): 17 | 18 | sg = SlideGenerator(number_of_properties=2) 19 | png = sg.generate_slide(self.mols, self.all_props, 'test_default.png') 20 | hash = imagehash.dhash(Image.open('test_default.png'), hash_size=16) 21 | self.assertEqual(self.default_hash, hash, msg="Images hashes do not match.") 22 | 23 | num_mols = sg.max_mols 24 | self.check_properties(png, num_mols) 25 | self.check_extraction(png, num_mols) 26 | 27 | def test_example_image(self): 28 | sg = SlideGenerator(mols_per_row=3, rows=3, font_size=18, font='comicbd', number_of_properties=2, 29 | slide_width=800, slide_height=600) 30 | png = sg.generate_slide(self.mols, self.all_props, 'test_example.png') 31 | hash = imagehash.dhash(Image.open('test_example.png'), hash_size=16) 32 | self.assertEqual(self.example_hash, hash, msg="Images hashes do not match.") 33 | 34 | num_mols = sg.max_mols 35 | self.check_properties(png, num_mols) 36 | self.check_extraction(png, num_mols) 37 | 38 | def test_slide_from_images(self): 39 | 40 | sg = SlideGenerator(mols_per_row=3, rows=3, font_size=18, font='comicbd', number_of_properties=2, 41 | slide_width=800, slide_height=600) 42 | 43 | img_width = sg.image_width 44 | img_height = sg.molecule_image_height 45 | 46 | images = [] 47 | for mol in self.mols: 48 | img = Draw.MolToImage(mol, size=(img_width, img_height)) 49 | images.append(img) 50 | 51 | png = sg.generate_slide_from_images(self.mols, self.all_props, images, 'test_from_images.png') 52 | hash = imagehash.dhash(Image.open('test_from_images.png'), hash_size=16) 53 | self.assertEqual(self.from_images_hash, hash, msg="Images hashes do not match.") 54 | 55 | num_mols = sg.max_mols 56 | self.check_properties(png, num_mols) 57 | self.check_extraction(png, num_mols) 58 | 59 | def test_font_from_file(self): 60 | 61 | sg = SlideGenerator(number_of_properties=2, font="Raleway-Bold.ttf") 62 | png = sg.generate_slide(self.mols, self.all_props, 'test_font.png') 63 | self.assertIsNotNone(png, msg="Could not generate slide from font file input") 64 | 65 | def check_properties(self, png, num_mols): 66 | 67 | # Check properties 68 | num_properties = 2 69 | # pickle, molfile and smiles 70 | num_mol_formats = 3 71 | # +1 for num_properties entry in metadata 72 | num_keys = (num_properties + num_mol_formats) * num_mols + 1 73 | props = Chem.MetadataFromPNGString(png) 74 | self.assertEqual(num_keys, len(props.keys()), msg="Number of key in metadat dict does not match. Expected {}, " 75 | "got {}.".format(num_keys, len(props.keys()))) 76 | 77 | def check_extraction(self, png, num_mols): 78 | 79 | e = DataExtractor() 80 | df = e.extract_single(png) 81 | self.assertEqual(num_mols, len(df), 82 | msg="Extracted dataframe has wrong length. Expected {}, got {}.".format(num_mols, len(df))) 83 | 84 | name0 = df.iloc[0, 0] 85 | self.assertEqual('Adinazolam', name0, 86 | msg="First molecule has wrong name. Expected Adinazolam, got {}.".format(name0)) 87 | name5 = df.iloc[5, 0] 88 | self.assertEqual('Clonazepam', name5, 89 | msg="First molecule has wrong name. Expected Clonazepam, got {}.".format(name5)) 90 | 91 | mol0 = df.iloc[0,2] 92 | smi = Chem.MolToSmiles(mol0) 93 | self.assertEqual('CN(C)Cc1nnc2CN=C(c3ccccc3)c3c(ccc(Cl)c3)-n21', smi, msg="First molecule does not match.") 94 | 95 | 96 | def setUp(self): 97 | suppl = Chem.SDMolSupplier('bzr21.sdf') 98 | self.mols = [x for x in suppl] 99 | self.all_props = [] 100 | for mol in self.mols: 101 | AllChem.Compute2DCoords(mol) 102 | a = float(mol.GetProp('ACTIVITY')) 103 | if a > 8.0: 104 | color = '#3A662F' 105 | elif a < 8.0 and a > 7: 106 | color = '#e8860e' 107 | else: 108 | color = '#b52009' 109 | props = [TextProperty('Name', mol.GetProp('_Name')), TextProperty('Activity', a, color=color)] 110 | self.all_props.append(props) 111 | 112 | self.default_hash = imagehash.dhash(Image.open('../images/test_default.png'), hash_size=16) 113 | self.example_hash = imagehash.dhash(Image.open('../images/example_slide_bzr.png'), hash_size=16) 114 | self.from_images_hash = imagehash.dhash(Image.open('../images/test_from_images.png'), hash_size=16) 115 | 116 | 117 | if __name__ == '__main__': 118 | unittest.main() 119 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # RDKit Molecule Slide Generator 2 | 3 | RDKit Molecule Slide Generator is a tool for generating an overview image of molecules and their properties for usage in reports, presentations or blogs. An advanced `MolsToGridImage`. It's easier to show than explain. 4 | 5 | ![example_slide_bzr](https://raw.githubusercontent.com/kienerj/molecule-slide-generator/master/images/example_slide_bzr.png) 6 | 7 | This example uses the first 9 molecules of the `bzr.sdf` in the RDKit distributions data directory and uses Comic Sans MS as font. Activity values are conditionally colored. 8 | 9 | ### Why should I use it? 10 | 11 | Traditional reporting tools could also be used to generate a similar output however the problem with these is that the information especially the chemical structure is then lost as it could only be restored via optical structure recognition. This can be avoided by using commercial tools like ChemDraw but it does not offer any automated way to generated such documents out-of-the-box and you are locked-in. 12 | 13 | Molecule Slide Generator can be used in an automated fashion via web application or say a python script in KNIME. The generated images contain all the chemical structures in different formats and the properties inside the images metadata. This data can be extracted again without the need for RDKit (albeit RDKit makes it easier if available). So you get an automated, vendor agnostic solution. 14 | 15 | The images can also be sent by email (tested with gmail) or used in blogs and websites. 16 | 17 | ### Installation 18 | 19 | ##### Requirements 20 | 21 | - RDKit 2020.09.1 or higher 22 | - numpy 23 | - pillow 24 | 25 | ##### New conda environment 26 | 27 | For installation into a new conda environment, please use the included `environment.yml` file: 28 | 29 | ```bash 30 | conda env create -f environment.yml 31 | ``` 32 | 33 | This takes care of all dependencies and is the suggested way to try it out. 34 | 35 | ##### Existing environment 36 | 37 | To install into an existing environment, please ensure the needed requirements are already installed as the install script does not verify all of them. 38 | 39 | ```bash 40 | pip install molecule-slide-generator 41 | ``` 42 | 43 | ### Features 44 | 45 | - Any true type font (.ttf) can be used for the atom labels and text. 46 | - Set font size of atom labels and text 47 | - The text can be colored separately for each molecule and property 48 | - Set bond length of molecule (`fixedBondLength`drawing option) 49 | - Molecules are rescaled to RDKits default bond length so that all of them have the same size 50 | - The property can be displayed with or without the properties name 51 | - Define size of slide (width, height) and number of rows and columns 52 | - Molecule data and properties are stored in images metadata and can be extracted again 53 | 54 | ### Example Code 55 | 56 | This is the code used to generate above image on Windows. For Linux you would have to use a different font or install MS Core fonts. 57 | 58 | ```python 59 | from rdkit import Chem 60 | from rdkit.Chem import AllChem,Draw 61 | from molecule_slide_generator import * 62 | 63 | suppl = Chem.SDMolSupplier('tests/bzr21.sdf') 64 | # first 9 mols 65 | mols = [x for x in suppl][:9] 66 | 67 | # Create properties with coloring 68 | all_props = [] 69 | for mol in mols: 70 | AllChem.Compute2DCoords(mol) # remove 3D coords 71 | a = float(mol.GetProp('ACTIVITY')) 72 | if a > 8.0: 73 | color = '#3A662F' 74 | elif a < 8.0 and a > 7: 75 | color = '#e8860e' 76 | else: 77 | color = '#b52009' 78 | props = [TextProperty('Name', mol.GetProp('_Name')), 79 | TextProperty('Activity', a, color=color)] 80 | all_props.append(props) 81 | 82 | # Generate the slide 83 | sg = SlideGenerator(mols_per_row=3, rows=3, font_size=18, font='comicbd', 84 | number_of_properties=2, slide_width=800, slide_height=600) 85 | png = sg.generate_slide(mols, all_props, 'example_slide.png') 86 | ``` 87 | 88 | For font you can either use a named font or a full path to a `.ttf` file. For named fonts the font must be in `C:/Windows/Fonts/` directory for Windows and for Linux in `/usr/share/fonts/truetype`. 89 | 90 | The returned `png` is a simple extension of `bytes` built-in class that can be used as such but is displayed as image in Jupyter notebooks automatically without needing to use `IPython.display` (it just works like with RDKit molecules). 91 | 92 | 93 | ### Extracting 94 | 95 | Data can be extracted either manually or with the provided `DataExtractor` tool. 96 | 97 | #### Manually 98 | 99 | Molecules and properties can be extracted "manually" using the according RDKit functionality: 100 | 101 | ```python 102 | mols = Chem.MolsFromPNGString(png) 103 | Draw.MolsToGridImage(mols,molsPerRow=3) 104 | ``` 105 | 106 | where `png`is a bytes object containing the png data. 107 | 108 | For properties you can see the available data also by using RDKit: 109 | 110 | ```python 111 | nprops = Chem.MetadataFromPNGString(png) 112 | nprops.keys() 113 | dict_keys(['rdkitPKL rdkit 2020.09.1', 'MOL rdkit 2020.09.1', 'SMILES rdkit 2020.09.1', 'Name', 114 | 'Activity', 'rdkitPKL1 rdkit 2020.09.1', 'MOL1 rdkit 2020.09.1', 'SMILES1 rdkit 2020.09.1', 115 | 'Name1', 'Activity1', 'rdkitPKL2 rdkit 2020.09.1', 'MOL2 rdkit 2020.09.1', 116 | 'SMILES2 rdkit 2020.09.1', 'Name2', 'Activity2', 'rdkitPKL3 rdkit 2020.09.1', 117 | 'MOL3 rdkit 2020.09.1', 'SMILES3 rdkit 2020.09.1', 'Name3', 'Activity3', 118 | 'rdkitPKL4 rdkit 2020.09.1', 'MOL4 rdkit 2020.09.1', 'SMILES4 rdkit 2020.09.1', 'Name4', 119 | 'Activity4', 'rdkitPKL5 rdkit 2020.09.1', 'MOL5 rdkit 2020.09.1', 'SMILES5 rdkit 2020.09.1', 120 | 'Name5', 'Activity5', 'rdkitPKL6 rdkit 2020.09.1', 'MOL6 rdkit 2020.09.1', 121 | 'SMILES6 rdkit 2020.09.1', 'Name6', 'Activity6', 'rdkitPKL7 rdkit 2020.09.1', 122 | 'MOL7 rdkit 2020.09.1', 'SMILES7 rdkit 2020.09.1', 'Name7', 'Activity7', 123 | 'rdkitPKL8 rdkit 2020.09.1', 'MOL8 rdkit 2020.09.1', 'SMILES8 rdkit 2020.09.1', 'Name8', 124 | 'Activity8']) 125 | ``` 126 | 127 | The system used is that first molecules data is in key with the properties name, eg. "Activity" in the example. For each subsequent molecule the index of the molecule in the file is appended. So to get the activity value for the second molecule in the image you would use the key "Activity1". Data is returned as bytes and must be converted accordingly. 128 | 129 | ```python 130 | float(nprops['Activity1'].decode('utf-8')) 131 | 7.7 132 | ``` 133 | 134 | #### Data Extractor 135 | 136 | The molecules and properties can be extracted again from the images by using `DataExtractor`. 137 | 138 | ``````python 139 | extractor = DataExtractor() 140 | df = extractor.extract_single("images/example_slide_bzr.png") 141 | `````` 142 | 143 | This will return a `pandas.DataFrame` containing all the molecules and stored properties. 144 | 145 | `DataExtractor` can also be called in a loop using multiple calls to `extractor.extract(image)` and finally calling `df = extractor.get_data()` to return the data from multiple images in a single data frame. 146 | 147 | #### Extracting from MS Word or PowerPoint 148 | 149 | If you insert the image into an MS Office document, it can get problematic to extract the original image with all the metadata. However looking at the document contents (thanks to Greg for this hint), the original images are present and can be extracted again. For extracting all the molecules in an MS Office document you can use the KNIME component [Extract RDKit Molecules From Office](https://hub.knime.com/kienerj/spaces/Public/latest/Extract%20RDKit%20Molecules%20From%20Office). Alternatively you can manually or programmatically unzip the office document and use `DataExtractor` to iterate over the contained png images. 150 | 151 | ### Miscellaneous 152 | 153 | #### Layout / Parameters 154 | 155 | The default parameters of the slide generator work well with small molecules and a PowerPoint template with an aspect ratio of 16:9 that has a title and subtitle text box, the specific setup I have to use. You will need to play with the parameters to find an good solution for your specific needs. 156 | 157 | If the image is "too crowed" then either increase the slide dimension or reduce the number of rows or columns on the slide. To change the size of the molecules, use the `bond_length` parameter. Molecules that do not fit in the defined space will be automatically shrunk down. However this has a limitation on the atom label font size. So some minor shrinking works fine but too much and the labels will be too large. In that case, reduce the `bond_length`. 158 | 159 | #### Inner workings 160 | 161 | Technically the generator creates a molecule image using RDKit and a separate image with the text (properties) and merges them. Then all these images get merged together into the final image to which the metadata is appended. For all this "image manipulation" `pillow` is used. -------------------------------------------------------------------------------- /molecule_slide_generator/slide_generator.py: -------------------------------------------------------------------------------- 1 | from PIL import Image, ImageDraw, ImageFont 2 | from PIL.PngImagePlugin import PngInfo 3 | from rdkit.Chem import AllChem 4 | from rdkit.Chem.Draw import rdMolDraw2D 5 | from io import BytesIO 6 | import math 7 | import numpy as np 8 | import rdkit 9 | import platform 10 | import os 11 | import pathlib 12 | 13 | 14 | class Slide(bytes): 15 | """ 16 | Helper class that extends bytes. It's expected the loaded bytes are a png image. 17 | The class displays the image as representation when used in Jupyter Notebooks without any further coding requirement 18 | for the user. 19 | 20 | As additional convince functions, the bytes can also be easily saved to file or converted to a PIL image. 21 | """ 22 | def save(self, file): 23 | with open(file, 'wb') as img: 24 | img.write(self) 25 | 26 | def to_pil_image(self): 27 | stream = BytesIO(self) 28 | pil_image = Image.open(stream) 29 | pil_image.load() 30 | return pil_image 31 | 32 | def _repr_png_(self): 33 | return self 34 | 35 | 36 | class SlideGenerator(object): 37 | """Molecule Overview Slide Generator 38 | 39 | This class creates png images meant to be used in presentations that need simple overviews of molecules. 40 | Each slide (image) contains a certain amount of molecules plus additional properties of interest (text) below the 41 | molecule like molecule name, internal registration number and activity data. 42 | 43 | The generator also stores the molecule info and the properties inside the pngs metadata and they can therefore be 44 | extracted again at a later time if so desired. (The reason png is used is because MS Office products strip out 45 | metadata out of the svg but not out of pngs.) 46 | 47 | """ 48 | 49 | # Font folder on Ubuntu-type distros 50 | LINUX_TRUETYPE_FONTS_FOLDER = '/usr/share/fonts/truetype' 51 | 52 | def __init__(self, mols_per_row=7, rows=3, font_size=16, font='Calibrib', number_of_properties=4, bond_length=20, 53 | bond_width=2, slide_width=1440, slide_height=607, dpi=(120,120), comic_mode=False): 54 | """ 55 | The parameters defined are used to calculate the size that each molecule and the properties part can take up. 56 | 57 | The defaults result in a well looking overview of molecules for putting into a PowerPoint presentation that 58 | has a 16:9 aspect ratio and uses a Title->Subtitle slide template. Default slide_width and slide_height were 59 | determined manually and optimal values will depend on your exact templates. PowerPoint respects the DPI metadata 60 | of the generated png image and scales it accordingly. So for different templates/use cases you will need to do 61 | some manual experiments to figure out optimal settings. 62 | 63 | 'font' must either be a font name of a installed font or the full path to a true type font file (.ttf). 64 | For Windows the named fonts must be in 'C:/Windows/Fonts/' directory and for Linux in 65 | '/usr/share/fonts/truetype'. (Linux font folder is for Ubuntu. Don't know if it is the same for other distros). 66 | The font is used for the atom labels and the properties. 67 | 68 | 'number_of_properties' defines how many additional data you want to show below the molecules. Each property 69 | takes up 1 line of text. Example: pIC50: 6.2. This is meant for very small amounts of text/data. If text is too 70 | long, it is simply truncated automatically due to image width limit. It's up to the caller to adjust the data if 71 | hard truncation isn't acceptable. The approximate number of characters per line can be deduced from the instance 72 | attribute 'num_chars_per_line'. Exact amount depends on the exact text. 73 | 74 | :param mols_per_row: number of molecules per row. default:7 75 | :param rows: number of rows. default: 3 76 | :param font_size: size of the properties font. default:16 77 | :param font: name of the font to use or path to a .ttf font file 78 | :param number_of_properties: number of properties to display below the molecule 79 | :param bond_length: maximum bond length. if needed will be scaled down to fit image 80 | :param bond_width: width of bonds 81 | :param slide_width: width of the generated image 82 | :param slide_height: height of the generated image 83 | :param dpi: resolution of the generated image. A 2-tuple, 1 for each dimension 84 | """ 85 | 86 | root, ext = os.path.splitext(font) 87 | platform_system = platform.system() 88 | if ext != '' and ext != '.ttf': 89 | raise ValueError(f"'font' must be a path to an existing ttf file. However {font} was provided as font.") 90 | elif ext == '.ttf': 91 | self.font_path = font 92 | elif platform_system == 'Windows': 93 | self.font_path = 'C:/Windows/Fonts/' + font + '.ttf' 94 | elif platform_system == 'Linux': 95 | # For Windows fonts, requires MS Core fonts installed 96 | # sudo apt install ttf-mscorefonts-installer 97 | font_file_name = font + '.ttf' 98 | for root, dirs, files in os.walk(SlideGenerator.LINUX_TRUETYPE_FONTS_FOLDER): 99 | if font_file_name in files: 100 | self.font_path = os.path.join(root, font_file_name) 101 | break 102 | else: 103 | raise ValueError(f"'font' was set to name {font} but the location of the font folder is unknown for " 104 | f"platform {platform_system}. Please use full path to font file.") 105 | 106 | p = pathlib.Path(self.font_path) 107 | if not p.is_file(): 108 | raise ValueError("Desired font file '{}' does not exist.".format({self.font_path})) 109 | 110 | self.font_size = font_size 111 | self.bond_width = bond_width 112 | self.mols_per_row = mols_per_row 113 | self.mols_per_column = rows 114 | self.max_mols = mols_per_row * rows 115 | self.number_of_properties = number_of_properties 116 | self.slide_width = slide_width 117 | self.slide_height = slide_height 118 | self.dpi = dpi 119 | self.image_width = slide_width // mols_per_row 120 | self.row_height = slide_height // rows 121 | self.font = ImageFont.truetype(self.font_path, size=font_size) 122 | self.line_height = self.font.getsize('hg')[1] + 1 123 | self.text_image_height = math.ceil(self.line_height * number_of_properties) 124 | self.molecule_image_height = self.row_height - self.text_image_height 125 | # estimate max number of characters per line 126 | avg_char_width = self.font.getsize('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ123456789-, ')[0] / 64 127 | self.num_chars_per_line = self.image_width / avg_char_width 128 | self.bond_length = bond_length 129 | self.comic_mode = comic_mode 130 | 131 | def generate_slide(self, mols, properties, out_path=None): 132 | """ 133 | Generates an image with all molecules and their properties below them. 134 | 135 | :param mols: list of rdkit molecules 136 | :param properties: list of list of TextProperty 137 | :param out_path: optional file to save generated images 138 | :return: bytes object containing the png image data say for display in a notebook 139 | """ 140 | 141 | mols, slide, png_info = self._prepare_slide(mols, properties) 142 | 143 | for index, mol in enumerate(mols): 144 | 145 | mol_image = self._draw_mol(mol) 146 | 147 | self._add_to_slide(slide, properties, mol_image, index, png_info) 148 | 149 | return self._finalize_slide(slide, png_info, out_path) 150 | 151 | def generate_slide_from_images(self, mols, properties, images, out_path=None): 152 | """ 153 | Generates an image with all molecules and their properties below them. 154 | 155 | Images is a list containing the molecules images as PIL images to use in the slide. They must be in same order 156 | as mols. This allows each molecule image to be generated differently like substructure highlighting, annotations 157 | and so forth. So many options they can't be all part of a methods' argument. 158 | 159 | :param mols: list of rdkit molecules 160 | :param properties: list of lists of TextProperty 161 | :param images: list of images to use for each molecule 162 | :param out_path: optional file to save generated images 163 | :return: bytes object containing the png image data say for display in a notebook 164 | """ 165 | 166 | if images is None or len(images) != len(mols): 167 | raise ValueError("List of images is of different size than list of molecules.") 168 | 169 | mols, slide, png_info = self._prepare_slide(mols, properties) 170 | 171 | for index, mol in enumerate(mols): 172 | 173 | mol_image = images[index] 174 | if mol_image.width != self.image_width: 175 | raise ValueError("Image at index {} has wrong width. {} but expected {}." 176 | .format(index, mol_image.width, self.image_width)) 177 | if mol_image.height != self.molecule_image_height: 178 | raise ValueError("Image at index {} has wrong height. {} but expected {}." 179 | .format(index, mol_image.height, self.molecule_image_height)) 180 | 181 | self._add_to_slide(slide, properties, mol_image, index, png_info) 182 | 183 | return self._finalize_slide(slide, png_info, out_path) 184 | 185 | def _prepare_slide(self, mols, properties): 186 | 187 | if mols is None: 188 | raise ValueError('Expected a list of rdkit molecule instances but got \'None\'') 189 | 190 | # cut-off mols + properties silently. I think this is better than raising a ValueError 191 | mols = mols[:self.max_mols] 192 | properties = properties[:self.max_mols] 193 | if self.number_of_properties > 0 and len(mols) != len(properties): 194 | raise ValueError('Number of molecules must match number of properties.') 195 | 196 | if len(mols) == self.max_mols: 197 | slide = Image.new('RGBA', (self.slide_width, self.slide_height), (255, 255, 255, 0)) 198 | # less mols -> smaller image 199 | elif len(mols) < self.mols_per_row: 200 | slide = Image.new('RGBA', (len(mols) * self.image_width, self.row_height), (255, 255, 255, 0)) 201 | else: 202 | num_rows = (len(mols) // self.mols_per_row) + 1 203 | slide = Image.new('RGBA', (self.slide_width, self.row_height * num_rows), (255, 255, 255, 0)) 204 | 205 | png_info = PngInfo() 206 | png_info.add_text('numProperties', str(self.number_of_properties)) 207 | 208 | return mols, slide, png_info 209 | 210 | def _add_to_slide(self, slide, properties, mol_image, index, png_info): 211 | 212 | if self.number_of_properties > 0: 213 | text_image = self._draw_text(properties[index]) 214 | 215 | combined = Image.new('RGBA', (self.image_width, self.row_height), (255, 255, 255, 0)) 216 | combined.paste(mol_image) 217 | combined.paste(text_image, (0, self.molecule_image_height)) 218 | else: 219 | combined = mol_image 220 | 221 | row = index // self.mols_per_row 222 | column = index % self.mols_per_row 223 | position = (column * self.image_width, row * self.row_height) 224 | 225 | slide.paste(combined, position) 226 | 227 | if index > 0: 228 | key_index = str(index) 229 | else: 230 | key_index = '' 231 | 232 | png_info.add_text('rdkitPKL{} rdkit {}'.format(key_index, rdkit.__version__), 233 | mol_image.info['rdkitPKL rdkit {}'.format(rdkit.__version__)]) 234 | png_info.add_text('MOL{} rdkit {}'.format(key_index, rdkit.__version__), 235 | mol_image.info['MOL rdkit {}'.format(rdkit.__version__)]) 236 | png_info.add_text('SMILES{} rdkit {}'.format(key_index, rdkit.__version__), 237 | mol_image.info['SMILES rdkit {}'.format(rdkit.__version__)]) 238 | 239 | if self.number_of_properties > 0: 240 | mol_properties = properties[index] 241 | mol_properties = mol_properties[:self.number_of_properties] 242 | for prop in mol_properties: 243 | png_info.add_text('{}{}'.format(prop.name, key_index), str(prop.value)) 244 | # print("{}: {}".format(prop.name, str(prop.value))) 245 | 246 | def _finalize_slide(self, slide, png_info, out_path): 247 | 248 | if out_path is not None: 249 | slide.save(out_path, format='PNG', dpi=self.dpi, pnginfo=png_info) 250 | 251 | img_byte_arr = BytesIO() 252 | slide.save(img_byte_arr, format='PNG', dpi=self.dpi, pnginfo=png_info) 253 | # img_byte_arr = img_byte_arr.getvalue() 254 | return Slide(img_byte_arr.getvalue()) 255 | 256 | def _draw_text(self, mol_properties): 257 | 258 | mol_properties = mol_properties[:self.number_of_properties] 259 | txt = Image.new('RGBA', (self.image_width, self.text_image_height), (255, 255, 255, 0)) 260 | d = ImageDraw.Draw(txt) 261 | position = (0, 0) 262 | 263 | for prop in mol_properties: 264 | d.text(position, prop.get_display_value(), font=self.font, fill=prop.color) 265 | position = (0, position[1] + self.line_height) 266 | 267 | return txt 268 | 269 | def _draw_mol(self, mol, kekulize=True, add_chiral_hs=True): 270 | 271 | if mol is None: 272 | raise ValueError('Expected a rdkit molecule instance but got \'None\'') 273 | 274 | mol = rdMolDraw2D.PrepareMolForDrawing(mol, kekulize=kekulize, addChiralHs=add_chiral_hs) 275 | mol = SlideGenerator._scale_bond_length(mol) 276 | drawer = rdMolDraw2D.MolDraw2DCairo(self.image_width, self.molecule_image_height) 277 | drawer.SetFontSize(self.font_size) 278 | opts = drawer.drawOptions() 279 | opts.clearBackground = False 280 | opts.bondLineWidth = self.bond_width 281 | opts.fixedBondLength = self.bond_length 282 | opts.minFontSize = self.font_size 283 | opts.maxFontSize = self.font_size 284 | opts.fontFile = self.font_path 285 | opts.comicMode = self.comic_mode 286 | 287 | drawer.DrawMolecule(mol) 288 | drawer.FinishDrawing() 289 | png = drawer.GetDrawingText() 290 | mol_image = Image.open(BytesIO(png)) 291 | mol_image.load() 292 | return mol_image 293 | 294 | @staticmethod 295 | def _scale_bond_length(mol): 296 | """ 297 | This helper function scales a molecules bond length so that all bonds have the RDKit default bond length of 298 | 1.5A. This is needed as input from sd-files can have very variable bond length and the output will then not 299 | look very nice. 300 | 301 | :param mol: the rdkit molecule 302 | :return: molecule with bond length changed to 1.5 303 | """ 304 | default_bond_length = 1.5 # rdkit default bond length 305 | 306 | bonds = mol.GetBonds() 307 | 308 | if len(bonds) == 0: 309 | return mol 310 | 311 | total = 0 312 | for bond in bonds: 313 | 314 | ai = bond.GetBeginAtomIdx() 315 | aj = bond.GetEndAtomIdx() 316 | bl = AllChem.GetBondLength(mol.GetConformer(), ai, aj) 317 | if not math.isnan(bl): 318 | total += bl 319 | 320 | avg_bl = (total / len(bonds)) 321 | 322 | if avg_bl > 0.0: 323 | 324 | bl_ratio = default_bond_length / avg_bl 325 | 326 | tm = np.zeros((4, 4), np.double) 327 | for i in range(3): 328 | tm[i, i] = bl_ratio 329 | 330 | AllChem.TransformMol(mol, tm) 331 | return mol 332 | else: 333 | # in some cases avg_bl is zero -> recreate 2D coords and try again 334 | AllChem.Compute2DCoords(mol) 335 | return SlideGenerator._scale_bond_length(mol) 336 | 337 | 338 | class TextProperty(object): 339 | 340 | def __init__(self, name, value, show_name=False, color=(0, 0, 0, 255)): 341 | """ 342 | Sets options of the data below the molecule is displayed. 343 | 344 | Color is either a HEX value or a RGBA 4-tuple. 345 | 346 | :param name: display name of the property 347 | :param value: the value of the property 348 | :param show_name: if the name of the property should be displayed or not 349 | :param color: color of the text for this property. Default is black. HEX or RGBA 4-tuple. 350 | """ 351 | self.name = name 352 | self.value = value 353 | self.show_name = show_name 354 | 355 | if isinstance(color, tuple): 356 | if len(color) == 4: 357 | self.color = color 358 | else: 359 | raise ValueError('Expected a RGBA color tuple of 4 values. Got tuple with {} values'.format(len(color))) 360 | elif isinstance(color, str) and color[0] == '#': 361 | self.color = TextProperty.hex_to_rgb(color) 362 | else: 363 | raise ValueError('Expected a hex color string or RGBA 4-tuple but got {}.'.format(color)) 364 | 365 | def get_display_value(self): 366 | 367 | if self.show_name: 368 | return self.name + ': ' + str(self.value) 369 | else: 370 | return str(self.value) 371 | 372 | @staticmethod 373 | def hex_to_rgb(hex_code): 374 | # copied from stackoverflow 375 | hex_code = hex_code.lstrip('#').upper() 376 | rgb = tuple(int(hex_code[i:i + 2], 16) for i in (0, 2, 4)) 377 | return rgb + (255,) # RGBA 378 | -------------------------------------------------------------------------------- /tests/bzr21.sdf: -------------------------------------------------------------------------------- 1 | Adinazolam 2 | RDKit 3D 3 | 4 | 25 28 0 0 0 0 0 0 0 0999 V2000 5 | 0.2640 2.1660 0.0190 C 0 0 0 0 0 0 0 0 0 0 0 0 6 | 0.0430 0.7800 0.1640 C 0 0 0 0 0 0 0 0 0 0 0 0 7 | 1.1520 -0.2320 0.2240 C 0 0 0 0 0 0 0 0 0 0 0 0 8 | 2.2090 -0.1360 0.9660 N 0 0 0 0 0 0 0 0 0 0 0 0 9 | 2.3780 1.0510 1.8020 C 0 0 0 0 0 0 0 0 0 0 0 0 10 | 2.5640 2.2460 0.9460 C 0 0 0 0 0 0 0 0 0 0 0 0 11 | 1.5690 2.7140 0.1120 N 0 0 0 0 0 0 0 0 0 0 0 0 12 | 2.1270 3.8290 -0.5020 C 0 0 0 0 0 0 0 0 0 0 0 0 13 | 3.3320 4.0420 0.0050 N 0 0 0 0 0 0 0 0 0 0 0 0 14 | 3.6100 3.0460 0.8990 N 0 0 0 0 0 0 0 0 0 0 0 0 15 | 1.4930 4.6050 -1.6230 C 0 0 0 0 0 0 0 0 0 0 0 0 16 | 2.3640 5.6890 -2.1500 N 0 0 0 0 0 0 0 0 0 0 0 0 17 | 1.5750 6.5690 -3.0230 C 0 0 0 0 0 0 0 0 0 0 0 0 18 | 3.4890 5.1300 -2.9130 C 0 0 0 0 0 0 0 0 0 0 0 0 19 | 1.0470 -1.4480 -0.6470 C 0 0 0 0 0 0 0 0 0 0 0 0 20 | 1.4910 -2.6820 -0.1560 C 0 0 0 0 0 0 0 0 0 0 0 0 21 | 1.4100 -3.8240 -0.9550 C 0 0 0 0 0 0 0 0 0 0 0 0 22 | 0.8950 -3.7350 -2.2480 C 0 0 0 0 0 0 0 0 0 0 0 0 23 | 0.4650 -2.5060 -2.7470 C 0 0 0 0 0 0 0 0 0 0 0 0 24 | 0.5440 -1.3600 -1.9520 C 0 0 0 0 0 0 0 0 0 0 0 0 25 | -1.2750 0.2880 0.1840 C 0 0 0 0 0 0 0 0 0 0 0 0 26 | -2.3520 1.1570 0.0270 C 0 0 0 0 0 0 0 0 0 0 0 0 27 | -2.1370 2.5210 -0.1390 C 0 0 0 0 0 0 0 0 0 0 0 0 28 | -0.8350 3.0270 -0.1360 C 0 0 0 0 0 0 0 0 0 0 0 0 29 | -3.9590 0.5400 0.0420 Cl 0 0 0 0 0 0 0 0 0 0 0 0 30 | 1 2 2 0 31 | 1 7 1 0 32 | 1 24 1 0 33 | 2 3 1 0 34 | 2 21 1 0 35 | 3 4 2 0 36 | 3 15 1 0 37 | 4 5 1 0 38 | 5 6 1 0 39 | 6 7 1 0 40 | 6 10 2 0 41 | 7 8 1 0 42 | 8 9 2 0 43 | 8 11 1 0 44 | 9 10 1 0 45 | 11 12 1 0 46 | 12 13 1 0 47 | 12 14 1 0 48 | 15 16 2 0 49 | 15 20 1 0 50 | 16 17 1 0 51 | 17 18 2 0 52 | 18 19 1 0 53 | 19 20 2 0 54 | 21 22 2 0 55 | 22 23 1 0 56 | 22 25 1 0 57 | 23 24 2 0 58 | M END 59 | > (1) 60 | 6.87 61 | 62 | $$$$ 63 | Alprazolam 64 | RDKit 3D 65 | 66 | 22 25 0 0 0 0 0 0 0 0999 V2000 67 | 0.2620 2.1700 0.0290 C 0 0 0 0 0 0 0 0 0 0 0 0 68 | 0.0450 0.7830 0.1710 C 0 0 0 0 0 0 0 0 0 0 0 0 69 | 1.1560 -0.2300 0.2260 C 0 0 0 0 0 0 0 0 0 0 0 0 70 | 2.2160 -0.1370 0.9630 N 0 0 0 0 0 0 0 0 0 0 0 0 71 | 2.3920 1.0490 1.7980 C 0 0 0 0 0 0 0 0 0 0 0 0 72 | 2.5740 2.2440 0.9400 C 0 0 0 0 0 0 0 0 0 0 0 0 73 | 1.5650 2.7240 0.1280 N 0 0 0 0 0 0 0 0 0 0 0 0 74 | 2.1130 3.8540 -0.4630 C 0 0 0 0 0 0 0 0 0 0 0 0 75 | 3.3400 4.0380 -0.0060 N 0 0 0 0 0 0 0 0 0 0 0 0 76 | 3.6290 3.0300 0.8690 N 0 0 0 0 0 0 0 0 0 0 0 0 77 | 1.4840 4.6740 -1.5280 C 0 0 0 0 0 0 0 0 0 0 0 0 78 | 1.0460 -1.4460 -0.6450 C 0 0 0 0 0 0 0 0 0 0 0 0 79 | 1.4880 -2.6810 -0.1550 C 0 0 0 0 0 0 0 0 0 0 0 0 80 | 1.4020 -3.8220 -0.9540 C 0 0 0 0 0 0 0 0 0 0 0 0 81 | 0.8850 -3.7320 -2.2460 C 0 0 0 0 0 0 0 0 0 0 0 0 82 | 0.4570 -2.5010 -2.7440 C 0 0 0 0 0 0 0 0 0 0 0 0 83 | 0.5400 -1.3560 -1.9490 C 0 0 0 0 0 0 0 0 0 0 0 0 84 | -1.2710 0.2870 0.1850 C 0 0 0 0 0 0 0 0 0 0 0 0 85 | -2.3510 1.1500 0.0210 C 0 0 0 0 0 0 0 0 0 0 0 0 86 | -2.1400 2.5130 -0.1500 C 0 0 0 0 0 0 0 0 0 0 0 0 87 | -0.8390 3.0250 -0.1400 C 0 0 0 0 0 0 0 0 0 0 0 0 88 | -3.9550 0.5270 0.0280 Cl 0 0 0 0 0 0 0 0 0 0 0 0 89 | 1 2 2 0 90 | 1 7 1 0 91 | 1 21 1 0 92 | 2 3 1 0 93 | 2 18 1 0 94 | 3 4 2 0 95 | 3 12 1 0 96 | 4 5 1 0 97 | 5 6 1 0 98 | 6 7 1 0 99 | 6 10 2 0 100 | 7 8 1 0 101 | 8 9 2 0 102 | 8 11 1 0 103 | 9 10 1 0 104 | 12 13 2 0 105 | 12 17 1 0 106 | 13 14 1 0 107 | 14 15 2 0 108 | 15 16 1 0 109 | 16 17 2 0 110 | 18 19 2 0 111 | 19 20 1 0 112 | 19 22 1 0 113 | 20 21 2 0 114 | M END 115 | > (2) 116 | 7.7 117 | 118 | $$$$ 119 | Bromazepam 120 | RDKit 3D 121 | 122 | 19 21 0 0 0 0 0 0 0 0999 V2000 123 | -2.0990 2.5010 -0.2150 C 0 0 0 0 0 0 0 0 0 0 0 0 124 | -2.3360 1.1420 -0.0350 C 0 0 0 0 0 0 0 0 0 0 0 0 125 | -1.2740 0.2630 0.1670 C 0 0 0 0 0 0 0 0 0 0 0 0 126 | 0.0470 0.7440 0.2000 C 0 0 0 0 0 0 0 0 0 0 0 0 127 | 0.2840 2.1260 0.0980 C 0 0 0 0 0 0 0 0 0 0 0 0 128 | -0.7930 2.9880 -0.1530 C 0 0 0 0 0 0 0 0 0 0 0 0 129 | 1.5460 2.7340 0.2240 N 0 0 0 0 0 0 0 0 0 0 0 0 130 | 2.6270 2.2550 0.9180 C 0 0 0 0 0 0 0 0 0 0 0 0 131 | 2.4060 1.0180 1.7760 C 0 0 0 0 0 0 0 0 0 0 0 0 132 | 2.2460 -0.1570 0.9210 N 0 0 0 0 0 0 0 0 0 0 0 0 133 | 1.1620 -0.2580 0.2170 C 0 0 0 0 0 0 0 0 0 0 0 0 134 | 1.0290 -1.4640 -0.6740 C 0 0 0 0 0 0 0 0 0 0 0 0 135 | 1.4240 -2.7240 -0.2390 C 0 0 0 0 0 0 0 0 0 0 0 0 136 | 1.2650 -3.7990 -1.1090 C 0 0 0 0 0 0 0 0 0 0 0 0 137 | 0.7140 -3.5840 -2.3680 C 0 0 0 0 0 0 0 0 0 0 0 0 138 | 0.3360 -2.2970 -2.7130 C 0 0 0 0 0 0 0 0 0 0 0 0 139 | 0.4760 -1.2280 -1.8950 N 0 0 0 0 0 0 0 0 0 0 0 0 140 | 3.7080 2.8530 0.8890 O 0 0 0 0 0 0 0 0 0 0 0 0 141 | -4.1060 0.4810 -0.0970 Br 0 0 0 0 0 0 0 0 0 0 0 0 142 | 1 2 2 0 143 | 1 6 1 0 144 | 2 3 1 0 145 | 2 19 1 0 146 | 3 4 2 0 147 | 4 5 1 0 148 | 4 11 1 0 149 | 5 6 2 0 150 | 5 7 1 0 151 | 7 8 1 0 152 | 8 9 1 0 153 | 8 18 2 0 154 | 9 10 1 0 155 | 10 11 2 0 156 | 11 12 1 0 157 | 12 13 2 0 158 | 12 17 1 0 159 | 13 14 1 0 160 | 14 15 2 0 161 | 15 16 1 0 162 | 16 17 2 0 163 | M END 164 | > (3) 165 | 7.74 166 | 167 | $$$$ 168 | Chlordiazepoxide 169 | RDKit 3D 170 | 171 | 21 23 0 0 0 0 0 0 0 0999 V2000 172 | -0.0910 2.0860 -0.0350 C 0 0 0 0 0 0 0 0 0 0 0 0 173 | -0.2000 0.6830 0.0450 C 0 0 0 0 0 0 0 0 0 0 0 0 174 | 0.9990 -0.2010 0.0730 C 0 0 0 0 0 0 0 0 0 0 0 0 175 | 2.0630 0.1350 0.7870 N 0 0 0 0 0 0 0 0 0 0 0 0 176 | 2.1220 1.3680 1.5940 C 0 0 0 0 0 0 0 0 0 0 0 0 177 | 2.1400 2.5130 0.6060 C 0 0 0 0 0 0 0 0 0 0 0 0 178 | 1.1130 2.8070 -0.1400 N 0 0 0 0 0 0 0 0 0 0 0 0 179 | 3.2990 3.2480 0.5150 N 0 0 0 0 0 0 0 0 0 0 0 0 180 | 3.4610 4.4220 -0.3100 C 0 0 0 0 0 0 0 0 0 0 0 0 181 | 3.1100 -0.6190 0.8050 O 0 0 0 0 0 0 0 0 0 0 0 0 182 | 0.9880 -1.4560 -0.7120 C 0 0 0 0 0 0 0 0 0 0 0 0 183 | 0.4820 -1.4380 -2.0150 C 0 0 0 0 0 0 0 0 0 0 0 0 184 | 0.4280 -2.6220 -2.7510 C 0 0 0 0 0 0 0 0 0 0 0 0 185 | 0.8710 -3.8180 -2.1840 C 0 0 0 0 0 0 0 0 0 0 0 0 186 | 1.3680 -3.8350 -0.8800 C 0 0 0 0 0 0 0 0 0 0 0 0 187 | 1.4250 -2.6540 -0.1390 C 0 0 0 0 0 0 0 0 0 0 0 0 188 | -1.4650 0.0740 0.1110 C 0 0 0 0 0 0 0 0 0 0 0 0 189 | -2.6180 0.8550 0.0840 C 0 0 0 0 0 0 0 0 0 0 0 0 190 | -2.5270 2.2390 -0.0090 C 0 0 0 0 0 0 0 0 0 0 0 0 191 | -1.2700 2.8450 -0.0710 C 0 0 0 0 0 0 0 0 0 0 0 0 192 | -4.1640 0.1030 0.1650 Cl 0 0 0 0 0 0 0 0 0 0 0 0 193 | 1 2 2 0 194 | 1 7 1 0 195 | 1 20 1 0 196 | 2 3 1 0 197 | 2 17 1 0 198 | 3 4 2 0 199 | 3 11 1 0 200 | 4 5 1 0 201 | 4 10 1 0 202 | 5 6 1 0 203 | 6 7 2 0 204 | 6 8 1 0 205 | 8 9 1 0 206 | 11 12 2 0 207 | 11 16 1 0 208 | 12 13 1 0 209 | 13 14 2 0 210 | 14 15 1 0 211 | 15 16 2 0 212 | 17 18 2 0 213 | 18 19 1 0 214 | 18 21 1 0 215 | 19 20 2 0 216 | M CHG 2 4 1 10 -1 217 | M END 218 | > (4) 219 | 6.45 220 | 221 | $$$$ 222 | Clobazam 223 | RDKit 3D 224 | 225 | 21 23 0 0 0 0 0 0 0 0999 V2000 226 | 0.2930 2.1180 0.0630 C 0 0 0 0 0 0 0 0 0 0 0 0 227 | 0.0440 0.7210 0.1520 C 0 0 0 0 0 0 0 0 0 0 0 0 228 | 1.0780 -0.2890 0.2100 N 0 0 0 0 0 0 0 0 0 0 0 0 229 | 2.2570 -0.1330 0.9460 C 0 0 0 0 0 0 0 0 0 0 0 0 230 | 2.3350 1.1000 1.7870 C 0 0 0 0 0 0 0 0 0 0 0 0 231 | 2.6400 2.2620 0.8970 C 0 0 0 0 0 0 0 0 0 0 0 0 232 | 1.6010 2.7110 0.0910 N 0 0 0 0 0 0 0 0 0 0 0 0 233 | 1.8300 3.9340 -0.6780 C 0 0 0 0 0 0 0 0 0 0 0 0 234 | 3.7540 2.7970 0.9270 O 0 0 0 0 0 0 0 0 0 0 0 0 235 | 3.2150 -0.9160 0.9300 O 0 0 0 0 0 0 0 0 0 0 0 0 236 | 0.8640 -1.4970 -0.5500 C 0 0 0 0 0 0 0 0 0 0 0 0 237 | 0.2700 -1.4540 -1.8260 C 0 0 0 0 0 0 0 0 0 0 0 0 238 | 0.0670 -2.6220 -2.5670 C 0 0 0 0 0 0 0 0 0 0 0 0 239 | 0.4580 -3.8540 -2.0500 C 0 0 0 0 0 0 0 0 0 0 0 0 240 | 1.0550 -3.9170 -0.7940 C 0 0 0 0 0 0 0 0 0 0 0 0 241 | 1.2600 -2.7480 -0.0530 C 0 0 0 0 0 0 0 0 0 0 0 0 242 | -1.3030 0.2780 0.1610 C 0 0 0 0 0 0 0 0 0 0 0 0 243 | -2.3680 1.1650 0.0270 C 0 0 0 0 0 0 0 0 0 0 0 0 244 | -2.1260 2.5190 -0.1120 C 0 0 0 0 0 0 0 0 0 0 0 0 245 | -0.8100 2.9860 -0.0940 C 0 0 0 0 0 0 0 0 0 0 0 0 246 | -3.9840 0.5760 0.0340 Cl 0 0 0 0 0 0 0 0 0 0 0 0 247 | 1 2 2 0 248 | 1 7 1 0 249 | 1 20 1 0 250 | 2 3 1 0 251 | 2 17 1 0 252 | 3 4 1 0 253 | 3 11 1 0 254 | 4 5 1 0 255 | 4 10 2 0 256 | 5 6 1 0 257 | 6 7 1 0 258 | 6 9 2 0 259 | 7 8 1 0 260 | 11 12 2 0 261 | 11 16 1 0 262 | 12 13 1 0 263 | 13 14 2 0 264 | 14 15 1 0 265 | 15 16 2 0 266 | 17 18 2 0 267 | 18 19 1 0 268 | 18 21 1 0 269 | 19 20 2 0 270 | M END 271 | > (5) 272 | 6.89 273 | 274 | $$$$ 275 | Clonazepam 276 | RDKit 3D 277 | 278 | 22 24 0 0 0 0 0 0 0 0999 V2000 279 | -2.1020 2.4770 -0.2560 C 0 0 0 0 0 0 0 0 0 0 0 0 280 | -2.3290 1.1080 -0.0950 C 0 0 0 0 0 0 0 0 0 0 0 0 281 | -1.2560 0.2350 0.1310 C 0 0 0 0 0 0 0 0 0 0 0 0 282 | 0.0590 0.7350 0.2110 C 0 0 0 0 0 0 0 0 0 0 0 0 283 | 0.2820 2.1220 0.1100 C 0 0 0 0 0 0 0 0 0 0 0 0 284 | -0.8000 2.9740 -0.1610 C 0 0 0 0 0 0 0 0 0 0 0 0 285 | 1.5340 2.7480 0.2390 N 0 0 0 0 0 0 0 0 0 0 0 0 286 | 2.6320 2.2850 0.9160 C 0 0 0 0 0 0 0 0 0 0 0 0 287 | 2.4430 1.0470 1.7750 C 0 0 0 0 0 0 0 0 0 0 0 0 288 | 2.2840 -0.1320 0.9260 N 0 0 0 0 0 0 0 0 0 0 0 0 289 | 1.1850 -0.2540 0.2570 C 0 0 0 0 0 0 0 0 0 0 0 0 290 | 1.0570 -1.4720 -0.5920 C 0 0 0 0 0 0 0 0 0 0 0 0 291 | 1.5110 -2.6890 -0.0630 C 0 0 0 0 0 0 0 0 0 0 0 0 292 | 1.4020 -3.8580 -0.8160 C 0 0 0 0 0 0 0 0 0 0 0 0 293 | 0.8400 -3.8160 -2.0920 C 0 0 0 0 0 0 0 0 0 0 0 0 294 | 0.3860 -2.6050 -2.6190 C 0 0 0 0 0 0 0 0 0 0 0 0 295 | 0.4910 -1.4280 -1.8720 C 0 0 0 0 0 0 0 0 0 0 0 0 296 | -0.0420 0.0450 -2.6030 Cl 0 0 0 0 0 0 0 0 0 0 0 0 297 | 3.7020 2.9020 0.8750 O 0 0 0 0 0 0 0 0 0 0 0 0 298 | -3.6970 0.5800 -0.1820 N 0 0 0 0 0 0 0 0 0 0 0 0 299 | -3.8700 -0.6400 -0.0020 O 0 0 0 0 0 0 0 0 0 0 0 0 300 | -4.6230 1.3750 -0.4300 O 0 0 0 0 0 0 0 0 0 0 0 0 301 | 1 2 2 0 302 | 1 6 1 0 303 | 2 3 1 0 304 | 2 20 1 0 305 | 3 4 2 0 306 | 4 5 1 0 307 | 4 11 1 0 308 | 5 6 2 0 309 | 5 7 1 0 310 | 7 8 1 0 311 | 8 9 1 0 312 | 8 19 2 0 313 | 9 10 1 0 314 | 10 11 2 0 315 | 11 12 1 0 316 | 12 13 2 0 317 | 12 17 1 0 318 | 13 14 1 0 319 | 14 15 2 0 320 | 15 16 1 0 321 | 16 17 2 0 322 | 17 18 1 0 323 | 20 21 2 0 324 | 20 22 1 0 325 | M CHG 2 20 1 22 -1 326 | M END 327 | > (6) 328 | 8.74 329 | 330 | $$$$ 331 | Clorazepate 332 | RDKit 3D 333 | 334 | 22 24 0 0 0 0 0 0 0 0999 V2000 335 | -2.1080 2.5070 -0.1800 C 0 0 0 0 0 0 0 0 0 0 0 0 336 | -2.3420 1.1480 -0.0050 C 0 0 0 0 0 0 0 0 0 0 0 0 337 | -1.2770 0.2700 0.1880 C 0 0 0 0 0 0 0 0 0 0 0 0 338 | 0.0420 0.7550 0.2160 C 0 0 0 0 0 0 0 0 0 0 0 0 339 | 0.2770 2.1370 0.1160 C 0 0 0 0 0 0 0 0 0 0 0 0 340 | -0.8020 2.9980 -0.1250 C 0 0 0 0 0 0 0 0 0 0 0 0 341 | 1.5400 2.7440 0.2290 N 0 0 0 0 0 0 0 0 0 0 0 0 342 | 2.6350 2.2630 0.9070 C 0 0 0 0 0 0 0 0 0 0 0 0 343 | 2.4110 1.0430 1.7950 C 0 0 0 0 0 0 0 0 0 0 0 0 344 | 2.2420 -0.1450 0.9330 N 0 0 0 0 0 0 0 0 0 0 0 0 345 | 1.1580 -0.2450 0.2330 C 0 0 0 0 0 0 0 0 0 0 0 0 346 | 1.0370 -1.4570 -0.6410 C 0 0 0 0 0 0 0 0 0 0 0 0 347 | 1.4750 -2.6950 -0.1560 C 0 0 0 0 0 0 0 0 0 0 0 0 348 | 1.3790 -3.8340 -0.9580 C 0 0 0 0 0 0 0 0 0 0 0 0 349 | 0.8560 -3.7370 -2.2470 C 0 0 0 0 0 0 0 0 0 0 0 0 350 | 0.4340 -2.5020 -2.7400 C 0 0 0 0 0 0 0 0 0 0 0 0 351 | 0.5270 -1.3600 -1.9420 C 0 0 0 0 0 0 0 0 0 0 0 0 352 | 3.5890 0.8060 2.7350 C 0 0 0 0 0 0 0 0 0 0 0 0 353 | 3.8940 1.4520 3.7300 O 0 0 0 0 0 0 0 0 0 0 0 0 354 | 4.3510 -0.2470 2.3480 O 0 0 0 0 0 0 0 0 0 0 0 0 355 | 3.7150 2.8580 0.8190 O 0 0 0 0 0 0 0 0 0 0 0 0 356 | -3.9520 0.5420 -0.0550 Cl 0 0 0 0 0 0 0 0 0 0 0 0 357 | 1 2 2 0 358 | 1 6 1 0 359 | 2 3 1 0 360 | 2 22 1 0 361 | 3 4 2 0 362 | 4 5 1 0 363 | 4 11 1 0 364 | 5 6 2 0 365 | 5 7 1 0 366 | 7 8 1 0 367 | 8 9 1 0 368 | 8 21 2 0 369 | 9 10 1 0 370 | 9 18 1 0 371 | 10 11 2 0 372 | 11 12 1 0 373 | 12 13 2 0 374 | 12 17 1 0 375 | 13 14 1 0 376 | 14 15 2 0 377 | 15 16 1 0 378 | 16 17 2 0 379 | 18 19 2 0 380 | 18 20 1 0 381 | M END 382 | > (7) 383 | 7.23 384 | 385 | $$$$ 386 | Delorazepam 387 | RDKit 3D 388 | 389 | 20 22 0 0 0 0 0 0 0 0999 V2000 390 | -2.1060 2.4660 -0.2050 C 0 0 0 0 0 0 0 0 0 0 0 0 391 | -2.3220 1.1020 -0.0470 C 0 0 0 0 0 0 0 0 0 0 0 0 392 | -1.2490 0.2380 0.1600 C 0 0 0 0 0 0 0 0 0 0 0 0 393 | 0.0640 0.7390 0.2280 C 0 0 0 0 0 0 0 0 0 0 0 0 394 | 0.2820 2.1260 0.1300 C 0 0 0 0 0 0 0 0 0 0 0 0 395 | -0.8080 2.9730 -0.1240 C 0 0 0 0 0 0 0 0 0 0 0 0 396 | 1.5330 2.7570 0.2430 N 0 0 0 0 0 0 0 0 0 0 0 0 397 | 2.6420 2.2930 0.9010 C 0 0 0 0 0 0 0 0 0 0 0 0 398 | 2.4700 1.0520 1.7580 C 0 0 0 0 0 0 0 0 0 0 0 0 399 | 2.3000 -0.1250 0.9100 N 0 0 0 0 0 0 0 0 0 0 0 0 400 | 1.1910 -0.2480 0.2570 C 0 0 0 0 0 0 0 0 0 0 0 0 401 | 1.0510 -1.4670 -0.5880 C 0 0 0 0 0 0 0 0 0 0 0 0 402 | 1.5130 -2.6830 -0.0650 C 0 0 0 0 0 0 0 0 0 0 0 0 403 | 1.3930 -3.8530 -0.8160 C 0 0 0 0 0 0 0 0 0 0 0 0 404 | 0.8120 -3.8110 -2.0830 C 0 0 0 0 0 0 0 0 0 0 0 0 405 | 0.3500 -2.6000 -2.6050 C 0 0 0 0 0 0 0 0 0 0 0 0 406 | 0.4660 -1.4230 -1.8600 C 0 0 0 0 0 0 0 0 0 0 0 0 407 | -0.0760 0.0500 -2.5820 Cl 0 0 0 0 0 0 0 0 0 0 0 0 408 | 3.7090 2.9130 0.8460 O 0 0 0 0 0 0 0 0 0 0 0 0 409 | -3.9220 0.4730 -0.1360 Cl 0 0 0 0 0 0 0 0 0 0 0 0 410 | 1 2 2 0 411 | 1 6 1 0 412 | 2 3 1 0 413 | 2 20 1 0 414 | 3 4 2 0 415 | 4 5 1 0 416 | 4 11 1 0 417 | 5 6 2 0 418 | 5 7 1 0 419 | 7 8 1 0 420 | 8 9 1 0 421 | 8 19 2 0 422 | 9 10 1 0 423 | 10 11 2 0 424 | 11 12 1 0 425 | 12 13 2 0 426 | 12 17 1 0 427 | 13 14 1 0 428 | 14 15 2 0 429 | 15 16 1 0 430 | 16 17 2 0 431 | 17 18 1 0 432 | M END 433 | > (8) 434 | 8.74 435 | 436 | $$$$ 437 | Demoxepam 438 | RDKit 3D 439 | 440 | 20 22 0 0 0 0 0 0 0 0999 V2000 441 | 0.2850 2.1280 0.1420 C 0 0 0 0 0 0 0 0 0 0 0 0 442 | 0.0730 0.7380 0.2120 C 0 0 0 0 0 0 0 0 0 0 0 0 443 | 1.1900 -0.2520 0.2050 C 0 0 0 0 0 0 0 0 0 0 0 0 444 | 2.2910 -0.0610 0.9120 N 0 0 0 0 0 0 0 0 0 0 0 0 445 | 2.4730 1.0890 1.7960 C 0 0 0 0 0 0 0 0 0 0 0 0 446 | 2.6410 2.2960 0.9250 C 0 0 0 0 0 0 0 0 0 0 0 0 447 | 1.5370 2.7560 0.2620 N 0 0 0 0 0 0 0 0 0 0 0 0 448 | 3.7080 2.9180 0.8710 O 0 0 0 0 0 0 0 0 0 0 0 0 449 | 3.2630 -0.9080 0.8600 O 0 0 0 0 0 0 0 0 0 0 0 0 450 | 1.0670 -1.4620 -0.6450 C 0 0 0 0 0 0 0 0 0 0 0 0 451 | 0.5110 -1.3420 -1.9220 C 0 0 0 0 0 0 0 0 0 0 0 0 452 | 0.3530 -2.4800 -2.7140 C 0 0 0 0 0 0 0 0 0 0 0 0 453 | 0.7440 -3.7300 -2.2290 C 0 0 0 0 0 0 0 0 0 0 0 0 454 | 1.2930 -3.8460 -0.9510 C 0 0 0 0 0 0 0 0 0 0 0 0 455 | 1.4540 -2.7120 -0.1530 C 0 0 0 0 0 0 0 0 0 0 0 0 456 | -1.2370 0.2360 0.1370 C 0 0 0 0 0 0 0 0 0 0 0 0 457 | -2.3140 1.1010 -0.0480 C 0 0 0 0 0 0 0 0 0 0 0 0 458 | -2.1030 2.4680 -0.1760 C 0 0 0 0 0 0 0 0 0 0 0 0 459 | -0.8060 2.9780 -0.0900 C 0 0 0 0 0 0 0 0 0 0 0 0 460 | -3.9130 0.4700 -0.1440 Cl 0 0 0 0 0 0 0 0 0 0 0 0 461 | 1 2 2 0 462 | 1 7 1 0 463 | 1 19 1 0 464 | 2 3 1 0 465 | 2 16 1 0 466 | 3 4 2 0 467 | 3 10 1 0 468 | 4 5 1 0 469 | 4 9 1 0 470 | 5 6 1 0 471 | 6 7 1 0 472 | 6 8 2 0 473 | 10 11 2 0 474 | 10 15 1 0 475 | 11 12 1 0 476 | 12 13 2 0 477 | 13 14 1 0 478 | 14 15 2 0 479 | 16 17 2 0 480 | 17 18 1 0 481 | 17 20 1 0 482 | 18 19 2 0 483 | M CHG 2 4 1 9 -1 484 | M END 485 | > (9) 486 | 6.51 487 | 488 | $$$$ 489 | Desmethylclobazam 490 | RDKit 3D 491 | 492 | 20 22 0 0 0 0 0 0 0 0999 V2000 493 | 0.2850 2.0670 0.1060 C 0 0 0 0 0 0 0 0 0 0 0 0 494 | 0.0220 0.6800 0.2230 C 0 0 0 0 0 0 0 0 0 0 0 0 495 | 1.0480 -0.3420 0.2840 N 0 0 0 0 0 0 0 0 0 0 0 0 496 | 2.2970 -0.1660 0.8900 C 0 0 0 0 0 0 0 0 0 0 0 0 497 | 2.4550 1.0490 1.7410 C 0 0 0 0 0 0 0 0 0 0 0 0 498 | 2.6400 2.2550 0.8840 C 0 0 0 0 0 0 0 0 0 0 0 0 499 | 1.5470 2.6830 0.1900 N 0 0 0 0 0 0 0 0 0 0 0 0 500 | 3.7010 2.8840 0.8500 O 0 0 0 0 0 0 0 0 0 0 0 0 501 | 3.2520 -0.9460 0.7720 O 0 0 0 0 0 0 0 0 0 0 0 0 502 | 0.7780 -1.5890 -0.3910 C 0 0 0 0 0 0 0 0 0 0 0 0 503 | 0.1560 -1.6160 -1.6520 C 0 0 0 0 0 0 0 0 0 0 0 0 504 | -0.0960 -2.8260 -2.3040 C 0 0 0 0 0 0 0 0 0 0 0 0 505 | 0.2730 -4.0300 -1.7100 C 0 0 0 0 0 0 0 0 0 0 0 0 506 | 0.9000 -4.0230 -0.4670 C 0 0 0 0 0 0 0 0 0 0 0 0 507 | 1.1550 -2.8120 0.1850 C 0 0 0 0 0 0 0 0 0 0 0 0 508 | -1.3340 0.2740 0.2180 C 0 0 0 0 0 0 0 0 0 0 0 0 509 | -2.3730 1.1810 0.0140 C 0 0 0 0 0 0 0 0 0 0 0 0 510 | -2.0970 2.5220 -0.1910 C 0 0 0 0 0 0 0 0 0 0 0 0 511 | -0.7750 2.9590 -0.1470 C 0 0 0 0 0 0 0 0 0 0 0 0 512 | -4.0030 0.6290 -0.0020 Cl 0 0 0 0 0 0 0 0 0 0 0 0 513 | 1 2 2 0 514 | 1 7 1 0 515 | 1 19 1 0 516 | 2 3 1 0 517 | 2 16 1 0 518 | 3 4 1 0 519 | 3 10 1 0 520 | 4 5 1 0 521 | 4 9 2 0 522 | 5 6 1 0 523 | 6 7 1 0 524 | 6 8 2 0 525 | 10 11 2 0 526 | 10 15 1 0 527 | 11 12 1 0 528 | 12 13 2 0 529 | 13 14 1 0 530 | 14 15 2 0 531 | 16 17 2 0 532 | 17 18 1 0 533 | 17 20 1 0 534 | 18 19 2 0 535 | M END 536 | > (10) 537 | 6.68 538 | 539 | $$$$ 540 | Desmethyltetrazepam 541 | RDKit 3D 542 | 543 | 19 21 0 0 0 0 0 0 0 0999 V2000 544 | -2.1110 2.5190 -0.1810 C 0 0 0 0 0 0 0 0 0 0 0 0 545 | -2.3550 1.1630 0.0020 C 0 0 0 0 0 0 0 0 0 0 0 0 546 | -1.2970 0.2790 0.2010 C 0 0 0 0 0 0 0 0 0 0 0 0 547 | 0.0280 0.7520 0.2250 C 0 0 0 0 0 0 0 0 0 0 0 0 548 | 0.2730 2.1320 0.1120 C 0 0 0 0 0 0 0 0 0 0 0 0 549 | -0.8010 3.0000 -0.1320 C 0 0 0 0 0 0 0 0 0 0 0 0 550 | 1.5400 2.7330 0.2130 N 0 0 0 0 0 0 0 0 0 0 0 0 551 | 2.6350 2.2480 0.8800 C 0 0 0 0 0 0 0 0 0 0 0 0 552 | 2.4250 1.0240 1.7570 C 0 0 0 0 0 0 0 0 0 0 0 0 553 | 2.2360 -0.1630 0.9240 N 0 0 0 0 0 0 0 0 0 0 0 0 554 | 1.1360 -0.2560 0.2480 C 0 0 0 0 0 0 0 0 0 0 0 0 555 | 0.9540 -1.4780 -0.6100 C 0 0 0 0 0 0 0 0 0 0 0 0 556 | 0.5620 -1.3470 -1.8900 C 0 0 0 0 0 0 0 0 0 0 0 0 557 | 0.3540 -2.5170 -2.8080 C 0 0 0 0 0 0 0 0 0 0 0 0 558 | 0.3340 -3.8600 -2.0770 C 0 0 0 0 0 0 0 0 0 0 0 0 559 | 1.4370 -3.9310 -1.0260 C 0 0 0 0 0 0 0 0 0 0 0 0 560 | 1.2920 -2.8110 0.0080 C 0 0 0 0 0 0 0 0 0 0 0 0 561 | 3.7200 2.8360 0.8170 O 0 0 0 0 0 0 0 0 0 0 0 0 562 | -3.9690 0.5690 -0.0430 Cl 0 0 0 0 0 0 0 0 0 0 0 0 563 | 1 2 2 0 564 | 1 6 1 0 565 | 2 3 1 0 566 | 2 19 1 0 567 | 3 4 2 0 568 | 4 5 1 0 569 | 4 11 1 0 570 | 5 6 2 0 571 | 5 7 1 0 572 | 7 8 1 0 573 | 8 9 1 0 574 | 8 18 2 0 575 | 9 10 1 0 576 | 10 11 2 0 577 | 11 12 1 0 578 | 12 13 2 0 579 | 12 17 1 0 580 | 13 14 1 0 581 | 14 15 1 0 582 | 15 16 1 0 583 | 16 17 1 0 584 | M END 585 | > (11) 586 | 7.47 587 | 588 | $$$$ 589 | Diazepam 590 | RDKit 3D 591 | 592 | 20 22 0 0 0 0 0 0 0 0999 V2000 593 | -2.1340 2.5050 -0.1520 C 0 0 0 0 0 0 0 0 0 0 0 0 594 | -2.3560 1.1480 0.0350 C 0 0 0 0 0 0 0 0 0 0 0 0 595 | -1.2800 0.2830 0.2010 C 0 0 0 0 0 0 0 0 0 0 0 0 596 | 0.0390 0.7770 0.1800 C 0 0 0 0 0 0 0 0 0 0 0 0 597 | 0.2840 2.1610 0.0480 C 0 0 0 0 0 0 0 0 0 0 0 0 598 | -0.8280 3.0040 -0.1470 C 0 0 0 0 0 0 0 0 0 0 0 0 599 | 1.5950 2.7420 0.1020 N 0 0 0 0 0 0 0 0 0 0 0 0 600 | 2.6360 2.2370 0.8850 C 0 0 0 0 0 0 0 0 0 0 0 0 601 | 2.3000 1.0700 1.8060 C 0 0 0 0 0 0 0 0 0 0 0 0 602 | 2.1830 -0.1410 0.9950 N 0 0 0 0 0 0 0 0 0 0 0 0 603 | 1.1390 -0.2360 0.2350 C 0 0 0 0 0 0 0 0 0 0 0 0 604 | 1.0410 -1.4460 -0.6440 C 0 0 0 0 0 0 0 0 0 0 0 0 605 | 0.5420 -1.3520 -1.9500 C 0 0 0 0 0 0 0 0 0 0 0 0 606 | 0.4700 -2.4930 -2.7520 C 0 0 0 0 0 0 0 0 0 0 0 0 607 | 0.9020 -3.7240 -2.2590 C 0 0 0 0 0 0 0 0 0 0 0 0 608 | 1.4130 -3.8190 -0.9650 C 0 0 0 0 0 0 0 0 0 0 0 0 609 | 1.4880 -2.6820 -0.1590 C 0 0 0 0 0 0 0 0 0 0 0 0 610 | 3.7740 2.7240 0.8830 O 0 0 0 0 0 0 0 0 0 0 0 0 611 | 1.8390 3.9820 -0.6320 C 0 0 0 0 0 0 0 0 0 0 0 0 612 | -3.9620 0.5330 0.0470 Cl 0 0 0 0 0 0 0 0 0 0 0 0 613 | 1 2 2 0 614 | 1 6 1 0 615 | 2 3 1 0 616 | 2 20 1 0 617 | 3 4 2 0 618 | 4 5 1 0 619 | 4 11 1 0 620 | 5 6 2 0 621 | 5 7 1 0 622 | 7 8 1 0 623 | 7 19 1 0 624 | 8 9 1 0 625 | 8 18 2 0 626 | 9 10 1 0 627 | 10 11 2 0 628 | 11 12 1 0 629 | 12 13 2 0 630 | 12 17 1 0 631 | 13 14 1 0 632 | 14 15 2 0 633 | 15 16 1 0 634 | 16 17 2 0 635 | M END 636 | > (12) 637 | 8.09 638 | 639 | $$$$ 640 | Estazolam 641 | RDKit 3D 642 | 643 | 21 24 0 0 0 0 0 0 0 0999 V2000 644 | 0.2520 2.1720 0.0710 C 0 0 0 0 0 0 0 0 0 0 0 0 645 | 0.0510 0.7830 0.2030 C 0 0 0 0 0 0 0 0 0 0 0 0 646 | 1.1710 -0.2230 0.2290 C 0 0 0 0 0 0 0 0 0 0 0 0 647 | 2.2590 -0.1290 0.9240 N 0 0 0 0 0 0 0 0 0 0 0 0 648 | 2.4690 1.0400 1.7700 C 0 0 0 0 0 0 0 0 0 0 0 0 649 | 2.5920 2.2610 0.9410 C 0 0 0 0 0 0 0 0 0 0 0 0 650 | 1.5340 2.7530 0.2080 N 0 0 0 0 0 0 0 0 0 0 0 0 651 | 1.9870 3.9590 -0.2660 C 0 0 0 0 0 0 0 0 0 0 0 0 652 | 3.2390 4.1540 0.0900 N 0 0 0 0 0 0 0 0 0 0 0 0 653 | 3.6230 3.0820 0.8520 N 0 0 0 0 0 0 0 0 0 0 0 0 654 | 1.0420 -1.4400 -0.6390 C 0 0 0 0 0 0 0 0 0 0 0 0 655 | 1.4760 -2.6780 -0.1500 C 0 0 0 0 0 0 0 0 0 0 0 0 656 | 1.3720 -3.8190 -0.9470 C 0 0 0 0 0 0 0 0 0 0 0 0 657 | 0.8450 -3.7250 -2.2350 C 0 0 0 0 0 0 0 0 0 0 0 0 658 | 0.4270 -2.4910 -2.7320 C 0 0 0 0 0 0 0 0 0 0 0 0 659 | 0.5280 -1.3460 -1.9390 C 0 0 0 0 0 0 0 0 0 0 0 0 660 | -1.2620 0.2780 0.1940 C 0 0 0 0 0 0 0 0 0 0 0 0 661 | -2.3460 1.1310 -0.0040 C 0 0 0 0 0 0 0 0 0 0 0 0 662 | -2.1440 2.4920 -0.1980 C 0 0 0 0 0 0 0 0 0 0 0 0 663 | -0.8490 3.0160 -0.1620 C 0 0 0 0 0 0 0 0 0 0 0 0 664 | -3.9440 0.4920 -0.0290 Cl 0 0 0 0 0 0 0 0 0 0 0 0 665 | 1 2 2 0 666 | 1 7 1 0 667 | 1 20 1 0 668 | 2 3 1 0 669 | 2 17 1 0 670 | 3 4 2 0 671 | 3 11 1 0 672 | 4 5 1 0 673 | 5 6 1 0 674 | 6 7 1 0 675 | 6 10 2 0 676 | 7 8 1 0 677 | 8 9 2 0 678 | 9 10 1 0 679 | 11 12 2 0 680 | 11 16 1 0 681 | 12 13 1 0 682 | 13 14 2 0 683 | 14 15 1 0 684 | 15 16 2 0 685 | 17 18 2 0 686 | 18 19 1 0 687 | 18 21 1 0 688 | 19 20 2 0 689 | M END 690 | > (13) 691 | 8.07 692 | 693 | $$$$ 694 | Etizolam 695 | RDKit 3D 696 | 697 | 23 26 0 0 0 0 0 0 0 0999 V2000 698 | 0.1810 2.0600 0.1640 C 0 0 0 0 0 0 0 0 0 0 0 0 699 | 0.0930 0.6760 0.1590 C 0 0 0 0 0 0 0 0 0 0 0 0 700 | 1.2260 -0.2600 0.1850 C 0 0 0 0 0 0 0 0 0 0 0 0 701 | 2.3320 -0.0750 0.8230 N 0 0 0 0 0 0 0 0 0 0 0 0 702 | 2.4850 1.0680 1.7170 C 0 0 0 0 0 0 0 0 0 0 0 0 703 | 2.4730 2.3630 0.9960 C 0 0 0 0 0 0 0 0 0 0 0 0 704 | 1.3450 2.8190 0.3350 N 0 0 0 0 0 0 0 0 0 0 0 0 705 | 1.6910 4.1170 -0.0370 C 0 0 0 0 0 0 0 0 0 0 0 0 706 | 2.9290 4.3760 0.3480 N 0 0 0 0 0 0 0 0 0 0 0 0 707 | 3.4190 3.2800 0.9910 N 0 0 0 0 0 0 0 0 0 0 0 0 708 | 0.8590 5.0540 -0.8310 C 0 0 0 0 0 0 0 0 0 0 0 0 709 | 1.0880 -1.4930 -0.6270 C 0 0 0 0 0 0 0 0 0 0 0 0 710 | 1.5780 -2.6950 -0.0970 C 0 0 0 0 0 0 0 0 0 0 0 0 711 | 1.4580 -3.8760 -0.8290 C 0 0 0 0 0 0 0 0 0 0 0 0 712 | 0.8500 -3.8590 -2.0840 C 0 0 0 0 0 0 0 0 0 0 0 0 713 | 0.3610 -2.6610 -2.6120 C 0 0 0 0 0 0 0 0 0 0 0 0 714 | 0.4780 -1.4730 -1.8860 C 0 0 0 0 0 0 0 0 0 0 0 0 715 | -0.1070 -0.0170 -2.6090 Cl 0 0 0 0 0 0 0 0 0 0 0 0 716 | -1.2900 0.2840 0.0210 C 0 0 0 0 0 0 0 0 0 0 0 0 717 | -2.1560 1.3530 -0.0800 C 0 0 0 0 0 0 0 0 0 0 0 0 718 | -1.3140 2.8330 -0.0250 S 0 0 0 0 0 0 0 0 0 0 0 0 719 | -3.6480 1.3240 -0.2340 C 0 0 0 0 0 0 0 0 0 0 0 0 720 | -4.0600 1.2810 -1.6980 C 0 0 0 0 0 0 0 0 0 0 0 0 721 | 1 2 2 0 722 | 1 7 1 0 723 | 1 21 1 0 724 | 2 3 1 0 725 | 2 19 1 0 726 | 3 4 2 0 727 | 3 12 1 0 728 | 4 5 1 0 729 | 5 6 1 0 730 | 6 7 1 0 731 | 6 10 2 0 732 | 7 8 1 0 733 | 8 9 2 0 734 | 8 11 1 0 735 | 9 10 1 0 736 | 12 13 2 0 737 | 12 17 1 0 738 | 13 14 1 0 739 | 14 15 2 0 740 | 15 16 1 0 741 | 16 17 2 0 742 | 17 18 1 0 743 | 19 20 2 0 744 | 20 21 1 0 745 | 20 22 1 0 746 | 22 23 1 0 747 | M END 748 | > (14) 749 | 8.51 750 | 751 | $$$$ 752 | Flunitrazepam 753 | RDKit 3D 754 | 755 | 23 25 0 0 0 0 0 0 0 0999 V2000 756 | -2.1360 2.4940 -0.1710 C 0 0 0 0 0 0 0 0 0 0 0 0 757 | -2.3560 1.1300 0.0100 C 0 0 0 0 0 0 0 0 0 0 0 0 758 | -1.2730 0.2630 0.1850 C 0 0 0 0 0 0 0 0 0 0 0 0 759 | 0.0440 0.7670 0.1840 C 0 0 0 0 0 0 0 0 0 0 0 0 760 | 0.2860 2.1530 0.0510 C 0 0 0 0 0 0 0 0 0 0 0 0 761 | -0.8280 2.9930 -0.1520 C 0 0 0 0 0 0 0 0 0 0 0 0 762 | 1.5940 2.7400 0.1040 N 0 0 0 0 0 0 0 0 0 0 0 0 763 | 2.6400 2.2430 0.8860 C 0 0 0 0 0 0 0 0 0 0 0 0 764 | 2.3150 1.0750 1.8070 C 0 0 0 0 0 0 0 0 0 0 0 0 765 | 2.2020 -0.1370 0.9940 N 0 0 0 0 0 0 0 0 0 0 0 0 766 | 1.1510 -0.2410 0.2480 C 0 0 0 0 0 0 0 0 0 0 0 0 767 | 1.0480 -1.4470 -0.6240 C 0 0 0 0 0 0 0 0 0 0 0 0 768 | 1.4260 -2.7030 -0.1340 C 0 0 0 0 0 0 0 0 0 0 0 0 769 | 1.3170 -3.8300 -0.9530 C 0 0 0 0 0 0 0 0 0 0 0 0 770 | 0.8280 -3.7070 -2.2550 C 0 0 0 0 0 0 0 0 0 0 0 0 771 | 0.4460 -2.4570 -2.7420 C 0 0 0 0 0 0 0 0 0 0 0 0 772 | 0.5540 -1.3340 -1.9250 C 0 0 0 0 0 0 0 0 0 0 0 0 773 | 0.2030 -0.1410 -2.4310 F 0 0 0 0 0 0 0 0 0 0 0 0 774 | 3.7750 2.7380 0.8820 O 0 0 0 0 0 0 0 0 0 0 0 0 775 | 1.8330 3.9790 -0.6340 C 0 0 0 0 0 0 0 0 0 0 0 0 776 | -3.7270 0.6020 0.0050 N 0 0 0 0 0 0 0 0 0 0 0 0 777 | -3.8890 -0.6190 0.1900 O 0 0 0 0 0 0 0 0 0 0 0 0 778 | -4.6660 1.3980 -0.1810 O 0 0 0 0 0 0 0 0 0 0 0 0 779 | 1 2 2 0 780 | 1 6 1 0 781 | 2 3 1 0 782 | 2 21 1 0 783 | 3 4 2 0 784 | 4 5 1 0 785 | 4 11 1 0 786 | 5 6 2 0 787 | 5 7 1 0 788 | 7 8 1 0 789 | 7 20 1 0 790 | 8 9 1 0 791 | 8 19 2 0 792 | 9 10 1 0 793 | 10 11 2 0 794 | 11 12 1 0 795 | 12 13 2 0 796 | 12 17 1 0 797 | 13 14 1 0 798 | 14 15 2 0 799 | 15 16 1 0 800 | 16 17 2 0 801 | 17 18 1 0 802 | 21 22 2 0 803 | 21 23 1 0 804 | M CHG 2 21 1 23 -1 805 | M END 806 | > (15) 807 | 8.42 808 | 809 | $$$$ 810 | Halazepam 811 | RDKit 3D 812 | 813 | 24 26 0 0 0 0 0 0 0 0999 V2000 814 | -2.1460 2.4930 -0.1590 C 0 0 0 0 0 0 0 0 0 0 0 0 815 | -2.3600 1.1370 0.0300 C 0 0 0 0 0 0 0 0 0 0 0 0 816 | -1.2800 0.2810 0.2030 C 0 0 0 0 0 0 0 0 0 0 0 0 817 | 0.0360 0.7840 0.1870 C 0 0 0 0 0 0 0 0 0 0 0 0 818 | 0.2770 2.1720 0.0570 C 0 0 0 0 0 0 0 0 0 0 0 0 819 | -0.8420 3.0030 -0.1470 C 0 0 0 0 0 0 0 0 0 0 0 0 820 | 1.5880 2.7570 0.1230 N 0 0 0 0 0 0 0 0 0 0 0 0 821 | 2.6360 2.2250 0.8800 C 0 0 0 0 0 0 0 0 0 0 0 0 822 | 2.2970 1.0710 1.8160 C 0 0 0 0 0 0 0 0 0 0 0 0 823 | 2.1760 -0.1420 1.0100 N 0 0 0 0 0 0 0 0 0 0 0 0 824 | 1.1360 -0.2310 0.2450 C 0 0 0 0 0 0 0 0 0 0 0 0 825 | 1.0400 -1.4400 -0.6380 C 0 0 0 0 0 0 0 0 0 0 0 0 826 | 0.5430 -1.3420 -1.9440 C 0 0 0 0 0 0 0 0 0 0 0 0 827 | 0.4730 -2.4810 -2.7500 C 0 0 0 0 0 0 0 0 0 0 0 0 828 | 0.9060 -3.7130 -2.2600 C 0 0 0 0 0 0 0 0 0 0 0 0 829 | 1.4160 -3.8110 -0.9660 C 0 0 0 0 0 0 0 0 0 0 0 0 830 | 1.4880 -2.6760 -0.1560 C 0 0 0 0 0 0 0 0 0 0 0 0 831 | 3.7860 2.6780 0.8290 O 0 0 0 0 0 0 0 0 0 0 0 0 832 | 1.8790 3.9960 -0.6390 C 0 0 0 0 0 0 0 0 0 0 0 0 833 | 1.9360 5.2830 0.1890 C 0 0 0 0 0 0 0 0 0 0 0 0 834 | 2.2000 6.3600 -0.5980 F 0 0 0 0 0 0 0 0 0 0 0 0 835 | 0.7630 5.5420 0.8200 F 0 0 0 0 0 0 0 0 0 0 0 0 836 | 2.8970 5.2550 1.1440 F 0 0 0 0 0 0 0 0 0 0 0 0 837 | -3.9630 0.5110 0.0360 Cl 0 0 0 0 0 0 0 0 0 0 0 0 838 | 1 2 2 0 839 | 1 6 1 0 840 | 2 3 1 0 841 | 2 24 1 0 842 | 3 4 2 0 843 | 4 5 1 0 844 | 4 11 1 0 845 | 5 6 2 0 846 | 5 7 1 0 847 | 7 8 1 0 848 | 7 19 1 0 849 | 8 9 1 0 850 | 8 18 2 0 851 | 9 10 1 0 852 | 10 11 2 0 853 | 11 12 1 0 854 | 12 13 2 0 855 | 12 17 1 0 856 | 13 14 1 0 857 | 14 15 2 0 858 | 15 16 1 0 859 | 16 17 2 0 860 | 19 20 1 0 861 | 20 21 1 0 862 | 20 22 1 0 863 | 20 23 1 0 864 | M END 865 | > (16) 866 | 7.04 867 | 868 | $$$$ 869 | Lorazepam 870 | RDKit 3D 871 | 872 | 21 23 0 0 0 0 0 0 0 0999 V2000 873 | -2.1160 2.5030 -0.1470 C 0 0 0 0 0 0 0 0 0 0 0 0 874 | -2.3330 1.1350 -0.0320 C 0 0 0 0 0 0 0 0 0 0 0 0 875 | -1.2610 0.2630 0.1400 C 0 0 0 0 0 0 0 0 0 0 0 0 876 | 0.0520 0.7620 0.2090 C 0 0 0 0 0 0 0 0 0 0 0 0 877 | 0.2720 2.1500 0.1570 C 0 0 0 0 0 0 0 0 0 0 0 0 878 | -0.8170 3.0070 -0.0600 C 0 0 0 0 0 0 0 0 0 0 0 0 879 | 1.5280 2.7690 0.2770 N 0 0 0 0 0 0 0 0 0 0 0 0 880 | 2.6390 2.2760 0.9130 C 0 0 0 0 0 0 0 0 0 0 0 0 881 | 2.4530 0.9920 1.7700 C 0 0 0 0 0 0 0 0 0 0 0 0 882 | 2.2740 -0.1410 0.8760 N 0 0 0 0 0 0 0 0 0 0 0 0 883 | 1.1790 -0.2260 0.1940 C 0 0 0 0 0 0 0 0 0 0 0 0 884 | 1.0390 -1.4310 -0.6770 C 0 0 0 0 0 0 0 0 0 0 0 0 885 | 1.4760 -2.6560 -0.1520 C 0 0 0 0 0 0 0 0 0 0 0 0 886 | 1.3590 -3.8230 -0.9090 C 0 0 0 0 0 0 0 0 0 0 0 0 887 | 0.8160 -3.7690 -2.1910 C 0 0 0 0 0 0 0 0 0 0 0 0 888 | 0.3970 -2.5480 -2.7250 C 0 0 0 0 0 0 0 0 0 0 0 0 889 | 0.5110 -1.3740 -1.9740 C 0 0 0 0 0 0 0 0 0 0 0 0 890 | 0.0280 0.1060 -2.7240 Cl 0 0 0 0 0 0 0 0 0 0 0 0 891 | 3.5700 0.7950 2.6320 O 0 0 0 0 0 0 0 0 0 0 0 0 892 | 3.7130 2.8890 0.8500 O 0 0 0 0 0 0 0 0 0 0 0 0 893 | -3.9350 0.5130 -0.1290 Cl 0 0 0 0 0 0 0 0 0 0 0 0 894 | 1 2 2 0 895 | 1 6 1 0 896 | 2 3 1 0 897 | 2 21 1 0 898 | 3 4 2 0 899 | 4 5 1 0 900 | 4 11 1 0 901 | 5 6 2 0 902 | 5 7 1 0 903 | 7 8 1 0 904 | 8 9 1 0 905 | 8 20 2 0 906 | 9 10 1 0 907 | 9 19 1 0 908 | 10 11 2 0 909 | 11 12 1 0 910 | 12 13 2 0 911 | 12 17 1 0 912 | 13 14 1 0 913 | 14 15 2 0 914 | 15 16 1 0 915 | 16 17 2 0 916 | 17 18 1 0 917 | M END 918 | > (17) 919 | 8.46 920 | 921 | $$$$ 922 | Meclonazepam 923 | RDKit 3D 924 | 925 | 23 25 0 0 0 0 0 0 0 0999 V2000 926 | -2.1000 2.4800 -0.2560 C 0 0 0 0 0 0 0 0 0 0 0 0 927 | -2.3300 1.1120 -0.0930 C 0 0 0 0 0 0 0 0 0 0 0 0 928 | -1.2590 0.2360 0.1320 C 0 0 0 0 0 0 0 0 0 0 0 0 929 | 0.0560 0.7340 0.2120 C 0 0 0 0 0 0 0 0 0 0 0 0 930 | 0.2840 2.1190 0.1100 C 0 0 0 0 0 0 0 0 0 0 0 0 931 | -0.7960 2.9740 -0.1610 C 0 0 0 0 0 0 0 0 0 0 0 0 932 | 1.5380 2.7410 0.2360 N 0 0 0 0 0 0 0 0 0 0 0 0 933 | 2.6380 2.2840 0.9170 C 0 0 0 0 0 0 0 0 0 0 0 0 934 | 2.4420 1.0400 1.7910 C 0 0 0 0 0 0 0 0 0 0 0 0 935 | 2.2760 -0.1330 0.9300 N 0 0 0 0 0 0 0 0 0 0 0 0 936 | 1.1800 -0.2550 0.2570 C 0 0 0 0 0 0 0 0 0 0 0 0 937 | 1.0550 -1.4720 -0.5930 C 0 0 0 0 0 0 0 0 0 0 0 0 938 | 1.5060 -2.6900 -0.0640 C 0 0 0 0 0 0 0 0 0 0 0 0 939 | 1.3970 -3.8580 -0.8200 C 0 0 0 0 0 0 0 0 0 0 0 0 940 | 0.8390 -3.8140 -2.0970 C 0 0 0 0 0 0 0 0 0 0 0 0 941 | 0.3870 -2.6010 -2.6230 C 0 0 0 0 0 0 0 0 0 0 0 0 942 | 0.4920 -1.4260 -1.8750 C 0 0 0 0 0 0 0 0 0 0 0 0 943 | -0.0370 0.0490 -2.6050 Cl 0 0 0 0 0 0 0 0 0 0 0 0 944 | 3.6590 0.7860 2.6750 C 0 0 0 0 0 0 0 0 0 0 0 0 945 | 3.6980 2.9160 0.8610 O 0 0 0 0 0 0 0 0 0 0 0 0 946 | -3.6990 0.5870 -0.1790 N 0 0 0 0 0 0 0 0 0 0 0 0 947 | -4.6290 1.3900 -0.3820 O 0 0 0 0 0 0 0 0 0 0 0 0 948 | -3.8710 -0.6390 -0.0430 O 0 0 0 0 0 0 0 0 0 0 0 0 949 | 1 2 2 0 950 | 1 6 1 0 951 | 2 3 1 0 952 | 2 21 1 0 953 | 3 4 2 0 954 | 4 5 1 0 955 | 4 11 1 0 956 | 5 6 2 0 957 | 5 7 1 0 958 | 7 8 1 0 959 | 8 9 1 0 960 | 8 20 2 0 961 | 9 10 1 0 962 | 9 19 1 0 963 | 10 11 2 0 964 | 11 12 1 0 965 | 12 13 2 0 966 | 12 17 1 0 967 | 13 14 1 0 968 | 14 15 2 0 969 | 15 16 1 0 970 | 16 17 2 0 971 | 17 18 1 0 972 | 21 22 2 0 973 | 21 23 1 0 974 | M CHG 2 21 1 23 -1 975 | M END 976 | > (18) 977 | 8.92 978 | 979 | $$$$ 980 | Medazepam 981 | RDKit 3D 982 | 983 | 19 21 0 0 0 0 0 0 0 0999 V2000 984 | 0.2890 2.1490 0.0120 C 0 0 0 0 0 0 0 0 0 0 0 0 985 | 0.0070 0.7720 0.1650 C 0 0 0 0 0 0 0 0 0 0 0 0 986 | 1.1130 -0.2340 0.2490 C 0 0 0 0 0 0 0 0 0 0 0 0 987 | 2.1260 -0.1380 1.0540 N 0 0 0 0 0 0 0 0 0 0 0 0 988 | 2.1840 1.0590 1.9050 C 0 0 0 0 0 0 0 0 0 0 0 0 989 | 2.5310 2.3060 1.0840 C 0 0 0 0 0 0 0 0 0 0 0 0 990 | 1.5870 2.6440 -0.0050 N 0 0 0 0 0 0 0 0 0 0 0 0 991 | 1.9010 3.8620 -0.7530 C 0 0 0 0 0 0 0 0 0 0 0 0 992 | 1.0520 -1.4340 -0.6490 C 0 0 0 0 0 0 0 0 0 0 0 0 993 | 0.5700 -1.3350 -1.9610 C 0 0 0 0 0 0 0 0 0 0 0 0 994 | 0.5280 -2.4670 -2.7770 C 0 0 0 0 0 0 0 0 0 0 0 0 995 | 0.9740 -3.6970 -2.2930 C 0 0 0 0 0 0 0 0 0 0 0 0 996 | 1.4670 -3.7980 -0.9930 C 0 0 0 0 0 0 0 0 0 0 0 0 997 | 1.5110 -2.6680 -0.1720 C 0 0 0 0 0 0 0 0 0 0 0 0 998 | -1.3140 0.2910 0.2200 C 0 0 0 0 0 0 0 0 0 0 0 0 999 | -2.3760 1.1760 0.0840 C 0 0 0 0 0 0 0 0 0 0 0 0 1000 | -2.1340 2.5300 -0.1020 C 0 0 0 0 0 0 0 0 0 0 0 0 1001 | -0.8170 3.0060 -0.1370 C 0 0 0 0 0 0 0 0 0 0 0 0 1002 | -3.9930 0.5920 0.1400 Cl 0 0 0 0 0 0 0 0 0 0 0 0 1003 | 1 2 2 0 1004 | 1 7 1 0 1005 | 1 18 1 0 1006 | 2 3 1 0 1007 | 2 15 1 0 1008 | 3 4 2 0 1009 | 3 9 1 0 1010 | 4 5 1 0 1011 | 5 6 1 0 1012 | 6 7 1 0 1013 | 7 8 1 0 1014 | 9 10 2 0 1015 | 9 14 1 0 1016 | 10 11 1 0 1017 | 11 12 2 0 1018 | 12 13 1 0 1019 | 13 14 2 0 1020 | 15 16 2 0 1021 | 16 17 1 0 1022 | 16 19 1 0 1023 | 17 18 2 0 1024 | M END 1025 | > (19) 1026 | 6.06 1027 | 1028 | $$$$ 1029 | Midazolam 1030 | RDKit 3D 1031 | 1032 | 23 26 0 0 0 0 0 0 0 0999 V2000 1033 | 0.2620 2.1660 0.0250 C 0 0 0 0 0 0 0 0 0 0 0 0 1034 | 0.0430 0.7800 0.1690 C 0 0 0 0 0 0 0 0 0 0 0 0 1035 | 1.1560 -0.2280 0.2240 C 0 0 0 0 0 0 0 0 0 0 0 0 1036 | 2.2130 -0.1320 0.9650 N 0 0 0 0 0 0 0 0 0 0 0 0 1037 | 2.3760 1.0480 1.8040 C 0 0 0 0 0 0 0 0 0 0 0 0 1038 | 2.5690 2.2260 0.9320 C 0 0 0 0 0 0 0 0 0 0 0 0 1039 | 1.5720 2.7130 0.1090 N 0 0 0 0 0 0 0 0 0 0 0 0 1040 | 2.1160 3.8270 -0.5280 C 0 0 0 0 0 0 0 0 0 0 0 0 1041 | 3.3490 4.0670 -0.1100 N 0 0 0 0 0 0 0 0 0 0 0 0 1042 | 3.6370 3.0780 0.7860 C 0 0 0 0 0 0 0 0 0 0 0 0 1043 | 1.4560 4.5920 -1.6230 C 0 0 0 0 0 0 0 0 0 0 0 0 1044 | 1.0500 -1.4400 -0.6430 C 0 0 0 0 0 0 0 0 0 0 0 0 1045 | 1.4930 -2.6750 -0.1520 C 0 0 0 0 0 0 0 0 0 0 0 0 1046 | 1.4040 -3.8160 -0.9540 C 0 0 0 0 0 0 0 0 0 0 0 0 1047 | 0.8850 -3.7270 -2.2460 C 0 0 0 0 0 0 0 0 0 0 0 0 1048 | 0.4590 -2.4950 -2.7440 C 0 0 0 0 0 0 0 0 0 0 0 0 1049 | 0.5480 -1.3580 -1.9440 C 0 0 0 0 0 0 0 0 0 0 0 0 1050 | 0.1610 -0.1820 -2.4610 F 0 0 0 0 0 0 0 0 0 0 0 0 1051 | -1.2730 0.2840 0.1830 C 0 0 0 0 0 0 0 0 0 0 0 0 1052 | -2.3510 1.1510 0.0240 C 0 0 0 0 0 0 0 0 0 0 0 0 1053 | -2.1380 2.5150 -0.1420 C 0 0 0 0 0 0 0 0 0 0 0 0 1054 | -0.8370 3.0240 -0.1350 C 0 0 0 0 0 0 0 0 0 0 0 0 1055 | -3.9570 0.5310 0.0310 Cl 0 0 0 0 0 0 0 0 0 0 0 0 1056 | 1 2 2 0 1057 | 1 7 1 0 1058 | 1 22 1 0 1059 | 2 3 1 0 1060 | 2 19 1 0 1061 | 3 4 2 0 1062 | 3 12 1 0 1063 | 4 5 1 0 1064 | 5 6 1 0 1065 | 6 7 1 0 1066 | 6 10 2 0 1067 | 7 8 1 0 1068 | 8 9 2 0 1069 | 8 11 1 0 1070 | 9 10 1 0 1071 | 12 13 2 0 1072 | 12 17 1 0 1073 | 13 14 1 0 1074 | 14 15 2 0 1075 | 15 16 1 0 1076 | 16 17 2 0 1077 | 17 18 1 0 1078 | 19 20 2 0 1079 | 20 21 1 0 1080 | 20 23 1 0 1081 | 21 22 2 0 1082 | M END 1083 | > (20) 1084 | 8.32 1085 | 1086 | $$$$ 1087 | Nitrazepam 1088 | RDKit 3D 1089 | 1090 | 21 23 0 0 0 0 0 0 0 0999 V2000 1091 | -2.1050 2.5210 -0.2110 C 0 0 0 0 0 0 0 0 0 0 0 0 1092 | -2.3450 1.1570 -0.0320 C 0 0 0 0 0 0 0 0 0 0 0 0 1093 | -1.2780 0.2710 0.1700 C 0 0 0 0 0 0 0 0 0 0 0 0 1094 | 0.0430 0.7560 0.2040 C 0 0 0 0 0 0 0 0 0 0 0 0 1095 | 0.2810 2.1390 0.1010 C 0 0 0 0 0 0 0 0 0 0 0 0 1096 | -0.7940 3.0040 -0.1490 C 0 0 0 0 0 0 0 0 0 0 0 0 1097 | 1.5430 2.7460 0.2250 N 0 0 0 0 0 0 0 0 0 0 0 0 1098 | 2.6270 2.2650 0.9150 C 0 0 0 0 0 0 0 0 0 0 0 0 1099 | 2.4060 1.0330 1.7790 C 0 0 0 0 0 0 0 0 0 0 0 0 1100 | 2.2400 -0.1460 0.9310 N 0 0 0 0 0 0 0 0 0 0 0 0 1101 | 1.1590 -0.2460 0.2280 C 0 0 0 0 0 0 0 0 0 0 0 0 1102 | 1.0390 -1.4590 -0.6440 C 0 0 0 0 0 0 0 0 0 0 0 0 1103 | 0.5290 -1.3630 -1.9460 C 0 0 0 0 0 0 0 0 0 0 0 0 1104 | 0.4370 -2.5060 -2.7430 C 0 0 0 0 0 0 0 0 0 0 0 0 1105 | 0.8600 -3.7400 -2.2490 C 0 0 0 0 0 0 0 0 0 0 0 0 1106 | 1.3820 -3.8360 -0.9590 C 0 0 0 0 0 0 0 0 0 0 0 0 1107 | 1.4770 -2.6970 -0.1580 C 0 0 0 0 0 0 0 0 0 0 0 0 1108 | 3.7090 2.8610 0.8800 O 0 0 0 0 0 0 0 0 0 0 0 0 1109 | -3.7210 0.6460 -0.0770 N 0 0 0 0 0 0 0 0 0 0 0 0 1110 | -3.9040 -0.5750 0.0940 O 0 0 0 0 0 0 0 0 0 0 0 0 1111 | -4.6460 1.4540 -0.2830 O 0 0 0 0 0 0 0 0 0 0 0 0 1112 | 1 2 2 0 1113 | 1 6 1 0 1114 | 2 3 1 0 1115 | 2 19 1 0 1116 | 3 4 2 0 1117 | 4 5 1 0 1118 | 4 11 1 0 1119 | 5 6 2 0 1120 | 5 7 1 0 1121 | 7 8 1 0 1122 | 8 9 1 0 1123 | 8 18 2 0 1124 | 9 10 1 0 1125 | 10 11 2 0 1126 | 11 12 1 0 1127 | 12 13 2 0 1128 | 12 17 1 0 1129 | 13 14 1 0 1130 | 14 15 2 0 1131 | 15 16 1 0 1132 | 16 17 2 0 1133 | 19 20 2 0 1134 | 19 21 1 0 1135 | M CHG 2 19 1 21 -1 1136 | M END 1137 | > (21) 1138 | 8 1139 | 1140 | $$$$ 1141 | --------------------------------------------------------------------------------